Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

bpf: Fix stack-out-of-bounds write in devmap

get_upper_ifindexes() iterates over all upper devices and writes their
indices into an array without checking bounds.

Also the callers assume that the max number of upper devices is
MAX_NEST_DEV and allocate excluded_devices[1+MAX_NEST_DEV] on the stack,
but that assumption is not correct and the number of upper devices could
be larger than MAX_NEST_DEV (e.g., many macvlans), causing a
stack-out-of-bounds write.

Add a max parameter to get_upper_ifindexes() to avoid the issue.
When there are too many upper devices, return -EOVERFLOW and abort the
redirect.

To reproduce, create more than MAX_NEST_DEV(8) macvlans on a device with
an XDP program attached using BPF_F_BROADCAST | BPF_F_EXCLUDE_INGRESS.
Then send a packet to the device to trigger the XDP redirect path.

Reported-by: syzbot+10cc7f13760b31bd2e61@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/698c4ce3.050a0220.340abe.000b.GAE@google.com/T/
Fixes: aeea1b86f936 ("bpf, devmap: Exclude XDP broadcast to master device")
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Signed-off-by: Kohei Enju <kohei@enjuk.jp>
Link: https://lore.kernel.org/r/20260225053506.4738-1-kohei@enjuk.jp
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Kohei Enju and committed by
Alexei Starovoitov
b7bf516c ad6fface

+17 -5
+17 -5
kernel/bpf/devmap.c
··· 588 588 } 589 589 590 590 /* Get ifindex of each upper device. 'indexes' must be able to hold at 591 - * least MAX_NEST_DEV elements. 592 - * Returns the number of ifindexes added. 591 + * least 'max' elements. 592 + * Returns the number of ifindexes added, or -EOVERFLOW if there are too 593 + * many upper devices. 593 594 */ 594 - static int get_upper_ifindexes(struct net_device *dev, int *indexes) 595 + static int get_upper_ifindexes(struct net_device *dev, int *indexes, int max) 595 596 { 596 597 struct net_device *upper; 597 598 struct list_head *iter; 598 599 int n = 0; 599 600 600 601 netdev_for_each_upper_dev_rcu(dev, upper, iter) { 602 + if (n >= max) 603 + return -EOVERFLOW; 601 604 indexes[n++] = upper->ifindex; 602 605 } 606 + 603 607 return n; 604 608 } 605 609 ··· 619 615 int err; 620 616 621 617 if (exclude_ingress) { 622 - num_excluded = get_upper_ifindexes(dev_rx, excluded_devices); 618 + num_excluded = get_upper_ifindexes(dev_rx, excluded_devices, 619 + ARRAY_SIZE(excluded_devices) - 1); 620 + if (num_excluded < 0) 621 + return num_excluded; 622 + 623 623 excluded_devices[num_excluded++] = dev_rx->ifindex; 624 624 } 625 625 ··· 741 733 int err; 742 734 743 735 if (exclude_ingress) { 744 - num_excluded = get_upper_ifindexes(dev, excluded_devices); 736 + num_excluded = get_upper_ifindexes(dev, excluded_devices, 737 + ARRAY_SIZE(excluded_devices) - 1); 738 + if (num_excluded < 0) 739 + return num_excluded; 740 + 745 741 excluded_devices[num_excluded++] = dev->ifindex; 746 742 } 747 743