Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys * change pr_bind to accept struct sockaddr * instead of ...



details:   https://anonhg.NetBSD.org/src/rev/6212d9de48e0
branches:  trunk
changeset: 337129:6212d9de48e0
user:      rtr <rtr%NetBSD.org@localhost>
date:      Fri Apr 03 20:01:07 2015 +0000

description:
* change pr_bind to accept struct sockaddr * instead of struct mbuf *
* update protocol bind implementations to use/expect sockaddr *
  instead of mbuf *
* introduce sockaddr_big struct for storage of addr data passed via
  sys_bind; sockaddr_big is of sufficient size and alignment to
  accommodate all addr data sizes received.
* modify sys_bind to allocate sockaddr_big instead of using an mbuf.
* bump kernel version to 7.99.9 for change to pr_bind() parameter type.

Patch posted to tech-net@
  http://mail-index.netbsd.org/tech-net/2015/03/15/msg005004.html

The choice to use a new structure sockaddr_big has been retained since
changing sockaddr_storage size would lead to unnecessary ABI change. The
use of the new structure does not preclude future work that increases
the size of sockaddr_storage and at that time sockaddr_big may be
trivially replaced.

Tested by mrg@ and myself, discussed with rmind@, posted to tech-net@

diffstat:

 sys/compat/linux/common/linux_socket.c |  83 +++++++++++++++++++++++++++++++--
 sys/compat/svr4/svr4_stream.c          |  24 +++------
 sys/kern/uipc_socket.c                 |   6 +-
 sys/kern/uipc_syscalls.c               |  54 ++++++++++++++++-----
 sys/kern/uipc_usrreq.c                 |  24 ++++++++-
 sys/net/if_gre.c                       |   6 +-
 sys/net/link_proto.c                   |   8 +-
 sys/net/rtsock.c                       |   6 +-
 sys/netatalk/ddp_usrreq.c              |  19 +++----
 sys/netbt/hci_socket.c                 |   9 +--
 sys/netbt/l2cap_socket.c               |   9 +--
 sys/netbt/rfcomm_socket.c              |   9 +--
 sys/netbt/sco_socket.c                 |   9 +--
 sys/netinet/in_pcb.c                   |  12 ++--
 sys/netinet/in_pcb.h                   |   4 +-
 sys/netinet/raw_ip.c                   |  16 ++---
 sys/netinet/tcp_usrreq.c               |  14 +++--
 sys/netinet/udp_usrreq.c               |   9 ++-
 sys/netinet6/in6_pcb.c                 |  12 ++--
 sys/netinet6/in6_pcb.h                 |   4 +-
 sys/netinet6/raw_ip6.c                 |  11 ++--
 sys/netinet6/udp6_usrreq.c             |   9 ++-
 sys/netipsec/keysock.c                 |   6 +-
 sys/netmpls/mpls_proto.c               |   6 +-
 sys/netnatm/natm.c                     |   6 +-
 sys/nfs/nfs_boot.c                     |  20 +++----
 sys/nfs/nfs_socket.c                   |  35 +++++---------
 sys/rump/net/lib/libsockin/sockin.c    |  12 ++--
 sys/sys/param.h                        |   4 +-
 sys/sys/protosw.h                      |   8 +-
 sys/sys/socket.h                       |  20 +++++++-
 sys/sys/socketvar.h                    |   6 +-
 32 files changed, 293 insertions(+), 187 deletions(-)

diffs (truncated from 1367 to 300 lines):

diff -r ccaf88b941d8 -r 6212d9de48e0 sys/compat/linux/common/linux_socket.c
--- a/sys/compat/linux/common/linux_socket.c    Fri Apr 03 18:03:05 2015 +0000
+++ b/sys/compat/linux/common/linux_socket.c    Fri Apr 03 20:01:07 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_socket.c,v 1.122 2014/11/26 09:53:53 ozaki-r Exp $       */
+/*     $NetBSD: linux_socket.c,v 1.123 2015/04/03 20:01:07 rtr Exp $   */
 
 /*-
  * Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.122 2014/11/26 09:53:53 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.123 2015/04/03 20:01:07 rtr Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -121,6 +121,8 @@
 int linux_getifhwaddr(struct lwp *, register_t *, u_int, void *);
 static int linux_get_sa(struct lwp *, int, struct mbuf **,
                const struct osockaddr *, unsigned int);
+static int linux_get_sa_sb(struct lwp *, int, struct sockaddr_big *,
+               const struct osockaddr *, socklen_t);
 static int linux_sa_put(struct osockaddr *osa);
 static int linux_to_bsd_msg_flags(int);
 static int bsd_to_linux_msg_flags(int);
@@ -1445,14 +1447,14 @@
                syscallarg(int) namelen;
        } */
        int             error;
