diff options
| author | Hauke Mehrtens | 2026-05-23 12:18:34 +0000 |
|---|---|---|
| committer | Hauke Mehrtens | 2026-06-18 00:35:03 +0000 |
| commit | 41b476dffce6eda24e0cb0909c8b3688e56810f5 (patch) | |
| tree | 28eb8c09546f458a3fd2078d29e107471946bebe | |
| parent | 6644b4623bc82c8380a9487eaa9eb19dfdf1c4dc (diff) | |
| download | odhcpd-41b476dffce6eda24e0cb0909c8b3688e56810f5.tar.gz | |
netlink: avoid 32-bit-wide shift when computing /0 IPv4 netmask
cb_addr_valid() computes the netmask as ~((1U << (32 - prefixlen)) - 1).
For a /0 IPv4 prefix the shift count is 32 — equal to the width of the
shifted type — which is undefined behaviour in C. The kernel does
deliver /0 addresses (e.g. on default-route-only interfaces), so this
is reachable.
Do the shift in uint64_t and truncate so /0 cleanly produces a zero
netmask, matching what the rest of the code already expects.
Assisted-by: Claude:claude-opus-4-7
Link: https://github.com/openwrt/odhcpd/pull/401
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
(cherry picked from commit a212daeace2733858fcd42d785aa719ecd0cd3cd)
| -rw-r--r-- | src/netlink.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/src/netlink.c b/src/netlink.c index 2473476..8fd3872 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -587,8 +587,14 @@ static int cb_addr_valid(struct nl_msg *msg, void *arg) memset(&oaddrs[ctxt->ret], 0, sizeof(oaddrs[ctxt->ret])); oaddrs[ctxt->ret].prefix_len = ifa->ifa_prefixlen; - if (ifa->ifa_family == AF_INET) - oaddrs[ctxt->ret].netmask = htonl(~((1U << (32 - ifa->ifa_prefixlen)) - 1)); + if (ifa->ifa_family == AF_INET) { + /* ifa_prefixlen is 0..32. A /0 prefix turns "32 - prefix" into a + * 32-bit shift on a 32-bit type, which is undefined behaviour; + * compute the host mask in 64-bit and truncate so /0 yields a + * zero netmask as expected. */ + uint32_t host_bits = (uint32_t)((1ULL << (32 - ifa->ifa_prefixlen)) - 1); + oaddrs[ctxt->ret].netmask = htonl(~host_bits); + } nla_memcpy(&oaddrs[ctxt->ret].addr, nla_addr, sizeof(oaddrs[ctxt->ret].addr)); |