diff --git a/SOURCES/1758-net-sched-ets-always-remove-class-from-active-list-before-deleting.patch b/SOURCES/1758-net-sched-ets-always-remove-class-from-active-list-before-deleting.patch new file mode 100644 index 000000000..03a5128a0 --- /dev/null +++ b/SOURCES/1758-net-sched-ets-always-remove-class-from-active-list-before-deleting.patch @@ -0,0 +1,227 @@ +From c7f6e7cc14df72b997258216e99d897d2df0dbbd Mon Sep 17 00:00:00 2001 +From: Jamal Hadi Salim +Date: Fri, 28 Nov 2025 10:19:19 -0500 +Subject: [PATCH] net/sched: ets: Always remove class from active list before + deleting in ets_qdisc_change + +[ Upstream commit ce052b9402e461a9aded599f5b47e76bc727f7de ] + +zdi-disclosures@trendmicro.com says: + +The vulnerability is a race condition between `ets_qdisc_dequeue` and +`ets_qdisc_change`. It leads to UAF on `struct Qdisc` object. +Attacker requires the capability to create new user and network namespace +in order to trigger the bug. +See my additional commentary at the end of the analysis. + +Analysis: + +static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) +{ +... + + // (1) this lock is preventing .change handler (`ets_qdisc_change`) + //to race with .dequeue handler (`ets_qdisc_dequeue`) + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { + if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } + + WRITE_ONCE(q->nbands, nbands); + for (i = nstrict; i < q->nstrict; i++) { + if (q->classes[i].qdisc->q.qlen) { + // (2) the class is added to the q->active + list_add_tail(&q->classes[i].alist, &q->active); + q->classes[i].deficit = quanta[i]; + } + } + WRITE_ONCE(q->nstrict, nstrict); + memcpy(q->prio2band, priomap, sizeof(priomap)); + + for (i = 0; i < q->nbands; i++) + WRITE_ONCE(q->classes[i].quantum, quanta[i]); + + for (i = oldbands; i < q->nbands; i++) { + q->classes[i].qdisc = queues[i]; + if (q->classes[i].qdisc != &noop_qdisc) + qdisc_hash_add(q->classes[i].qdisc, true); + } + + // (3) the qdisc is unlocked, now dequeue can be called in parallel + // to the rest of .change handler + sch_tree_unlock(sch); + + ets_offload_change(sch); + for (i = q->nbands; i < oldbands; i++) { + // (4) we're reducing the refcount for our class's qdisc and + // freeing it + qdisc_put(q->classes[i].qdisc); + // (5) If we call .dequeue between (4) and (5), we will have + // a strong UAF and we can control RIP + q->classes[i].qdisc = NULL; + WRITE_ONCE(q->classes[i].quantum, 0); + q->classes[i].deficit = 0; + gnet_stats_basic_sync_init(&q->classes[i].bstats); + memset(&q->classes[i].qstats, 0, sizeof(q->classes[i].qstats)); + } + return 0; +} + +Comment: +This happens because some of the classes have their qdiscs assigned to +NULL, but remain in the active list. This commit fixes this issue by always +removing the class from the active list before deleting and freeing its +associated qdisc + +Reproducer Steps +(trimmed version of what was sent by zdi-disclosures@trendmicro.com) + +``` +DEV="${DEV:-lo}" +ROOT_HANDLE="${ROOT_HANDLE:-1:}" +BAND2_HANDLE="${BAND2_HANDLE:-20:}" # child under 1:2 +PING_BYTES="${PING_BYTES:-48}" +PING_COUNT="${PING_COUNT:-200000}" +PING_DST="${PING_DST:-127.0.0.1}" + +SLOW_TBF_RATE="${SLOW_TBF_RATE:-8bit}" +SLOW_TBF_BURST="${SLOW_TBF_BURST:-100b}" +SLOW_TBF_LAT="${SLOW_TBF_LAT:-1s}" + +cleanup() { + tc qdisc del dev "$DEV" root 2>/dev/null +} +trap cleanup EXIT + +ip link set "$DEV" up + +tc qdisc del dev "$DEV" root 2>/dev/null || true + +tc qdisc add dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 + +tc qdisc add dev "$DEV" parent 1:2 handle "$BAND2_HANDLE" \ + tbf rate "$SLOW_TBF_RATE" burst "$SLOW_TBF_BURST" latency "$SLOW_TBF_LAT" + +tc filter add dev "$DEV" parent 1: protocol all prio 1 u32 match u32 0 0 flowid 1:2 +tc -s qdisc ls dev $DEV + +ping -I "$DEV" -f -c "$PING_COUNT" -s "$PING_BYTES" -W 0.001 "$PING_DST" \ + >/dev/null 2>&1 & +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 0 +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 2 strict 2 +tc -s qdisc ls dev $DEV +tc qdisc del dev "$DEV" parent 1:2 || true +tc -s qdisc ls dev $DEV +tc qdisc change dev "$DEV" root handle "$ROOT_HANDLE" ets bands 1 strict 1 +``` + +KASAN report +``` +================================================================== +BUG: KASAN: slab-use-after-free in ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 +Read of size 8 at addr ffff8880502fc018 by task ping/12308 +> +CPU: 0 UID: 0 PID: 12308 Comm: ping Not tainted 6.18.0-rc4-dirty #1 PREEMPT(full) +Hardware name: QEMU Ubuntu 25.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 +Call Trace: + + __dump_stack kernel/lib/dump_stack.c:94 + dump_stack_lvl+0x100/0x190 kernel/lib/dump_stack.c:120 + print_address_description kernel/mm/kasan/report.c:378 + print_report+0x156/0x4c9 kernel/mm/kasan/report.c:482 + kasan_report+0xdf/0x110 kernel/mm/kasan/report.c:595 + ets_qdisc_dequeue+0x1071/0x11b0 kernel/net/sched/sch_ets.c:481 + dequeue_skb kernel/net/sched/sch_generic.c:294 + qdisc_restart kernel/net/sched/sch_generic.c:399 + __qdisc_run+0x1c9/0x1b00 kernel/net/sched/sch_generic.c:417 + __dev_xmit_skb kernel/net/core/dev.c:4221 + __dev_queue_xmit+0x2848/0x4410 kernel/net/core/dev.c:4729 + dev_queue_xmit kernel/./include/linux/netdevice.h:3365 +[...] + +Allocated by task 17115: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + poison_kmalloc_redzone kernel/mm/kasan/common.c:400 + __kasan_kmalloc+0xaa/0xb0 kernel/mm/kasan/common.c:417 + kasan_kmalloc kernel/./include/linux/kasan.h:262 + __do_kmalloc_node kernel/mm/slub.c:5642 + __kmalloc_node_noprof+0x34e/0x990 kernel/mm/slub.c:5648 + kmalloc_node_noprof kernel/./include/linux/slab.h:987 + qdisc_alloc+0xb8/0xc30 kernel/net/sched/sch_generic.c:950 + qdisc_create_dflt+0x93/0x490 kernel/net/sched/sch_generic.c:1012 + ets_class_graft+0x4fd/0x800 kernel/net/sched/sch_ets.c:261 + qdisc_graft+0x3e4/0x1780 kernel/net/sched/sch_api.c:1196 +[...] + +Freed by task 9905: + kasan_save_stack+0x30/0x50 kernel/mm/kasan/common.c:56 + kasan_save_track+0x14/0x30 kernel/mm/kasan/common.c:77 + __kasan_save_free_info+0x3b/0x70 kernel/mm/kasan/generic.c:587 + kasan_save_free_info kernel/mm/kasan/kasan.h:406 + poison_slab_object kernel/mm/kasan/common.c:252 + __kasan_slab_free+0x5f/0x80 kernel/mm/kasan/common.c:284 + kasan_slab_free kernel/./include/linux/kasan.h:234 + slab_free_hook kernel/mm/slub.c:2539 + slab_free kernel/mm/slub.c:6630 + kfree+0x144/0x700 kernel/mm/slub.c:6837 + rcu_do_batch kernel/kernel/rcu/tree.c:2605 + rcu_core+0x7c0/0x1500 kernel/kernel/rcu/tree.c:2861 + handle_softirqs+0x1ea/0x8a0 kernel/kernel/softirq.c:622 + __do_softirq kernel/kernel/softirq.c:656 +[...] + +Commentary: + +1. Maher Azzouzi working with Trend Micro Zero Day Initiative was reported as +the person who found the issue. I requested to get a proper email to add to the +reported-by tag but got no response. For this reason i will credit the person +i exchanged emails with i.e zdi-disclosures@trendmicro.com + +2. Neither i nor Victor who did a much more thorough testing was able to +reproduce a UAF with the PoC or other approaches we tried. We were both able to +reproduce a null ptr deref. After exchange with zdi-disclosures@trendmicro.com +they sent a small change to be made to the code to add an extra delay which +was able to simulate the UAF. i.e, this: + qdisc_put(q->classes[i].qdisc); + mdelay(90); + q->classes[i].qdisc = NULL; + +I was informed by Thomas Gleixner(tglx@linutronix.de) that adding delays was +acceptable approach for demonstrating the bug, quote: +"Adding such delays is common exploit validation practice" +The equivalent delay could happen "by virt scheduling the vCPU out, SMIs, +NMIs, PREEMPT_RT enabled kernel" + +3. I asked the OP to test and report back but got no response and after a +few days gave up and proceeded to submit this fix. + +Fixes: de6d25924c2a ("net/sched: sch_ets: don't peek at classes beyond 'nbands'") +Reported-by: zdi-disclosures@trendmicro.com +Tested-by: Victor Nogueira +Signed-off-by: Jamal Hadi Salim +Reviewed-by: Davide Caratti +Link: https://patch.msgid.link/20251128151919.576920-1-jhs@mojatatu.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin + +diff --git a/net/sched/sch_ets.c b/net/sched/sch_ets.c +index d95d12797525..bcd91ffe9bc6 100644 +--- a/net/sched/sch_ets.c ++++ b/net/sched/sch_ets.c +@@ -665,7 +665,7 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt, + sch_tree_lock(sch); + + for (i = nbands; i < oldbands; i++) { +- if (i >= q->nstrict && q->classes[i].qdisc->q.qlen) ++ if (cl_is_active(&q->classes[i])) + list_del_init(&q->classes[i].alist); + qdisc_purge_queue(q->classes[i].qdisc); + } +-- +2.50.1 (Apple Git-155) + diff --git a/SOURCES/1710-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-gfn.patch b/SOURCES/1759-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-gfn.patch similarity index 96% rename from SOURCES/1710-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-gfn.patch rename to SOURCES/1759-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-gfn.patch index 369c83b23..7918184a2 100644 --- a/SOURCES/1710-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-gfn.patch +++ b/SOURCES/1759-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-gfn.patch @@ -58,12 +58,9 @@ Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson Link: https://patch.msgid.link/20260503201029.106481-1-pbonzini@redhat.com/ Signed-off-by: Paolo Bonzini ---- - arch/x86/kvm/mmu/mmu.c | 35 ++++++++++++++--------------------- - 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c -index 8895c98..6140702 100644 +index 8895c98f0..6140702e1 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -183,6 +183,8 @@ struct kmem_cache *mmu_page_header_cache; @@ -129,6 +126,3 @@ index 8895c98..6140702 100644 spte = make_nonleaf_spte(sp->spt, sp_ad_disabled(sp)); --- -2.43.0 - diff --git a/SOURCES/1711-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-role.patch b/SOURCES/1760-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-role.patch similarity index 95% rename from SOURCES/1711-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-role.patch rename to SOURCES/1760-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-role.patch index 3119798ef..8e57ae462 100644 --- a/SOURCES/1711-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-role.patch +++ b/SOURCES/1760-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-role.patch @@ -34,12 +34,9 @@ use-after-free. Fixes: 2032a93d66fa ("KVM: MMU: Don't allocate gfns page for direct mmu pages") Reported-by: Hyunwoo Kim Signed-off-by: Paolo Bonzini ---- - arch/x86/kvm/mmu/mmu.c | 10 ++++++---- - 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c -index 6140702..8996c89 100644 +index 6140702e1..8996c8965 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -2315,13 +2315,15 @@ static struct kvm_mmu_page *kvm_mmu_get_child_sp(struct kvm_vcpu *vcpu, @@ -62,6 +59,3 @@ index 6140702..8996c89 100644 return kvm_mmu_get_shadow_page(vcpu, gfn, role); } --- -2.43.0 - diff --git a/SPECS/kernel.spec b/SPECS/kernel.spec index c127a50f8..7c9cc471f 100644 --- a/SPECS/kernel.spec +++ b/SPECS/kernel.spec @@ -176,13 +176,13 @@ Summary: The Linux kernel # define buildid .local %define specversion 5.14.0 %define patchversion 5.14 -%define pkgrelease 687.23.2 +%define pkgrelease 687.24.1 %define kversion 5 %define tarfile_release 5.14.0-687.5.1.el9_8 # This is needed to do merge window version magic %define patchlevel 14 # This allows pkg_release to have configurable %%{?dist} tag -%define specrelease 687.23.2%{?buildid}%{?dist} +%define specrelease 687.24.1%{?buildid}%{?dist} # This defines the kabi tarball version %define kabiversion 5.14.0-687.5.1.el9_8 @@ -1587,8 +1587,6 @@ Patch1706: 1706-crypto-testmgr-allow-authenc-hmac-sha-256-384-cts-cbc-aes-in.pat Patch1707: 1707-crypto-krb5enc-fix-sleepable-flag-handling-in-encrypt-dispat.patch Patch1708: 1708-crypto-krb5enc-fix-async-decrypt-skipping-hash-verification.patch Patch1709: 1709-crypto-krb5-filter-out-async-aead-implementations-at-alloc.patch -Patch1710: 1710-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-gfn.patch -Patch1711: 1711-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-role.patch Patch1713: 1713-nouveau-gsp-drop-warn-on-in-acpi-probes.patch Patch1714: 1714-sctp-revalidate-list-cursor-after-sctp-sendmsg-to-asoc-in-sc.patch Patch1715: 1715-drm-gem-fix-inconsistent-plane-dimension-calculation-in-drm.patch @@ -1630,6 +1628,9 @@ Patch1754: 1754-eventpoll-fix-integer-overflow-in-ep-loop-check-proc.patch Patch1755: 1755-eventpoll-refresh-epi-fget-ep-remove-file-comments.patch Patch1756: 1756-rtmutex-use-waiter-task-in-remove-waiter.patch Patch1757: 1757-rtmutex-skip-remove-waiter-when-not-enqueued.patch +Patch1758: 1758-net-sched-ets-always-remove-class-from-active-list-before-deleting.patch +Patch1759: 1759-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-gfn.patch +Patch1760: 1760-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-role.patch # END OF PATCH DEFINITIONS %description @@ -2984,8 +2985,6 @@ ApplyPatch 1706-crypto-testmgr-allow-authenc-hmac-sha-256-384-cts-cbc-aes-in.pat ApplyPatch 1707-crypto-krb5enc-fix-sleepable-flag-handling-in-encrypt-dispat.patch ApplyPatch 1708-crypto-krb5enc-fix-async-decrypt-skipping-hash-verification.patch ApplyPatch 1709-crypto-krb5-filter-out-async-aead-implementations-at-alloc.patch -ApplyPatch 1710-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-gfn.patch -ApplyPatch 1711-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-role.patch ApplyPatch 1713-nouveau-gsp-drop-warn-on-in-acpi-probes.patch ApplyPatch 1714-sctp-revalidate-list-cursor-after-sctp-sendmsg-to-asoc-in-sc.patch ApplyPatch 1715-drm-gem-fix-inconsistent-plane-dimension-calculation-in-drm.patch @@ -3027,6 +3026,9 @@ ApplyPatch 1754-eventpoll-fix-integer-overflow-in-ep-loop-check-proc.patch ApplyPatch 1755-eventpoll-refresh-epi-fget-ep-remove-file-comments.patch ApplyPatch 1756-rtmutex-use-waiter-task-in-remove-waiter.patch ApplyPatch 1757-rtmutex-skip-remove-waiter-when-not-enqueued.patch +ApplyPatch 1758-net-sched-ets-always-remove-class-from-active-list-before-deleting.patch +ApplyPatch 1759-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-gfn.patch +ApplyPatch 1760-kvm-x86-fix-shadow-paging-use-after-free-due-to-unexpected-role.patch # END OF PATCH APPLICATIONS # Any further pre-build tree manipulations happen here. @@ -5101,6 +5103,17 @@ fi # # %changelog +* Thu Jul 09 2026 Andrew Lukoshko - 5.14.0-687.24.1 +- Recreate RHEL 5.14.0-687.24.1 from upstream stable backports (1758-1760) +- The AlmaLinux ahead-of-RHEL KVM x86 shadow paging fixes (1710, 1711) are + superseded by RHEL's copies and dropped +- RHEL changelog for 687.24.1 follows: + +* Tue Jul 07 2026 CKI KWF Bot [5.14.0-687.24.1.el9_8] +- KVM: x86: Fix shadow paging use-after-free due to unexpected role (Paolo Bonzini) [RHEL-192400] {CVE-2026-53359} +- KVM: x86: Fix shadow paging use-after-free due to unexpected GFN (CKI Backport Bot) [RHEL-186702] {CVE-2026-46113} +- net/sched: ets: Always remove class from active list before deleting in ets_qdisc_change (CKI Backport Bot) [RHEL-183004] {CVE-2025-71066} + * Wed Jul 08 2026 Andrew Lukoshko - 5.14.0-687.23.2 - Bring back the rtmutex self-deadlock NULL pointer dereference fixes in remove_waiter() ahead of RHEL, upstream 3bfdc63936dd + 40a25d59e85b (1756, 1757)