lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID:
 <CO6PR11MB5586DF80BE9D06569A79ECB2CD2DA@CO6PR11MB5586.namprd11.prod.outlook.com>
Date: Wed, 6 Aug 2025 08:29:34 +0000
From: "He, Guocai (CN)" <Guocai.He.CN@...driver.com>
To: Lion Ackermann <nnamrec@...il.com>,
        "netdev@...r.kernel.org"
	<netdev@...r.kernel.org>
CC: "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
        "ovs-discuss@...nvswitch.org" <ovs-discuss@...nvswitch.org>
Subject: [netdev] htb_qlen_notify warning triggered after
 qdisc_tree_reduce_backlog change

Dear netdev maintainers and community,

I have encountered a kernel warning in the HTB scheduler (`htb_qlen_notify` at `net/sched/sch_htb.c:609`) when using Open vSwitch (OVS) with a linux-htb QoS configuration. The issue appears related to a recent change in `qdisc_tree_reduce_backlog`.

### Environment
- Kernel version: 5.15.189-rt76-yocto-preempt-rt
- Open vSwitch version: 2.17.9
- Configuration:
  - Created a veth pair (`veth0` and `veth1`), added `veth0` to an OVS bridge (`br-test`).
  - Applied QoS with linux-htb type, total max-rate=2Mbps, two queues (queue 0: max-rate=1Mbps, queue 1: max-rate=0.5Mbps).
  - Command sequence:
    ```bash
    ip link add veth0 type veth peer name veth1
    ip link set veth0 up
    ip link set veth1 up
    ovs-vsctl add-br br-test
    ovs-vsctl add-port br-test veth0
    ip addr add 10.0.0.1/24 dev veth1
    ovs-vsctl set port veth0 qos=@...qos \
    -- --id=@...qos create qos type=linux-htb other-config:max-rate=2000000 queues=0=@q0,1=@q1 \
    -- --id=@q0 create queue other-config:min-rate=800000 other-config:max-rate=1000000 \
    -- --id=@q1 create queue other-config:min-rate=400000 other-config:max-rate=500000
    
    
### Issue
After applying the QoS configuration, the following warning appears in dmesg:
[73591.168117] WARNING: CPU: 6 PID: 61296 at net/sched/sch_htb.c:609 htb_qlen_notify+0x3a/0x40 [sch_htb]

Suspected Cause
The warning seems related to a change in qdisc_tree_reduce_backlog (/net/sched/sch_api.c)
the commit is  e269f29e9395527bc00c213c6b15da04ebb35070 (5.15)

when I revert this commit, the warning disappeared.

I dont know if it is a known issue or have fixing ?

git show e269f29e9395527bc00c213c6b15da04ebb35070
commit e269f29e9395527bc00c213c6b15da04ebb35070
Author: Lion Ackermann <nnamrec@...il.com>
Date:   Mon Jun 30 15:27:30 2025 +0200
    net/sched: Always pass notifications when child class becomes empty
    [ Upstream commit 103406b38c600fec1fe375a77b27d87e314aea09 ]
    Certain classful qdiscs may invoke their classes' dequeue handler on an
    enqueue operation. This may unexpectedly empty the child qdisc and thus
    make an in-flight class passive via qlen_notify(). Most qdiscs do not
    expect such behaviour at this point in time and may re-activate the
    class eventually anyways which will lead to a use-after-free.
..............
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index d9ce273ba43d..222921b4751f 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -768,15 +768,12 @@ static u32 qdisc_alloc_handle(struct net_device *dev)

 void qdisc_tree_reduce_backlog(struct Qdisc *sch, int n, int len)
 {
-       bool qdisc_is_offloaded = sch->flags & TCQ_F_OFFLOADED;
        const struct Qdisc_class_ops *cops;
        unsigned long cl;
        u32 parentid;
        bool notify;
        int drops;

-       if (n == 0 && len == 0)
-               return;
        drops = max_t(int, n, 0);
        rcu_read_lock();
        while ((parentid = sch->parent)) {
@@ -785,17 +782,8 @@ void qdisc_tree_reduce_backlog(struct Qdisc *sch, int n, int len)

                if (sch->flags & TCQ_F_NOPARENT)
                        break;
-               /* Notify parent qdisc only if child qdisc becomes empty.
-                *
-                * If child was empty even before update then backlog
-                * counter is screwed and we skip notification because
-                * parent class is already passive.
-                *
-                * If the original child was offloaded then it is allowed
-                * to be seem as empty, so the parent is notified anyway.
-                */
-               notify = !sch->q.qlen && !WARN_ON_ONCE(!n &&
-                                                      !qdisc_is_offloaded);
+               /* Notify parent qdisc only if child qdisc becomes empty. */
+               notify = !sch->q.qlen;
                /* TODO: perform the search on a per txq basis */
                sch = qdisc_lookup(qdisc_dev(sch), TC_H_MAJ(parentid));
                if (sch == NULL) {
@@ -804,6 +792,9 @@ void qdisc_tree_reduce_backlog(struct Qdisc *sch, int n, int len)
                }
                cops = sch->ops->cl_ops;
                if (notify && cops->qlen_notify) {
+                       /* Note that qlen_notify must be idempotent as it may get called
+                        * multiple times.
+                        */
                        cl = cops->find(sch, parentid);
                        cops->qlen_notify(sch, cl);
                }


Thanks
Guocai

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