commit
fc5f33768cca7144f8d793205b229d46740d183b upstream.
The Marvell switches under some conditions will pass a frame to the
host with the port being the CPU port. Such frames are invalid, and
should be dropped. Not dropping them can result in a crash when
incrementing the receive statistics for an invalid port.
This has been reworked for 4.14, which does not have the central
dsa_master_find_slave() function, so each tag driver needs to check.
Reported-by: Chris Healy <cphealy@gmail.com>
Fixes:
91da11f870f0 ("net: Distributed Switch Architecture protocol support")
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
if (source_port >= ds->num_ports || !ds->ports[source_port].netdev)
return NULL;
+ if (unlikely(ds->cpu_port_mask & BIT(source_port)))
+ return NULL;
+
/* Remove Broadcom tag and update checksum */
skb_pull_rcsum(skb, BRCM_TAG_LEN);
if (source_port >= ds->num_ports || !ds->ports[source_port].netdev)
return NULL;
+ if (unlikely(ds->cpu_port_mask & BIT(source_port)))
+ return NULL;
+
/*
* Convert the DSA header to an 802.1q header if the 'tagged'
* bit in the DSA header is set. If the 'tagged' bit is clear,
if (source_port >= ds->num_ports || !ds->ports[source_port].netdev)
return NULL;
+ if (unlikely(ds->cpu_port_mask & BIT(source_port)))
+ return NULL;
+
/*
* If the 'tagged' bit is set, convert the DSA tag to a 802.1q
* tag and delete the ethertype part. If the 'tagged' bit is
if (source_port >= ds->num_ports || !ds->ports[source_port].netdev)
return NULL;
+ if (unlikely(ds->cpu_port_mask & BIT(source_port)))
+ return NULL;
+
pskb_trim_rcsum(skb, skb->len - KSZ_EGRESS_TAG_LEN);
skb->dev = ds->ports[source_port].netdev;
return NULL;
}
+ if (unlikely(ds->cpu_port_mask & BIT(source_port)))
+ return NULL;
+
if (!ds->ports[source_port].netdev) {
dev_warn_ratelimited(&dev->dev, "Dropping packet due to invalid netdev or device\n");
return NULL;
if (!ds->ports[port].netdev)
return NULL;
+ if (unlikely(ds->cpu_port_mask & BIT(port)))
+ return NULL;
+
skb->dev = ds->ports[port].netdev;
return skb;
if (!ds->ports[port].netdev)
return NULL;
+ if (unlikely(ds->cpu_port_mask & BIT(port)))
+ return NULL;
+
/* Update skb & forward the frame accordingly */
skb->dev = ds->ports[port].netdev;
if (source_port >= ds->num_ports || !ds->ports[source_port].netdev)
return NULL;
+ if (unlikely(ds->cpu_port_mask & BIT(source_port)))
+ return NULL;
+
pskb_trim_rcsum(skb, skb->len - 4);
skb->dev = ds->ports[source_port].netdev;