* [PATCH 6.12.y] net: bonding: fix use-after-free in bond_xmit_broadcast() @ 2026-04-13 21:34 Chenglong Tang 2026-04-13 21:54 ` Xiang Mei 0 siblings, 1 reply; 6+ messages in thread From: Chenglong Tang @ 2026-04-13 21:34 UTC (permalink / raw) To: stable Cc: kpberry, rnj, joneslee, Chenglong Tang, Weiming Shi, Xiang Mei, Paolo Abeni commit 2884bf72fb8f03409e423397319205de48adca16 upstream. bond_xmit_broadcast() reuses the original skb for the last slave (determined by bond_is_last_slave()) and clones it for others. Concurrent slave enslave/release can mutate the slave list during RCU-protected iteration, changing which slave is "last" mid-loop. This causes the original skb to be double-consumed (double-freed). Replace the racy bond_is_last_slave() check with a simple index comparison (i + 1 == slaves_count) against the pre-snapshot slave count taken via READ_ONCE() before the loop. This preserves the zero-copy optimization for the last slave while making the "last" determination stable against concurrent list mutations. The UAF can trigger the following crash: ================================================================== BUG: KASAN: slab-use-after-free in skb_clone Read of size 8 at addr ffff888100ef8d40 by task exploit/147 CPU: 1 UID: 0 PID: 147 Comm: exploit Not tainted 7.0.0-rc3+ #4 PREEMPTLAZY Call Trace: <TASK> dump_stack_lvl (lib/dump_stack.c:123) print_report (mm/kasan/report.c:379 mm/kasan/report.c:482) kasan_report (mm/kasan/report.c:597) skb_clone (include/linux/skbuff.h:1724 include/linux/skbuff.h:1792 include/linux/skbuff.h:3396 net/core/skbuff.c:2108) bond_xmit_broadcast (drivers/net/bonding/bond_main.c:5334) bond_start_xmit (drivers/net/bonding/bond_main.c:5567 drivers/net/bonding/bond_main.c:5593) dev_hard_start_xmit (include/linux/netdevice.h:5325 include/linux/netdevice.h:5334 net/core/dev.c:3871 net/core/dev.c:3887) __dev_queue_xmit (include/linux/netdevice.h:3601 net/core/dev.c:4838) ip6_finish_output2 (include/net/neighbour.h:540 include/net/neighbour.h:554 net/ipv6/ip6_output.c:136) ip6_finish_output (net/ipv6/ip6_output.c:208 net/ipv6/ip6_output.c:219) ip6_output (net/ipv6/ip6_output.c:250) ip6_send_skb (net/ipv6/ip6_output.c:1985) udp_v6_send_skb (net/ipv6/udp.c:1442) udpv6_sendmsg (net/ipv6/udp.c:1733) __sys_sendto (net/socket.c:730 net/socket.c:742 net/socket.c:2206) __x64_sys_sendto (net/socket.c:2209) do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130) </TASK> Allocated by task 147: Freed by task 147: The buggy address belongs to the object at ffff888100ef8c80 which belongs to the cache skbuff_head_cache of size 224 The buggy address is located 192 bytes inside of freed 224-byte region [ffff888100ef8c80, ffff888100ef8d60) Memory state around the buggy address: ffff888100ef8c00: fb fb fb fb fc fc fc fc fc fc fc fc fc fc fc fc ffff888100ef8c80: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >ffff888100ef8d00: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc ^ ffff888100ef8d80: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb ffff888100ef8e00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ================================================================== Fixes: 4e5bd03ae346 ("net: bonding: fix bond_xmit_broadcast return value error bug") Reported-by: Weiming Shi <bestswngs@gmail.com> Change-Id: I2349f4953b5760b7f4a12da583aa779c19c4b59c Signed-off-by: Xiang Mei <xmei5@asu.edu> Link: https://patch.msgid.link/20260326075553.3960562-1-xmei5@asu.edu Signed-off-by: Paolo Abeni <pabeni@redhat.com> [Kevin Berry <kpberry@google.com>: fixed merge conflicts and adapted to 6.12 struct] Signed-off-by: Chenglong Tang <chenglongtang@google.com> --- drivers/net/bonding/bond_main.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2ac455a9d1bb..fb8d7fec27ee 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -5346,23 +5346,33 @@ static netdev_tx_t bond_3ad_xor_xmit(struct sk_buff *skb, return bond_tx_drop(dev, skb); } -/* in broadcast mode, we send everything to all usable interfaces. */ +/* in broadcast mode, we send everything to all or usable slave interfaces. + * under rcu_read_lock when this function is called. + */ static netdev_tx_t bond_xmit_broadcast(struct sk_buff *skb, - struct net_device *bond_dev) + struct net_device *bond_dev, + bool all_slaves) { struct bonding *bond = netdev_priv(bond_dev); - struct slave *slave = NULL; - struct list_head *iter; + struct bond_up_slave *slaves; bool xmit_suc = false; bool skb_used = false; + int slaves_count, i; - bond_for_each_slave_rcu(bond, slave, iter) { + if (all_slaves) + slaves = rcu_dereference(bond->all_slaves); + else + slaves = rcu_dereference(bond->usable_slaves); + + slaves_count = slaves ? READ_ONCE(slaves->count) : 0; + for (i = 0; i < slaves_count; i++) { + struct slave *slave = slaves->arr[i]; struct sk_buff *skb2; if (!(bond_slave_is_up(slave) && slave->link == BOND_LINK_UP)) continue; - if (bond_is_last_slave(bond, slave)) { + if (i + 1 == slaves_count) { skb2 = skb; skb_used = true; } else { @@ -5597,7 +5607,7 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev case BOND_MODE_XOR: return bond_3ad_xor_xmit(skb, dev); case BOND_MODE_BROADCAST: - return bond_xmit_broadcast(skb, dev); + return bond_xmit_broadcast(skb, dev, true); case BOND_MODE_ALB: return bond_alb_xmit(skb, dev); case BOND_MODE_TLB: -- 2.54.0.rc0.605.g598a273b03-goog ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 6.12.y] net: bonding: fix use-after-free in bond_xmit_broadcast() 2026-04-13 21:34 [PATCH 6.12.y] net: bonding: fix use-after-free in bond_xmit_broadcast() Chenglong Tang @ 2026-04-13 21:54 ` Xiang Mei 2026-04-27 18:42 ` Kevin Berry 0 siblings, 1 reply; 6+ messages in thread From: Xiang Mei @ 2026-04-13 21:54 UTC (permalink / raw) To: Chenglong Tang; +Cc: stable, kpberry, rnj, joneslee, Weiming Shi, Paolo Abeni Hi Chenglong, I’m not entirely clear on how PATCH 6.12.y works and had a question regarding this patch. Could you please clarify the need for the parameter bool all_slaves? As this feature (was introduced in ce7a381697cb) is not introduced in v6.12, I was wondering if it might be sufficient to apply my original patch instead. I’ve also checked against 6.12.81 and didn’t encounter any conflicts. Thanks, Xiang On Mon, Apr 13, 2026 at 2:35 PM Chenglong Tang <chenglongtang@google.com> wrote: > > commit 2884bf72fb8f03409e423397319205de48adca16 upstream. > > bond_xmit_broadcast() reuses the original skb for the last slave > (determined by bond_is_last_slave()) and clones it for others. > Concurrent slave enslave/release can mutate the slave list during > RCU-protected iteration, changing which slave is "last" mid-loop. > This causes the original skb to be double-consumed (double-freed). > > Replace the racy bond_is_last_slave() check with a simple index > comparison (i + 1 == slaves_count) against the pre-snapshot slave > count taken via READ_ONCE() before the loop. This preserves the > zero-copy optimization for the last slave while making the "last" > determination stable against concurrent list mutations. > > The UAF can trigger the following crash: > > ================================================================== > BUG: KASAN: slab-use-after-free in skb_clone > Read of size 8 at addr ffff888100ef8d40 by task exploit/147 > > CPU: 1 UID: 0 PID: 147 Comm: exploit Not tainted 7.0.0-rc3+ #4 PREEMPTLAZY > Call Trace: > <TASK> > dump_stack_lvl (lib/dump_stack.c:123) > print_report (mm/kasan/report.c:379 mm/kasan/report.c:482) > kasan_report (mm/kasan/report.c:597) > skb_clone (include/linux/skbuff.h:1724 include/linux/skbuff.h:1792 include/linux/skbuff.h:3396 net/core/skbuff.c:2108) > bond_xmit_broadcast (drivers/net/bonding/bond_main.c:5334) > bond_start_xmit (drivers/net/bonding/bond_main.c:5567 drivers/net/bonding/bond_main.c:5593) > dev_hard_start_xmit (include/linux/netdevice.h:5325 include/linux/netdevice.h:5334 net/core/dev.c:3871 net/core/dev.c:3887) > __dev_queue_xmit (include/linux/netdevice.h:3601 net/core/dev.c:4838) > ip6_finish_output2 (include/net/neighbour.h:540 include/net/neighbour.h:554 net/ipv6/ip6_output.c:136) > ip6_finish_output (net/ipv6/ip6_output.c:208 net/ipv6/ip6_output.c:219) > ip6_output (net/ipv6/ip6_output.c:250) > ip6_send_skb (net/ipv6/ip6_output.c:1985) > udp_v6_send_skb (net/ipv6/udp.c:1442) > udpv6_sendmsg (net/ipv6/udp.c:1733) > __sys_sendto (net/socket.c:730 net/socket.c:742 net/socket.c:2206) > __x64_sys_sendto (net/socket.c:2209) > do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94) > entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130) > </TASK> > > Allocated by task 147: > > Freed by task 147: > > The buggy address belongs to the object at ffff888100ef8c80 > which belongs to the cache skbuff_head_cache of size 224 > The buggy address is located 192 bytes inside of > freed 224-byte region [ffff888100ef8c80, ffff888100ef8d60) > > Memory state around the buggy address: > ffff888100ef8c00: fb fb fb fb fc fc fc fc fc fc fc fc fc fc fc fc > ffff888100ef8c80: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > >ffff888100ef8d00: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc > ^ > ffff888100ef8d80: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb > ffff888100ef8e00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > ================================================================== > > Fixes: 4e5bd03ae346 ("net: bonding: fix bond_xmit_broadcast return value error bug") > Reported-by: Weiming Shi <bestswngs@gmail.com> > Change-Id: I2349f4953b5760b7f4a12da583aa779c19c4b59c > Signed-off-by: Xiang Mei <xmei5@asu.edu> > Link: https://patch.msgid.link/20260326075553.3960562-1-xmei5@asu.edu > Signed-off-by: Paolo Abeni <pabeni@redhat.com> > [Kevin Berry <kpberry@google.com>: fixed merge conflicts and adapted > to 6.12 struct] > Signed-off-by: Chenglong Tang <chenglongtang@google.com> > --- > drivers/net/bonding/bond_main.c | 24 +++++++++++++++++------- > 1 file changed, 17 insertions(+), 7 deletions(-) > > diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c > index 2ac455a9d1bb..fb8d7fec27ee 100644 > --- a/drivers/net/bonding/bond_main.c > +++ b/drivers/net/bonding/bond_main.c > @@ -5346,23 +5346,33 @@ static netdev_tx_t bond_3ad_xor_xmit(struct sk_buff *skb, > return bond_tx_drop(dev, skb); > } > > -/* in broadcast mode, we send everything to all usable interfaces. */ > +/* in broadcast mode, we send everything to all or usable slave interfaces. > + * under rcu_read_lock when this function is called. > + */ > static netdev_tx_t bond_xmit_broadcast(struct sk_buff *skb, > - struct net_device *bond_dev) > + struct net_device *bond_dev, > + bool all_slaves) > { > struct bonding *bond = netdev_priv(bond_dev); > - struct slave *slave = NULL; > - struct list_head *iter; > + struct bond_up_slave *slaves; > bool xmit_suc = false; > bool skb_used = false; > + int slaves_count, i; > > - bond_for_each_slave_rcu(bond, slave, iter) { > + if (all_slaves) > + slaves = rcu_dereference(bond->all_slaves); > + else > + slaves = rcu_dereference(bond->usable_slaves); > + > + slaves_count = slaves ? READ_ONCE(slaves->count) : 0; > + for (i = 0; i < slaves_count; i++) { > + struct slave *slave = slaves->arr[i]; > struct sk_buff *skb2; > > if (!(bond_slave_is_up(slave) && slave->link == BOND_LINK_UP)) > continue; > > - if (bond_is_last_slave(bond, slave)) { > + if (i + 1 == slaves_count) { > skb2 = skb; > skb_used = true; > } else { > @@ -5597,7 +5607,7 @@ static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev > case BOND_MODE_XOR: > return bond_3ad_xor_xmit(skb, dev); > case BOND_MODE_BROADCAST: > - return bond_xmit_broadcast(skb, dev); > + return bond_xmit_broadcast(skb, dev, true); > case BOND_MODE_ALB: > return bond_alb_xmit(skb, dev); > case BOND_MODE_TLB: > -- > 2.54.0.rc0.605.g598a273b03-goog > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 6.12.y] net: bonding: fix use-after-free in bond_xmit_broadcast() 2026-04-13 21:54 ` Xiang Mei @ 2026-04-27 18:42 ` Kevin Berry 2026-04-27 18:42 ` [PATCH] " Kevin Berry 0 siblings, 1 reply; 6+ messages in thread From: Kevin Berry @ 2026-04-27 18:42 UTC (permalink / raw) To: xmei5; +Cc: bestswngs, chenglongtang, joneslee, kpberry, pabeni, rnj, stable Hi Xiang, > I was wondering if it might be sufficient to apply my original > patch instead. I’ve also checked against 6.12.81 and didn’t encounter > any conflicts. We tried applying your original patch first, but, while it does apply cleanly, it doesn't compile because the version of bond_xmit_broadcast in the 6.12 kernel doesn't have the slaves_count variable introduced in ce7a381697cb. > Could you please clarify the need for the parameter bool all_slaves? We had included the all_slaves parameter to try to reduce the chance of conflicts with any other potential backports from later kernel versions, but I agree that omitting it is probably better. I've sent an amended version of the patch which just adds slaves_count, uses an explicit loop, and applies your original change. Tested the patch by compiling it. Thanks, Kevin ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH] net: bonding: fix use-after-free in bond_xmit_broadcast() 2026-04-27 18:42 ` Kevin Berry @ 2026-04-27 18:42 ` Kevin Berry 2026-04-27 20:07 ` Xiang Mei 0 siblings, 1 reply; 6+ messages in thread From: Kevin Berry @ 2026-04-27 18:42 UTC (permalink / raw) To: xmei5 Cc: bestswngs, chenglongtang, joneslee, kpberry, pabeni, rnj, stable, Sasha Levin From: Xiang Mei <xmei5@asu.edu> [ Upstream commit 2884bf72fb8f03409e423397319205de48adca16 ] bond_xmit_broadcast() reuses the original skb for the last slave (determined by bond_is_last_slave()) and clones it for others. Concurrent slave enslave/release can mutate the slave list during RCU-protected iteration, changing which slave is "last" mid-loop. This causes the original skb to be double-consumed (double-freed). Replace the racy bond_is_last_slave() check with a simple index comparison (i + 1 == slaves_count) against the pre-snapshot slave count taken via READ_ONCE() before the loop. This preserves the zero-copy optimization for the last slave while making the "last" determination stable against concurrent list mutations. The UAF can trigger the following crash: ================================================================== BUG: KASAN: slab-use-after-free in skb_clone Read of size 8 at addr ffff888100ef8d40 by task exploit/147 CPU: 1 UID: 0 PID: 147 Comm: exploit Not tainted 7.0.0-rc3+ #4 PREEMPTLAZY Call Trace: <TASK> dump_stack_lvl (lib/dump_stack.c:123) print_report (mm/kasan/report.c:379 mm/kasan/report.c:482) kasan_report (mm/kasan/report.c:597) skb_clone (include/linux/skbuff.h:1724 include/linux/skbuff.h:1792 include/linux/skbuff.h:3396 net/core/skbuff.c:2108) bond_xmit_broadcast (drivers/net/bonding/bond_main.c:5334) bond_start_xmit (drivers/net/bonding/bond_main.c:5567 drivers/net/bonding/bond_main.c:5593) dev_hard_start_xmit (include/linux/netdevice.h:5325 include/linux/netdevice.h:5334 net/core/dev.c:3871 net/core/dev.c:3887) __dev_queue_xmit (include/linux/netdevice.h:3601 net/core/dev.c:4838) ip6_finish_output2 (include/net/neighbour.h:540 include/net/neighbour.h:554 net/ipv6/ip6_output.c:136) ip6_finish_output (net/ipv6/ip6_output.c:208 net/ipv6/ip6_output.c:219) ip6_output (net/ipv6/ip6_output.c:250) ip6_send_skb (net/ipv6/ip6_output.c:1985) udp_v6_send_skb (net/ipv6/udp.c:1442) udpv6_sendmsg (net/ipv6/udp.c:1733) __sys_sendto (net/socket.c:730 net/socket.c:742 net/socket.c:2206) __x64_sys_sendto (net/socket.c:2209) do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130) </TASK> Allocated by task 147: Freed by task 147: The buggy address belongs to the object at ffff888100ef8c80 which belongs to the cache skbuff_head_cache of size 224 The buggy address is located 192 bytes inside of freed 224-byte region [ffff888100ef8c80, ffff888100ef8d60) Memory state around the buggy address: ffff888100ef8c00: fb fb fb fb fc fc fc fc fc fc fc fc fc fc fc fc ffff888100ef8c80: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb >ffff888100ef8d00: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc ^ ffff888100ef8d80: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb ffff888100ef8e00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ================================================================== Fixes: 4e5bd03ae346 ("net: bonding: fix bond_xmit_broadcast return value error bug") Reported-by: Weiming Shi <bestswngs@gmail.com> Signed-off-by: Xiang Mei <xmei5@asu.edu> Link: https://patch.msgid.link/20260326075553.3960562-1-xmei5@asu.edu Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Kevin Berry <kpberry@google.com> --- drivers/net/bonding/bond_main.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 5035cfa74f1a..20043f1094df 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -5322,18 +5322,22 @@ static netdev_tx_t bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); - struct slave *slave = NULL; - struct list_head *iter; + struct bond_up_slave *slaves; bool xmit_suc = false; bool skb_used = false; + int slaves_count, i; - bond_for_each_slave_rcu(bond, slave, iter) { + slaves = rcu_dereference(bond->all_slaves); + + slaves_count = slaves ? READ_ONCE(slaves->count) : 0; + for (i = 0; i < slaves_count; i++) { + struct slave *slave = slaves->arr[i]; struct sk_buff *skb2; if (!(bond_slave_is_up(slave) && slave->link == BOND_LINK_UP)) continue; - if (bond_is_last_slave(bond, slave)) { + if (i + 1 == slaves_count) { skb2 = skb; skb_used = true; } else { base-commit: eefc95626b5cb02ea6268d1ae58237768004a60d -- 2.54.0.545.g6539524ca2-goog ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] net: bonding: fix use-after-free in bond_xmit_broadcast() 2026-04-27 18:42 ` [PATCH] " Kevin Berry @ 2026-04-27 20:07 ` Xiang Mei 2026-04-27 21:06 ` Kevin Berry 0 siblings, 1 reply; 6+ messages in thread From: Xiang Mei @ 2026-04-27 20:07 UTC (permalink / raw) To: Kevin Berry Cc: bestswngs, chenglongtang, joneslee, pabeni, rnj, stable, Sasha Levin Hi Kevin, Thanks for the explanation. I now understand that we are backporting the patch to 6.12 (I didn't realize it couldn't be backported). I have one concern about your patch. On 6.12, bond->all_slaves is only set by bond_update_slave_arr(), which is gated by bond_mode_can_use_xmit_hash() (i.e., 802.3ad, XOR, TLB, ALB). This does not include BOND_MODE_BROADCAST, and nothing else initializes it. As a result, in bond_xmit_broadcast() on 6.12, rcu_dereference(bond->all_slaves) is NULL, slaves_count is 0, the loop never executes, the skb is freed, and NET_XMIT_DROP is returned, so it drops every packet. This works in mainline because the array-based iteration was introduced alongside additional changes that ensure all_slaves is valid in broadcast mode. Those supporting changes are not present in 6.12. To resolve this, we can either backport the prerequisite series or apply a smaller, self-contained fix like the one below: ``` --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -5326,14 +5326,21 @@ static netdev_tx_t bond_xmit_broadcast(struct sk_buff *skb, struct list_head *iter; bool xmit_suc = false; bool skb_used = false; + int slaves_count, i = 0; + slaves_count = READ_ONCE(bond->slave_cnt); bond_for_each_slave_rcu(bond, slave, iter) { struct sk_buff *skb2; + bool is_last; + + if (++i > slaves_count) + break; + is_last = (i == slaves_count); if (!(bond_slave_is_up(slave) && slave->link == BOND_LINK_UP)) continue; - if (bond_is_last_slave(bond, slave)) { + if (is_last) { skb2 = skb; skb_used = true; } else { ``` Please let me know your thoughts. Thanks, Xiang On Mon, Apr 27, 2026 at 11:42 AM Kevin Berry <kpberry@google.com> wrote: > > From: Xiang Mei <xmei5@asu.edu> > > [ Upstream commit 2884bf72fb8f03409e423397319205de48adca16 ] > > bond_xmit_broadcast() reuses the original skb for the last slave > (determined by bond_is_last_slave()) and clones it for others. > Concurrent slave enslave/release can mutate the slave list during > RCU-protected iteration, changing which slave is "last" mid-loop. > This causes the original skb to be double-consumed (double-freed). > > Replace the racy bond_is_last_slave() check with a simple index > comparison (i + 1 == slaves_count) against the pre-snapshot slave > count taken via READ_ONCE() before the loop. This preserves the > zero-copy optimization for the last slave while making the "last" > determination stable against concurrent list mutations. > > The UAF can trigger the following crash: > > ================================================================== > BUG: KASAN: slab-use-after-free in skb_clone > Read of size 8 at addr ffff888100ef8d40 by task exploit/147 > > CPU: 1 UID: 0 PID: 147 Comm: exploit Not tainted 7.0.0-rc3+ #4 PREEMPTLAZY > Call Trace: > <TASK> > dump_stack_lvl (lib/dump_stack.c:123) > print_report (mm/kasan/report.c:379 mm/kasan/report.c:482) > kasan_report (mm/kasan/report.c:597) > skb_clone (include/linux/skbuff.h:1724 include/linux/skbuff.h:1792 include/linux/skbuff.h:3396 net/core/skbuff.c:2108) > bond_xmit_broadcast (drivers/net/bonding/bond_main.c:5334) > bond_start_xmit (drivers/net/bonding/bond_main.c:5567 drivers/net/bonding/bond_main.c:5593) > dev_hard_start_xmit (include/linux/netdevice.h:5325 include/linux/netdevice.h:5334 net/core/dev.c:3871 net/core/dev.c:3887) > __dev_queue_xmit (include/linux/netdevice.h:3601 net/core/dev.c:4838) > ip6_finish_output2 (include/net/neighbour.h:540 include/net/neighbour.h:554 net/ipv6/ip6_output.c:136) > ip6_finish_output (net/ipv6/ip6_output.c:208 net/ipv6/ip6_output.c:219) > ip6_output (net/ipv6/ip6_output.c:250) > ip6_send_skb (net/ipv6/ip6_output.c:1985) > udp_v6_send_skb (net/ipv6/udp.c:1442) > udpv6_sendmsg (net/ipv6/udp.c:1733) > __sys_sendto (net/socket.c:730 net/socket.c:742 net/socket.c:2206) > __x64_sys_sendto (net/socket.c:2209) > do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94) > entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130) > </TASK> > > Allocated by task 147: > > Freed by task 147: > > The buggy address belongs to the object at ffff888100ef8c80 > which belongs to the cache skbuff_head_cache of size 224 > The buggy address is located 192 bytes inside of > freed 224-byte region [ffff888100ef8c80, ffff888100ef8d60) > > Memory state around the buggy address: > ffff888100ef8c00: fb fb fb fb fc fc fc fc fc fc fc fc fc fc fc fc > ffff888100ef8c80: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > >ffff888100ef8d00: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc > ^ > ffff888100ef8d80: fc fc fc fc fc fc fc fc fa fb fb fb fb fb fb fb > ffff888100ef8e00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > ================================================================== > > Fixes: 4e5bd03ae346 ("net: bonding: fix bond_xmit_broadcast return value error bug") > Reported-by: Weiming Shi <bestswngs@gmail.com> > Signed-off-by: Xiang Mei <xmei5@asu.edu> > Link: https://patch.msgid.link/20260326075553.3960562-1-xmei5@asu.edu > Signed-off-by: Paolo Abeni <pabeni@redhat.com> > Signed-off-by: Sasha Levin <sashal@kernel.org> > Signed-off-by: Kevin Berry <kpberry@google.com> > --- > drivers/net/bonding/bond_main.c | 12 ++++++++---- > 1 file changed, 8 insertions(+), 4 deletions(-) > > diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c > index 5035cfa74f1a..20043f1094df 100644 > --- a/drivers/net/bonding/bond_main.c > +++ b/drivers/net/bonding/bond_main.c > @@ -5322,18 +5322,22 @@ static netdev_tx_t bond_xmit_broadcast(struct sk_buff *skb, > struct net_device *bond_dev) > { > struct bonding *bond = netdev_priv(bond_dev); > - struct slave *slave = NULL; > - struct list_head *iter; > + struct bond_up_slave *slaves; > bool xmit_suc = false; > bool skb_used = false; > + int slaves_count, i; > > - bond_for_each_slave_rcu(bond, slave, iter) { > + slaves = rcu_dereference(bond->all_slaves); > + > + slaves_count = slaves ? READ_ONCE(slaves->count) : 0; > + for (i = 0; i < slaves_count; i++) { > + struct slave *slave = slaves->arr[i]; > struct sk_buff *skb2; > > if (!(bond_slave_is_up(slave) && slave->link == BOND_LINK_UP)) > continue; > > - if (bond_is_last_slave(bond, slave)) { > + if (i + 1 == slaves_count) { > skb2 = skb; > skb_used = true; > } else { > > base-commit: eefc95626b5cb02ea6268d1ae58237768004a60d > -- > 2.54.0.545.g6539524ca2-goog > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] net: bonding: fix use-after-free in bond_xmit_broadcast() 2026-04-27 20:07 ` Xiang Mei @ 2026-04-27 21:06 ` Kevin Berry 0 siblings, 0 replies; 6+ messages in thread From: Kevin Berry @ 2026-04-27 21:06 UTC (permalink / raw) To: Xiang Mei Cc: bestswngs, chenglongtang, joneslee, pabeni, rnj, stable, Sasha Levin Hi Xiang, Thanks for the explanation! I was worried that bond->all_slaves might have been uninitialized, thanks for confirming that. Your patch looks good to me, minus the formatting. Thanks, Kevin ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-04-27 21:06 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-04-13 21:34 [PATCH 6.12.y] net: bonding: fix use-after-free in bond_xmit_broadcast() Chenglong Tang 2026-04-13 21:54 ` Xiang Mei 2026-04-27 18:42 ` Kevin Berry 2026-04-27 18:42 ` [PATCH] " Kevin Berry 2026-04-27 20:07 ` Xiang Mei 2026-04-27 21:06 ` Kevin Berry
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox