net: mscc: ocelot: fix use-after-free in ocelot_vlan_del()
authorVladimir Oltean <vladimir.oltean@nxp.com>
Mon, 14 Feb 2022 23:42:00 +0000 (01:42 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 23 Feb 2022 11:05:58 +0000 (12:05 +0100)
commit ef57640575406f57f5b3393cf57f457b0ace837e upstream.

ocelot_vlan_member_del() will free the struct ocelot_bridge_vlan, so if
this is the same as the port's pvid_vlan which we access afterwards,
what we're accessing is freed memory.

Fix the bug by determining whether to clear ocelot_port->pvid_vlan prior
to calling ocelot_vlan_member_del().

Fixes: d4004422f6f9 ("net: mscc: ocelot: track the port pvid using a pointer")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/ethernet/mscc/ocelot.c

index 02edd383dea2243efbad6af56bbb7415b630db80..886daa29bfb025910139f7025e21400fb87d43c0 100644 (file)
@@ -480,14 +480,18 @@ EXPORT_SYMBOL(ocelot_vlan_add);
 int ocelot_vlan_del(struct ocelot *ocelot, int port, u16 vid)
 {
        struct ocelot_port *ocelot_port = ocelot->ports[port];
+       bool del_pvid = false;
        int err;
 
+       if (ocelot_port->pvid_vlan && ocelot_port->pvid_vlan->vid == vid)
+               del_pvid = true;
+
        err = ocelot_vlan_member_del(ocelot, port, vid);
        if (err)
                return err;
 
        /* Ingress */
-       if (ocelot_port->pvid_vlan && ocelot_port->pvid_vlan->vid == vid)
+       if (del_pvid)
                ocelot_port_set_pvid(ocelot, port, NULL);
 
        /* Egress */