Skip to content

[FIPS 8.7 Legacy] net_sched: hfsc: Address reentrant enqueue adding class to eltree twice #510

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

Open
wants to merge 2 commits into
base: fips-legacy-8-compliant/4.18.0-425.13.1
Choose a base branch
from

Conversation

pvts-mat
Copy link
Contributor

@pvts-mat pvts-mat commented Aug 18, 2025

[FIPS 8.7 Legacy]
CVE-2025-37890
VULN-68294

Problem

https://access.redhat.com/security/cve/CVE-2025-37890

A use-after-free vulnerability has been identified in the Linux kernel's HFSC (Hierarchical Fair Service Curve) queuing discipline when it is configured with NETEM (Network Emulation) as a child. This flaw can lead to a kernel panic or crash due to incorrect assumptions about the queue state. Exploitation of this vulnerability requires local access with CAP_NET_ADMIN privileges and control over the qdisc (queueing discipline) setup. A local attacker could leverage this flaw to achieve denial of service or escalate privileges. Given that it affects kernel memory structures, successful exploitation could result in memory corruption, data leaks, or arbitrary write capabilities, leading to a full kernel crash.

Applicability: yes

The patch relates to the sch_hfsc module, enabled with the NET_SCH_HFSC option. It's set to m in all configs of FIPS 8.7 Legacy:

$ grep 'NET_SCH_HFSC\b' configs/*.config

configs/kernel-aarch64-debug.config:CONFIG_NET_SCH_HFSC=m
configs/kernel-aarch64.config:CONFIG_NET_SCH_HFSC=m
configs/kernel-ppc64le-debug.config:CONFIG_NET_SCH_HFSC=m
configs/kernel-ppc64le.config:CONFIG_NET_SCH_HFSC=m
configs/kernel-s390x-debug.config:CONFIG_NET_SCH_HFSC=m
configs/kernel-s390x-zfcpdump.config:CONFIG_NET_SCH_HFSC=m
configs/kernel-s390x.config:CONFIG_NET_SCH_HFSC=m
configs/kernel-x86_64-debug.config:CONFIG_NET_SCH_HFSC=m
configs/kernel-x86_64.config:CONFIG_NET_SCH_HFSC=m

The commit 37d9cf1 marked as introducing the bug was backported to FIPS 8.7 Legacy in f3e1778. The mainline fix 141d343 wasn't backported. For the full picture please refer to the Appendix: Bug timeline

Solution

The same situation as in #490, which see.

kABI check: passed

DEBUG=1 CVE=CVE-2025-37890 ./ninja.sh _kabi_checked__x86_64--test--fips8l-CVE-2025-37890

[0/1] Check ABI of kernel [fips8l-CVE-2025-37890]
++ uname -m
+ python3 /data/src/ctrliq-github/kernel-dist-git-el-8.6/SOURCES/check-kabi -k /data/src/ctrliq-github/kernel-dist-git-el-8.6/SOURCES/Module.kabi_x86_64 -s vms/x86_64--build--ciqlts8_6/build_files/kernel-src-tree-fips8l-CVE-2025-37890/Module.symvers
kABI check passed
+ touch state/kernels/fips8l-CVE-2025-37890/x86_64/kabi_checked

Boot test: passed

boot-test.log

Kselftests: passed relative

Coverage

Only the net-related tests were run.

  • net/forwarding (except sch_tbf_prio.sh, ipip_hier_gre_keys.sh, sch_tbf_ets.sh, mirror_gre_vlan_bridge_1q.sh, sch_ets.sh, mirror_gre_bridge_1d_vlan.sh, bridge_igmp.sh, sch_tbf_root.sh, tc_actions.sh),
  • net/mptcp (except mptcp_join.sh, simult_flows.sh),
  • net (except udpgro_fwd.sh, udpgso_bench.sh, txtimestamp.sh, xfrm_policy.sh, ip_defrag.sh, gro.sh, reuseport_addr_any.sh),
  • netfilter (except nft_trans_stress.sh)

Reference

kselftests–fips8l–run1.log
kselftests–fips8l–run2.log

Patch

kselftests–fips8l-CVE-2025-37890–run1.log
kselftests–fips8l-CVE-2025-37890–run2.log

Comparison

The tests results for the reference and patch are the same.

$ ktests.xsh diff -d kselftests*.log

Column    File
--------  -------------------------------------------
Status0   kselftests--fips8l--run1.log
Status1   kselftests--fips8l--run2.log
Status2   kselftests--fips8l-CVE-2025-37890--run1.log
Status3   kselftests--fips8l-CVE-2025-37890--run2.log

Specific tests: skipped

Appendix: Bug timeline

(This is a version of "Appendix: Bug timeline" from #490 augmented with FIPS kernels)

The following table summarizes the timeline of the net/sched/sch_hfsc.c file on 9 branches:

  • Rocky LTS: ciqlts9_4, ciqlts9_2, ciqlts8_6,
  • Rocky FIPS: fips-legacy-8-compliant/4.18.0-425.13.1 (as fips8l), fips-8-compliant/4.18.0-553.16.1 (as fips8c), fips-9-compliant/5.14.0-284.30.1 (as fips9c),
  • upstream: kernel-mainline, linux-5.15.y, linux-4.19.y,

ordered from the newest to the oldest (roughly).

0 Commit introducing the bug CVE-2025-37890
1 Official fix of CVE-2025-37890
2 The fix of the fix of CVE-2025-37890
   kernel-mainline                                                                                                        linux-5.15.y            ciqlts9_4               fips9c                  ciqlts9_2               linux-4.19.y            fips8c                  fips8l                  ciqlts8_6
   ---------------------------------------------------------------------------------------------------------------------  ----------------------  ----------------------  ----------------------  ----------------------  ----------------------  ----------------------  ----------------------  ----------------------
   dd831ac82 2025-07-10 net/sched: sch_qfq: Fix null-deref in agg_dequeue
2> ac9fe7dd8 2025-05-28 net_sched: hfsc: Address reentrant enqueue adding class to eltree twice                           ~ 2c928b3a0 2025-06-04
   3f9811381 2025-05-22 sch_hfsc: Fix qlen accounting bug when using peek in hfsc_enqueue()                               ~ 89c301e92 2025-06-04
1> 141d34391 2025-04-28 net_sched: hfsc: Fix a UAF vulnerability in class with netem as child qdisc                       ~ e3e949a39 2025-05-09
   6ccbda44e 2025-04-23 net_sched: hfsc: Fix a potential UAF in hfsc_dequeue() too                                        ~ da7936518 2025-05-02
   3df275ef0 2025-04-23 net_sched: hfsc: Fix a UAF vulnerability in class handling                                        ~ fcc8ede66 2025-05-02
   51eb3b655 2025-04-08 sch_hfsc: make hfsc_qlen_notify() idempotent
   49e8ae537 2024-04-19 net_sched: sch_hfsc: implement lockless accesses to q->defcls
   241a94abc 2024-02-02 net/sched: Add module aliases for cls_,sch_,act_ modules
   f96118c5d 2023-11-01 net: sched: Fill in missing MODULE_DESCRIPTION for qdiscs
   a13b67c9a 2023-10-18 net/sched: sch_hfsc: upgrade 'rt' to 'sc' when it becomes a inner curve                           ~ b33179dbf 2023-10-25  ~ 9950d4d93 2023-10-26  ~ 1d92bc1fc 2025-05-06  ~ 963fd188b 2025-02-21  ~ a39a303c0 2023-10-25  ~ ae71642ce 2024-09-11  ~ 62831c7fb 2025-04-29  ~ 7a44a1754 2025-02-21
   b3d26c570 2023-08-25 net/sched: sch_hfsc: Ensure inner classes have fsc curve                                          ~ 4cf994d3f 2023-09-19  ~ ff4452fb0 2023-10-26  ~ 6eac08331 2025-05-06  ~ 8bb8fbc62 2025-02-21  ~ 7c62e0c3c 2023-09-23  ~ 1a61f0a5d 2024-09-11  ~ 9657abee6 2025-04-29  ~ 1b3b94f37 2024-09-13
   8e4553ef3 2023-08-01 net/sched: sch_hfsc: warn about class in use while deleting                                                               ~ 24c91e176 2023-12-11
   8798481b6 2023-08-01 net/sched: wrap open coded Qdics class filter counter
   e046fa895 2022-09-22 net/sched: use tc_qdisc_stats_dump() in qdisc                                                                             ~ c25ea5b55 2023-05-10                                                                          ~ 425f58a2b 2024-09-11
   a102c8973 2022-09-01 net: sched: remove redundant NULL check in change hook function                                                           ~ c26048684 2023-05-10                                                                          ~ cbb52db96 2024-09-11
   c19d893fb 2022-08-25 net: sched: delete duplicate cleanup of backlog and qlen                                          ~ 34f2a4eed 2022-10-29  ~ 3b0715d0c 2023-05-10                                                                          # 61fc01147 2024-09-11
   29cbcd858 2021-10-18 net: sched: Remove Qdisc::running sequence counter                                                                        ~ 43c09223c 2022-06-06  ~ 43c09223c 2022-06-06  ~ 43c09223c 2022-06-06                          ~ f683b275d 2024-09-11  ~ 47144ea4e 2024-09-12
   50dc9a857 2021-10-18 net: sched: Merge Qdisc::bstats and Qdisc::cpu_bstats data types                                                          ~ 07089a02e 2022-06-06  ~ 07089a02e 2022-06-06  ~ 07089a02e 2022-06-06                          ~ 4d6ceedf8 2024-09-11  ~ e60c20816 2024-09-12
   67c9e6270 2021-10-18 net: sched: Protect Qdisc::bstats with u64_stats                                                                          ~ 899676622 2022-06-06  ~ 899676622 2022-06-06  ~ 899676622 2022-06-06                          ~ a1d655fee 2024-09-11  ~ 6037cb9d1 2024-09-12
   3aa260559 2021-07-29 net/sched: store the last executed chain also for clsact egress                                   = 3aa260559 2021-07-29  ~ bee2c235e 2021-12-09  ~ bee2c235e 2021-12-09  ~ bee2c235e 2021-12-09                          ~ ffb881ce7 2024-09-11  ~ ffb881ce7 2024-09-11  ~ ffb881ce7 2024-09-11
   4dd78a737 2021-01-22 net: sched: Add extack to Qdisc_class_ops.delete                                                  = 4dd78a737 2021-01-22  = 4dd78a737 2021-01-22  = 4dd78a737 2021-01-22  = 4dd78a737 2021-01-22                          ~ d73d5e5ed 2024-09-11  ~ d73d5e5ed 2024-09-11  ~ d73d5e5ed 2024-09-11
   ac5c66f26 2020-07-16 Revert "net: sched: Pass root lock to Qdisc_ops.enqueue"                                          = ac5c66f26 2020-07-16  = ac5c66f26 2020-07-16  = ac5c66f26 2020-07-16  = ac5c66f26 2020-07-16
   3f649ab72 2020-07-16 treewide: Remove uninitialized_var() usage                                                        = 3f649ab72 2020-07-16  = 3f649ab72 2020-07-16  = 3f649ab72 2020-07-16  = 3f649ab72 2020-07-16
   964201de6 2020-07-07 net/sched: Use fallthrough pseudo-keyword                                                         = 964201de6 2020-07-07  = 964201de6 2020-07-07  = 964201de6 2020-07-07  = 964201de6 2020-07-07                          ~ 1dada1b74 2024-09-11  ~ 1dada1b74 2024-09-11  ~ 1dada1b74 2024-09-11
   aebe4426c 2020-06-29 net: sched: Pass root lock to Qdisc_ops.enqueue                                                   = aebe4426c 2020-06-29  = aebe4426c 2020-06-29  = aebe4426c 2020-06-29  = aebe4426c 2020-06-29
   8cb081746 2019-04-27 netlink: make validation more configurable for future strictness                                  = 8cb081746 2019-04-27  = 8cb081746 2019-04-27  = 8cb081746 2019-04-27  = 8cb081746 2019-04-27                          # 9c3767b38 2024-09-11  # 9c3767b38 2024-09-11  # 9c3767b38 2024-09-11
   ae0be8de9 2019-04-27 netlink: make nla_nest_start() add NLA_F_NESTED flag                                              = ae0be8de9 2019-04-27  = ae0be8de9 2019-04-27  = ae0be8de9 2019-04-27  = ae0be8de9 2019-04-27                          # 9c3767b38 2024-09-11  # 9c3767b38 2024-09-11  # 9c3767b38 2024-09-11
   e5f0e8f8e 2019-04-01 net: sched: introduce and use qdisc tree flush/purge helpers                                      = e5f0e8f8e 2019-04-01  = e5f0e8f8e 2019-04-01  = e5f0e8f8e 2019-04-01  = e5f0e8f8e 2019-04-01                          ~ 8eebb4e4c 2024-09-11  ~ 8eebb4e4c 2024-09-11  ~ 8eebb4e4c 2024-09-11
   5dd431b6b 2019-04-01 net: sched: introduce and use qstats read helpers                                                 = 5dd431b6b 2019-04-01  = 5dd431b6b 2019-04-01  = 5dd431b6b 2019-04-01  = 5dd431b6b 2019-04-01                          ~ ce56c8fb0 2024-09-11  ~ ce56c8fb0 2024-09-11  ~ ce56c8fb0 2024-09-11
0> 37d9cf1a3 2019-01-15 sched: Fix detection of empty queues in child qdiscs                                              = 37d9cf1a3 2019-01-15  = 37d9cf1a3 2019-01-15  = 37d9cf1a3 2019-01-15  = 37d9cf1a3 2019-01-15                          ~ f3e1778ab 2024-09-11  ~ f3e1778ab 2024-09-11  ~ f3e1778ab 2024-09-11
   f6bab1993 2019-01-15 sched: Avoid dereferencing skb pointer after child enqueue                                        = f6bab1993 2019-01-15  = f6bab1993 2019-01-15  = f6bab1993 2019-01-15  = f6bab1993 2019-01-15                          ~ aded77caa 2024-09-11  ~ aded77caa 2024-09-11  ~ aded77caa 2024-09-11
   …

… qdisc

jira VULN-68294
cve CVE-2025-37890
commit-author Victor Nogueira <[email protected]>
commit 141d343

As described in Gerrard's report [1], we have a UAF case when an hfsc class
has a netem child qdisc. The crux of the issue is that hfsc is assuming
that checking for cl->qdisc->q.qlen == 0 guarantees that it hasn't inserted
the class in the vttree or eltree (which is not true for the netem
duplicate case).

This patch checks the n_active class variable to make sure that the code
won't insert the class in the vttree or eltree twice, catering for the
reentrant case.

[1] https://lore.kernel.org/netdev/CAHcdcOm+03OD2j6R0=YHKqmy=VgJ8xEOKuP6c7mSgnp-TEJJbw@mail.gmail.com/

Fixes: 37d9cf1 ("sched: Fix detection of empty queues in child qdiscs")
	Reported-by: Gerrard Tai <[email protected]>
	Acked-by: Jamal Hadi Salim <[email protected]>
	Signed-off-by: Victor Nogueira <[email protected]>
Link: https://patch.msgid.link/[email protected]
	Signed-off-by: Jakub Kicinski <[email protected]>
(cherry picked from commit 141d343)
	Signed-off-by: Marcin Wcisło <[email protected]>
@pvts-mat
Copy link
Contributor Author

"LC" = "Legacy Compliant". Goes with the "LTS" naming for the "Long Term Support" kernels. Planning to use a similar naming for other FIPSes as well:

  • [FIPS 8 LC] for fips-legacy-8-compliant/4.18.0-425.13.1
  • [FIPS 8 C] for fips-8-compliant/4.18.0-553.16.1
  • [FIPS 9 C] for fips-9-compliant/5.14.0-284.30.1

Didn't see such naming in other PRs, but also didn't see any other consistent naming for that matter, which means there are probably no hard requirements. Let me know please @PlaidCat if that's ok

@PlaidCat
Copy link
Collaborator

"LC" = "Legacy Compliant". Goes with the "LTS" naming for the "Long Term Support" kernels. Planning to use a similar naming for other FIPSes as well:

* [FIPS 8 LC] for `fips-legacy-8-compliant/4.18.0-425.13.1`

* [FIPS 8 C] for `fips-8-compliant/4.18.0-553.16.1`

* [FIPS 9 C] for `fips-9-compliant/5.14.0-284.30.1`

Didn't see such naming in other PRs, but also didn't see any other consistent naming for that matter, which means there are probably no hard requirements. Let me know please @PlaidCat if that's ok

We have been using:

@pvts-mat
Copy link
Contributor Author

pvts-mat commented Aug 19, 2025

We have been using:
[...]

No, it has been much richer than that, that's the point.

fips-8-compliant/4.18.0-553.16.1

  1. [fips-8] [fips-8] netdevsim: Fix memory leak of nsim_dev->fa_cookie #355
  2. [fips-8.6] [fips-8.6] netfilter: ipset: add missing range check in bitmap_ip_uadt #319

fips-legacy-8-compliant/4.18.0-425.13.1:

  1. [fipslegacy-8.6] [fipslegacy-8.6] net: atlantic: fix aq_vec index out of range error #370
  2. [fips-legacy-8] [fips-legacy-8] netfilter: ipset: add the missing IP_SET_HASH_WITH_NET0 macro for ip_… #356
  3. [FIPS LEGACY 8] [FIPS LEGACY 8] CVEs: CVE-2025-21785, CVE-2023-4623 #233
  4. [FIPS Legacy 8.6] [FIPS Legacy 8.6] configs: x86_64: Sync with dist-git #212

fips-9-compliant/5.14.0-284.30.1:

  1. [FIPS 9.2] [FIPS 9.2] smb: client: fix OOBs when building SMB2_IOCTL request #504
  2. [fips 9.2] [fips 9.2] netfilter: nf_tables: skip bound chain on rule flush #462
  3. [fips-9.2] [fips-9.2] i2c: Fix a potential use after free #437
  4. [fips-9] [fips-9] netfilter: nf_tables: Reject tables of unsupported family #501
  5. [fips-9-compliant] [fips-9-compliant] CVE-2023-51042 and CVE-2023-40283 #492
  6. [fips92] [fips92] net/tipc: fix slab-use-after-free Read in tipc_aead_encrypt_done #458
  7. [fips9.2] [fips9.2] nvme-tcp: fix potential memory corruption in nvme_tcp_recv_pdu() #257
  8. [FIPS 9.2 Compliant] [FIPS 9.2 Compliant] CVEs: CVE-2023-4623, CVE-2025-21785 #239
    ...

Let me use these tags then:

  • [FIPS 8.10] for fips-8-compliant/4.18.0-553.16.1
  • [FIPS 9.2] for fips-9-compliant/5.14.0-284.30.1
  • [FIPS 8.7 Legacy] for fips-legacy-8-compliant/4.18.0-425.13.1

Why:

  • Capital "FIPS" to be consistent with capital "LTS"
  • No hyphen between FIPS and version to be consistent with no hyphen between LTS and version.
  • Version numbering MAJOR.MINOR consistent between all FIPSes as well as with LTSes
  • "Compliant" implicit for all FIPSes - no need to spell it out.
  • "8.10" instead of "8.6" because that's the actual version of the forked kernel (right?).
  • "Legacy" put at the end to keep the prefix more regular, but can be [FIPS Legacy 8.7] as well.

Is that ok, @PlaidCat?

@pvts-mat pvts-mat changed the title [FIPS 8 LC] net_sched: hfsc: Address reentrant enqueue adding class to eltree twice [FIPS 8.7 Legacy] net_sched: hfsc: Address reentrant enqueue adding class to eltree twice Aug 20, 2025
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:

jira VULN-68363
cve CVE-2025-38001
commit-author Pedro Tammela <[email protected]>
commit ac9fe7d

Savino says:
    "We are writing to report that this recent patch
    (141d343) [1]
    can be bypassed, and a UAF can still occur when HFSC is utilized with
    NETEM.

    The patch only checks the cl->cl_nactive field to determine whether
    it is the first insertion or not [2], but this field is only
    incremented by init_vf [3].

    By using HFSC_RSC (which uses init_ed) [4], it is possible to bypass the
    check and insert the class twice in the eltree.
    Under normal conditions, this would lead to an infinite loop in
    hfsc_dequeue for the reasons we already explained in this report [5].

    However, if TBF is added as root qdisc and it is configured with a
    very low rate,
    it can be utilized to prevent packets from being dequeued.
    This behavior can be exploited to perform subsequent insertions in the
    HFSC eltree and cause a UAF."

To fix both the UAF and the infinite loop, with netem as an hfsc child,
check explicitly in hfsc_enqueue whether the class is already in the eltree
whenever the HFSC_RSC flag is set.

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=141d34391abbb315d68556b7c67ad97885407547
[2] https://elixir.bootlin.com/linux/v6.15-rc5/source/net/sched/sch_hfsc.c#L1572
[3] https://elixir.bootlin.com/linux/v6.15-rc5/source/net/sched/sch_hfsc.c#L677
[4] https://elixir.bootlin.com/linux/v6.15-rc5/source/net/sched/sch_hfsc.c#L1574
[5] https://lore.kernel.org/netdev/8DuRWwfqjoRDLDmBMlIfbrsZg9Gx50DHJc1ilxsEBNe2D6NMoigR_eIRIG0LOjMc3r10nUUZtArXx4oZBIdUfZQrwjcQhdinnMis_0G7VEk=@willsroot.io/T/#u

Fixes: 37d9cf1 ("sched: Fix detection of empty queues in child qdiscs")
	Reported-by: Savino Dicanosa <[email protected]>
	Reported-by: William Liu <[email protected]>
	Acked-by: Jamal Hadi Salim <[email protected]>
	Tested-by: Victor Nogueira <[email protected]>
	Signed-off-by: Pedro Tammela <[email protected]>
Link: https://patch.msgid.link/[email protected]
	Signed-off-by: Paolo Abeni <[email protected]>

(cherry picked from commit ac9fe7d)
	Signed-off-by: Marcin Wcisło <[email protected]>
@pvts-mat pvts-mat force-pushed the fips8l-CVE-2025-37890 branch from 47dae5f to 80897f5 Compare August 22, 2025 21:02
@pvts-mat
Copy link
Contributor Author

Changed tags in accordance with #514 (comment)

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.

2 participants