Module Name: src
Committed By: snj
Date: Tue Jul 25 01:55:21 UTC 2017
Modified Files:
src/sys/kern [netbsd-8]: uipc_domain.c
src/sys/net [netbsd-8]: rtsock.c
src/sys/sys [netbsd-8]: socket.h
Log Message:
Pull up following revision(s) (requested by ozaki-r in ticket #140):
sys/kern/uipc_domain.c: 1.97-1.99
sys/net/rtsock.c: 1.225-1.227
sys/sys/socket.h: 1.123
Restore the original length of a sockaddr for netmask
route(8) passes a sockaddr for netmask that is truncated with its
prefixlen. However the kernel basically doesn't expect such format
and may read beyond the data. So restore the original length of the
the data at the beginning of the kernel for the rest components.
Failures of ATF tests such as route_flags_blackhole6 should
be fixed.
--
Avoid DIAGNOSTIC warning with previous fix and simplify it (don't require
memory alloc/free).
--
put the code that returns the sizeof the socket by family in one place.
--
don't warn about AF_LINK sockets with sa_len less than the size of the sockaddr
--
don't print diagnostic for AF_LINK
To generate a diff of this commit:
cvs rdiff -u -r1.96 -r1.96.10.1 src/sys/kern/uipc_domain.c
cvs rdiff -u -r1.213.2.1 -r1.213.2.2 src/sys/net/rtsock.c
cvs rdiff -u -r1.122 -r1.122.2.1 src/sys/sys/socket.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/uipc_domain.c
diff -u src/sys/kern/uipc_domain.c:1.96 src/sys/kern/uipc_domain.c:1.96.10.1
--- src/sys/kern/uipc_domain.c:1.96 Tue Dec 2 19:45:58 2014
+++ src/sys/kern/uipc_domain.c Tue Jul 25 01:55:21 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: uipc_domain.c,v 1.96 2014/12/02 19:45:58 christos Exp $ */
+/* $NetBSD: uipc_domain.c,v 1.96.10.1 2017/07/25 01:55:21 snj Exp $ */
/*
* Copyright (c) 1982, 1986, 1993
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_domain.c,v 1.96 2014/12/02 19:45:58 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_domain.c,v 1.96.10.1 2017/07/25 01:55:21 snj Exp $");
#include <sys/param.h>
#include <sys/socket.h>
@@ -228,7 +228,7 @@ sockaddr_const_addr(const struct sockadd
}
const struct sockaddr *
-sockaddr_any_by_family(int family)
+sockaddr_any_by_family(sa_family_t family)
{
const struct domain *dom;
@@ -255,43 +255,45 @@ sockaddr_anyaddr(const struct sockaddr *
return sockaddr_const_addr(any, slenp);
}
-#ifdef DIAGNOSTIC
-static void
-sockaddr_checklen(const struct sockaddr *sa)
+socklen_t
+sockaddr_getsize_by_family(sa_family_t af)
{
- socklen_t len = 0;
- switch (sa->sa_family) {
+ switch (af) {
case AF_INET:
- len = sizeof(struct sockaddr_in);
- break;
+ return sizeof(struct sockaddr_in);
case AF_INET6:
- len = sizeof(struct sockaddr_in6);
- break;
+ return sizeof(struct sockaddr_in6);
case AF_UNIX:
- len = sizeof(struct sockaddr_un);
- break;
+ return sizeof(struct sockaddr_un);
case AF_LINK:
- len = sizeof(struct sockaddr_dl);
- // As long as it is not 0...
- if (sa->sa_len != 0)
- return;
- break;
+ return sizeof(struct sockaddr_dl);
case AF_APPLETALK:
- len = sizeof(struct sockaddr_at);
- break;
+ return sizeof(struct sockaddr_at);
default:
- printf("%s: Unhandled af=%hhu socklen=%hhu\n", __func__,
- sa->sa_family, sa->sa_len);
- return;
- }
- if (len != sa->sa_len) {
- char buf[512];
- sockaddr_format(sa, buf, sizeof(buf));
- printf("%s: %p bad len af=%hhu socklen=%hhu len=%u [%s]\n",
- __func__, sa, sa->sa_family, sa->sa_len,
- (unsigned)len, buf);
+#ifdef DIAGNOSTIC
+ printf("%s: Unhandled address family=%hhu\n", __func__, af);
+#endif
+ return 0;
}
}
+
+#ifdef DIAGNOSTIC
+static void
+sockaddr_checklen(const struct sockaddr *sa)
+{
+ // Can't tell how much was allocated, if it was allocated.
+ if (sa->sa_family == AF_LINK)
+ return;
+
+ socklen_t len = sockaddr_getsize_by_family(sa->sa_family);
+ if (len == 0 || len == sa->sa_len)
+ return;
+
+ char buf[512];
+ sockaddr_format(sa, buf, sizeof(buf));
+ printf("%s: %p bad len af=%hhu socklen=%hhu len=%u [%s]\n",
+ __func__, sa, sa->sa_family, sa->sa_len, (unsigned)len, buf);
+}
#else
#define sockaddr_checklen(sa) ((void)0)
#endif
Index: src/sys/net/rtsock.c
diff -u src/sys/net/rtsock.c:1.213.2.1 src/sys/net/rtsock.c:1.213.2.2
--- src/sys/net/rtsock.c:1.213.2.1 Fri Jul 7 13:57:26 2017
+++ src/sys/net/rtsock.c Tue Jul 25 01:55:21 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: rtsock.c,v 1.213.2.1 2017/07/07 13:57:26 martin Exp $ */
+/* $NetBSD: rtsock.c,v 1.213.2.2 2017/07/25 01:55:21 snj Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.213.2.1 2017/07/07 13:57:26 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.213.2.2 2017/07/25 01:55:21 snj Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@@ -736,6 +736,7 @@ COMPATNAME(route_output)(struct mbuf *m,
struct sockaddr_dl sdl;
int bound = curlwp_bind();
bool do_rt_free = false;
+ struct sockaddr_storage netmask;
#define senderr(e) do { error = e; goto flush;} while (/*CONSTCOND*/ 0)
if (m == NULL || ((m->m_len < sizeof(int32_t)) &&
@@ -793,6 +794,25 @@ COMPATNAME(route_output)(struct mbuf *m,
0, rtm, NULL, NULL) != 0)
senderr(EACCES);
+ /*
+ * route(8) passes a sockaddr truncated with prefixlen.
+ * The kernel doesn't expect such sockaddr and need to
+ * use a buffer that is big enough for the sockaddr expected
+ * (padded with 0's). We keep the original length of the sockaddr.
+ */
+ if (info.rti_info[RTAX_NETMASK]) {
+ socklen_t sa_len = sockaddr_getsize_by_family(
+ info.rti_info[RTAX_NETMASK]->sa_family);
+ socklen_t masklen = sockaddr_getlen(
+ info.rti_info[RTAX_NETMASK]);
+ if (sa_len != 0 && sa_len > masklen) {
+ KASSERT(sa_len <= sizeof(netmask));
+ memcpy(&netmask, info.rti_info[RTAX_NETMASK], masklen);
+ memset((char *)&netmask + masklen, 0, sa_len - masklen);
+ info.rti_info[RTAX_NETMASK] = sstocsa(&netmask);
+ }
+ }
+
switch (rtm->rtm_type) {
case RTM_ADD:
Index: src/sys/sys/socket.h
diff -u src/sys/sys/socket.h:1.122 src/sys/sys/socket.h:1.122.2.1
--- src/sys/sys/socket.h:1.122 Sat May 27 21:02:56 2017
+++ src/sys/sys/socket.h Tue Jul 25 01:55:21 2017
@@ -1,4 +1,4 @@
-/* $NetBSD: socket.h,v 1.122 2017/05/27 21:02:56 bouyer Exp $ */
+/* $NetBSD: socket.h,v 1.122.2.1 2017/07/25 01:55:21 snj Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -625,6 +625,7 @@ sockaddr_getlen(const struct sockaddr *s
}
__BEGIN_DECLS
+socklen_t sockaddr_getsize_by_family(sa_family_t);
struct sockaddr *sockaddr_copy(struct sockaddr *, socklen_t,
const struct sockaddr *);
struct sockaddr *sockaddr_externalize(struct sockaddr *, socklen_t,
@@ -633,7 +634,7 @@ struct sockaddr *sockaddr_alloc(sa_famil
const void *sockaddr_const_addr(const struct sockaddr *, socklen_t *);
void *sockaddr_addr(struct sockaddr *, socklen_t *);
const struct sockaddr *sockaddr_any(const struct sockaddr *);
-const struct sockaddr *sockaddr_any_by_family(int);
+const struct sockaddr *sockaddr_any_by_family(sa_family_t);
const void *sockaddr_anyaddr(const struct sockaddr *, socklen_t *);
int sockaddr_cmp(const struct sockaddr *, const struct sockaddr *);
struct sockaddr *sockaddr_dup(const struct sockaddr *, int);