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