summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2020-12-23 16:15:11 +0000
committerMark Johnston <markj@FreeBSD.org>2020-12-23 16:16:40 +0000
commit92be2847e845ba90e4da028cfd7f5a8013919f90 (patch)
tree3901d13019e6884d180556251e99d2525dc3a17f /sys
parenta7a7c306bfb0d8d1a83569a098cf6cde492f8bf7 (diff)
downloadsrc-test-92be2847e845ba90e4da028cfd7f5a8013919f90.tar.gz
src-test-92be2847e845ba90e4da028cfd7f5a8013919f90.zip
rtsock: Avoid copying uninitialized padding bytes
When copying sockaddrs out to userspace, we pad them to a multiple of the platform alignment (sizeof(long)). However, some sockaddr sizes, such as struct sockaddr_dl, are not an integer multiple of the alignment, so we may end up copying out uninitialized bytes. Fix this by always bouncing through a pre-zeroed sockaddr_storage. Reported by: KASAN Reviewed by: melifaro MFC after: 3 days Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D27729
Diffstat (limited to 'sys')
-rw-r--r--sys/net/rtsock.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index 4c35642866c9f..5acfd658caf60 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -1258,12 +1258,12 @@ rtsock_fix_netmask(const struct sockaddr *dst, const struct sockaddr *smask,
static struct mbuf *
rtsock_msg_mbuf(int type, struct rt_addrinfo *rtinfo)
{
+ struct sockaddr_storage ss;
struct rt_msghdr *rtm;
struct mbuf *m;
int i;
struct sockaddr *sa;
#ifdef INET6
- struct sockaddr_storage ss;
struct sockaddr_in6 *sin6;
#endif
int len, dlen;
@@ -1308,13 +1308,17 @@ rtsock_msg_mbuf(int type, struct rt_addrinfo *rtinfo)
if ((sa = rtinfo->rti_info[i]) == NULL)
continue;
rtinfo->rti_addrs |= (1 << i);
+
dlen = SA_SIZE(sa);
+ KASSERT(dlen <= sizeof(ss),
+ ("%s: sockaddr size overflow", __func__));
+ bzero(&ss, sizeof(ss));
+ bcopy(sa, &ss, sa->sa_len);
+ sa = (struct sockaddr *)&ss;
#ifdef INET6
if (sa->sa_family == AF_INET6) {
- sin6 = (struct sockaddr_in6 *)&ss;
- bcopy(sa, sin6, sizeof(*sin6));
- if (sa6_recoverscope(sin6) == 0)
- sa = (struct sockaddr *)sin6;
+ sin6 = (struct sockaddr_in6 *)sa;
+ (void)sa6_recoverscope(sin6);
}
#endif
m_copyback(m, len, dlen, (caddr_t)sa);
@@ -1342,12 +1346,11 @@ rtsock_msg_mbuf(int type, struct rt_addrinfo *rtinfo)
static int
rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, struct walkarg *w, int *plen)
{
- int i;
- int len, buflen = 0, dlen;
+ struct sockaddr_storage ss;
+ int len, buflen = 0, dlen, i;
caddr_t cp = NULL;
struct rt_msghdr *rtm = NULL;
#ifdef INET6
- struct sockaddr_storage ss;
struct sockaddr_in6 *sin6;
#endif
#ifdef COMPAT_FREEBSD32
@@ -1414,12 +1417,15 @@ rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, struct walkarg *w, int *
#endif
dlen = SA_SIZE(sa);
if (cp != NULL && buflen >= dlen) {
+ KASSERT(dlen <= sizeof(ss),
+ ("%s: sockaddr size overflow", __func__));
+ bzero(&ss, sizeof(ss));
+ bcopy(sa, &ss, sa->sa_len);
+ sa = (struct sockaddr *)&ss;
#ifdef INET6
if (sa->sa_family == AF_INET6) {
- sin6 = (struct sockaddr_in6 *)&ss;
- bcopy(sa, sin6, sizeof(*sin6));
- if (sa6_recoverscope(sin6) == 0)
- sa = (struct sockaddr *)sin6;
+ sin6 = (struct sockaddr_in6 *)sa;
+ (void)sa6_recoverscope(sin6);
}
#endif
bcopy((caddr_t)sa, cp, (unsigned)dlen);