Skip to content

Commit 7e49e64

Browse files
committed
Merge branch 'collection-of-dsa-bug-fixes'
Vladimir Oltean says: ==================== Collection of DSA bug fixes Prompted by Russell King's 3 DSA bug reports from Friday (linked in their respective patches: 1, 2 and 3), I am providing fixes to those, as well as flushing the queue with 2 other bug fixes I had. 1: fix NULL pointer dereference during mv88e6xxx driver unbind, on old switch models which lack PVT and/or STU. Seen on the ZII dev board rev B. 2: fix failure to delete bridge port VLANs on old mv88e6xxx chips which lack STU. Seen on the same board. 3: fix WARN_ON() and resource leak in DSA core on driver unbind. Seen on the same board but is a much more widespread issue. 4: fix use-after-free during probing of DSA trees with >= 3 switches, if -EPROBE_DEFER exists. In principle issue also exists for the ZII board, I reproduced on Turris MOX. 5: fix incorrect use of refcount API in DSA core for those switches which use tag_8021q (felix, sja1105, vsc73xx). Returning an error when attempting to delete a tag_8021q VLAN prints a WARN_ON(), which is harmless but might be problematic with CONFIG_PANIC_ON_OOPS. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents b272732 + 514eff7 commit 7e49e64

File tree

4 files changed

+64
-13
lines changed

4 files changed

+64
-13
lines changed

drivers/net/dsa/mv88e6xxx/chip.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1852,6 +1852,8 @@ static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,
18521852
if (!chip->info->ops->vtu_getnext)
18531853
return -EOPNOTSUPP;
18541854

1855+
memset(entry, 0, sizeof(*entry));
1856+
18551857
entry->vid = vid ? vid - 1 : mv88e6xxx_max_vid(chip);
18561858
entry->valid = false;
18571859

@@ -1960,7 +1962,16 @@ static int mv88e6xxx_mst_put(struct mv88e6xxx_chip *chip, u8 sid)
19601962
struct mv88e6xxx_mst *mst, *tmp;
19611963
int err;
19621964

1963-
if (!sid)
1965+
/* If the SID is zero, it is for a VLAN mapped to the default MSTI,
1966+
* and mv88e6xxx_stu_setup() made sure it is always present, and thus,
1967+
* should not be removed here.
1968+
*
1969+
* If the chip lacks STU support, numerically the "sid" variable will
1970+
* happen to also be zero, but we don't want to rely on that fact, so
1971+
* we explicitly test that first. In that case, there is also nothing
1972+
* to do here.
1973+
*/
1974+
if (!mv88e6xxx_has_stu(chip) || !sid)
19641975
return 0;
19651976

19661977
list_for_each_entry_safe(mst, tmp, &chip->msts, node) {

drivers/net/dsa/mv88e6xxx/devlink.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,8 @@ void mv88e6xxx_teardown_devlink_regions_global(struct dsa_switch *ds)
736736
int i;
737737

738738
for (i = 0; i < ARRAY_SIZE(mv88e6xxx_regions); i++)
739-
dsa_devlink_region_destroy(chip->regions[i]);
739+
if (chip->regions[i])
740+
dsa_devlink_region_destroy(chip->regions[i]);
740741
}
741742

742743
void mv88e6xxx_teardown_devlink_regions_port(struct dsa_switch *ds, int port)

net/dsa/dsa.c

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,16 @@ static void dsa_tree_teardown_lags(struct dsa_switch_tree *dst)
862862
kfree(dst->lags);
863863
}
864864

865+
static void dsa_tree_teardown_routing_table(struct dsa_switch_tree *dst)
866+
{
867+
struct dsa_link *dl, *next;
868+
869+
list_for_each_entry_safe(dl, next, &dst->rtable, list) {
870+
list_del(&dl->list);
871+
kfree(dl);
872+
}
873+
}
874+
865875
static int dsa_tree_setup(struct dsa_switch_tree *dst)
866876
{
867877
bool complete;
@@ -879,7 +889,7 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst)
879889

880890
err = dsa_tree_setup_cpu_ports(dst);
881891
if (err)
882-
return err;
892+
goto teardown_rtable;
883893

884894
err = dsa_tree_setup_switches(dst);
885895
if (err)
@@ -911,14 +921,14 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst)
911921
dsa_tree_teardown_switches(dst);
912922
teardown_cpu_ports:
913923
dsa_tree_teardown_cpu_ports(dst);
924+
teardown_rtable:
925+
dsa_tree_teardown_routing_table(dst);
914926

915927
return err;
916928
}
917929

918930
static void dsa_tree_teardown(struct dsa_switch_tree *dst)
919931
{
920-
struct dsa_link *dl, *next;
921-
922932
if (!dst->setup)
923933
return;
924934

@@ -932,10 +942,7 @@ static void dsa_tree_teardown(struct dsa_switch_tree *dst)
932942

933943
dsa_tree_teardown_cpu_ports(dst);
934944

935-
list_for_each_entry_safe(dl, next, &dst->rtable, list) {
936-
list_del(&dl->list);
937-
kfree(dl);
938-
}
945+
dsa_tree_teardown_routing_table(dst);
939946

940947
pr_info("DSA: tree %d torn down\n", dst->index);
941948

@@ -1478,12 +1485,44 @@ static int dsa_switch_parse(struct dsa_switch *ds, struct dsa_chip_data *cd)
14781485

14791486
static void dsa_switch_release_ports(struct dsa_switch *ds)
14801487
{
1488+
struct dsa_mac_addr *a, *tmp;
14811489
struct dsa_port *dp, *next;
1490+
struct dsa_vlan *v, *n;
14821491

14831492
dsa_switch_for_each_port_safe(dp, next, ds) {
1484-
WARN_ON(!list_empty(&dp->fdbs));
1485-
WARN_ON(!list_empty(&dp->mdbs));
1486-
WARN_ON(!list_empty(&dp->vlans));
1493+
/* These are either entries that upper layers lost track of
1494+
* (probably due to bugs), or installed through interfaces
1495+
* where one does not necessarily have to remove them, like
1496+
* ndo_dflt_fdb_add().
1497+
*/
1498+
list_for_each_entry_safe(a, tmp, &dp->fdbs, list) {
1499+
dev_info(ds->dev,
1500+
"Cleaning up unicast address %pM vid %u from port %d\n",
1501+
a->addr, a->vid, dp->index);
1502+
list_del(&a->list);
1503+
kfree(a);
1504+
}
1505+
1506+
list_for_each_entry_safe(a, tmp, &dp->mdbs, list) {
1507+
dev_info(ds->dev,
1508+
"Cleaning up multicast address %pM vid %u from port %d\n",
1509+
a->addr, a->vid, dp->index);
1510+
list_del(&a->list);
1511+
kfree(a);
1512+
}
1513+
1514+
/* These are entries that upper layers have lost track of,
1515+
* probably due to bugs, but also due to dsa_port_do_vlan_del()
1516+
* having failed and the VLAN entry still lingering on.
1517+
*/
1518+
list_for_each_entry_safe(v, n, &dp->vlans, list) {
1519+
dev_info(ds->dev,
1520+
"Cleaning up vid %u from port %d\n",
1521+
v->vid, dp->index);
1522+
list_del(&v->list);
1523+
kfree(v);
1524+
}
1525+
14871526
list_del(&dp->list);
14881527
kfree(dp);
14891528
}

net/dsa/tag_8021q.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ static int dsa_port_do_tag_8021q_vlan_del(struct dsa_port *dp, u16 vid)
197197

198198
err = ds->ops->tag_8021q_vlan_del(ds, port, vid);
199199
if (err) {
200-
refcount_inc(&v->refcount);
200+
refcount_set(&v->refcount, 1);
201201
return err;
202202
}
203203

0 commit comments

Comments
 (0)