PERFORCE change 100207 for review

John Baldwin jhb at FreeBSD.org
Wed Jun 28 15:49:29 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=100207

Change 100207 by jhb at jhb_mutex on 2006/06/28 15:16:02

	- Add kern_getsockname() and kern_getpeername() and use them to
	  eliminate some stackgap usage in svr4.

Affected files ...

.. //depot/projects/smpng/sys/compat/svr4/svr4_stream.c#29 edit
.. //depot/projects/smpng/sys/kern/uipc_syscalls.c#78 edit
.. //depot/projects/smpng/sys/sys/syscallsubr.h#33 edit

Differences ...

==== //depot/projects/smpng/sys/compat/svr4/svr4_stream.c#29 (text+ko) ====

@@ -992,7 +992,6 @@
 	struct sockaddr *skp;
 	int sasize;
 	struct svr4_strmcmd bnd;
-	struct bind_args ba;
 
 	if (st == NULL) {
 		DPRINTF(("ti_bind: bad file descriptor\n"));
@@ -1012,7 +1011,7 @@
 
 	switch (st->s_family) {
 	case AF_INET:
-		skp = &sain;
+		skp = (struct sockaddr *)&sain;
 		sasize = sizeof(sain);
 
 		if (bnd.offs == 0)
@@ -1026,7 +1025,7 @@
 		break;
 
 	case AF_LOCAL:
-		skp = &saun;
+		skp = (struct sockaddr *)&saun;
 		sasize = sizeof(saun);
 		if (bnd.offs == 0)
 			goto error;
@@ -1117,13 +1116,9 @@
 	struct svr4_strbuf skb, *sub = (struct svr4_strbuf *) dat;
 	struct svr4_strm *st = svr4_stream_get(fp);
 	int error;
-	void *skp, *sup;
-	struct sockaddr_in sain;
-	struct sockaddr_un saun;
+	struct sockaddr *sa;
+	socklen_t sasize, oldsasize;
 	struct svr4_strmcmd sc;
-	int sasize, oldsasize;
-	caddr_t sg;
-	int *lenp;
 
 	DPRINTF(("svr4_stream_ti_ioctl\n"));
 
@@ -1139,13 +1134,11 @@
 
 	switch (st->s_family) {
 	case AF_INET:
-		skp = &sain;
-		sasize = sizeof(sain);
+		sasize = sizeof(struct sockaddr_in);
 		break;
 
 	case AF_LOCAL:
-		skp = &saun;
-		sasize = sizeof(saun);
+		sasize = sizeof(struct sockaddr_un);
 		break;
 
 	default:
@@ -1153,25 +1146,14 @@
 			 st->s_family));
 		return ENOSYS;
 	}
