untrusted comment: verify with openbsd-69-base.pub RWQQsAemppS46J2WuYwo2Cww4zYkyt/hv9kxHHEtEE9LRB2pHjziGSI8ujUE+C3jXTg52jNXNYdAhHejwWb/zq4D76Fr37OEuAQ= OpenBSD 6.9 errata 033, March 22, 2022: A malicious router advertisement could overflow heap memory in unprivileged slaacd process. Apply by doing: signify -Vep /etc/signify/openbsd-69-base.pub -x 033_slaacd.patch.sig \ -m - | (cd /usr/src && patch -p0) And then rebuild and install slaacd and slaacctl: cd /usr/src/sbin/slaacd make obj make make install cd /usr/src/usr.sbin/slaacctl make obj make make install Index: sbin/slaacd/engine.c =================================================================== RCS file: /cvs/src/sbin/slaacd/engine.c,v retrieving revision 1.71.2.1 diff -u -p -r1.71.2.1 engine.c --- sbin/slaacd/engine.c 21 Feb 2022 17:44:41 -0000 1.71.2.1 +++ sbin/slaacd/engine.c 18 Mar 2022 20:15:08 -0000 @@ -156,11 +156,6 @@ struct radv_rdns { struct in6_addr rdns; }; -struct radv_dnssl { - LIST_ENTRY(radv_dnssl) entries; - char dnssl[SLAACD_MAX_DNSSL]; -}; - struct radv { LIST_ENTRY(radv) entries; struct sockaddr_in6 from; @@ -178,8 +173,6 @@ struct radv { LIST_HEAD(, radv_prefix) prefixes; uint32_t rdns_lifetime; LIST_HEAD(, radv_rdns) rdns_servers; - uint32_t dnssl_lifetime; - LIST_HEAD(, radv_dnssl) dnssls; uint32_t mtu; }; @@ -304,7 +297,6 @@ void propose_rdns(struct rdns_proposa void free_rdns_proposal(struct rdns_proposal *); void compose_rdns_proposal(uint32_t, int); #endif /* SMALL */ -char *parse_dnssl(char *, int); void update_iface_ra(struct slaacd_iface *, struct radv *); void update_iface_ra_dfr(struct slaacd_iface *, struct radv *); @@ -772,14 +764,12 @@ send_interface_info(struct slaacd_iface struct ctl_engine_info_ra cei_ra; struct ctl_engine_info_ra_prefix cei_ra_prefix; struct ctl_engine_info_ra_rdns cei_ra_rdns; - struct ctl_engine_info_ra_dnssl cei_ra_dnssl; struct ctl_engine_info_address_proposal cei_addr_proposal; struct ctl_engine_info_dfr_proposal cei_dfr_proposal; struct ctl_engine_info_rdns_proposal cei_rdns_proposal; struct radv *ra; struct radv_prefix *prefix; struct radv_rdns *rdns; - struct radv_dnssl *dnssl; struct address_proposal *addr_proposal; struct dfr_proposal *dfr_proposal; struct rdns_proposal *rdns_proposal; @@ -836,16 +826,6 @@ send_interface_info(struct slaacd_iface IMSG_CTL_SHOW_INTERFACE_INFO_RA_RDNS, pid, &cei_ra_rdns, sizeof(cei_ra_rdns)); } - - LIST_FOREACH(dnssl, &ra->dnssls, entries) { - memset(&cei_ra_dnssl, 0, sizeof(cei_ra_dnssl)); - memcpy(&cei_ra_dnssl.dnssl, &dnssl->dnssl, - sizeof(cei_ra_dnssl.dnssl)); - cei_ra_dnssl.lifetime = ra->dnssl_lifetime; - engine_imsg_compose_frontend( - IMSG_CTL_SHOW_INTERFACE_INFO_RA_DNSSL, pid, - &cei_ra_dnssl, sizeof(cei_ra_dnssl)); - } } if (!LIST_EMPTY(&iface->addr_proposals)) @@ -1047,7 +1027,6 @@ free_ra(struct radv *ra) { struct radv_prefix *prefix; struct radv_rdns *rdns; - struct radv_dnssl *dnssl; if (ra == NULL) return; @@ -1066,12 +1045,6 @@ free_ra(struct radv *ra) free(rdns); } - while (!LIST_EMPTY(&ra->dnssls)) { - dnssl = LIST_FIRST(&ra->dnssls); - LIST_REMOVE(dnssl, entries); - free(dnssl); - } - free(ra); } @@ -1175,7 +1148,6 @@ parse_ra(struct slaacd_iface *iface, str struct radv *radv; struct radv_prefix *prefix; struct radv_rdns *rdns; - struct radv_dnssl *ra_dnssl; ssize_t len = ra->len; const char *hbuf; uint8_t *p; @@ -1213,7 +1185,6 @@ parse_ra(struct slaacd_iface *iface, str LIST_INIT(&radv->prefixes); LIST_INIT(&radv->rdns_servers); - LIST_INIT(&radv->dnssls); radv->min_lifetime = UINT32_MAX; @@ -1264,11 +1235,9 @@ parse_ra(struct slaacd_iface *iface, str struct nd_opt_hdr *nd_opt_hdr = (struct nd_opt_hdr *)p; struct nd_opt_prefix_info *prf; struct nd_opt_rdnss *rdnss; - struct nd_opt_dnssl *dnssl; struct nd_opt_mtu *mtu; struct in6_addr *in6; int i; - char *nssl; len -= sizeof(struct nd_opt_hdr); p += sizeof(struct nd_opt_hdr); @@ -1336,37 +1305,6 @@ parse_ra(struct slaacd_iface *iface, str entries); } break; - case ND_OPT_DNSSL: - if (nd_opt_hdr->nd_opt_len < 2) { - log_warnx("invalid ND_OPT_DNSSL: len < 16"); - goto err; - } - - dnssl = (struct nd_opt_dnssl*) nd_opt_hdr; - - if ((nssl = parse_dnssl(p + 6, - (nd_opt_hdr->nd_opt_len - 1) * 8)) == NULL) - goto err; /* error logging in parse_dnssl */ - - if((ra_dnssl = calloc(1, sizeof(*ra_dnssl))) == NULL) - fatal("calloc"); - - radv->dnssl_lifetime = ntohl( - dnssl->nd_opt_dnssl_lifetime); - if (radv->min_lifetime > radv->dnssl_lifetime) - radv->min_lifetime = radv->dnssl_lifetime; - - if (strlcpy(ra_dnssl->dnssl, nssl, - sizeof(ra_dnssl->dnssl)) >= - sizeof(ra_dnssl->dnssl)) { - log_warnx("dnssl too long"); - goto err; - } - free(nssl); - - LIST_INSERT_HEAD(&radv->dnssls, ra_dnssl, entries); - - break; case ND_OPT_MTU: if (nd_opt_hdr->nd_opt_len != 1) { log_warnx("invalid ND_OPT_MTU: len != 1"); @@ -1382,6 +1320,7 @@ parse_ra(struct slaacd_iface *iface, str } break; + case ND_OPT_DNSSL: case ND_OPT_REDIRECTED_HEADER: case ND_OPT_SOURCE_LINKADDR: case ND_OPT_TARGET_LINKADDR: @@ -1584,10 +1523,8 @@ debug_log_ra(struct imsg_ra *ra) struct nd_opt_mtu *mtu; struct nd_opt_prefix_info *prf; struct nd_opt_rdnss *rdnss; - struct nd_opt_dnssl *dnssl; struct in6_addr *in6; int i; - char *nssl; len -= sizeof(struct nd_opt_hdr); p += sizeof(struct nd_opt_hdr); @@ -1676,24 +1613,6 @@ debug_log_ra(struct imsg_ra *ra) ntopbuf, INET6_ADDRSTRLEN)); } break; - case ND_OPT_DNSSL: - if (nd_opt_hdr->nd_opt_len < 2) { - log_warnx("invalid ND_OPT_DNSSL: len < 16"); - return; - } - dnssl = (struct nd_opt_dnssl*) nd_opt_hdr; - nssl = parse_dnssl(p + 6, (nd_opt_hdr->nd_opt_len - 1) - * 8); - - if (nssl == NULL) - return; - - log_debug("\t\tND_OPT_DNSSL: lifetime: %u", ntohl( - dnssl->nd_opt_dnssl_lifetime)); - log_debug("\t\t\tsearch: %s", nssl); - - free(nssl); - break; default: log_debug("\t\tUNKNOWN: %d", nd_opt_hdr->nd_opt_type); break; @@ -1704,48 +1623,6 @@ debug_log_ra(struct imsg_ra *ra) } } #endif /* SMALL */ - -char* -parse_dnssl(char* data, int datalen) -{ - int len, pos; - char *nssl, *nsslp; - - if((nssl = calloc(1, datalen + 1)) == NULL) { - log_warn("malloc"); - return NULL; - } - nsslp = nssl; - - pos = 0; - - do { - len = data[pos]; - if (len > 63 || len + pos + 1 > datalen) { - free(nssl); - log_warnx("invalid label in DNSSL"); - return NULL; - } - if (len == 0) { - if (pos < datalen && data[pos + 1] != 0) - *nsslp++ = ' '; /* seperator for next domain */ - else - break; - } else { - if (pos != 0 && data[pos - 1] != 0) /* no . at front */ - *nsslp++ = '.'; - memcpy(nsslp, data + pos + 1, len); - nsslp += len; - } - pos += len + 1; - } while(pos < datalen); - if (len != 0) { - free(nssl); - log_warnx("invalid label in DNSSL"); - return NULL; - } - return nssl; -} void update_iface_ra(struct slaacd_iface *iface, struct radv *ra) { Index: sbin/slaacd/frontend.c =================================================================== RCS file: /cvs/src/sbin/slaacd/frontend.c,v retrieving revision 1.55 diff -u -p -r1.55 frontend.c --- sbin/slaacd/frontend.c 21 Mar 2021 18:25:24 -0000 1.55 +++ sbin/slaacd/frontend.c 18 Mar 2022 20:15:08 -0000 @@ -415,7 +415,6 @@ frontend_dispatch_engine(int fd, short e case IMSG_CTL_SHOW_INTERFACE_INFO_RA: case IMSG_CTL_SHOW_INTERFACE_INFO_RA_PREFIX: case IMSG_CTL_SHOW_INTERFACE_INFO_RA_RDNS: - case IMSG_CTL_SHOW_INTERFACE_INFO_RA_DNSSL: case IMSG_CTL_SHOW_INTERFACE_INFO_ADDR_PROPOSALS: case IMSG_CTL_SHOW_INTERFACE_INFO_ADDR_PROPOSAL: case IMSG_CTL_SHOW_INTERFACE_INFO_DFR_PROPOSALS: Index: sbin/slaacd/slaacd.h =================================================================== RCS file: /cvs/src/sbin/slaacd/slaacd.h,v retrieving revision 1.33 diff -u -p -r1.33 slaacd.h --- sbin/slaacd/slaacd.h 21 Mar 2021 18:25:24 -0000 1.33 +++ sbin/slaacd/slaacd.h 18 Mar 2022 20:15:08 -0000 @@ -24,9 +24,6 @@ #define SLAACD_SOIIKEY_LEN 16 -/* MAXDNAME from arpa/namesr.h */ -#define SLAACD_MAX_DNSSL 1025 - #define MAX_RDNS_COUNT 8 /* max nameserver in a RTM_PROPOSAL */ #define IMSG_DATA_SIZE(imsg) ((imsg).hdr.len - IMSG_HEADER_SIZE) @@ -46,7 +43,6 @@ enum imsg_type { IMSG_CTL_SHOW_INTERFACE_INFO_RA, IMSG_CTL_SHOW_INTERFACE_INFO_RA_PREFIX, IMSG_CTL_SHOW_INTERFACE_INFO_RA_RDNS, - IMSG_CTL_SHOW_INTERFACE_INFO_RA_DNSSL, IMSG_CTL_SHOW_INTERFACE_INFO_ADDR_PROPOSALS, IMSG_CTL_SHOW_INTERFACE_INFO_ADDR_PROPOSAL, IMSG_CTL_SHOW_INTERFACE_INFO_DFR_PROPOSALS, @@ -120,11 +116,6 @@ struct ctl_engine_info_ra_prefix { struct ctl_engine_info_ra_rdns { uint32_t lifetime; struct in6_addr rdns; -}; - -struct ctl_engine_info_ra_dnssl { - uint32_t lifetime; - char dnssl[SLAACD_MAX_DNSSL]; }; struct ctl_engine_info_address_proposal { Index: usr.sbin/slaacctl/slaacctl.c =================================================================== RCS file: /cvs/src/usr.sbin/slaacctl/slaacctl.c,v retrieving revision 1.22 diff -u -p -r1.22 slaacctl.c --- usr.sbin/slaacctl/slaacctl.c 21 Mar 2021 18:25:24 -0000 1.22 +++ usr.sbin/slaacctl/slaacctl.c 18 Mar 2022 20:15:08 -0000 @@ -177,7 +177,6 @@ show_interface_msg(struct imsg *imsg) struct ctl_engine_info_ra *cei_ra; struct ctl_engine_info_ra_prefix *cei_ra_prefix; struct ctl_engine_info_ra_rdns *cei_ra_rdns; - struct ctl_engine_info_ra_dnssl *cei_ra_dnssl; struct ctl_engine_info_address_proposal *cei_addr_proposal; struct ctl_engine_info_dfr_proposal *cei_dfr_proposal; struct ctl_engine_info_rdns_proposal *cei_rdns_proposal; @@ -256,11 +255,6 @@ show_interface_msg(struct imsg *imsg) printf("\t\trdns: %s, lifetime: %u\n", inet_ntop(AF_INET6, &cei_ra_rdns->rdns, ntopbuf, INET6_ADDRSTRLEN), cei_ra_rdns->lifetime); - break; - case IMSG_CTL_SHOW_INTERFACE_INFO_RA_DNSSL: - cei_ra_dnssl = imsg->data; - printf("\t\tsearch: %s, lifetime: %u\n", cei_ra_dnssl->dnssl, - cei_ra_dnssl->lifetime); break; case IMSG_CTL_SHOW_INTERFACE_INFO_ADDR_PROPOSALS: printf("\tAddress proposals\n");