* [PATCH 6.12.y] net: bonding: fix use-after-free in bond_xmit_broadcast()
@ 2026-04-10 21:09 Chenglong Tang
2026-04-13 11:51 ` Greg KH
0 siblings, 1 reply; 4+ messages in thread
From: Chenglong Tang @ 2026-04-10 21:09 UTC (permalink / raw)
To: stable; +Cc: xmei5, pabeni, gregkh, sashal, Kevin Berry, Lee Jones
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>
Signed-off-by: Xiang Mei <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>
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:
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 6.12.y] net: bonding: fix use-after-free in bond_xmit_broadcast()
2026-04-10 21:09 [PATCH 6.12.y] net: bonding: fix use-after-free in bond_xmit_broadcast() Chenglong Tang
@ 2026-04-13 11:51 ` Greg KH
0 siblings, 0 replies; 4+ messages in thread
From: Greg KH @ 2026-04-13 11:51 UTC (permalink / raw)
To: Chenglong Tang; +Cc: stable, xmei5, pabeni, sashal, Kevin Berry, Lee Jones
On Fri, Apr 10, 2026 at 02:09:42PM -0700, Chenglong Tang 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>
> Signed-off-by: Xiang Mei <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>
>
> 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.
> + */
This is totally corrupted and can not be applied :(
^ permalink raw reply [flat|nested] 4+ messages in thread
* [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; 4+ 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] 4+ messages in thread
* Re: [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, 0 replies; 4+ 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] 4+ messages in thread
end of thread, other threads:[~2026-04-13 21:54 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-10 21:09 [PATCH 6.12.y] net: bonding: fix use-after-free in bond_xmit_broadcast() Chenglong Tang
2026-04-13 11:51 ` Greg KH
-- strict thread matches above, loose matches on Subject: below --
2026-04-13 21:34 Chenglong Tang
2026-04-13 21:54 ` Xiang Mei
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox