Skip to content

[fips-legacy-8] net/sched: sch_qfq: account for stab overhead in qfq_enqueue #320

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

bmastbergen
Copy link
Collaborator

jira VULN-8822
cve CVE-2023-3611

commit-author Pedro Tammela <pctammela@mojatatu.com> commit 3e337087c3b5805fe0b8a46ba622a962880b5d64
upstream-diff used linux-stable LT-4.19 sha ee3bc829f9b4df96d208d58b654e400fa1f3b46c

commit 3e337087c3b5805fe0b8a46ba622a962880b5d64 upstream.

Lion says:
-------
In the QFQ scheduler a similar issue to CVE-2023-31436 persists.

Consider the following code in net/sched/sch_qfq.c:

static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                struct sk_buff **to_free)
{
     unsigned int len = qdisc_pkt_len(skb), gso_segs;

    // ...

     if (unlikely(cl->agg->lmax < len)) {
         pr_debug("qfq: increasing maxpkt from %u to %u for class %u",
              cl->agg->lmax, len, cl->common.classid);
         err = qfq_change_agg(sch, cl, cl->agg->class_weight, len);
         if (err) {
             cl->qstats.drops++;
             return qdisc_drop(skb, sch, to_free);
         }

    // ...

     }

Similarly to CVE-2023-31436, "lmax" is increased without any bounds checks according to the packet length "len". Usually this would not impose a problem because packet sizes are naturally limited.

This is however not the actual packet length, rather the "qdisc_pkt_len(skb)" which might apply size transformations according to "struct qdisc_size_table" as created by "qdisc_get_stab()" in net/sched/sch_api.c if the TCA_STAB option was set when modifying the qdisc.

A user may choose virtually any size using such a table.

As a result the same issue as in CVE-2023-31436 can occur, allowing heap out-of-bounds read / writes in the kmalloc-8192 cache. -------

We can create the issue with the following commands:

tc qdisc add dev $DEV root handle 1: stab mtu 2048 tsize 512 mpu 0 \ overhead 999999999 linklayer ethernet qfq
tc class add dev $DEV parent 1: classid 1:1 htb rate 6mbit burst 15k tc filter add dev $DEV parent 1: matchall classid 1:1 ping -I $DEV 1.1.1.2

This is caused by incorrectly assuming that qdisc_pkt_len() returns a length within the QFQ_MIN_LMAX < len < QFQ_MAX_LMAX.

Fixes: 462dbc9101ac ("pkt_sched: QFQ Plus: fair-queueing service at DRR cost")
	Reported-by: Lion <nnamrec@gmail.com>
	Reviewed-by: Eric Dumazet <edumazet@google.com>
	Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
	Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
	Reviewed-by: Simon Horman <simon.horman@corigine.com>
	Signed-off-by: Paolo Abeni <pabeni@redhat.com>
	Signed-off-by: Shaoying Xu <shaoyi@amazon.com>
	Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit ee3bc829f9b4df96d208d58b654e400fa1f3b46c)
	Signed-off-by: Brett Mastbergen <bmastbergen@ciq.com>

Build Log

/home/brett/kernel-src-tree
no .config file found, moving on
[TIMER]{MRPROPER}: 0s
x86_64 architecture detected, copying config
'configs/kernel-x86_64.config' -> '.config'
Setting Local Version for build
CONFIG_LOCALVERSION="-b_f-l-8-c_4.18.0-425.13.1_VULN-8822-bb3f6e35c82b"
Making olddefconfig
--
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf  --olddefconfig Kconfig
#
# configuration written to .config
#
Starting Build
scripts/kconfig/conf  --syncconfig Kconfig
  SYSTBL  arch/x86/include/generated/asm/syscalls_32.h
  SYSHDR  arch/x86/include/generated/asm/unistd_32_ia32.h
  SYSHDR  arch/x86/include/generated/asm/unistd_64_x32.h
  SYSTBL  arch/x86/include/generated/asm/syscalls_64.h
--
  LD [M]  sound/usb/usx2y/snd-usb-usx2y.ko
  LD [M]  sound/x86/snd-hdmi-lpe-audio.ko
  LD [M]  sound/xen/snd_xen_front.ko
  LD [M]  sound/virtio/virtio_snd.ko
  LD [M]  virt/lib/irqbypass.ko
[TIMER]{BUILD}: 1019s
Making Modules
  INSTALL arch/x86/crypto/blowfish-x86_64.ko
  INSTALL arch/x86/crypto/camellia-aesni-avx-x86_64.ko
  INSTALL arch/x86/crypto/camellia-aesni-avx2.ko
  INSTALL arch/x86/crypto/camellia-x86_64.ko
--
  INSTALL sound/virtio/virtio_snd.ko
  INSTALL sound/x86/snd-hdmi-lpe-audio.ko
  INSTALL sound/xen/snd_xen_front.ko
  INSTALL virt/lib/irqbypass.ko
  DEPMOD  4.18.0-b_f-l-8-c_4.18.0-425.13.1_VULN-8822-bb3f6e35c82b+
