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