Hi, The kernel may crash as there is not enough input validation in routing messages.
https://syzkaller.appspot.com/bug?id=e2076a6518b49730aefe64acf0a266f8e79685a5 Here the name of a routing label is not NUL terminated, but there are more things that can go wrong. So I added some checks for incoming routing addresses from userland that the kernel actually uses. It is not super strict as userland may provide incomplete addresses that work anyway. I remember openvpn caused some problems in this area. Could someone test it with this diff? ok? bluhm Index: net/rtsock.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/net/rtsock.c,v retrieving revision 1.290 diff -u -p -w -r1.290 rtsock.c --- net/rtsock.c 28 Aug 2019 20:54:24 -0000 1.290 +++ net/rtsock.c 28 Aug 2019 21:23:34 -0000 @@ -1366,6 +1366,91 @@ rtm_xaddrs(caddr_t cp, caddr_t cplim, st rtinfo->rti_info[i] = sa; ADVANCE(cp, sa); } + for (i = 0; i < RTAX_MAX; i++) { + size_t len, maxlen, size; + + sa = rtinfo->rti_info[i]; + if (sa == NULL) + continue; + maxlen = size = 0; + switch (i) { + case RTAX_DST: + case RTAX_GATEWAY: + case RTAX_SRC: + switch (sa->sa_family) { + case AF_INET: + size = sizeof(struct sockaddr_in); + break; +#ifdef INET6 + case AF_INET6: + size = sizeof(struct sockaddr_in6); + break; +#endif +#ifdef MPLS + case AF_MPLS: + size = sizeof(struct sockaddr_mpls); + break; +#endif + } + break; + case RTAX_IFP: + if (sa->sa_family != AF_LINK) + return (EAFNOSUPPORT); + /* + * XXX Should be sizeof(struct sockaddr_dl), but + * route(8) has a bug and provides less memory. + */ + size = 16; + break; + case RTAX_IFA: + switch (sa->sa_family) { + case AF_INET: + size = sizeof(struct sockaddr_in); + break; +#ifdef INET6 + case AF_INET6: + size = sizeof(struct sockaddr_in6); + break; +#endif + default: + return (EAFNOSUPPORT); + } + break; + case RTAX_LABEL: + maxlen = RTLABEL_LEN; + size = sizeof(struct sockaddr_rtlabel); + break; +#ifdef BFD + case RTAX_BFD: + size = sizeof(struct sockaddr_bfd); + break; +#endif + case RTAX_DNS: + maxlen = RTDNS_LEN; + size = sizeof(struct sockaddr_rtdns); + break; + case RTAX_STATIC: + maxlen = RTSTATIC_LEN; + size = sizeof(struct sockaddr_rtstatic); + break; + case RTAX_SEARCH: + maxlen = RTSEARCH_LEN; + size = sizeof(struct sockaddr_rtsearch); + break; + } + if (size) { + if (sa->sa_len < size) + return (EINVAL); + } + if (maxlen) { + if (2 + maxlen >= size) + return (EINVAL); + len = strnlen(sa->sa_data, maxlen); + if (len >= maxlen || 2 + len >= sa->sa_len) + return (EINVAL); + break; + } + } return (0); }
