Skip to content

Commit 28a23bb

Browse files
Stanislav FomichevNipaLocal
Stanislav Fomichev
authored and
NipaLocal
committed
net: don't relock netdev when on qdisc_create replay
Eric reports that by the time we call netdev_lock_ops after rtnl_unlock/rtnl_lock, the dev might point to an invalid device. Don't relock the device after request_module and don't try to unlock it in the caller (tc_modify_qdisc) in case of replay. Fixes: a0527ee ("net: hold netdev instance lock during qdisc ndo_setup_tc") Reported-by: Eric Dumazet <[email protected]> Link: https://lore.kernel.org/netdev/[email protected]/T/#me8dfd778ea4c4463acab55644e3f9836bc608771 Signed-off-by: Stanislav Fomichev <[email protected]> Signed-off-by: NipaLocal <nipa@local>
1 parent ac1b78b commit 28a23bb

File tree

1 file changed

+5
-3
lines changed

1 file changed

+5
-3
lines changed

net/sched/sch_api.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,13 +1278,14 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
12781278
* tell the caller to replay the request. We
12791279
* indicate this using -EAGAIN.
12801280
* We replay the request because the device may
1281-
* go away in the mean time.
1281+
* go away in the mean time. Note that we also
1282+
* don't relock the device because it might
1283+
* be gone at this point.
12821284
*/
12831285
netdev_unlock_ops(dev);
12841286
rtnl_unlock();
12851287
request_module(NET_SCH_ALIAS_PREFIX "%s", name);
12861288
rtnl_lock();
1287-
netdev_lock_ops(dev);
12881289
ops = qdisc_lookup_ops(kind);
12891290
if (ops != NULL) {
12901291
/* We will try again qdisc_lookup_ops,
@@ -1837,9 +1838,10 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
18371838
replay = false;
18381839
netdev_lock_ops(dev);
18391840
err = __tc_modify_qdisc(skb, n, extack, dev, tca, tcm, &replay);
1840-
netdev_unlock_ops(dev);
1841+
/* __tc_modify_qdisc returns with unlocked dev in case of replay */
18411842
if (replay)
18421843
goto replay;
1844+
netdev_unlock_ops(dev);
18431845

18441846
return err;
18451847
}

0 commit comments

Comments
 (0)