2014-01-30 Florian Fainelli <flor...@openwrt.org>:
> 2014-01-29 Rafał Miłecki <zaj...@gmail.com>:
>> 2014-01-28 Jonas Gorski <j...@openwrt.org>:
>>> On Tue, Jan 28, 2014 at 8:41 PM, Rafał Miłecki <zaj...@gmail.com> wrote:
>> On my:
>>> Found chip with id 0x5357, rev 0x02 and package 0x0A
>> code
>> if (!(mgmt & SM_SW_FWD_EN)) {
>> ...
>> }
>> is never called, because that bit is already set:
>>> b53_common: B53_SWITCH_MODE: 0x06 (SM_SW_FWD_EN:0x02)
>>
>> So this won't help, because SM_SW_FWD_EN is already set after reset.
>
> SM_SW_FWD_EN can be overriden using hardware straps, which is probably
> the reason why it is already set after reset for your case and why you
> are seeing leakage. Ideally the bootloader would have cleared that bit
> to make sure it puts the switch back into unconfigured managed mode
> and avoid the leakage.
>
> If you have some way to access the MII registers in CFE, try to clear
> that bit and see if the leakage still happens?

No, (mine) CFE doesn't have tools like that.

I've applied attached patch to see what actually makes switch allow
transfer between LANs and WAN ports. I setup two machines:
1) Notebook connected to one of the LAN ports (static 192.168.1.2)
2) PC connected to the WAN port (static 192.168.1.3)

Right after early OpenWrt booting, before b53 kicks in, machines were
*not* able to talk. After modified b53 was started:
[ 3.540000] bgmac bcma0:1: Found PHY addr: 30 (NOREGS)
[ 3.550000] bgmac bcma0:1: Support for Roboswitch not implemented
[ 3.560000] libphy: bgmac mii bus: probed
[ 3.570000] b53_common: [b53_switch_reset:488] B53_SWITCH_MODE: 0x06
[ 3.650000] b53_common: [b53_switch_reset_gpio:480] GPIO reset done
[ 3.650000] b53_common: [b53_switch_reset:493] B53_SWITCH_MODE: 0x06
[ 3.660000] b53_common: [b53_switch_reset:496] ABORT
[ 3.670000] b53_common: found switch: BCM53125, rev 4
[ 3.670000] bgmac: Broadcom 47xx GBit MAC driver loaded
[ 5.670000] libphy: bgmac-0-0:1e - Link is Up - 1000/Full
[ 11.800000] NET: Registered protocol family 10
[ 11.810000] nf_conntrack version 0.5.0 (965 buckets, 3860 max)
[ 11.830000] ip6_tables: (C) 2000-2006 Netfilter Core Team
[ 11.860000] ip_tables: (C) 2000-2006 Netfilter Core Team
[ 11.920000] xt_time: kernel timezone is -0000
[ 11.930000] PPP generic driver version 2.4.2
[ 11.940000] NET: Registered protocol family 24
[ 15.650000] b53_common: [b53_global_apply_config:803] ABORT
machines were able to talk (ping each other).

As you can see, my patch aborts all switch configuration leaving only
call to the b53_switch_reset_gpio on the beginning of
b53_switch_reset.

So:
1) Before b53_switch_reset_gpio LAN ports and WAN port are separated
2) After b53_switch_reset_gpio LAN ports and WAN port are the same network/VLAN

After above test I started moving my:
> /* Abort at this early point to see what happens after GPIO reset */
> pr_info("[%s:%d] ABORT\n", __FUNCTION__, __LINE__);
> return 0;
to see what part of code will make LAN port and WAN port separated
again. It is call to the b53_enable_ports.

If I put my "return 0;" right after calling "b53_enable_ports"
(everything in b53_switch_reset) - it's enough. After allowing this
call to "b53_enable_ports" my machines were not able to talk each
other anymore.

* CONCLUSION *

b53_switch_reset_gpio resets switch into a vulnerable state, where
machine behind the WAN can "access" LAN machines.
We need to put switch in some safe state before we call b53_switch_reset_gpio.
Example of configuring ports into a safe state is b53_enable_ports.

Any idea what exactly we should do before calling b53_switch_reset_gpio?

-- 
Rafał
diff --git a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c 
b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c
index f6a5418..6ce6660 100644
--- a/target/linux/generic/files/drivers/net/phy/b53/b53_common.c
+++ b/target/linux/generic/files/drivers/net/phy/b53/b53_common.c
@@ -476,14 +476,26 @@ static void b53_switch_reset_gpio(struct b53_device *dev)
        mdelay(20);
 
        dev->current_page = 0xff;
+
+       pr_info("[%s:%d] GPIO reset done\n", __FUNCTION__, __LINE__);
 }
 
 static int b53_switch_reset(struct b53_device *dev)
 {
        u8 mgmt;
 
+       b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
+       pr_info("[%s:%d] B53_SWITCH_MODE: 0x%02X\n", __FUNCTION__, __LINE__, 
mgmt);
+
        b53_switch_reset_gpio(dev);
 
+       b53_read8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, &mgmt);
+       pr_info("[%s:%d] B53_SWITCH_MODE: 0x%02X\n", __FUNCTION__, __LINE__, 
mgmt);
+
+       /* Abort at this early point to see what happens after GPIO reset */
+       pr_info("[%s:%d] ABORT\n", __FUNCTION__, __LINE__);
+       return 0;
+
        if (is539x(dev)) {
                b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, 0x83);
                b53_write8(dev, B53_CTRL_PAGE, B53_SOFTRESET, 0x00);
@@ -778,6 +790,8 @@ static int b53_global_reset_switch(struct switch_dev *dev)
        memset(priv->vlans, 0, sizeof(priv->vlans) * dev->vlans);
        memset(priv->ports, 0, sizeof(priv->ports) * dev->ports);
 
+       /* We reset switch once in b53_switch_init, it's enough for tests */
+       return 0;
        return b53_switch_reset(priv);
 }
 
@@ -785,6 +799,10 @@ static int b53_global_apply_config(struct switch_dev *dev)
 {
        struct b53_device *priv = sw_to_b53(dev);
 
+       /* We want to check switch state after GPIO reset, don't configure it */
+       pr_info("[%s:%d] ABORT\n", __FUNCTION__, __LINE__);
+       return 0;
+
        /* disable switching */
        b53_set_forwarding(priv, 0);
 
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel

Reply via email to