shithub: riscv

Download patch

ref: e8c1d0fe7cdfcbf0d913b5091a33a14da561f976
parent: e8a02760901e0b700ba845c9f57601f662e0e0aa
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Mon Apr 1 21:40:29 EDT 2013

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).

--- a/sys/src/ape/lib/bsd/accept.c
+++ b/sys/src/ape/lib/bsd/accept.c
@@ -62,14 +62,8 @@
 			close(nfd);
 			return -1;
 		}
-		/* get remote address */
-		_sock_ingetaddr(nr, &nr->raddr, &n, "remote");
-		if(a != 0){
-			if(n > 0)
-				memmove(a, &nr->raddr, n);
-			*alen = n;
-		}
-		return nfd;
+		_sock_ingetaddr(nr, &nr->raddr, 0, "remote");	
+		break;
 	case PF_UNIX:
 		if(r->other >= 0){
 			errno = EGREG;
@@ -106,10 +100,15 @@
 		nr->domain = r->domain;
 		nr->stype = r->stype;
 		nr->protocol = r->protocol;
-
-		return nfd;
+		nr->raddr = r->addr;
+		break;
 	default:
 		errno = EOPNOTSUPP;
 		return -1;
 	}
+
+	if(a != 0)
+		getpeername(nfd, a, alen);
+
+	return nfd;
 }
--- a/sys/src/ape/lib/bsd/bind.c
+++ b/sys/src/ape/lib/bsd/bind.c
@@ -25,6 +25,7 @@
 bind(int fd, void *a, int alen)
 {
 	int n, len, cfd, port;
+	struct sockaddr *sa;
 	Rock *r;
 	char msg[128];
 
@@ -32,6 +33,11 @@
 	r = _sock_findrock(fd, 0);
 	if(r == 0){
 		errno = ENOTSOCK;
+		return -1;
+	}
+	sa = (struct sockaddr*)a;
+	if(sa->sa_family != r->domain){
+		errno = EAFNOSUPPORT;
 		return -1;
 	}
 	if(alen > sizeof(r->addr)){
--- a/sys/src/ape/lib/bsd/connect.c
+++ b/sys/src/ape/lib/bsd/connect.c
@@ -30,13 +30,13 @@
 		errno = ENOTSOCK;
 		return -1;
 	}
-	if(alen > sizeof(r->raddr)){
-		errno = ENAMETOOLONG;
-		return -1;
-	}
 	sa = (struct sockaddr*)a;
 	if(sa->sa_family != r->domain){
 		errno = EAFNOSUPPORT;
+		return -1;
+	}
+	if(alen > sizeof(r->raddr)){
+		errno = ENAMETOOLONG;
 		return -1;
 	}
 	memmove(&r->raddr, a, alen);
--- a/sys/src/ape/lib/bsd/getpeername.c
+++ b/sys/src/ape/lib/bsd/getpeername.c
@@ -19,7 +19,7 @@
 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 @@
 
 	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;
 }
--- a/sys/src/ape/lib/bsd/getsockname.c
+++ b/sys/src/ape/lib/bsd/getsockname.c
@@ -19,7 +19,7 @@
 getsockname(int fd, struct sockaddr *addr, int *alen)
 {
 	Rock *r;
-	int i;
+	int len, olen;
 	struct sockaddr_un *lunix;
 
 	r = _sock_findrock(fd, 0);
@@ -28,21 +28,29 @@
 		return -1;
 	}
 
+	len = 0;
 	switch(r->domain){
 	case PF_INET:
 	case PF_INET6:
-		_sock_ingetaddr(r, addr, alen, "local");
+		_sock_ingetaddr(r, &r->addr, &len, "local");
 		break;
 	case PF_UNIX:
 		lunix = (struct sockaddr_un*)&r->addr;
-		i = &lunix->sun_path[strlen(lunix->sun_path)] - (char*)lunix;
-		memmove(addr, lunix, i);
-		if(alen != 0)
-			*alen = i;
+		len = &lunix->sun_path[strlen(lunix->sun_path)] - (char*)lunix;
 		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->addr, len);
+
 	return 0;
 }
--