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
This commit is contained in:
parent
a7a7c306bf
commit
92be2847e8
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user