Skip to content

Commit a0527ee

Browse files
Stanislav Fomichevkuba-moo
Stanislav Fomichev
authored andcommitted
net: hold netdev instance lock during qdisc ndo_setup_tc
Qdisc operations that can lead to ndo_setup_tc might need to have an instance lock. Add netdev_lock_ops/netdev_unlock_ops invocations for all psched_rtnl_msg_handlers operations. Cc: Cong Wang <[email protected]> Cc: Jiri Pirko <[email protected]> Cc: Saeed Mahameed <[email protected]> Reviewed-by: Jamal Hadi Salim <[email protected]> Signed-off-by: Stanislav Fomichev <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 7c79cff commit a0527ee

File tree

1 file changed

+24
-4
lines changed

1 file changed

+24
-4
lines changed

net/sched/sch_api.c

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,9 +1279,11 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
12791279
* We replay the request because the device may
12801280
* go away in the mean time.
12811281
*/
1282+
netdev_unlock_ops(dev);
12821283
rtnl_unlock();
12831284
request_module(NET_SCH_ALIAS_PREFIX "%s", name);
12841285
rtnl_lock();
1286+
netdev_lock_ops(dev);
12851287
ops = qdisc_lookup_ops(kind);
12861288
if (ops != NULL) {
12871289
/* We will try again qdisc_lookup_ops,
@@ -1591,7 +1593,11 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
15911593
if (!dev)
15921594
return -ENODEV;
15931595

1594-
return __tc_get_qdisc(skb, n, extack, dev, tca, tcm);
1596+
netdev_lock_ops(dev);
1597+
err = __tc_get_qdisc(skb, n, extack, dev, tca, tcm);
1598+
netdev_unlock_ops(dev);
1599+
1600+
return err;
15951601
}
15961602

15971603
static bool req_create_or_replace(struct nlmsghdr *n)
@@ -1828,7 +1834,9 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
18281834
return -ENODEV;
18291835

18301836
replay = false;
1837+
netdev_lock_ops(dev);
18311838
err = __tc_modify_qdisc(skb, n, extack, dev, tca, tcm, &replay);
1839+
netdev_unlock_ops(dev);
18321840
if (replay)
18331841
goto replay;
18341842

@@ -1919,17 +1927,23 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb)
19191927
s_q_idx = 0;
19201928
q_idx = 0;
19211929

1930+
netdev_lock_ops(dev);
19221931
if (tc_dump_qdisc_root(rtnl_dereference(dev->qdisc),
19231932
skb, cb, &q_idx, s_q_idx,
1924-
true, tca[TCA_DUMP_INVISIBLE]) < 0)
1933+
true, tca[TCA_DUMP_INVISIBLE]) < 0) {
1934+
netdev_unlock_ops(dev);
19251935
goto done;
1936+
}
19261937

19271938
dev_queue = dev_ingress_queue(dev);
19281939
if (dev_queue &&
19291940
tc_dump_qdisc_root(rtnl_dereference(dev_queue->qdisc_sleeping),
19301941
skb, cb, &q_idx, s_q_idx, false,
1931-
tca[TCA_DUMP_INVISIBLE]) < 0)
1942+
tca[TCA_DUMP_INVISIBLE]) < 0) {
1943+
netdev_unlock_ops(dev);
19321944
goto done;
1945+
}
1946+
netdev_unlock_ops(dev);
19331947

19341948
cont:
19351949
idx++;
@@ -2308,7 +2322,11 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n,
23082322
if (!dev)
23092323
return -ENODEV;
23102324

2311-
return __tc_ctl_tclass(skb, n, extack, dev, tca, tcm);
2325+
netdev_lock_ops(dev);
2326+
err = __tc_ctl_tclass(skb, n, extack, dev, tca, tcm);
2327+
netdev_unlock_ops(dev);
2328+
2329+
return err;
23122330
}
23132331

23142332
struct qdisc_dump_args {
@@ -2426,7 +2444,9 @@ static int tc_dump_tclass(struct sk_buff *skb, struct netlink_callback *cb)
24262444
if (!dev)
24272445
return 0;
24282446

2447+
netdev_lock_ops(dev);
24292448
err = __tc_dump_tclass(skb, cb, tcm, dev);
2449+
netdev_unlock_ops(dev);
24302450

24312451
dev_put(dev);
24322452

0 commit comments

Comments
 (0)