[TIMER]{MODULES}: 13s
Making Install
sh ./arch/x86/boot/install.sh 4.18.0-b_f-l-8-c_4.18.0-425.13.1_VULN-8822-bb3f6e35c82b+ arch/x86/boot/bzImage \
	System.map "/boot"
[TIMER]{INSTALL}: 62s
Checking kABI
Checking kABI
kABI check passed
Setting Default Kernel to /boot/vmlinuz-4.18.0-b_f-l-8-c_4.18.0-425.13.1_VULN-8822-bb3f6e35c82b+ and Index to 0
Hopefully Grub2.0 took everything ... rebooting after time metrices
[TIMER]{MRPROPER}: 0s
[TIMER]{BUILD}: 1019s
[TIMER]{MODULES}: 13s
[TIMER]{INSTALL}: 62s
[TIMER]{TOTAL} 1109s
Rebooting in 10 seconds

Testing

kselftests were run before and after applying the change

selftest-4.18.0-425.13.1.el8.ciqfipscompliant.39.1.x86_64.log

selftest-4.18.0-b_f-l-8-c_4.18.0-425.13.1_VULN-8822-bb3f6e35c82b+.log

brett@lycia ~/ciq/vuln-8822 % grep ^ok selftest-4.18.0-425.13.1.el8.ciqfipscompliant.39.1.x86_64.log | wc -l
229
brett@lycia ~/ciq/vuln-8822 % grep ^ok selftest-4.18.0-b_f-l-8-c_4.18.0-425.13.1_VULN-8822-bb3f6e35c82b+.log | wc -l
227
brett@lycia ~/ciq/vuln-8822 %

jira VULN-8822
cve CVE-2023-3611
commit-author Pedro Tammela <pctammela@mojatatu.com>
commit 3e33708
upstream-diff used linux-stable LT-4.19 sha ee3bc82

commit 3e33708 upstream.

Lion says:
-------
In the QFQ scheduler a similar issue to CVE-2023-31436
persists.

Consider the following code in net/sched/sch_qfq.c:

static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                struct sk_buff **to_free)
{
     unsigned int len = qdisc_pkt_len(skb), gso_segs;

    // ...

     if (unlikely(cl->agg->lmax < len)) {
         pr_debug("qfq: increasing maxpkt from %u to %u for class %u",
              cl->agg->lmax, len, cl->common.classid);
         err = qfq_change_agg(sch, cl, cl->agg->class_weight, len);
         if (err) {
             cl->qstats.drops++;
             return qdisc_drop(skb, sch, to_free);
         }

    // ...

     }

Similarly to CVE-2023-31436, "lmax" is increased without any bounds
checks according to the packet length "len". Usually this would not
impose a problem because packet sizes are naturally limited.

This is however not the actual packet length, rather the
"qdisc_pkt_len(skb)" which might apply size transformations according to
"struct qdisc_size_table" as created by "qdisc_get_stab()" in
net/sched/sch_api.c if the TCA_STAB option was set when modifying the qdisc.

A user may choose virtually any size using such a table.

As a result the same issue as in CVE-2023-31436 can occur, allowing heap
out-of-bounds read / writes in the kmalloc-8192 cache.
-------

We can create the issue with the following commands:

tc qdisc add dev $DEV root handle 1: stab mtu 2048 tsize 512 mpu 0 \
overhead 999999999 linklayer ethernet qfq
tc class add dev $DEV parent 1: classid 1:1 htb rate 6mbit burst 15k
tc filter add dev $DEV parent 1: matchall classid 1:1
ping -I $DEV 1.1.1.2

This is caused by incorrectly assuming that qdisc_pkt_len() returns a
length within the QFQ_MIN_LMAX < len < QFQ_MAX_LMAX.

Fixes: 462dbc9 ("pkt_sched: QFQ Plus: fair-queueing service at DRR cost")
	Reported-by: Lion <nnamrec@gmail.com>
	Reviewed-by: Eric Dumazet <edumazet@google.com>
	Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
	Signed-off-by: Pedro Tammela <pctammela@mojatatu.com>
	Reviewed-by: Simon Horman <simon.horman@corigine.com>
	Signed-off-by: Paolo Abeni <pabeni@redhat.com>
	Signed-off-by: Shaoying Xu <shaoyi@amazon.com>
	Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit ee3bc82)
	Signed-off-by: Brett Mastbergen <bmastbergen@ciq.com>
Copy link

@thefossguy-ciq thefossguy-ciq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚤

Copy link
Collaborator

@PlaidCat PlaidCat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@bmastbergen bmastbergen merged commit f45f022 into fips-legacy-8-compliant/4.18.0-425.13.1 Jun 6, 2025
1 check passed
@bmastbergen bmastbergen deleted the bmastbergen_fips-legacy-8-compliant/4.18.0-425.13.1/VULN-8822 branch June 6, 2025 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants