public inbox for netdev@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH net v1 0/2] bonding: fix missing XDP compat check on xmit_hash_policy change
@ 2026-02-26  8:03 Jiayuan Chen
  2026-02-26  8:03 ` [PATCH net v1 1/2] bpf/bonding: reject vlan+srcmac xmit_hash_policy change when XDP is loaded Jiayuan Chen
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Jiayuan Chen @ 2026-02-26  8:03 UTC (permalink / raw)
  To: netdev
  Cc: jiayuan.chen, jiayuan.chen, Jay Vosburgh, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Andrii Nakryiko, Eduard Zingerman, Martin KaFai Lau, Song Liu,
	Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Shuah Khan,
	Jonathan Toppins, Jussi Maki, linux-kernel, bpf, linux-kselftest

syzkaller reported a bug https://syzkaller.appspot.com/bug?extid=5a287bcdc08104bc3132

When a bond device is in 802.3ad or balance-xor mode, XDP is supported
only when xmit_hash_policy != vlan+srcmac.  This constraint is enforced
in bond_option_mode_set() via bond_xdp_check(), which prevents switching
to an XDP-incompatible mode while a program is loaded.  However, the
symmetric path -- changing xmit_hash_policy while XDP is loaded -- had
no such guard in bond_option_xmit_hash_policy_set().

This means the following sequence silently creates an inconsistent state:

  1. Create a bond in 802.3ad mode with xmit_hash_policy=layer2+3.
  2. Attach a native XDP program to the bond.
  3. Change xmit_hash_policy to vlan+srcmac (no error, not checked).

Now bond->xdp_prog is set but bond_xdp_check() returns false for the
same device.  When the bond is later torn down (e.g. netns deletion),
dev_xdp_uninstall() calls bond_xdp_set(dev, NULL) to remove the
program, which hits the bond_xdp_check() guard and returns -EOPNOTSUPP,
triggering a kernel WARNING:

  bond1 (unregistering): Error: No native XDP support for the current bonding mode
  ------------[ cut here ]------------
  dev_xdp_install(dev, mode, bpf_op, NULL, 0, NULL)
  WARNING: net/core/dev.c:10361 at dev_xdp_uninstall net/core/dev.c:10361 [inline], CPU#0: kworker/u8:22/11031
  Modules linked in:
  CPU: 0 UID: 0 PID: 11031 Comm: kworker/u8:22 Not tainted syzkaller #0 PREEMPT(full)
  Workqueue: netns cleanup_net
  RIP: 0010:dev_xdp_uninstall net/core/dev.c:10361 [inline]
  RIP: 0010:unregister_netdevice_many_notify+0x1efd/0x2370 net/core/dev.c:12393
  RSP: 0018:ffffc90003b2f7c0 EFLAGS: 00010293
  RAX: ffffffff8971e99c RBX: ffff888052f84c40 RCX: ffff88807896bc80
  RDX: 0000000000000000 RSI: 00000000ffffffa1 RDI: 0000000000000000
  RBP: ffffc90003b2f930 R08: ffffc90003b2f207 R09: 1ffff92000765e40
  R10: dffffc0000000000 R11: fffff52000765e41 R12: 00000000ffffffa1
  R13: ffff888052f84c38 R14: 1ffff1100a5f0988 R15: ffffc9000df67000
  FS:  0000000000000000(0000) GS:ffff8881254ae000(0000) knlGS:0000000000000000
  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
  CR2: 00007f60871d5d58 CR3: 000000006c41c000 CR4: 00000000003526f0
  Call Trace:
   <TASK>
   ops_exit_rtnl_list net/core/net_namespace.c:187 [inline]
   ops_undo_list+0x3d3/0x940 net/core/net_namespace.c:248
   cleanup_net+0x56b/0x800 net/core/net_namespace.c:704
   process_one_work kernel/workqueue.c:3275 [inline]
   process_scheduled_works+0xaec/0x17a0 kernel/workqueue.c:3358
   worker_thread+0xa50/0xfc0 kernel/workqueue.c:3439
   kthread+0x388/0x470 kernel/kthread.c:467
   ret_from_fork+0x51e/0xb90 arch/x86/kernel/process.c:158
   ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
   </TASK>

Beyond the WARNING itself, when dev_xdp_install() fails during
dev_xdp_uninstall(), bond_xdp_set() returns early without calling
bpf_prog_put() on the old program.  dev_xdp_uninstall() then releases
only the reference held by dev->xdp_state[], while the reference held
by bond->xdp_prog is never dropped, leaking the struct bpf_prog.

The fix refactors the core logic of bond_xdp_check() into a new helper
__bond_xdp_check_mode(mode, xmit_policy) that takes both parameters
explicitly, avoiding the need to read them from the bond struct.
bond_xdp_check() becomes a thin wrapper around it.
bond_option_xmit_hash_policy_set() then uses __bond_xdp_check_mode()
directly, passing the candidate xmit_policy before it is committed,
mirroring exactly what bond_option_mode_set() already does for mode
changes.

Patch 1 adds the kernel fix.
Patch 2 adds a selftest that reproduces the WARNING by attaching native
XDP to a bond in 802.3ad mode, then attempting to change xmit_hash_policy
to vlan+srcmac -- verifying the change is rejected with the fix applied.

Jiayuan Chen (2):
  bpf/bonding: reject vlan+srcmac xmit_hash_policy change when XDP is
    loaded
  selftests/bpf: add test for xdp_bonding xmit_hash_policy compat

 drivers/net/bonding/bond_main.c               |  9 ++-
 drivers/net/bonding/bond_options.c            |  2 +
 include/net/bonding.h                         |  1 +
 .../selftests/bpf/prog_tests/xdp_bonding.c    | 58 +++++++++++++++++++
 4 files changed, 68 insertions(+), 2 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH net v1 1/2] bpf/bonding: reject vlan+srcmac xmit_hash_policy change when XDP is loaded
  2026-02-26  8:03 [PATCH net v1 0/2] bonding: fix missing XDP compat check on xmit_hash_policy change Jiayuan Chen
@ 2026-02-26  8:03 ` Jiayuan Chen
  2026-02-26  8:03 ` [PATCH net v1 2/2] selftests/bpf: add test for xdp_bonding xmit_hash_policy compat Jiayuan Chen
  2026-03-03 10:00 ` [PATCH net v1 0/2] bonding: fix missing XDP compat check on xmit_hash_policy change patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: Jiayuan Chen @ 2026-02-26  8:03 UTC (permalink / raw)
  To: netdev
  Cc: jiayuan.chen, jiayuan.chen, syzbot+5a287bcdc08104bc3132,
	Jay Vosburgh, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, Alexei Starovoitov,
	Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend,
	Stanislav Fomichev, Andrii Nakryiko, Eduard Zingerman,
	Martin KaFai Lau, Song Liu, Yonghong Song, KP Singh, Hao Luo,
	Jiri Olsa, Shuah Khan, Jussi Maki, Jonathan Toppins, linux-kernel,
	bpf, linux-kselftest

