diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-04-02 01:40:29 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2013-04-02 01:40:29 +0200 |
commit | e8c1d0fe7cdfcbf0d913b5091a33a14da561f976 (patch) | |
tree | a04271094793b14bcd1bd5050afc7c90399b6fe7 /sys/src/ape/lib/bsd/getpeername.c | |
parent | e8a02760901e0b700ba845c9f57601f662e0e0aa (diff) |
ape: check *alen before copying in getpeername(), getsockname() and accept()
*alen has to be initialized to the size of the buffer
by the caller, and we are supposed to put the real
size of the address in there, but not copy more than
the original *alen value (truncate).
Diffstat (limited to 'sys/src/ape/lib/bsd/getpeername.c')
-rw-r--r-- | sys/src/ape/lib/bsd/getpeername.c | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/sys/src/ape/lib/bsd/getpeername.c b/sys/src/ape/lib/bsd/getpeername.c index 55b4f8eb3..cec7a057a 100644 --- a/sys/src/ape/lib/bsd/getpeername.c +++ b/sys/src/ape/lib/bsd/getpeername.c @@ -19,7 +19,7 @@ int getpeername(int fd, struct sockaddr *addr, int *alen) { Rock *r; - int i; + int olen, len; struct sockaddr_un *runix; r = _sock_findrock(fd, 0); @@ -30,22 +30,28 @@ getpeername(int fd, struct sockaddr *addr, int *alen) switch(r->domain){ case PF_INET: - memmove(addr, &r->raddr, sizeof(struct sockaddr_in)); - *alen = sizeof(struct sockaddr_in); + len = sizeof(struct sockaddr_in); break; case PF_INET6: - memmove(addr, &r->raddr, sizeof(struct sockaddr_in6)); - *alen = sizeof(struct sockaddr_in6); + len = sizeof(struct sockaddr_in6); break; case PF_UNIX: runix = (struct sockaddr_un*)&r->raddr; - i = &runix->sun_path[strlen(runix->sun_path)] - (char*)runix; - memmove(addr, runix, i); - *alen = i; + len = &runix->sun_path[strlen(runix->sun_path)] - (char*)runix; break; default: errno = EAFNOSUPPORT; return -1; } + + if(alen != 0){ + olen = *alen; + *alen = len; + if(olen < len) + len = olen; + } + if(addr != 0 && len > 0) + memmove(addr, &r->raddr, len); + return 0; } |