Message ID | 20220112102805.488510-1-maximmi@nvidia.com (mailing list archive) |
---|---|
State | Accepted |
Commit | de2d807b294d3d2ce5e59043ae2634016765d076 |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | sch_api: Don't skip qdisc attach on ingress | expand |
On Wed, Jan 12, 2022 at 2:28 AM Maxim Mikityanskiy <maximmi@nvidia.com> wrote: > > The attach callback of struct Qdisc_ops is used by only a few qdiscs: > mq, mqprio and htb. qdisc_graft() contains the following logic > (pseudocode): > > if (!qdisc->ops->attach) { > if (ingress) > do ingress stuff; > else > do egress stuff; > } > if (!ingress) { > ... > if (qdisc->ops->attach) > qdisc->ops->attach(qdisc); > } else { > ... > } > > unregister_netdevice: waiting for lo to become free. Usage count = 2 > > This commit addresses the issue by running "do ingress stuff" in the > ingress flow even in the attach callback is present, which is fine, > because attach isn't going to be called afterwards. > > The bug was found by syzbot and reported by Eric. > > Fixes: d03b195b5aa0 ("sch_htb: Hierarchical QoS hardware offload") > Signed-off-by: Maxim Mikityanskiy <maximmi@nvidia.com> > Reported-by: Eric Dumazet <edumazet@google.com> > --- Thanks for fixing this issue. Reviewed-by: Eric Dumazet <edumazet@google.com>
Hello: This patch was applied to netdev/net.git (master) by David S. Miller <davem@davemloft.net>: On Wed, 12 Jan 2022 12:28:05 +0200 you wrote: > The attach callback of struct Qdisc_ops is used by only a few qdiscs: > mq, mqprio and htb. qdisc_graft() contains the following logic > (pseudocode): > > if (!qdisc->ops->attach) { > if (ingress) > do ingress stuff; > else > do egress stuff; > } > if (!ingress) { > ... > if (qdisc->ops->attach) > qdisc->ops->attach(qdisc); > } else { > ... > } > > [...] Here is the summary with links: - sch_api: Don't skip qdisc attach on ingress https://git.kernel.org/netdev/net/c/de2d807b294d You are awesome, thank you!
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index c9c6f49f9c28..2cb496c84878 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c @@ -1062,7 +1062,7 @@ static int qdisc_graft(struct net_device *dev, struct Qdisc *parent, qdisc_offload_graft_root(dev, new, old, extack); - if (new && new->ops->attach) + if (new && new->ops->attach && !ingress) goto skip; for (i = 0; i < num_q; i++) {
The attach callback of struct Qdisc_ops is used by only a few qdiscs: mq, mqprio and htb. qdisc_graft() contains the following logic (pseudocode): if (!qdisc->ops->attach) { if (ingress) do ingress stuff; else do egress stuff; } if (!ingress) { ... if (qdisc->ops->attach) qdisc->ops->attach(qdisc); } else { ... } As we see, the attach callback is not called if the qdisc is being attached to ingress (TC_H_INGRESS). That wasn't a problem for mq and mqprio, since they contain a check that they are attached to TC_H_ROOT, and they can't be attached to TC_H_INGRESS anyway. However, the commit cited below added the attach callback to htb. It is needed for the hardware offload, but in the non-offload mode it simulates the "do egress stuff" part of the pseudocode above. The problem is that when htb is attached to ingress, neither "do ingress stuff" nor attach() is called. It results in an inconsistency, and the following message is printed to dmesg: unregister_netdevice: waiting for lo to become free. Usage count = 2 This commit addresses the issue by running "do ingress stuff" in the ingress flow even in the attach callback is present, which is fine, because attach isn't going to be called afterwards. The bug was found by syzbot and reported by Eric. Fixes: d03b195b5aa0 ("sch_htb: Hierarchical QoS hardware offload") Signed-off-by: Maxim Mikityanskiy <maximmi@nvidia.com> Reported-by: Eric Dumazet <edumazet@google.com> --- net/sched/sch_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)