Netdev List
 help / color / mirror / Atom feed
* Re: Use-after-free in Linux tc subsystem (v6.15)
       [not found]           ` <CAE1YQVq=FmrGw56keHQ2gEGtrdg3H5Nf_OcPb8_Rn5NVQ4AoHg@mail.gmail.com>
@ 2025-06-28 21:26             ` Jamal Hadi Salim
  2025-06-29 21:08               ` Cong Wang
  2025-06-30 18:50               ` Victor Nogueira
  0 siblings, 2 replies; 6+ messages in thread
From: Jamal Hadi Salim @ 2025-06-28 21:26 UTC (permalink / raw)
  To: Mingi Cho
  Cc: Cong Wang, security, Jiri Pirko, Linux Kernel Network Developers

On Thu, Jun 26, 2025 at 1:11 AM Mingi Cho <mgcho.minic@gmail.com> wrote:
>
> On Fri, Jun 20, 2025 at 8:24 PM Jamal Hadi Salim <jhs@mojatatu.com> wrote:
> >
> > On Wed, Jun 18, 2025 at 4:17 PM Jamal Hadi Salim <jhs@mojatatu.com> wrote:
> > >
> > > On Mon, Jun 16, 2025 at 9:03 PM Cong Wang <xiyou.wangcong@gmail.com> wrote:
> > > >
> > > > On Sun, Jun 15, 2025 at 10:02 PM Cong Wang <xiyou.wangcong@gmail.com> wrote:
> > > > >
> > > > > On Thu, Jun 12, 2025 at 2:18 PM Cong Wang <xiyou.wangcong@gmail.com> wrote:
> > > > > >
> > > > > > Hi Mingi,
> > > > > >
> > > > > > Thanks for your report!
> > > > > >
> > > > > > I won't have time to look into this until this Sunday, if you or
> > > > > > anyone else have
> > > > > > time before that, please feel free to work on a patch. Otherwise, I will take a
> > > > > > look this Sunday.
> > > > >
> > > > > I am testing the attached patch, I will take a deeper look tomorrow.
> > > >
> > > > It is more complicated than I thought. I think we need to rollback all
> > > > the previous enqueue operations, but it does not look pretty either.
> > > >
> > > > Jamal, do you like the attached fix? I don't have any better ideas
> > > > so far. :-/
> > > >
> > >
> > > I just got back - let me look at it tomorrow. Immediate reaction is i
> > > would suspect netem
> >
> > Spent time yesterday and there are two potential approaches
> > (attached), both of which fix the issue but i am not satisfied with
> > either.
> >
> > The root cause being exploited here is there are some qdisc's whose
> > peek() drops packets - but given peek() doesnt return a code, the
> > parent is unaware of what happened.
> >
> > drr_fix.diff
> > avoids making a class active  by detecting whether drr_qlen_notify was
> > called between after enqueue (even though that enqueue succeeded), in
> > that case, returns a NET_XMIT_SUCCESS | __NET_XMIT_BYPASS which ensure
> > we don't add the class to drr.
> >
> > This fixes the UAF but it would require an analogous fix for other
> > qdiscs with similar behavior (ets, hfsc, ...)
> >
> > qfq_netem_child_fix.diff
> > piggy backs on your tbf patch and detects whether
> > qdisc_tree_reduce_backlog was called after qfq's peeked its child
> > (netem in this repro) in enqueue.
> > This would also require fixing other qdiscs.
> >
> > TBH, while both approaches fix the UAF, IMO they are short term hacks
> > and i am sure Mingi and co will find yet another way to send netlink
> > messages to config a _nonsensical hierarchy of qdiscs_ (as was this
> > one!) to create yet another UAF.
> >
> > My suggestion is we go back to a proposal i made a few moons back:
> > create a mechanism to disallow certain hierarchies of qdiscs, ex in
> > this case disallow qfq from being the ancestor of "qdiscs that may
> > drop during peek" (such as netem). Then we can just keep adding more
> > "disallowed configs" that will be rejected via netlink.
> > And TBH, i feel like obsoleting qfq altogether - the author doesnt
> > even respond to emails.
> >
> > cheers,
> > jamal
>
> Hello,
>
> I think the testcase I reported earlier actually contains two
> different bugs. The first is returning SUCCESS with an empty TBF qdisc
> in tbf_segment, and the second is returning SUCCESS with an empty QFQ
> qdisc in qfq_enqueue.
>

