Re: [PATCH] net/sched: sch_qfq: prevent aggregate self-replacement

From: Jamal Hadi Salim

Date: Fri Oct 23 2026 - 14:13:20 EST


On Fri, Oct 23, 2026 at 11:45 AM David Lee <david.lee@xxxxxxxxxxxxxxx> wrote:
>
> Hi Jamal,
>
> I reproduced the issue on upstream Linux at commit
> 734bef548a96e8774d6eef5dfa2026c6edc4e80b using the original PoC,
> confirming that it is still present at that revision.
>
> I've attached the KASAN log, the PoC, reproduction steps, and the bug report.
>
> For reference, the original patch thread is:
> https://lore.kernel.org/netdev/20260731140533.566493-1-david.lee@xxxxxxxxxxxxxxx/
>

Thanks for persevering David - i have queued it to look at - so it
wont be lost this time.

cheers,
jamal
> Best regards,
> David
>
>
> On Thu, 22 Oct 2026 05:14:38 -0400, Jamal Hadi Salim <jhs@xxxxxxxxxxxx> wrote:
> > On Wed, Oct 21, 2026 at 10:56 AM David Lee <david.lee@xxxxxxxxxxxxxxx> wrote:
> > >
> > > Hi Jamal,
> > >
> > > Following up on this thread. Please let me know if you had a chance to review the attached reproducer or if you need any additional information.
> > >
> >
> > Please resend to the list - I lost track.
> > And if you follow up after like 2 months(!) you will really have to
> > retest with the new kernel and likely look at the list to see if there
> > are other fixes that cover this issue.
> >
> >
> > cheers,
> > jamal
> >
> > > Best regards,
> > >
> > >
> > >
> > > On Mon, Aug 10, 2026 at 11:22 AM David Lee <david.lee@xxxxxxxxxxxxxxx> wrote:
> > >>
> > >> Hi Jamal,
> > >>
> > >> Reproducer has been attached to this email.
> > >>
> > >> ========== Reproduction ==========
> > >>
> > >> 1. Build Linux at 82a47586c0b9266622657009aa30573dddf09f53
> > >> with the configuration options listed above and KASAN enabled.
> > >> Use a system with at least two CPUs. If QFQ is configured as a
> > >> module, make sch_qfq available before running the reproducer.
> > >>
> > >> 2. Build the attached poc.c:
> > >>
> > >> ~
> > >> gcc -static -O2 -pthread -Wall -Wextra -o poc poc.c
> > >> ~
> > >>
> > >> 3. Run the resulting binary:
> > >>
> > >> ~
> > >> ./poc
> > >> ~
> > >>
> > >> The reproducer creates user and network namespaces, brings up the
> > >> loopback device, installs a QFQ qdisc and class, and races class
> > >> changes against packet enqueue. Race timing varies between systems.
> > >> On the validated KASAN kernel, the expected result is a
> > >> slab-use-after-free report in qfq_add_to_agg(), followed by a kernel
> > >> panic. The full observed output is attached as splash.txt.
> > >>
> > >> he issue was reproduced on Linux 7.2-rc3 at:
> > >>
> > >> 82a47586c0b9266622657009aa30573dddf09f53
> > >>
> > >> It is also present in Linux 7.2-rc5 at:
> > >>
> > >> f5098b6bae761e346ebcd9da7f95622c04733cff
> > >>
> > >> As of July 27, 2026, the vulnerable sequence remains in upstream
> > >> master at:
> > >>
> > >> 62cc90241548d5570ee68e01aaba6506964e9811
> > >> https://github.com/torvalds/linux/commit/62cc90241548d5570ee68e01aaba6506964e9811
> > >>
> > >> Required configuration:
> > >>
> > >> * CONFIG_NET_SCHED
> > >> * CONFIG_NET_SCH_QFQ
> > >>
> > >> The attached reproducer additionally requires:
> > >>
> > >> * CONFIG_USER_NS
> > >> * CONFIG_NET_NS
> > >> * CONFIG_INET
> > >>
> > >> KASAN is recommended to observe the first invalid access.
> > >>
> > >> Regarding the format, I can send v2 if the reproducer looks good on your end.
> > >>
> > >> Thank you.
> > >>
> > >> Best regards,
> > >> David
> > >>
> > >> On Fri, Jul 31, 2026 at 12:33 PM Jamal Hadi Salim <jhs@xxxxxxxxxxxx> wrote:
> > >>>
> > >>> On Fri, Jul 31, 2026 at 10:05 AM David Lee <david.lee@xxxxxxxxxxxxxxx> wrote:
> > >>> >
> > >>> > qfq_change_class() snapshots the current aggregate settings while
> > >>> > holding the qdisc tree lock, but drops the lock before selecting the
> > >>> > destination aggregate. During that gap, qfq_enqueue() can move the
> > >>> > class to an aggregate matching the requested settings.
> > >>> >
> > >>> > When qfq_change_class() resumes, qfq_find_agg() then returns cl->agg.
> > >>> > If it is a singleton, qfq_deact_rm_from_agg() frees the aggregate
> > >>> > before qfq_add_to_agg() immediately accesses the same pointer, causing
> > >>> > a use-after-free.
> > >>> >
> > >>> > While holding the tree lock, skip the replacement when the destination
> > >>> > is already the current aggregate. Any estimator replacement has already
> > >>> > completed, so the class change can finish normally.
> > >>> >
> > >>> > Fixes: 462dbc9101ac ("pkt_sched: QFQ Plus: fair-queueing service at DRR cost")
> > >>> > Bug found and triaged by OpenAI Security Research and
> > >>> > validated by Trail of Bits.
> > >>> >
> > >>>
> > >>> Please always send a reproducer - either as a tdc test case or if it
> > >>> is sensitive send it privately to me and Cc the other maintainers.
> > >>> As trivial as this looks I will not look at it without a repro.
> > >>>
> > >>> cheers,
> > >>> jamal
> > >>>
> > >>> > Assisted-by: Codex:gpt-5.6-sol gpt-5.5-cyber
> > >>> > Signed-off-by: Kyle Zeng <kylebot@xxxxxxxxxx>
> > >>> > ---
> > >>> > Trail of Bits has a reproducer for this bug that triggers a
> > >>> > KASAN use-after-free and can share if needed.
> > >>> >
> > >>> > net/sched/sch_qfq.c | 3 +++
> > >>> > 1 file changed, 3 insertions(+)
> > >>> >
> > >>> > diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
> > >>> > index 6f3b7273c..e900890e9 100644
> > >>> > --- a/net/sched/sch_qfq.c
> > >>> > +++ b/net/sched/sch_qfq.c
> > >>> > @@ -517,11 +517,14 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
> > >>> > sch_tree_lock(sch);
> > >>> > qfq_init_agg(q, new_agg, lmax, weight);
> > >>> > }
> > >>> > + if (existing && new_agg == cl->agg)
> > >>> > + goto unlock;
> > >>> > if (existing)
> > >>> > qfq_deact_rm_from_agg(q, cl);
> > >>> > else
> > >>> > qdisc_class_hash_insert(&q->clhash, &cl->common);
> > >>> > qfq_add_to_agg(q, new_agg, cl);
> > >>> > +unlock:
> > >>> > sch_tree_unlock(sch);
> > >>> > qdisc_class_hash_grow(sch, &q->clhash);
> > >>> >
> > >>> > --
> > >>> > 2.53.0
> > >
> > >
> > >
> > > --
> > > David Lee
> > > Security Engineer I, Application Security | Trail of Bits
> > > trailofbits.com