-       struct mbuf     *nam;
+       struct sockaddr_big sb;
 
-       error = linux_get_sa(l, SCARG(uap, s), &nam, SCARG(uap, name),
+       error = linux_get_sa_sb(l, SCARG(uap, s), &sb, SCARG(uap, name),
            SCARG(uap, namelen));
        if (error)
                return (error);
 
-       return do_sys_bind(l, SCARG(uap, s), nam);
+       return do_sys_bind(l, SCARG(uap, s), (struct sockaddr *)&sb);
 }
 
 int
@@ -1493,6 +1495,77 @@
        return (0);
 }
 
+static int
+linux_get_sa_sb(struct lwp *l, int s, struct sockaddr_big *sb,
+    const struct osockaddr *name, socklen_t namelen)
+{
+       int error, bdom;
+
+       if (namelen > UCHAR_MAX ||
+           namelen <= offsetof(struct sockaddr_big, sb_data))
+               return EINVAL;
+
+       error = copyin(name, sb, namelen);
+       if (error)
+               return error;
+
+       bdom = linux_to_bsd_domain(sb->sb_family);
+       if (bdom == -1)
+               return EINVAL;
+
+       /*
+        * If the family is unspecified, use address family of the socket.
+        * This avoid triggering strict family checks in netinet/in_pcb.c et.al.
+        */
+       if (bdom == AF_UNSPEC) {
+               struct socket *so;
+
+               /* fd_getsock() will use the descriptor for us */
+               if ((error = fd_getsock(s, &so)) != 0)
+                       return error;
+
+               bdom = so->so_proto->pr_domain->dom_family;
+               fd_putfile(s);
+       }
+
+       /*
+        * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
+        * which lacks the scope id compared with RFC2553 one. If we detect
+        * the situation, reject the address and write a message to system log.
+        *
+        * Still accept addresses for which the scope id is not used.
+        */
+       if (bdom == AF_INET6 &&
+           namelen == sizeof(struct sockaddr_in6) - sizeof(uint32_t)) {
+               struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sb;
+               if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) &&
+                   (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
+                    IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) ||
+                    IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) ||
+                    IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
+                    IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
+                       struct proc *p = l->l_proc;
+                       int uid = l->l_cred ? kauth_cred_geteuid(l->l_cred) : -1;
+
+                       log(LOG_DEBUG,
+                           "pid %d (%s), uid %d: obsolete pre-RFC2553 "
+                           "sockaddr_in6 rejected",
+                           p->p_pid, p->p_comm, uid);
+                       return EINVAL;
+               }
+               namelen = sizeof(struct sockaddr_in6);
+               sin6->sin6_scope_id = 0;
+       }
+
+       if (bdom == AF_INET)
+               namelen = sizeof(struct sockaddr_in);
+
+       sb->sb_family = bdom;
+       sb->sb_len = namelen;
+       ktrkuser("mbsoname", sb, namelen);
+       return 0;
+}
+
 /*
  * Copy the osockaddr structure pointed to by osa to mbuf, adjust
  * family and convert to sockaddr.
diff -r ccaf88b941d8 -r 6212d9de48e0 sys/compat/svr4/svr4_stream.c
--- a/sys/compat/svr4/svr4_stream.c     Fri Apr 03 18:03:05 2015 +0000
+++ b/sys/compat/svr4/svr4_stream.c     Fri Apr 03 20:01:07 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: svr4_stream.c,v 1.81 2014/09/05 09:21:55 matt Exp $     */
+/*     $NetBSD: svr4_stream.c,v 1.82 2015/04/03 20:01:07 rtr Exp $      */
 
 /*-
  * Copyright (c) 1994, 2008 The NetBSD Foundation, Inc.
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: svr4_stream.c,v 1.81 2014/09/05 09:21:55 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: svr4_stream.c,v 1.82 2015/04/03 20:01:07 rtr Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -752,10 +752,10 @@
        struct svr4_strm *st = svr4_stream_get(fp);
        struct sockaddr_in sain;
        struct sockaddr_un saun;
-       void *skp, *sup = NULL;
+       struct sockaddr_big *sbig;
+       void *sup = NULL;
        int sasize;
        struct svr4_strmcmd bnd;
-       struct mbuf *name;
 
        if (st == NULL) {
                DPRINTF(("ti_bind: bad file descriptor\n"));
@@ -775,8 +775,8 @@
 
        switch (st->s_family) {
        case AF_INET:
-               skp = &sain;
-               sasize = sizeof(sain);
+               sbig = (struct sockaddr_big *)&sain;
+               sbig->sb_len = sasize = sizeof(sain);
 
                if (bnd.offs == 0)
                        goto reply;
@@ -789,8 +789,8 @@
                break;
 
        case AF_LOCAL:
-               skp = &saun;
-               sasize = sizeof(saun);
+               sbig = (struct sockaddr_big *)&saun;
+               sbig->sb_len = sasize = sizeof(saun);
                if (bnd.offs == 0)
                        goto reply;
 
@@ -814,15 +814,9 @@
                return ENOSYS;
        }
 
-       name = m_get(M_WAIT, MT_SONAME);
-       if (sasize > MLEN)
-               MEXTMALLOC(name, sasize, M_WAITOK);
-
-       memcpy(mtod(name, void *), skp, sasize);
-
        DPRINTF(("TI_BIND: fileno %d\n", fd));
 
-       error = do_sys_bind(l, fd, name);
+       error = do_sys_bind(l, fd, (struct sockaddr *)sbig);
        if (error != 0) {
                DPRINTF(("TI_BIND: bind failed %d\n", error));
                return error;
diff -r ccaf88b941d8 -r 6212d9de48e0 sys/kern/uipc_socket.c
--- a/sys/kern/uipc_socket.c    Fri Apr 03 18:03:05 2015 +0000
+++ b/sys/kern/uipc_socket.c    Fri Apr 03 20:01:07 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uipc_socket.c,v 1.235 2014/09/05 09:20:59 matt Exp $   */
+/*     $NetBSD: uipc_socket.c,v 1.236 2015/04/03 20:01:07 rtr Exp $    */
 
 /*-
  * Copyright (c) 2002, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.235 2014/09/05 09:20:59 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_socket.c,v 1.236 2015/04/03 20:01:07 rtr Exp $");
 
 #include "opt_compat_netbsd.h"
 #include "opt_sock_counters.h"
@@ -624,7 +624,7 @@
 }
 
 int
-sobind(struct socket *so, struct mbuf *nam, struct lwp *l)
+sobind(struct socket *so, struct sockaddr *nam, struct lwp *l)
 {
        int     error;
 
diff -r ccaf88b941d8 -r 6212d9de48e0 sys/kern/uipc_syscalls.c
--- a/sys/kern/uipc_syscalls.c  Fri Apr 03 18:03:05 2015 +0000
+++ b/sys/kern/uipc_syscalls.c  Fri Apr 03 20:01:07 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uipc_syscalls.c,v 1.174 2015/03/06 03:35:00 rtr Exp $  */
+/*     $NetBSD: uipc_syscalls.c,v 1.175 2015/04/03 20:01:07 rtr Exp $  */
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.174 2015/03/06 03:35:00 rtr Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls.c,v 1.175 2015/04/03 20:01:07 rtr Exp $");
 
 #include "opt_pipe.h"
 
@@ -91,6 +91,8 @@
  */
 extern const struct fileops socketops;
 
+static int     sockargs_sb(struct sockaddr_big *, const void *, socklen_t);
+
 int
 sys___socket30(struct lwp *l, const struct sys___socket30_args *uap,
     register_t *retval)
@@ -118,30 +120,25 @@
                syscallarg(const struct sockaddr *)     name;
                syscallarg(unsigned int)                namelen;
        } */
-       struct mbuf     *nam;
        int             error;
+       struct sockaddr_big sb;
 
-       error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
-           MT_SONAME);
+       error = sockargs_sb(&sb, SCARG(uap, name), SCARG(uap, namelen));
        if (error)
                return error;
 
-       return do_sys_bind(l, SCARG(uap, s), nam);
+       return do_sys_bind(l, SCARG(uap, s), (struct sockaddr *)&sb);
 }
 
 int
-do_sys_bind(struct lwp *l, int fd, struct mbuf *nam)
+do_sys_bind(struct lwp *l, int fd, struct sockaddr *nam)
 {
        struct socket   *so;
        int             error;
 
-       if ((error = fd_getsock(fd, &so)) != 0) {
-               m_freem(nam);
-               return (error);
-       }
-       MCLAIM(nam, so->so_mowner);
+       if ((error = fd_getsock(fd, &so)) != 0)
+               return error;
        error = sobind(so, nam, l);
-       m_freem(nam);
        fd_putfile(fd);
        return error;
 }
@@ -1444,6 +1441,37 @@
        return error;
 }
 
+static int
+sockargs_sb(struct sockaddr_big *sb, const void *name, socklen_t buflen)
+{
+       int error;
+
+       /*
+        * We can't allow socket names > UCHAR_MAX in length, since that
+        * will overflow sb_len. Further no reasonable buflen is <=
+        * offsetof(sockaddr_big, sb_data) since it shall be at least
+        * the size of the preamble sb_len and sb_family members.
+        */
+       if (buflen > UCHAR_MAX ||



Home | Main Index | Thread Index | Old Index