diff options
author | Jakub Kicinski <kuba@kernel.org> | 2022-09-22 06:40:15 -0700 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2022-09-22 06:40:16 -0700 |
commit | c5da4b68d2a8592a7535bb9e4523158088a6538b (patch) | |
tree | b07036217baa9210b095571b5316664e0077a665 | |
parent | 2002fbac743b6e2391b4ed50ad9eb626768dd78a (diff) | |
parent | 2ffd57327ff1e91ad675c1efd5f02a3d786e64d1 (diff) |
Merge branch 'bonding-fix-null-deref-in-bond_rr_gen_slave_id'
Jonathan Toppins says:
====================
bonding: fix NULL deref in bond_rr_gen_slave_id
Fix a NULL dereference of the struct bonding.rr_tx_counter member because
if a bond is initially created with an initial mode != zero (Round Robin)
the memory required for the counter is never created and when the mode is
changed there is never any attempt to verify the memory is allocated upon
switching modes.
====================
Link: https://lore.kernel.org/r/cover.1663694476.git.jtoppins@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r-- | drivers/net/bonding/bond_main.c | 15 | ||||
-rw-r--r-- | tools/testing/selftests/drivers/net/bonding/Makefile | 3 | ||||
-rwxr-xr-x | tools/testing/selftests/drivers/net/bonding/bond-arp-interval-causes-panic.sh | 49 |
3 files changed, 57 insertions, 10 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index bc6d8b0aa6fb..86d42306aa5e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4182,6 +4182,12 @@ static int bond_open(struct net_device *bond_dev) struct list_head *iter; struct slave *slave; + if (BOND_MODE(bond) == BOND_MODE_ROUNDROBIN && !bond->rr_tx_counter) { + bond->rr_tx_counter = alloc_percpu(u32); + if (!bond->rr_tx_counter) + return -ENOMEM; + } + /* reset slave->backup and slave->inactive */ if (bond_has_slaves(bond)) { bond_for_each_slave(bond, slave, iter) { @@ -6243,15 +6249,6 @@ static int bond_init(struct net_device *bond_dev) if (!bond->wq) return -ENOMEM; - if (BOND_MODE(bond) == BOND_MODE_ROUNDROBIN) { - bond->rr_tx_counter = alloc_percpu(u32); - if (!bond->rr_tx_counter) { - destroy_workqueue(bond->wq); - bond->wq = NULL; - return -ENOMEM; - } - } - spin_lock_init(&bond->stats_lock); netdev_lockdep_set_classes(bond_dev); diff --git a/tools/testing/selftests/drivers/net/bonding/Makefile b/tools/testing/selftests/drivers/net/bonding/Makefile index 0f9659407969..1d866658e541 100644 --- a/tools/testing/selftests/drivers/net/bonding/Makefile +++ b/tools/testing/selftests/drivers/net/bonding/Makefile @@ -2,7 +2,8 @@ # Makefile for net selftests TEST_PROGS := bond-break-lacpdu-tx.sh \ - dev_addr_lists.sh + dev_addr_lists.sh \ + bond-arp-interval-causes-panic.sh TEST_FILES := lag_lib.sh diff --git a/tools/testing/selftests/drivers/net/bonding/bond-arp-interval-causes-panic.sh b/tools/testing/selftests/drivers/net/bonding/bond-arp-interval-causes-panic.sh new file mode 100755 index 000000000000..71c00bfafbc9 --- /dev/null +++ b/tools/testing/selftests/drivers/net/bonding/bond-arp-interval-causes-panic.sh @@ -0,0 +1,49 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# cause kernel oops in bond_rr_gen_slave_id +DEBUG=${DEBUG:-0} + +set -e +test ${DEBUG} -ne 0 && set -x + +finish() +{ + ip netns delete server || true + ip netns delete client || true + ip link del link1_1 || true +} + +trap finish EXIT + +client_ip4=192.168.1.198 +server_ip4=192.168.1.254 + +# setup kernel so it reboots after causing the panic +echo 180 >/proc/sys/kernel/panic + +# build namespaces +ip link add dev link1_1 type veth peer name link1_2 + +ip netns add "server" +ip link set dev link1_2 netns server up name eth0 +ip netns exec server ip addr add ${server_ip4}/24 dev eth0 + +ip netns add "client" +ip link set dev link1_1 netns client down name eth0 +ip netns exec client ip link add dev bond0 down type bond mode 1 \ + miimon 100 all_slaves_active 1 +ip netns exec client ip link set dev eth0 down master bond0 +ip netns exec client ip link set dev bond0 up +ip netns exec client ip addr add ${client_ip4}/24 dev bond0 +ip netns exec client ping -c 5 $server_ip4 >/dev/null + +ip netns exec client ip link set dev eth0 down nomaster +ip netns exec client ip link set dev bond0 down +ip netns exec client ip link set dev bond0 type bond mode 0 \ + arp_interval 1000 arp_ip_target "+${server_ip4}" +ip netns exec client ip link set dev eth0 down master bond0 +ip netns exec client ip link set dev bond0 up +ip netns exec client ping -c 5 $server_ip4 >/dev/null + +exit 0 |