ref: 0f0b6def8c70d27b75844217691b6e88e2ff646a
parent: 8e896536b5355389b00c7ffd0f75c2cfa8a92658
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Aug 23 01:07:30 EDT 2020
kernel: fix Abind cyclic reference and mounthead leaks (thanks Alex Musolino)
The Abind case in namec() needs to cunique() the chan
before attaching the umh mount head pointer onto it.
This is because we cannot give a reference to the mount
head to any of the mh->mount...->to channels, as they
will never go away until the mount head goes away.
This is a cyclic reference.
This could be reproduced with:
@{rfork n; mount -a '#s/boot' /mnt/root; bind /mnt/root /}
Also, fix memory leaks around cunique(), which can
error, leaking the mount head we got from domount().
Move the umh != nil check inside cunique().
--- a/sys/src/9/port/chan.c
+++ b/sys/src/9/port/chan.c
@@ -556,6 +556,12 @@
c = nc;
}
+ if(c->umh != nil){ //BUG+ print("cunique umh != nil from %#p\n", getcallerpc(&c));+ putmhead(c->umh);
+ c->umh = nil;
+ }
+
return c;
}
@@ -1094,11 +1100,6 @@
}
putmhead(mh);
c = cunique(c);
- if(c->umh != nil){ //BUG- print("walk umh\n");- putmhead(c->umh);
- c->umh = nil;
- }
pathclose(c->path);
c->path = path;
@@ -1410,8 +1411,13 @@
m = nil;
if(!nomount)
domount(&c, &m, nil);
- putmhead(c->umh);
+ if(waserror()){+ putmhead(m);
+ nexterror();
+ }
+ c = cunique(c);
c->umh = m;
+ poperror();
break;
case Aaccess:
@@ -1428,9 +1434,13 @@
m = nil;
if(!nomount)
domount(&c, &m, &path);
-
+ if(waserror()){+ putmhead(m);
+ nexterror();
+ }
/* our own copy to open or remove */
c = cunique(c);
+ poperror();
/* now it's our copy anyway, we can put the name back */
pathclose(c->path);
@@ -1448,11 +1458,6 @@
case Aopen:
case Acreate:
- if(c->umh != nil){- print("cunique umh Open\n");- putmhead(c->umh);
- c->umh = nil;
- }
/* only save the mount head if it's a multiple element union */
if(m != nil && m->mount != nil && m->mount->next != nil)
c->umh = m;
--
⑨