diff options
author | rsc <devnull@localhost> | 2007-04-08 01:30:26 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2007-04-08 01:30:26 +0000 |
commit | 4f6d2bb1e8e38aaeeeabb159272da19718bfb05d (patch) | |
tree | 100758b863425d60071fea95e1ffb3a6ed0ada15 /src/libventi | |
parent | 8ecb4ffe4c618bb484299a4a3b29f2a991903e53 (diff) | |
download | plan9port-4f6d2bb1e8e38aaeeeabb159272da19718bfb05d.tar.gz plan9port-4f6d2bb1e8e38aaeeeabb159272da19718bfb05d.tar.bz2 plan9port-4f6d2bb1e8e38aaeeeabb159272da19718bfb05d.zip |
correct dangling pointer race (Bakul Shah)
Diffstat (limited to 'src/libventi')
-rw-r--r-- | src/libventi/conn.c | 1 | ||||
-rw-r--r-- | src/libventi/queue.c | 21 | ||||
-rw-r--r-- | src/libventi/queue.h | 3 | ||||
-rw-r--r-- | src/libventi/send.c | 17 |
4 files changed, 36 insertions, 6 deletions
diff --git a/src/libventi/conn.c b/src/libventi/conn.c index 5b6d5436..e488c6db 100644 --- a/src/libventi/conn.c +++ b/src/libventi/conn.c @@ -46,5 +46,6 @@ vtfreeconn(VtConn *z) packetfree(z->part); vtfree(z->version); vtfree(z->sid); + qunlock(&z->lk); vtfree(z); } diff --git a/src/libventi/queue.c b/src/libventi/queue.c index 3a1f6ea5..bba63032 100644 --- a/src/libventi/queue.c +++ b/src/libventi/queue.c @@ -12,6 +12,7 @@ struct Qel struct Queue { + int ref; int hungup; QLock lk; Rendez r; @@ -26,14 +27,32 @@ _vtqalloc(void) q = vtmallocz(sizeof(Queue)); q->r.l = &q->lk; + q->ref = 1; + return q; +} + +Queue* +_vtqincref(Queue *q) +{ + qlock(&q->lk); + q->ref++; + qunlock(&q->lk); return q; } void -_vtqfree(Queue *q) +_vtqdecref(Queue *q) { Qel *e; + qlock(&q->lk); + if(--q->ref > 0){ + qunlock(&q->lk); + return; + } + assert(q->ref == 0); + qunlock(&q->lk); + /* Leaks the pointers e->p! */ while(q->head){ e = q->head; diff --git a/src/libventi/queue.h b/src/libventi/queue.h index 2807783b..90ee1402 100644 --- a/src/libventi/queue.h +++ b/src/libventi/queue.h @@ -4,4 +4,5 @@ int _vtqsend(Queue*, void*); void *_vtqrecv(Queue*); void _vtqhangup(Queue*); void *_vtnbqrecv(Queue*); -void _vtqfree(Queue*); +void _vtqdecref(Queue*); +Queue *_vtqincref(Queue*); diff --git a/src/libventi/send.c b/src/libventi/send.c index 7ada51af..70cc8272 100644 --- a/src/libventi/send.c +++ b/src/libventi/send.c @@ -147,7 +147,7 @@ vtrecvproc(void *v) _vtqhangup(q); while((p = _vtnbqrecv(q)) != nil) packetfree(p); - _vtqfree(q); + _vtqdecref(q); z->readq = nil; rwakeup(&z->rpcfork); qunlock(&z->lk); @@ -178,7 +178,7 @@ vtsendproc(void *v) _vtqhangup(q); while((p = _vtnbqrecv(q)) != nil) packetfree(p); - _vtqfree(q); + _vtqdecref(q); z->writeq = nil; rwakeup(&z->rpcfork); qunlock(&z->lk); @@ -189,6 +189,7 @@ Packet* vtrecv(VtConn *z) { Packet *p; + Queue *q; qlock(&z->lk); if(z->state != VtStateConnected){ @@ -197,8 +198,11 @@ vtrecv(VtConn *z) return nil; } if(z->readq){ + q = _vtqincref(z->readq); qunlock(&z->lk); - return _vtqrecv(z->readq); + p = _vtqrecv(q); + _vtqdecref(q); + return p; } qlock(&z->inlk); @@ -213,6 +217,8 @@ vtrecv(VtConn *z) int vtsend(VtConn *z, Packet *p) { + Queue *q; + qlock(&z->lk); if(z->state != VtStateConnected){ packetfree(p); @@ -221,11 +227,14 @@ vtsend(VtConn *z, Packet *p) return -1; } if(z->writeq){ + q = _vtqincref(z->writeq); qunlock(&z->lk); - if(_vtqsend(z->writeq, p) < 0){ + if(_vtqsend(q, p) < 0){ + _vtqdecref(q); packetfree(p); return -1; } + _vtqdecref(q); return 0; } |