#!/bin/bash # SPDX-License-Identifier: GPL-2.0 # # Test that bond_header_parse() does not infinitely recurse with stacked bonds. # # When a non-Ethernet device (e.g. GRE) is enslaved to a bond that is itself # enslaved to another bond (bond1 -> bond0 -> gre), receiving a packet via # AF_PACKET SOCK_DGRAM triggers dev_parse_header() -> bond_header_parse(). # Since parse() used skb->dev (always the topmost bond) instead of a passed-in # dev pointer, it would recurse back into itself indefinitely. # shellcheck disable=SC2034 ALL_TESTS=" bond_test_stacked_header_parse " REQUIRE_MZ=no NUM_NETIFS=0 lib_dir=$(dirname "$0") source "$lib_dir"/../../../net/forwarding/lib.sh # shellcheck disable=SC2329 bond_test_stacked_header_parse() { local devdummy="test-dummy0" local devgre="test-gre0" local devbond0="test-bond0" local devbond1="test-bond1" # shellcheck disable=SC2034 RET=0 # Setup: dummy -> gre -> bond0 -> bond1 ip link add name "$devdummy" type dummy ip addr add 10.0.0.1/24 dev "$devdummy" ip link set "$devdummy" up ip link add name "$devgre" type gre local 10.0.0.1 ip link add name "$devbond0" type bond mode active-backup ip link add name "$devbond1" type bond mode active-backup ip link set "$devgre" master "$devbond0" ip link set "$devbond0" master "$devbond1" ip link set "$devgre" up ip link set "$devbond0" up ip link set "$devbond1" up # tcpdump on a non-Ethernet bond uses AF_PACKET SOCK_DGRAM (cooked # capture), which triggers dev_parse_header() -> bond_header_parse() # on receive. With the bug, this recurses infinitely. timeout 5 tcpdump -c 1 -i "$devbond1" >/dev/null 2>&1 & local tcpdump_pid=$! sleep 1 # Send a GRE packet to 10.0.0.1 so it arrives via gre -> bond0 -> bond1 python3 -c "from scapy.all import *; send(IP(src='10.0.0.2', dst='10.0.0.1')/GRE()/IP()/UDP(), verbose=0)" check_err $? "failed to send GRE packet (scapy installed?)" wait "$tcpdump_pid" 2>/dev/null ip link del "$devbond1" 2>/dev/null ip link del "$devbond0" 2>/dev/null ip link del "$devgre" 2>/dev/null ip link del "$devdummy" 2>/dev/null log_test "Stacked bond header_parse does not recurse" } tests_run exit "$EXIT_STATUS"