Please join the list where a more general solution is being discussed here:
https://lore.kernel.org/netdev/aF847kk6H+kr5kIV@pop-os.localdomain/

cheers,
jamal
> The first bug is present in TBF qdisc, so the UAF is also triggered
> when using a qdisc other than QFQ. Below is a POC that shows how the
> TBF qdisc can be made empty by using a CHOKE qdisc instead of a QFQ.
>
> #define _GNU_SOURCE
>
> #include <arpa/inet.h>
> #include <fcntl.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <linux/udp.h>
>
> #ifndef SOL_UDP
> #define SOL_UDP 17 // UDP protocol value for setsockopt
> #endif
>
> void loopback_send (uint64_t size) {
>     struct sockaddr iaddr = { AF_INET };
>     char data[0x1000] = {0,};
>
>     int inet_sock_fd = socket(PF_INET, SOCK_DGRAM, 0);
>
>     int gso_size = 1300;
>
>     setsockopt(inet_sock_fd, SOL_UDP, UDP_SEGMENT, &gso_size, sizeof(gso_size));
>
>     connect(inet_sock_fd, &iaddr, sizeof(iaddr));
>
>     write(inet_sock_fd, data, size);
>
>     close(inet_sock_fd);
> }
>
> int main(int argc, char **argv) {
>     system("ip link set dev lo up");
>     system("ip link set dev lo mtu 1500");
>
>     system("tc qdisc add dev lo root handle 1: drr");
>     system("tc filter add dev lo parent 1: basic classid 1:1");
>     system("tc class add dev lo parent 1: classid 1:1 drr");
>     system("tc class add dev lo parent 1: classid 1:2 drr");
>
>     system("tc qdisc add dev lo parent 1:1 handle 2: tbf rate 1Mbit
> burst 1514 latency 50ms");
>
>     system("tc qdisc add dev lo parent 2:1 handle 3: choke limit 2
> bandwidth 1kbit min 1 max 2 burst 1");
>
>     loopback_send(2000);
>
>     system("tc class del dev lo classid 1:1");
>
>     system("timeout 0.1 ping -c 1 -W0.01 localhost > /dev/null");
> }
>
> My opinion is that creating separate patches for each bug would be an
> easier way to approach the problem.
>
> I tested the suggested patch and found some possible issues.
>
> diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c
> index bf1282cb22eb..6d85da21c4b8 100644
> --- a/net/sched/sch_qfq.c
> +++ b/net/sched/sch_qfq.c
> @@ -1258,7 +1258,17 @@ static int qfq_enqueue(struct sk_buff *skb,
> struct Qdisc *sch,
>     agg = cl->agg;
>     /* if the class is active, then done here */
>     if (cl_is_active(cl)) {
> -       if (unlikely(skb == cl->qdisc->ops->peek(cl->qdisc)) &&
> +       const u32 pre_peek_backlog = sch->qstats.backlog;
> +
> +       skb = cl->qdisc->ops->peek(cl->qdisc);
> +       /* Address corner case where a child qdisc dropped the packet
> +        * in peek after enqueue returned success.
> +        * Qdiscs like netem may exhibit this behaviour.
> +        */
> +       if (unlikely(sch->qstats.backlog < pre_peek_backlog))
> +           return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
> +
> +       if (unlikely(skb) &&
>             list_first_entry(&agg->active, struct qfq_class, alist)
>             == cl && cl->deficit < len)
>             list_move_tail(&cl->alist, &agg->active);
>
> First, in the proposed patch, the peek function of qfq_enqueue checks
> qstats.backlog to know if a packet has been dropped. However, since
> qstats.backlog decreases during the normal peek process, it would be
> better to use the q.qlen.
>
> diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
> index c5e3673aadbe..10fb72fef98e 100644
> --- a/net/sched/sch_api.c
> +++ b/net/sched/sch_api.c
> @@ -814,6 +814,11 @@ void qdisc_tree_reduce_backlog(struct Qdisc *sch,
> int n, int len)
>             WARN_ON_ONCE(parentid != TC_H_ROOT);
>             break;
>         }
> +
> +       if (unlikely((!sch->q.qlen && n) ||
> +                (!sch->qstats.backlog && len)))
> +           continue;
> +
>         cops = sch->ops->cl_ops;
>         if (notify && cops->qlen_notify) {
>             cl = cops->find(sch, parentid);
>
> Also, if the qdisc_tree_reduce_backlog function excludes cases where
> qlen is 0, as in the above patch, the normal tbf qdisc features may
> not work.
>
> static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch,
>                struct sk_buff **to_free)
> ...
>     sch->q.qlen += nb;
>     sch->qstats.backlog += len;
>     if (nb > 0) {
>         qdisc_tree_reduce_backlog(sch, 1 - nb, prev_len - len);
>         consume_skb(skb);
>         return NET_XMIT_SUCCESS;
>     }
>
> For example, qlen can be 0 when calling qdisc_tree_reduce_backlog on
> tbf_segment in the code above.
>
> Additionally, I believe that using the peek function in the enqueue
> function can increase the complexity of qdisc and can lead to a number
> of issues. Therefore, I believe that avoiding the use of peek in the
> enqueue function will reduce the chance of introducing bugs.
>
> Thanks,
> Mingi

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Use-after-free in Linux tc subsystem (v6.15)
  2025-06-28 21:26             ` Use-after-free in Linux tc subsystem (v6.15) Jamal Hadi Salim
@ 2025-06-29 21:08               ` Cong Wang
  2025-06-30 11:06                 ` Jamal Hadi Salim
  2025-06-30 18:50               ` Victor Nogueira
  1 sibling, 1 reply; 6+ messages in thread
From: Cong Wang @ 2025-06-29 21:08 UTC (permalink / raw)
  To: Jamal Hadi Salim
  Cc: Mingi Cho, security, Jiri Pirko, Linux Kernel Network Developers

On Sat, Jun 28, 2025 at 05:26:59PM -0400, Jamal Hadi Salim wrote:
> On Thu, Jun 26, 2025 at 1:11 AM Mingi Cho <mgcho.minic@gmail.com> wrote:
> > Hello,
> >
> > I think the testcase I reported earlier actually contains two
> > different bugs. The first is returning SUCCESS with an empty TBF qdisc
> > in tbf_segment, and the second is returning SUCCESS with an empty QFQ
> > qdisc in qfq_enqueue.
> >
> 
> Please join the list where a more general solution is being discussed here:
> https://lore.kernel.org/netdev/aF847kk6H+kr5kIV@pop-os.localdomain/

I think that one is different, the one here is related to GSO, the above
linked one is not. Let me think about the GSO issue, since I already
looked into it before.

Thanks.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Use-after-free in Linux tc subsystem (v6.15)
  2025-06-29 21:08               ` Cong Wang
@ 2025-06-30 11:06                 ` Jamal Hadi Salim
  2025-06-30 11:52                   ` Victor Nogueira
  0 siblings, 1 reply; 6+ messages in thread
From: Jamal Hadi Salim @ 2025-06-30 11:06 UTC (permalink / raw)
  To: Cong Wang
  Cc: Mingi Cho, security, Jiri Pirko, Linux Kernel Network Developers

On Sun, Jun 29, 2025 at 5:08 PM Cong Wang <xiyou.wangcong@gmail.com> wrote:
>
> On Sat, Jun 28, 2025 at 05:26:59PM -0400, Jamal Hadi Salim wrote:
> > On Thu, Jun 26, 2025 at 1:11 AM Mingi Cho <mgcho.minic@gmail.com> wrote:
> > > Hello,
> > >
> > > I think the testcase I reported earlier actually contains two
> > > different bugs. The first is returning SUCCESS with an empty TBF qdisc
> > > in tbf_segment, and the second is returning SUCCESS with an empty QFQ
> > > qdisc in qfq_enqueue.
> > >
> >
> > Please join the list where a more general solution is being discussed here:
> > https://lore.kernel.org/netdev/aF847kk6H+kr5kIV@pop-os.localdomain/
>
> I think that one is different, the one here is related to GSO, the above
> linked one is not. Let me think about the GSO issue, since I already
> looked into it before.

TBH, they all look the same to me - at minimal, they should be tested
against Lion's patch first. Maybe there's a GSO corner case but wasnt
clear to me.

cheers,
jamal

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Use-after-free in Linux tc subsystem (v6.15)
  2025-06-30 11:06                 ` Jamal Hadi Salim
@ 2025-06-30 11:52                   ` Victor Nogueira
  2025-06-30 22:10                     ` Cong Wang
  0 siblings, 1 reply; 6+ messages in thread
From: Victor Nogueira @ 2025-06-30 11:52 UTC (permalink / raw)
  To: Jamal Hadi Salim, Cong Wang
  Cc: Mingi Cho, security, Jiri Pirko, Linux Kernel Network Developers

On 6/30/25 08:06, Jamal Hadi Salim wrote:
> On Sun, Jun 29, 2025 at 5:08 PM Cong Wang <xiyou.wangcong@gmail.com> wrote:
>>
>> On Sat, Jun 28, 2025 at 05:26:59PM -0400, Jamal Hadi Salim wrote:
>>> On Thu, Jun 26, 2025 at 1:11 AM Mingi Cho <mgcho.minic@gmail.com> wrote:
>>>> Hello,
>>>>
>>>> I think the testcase I reported earlier actually contains two
>>>> different bugs. The first is returning SUCCESS with an empty TBF qdisc
>>>> in tbf_segment, and the second is returning SUCCESS with an empty QFQ
>>>> qdisc in qfq_enqueue.
>>>>
>>>
>>> Please join the list where a more general solution is being discussed here:
>>> https://lore.kernel.org/netdev/aF847kk6H+kr5kIV@pop-os.localdomain/
>>
>> I think that one is different, the one here is related to GSO, the above
>> linked one is not. Let me think about the GSO issue, since I already
>> looked into it before.
> 
> TBH, they all look the same to me - at minimal, they should be tested
> against Lion's patch first. Maybe there's a GSO corner case but wasnt
> clear to me.

I did a quick test of Lion's patch using Mingi's C reproducer.
The patch seems to fix the UAF.

cheers,
Victor

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Use-after-free in Linux tc subsystem (v6.15)
  2025-06-28 21:26             ` Use-after-free in Linux tc subsystem (v6.15) Jamal Hadi Salim
  2025-06-29 21:08               ` Cong Wang
@ 2025-06-30 18:50               ` Victor Nogueira
  1 sibling, 0 replies; 6+ messages in thread
From: Victor Nogueira @ 2025-06-30 18:50 UTC (permalink / raw)
  To: Jamal Hadi Salim, Mingi Cho
  Cc: Cong Wang, security, Jiri Pirko, Linux Kernel Network Developers

> On Thu, Jun 26, 2025 at 1:11 AM Mingi Cho <mgcho.minic@gmail.com> wrote:
>>
>> On Fri, Jun 20, 2025 at 8:24 PM Jamal Hadi Salim <jhs@mojatatu.com> wrote:
>>>
>>> On Wed, Jun 18, 2025 at 4:17 PM Jamal Hadi Salim <jhs@mojatatu.com> wrote:
>>>>
>>>> On Mon, Jun 16, 2025 at 9:03 PM Cong Wang <xiyou.wangcong@gmail.com> wrote:
>>>>>
>>>>> On Sun, Jun 15, 2025 at 10:02 PM Cong Wang <xiyou.wangcong@gmail.com> wrote:
>>>>>>
>>>>>> On Thu, Jun 12, 2025 at 2:18 PM Cong Wang <xiyou.wangcong@gmail.com> wrote:
>>>>>>>
>>>>>>> Hi Mingi,
>>>>>>>
>>>>>>> Thanks for your report!
>>>>>>>
>>>>>>> I won't have time to look into this until this Sunday, if you or
>>>>>>> anyone else have
>>>>>>> time before that, please feel free to work on a patch. Otherwise, I will take a
>>>>>>> look this Sunday.
>>>>>>
>>>>>> I am testing the attached patch, I will take a deeper look tomorrow.
>>>>>
>>>>> It is more complicated than I thought. I think we need to rollback all
>>>>> the previous enqueue operations, but it does not look pretty either.
>>>>>
>>>>> Jamal, do you like the attached fix? I don't have any better ideas
>>>>> so far. :-/
>>>>>
>>>>
>>>> I just got back - let me look at it tomorrow. Immediate reaction is i
>>>> would suspect netem
>>>
>>> Spent time yesterday and there are two potential approaches
>>> (attached), both of which fix the issue but i am not satisfied with
>>> either.
>>>
>>> The root cause being exploited here is there are some qdisc's whose
>>> peek() drops packets - but given peek() doesnt return a code, the
>>> parent is unaware of what happened.
>>>
>>> drr_fix.diff
>>> avoids making a class active  by detecting whether drr_qlen_notify was
>>> called between after enqueue (even though that enqueue succeeded), in
>>> that case, returns a NET_XMIT_SUCCESS | __NET_XMIT_BYPASS which ensure
>>> we don't add the class to drr.
>>>
>>> This fixes the UAF but it would require an analogous fix for other
>>> qdiscs with similar behavior (ets, hfsc, ...)
>>>
>>> qfq_netem_child_fix.diff
>>> piggy backs on your tbf patch and detects whether
>>> qdisc_tree_reduce_backlog was called after qfq's peeked its child
>>> (netem in this repro) in enqueue.
>>> This would also require fixing other qdiscs.
>>>
>>> TBH, while both approaches fix the UAF, IMO they are short term hacks
>>> and i am sure Mingi and co will find yet another way to send netlink
>>> messages to config a _nonsensical hierarchy of qdiscs_ (as was this
>>> one!) to create yet another UAF.
>>>
>>> My suggestion is we go back to a proposal i made a few moons back:
>>> create a mechanism to disallow certain hierarchies of qdiscs, ex in
>>> this case disallow qfq from being the ancestor of "qdiscs that may
>>> drop during peek" (such as netem). Then we can just keep adding more
>>> "disallowed configs" that will be rejected via netlink.
>>> And TBH, i feel like obsoleting qfq altogether - the author doesnt
>>> even respond to emails.
>>>
>>> cheers,
>>> jamal
>>
>> Hello,
>>
>> I think the testcase I reported earlier actually contains two
>> different bugs. The first is returning SUCCESS with an empty TBF qdisc
>> in tbf_segment, and the second is returning SUCCESS with an empty QFQ
>> qdisc in qfq_enqueue.

Mingi, can you create a selftest for the drr UAF case with a qfq child
that you reproduced? Since you required setsockopt for creating GSO
packets, I don't believe you'll be able to use tdc for this.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Use-after-free in Linux tc subsystem (v6.15)
  2025-06-30 11:52                   ` Victor Nogueira
@ 2025-06-30 22:10                     ` Cong Wang
  0 siblings, 0 replies; 6+ messages in thread
From: Cong Wang @ 2025-06-30 22:10 UTC (permalink / raw)
  To: Victor Nogueira
  Cc: Jamal Hadi Salim, Mingi Cho, security, Jiri Pirko,
	Linux Kernel Network Developers

On Mon, Jun 30, 2025 at 08:52:22AM -0300, Victor Nogueira wrote:
> On 6/30/25 08:06, Jamal Hadi Salim wrote:
> > On Sun, Jun 29, 2025 at 5:08 PM Cong Wang <xiyou.wangcong@gmail.com> wrote:
> > > 
> > > On Sat, Jun 28, 2025 at 05:26:59PM -0400, Jamal Hadi Salim wrote:
> > > > On Thu, Jun 26, 2025 at 1:11 AM Mingi Cho <mgcho.minic@gmail.com> wrote:
> > > > > Hello,
> > > > > 
> > > > > I think the testcase I reported earlier actually contains two
> > > > > different bugs. The first is returning SUCCESS with an empty TBF qdisc
> > > > > in tbf_segment, and the second is returning SUCCESS with an empty QFQ
> > > > > qdisc in qfq_enqueue.
> > > > > 
> > > > 
> > > > Please join the list where a more general solution is being discussed here:
> > > > https://lore.kernel.org/netdev/aF847kk6H+kr5kIV@pop-os.localdomain/
> > > 
> > > I think that one is different, the one here is related to GSO, the above
> > > linked one is not. Let me think about the GSO issue, since I already
> > > looked into it before.
> > 
> > TBH, they all look the same to me - at minimal, they should be tested
> > against Lion's patch first. Maybe there's a GSO corner case but wasnt
> > clear to me.
> 
> I did a quick test of Lion's patch using Mingi's C reproducer.
> The patch seems to fix the UAF.

Good finding! I think Mingi's reproducer still exploits the
->qlen_notify() refcnt to expose issues, but the GSO segmentation itself
is also problematic even without ->qlen_notify(), IMHO.

I have an elegant solution to move the skb_gso_segment() to the upper
layer so that child Qdisc's don't need to handle GSO segmentation any
more. It fixes the UAF too, without Lion's patch.

I will wait for Mingi's response to see if I should submit it for -net
as a bug fix, or -net-next as code refactoring.

Thanks!

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-06-30 22:11 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <CAE1YQVoTz5REkvZWzq_X5f31Sr6NzutVCxxmLfWtmVZkjiingA@mail.gmail.com>
     [not found] ` <CAM_iQpV8NpK_L2_697NccDPfb9SPYhQ7BT1Ssueh7nT-rRKJRA@mail.gmail.com>
     [not found]   ` <CAM_iQpXVaxTVALH9_Lki+O=1cMaVx4uQhcRvi4VcS2rEdYkj5Q@mail.gmail.com>
     [not found]     ` <CAM_iQpVi0V7DNQFiNWWMr+crM-1EFbnvWV5_L-aOkFsKaA3JBQ@mail.gmail.com>
     [not found]       ` <CAM0EoMm4D+q1eLzfKw3gKbQF43GzpBcDFY3w2k2OmtohJn=aJw@mail.gmail.com>
     [not found]         ` <CAM0EoMkFzD0gKfJM2-Dtgv6qQ8mjGRFmWF7+oe=qGgBEkVSimg@mail.gmail.com>
     [not found]           ` <CAE1YQVq=FmrGw56keHQ2gEGtrdg3H5Nf_OcPb8_Rn5NVQ4AoHg@mail.gmail.com>
2025-06-28 21:26             ` Use-after-free in Linux tc subsystem (v6.15) Jamal Hadi Salim
2025-06-29 21:08               ` Cong Wang
2025-06-30 11:06                 ` Jamal Hadi Salim
2025-06-30 11:52                   ` Victor Nogueira
2025-06-30 22:10                     ` Cong Wang
2025-06-30 18:50               ` Victor Nogueira

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox