4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Andrew Lunn <andrew@xxxxxxx> 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@xxxxxxxxx> Fixes: 91da11f870f0 ("net: Distributed Switch Architecture protocol support") Signed-off-by: Andrew Lunn <andrew@xxxxxxx> Reviewed-by: Florian Fainelli <f.fainelli@xxxxxxxxx> Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- net/dsa/tag_brcm.c | 3 +++ net/dsa/tag_dsa.c | 3 +++ net/dsa/tag_edsa.c | 3 +++ net/dsa/tag_ksz.c | 3 +++ net/dsa/tag_lan9303.c | 3 +++ net/dsa/tag_mtk.c | 3 +++ net/dsa/tag_qca.c | 3 +++ net/dsa/tag_trailer.c | 3 +++ 8 files changed, 24 insertions(+) --- a/net/dsa/tag_brcm.c +++ b/net/dsa/tag_brcm.c @@ -121,6 +121,9 @@ static struct sk_buff *brcm_tag_rcv(stru 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); --- a/net/dsa/tag_dsa.c +++ b/net/dsa/tag_dsa.c @@ -107,6 +107,9 @@ static struct sk_buff *dsa_rcv(struct sk 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, --- a/net/dsa/tag_edsa.c +++ b/net/dsa/tag_edsa.c @@ -120,6 +120,9 @@ static struct sk_buff *edsa_rcv(struct s 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 --- a/net/dsa/tag_ksz.c +++ b/net/dsa/tag_ksz.c @@ -92,6 +92,9 @@ static struct sk_buff *ksz_rcv(struct sk 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; --- a/net/dsa/tag_lan9303.c +++ b/net/dsa/tag_lan9303.c @@ -108,6 +108,9 @@ static struct sk_buff *lan9303_rcv(struc 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; --- a/net/dsa/tag_mtk.c +++ b/net/dsa/tag_mtk.c @@ -81,6 +81,9 @@ static struct sk_buff *mtk_tag_rcv(struc 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; --- a/net/dsa/tag_qca.c +++ b/net/dsa/tag_qca.c @@ -104,6 +104,9 @@ static struct sk_buff *qca_tag_rcv(struc 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; --- a/net/dsa/tag_trailer.c +++ b/net/dsa/tag_trailer.c @@ -76,6 +76,9 @@ static struct sk_buff *trailer_rcv(struc 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;