From: Jiayuan Chen xdp_master_redirect() dereferences the master device pointer and calls ndo_xdp_get_xmit_slave() without checking whether the master is valid or running. When a bond device in round-robin mode has never been brought up, bond->rr_tx_counter is not allocated (only allocated in bond_open()). The XDP redirect path can still reach bond_rr_gen_slave_id() via xdp_master_redirect() → bond_xdp_get_xmit_slave() → bond_xdp_xmit_roundrobin_slave_get(), causing a null-ptr-deref on rr_tx_counter. bpf_master_redirect_enabled_key is a global static key. When any bond device has native XDP attached, this key is enabled system-wide, causing the XDP_TX → xdp_master_redirect interception to fire for all bond slaves, even slaves of other bond devices that have never been opened. To trigger, the following conditions must be met: 1. A bond (bond0) with native XDP attached, enabling the global key 2. Another bond (bond1) in round-robin mode, never brought up 3. A slave (veth1) of bond1 with generic XDP returning XDP_TX 4. Packets hitting the generic XDP path on veth1 Add a check in xdp_master_redirect() to verify the master device is valid and running before proceeding with the redirect. This is semantically correct because redirecting to a non-running master is meaningless, and safe from a concurrency perspective because xdp_master_redirect() runs under RCU protection and the master's resources are not freed until after an RCU grace period. Fixes: 879af96ffd72 ("net, core: Add support for XDP redirection to slave device") Reported-by: syzbot+80e046b8da2820b6ba73@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/698f84c6.a70a0220.2c38d7.00cc.GAE@google.com/T/ Signed-off-by: Jiayuan Chen --- net/core/filter.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/core/filter.c b/net/core/filter.c index ba019ded773d..9a45dabd0044 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -4387,6 +4387,9 @@ u32 xdp_master_redirect(struct xdp_buff *xdp) struct net_device *master, *slave; master = netdev_master_upper_dev_get_rcu(xdp->rxq->dev); + if (unlikely(!master || !netif_running(master))) + return XDP_TX; + slave = master->netdev_ops->ndo_xdp_get_xmit_slave(master, xdp); if (slave && slave != xdp->rxq->dev) { /* The target device is different from the receiving device, so -- 2.43.0