lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <cf3001de-4ee2-45f2-83d3-3c878b85d628@free.fr>
Date:   Mon, 14 Jun 2021 18:42:25 +0200
From:   Adel Belhouane <bugs.a.b@...e.fr>
To:     Roopa Prabhu <roopa@...dia.com>,
        Nikolay Aleksandrov <nikolay@...dia.com>
Cc:     bridge@...ts.linux-foundation.org, netdev@...r.kernel.org
Subject: [bridge]: STP: no port in blocking state despite a loop when in a
 network namespace

Hello,

I would like to simulate redundant bridge links in network namespaces
and protect against loops by using STP. I need the behavior to stay
consistent between the initial network namespace and a new network
namespace. This doesn't appear to be the case below.

I'm creating the simplest experiment possible: a loop between two
bridges with STP enabled, both linked directly with two pairs of
veth links.

In the first case, when run from initial network namespace, one bridge
port is put in blocking state to avoid the loop, as expected.

In the second case, when running the same experiment inside a new
network namespace, no port is put in blocking state. So every port goes
from listening -> learning -> forwarding. As I didn't disable for
example IPv6 auto-configuration, there's traffic starting to loop
between the two bridges. To be sure whatever happens there won't be too
much traffic and CPU use, I added a netem qdisc on all veth links.


Unique script loopbridgestp.sh below:

----

#!/bin/sh


cleanup () {
	for dev in lbr0 lbr1 lbr0p1 lbr0p2; do
		ip link del dev "$dev" 2>/dev/null || :
	done
}

cleanup

ip link add name lbr0 type bridge stp_state 1
ip link add name lbr1 type bridge stp_state 1
ip link add name lbr0p1 up master lbr0 type veth peer name lbr1p1
ip link set dev lbr1p1 up master lbr1
ip link add name lbr0p2 up master lbr0 type veth peer name lbr1p2
ip link set dev lbr1p2 up master lbr1

#optional, to protect host
tc qdisc add dev lbr0p1 root handle 1: netem rate 1gbit
tc qdisc add dev lbr0p2 root handle 1: netem rate 1gbit
tc qdisc add dev lbr1p1 root handle 1: netem rate 1gbit
tc qdisc add dev lbr1p2 root handle 1: netem rate 1gbit


ip link set lbr0 up
ip link set lbr1 up


----

First case (directly in initial network namespace in a VM):

    ./loopbridgestp.sh

First case results, waiting a bit for states to change, showing as
expected a port in blocking state:

    root@...ian10:~# bridge link
    5: lbr1p1@...0p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr1 state listening priority 32 cost 2 
    6: lbr0p1@...1p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr0 state listening priority 32 cost 2 
    7: lbr1p2@...0p2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr1 state listening priority 32 cost 2 
    8: lbr0p2@...1p2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr0 state blocking priority 32 cost 2 
    root@...ian10:~# bridge link
    5: lbr1p1@...0p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr1 state learning priority 32 cost 2 
    6: lbr0p1@...1p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr0 state learning priority 32 cost 2 
    7: lbr1p2@...0p2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr1 state learning priority 32 cost 2 
    8: lbr0p2@...1p2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr0 state blocking priority 32 cost 2 
    root@...ian10:~# bridge link
    5: lbr1p1@...0p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr1 state forwarding priority 32 cost 2 
    6: lbr0p1@...1p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr0 state forwarding priority 32 cost 2 
    7: lbr1p2@...0p2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr1 state forwarding priority 32 cost 2 
    8: lbr0p2@...1p2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr0 state blocking priority 32 cost 2 


Second case, within a new network namespace:

    ip netns add experiment
    ip netns exec experiment bash

then:

    ./loopbridgestp.sh


Second case results in allowing bridge forwarding loops to happen
despite STP:

    root@...ian10:~# bridge link
    4: lbr1p1@...0p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr1 state listening priority 32 cost 2 
    5: lbr0p1@...1p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr0 state listening priority 32 cost 2 
    6: lbr1p2@...0p2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr1 state listening priority 32 cost 2 
    7: lbr0p2@...1p2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr0 state listening priority 32 cost 2 
    root@...ian10:~# bridge link
    4: lbr1p1@...0p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr1 state learning priority 32 cost 2 
    5: lbr0p1@...1p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr0 state learning priority 32 cost 2 
    6: lbr1p2@...0p2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr1 state learning priority 32 cost 2 
    7: lbr0p2@...1p2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr0 state learning priority 32 cost 2 
    root@...ian10:~# bridge link
    4: lbr1p1@...0p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr1 state forwarding priority 32 cost 2 
    5: lbr0p1@...1p1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr0 state forwarding priority 32 cost 2 
    6: lbr1p2@...0p2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr1 state forwarding priority 32 cost 2 
    7: lbr0p2@...1p2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master lbr0 state forwarding priority 32 cost 2 

Tested with same results on:

* Debian kernel 4.19.0-16-amd64
* Linux vanilla kernel 5.10.43
* Linux vanilla kernel 5.12.10

and this behavior might date back from much earlier from what I can
remember.

tcpdump shows there is still STP traffic on the veth interfaces.

No firewall was in use: no ebtables/iptables/nftables kernel module
was loaded.

Relevant kernel configuration: 

CONFIG_BRIDGE=m
CONFIG_BRIDGE_IGMP_SNOOPING=y
CONFIG_BRIDGE_VLAN_FILTERING=y
# CONFIG_BRIDGE_MRP is not set
# CONFIG_BRIDGE_CFM is not set
CONFIG_STP=m
CONFIG_GARP=m
CONFIG_MRP=m

root@...ian10:~# uname -a
Linux debian10 5.12.10 #1 SMP Sat Jun 12 18:22:17 UTC 2021 x86_64 GNU/Linux
root@...ian10:~# lsmod | egrep 'br|stp|garp|mrp'
bridge                266240  0
stp                    16384  1 bridge
llc                    16384  2 bridge,stp

Is there something I missed in order to have STP select a bridge port to
be in blocking state in a new network namespace as is the case in the
initial network namespace?

Or is that a bug?

Regards,
Adel Belhouane.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