-
-	sg = stackgap_init();
-	sup = stackgap_alloc(&sg, sasize);
-	lenp = stackgap_alloc(&sg, sizeof(*lenp));
-
-	if ((error = copyout(&sasize, lenp, sizeof(*lenp))) != 0) {
-		DPRINTF(("ti_ioctl: error copying out lenp\n"));
-		return error;
-	}
+	oldsasize = sasize;
 
 	switch (cmd) {
 	case SVR4_TI_GETMYNAME:
 		DPRINTF(("TI_GETMYNAME\n"));
 		{
-			struct getsockname_args ap;
-			ap.fdes = fd;
-			ap.asa = sup;
-			ap.alen = lenp;
-			if ((error = getsockname(td, &ap)) != 0) {
+			error = kern_getsockname(td, fd, &sa, &sasize);
+			if (error) {
 				DPRINTF(("ti_ioctl: getsockname error\n"));
 				return error;
 			}
@@ -1181,11 +1163,8 @@
 	case SVR4_TI_GETPEERNAME:
 		DPRINTF(("TI_GETPEERNAME\n"));
 		{
-			struct getpeername_args ap;
-			ap.fdes = fd;
-			ap.asa = sup;
-			ap.alen = lenp;
-			if ((error = getpeername(td, &ap)) != 0) {
+			error = kern_getpeername(td, fd, &sa, &sasize);
+			if (error) {
 				DPRINTF(("ti_ioctl: getpeername error\n"));
 				return error;
 			}
@@ -1204,36 +1183,27 @@
 		return ENOSYS;
 	}
 
-	if ((error = copyin(sup, skp, sasize)) != 0) {
-		DPRINTF(("ti_ioctl: error copying in socket data\n"));
-		return error;
+	if (sasize < 0 || sasize > oldsasize) {
+		free(sa, M_SONAME);
+		return EINVAL;
 	}
 
-	oldsasize = sasize;
-
-	if ((error = copyin(lenp, &sasize, sizeof(*lenp))) != 0) {
-		DPRINTF(("ti_ioctl: error copying in socket size\n"));
-		return error;
-	}
-
-	if (sasize < 0 || sasize > oldsasize)
-		return EINVAL;
-
 	switch (st->s_family) {
 	case AF_INET:
-		sockaddr_to_netaddr_in(&sc, &sain);
+		sockaddr_to_netaddr_in(&sc, (struct sockaddr_in *)sa);
 		skb.len = sasize;
 		break;
 
 	case AF_LOCAL:
-		sockaddr_to_netaddr_un(&sc, &saun);
+		sockaddr_to_netaddr_un(&sc, (struct sockaddr_un *)sa);
 		skb.len = sasize + 4;
 		break;
 
 	default:
+		free(sa, M_SONAME);
 		return ENOSYS;
 	}
-
+	free(sa, M_SONAME);
 
 	if ((error = copyout(SVR4_ADDROF(&sc), skb.buf, sasize)) != 0) {
 		DPRINTF(("ti_ioctl: error copying out socket data\n"));

==== //depot/projects/smpng/sys/kern/uipc_syscalls.c#78 (text+ko) ====

@@ -1459,48 +1459,64 @@
 	} */ *uap;
 	int compat;
 {
+	struct sockaddr *sa;
+	socklen_t len;
+	int error;
+
+	error = copyin(uap->alen, &len, sizeof(len));
+	if (error)
+		return (error);
+
+	error = kern_getsockname(td, uap->fdes, &sa, &len);
+	if (error)
+		return (error);
+
+	if (len != 0) {
+#ifdef COMPAT_OLDSOCK
+		if (compat)
+			((struct osockaddr *)sa)->sa_family = sa->sa_family;
+#endif
+		error = copyout(sa, uap->asa, (u_int)len);
+	}
+	free(sa, M_SONAME);
+	if (error == 0)
+		error = copyout(&len, uap->alen, sizeof(len));
+	return (error);
+}
+
+int
+kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
+    socklen_t *alen)
+{
 	struct socket *so;
-	struct sockaddr *sa;
 	struct file *fp;
 	socklen_t len;
 	int error;
 
+	if (*alen < 0)
+		return (EINVAL);
+
 	NET_LOCK_GIANT();
-	error = getsock(td->td_proc->p_fd, uap->fdes, &fp, NULL);
+	error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
 	if (error)
-		goto done2;
+		goto done;
 	so = fp->f_data;
-	error = copyin(uap->alen, &len, sizeof (len));
-	if (error)
-		goto done1;
-	if (len < 0) {
-		error = EINVAL;
-		goto done1;
-	}
-	sa = 0;
-	error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa);
+	*sa = NULL;
+	error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, sa);
 	if (error)
 		goto bad;
-	if (sa == 0) {
+	if (*sa == NULL)
 		len = 0;
-		goto gotnothing;
-	}
-
-	len = MIN(len, sa->sa_len);
-#ifdef COMPAT_OLDSOCK
-	if (compat)
-		((struct osockaddr *)sa)->sa_family = sa->sa_family;
-#endif
-	error = copyout(sa, uap->asa, (u_int)len);
-	if (error == 0)
-gotnothing:
-		error = copyout(&len, uap->alen, sizeof (len));
+	else
+		len = MIN(*alen, (*sa)->sa_len);
+	*alen = len;
 bad:
-	if (sa)
-		FREE(sa, M_SONAME);
-done1:
 	fdrop(fp, td);
-done2:
+	if (error && *sa) {
+		free(*sa, M_SONAME);
+		*sa = NULL;
+	}
+done:
 	NET_UNLOCK_GIANT();
 	return (error);
 }
@@ -1547,14 +1563,45 @@
 	} */ *uap;
 	int compat;
 {
+	struct sockaddr *sa;
+	socklen_t len;
+	int error;
+
+	error = copyin(uap->alen, &len, sizeof (len));
+	if (error)
+		return (error);
+
+	error = kern_getpeername(td, uap->fdes, &sa, &len);
+	if (error)
+		return (error);
+
+	if (len != 0) {
+#ifdef COMPAT_OLDSOCK
+		if (compat)
+			((struct osockaddr *)sa)->sa_family = sa->sa_family;
+#endif
+		error = copyout(sa, uap->asa, (u_int)len);
+	}
+	free(sa, M_SONAME);
+	if (error == 0)
+		error = copyout(&len, uap->alen, sizeof(len));
+	return (error);
+}
+
+int
+kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
+    socklen_t *alen)
+{
 	struct socket *so;
-	struct sockaddr *sa;
 	struct file *fp;
 	socklen_t len;
 	int error;
 
+	if (*alen < 0)
+		return (EINVAL);
+
 	NET_LOCK_GIANT();
-	error = getsock(td->td_proc->p_fd, uap->fdes, &fp, NULL);
+	error = getsock(td->td_proc->p_fd, fd, &fp, NULL);
 	if (error)
 		goto done2;
 	so = fp->f_data;
@@ -1562,35 +1609,20 @@
 		error = ENOTCONN;
 		goto done1;
 	}