From: Jiayuan Chen <jiayuan.chen@shopee.com>

bond_option_mode_set() already rejects mode changes that would make a
loaded XDP program incompatible via bond_xdp_check().  However,
bond_option_xmit_hash_policy_set() has no such guard.

For 802.3ad and balance-xor modes, bond_xdp_check() returns false when
xmit_hash_policy is vlan+srcmac, because the 802.1q payload is usually
absent due to hardware offload.  This means a user can:

1. Attach a native XDP program to a bond in 802.3ad/balance-xor mode
   with a compatible xmit_hash_policy (e.g. layer2+3).
2. Change xmit_hash_policy to vlan+srcmac while XDP remains loaded.

This leaves bond->xdp_prog set but bond_xdp_check() now returning false
for the same device.  When the bond is later destroyed, dev_xdp_uninstall()
calls bond_xdp_set(dev, NULL, NULL) to remove the program, which hits
the bond_xdp_check() guard and returns -EOPNOTSUPP, triggering:

WARN_ON(dev_xdp_install(dev, mode, bpf_op, NULL, 0, NULL))

Fix this by rejecting xmit_hash_policy changes to vlan+srcmac when an
XDP program is loaded on a bond in 802.3ad or balance-xor mode.

commit 39a0876d595b ("net, bonding: Disallow vlan+srcmac with XDP")
introduced bond_xdp_check() which returns false for 802.3ad/balance-xor
modes when xmit_hash_policy is vlan+srcmac.  The check was wired into
bond_xdp_set() to reject XDP attachment with an incompatible policy, but
the symmetric path -- preventing xmit_hash_policy from being changed to an
incompatible value after XDP is already loaded -- was left unguarded in
bond_option_xmit_hash_policy_set().

Note:
commit 094ee6017ea0 ("bonding: check xdp prog when set bond mode")
later added a similar guard to bond_option_mode_set(), but
bond_option_xmit_hash_policy_set() remained unprotected.

Reported-by: syzbot+5a287bcdc08104bc3132@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/6995aff6.050a0220.2eeac1.014e.GAE@google.com/T/
Fixes: 39a0876d595b ("net, bonding: Disallow vlan+srcmac with XDP")
Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
---
 drivers/net/bonding/bond_main.c    | 9 +++++++--
 drivers/net/bonding/bond_options.c | 2 ++
 include/net/bonding.h              | 1 +
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 78cff904cdc3..2854cdfa4af9 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -324,7 +324,7 @@ static bool bond_sk_check(struct bonding *bond)
 	}
 }
 
-bool bond_xdp_check(struct bonding *bond, int mode)
+bool __bond_xdp_check(int mode, int xmit_policy)
 {
 	switch (mode) {
 	case BOND_MODE_ROUNDROBIN:
@@ -335,7 +335,7 @@ bool bond_xdp_check(struct bonding *bond, int mode)
 		/* vlan+srcmac is not supported with XDP as in most cases the 802.1q
 		 * payload is not in the packet due to hardware offload.
 		 */
-		if (bond->params.xmit_policy != BOND_XMIT_POLICY_VLAN_SRCMAC)
+		if (xmit_policy != BOND_XMIT_POLICY_VLAN_SRCMAC)
 			return true;
 		fallthrough;
 	default:
@@ -343,6 +343,11 @@ bool bond_xdp_check(struct bonding *bond, int mode)
 	}
 }
 
+bool bond_xdp_check(struct bonding *bond, int mode)
+{
+	return __bond_xdp_check(mode, bond->params.xmit_policy);
+}
+
 /*---------------------------------- VLAN -----------------------------------*/
 
 /* In the following 2 functions, bond_vlan_rx_add_vid and bond_vlan_rx_kill_vid,
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index f1c6e9d8f616..adc216df4345 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -1574,6 +1574,8 @@ static int bond_option_fail_over_mac_set(struct bonding *bond,
 static int bond_option_xmit_hash_policy_set(struct bonding *bond,
 					    const struct bond_opt_value *newval)
 {
+	if (bond->xdp_prog && !__bond_xdp_check(BOND_MODE(bond), newval->value))
+		return -EOPNOTSUPP;
 	netdev_dbg(bond->dev, "Setting xmit hash policy to %s (%llu)\n",
 		   newval->string, newval->value);
 	bond->params.xmit_policy = newval->value;
diff --git a/include/net/bonding.h b/include/net/bonding.h
index 4ad5521e7731..395c6e281c5f 100644
--- a/include/net/bonding.h
+++ b/include/net/bonding.h
@@ -699,6 +699,7 @@ void bond_debug_register(struct bonding *bond);
 void bond_debug_unregister(struct bonding *bond);
 void bond_debug_reregister(struct bonding *bond);
 const char *bond_mode_name(int mode);
+bool __bond_xdp_check(int mode, int xmit_policy);
 bool bond_xdp_check(struct bonding *bond, int mode);
 void bond_setup(struct net_device *bond_dev);
 unsigned int bond_get_num_tx_queues(void);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH net v1 2/2] selftests/bpf: add test for xdp_bonding xmit_hash_policy compat
  2026-02-26  8:03 [PATCH net v1 0/2] bonding: fix missing XDP compat check on xmit_hash_policy change Jiayuan Chen
  2026-02-26  8:03 ` [PATCH net v1 1/2] bpf/bonding: reject vlan+srcmac xmit_hash_policy change when XDP is loaded Jiayuan Chen
@ 2026-02-26  8:03 ` Jiayuan Chen
  2026-03-03 10:00 ` [PATCH net v1 0/2] bonding: fix missing XDP compat check on xmit_hash_policy change patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: Jiayuan Chen @ 2026-02-26  8:03 UTC (permalink / raw)
  To: netdev
  Cc: jiayuan.chen, jiayuan.chen, Jay Vosburgh, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
	Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, Shuah Khan,
	Jussi Maki, Jonathan Toppins, linux-kernel, bpf, linux-kselftest

From: Jiayuan Chen <jiayuan.chen@shopee.com>

Add a selftest to verify that changing xmit_hash_policy to vlan+srcmac
is rejected when a native XDP program is loaded on a bond in 802.3ad
mode.  Without the fix in bond_option_xmit_hash_policy_set(), the change
succeeds silently, creating an inconsistent state that triggers a kernel
WARNING in dev_xdp_uninstall() when the bond is torn down.

The test attaches native XDP to a bond0 (802.3ad, layer2+3), then
attempts to switch xmit_hash_policy to vlan+srcmac and asserts the
operation fails.  It also verifies the change succeeds after XDP is
detached, confirming the rejection is specific to the XDP-loaded state.

Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
---
 .../selftests/bpf/prog_tests/xdp_bonding.c    | 58 +++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_bonding.c b/tools/testing/selftests/bpf/prog_tests/xdp_bonding.c
index a5b15e464018..0d4ec1e5b401 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_bonding.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_bonding.c
@@ -704,6 +704,61 @@ static void test_xdp_bonding_features(struct skeletons *skeletons)
 	system("ip link del bond");
 }
 
+/*
+ * Test that changing xmit_hash_policy to vlan+srcmac is rejected when a
+ * native XDP program is loaded on a bond in 802.3ad or balance-xor mode.
+ * These modes support XDP only when xmit_hash_policy != vlan+srcmac; freely
+ * changing the policy creates an inconsistency that triggers a WARNING in
+ * dev_xdp_uninstall() during device teardown.
+ */
+static void test_xdp_bonding_xmit_policy_compat(struct skeletons *skeletons)
+{
+	struct nstoken *nstoken = NULL;
+	int bond_ifindex = -1;
+	int xdp_fd, err;
+
+	SYS(out, "ip netns add ns_xmit_policy");
+	nstoken = open_netns("ns_xmit_policy");
+	if (!ASSERT_OK_PTR(nstoken, "open ns_xmit_policy"))
+		goto out;
+
+	/* 802.3ad with layer2+3 policy: native XDP is supported */
+	SYS(out, "ip link add bond0 type bond mode 802.3ad xmit_hash_policy layer2+3");
+	SYS(out, "ip link add veth0 type veth peer name veth0p");
+	SYS(out, "ip link set veth0 master bond0");
+	SYS(out, "ip link set bond0 up");
+
+	bond_ifindex = if_nametoindex("bond0");
+	if (!ASSERT_GT(bond_ifindex, 0, "bond0 ifindex"))
+		goto out;
+
+	xdp_fd = bpf_program__fd(skeletons->xdp_dummy->progs.xdp_dummy_prog);
+	if (!ASSERT_GE(xdp_fd, 0, "xdp_dummy fd"))
+		goto out;
+
+	err = bpf_xdp_attach(bond_ifindex, xdp_fd, XDP_FLAGS_DRV_MODE, NULL);
+	if (!ASSERT_OK(err, "attach XDP to bond0"))
+		goto out;
+
+	/* With XDP loaded, switching to vlan+srcmac must be rejected */
+	err = system("ip link set bond0 type bond xmit_hash_policy vlan+srcmac 2>/dev/null");
+	ASSERT_NEQ(err, 0, "vlan+srcmac change with XDP loaded should fail");
+
+	/* Detach XDP first, then the same change must succeed */
+	ASSERT_OK(bpf_xdp_detach(bond_ifindex, XDP_FLAGS_DRV_MODE, NULL),
+		  "detach XDP from bond0");
+
+	bond_ifindex = -1;
+	err = system("ip link set bond0 type bond xmit_hash_policy vlan+srcmac 2>/dev/null");
+	ASSERT_OK(err, "vlan+srcmac change without XDP should succeed");
+
+out:
+	if (bond_ifindex > 0)
+		bpf_xdp_detach(bond_ifindex, XDP_FLAGS_DRV_MODE, NULL);
+	close_netns(nstoken);
+	SYS_NOFAIL("ip netns del ns_xmit_policy");
+}
+
 static int libbpf_debug_print(enum libbpf_print_level level,
 			      const char *format, va_list args)
 {
@@ -771,6 +826,9 @@ void serial_test_xdp_bonding(void)
 				test_case->xmit_policy);
 	}
 
+	if (test__start_subtest("xdp_bonding_xmit_policy_compat"))
+		test_xdp_bonding_xmit_policy_compat(&skeletons);
+
 	if (test__start_subtest("xdp_bonding_redirect_multi"))
 		test_xdp_bonding_redirect_multi(&skeletons);
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH net v1 0/2] bonding: fix missing XDP compat check on xmit_hash_policy change
  2026-02-26  8:03 [PATCH net v1 0/2] bonding: fix missing XDP compat check on xmit_hash_policy change Jiayuan Chen
  2026-02-26  8:03 ` [PATCH net v1 1/2] bpf/bonding: reject vlan+srcmac xmit_hash_policy change when XDP is loaded Jiayuan Chen
  2026-02-26  8:03 ` [PATCH net v1 2/2] selftests/bpf: add test for xdp_bonding xmit_hash_policy compat Jiayuan Chen
@ 2026-03-03 10:00 ` patchwork-bot+netdevbpf
  2 siblings, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-03-03 10:00 UTC (permalink / raw)
  To: Jiayuan Chen
  Cc: netdev, jiayuan.chen, jv, andrew+netdev, davem, edumazet, kuba,
	pabeni, horms, ast, daniel, hawk, john.fastabend, sdf, andrii,
	eddyz87, martin.lau, song, yonghong.song, kpsingh, haoluo, jolsa,
	shuah, jon.toppins+linux, joamaki, linux-kernel, bpf,
	linux-kselftest

Hello:

This series was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:

On Thu, 26 Feb 2026 16:03:00 +0800 you wrote:
> syzkaller reported a bug https://syzkaller.appspot.com/bug?extid=5a287bcdc08104bc3132
> 
> When a bond device is in 802.3ad or balance-xor mode, XDP is supported
> only when xmit_hash_policy != vlan+srcmac.  This constraint is enforced
> in bond_option_mode_set() via bond_xdp_check(), which prevents switching
> to an XDP-incompatible mode while a program is loaded.  However, the
> symmetric path -- changing xmit_hash_policy while XDP is loaded -- had
> no such guard in bond_option_xmit_hash_policy_set().
> 
> [...]

Here is the summary with links:
  - [net,v1,1/2] bpf/bonding: reject vlan+srcmac xmit_hash_policy change when XDP is loaded
    https://git.kernel.org/netdev/net/c/479d589b40b8
  - [net,v1,2/2] selftests/bpf: add test for xdp_bonding xmit_hash_policy compat
    https://git.kernel.org/netdev/net/c/181cafbd8a01

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-03-03 10:00 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-26  8:03 [PATCH net v1 0/2] bonding: fix missing XDP compat check on xmit_hash_policy change Jiayuan Chen
2026-02-26  8:03 ` [PATCH net v1 1/2] bpf/bonding: reject vlan+srcmac xmit_hash_policy change when XDP is loaded Jiayuan Chen
2026-02-26  8:03 ` [PATCH net v1 2/2] selftests/bpf: add test for xdp_bonding xmit_hash_policy compat Jiayuan Chen
2026-03-03 10:00 ` [PATCH net v1 0/2] bonding: fix missing XDP compat check on xmit_hash_policy change patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox