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.

selftests: bonding: add test for stacked bond header_parse recursion

Add a selftest to reproduce the infinite recursion in bond_header_parse()
when bonds are stacked (bond1 -> bond0 -> gre). When a packet is received
via AF_PACKET SOCK_DGRAM on the topmost bond, dev_parse_header() calls
bond_header_parse() which used skb->dev (always the topmost bond) to get
the bonding struct. This caused it to recurse back into itself
indefinitely, leading to stack overflow.

Before commit b7405dcf7385 ("bonding: prevent potential infinite loop
in bond_header_parse()"), the test triggers:

./bond_stacked_header_parse.sh

[ 71.999481] BUG: MAX_LOCK_DEPTH too low!
[ 72.000170] turning off the locking correctness validator.
[ 72.001029] Please attach the output of /proc/lock_stat to the bug report
[ 72.002079] depth: 48 max: 48!
...

After the fix, everything works fine:

./bond_stacked_header_parse.sh
TEST: Stacked bond header_parse does not recurse [ OK ]

Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
Link: https://patch.msgid.link/20260320022245.392384-1-jiayuan.chen@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Jiayuan Chen and committed by
Jakub Kicinski
e81cf512 db3bd9e5

+74
+1
tools/testing/selftests/drivers/net/bonding/Makefile
··· 11 11 bond_macvlan_ipvlan.sh \ 12 12 bond_options.sh \ 13 13 bond_passive_lacp.sh \ 14 + bond_stacked_header_parse.sh \ 14 15 dev_addr_lists.sh \ 15 16 mode-1-recovery-updelay.sh \ 16 17 mode-2-recovery-updelay.sh \
+72
tools/testing/selftests/drivers/net/bonding/bond_stacked_header_parse.sh
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # Test that bond_header_parse() does not infinitely recurse with stacked bonds. 5 + # 6 + # When a non-Ethernet device (e.g. GRE) is enslaved to a bond that is itself 7 + # enslaved to another bond (bond1 -> bond0 -> gre), receiving a packet via 8 + # AF_PACKET SOCK_DGRAM triggers dev_parse_header() -> bond_header_parse(). 9 + # Since parse() used skb->dev (always the topmost bond) instead of a passed-in 10 + # dev pointer, it would recurse back into itself indefinitely. 11 + 12 + # shellcheck disable=SC2034 13 + ALL_TESTS=" 14 + bond_test_stacked_header_parse 15 + " 16 + REQUIRE_MZ=no 17 + NUM_NETIFS=0 18 + lib_dir=$(dirname "$0") 19 + source "$lib_dir"/../../../net/forwarding/lib.sh 20 + 21 + # shellcheck disable=SC2329 22 + bond_test_stacked_header_parse() 23 + { 24 + local devdummy="test-dummy0" 25 + local devgre="test-gre0" 26 + local devbond0="test-bond0" 27 + local devbond1="test-bond1" 28 + 29 + # shellcheck disable=SC2034 30 + RET=0 31 + 32 + # Setup: dummy -> gre -> bond0 -> bond1 33 + ip link add name "$devdummy" type dummy 34 + ip addr add 10.0.0.1/24 dev "$devdummy" 35 + ip link set "$devdummy" up 36 + 37 + ip link add name "$devgre" type gre local 10.0.0.1 38 + 39 + ip link add name "$devbond0" type bond mode active-backup 40 + ip link add name "$devbond1" type bond mode active-backup 41 + 42 + ip link set "$devgre" master "$devbond0" 43 + ip link set "$devbond0" master "$devbond1" 44 + 45 + ip link set "$devgre" up 46 + ip link set "$devbond0" up 47 + ip link set "$devbond1" up 48 + 49 + # tcpdump on a non-Ethernet bond uses AF_PACKET SOCK_DGRAM (cooked 50 + # capture), which triggers dev_parse_header() -> bond_header_parse() 51 + # on receive. With the bug, this recurses infinitely. 52 + timeout 5 tcpdump -c 1 -i "$devbond1" >/dev/null 2>&1 & 53 + local tcpdump_pid=$! 54 + sleep 1 55 + 56 + # Send a GRE packet to 10.0.0.1 so it arrives via gre -> bond0 -> bond1 57 + python3 -c "from scapy.all import *; send(IP(src='10.0.0.2', dst='10.0.0.1')/GRE()/IP()/UDP(), verbose=0)" 58 + check_err $? "failed to send GRE packet (scapy installed?)" 59 + 60 + wait "$tcpdump_pid" 2>/dev/null 61 + 62 + ip link del "$devbond1" 2>/dev/null 63 + ip link del "$devbond0" 2>/dev/null 64 + ip link del "$devgre" 2>/dev/null 65 + ip link del "$devdummy" 2>/dev/null 66 + 67 + log_test "Stacked bond header_parse does not recurse" 68 + } 69 + 70 + tests_run 71 + 72 + exit "$EXIT_STATUS"
+1
tools/testing/selftests/drivers/net/bonding/config
··· 14 14 CONFIG_NETCONSOLE_DYNAMIC=y 15 15 CONFIG_NETCONSOLE_EXTENDED_LOG=y 16 16 CONFIG_NETDEVSIM=m 17 + CONFIG_NET_IPGRE=y 17 18 CONFIG_NET_SCH_INGRESS=y 18 19 CONFIG_NLMON=y 19 20 CONFIG_VETH=y