[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openbsd-tech
Subject:    Fix accept/recv/getsockname/etc to return the full addr length
From:       Matthew Dempsky <matthew () dempsky ! org>
Date:       2012-04-25 22:42:33
Message-ID: 20120425224233.GA6118 () mdempsky ! mtv ! corp ! google ! com
[Download RAW message or body]

According to POSIX, accept(), recvfrom(), recvmsg(), getsockname(),
and getpeername() are supposed to store the untruncated address length
in *addrlen.

Diff below makes our methods conform to this requirement and also
cleans things up a little bit by refactoring out some common code into
a new copyaddrout() function.

ok?


Index: uipc_syscalls.c
===================================================================
RCS file: /home/mdempsky/anoncvs/cvs/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.84
diff -u -p -r1.84 uipc_syscalls.c
--- uipc_syscalls.c	3 Dec 2011 12:38:30 -0000	1.84
+++ uipc_syscalls.c	20 Apr 2012 22:10:04 -0000
@@ -61,6 +61,9 @@
  */
 extern	struct fileops socketops;
 
+int copyaddrout(struct proc *, struct mbuf *, struct sockaddr *, socklen_t,
+    socklen_t *);
+
 int
 sys_socket(struct proc *p, void *v, register_t *retval)
 {
@@ -118,8 +121,8 @@ sys_bind(struct proc *p, void *v, regist
 			 MT_SONAME);
 	if (error == 0) {
 #ifdef KTRACE
-	if (KTRPOINT(p, KTR_STRUCT))
-		ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen));
+		if (KTRPOINT(p, KTR_STRUCT))
+			ktrsockaddr(p, mtod(nam, caddr_t), SCARG(uap, namelen));
 #endif
 		error = sobind(fp->f_data, nam, p);
 		m_freem(nam);
@@ -235,18 +238,8 @@ sys_accept(struct proc *p, void *v, regi
 	nam = m_get(M_WAIT, MT_SONAME);
 	error = soaccept(so, nam);
 	if (!error && SCARG(uap, name)) {
-		if (namelen > nam->m_len)
-			namelen = nam->m_len;
-		/* SHOULD COPY OUT A CHAIN HERE */
-		if ((error = copyout(mtod(nam, caddr_t),
-		    SCARG(uap, name), namelen)) == 0) {
-#ifdef KTRACE
-			if (KTRPOINT(p, KTR_STRUCT))
-				ktrsockaddr(p, mtod(nam, caddr_t), namelen);
-#endif
-			error = copyout(&namelen, SCARG(uap, anamelen),
-			    sizeof (*SCARG(uap, anamelen)));
-		}
+		error = copyaddrout(p, nam, SCARG(uap, name), namelen,
+		    SCARG(uap, anamelen));
 	}
 
 	if (error) {
@@ -690,16 +683,15 @@ recvit(struct proc *p, int s, struct msg
 		if (from == NULL)
 			alen = 0;
 		else {
-			alen = MIN(from->m_len, mp->msg_namelen);
+			alen = from->m_len;
 			error = copyout(mtod(from, caddr_t), mp->msg_name,
-			    alen);
+			    MIN(alen, mp->msg_namelen));
 			if (error)
 				goto out;
 #ifdef KTRACE
 			if (KTRPOINT(p, KTR_STRUCT))
 				ktrsockaddr(p, mtod(from, caddr_t), alen);
 #endif
-
 		}
 		mp->msg_namelen = alen;
 		if (namelenp &&
@@ -886,16 +878,7 @@ sys_getsockname(struct proc *p, void *v,
 	error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0, p);
 	if (error)
 		goto bad;
-	if (len > m->m_len)
-		len = m->m_len;
-	error = copyout(mtod(m, caddr_t), SCARG(uap, asa), len);
-	if (error == 0) {
-#ifdef KTRACE
-		if (KTRPOINT(p, KTR_STRUCT))
-			ktrsockaddr(p, mtod(m, caddr_t), len);
-#endif
-		error = copyout(&len, SCARG(uap, alen), sizeof (len));
-	}
+	error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
 bad:
 	FRELE(fp);
 	if (m)
@@ -935,16 +918,7 @@ sys_getpeername(struct proc *p, void *v,
 	error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0, p);
 	if (error)
 		goto bad;
-	if (len > m->m_len)
-		len = m->m_len;
-	error = copyout(mtod(m, caddr_t), SCARG(uap, asa), len);
-	if (error == 0) {
-#ifdef KTRACE
-		if (KTRPOINT(p, KTR_STRUCT))
-			ktrsockaddr(p, mtod(m, caddr_t), len);
-#endif
-		error = copyout(&len, SCARG(uap, alen), sizeof (len));
-	}
+	error = copyaddrout(p, m, SCARG(uap, asa), len, SCARG(uap, alen));
 bad:
 	FRELE(fp);
 	m_freem(m);
@@ -1036,4 +1010,24 @@ sys_getrtable(struct proc *p, void *v, r
 {
 	*retval = (int)p->p_p->ps_rtableid;
 	return (0);
+}
+
+int
+copyaddrout(struct proc *p, struct mbuf *name, struct sockaddr *sa,
+    socklen_t buflen, socklen_t *outlen)
+{
+	int error;
+	socklen_t namelen = name->m_len;
+
+	/* SHOULD COPY OUT A CHAIN HERE */
+	error = copyout(mtod(name, caddr_t), sa, MIN(buflen, namelen));
+	if (error == 0) {
+#ifdef KTRACE
+		if (KTRPOINT(p, KTR_STRUCT))
+			ktrsockaddr(p, mtod(name, caddr_t), namelen);
+#endif
+		error = copyout(&namelen, outlen, sizeof(*outlen));
+	}
+
+	return (error);
 }

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic