case ND_OPT_RDNSS_INFORMATION:
rdnssinfo = (struct nd_opt_rdnss_info_local *) opt_str;
count = rdnssinfo->nd_opt_rdnssi_len;
/* Check the RNDSS addresses received */
switch (count) {
case 7:
Now opt_str is the options part of the packet. Does the code check that the packet is big enough to account for these options? No. There are a bunch of cases like this. All lead to out of bounds memory access.
Lets look at the current radvd source from a recent Linux distro
case ND_OPT_RDNSS_INFORMATION: {
char rdnss_str[INET6_ADDRSTRLEN];
struct AdvRDNSS *rdnss = 0;
struct nd_opt_rdnss_info_local *rdnssinfo = (struct nd_opt_rdnss_info_local *)opt_str;
if (len < sizeof(*rdnssinfo))
return;
int count = rdnssinfo->nd_opt_rdnssi_len;
/* Check the RNDSS addresses received */
switch (count) {
case 7:
It's clearly been fixed. But the patches haven't been backported to the router firmware.