Skip to content

Commit 4e0c19f

Browse files
vladimirolteankuba-moo
authored andcommitted
net: dsa: don't leak tagger-owned storage on switch driver unbind
In the initial commit dc452a4 ("net: dsa: introduce tagger-owned storage for private and shared data"), we had a call to tag_ops->disconnect(dst) issued from dsa_tree_free(), which is called at tree teardown time. There were problems with connecting to a switch tree as a whole, so this got reworked to connecting to individual switches within the tree. In this process, tag_ops->disconnect(ds) was made to be called only from switch.c (cross-chip notifiers emitted as a result of dynamic tag proto changes), but the normal driver teardown code path wasn't replaced with anything. Solve this problem by adding a function that does the opposite of dsa_switch_setup_tag_protocol(), which is called from the equivalent spot in dsa_switch_teardown(). The positioning here also ensures that we won't have any use-after-free in tagging protocol (*rcv) ops, since the teardown sequence is as follows: dsa_tree_teardown -> dsa_tree_teardown_master -> dsa_master_teardown -> unsets master->dsa_ptr, making no further packets match the ETH_P_XDSA packet type handler -> dsa_tree_teardown_ports -> dsa_port_teardown -> dsa_slave_destroy -> unregisters DSA net devices, there is even a synchronize_net() in unregister_netdevice_many() -> dsa_tree_teardown_switches -> dsa_switch_teardown -> dsa_switch_teardown_tag_protocol -> finally frees the tagger-owned storage Fixes: 7f29731 ("net: dsa: make tagging protocols connect to individual switches from a tree") Signed-off-by: Vladimir Oltean <[email protected]> Reviewed-by: Saeed Mahameed <[email protected]> Reviewed-by: Florian Fainelli <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 2929cce commit 4e0c19f

File tree

1 file changed

+10
-0
lines changed

1 file changed

+10
-0
lines changed

net/dsa/dsa2.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,14 @@ static int dsa_switch_setup_tag_protocol(struct dsa_switch *ds)
864864
return err;
865865
}
866866

867+
static void dsa_switch_teardown_tag_protocol(struct dsa_switch *ds)
868+
{
869+
const struct dsa_device_ops *tag_ops = ds->dst->tag_ops;
870+
871+
if (tag_ops->disconnect)
872+
tag_ops->disconnect(ds);
873+
}
874+
867875
static int dsa_switch_setup(struct dsa_switch *ds)
868876
{
869877
struct dsa_devlink_priv *dl_priv;
@@ -953,6 +961,8 @@ static void dsa_switch_teardown(struct dsa_switch *ds)
953961
ds->slave_mii_bus = NULL;
954962
}
955963

964+
dsa_switch_teardown_tag_protocol(ds);
965+
956966
if (ds->ops->teardown)
957967
ds->ops->teardown(ds);
958968

0 commit comments

Comments
 (0)