-	error = copyin(uap->alen, &len, sizeof (len));
-	if (error)
-		goto done1;
-	if (len < 0) {
-		error = EINVAL;
-		goto done1;
-	}
-	sa = 0;
-	error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa);
+	*sa = NULL;
+	error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, sa);
 	if (error)
 		goto bad;
-	if (sa == 0) {
+	if (*sa == NULL)
 		len = 0;
-		goto gotnothing;
+	else
+		len = MIN(*alen, (*sa)->sa_len);
+	*alen = len;
+bad:
+	if (error && *sa) {
+		free(*sa, M_SONAME);
+		*sa = NULL;
 	}
-	len = MIN(len, sa->sa_len);
-#ifdef COMPAT_OLDSOCK
-	if (compat)
-		((struct osockaddr *)sa)->sa_family =
-		    sa->sa_family;
-#endif
-	error = copyout(sa, uap->asa, (u_int)len);
-	if (error)
-		goto bad;
-gotnothing:
-	error = copyout(&len, uap->alen, sizeof (len));
-bad:
-	if (sa)
-		FREE(sa, M_SONAME);
 done1:
 	fdrop(fp, td);
 done2:

==== //depot/projects/smpng/sys/sys/syscallsubr.h#33 (text+ko) ====

@@ -82,7 +82,11 @@
 int	kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
 	    enum uio_seg bufseg, int flags);
 int	kern_getitimer(struct thread *, u_int, struct itimerval *);
+int	kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
+	    socklen_t *alen);
 int	kern_getrusage(struct thread *td, int who, struct rusage *rup);
+int	kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
+	    socklen_t *alen);
 int	kern_getsockopt(struct thread *td, int s, int level, int name,
 	    void *optval, enum uio_seg valseg, socklen_t *valsize);
 int	kern_kevent(struct thread *td, int fd, int nchanges, int nevents,


More information about the p4-projects mailing list