Skip to content

Commit 4fab641

Browse files
edumazetdavem330
authored andcommitted
net/sched: fix error recovery in qdisc_create()
If TCA_STAB attribute is malformed, qdisc_get_stab() returns an error, and we end up calling ops->destroy() while ops->init() has not been called yet. While we are at it, call qdisc_put_stab() after ops->destroy(). Fixes: 1f62879 ("net/sched: make stab available before ops->init() call") Reported-by: [email protected] Signed-off-by: Eric Dumazet <[email protected]> Cc: Vladimir Oltean <[email protected]> Cc: Kurt Kanzenbach <[email protected]> Reviewed-by: Vladimir Oltean <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent cafc366 commit 4fab641

File tree

1 file changed

+8
-7
lines changed

1 file changed

+8
-7
lines changed

net/sched/sch_api.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,22 +1286,22 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
12861286
stab = qdisc_get_stab(tca[TCA_STAB], extack);
12871287
if (IS_ERR(stab)) {
12881288
err = PTR_ERR(stab);
1289-
goto err_out4;
1289+
goto err_out3;
12901290
}
12911291
rcu_assign_pointer(sch->stab, stab);
12921292
}
12931293

12941294
if (ops->init) {
12951295
err = ops->init(sch, tca[TCA_OPTIONS], extack);
12961296
if (err != 0)
1297-
goto err_out5;
1297+
goto err_out4;
12981298
}
12991299

13001300
if (tca[TCA_RATE]) {
13011301
err = -EOPNOTSUPP;
13021302
if (sch->flags & TCQ_F_MQROOT) {
13031303
NL_SET_ERR_MSG(extack, "Cannot attach rate estimator to a multi-queue root qdisc");
1304-
goto err_out5;
1304+
goto err_out4;
13051305
}
13061306

13071307
err = gen_new_estimator(&sch->bstats,
@@ -1312,7 +1312,7 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
13121312
tca[TCA_RATE]);
13131313
if (err) {
13141314
NL_SET_ERR_MSG(extack, "Failed to generate new estimator");
1315-
goto err_out5;
1315+
goto err_out4;
13161316
}
13171317
}
13181318

@@ -1321,12 +1321,13 @@ static struct Qdisc *qdisc_create(struct net_device *dev,
13211321

13221322
return sch;
13231323

1324-
err_out5:
1325-
qdisc_put_stab(rtnl_dereference(sch->stab));
13261324
err_out4:
1327-
/* ops->init() failed, we call ->destroy() like qdisc_create_dflt() */
1325+
/* Even if ops->init() failed, we call ops->destroy()
1326+
* like qdisc_create_dflt().
1327+
*/
13281328
if (ops->destroy)
13291329
ops->destroy(sch);
1330+
qdisc_put_stab(rtnl_dereference(sch->stab));
13301331
err_out3:
13311332
netdev_put(dev, &sch->dev_tracker);
13321333
qdisc_free(sch);

0 commit comments

Comments
 (0)