summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-05-11 20:54:50 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2013-05-11 20:54:50 +0200
commit25bc4e84e9ef8df694937b107111160e707e0299 (patch)
treea1ce48aa786af8f318a0833e7ac99fba8108d228
parentfe073f852a0c085c99545b361e948d29023531c8 (diff)
downloadplan9front-25bc4e84e9ef8df694937b107111160e707e0299.tar.xz
devmnt: fix mount device leak and allocation error handling in mntversion()
the fist problem is that qopen() might return nil and that kstrdup() will sleep, so we should try to avoid holding the mntalloc lock. so we move the kstrdup() and qopen() calls before the Mnt allocation, and properly recover the memory if we fail later. the second problem was that we error(Eshort) after we already created the Mnt when returnlen < sizeof(f.version). this check has to happen *before* we even attempt to allocate the Mnt structures. note that we only copy the version string once everything is in the clear, so the semantics of the user buffer not being modified in case of error is not changed. a little cleanup in muxclose(), getting rid of mntptfree()...
-rw-r--r--sys/src/9/port/devmnt.c48
1 files changed, 24 insertions, 24 deletions
diff --git a/sys/src/9/port/devmnt.c b/sys/src/9/port/devmnt.c
index 5f46b9467..da51d0366 100644
--- a/sys/src/9/port/devmnt.c
+++ b/sys/src/9/port/devmnt.c
@@ -61,7 +61,6 @@ Mntrpc* mntflushalloc(Mntrpc*, ulong);
void mntflushfree(Mnt*, Mntrpc*);
void mntfree(Mntrpc*);
void mntgate(Mnt*);
-void mntpntfree(Mnt*);
void mntqrm(Mnt*, Mntrpc*);
Mntrpc* mntralloc(Chan*, ulong);
long mntrdwr(int, Chan*, void*, long, vlong);
@@ -101,6 +100,7 @@ mntversion(Chan *c, char *version, int msize, int returnlen)
uchar *msg;
Mnt *m;
char *v;
+ Queue *q;
long k, l;
uvlong oo;
char buf[128];
@@ -199,6 +199,16 @@ mntversion(Chan *c, char *version, int msize, int returnlen)
k = strlen(f.version);
if(strncmp(f.version, v, k) != 0)
error("bad 9P version returned from server");
+ if(returnlen > 0 && returnlen < k)
+ error(Eshort);
+
+ v = nil;
+ kstrdup(&v, f.version);
+ q = qopen(10*MAXRPC, 0, nil, nil);
+ if(q == nil){
+ free(v);
+ exhausted("mount queues");
+ }
/* now build Mnt associated with this connection */
lock(&mntalloc);
@@ -208,24 +218,22 @@ mntversion(Chan *c, char *version, int msize, int returnlen)
else {
m = malloc(sizeof(Mnt));
if(m == 0) {
+ qfree(q);
+ free(v);
unlock(&mntalloc);
exhausted("mount devices");
}
}
m->list = mntalloc.list;
mntalloc.list = m;
- m->version = nil;
- kstrdup(&m->version, f.version);
+ m->version = v;
m->id = mntalloc.id++;
- m->q = qopen(10*MAXRPC, 0, nil, nil);
+ m->q = q;
m->msize = f.msize;
unlock(&mntalloc);
- if(returnlen > 0){
- if(returnlen < k)
- error(Eshort);
- memmove(version, f.version, k);
- }
+ if(returnlen > 0)
+ memmove(version, f.version, k); /* length was checked above */
poperror(); /* msg */
free(msg);
@@ -564,23 +572,18 @@ mntclunk(Chan *c, int t)
void
muxclose(Mnt *m)
{
- Mntrpc *q, *r;
+ Mnt *f, **l;
+ Mntrpc *r;
- for(q = m->queue; q; q = r) {
- r = q->list;
- mntfree(q);
+ while((r = m->queue) != nil){
+ m->queue = r->list;
+ mntfree(r);
}
m->id = 0;
free(m->version);
m->version = nil;
- mntpntfree(m);
-}
-
-void
-mntpntfree(Mnt *m)
-{
- Mnt *f, **l;
- Queue *q;
+ qfree(m->q);
+ m->q = nil;
lock(&mntalloc);
l = &mntalloc.list;
@@ -593,10 +596,7 @@ mntpntfree(Mnt *m)
}
m->list = mntalloc.mntfree;
mntalloc.mntfree = m;
- q = m->q;
unlock(&mntalloc);
-
- qfree(q);
}
static void