• Vladimir Oltean's avatar
    net: dsa: sja1105: prevent tag_8021q VLANs from being received on user ports · 73ceab83
    Vladimir Oltean authored
    Currently it is possible for an attacker to craft packets with a fake
    DSA tag and send them to us, and our user ports will accept them and
    preserve that VLAN when transmitting towards the CPU. Then the tagger
    will be misled into thinking that the packets came on a different port
    than they really came on.
    
    Up until recently there wasn't a good option to prevent this from
    happening. In SJA1105P and later, the MAC Configuration Table introduced
    two options called:
    - DRPSITAG: Drop Single Inner Tagged Frames
    - DRPSOTAG: Drop Single Outer Tagged Frames
    
    Because the sja1105 driver classifies all VLANs as "outer VLANs" (S-Tags),
    it would be in principle possible to enable the DRPSOTAG bit on ports
    using tag_8021q, and drop on ingress all packets which have a VLAN tag.
    When the switch is VLAN-unaware, this works, because it uses a custom
    TPID of 0xdadb, so any "tagged" packets received on a user port are
    probably a spoofing attempt. But when the switch overall is VLAN-aware,
    and some ports are standalone (therefore they use tag_8021q), the TPID
    is 0x8100, and the port can receive a mix of untagged and VLAN-tagged
    packets. The untagged ones will be classified to the tag_8021q pvid, and
    the tagged ones to the VLAN ID from the packet header. Yes, it is true
    that since commit 4fbc08bd ("net: dsa: sja1105: deny 8021q uppers on
    ports") we no longer support this mixed mode, but that is a temporary
    limitation which will eventually be lifted. It would be nice to not
    introduce one more restriction via DRPSOTAG, which would make the
    standalone ports of a VLAN-aware switch drop genuinely VLAN-tagged
    packets.
    
    Also, the DRPSOTAG bit is not available on the first generation of
    switches (SJA1105E, SJA1105T). So since one of the key features of this
    driver is compatibility across switch generations, this makes it an even
    less desirable approach.
    
    The breakthrough comes from commit bef0746c ("net: dsa: sja1105:
    make sure untagged packets are dropped on ingress ports with no pvid"),
    where it became obvious that untagged packets are not dropped even if
    the ingress port is not in the VMEMB_PORT vector of that port's pvid.
    However, VLAN-tagged packets are subject to VLAN ingress
    checking/dropping. This means that instead of using the catch-all
    DRPSOTAG bit introduced in SJA1105P, we can drop tagged packets on a
    per-VLAN basis, and this is already compatible with SJA1105E/T.
    
    This patch adds an "allowed_ingress" argument to sja1105_vlan_add(), and
    we call it with "false" for tag_8021q VLANs on user ports. The tag_8021q
    VLANs still need to be allowed, of course, on ingress to DSA ports and
    CPU ports.
    
    We also need to refine the drop_untagged check in sja1105_commit_pvid to
    make it not freak out about this new configuration. Currently it will
    try to keep the configuration consistent between untagged and pvid-tagged
    packets, so if the pvid of a port is 1 but VLAN 1 is not in VMEMB_PORT,
    packets tagged with VID 1 will behave the same as untagged packets, and
    be dropped. This behavior is what we want for ports under a VLAN-aware
    bridge, but for the ports with a tag_8021q pvid, we want untagged
    packets to be accepted, but packets tagged with a header recognized by
    the switch as a tag_8021q VLAN to be dropped. So only restrict the
    drop_untagged check to apply to the bridge_pvid, not to the tag_8021q_pvid.
    Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    73ceab83
sja1105_main.c 95.4 KB