Message ID | 20230210152605.1852743-1-edumazet@google.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 4fab64126891d413f207dacd5762a839b3470315 |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [net-next] net/sched: fix error recovery in qdisc_create() | expand |
On Fri, Feb 10, 2023 at 03:26:05PM +0000, Eric Dumazet wrote: > 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: 1f62879e3632 ("net/sched: make stab available before ops->init() call") > Reported-by: syzbot+d44d88f1d11e6ca8576b@syzkaller.appspotmail.com > Signed-off-by: Eric Dumazet <edumazet@google.com> > Cc: Vladimir Oltean <vladimir.oltean@nxp.com> > Cc: Kurt Kanzenbach <kurt@linutronix.de> > --- Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Hello: This patch was applied to netdev/net-next.git (master) by David S. Miller <davem@davemloft.net>: On Fri, 10 Feb 2023 15:26:05 +0000 you wrote: > 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: 1f62879e3632 ("net/sched: make stab available before ops->init() call") > Reported-by: syzbot+d44d88f1d11e6ca8576b@syzkaller.appspotmail.com > Signed-off-by: Eric Dumazet <edumazet@google.com> > Cc: Vladimir Oltean <vladimir.oltean@nxp.com> > Cc: Kurt Kanzenbach <kurt@linutronix.de> > > [...] Here is the summary with links: - [net-next] net/sched: fix error recovery in qdisc_create() https://git.kernel.org/netdev/net-next/c/4fab64126891 You are awesome, thank you!
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index e9780631b5b58202068e20c42ccf1197eac2194c..aba789c30a2eb50d339b8a888495b794825e1775 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1286,7 +1286,7 @@ static struct Qdisc *qdisc_create(struct net_device *dev, stab = qdisc_get_stab(tca[TCA_STAB], extack); if (IS_ERR(stab)) { err = PTR_ERR(stab); - goto err_out4; + goto err_out3; } rcu_assign_pointer(sch->stab, stab); } @@ -1294,14 +1294,14 @@ static struct Qdisc *qdisc_create(struct net_device *dev, if (ops->init) { err = ops->init(sch, tca[TCA_OPTIONS], extack); if (err != 0) - goto err_out5; + goto err_out4; } if (tca[TCA_RATE]) { err = -EOPNOTSUPP; if (sch->flags & TCQ_F_MQROOT) { NL_SET_ERR_MSG(extack, "Cannot attach rate estimator to a multi-queue root qdisc"); - goto err_out5; + goto err_out4; } err = gen_new_estimator(&sch->bstats, @@ -1312,7 +1312,7 @@ static struct Qdisc *qdisc_create(struct net_device *dev, tca[TCA_RATE]); if (err) { NL_SET_ERR_MSG(extack, "Failed to generate new estimator"); - goto err_out5; + goto err_out4; } } @@ -1321,12 +1321,13 @@ static struct Qdisc *qdisc_create(struct net_device *dev, return sch; -err_out5: - qdisc_put_stab(rtnl_dereference(sch->stab)); err_out4: - /* ops->init() failed, we call ->destroy() like qdisc_create_dflt() */ + /* Even if ops->init() failed, we call ops->destroy() + * like qdisc_create_dflt(). + */ if (ops->destroy) ops->destroy(sch); + qdisc_put_stab(rtnl_dereference(sch->stab)); err_out3: netdev_put(dev, &sch->dev_tracker); qdisc_free(sch);
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: 1f62879e3632 ("net/sched: make stab available before ops->init() call") Reported-by: syzbot+d44d88f1d11e6ca8576b@syzkaller.appspotmail.com Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Vladimir Oltean <vladimir.oltean@nxp.com> Cc: Kurt Kanzenbach <kurt@linutronix.de> --- net/sched/sch_api.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)