--- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -900,6 +900,18 @@ */ if (ifra->ifra_prefixmask.sin6_len > sizeof(struct sockaddr_in6)) return (EINVAL); + + /* + * Validate ifra_dstaddr length. The kernel keeps copying the + * whole sockaddr_in6 -- including the bogus sin6_len -- into + * ia->ia_dstaddr, and in6_lifaddr_ioctl() later uses + * ia_dstaddr.sin6_len as a bcopy() length (SIOCGLIFADDR / + * SIOCDLIFADDR), causing an out-of-bounds read past the + * in6_ifaddr allocation and an out-of-bounds write past the + * 128-byte on-stack struct in6_aliasreq. + */ + if (ifra->ifra_dstaddr.sin6_len > sizeof(struct sockaddr_in6)) + return (EINVAL); /* * Because the IPv6 address architecture is classless, we require * users to specify a (non 0) prefix length (mask) for a new address.