On Thu, Feb 26, 2026 at 5:59 AM Eelco Chaudron via dev <
[email protected]> wrote:

> Coverity reports a tainted scalar issue (CID 278405) in the
> packet_set_nd() function. The function processes IPv6 Neighbor
> Discovery options from untrusted packet data without properly
> validating the option length field before using it.
>
> The current code:
>     while (bytes_remain >= ND_LLA_OPT_LEN && opt->len != 0) {
>         ...
>         opt += opt->len;
>         bytes_remain -= opt->len * ND_LLA_OPT_LEN;
>     }
>
> This only checks that at least 8 bytes remain, but doesn't validate
> that the full option (opt->len * ND_LLA_OPT_LEN bytes) fits within
> the remaining buffer. A maliciously crafted packet with an oversized
> opt->len value can cause:
> 1. Pointer advancement beyond packet bounds (opt += opt->len)
> 2. Integer underflow in bytes_remain calculation
> 3. Potential out-of-bounds memory access or infinite loop
>
> Fix this by strengthening the loop condition to validate that the
> full option length fits within bytes_remain before processing it:
>     while (opt->len != 0 && bytes_remain >= (opt->len * ND_LLA_OPT_LEN))
>
> This ensures both the pointer arithmetic and the bytes_remain
> subtraction are always safe.
>
> Fixes: e60e935b1f37 ("Implement set-field for IPv6 ND fields (nd_target,
> nd_sll, and nd_tll).")
> Signed-off-by: Eelco Chaudron <[email protected]>
> ---
>  lib/packets.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/lib/packets.c b/lib/packets.c
> index 67e2de4be..654f4ee07 100644
> --- a/lib/packets.c
> +++ b/lib/packets.c
> @@ -1609,7 +1609,7 @@ packet_set_nd(struct dp_packet *packet, const struct
> in6_addr *target,
>                               true);
>      }
>
> -    while (bytes_remain >= ND_LLA_OPT_LEN && opt->len != 0) {
> +    while (opt->len != 0 && bytes_remain >= (opt->len * ND_LLA_OPT_LEN)) {
>

Wouldn't this result in an out of bounds read of opt, which might be beyond
the end of packet? I'd think it should be something like:

while (bytes_remain > ND_LLA_OPT_LEN && opt->len != 0 && bytes_remain >=
(opt->len * ND_LLA_OPT_LEN)) {

Cheers,
M


>          if (opt->type == ND_OPT_SOURCE_LINKADDR && opt->len == 1) {
>              if (!eth_addr_equals(opt->mac, sll)) {
>                  ovs_be16 *csum = &(ns->icmph.icmp6_cksum);
> --
> 2.52.0
>
> _______________________________________________
> dev mailing list
> [email protected]
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to