summaryrefslogtreecommitdiff
path: root/sys/src/ape
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-03-29 20:49:49 +0100
committercinap_lenrek <cinap_lenrek@gmx.de>2013-03-29 20:49:49 +0100
commitc97a0268f34e50f51ec56d53d62b7abe2f2afa19 (patch)
tree0345a1f81eb78fa7282ce4941750c8ce8a9fccff /sys/src/ape
parent10987d2dc7cd5bddf1a6a252b2349f4477753b0a (diff)
ape: fix potential double close in socket() and protect rock chain with spinlock
Diffstat (limited to 'sys/src/ape')
-rw-r--r--sys/src/ape/lib/bsd/socket.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/sys/src/ape/lib/bsd/socket.c b/sys/src/ape/lib/bsd/socket.c
index 6623936b8..d14b35386 100644
--- a/sys/src/ape/lib/bsd/socket.c
+++ b/sys/src/ape/lib/bsd/socket.c
@@ -14,7 +14,10 @@
#include "priv.h"
-Rock *_sock_rock;
+#include <lock.h>
+
+static Lock _sock_lock;
+static Rock *_sock_rock;
Rock*
_sock_findrock(int fd, struct stat *dp)
@@ -24,12 +27,15 @@ _sock_findrock(int fd, struct stat *dp)
if(dp == 0)
dp = &d;
- fstat(fd, dp);
+ if(fstat(fd, dp) < 0)
+ return 0;
+ lock(&_sock_lock);
for(r = _sock_rock; r; r = r->next){
if(r->inode == dp->st_ino
&& r->dev == dp->st_dev)
break;
}
+ unlock(&_sock_lock);
return r;
}
@@ -39,22 +45,29 @@ _sock_newrock(int fd)
Rock *r;
struct stat d;
- r = _sock_findrock(fd, &d);
+ if(fstat(fd, &d) < 0)
+ return 0;
+ lock(&_sock_lock);
+ for(r = _sock_rock; r; r = r->next){
+ if(r->inode == d.st_ino
+ && r->dev == d.st_dev)
+ break;
+ }
if(r == 0){
r = malloc(sizeof(Rock));
- if(r == 0)
+ if(r == 0){
+ unlock(&_sock_lock);
return 0;
+ }
r->dev = d.st_dev;
r->inode = d.st_ino;
- r->other = -1;
r->next = _sock_rock;
_sock_rock = r;
}
+ unlock(&_sock_lock);
memset(&r->raddr, 0, sizeof(r->raddr));
memset(&r->addr, 0, sizeof(r->addr));
r->reserved = 0;
- r->dev = d.st_dev;
- r->inode = d.st_ino;
r->other = -1;
return r;
}
@@ -81,7 +94,6 @@ _sock_data(int cfd, char *net, int domain, int stype, int protocol, Rock **rp)
fd = open(name, O_RDWR);
close(cfd);
if(fd < 0){
- close(cfd);
errno = ENOBUFS;
return -1;
}
@@ -90,18 +102,16 @@ _sock_data(int cfd, char *net, int domain, int stype, int protocol, Rock **rp)
snprintf(name, sizeof name, "/net/%s/%d/ctl", net, n);
r = _sock_newrock(fd);
if(r == 0){
- errno = ENOBUFS;
close(fd);
+ errno = ENOBUFS;
return -1;
}
- if(rp)
- *rp = r;
- memset(&r->raddr, 0, sizeof(r->raddr));
- memset(&r->addr, 0, sizeof(r->addr));
r->domain = domain;
r->stype = stype;
r->protocol = protocol;
strcpy(r->ctl, name);
+ if(rp)
+ *rp = r;
return fd;
}
@@ -140,6 +150,12 @@ socket(int domain, int stype, int protocol)
return -1;
}
r = _sock_newrock(pfd[0]);
+ if(r == 0){
+ close(pfd[0]);
+ close(pfd[1]);
+ errno = ENOBUFS;
+ return -1;
+ }
r->domain = domain;
r->stype = stype;
r->protocol = protocol;