Skip to content

Commit 993107f

Browse files
idoschdavem330
authored andcommitted
mlxsw: spectrum_switchdev: Fix VLAN device deletion via ioctl
When deleting a VLAN device using an ioctl the netdev is unregistered before the VLAN filter is updated via ndo_vlan_rx_kill_vid(). It can lead to a use-after-free in mlxsw in case the VLAN device is deleted while being enslaved to a bridge. The reason for the above is that when mlxsw receives the CHANGEUPPER event, it wrongly assumes that the VLAN device is no longer its upper and thus destroys the internal representation of the bridge port despite the reference count being non-zero. Fix this by checking if the VLAN device is our upper using its real device. In net-next I'm going to remove this trick and instead make mlxsw completely agnostic to the order of the events. Fixes: c57529e ("mlxsw: spectrum: Replace vPorts with Port-VLAN") Signed-off-by: Ido Schimmel <[email protected]> Reviewed-by: Petr Machata <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent da93d29 commit 993107f

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,13 @@ static bool
296296
mlxsw_sp_bridge_port_should_destroy(const struct mlxsw_sp_bridge_port *
297297
bridge_port)
298298
{
299-
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_lower_get(bridge_port->dev);
299+
struct net_device *dev = bridge_port->dev;
300+
struct mlxsw_sp *mlxsw_sp;
301+
302+
if (is_vlan_dev(dev))
303+
mlxsw_sp = mlxsw_sp_lower_get(vlan_dev_real_dev(dev));
304+
else
305+
mlxsw_sp = mlxsw_sp_lower_get(dev);
300306

301307
/* In case ports were pulled from out of a bridged LAG, then
302308
* it's possible the reference count isn't zero, yet the bridge
@@ -2109,7 +2115,7 @@ mlxsw_sp_bridge_8021d_port_leave(struct mlxsw_sp_bridge_device *bridge_device,
21092115

21102116
vid = is_vlan_dev(dev) ? vlan_dev_vlan_id(dev) : 1;
21112117
mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
2112-
if (WARN_ON(!mlxsw_sp_port_vlan))
2118+
if (!mlxsw_sp_port_vlan)
21132119
return;
21142120

21152121
mlxsw_sp_port_vlan_bridge_leave(mlxsw_sp_port_vlan);

0 commit comments

Comments
 (0)