Skip to content

Commit f67caec

Browse files
nealcardwelldavem330
authored andcommitted
inet_diag: avoid unsafe and nonsensical prefix matches in inet_diag_bc_run()
Add logic to check the address family of the user-supplied conditional and the address family of the connection entry. We now do not do prefix matching of addresses from different address families (AF_INET vs AF_INET6), except for the previously existing support for having an IPv4 prefix match an IPv4-mapped IPv6 address (which this commit maintains as-is). This change is needed for two reasons: (1) The addresses are different lengths, so comparing a 128-bit IPv6 prefix match condition to a 32-bit IPv4 connection address can cause us to unwittingly walk off the end of the IPv4 address and read garbage or oops. (2) The IPv4 and IPv6 address spaces are semantically distinct, so a simple bit-wise comparison of the prefixes is not meaningful, and would lead to bogus results (except for the IPv4-mapped IPv6 case, which this commit maintains). Signed-off-by: Neal Cardwell <ncardwell@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 405c005 commit f67caec

File tree

1 file changed

+17
-11
lines changed

1 file changed

+17
-11
lines changed

net/ipv4/inet_diag.c

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -432,25 +432,31 @@ static int inet_diag_bc_run(const struct nlattr *_bc,
432432
break;
433433
}
434434

435-
if (cond->prefix_len == 0)
436-
break;
437-
438435
if (op->code == INET_DIAG_BC_S_COND)
439436
addr = entry->saddr;
440437
else
441438
addr = entry->daddr;
442439

440+
if (cond->family != AF_UNSPEC &&
441+
cond->family != entry->family) {
442+
if (entry->family == AF_INET6 &&
443+
cond->family == AF_INET) {
444+
if (addr[0] == 0 && addr[1] == 0 &&
445+
addr[2] == htonl(0xffff) &&
446+
bitstring_match(addr + 3,
447+
cond->addr,
448+
cond->prefix_len))
449+
break;
450+
}
451+
yes = 0;
452+
break;
453+
}
454+
455+
if (cond->prefix_len == 0)
456+
break;
443457
if (bitstring_match(addr, cond->addr,
444458
cond->prefix_len))
445459
break;
446-
if (entry->family == AF_INET6 &&
447-
cond->family == AF_INET) {
448-
if (addr[0] == 0 && addr[1] == 0 &&
449-
addr[2] == htonl(0xffff) &&
450-
bitstring_match(addr + 3, cond->addr,
451-
cond->prefix_len))
452-
break;
453-
}
454460
yes = 0;
455461
break;
456462
}

0 commit comments

Comments
 (0)