Skip to content

Conversation

@pvts-mat
Copy link
Contributor

@pvts-mat pvts-mat commented Jan 19, 2026

[LTS 9.4]
CVE-2025-38084 VULN-71578
CVE-2025-38085 VULN-71587
CVE-2024-57883 VULN-46930

About

This PR is the LTS 9.4 version of #731. While CVE-2025-38084 and CVE-2025-38085 are not interdependent, their fixes appeared on upstream in the same branch d3c82f6 and are usually backported together as well (CentOS 9 462b3c3, CentOS 10 42421eb, stable 6.1 b7754d3aa7bf9f62218d096c0c8f6c13698fac8b, stable 5.10 952596b08c74e8fe9e2883d1dc8a8f54a37384ec, stable 5.15 a3d864c901a300c295692d129159fc3001a56185).

For the comparison of commits related to the CVEs in different Linuxes see Appendix: Backports Overview

Relation to the LTS 9.2 fix

The fix is, for the most part, the same as in LTS 9.2 #731, with some minor differences.

  • The fix for for CVE-2025-38085 (mm/hugetlb: fix huge_pmd_unshare() vs GUP-fast race) and it's prerequisite (mm: hugetlb: independent PMD page table shared count) were taken from linux-6.1.y instead of linux-5.15.y. This was only to avoid context conflicts, as linux-6.1.y has more similar history of tlb module to ciqlts9_4 than the linux-5.15.y does. The commits diffs are practically the same.
  • The commit 3aa4ed8 mm/hugetlb: make detecting shared pte more reliable wasn't backported as the prerequisite for the bugfix of CVE-2025-38085 fix (the mm/hugetlb: fix copy_hugetlb_page_range() to use ->pt_share_count commit) because it was already backported to ciqlts9_4 as 643137f.
  • Similarly no backport of 2ba99c5 mm/khugepaged: fix GUP-fast interaction by sending IPI as prerequisite for CVE-2025-38085 fix (mm/hugetlb: fix huge_pmd_unshare() vs GUP-fast race) was done, because it was already backported to ciqlts9_4 in f4c1e18.
  • The fix for CVE-2025-38084 (mm/hugetlb: unshare page tables during VMA split, not before) was taken from linux-5.15.y to minimize conflicts compared to the upstream, just like in LTS 9.2 case, however, the end result differs from the linux-5.15.y pick for the LTS 9.2 version ad741c4 - see function hugetlb_unshare_pmds().

CVE-2025-38085 fix discussion

The LTS 9.2 PR #731 raised suspicion over the kABI breakage, which was eventually resolved. The same situation can be found in this patch set. An attempt was made to avoid the mm: hugetlb: independent PMD page table shared count commit requiring the use of RH_KABI_BROKEN_INSERT as it may not have been strictly required for the fix of CVE-2025-38085. However, it was decided to backport it to LTS 9.4 as well, because only one solution was found - the CentOS 9 fix 12a6db3 - which didn't incorporate this commit as prerequisite. All other analyzed solutions did (CentOS 10 41f7eb5, stable 6.6 fe684290418ef9ef76630072086ee530b92f02b8, stable 6.1 b7754d3aa7bf9f62218d096c0c8f6c13698fac8b, stable 5.15 a3d864c901a300c295692d129159fc3001a56185, stable 5.10 952596b08c74e8fe9e2883d1dc8a8f54a37384ec).

The upstream fix 1013af4 message explicitly mentions

huge_pmd_unshare() drops a reference on a page table

which refers to the line right after the introduced tlb_remove_table_sync_one() call:

ptdesc_pmd_pts_dec(virt_to_ptdesc(ptep));

In ciqlts9_4 without mm: hugetlb: independent PMD page table shared count this line would be

put_page(virt_to_page(ptep));

just like it was in CentOS 9 fix 12a6db3. It could not have been determined whether these two situations were similar enough to warrant the exact same fix, so the more established solution was used, even though 12a6db3 cherry-picked cleanly.

Additionally, this prerequisite has its own CVE-2024-57883 associated, which will probably have to be solved eventually anyway.

CVE-2024-57883 fresh fixes

The recent bugfixes of the fix of CVE-2024-57883 were part of the same branch c25f2fb.

$ git log -n 18 --oneline --graph c25f2fb1f469deaed2df8db524d91f3321a0f816
*   c25f2fb1f Merge tag 'mm-hotfixes-stable-2026-01-20-13-09' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
|\  
| * 16aca2c98 mm: restore per-memcg proactive reclaim with !CONFIG_NUMA
| * 9bc9ccbf4 mm/kfence: fix potential deadlock in reboot notifier
| * cb7d761bf Docs/mm/allocation-profiling: describe sysctrl limitations in debug mode
| * 35e247032 mm: do not copy page tables unnecessarily for VM_UFFD_WP
| * 8ce720d5b mm/hugetlb: fix excessive IPI broadcasts when unsharing PMD tables using mmu_gather   < 1
| * a8682d500 mm/rmap: fix two comments related to huge_pmd_unshare()                               < 2
| * 3937027ca mm/hugetlb: fix two comments related to huge_pmd_unshare()                            < 3
| * ca1a47cd3 mm/hugetlb: fix hugetlb_pmd_shared()                                                  < 4
| * 90888b4ae mm: remove unnecessary and incorrect mmap lock assert
| * b505f1944 x86/kfence: avoid writing L1TF-vulnerable PTEs
| * 605f6586e mm/vma: do not leak memory when .mmap_prepare swaps the file
| * b7880cb16 migrate: correct lock ordering for hugetlb file folios
| * 90f3c1232 panic: only warn about deprecated panic_print on write access
| * f9a49aa30 fs/writeback: skip AS_NO_DATA_INTEGRITY mappings in wait_sb_inodes()
| * be31340a4 mm: take into account mm_cid size for mm_struct static definitions
| * 6ac433f8b mm: rename cpu_bitmap field to flexible_array
| * 12a6ddfc7 mm: add missing static initializer for init_mm::mm_cid.lock

Of these the commits 2, 3, 4 were backported. Commit 1 was dropped, for the following reasons:

  1. Commit mm/hugetlb: fix excessive IPI broadcasts when unsharing PMD tables using mmu_gather represents more of an optimization than a bug fix, let alone vulnerability fix. Moreover, the performance drop was observed in a highly specific environment

    https://lore.kernel.org/all/[email protected]/

    On large machines with 1.5TB of memory with 196 cores, we identified mmapping of 1.2TB of shared memory and forking itself dozens or hundreds of times we see a increase of execution times of a factor of 4.

  2. The commit is relatively big and complicated, causing multiple conflicts upon cherry-picking onto ciqlts9_4. Although they were resolved eventually (see f0dd083 for reference) no other backports (official stable or centos) exist to compare the solution with. This increases the risk of erroneous backport.

  3. The fix breaks the kABI with the change in struct mmu_gather in mm/mmu_gather.c:

    8ce720d#diff-297cf0f839ab2f417e9f0f34ba2b1e49d6056e3c99595aabd6a3d3c17eee991eL364

    The breakage occurs in the pv_ops variable, at the definition of .mmu.tlb_remove_table field

    .mmu.tlb_remove_table =
    (void (*)(struct mmu_gather *, void *))tlb_remove_page,

    To establish whether the change is an actual kABI breakage the usage of mmu_gather must be analyzed. The documentation of the struct suggests that it's local to the memory management module

    /*
    * struct mmu_gather is an opaque type used by the mm code for passing around
    * any data needed by arch specific code for tlb_remove_page.
    */

    However, the usage can also be found in the files subsystem

    struct mmu_gather tlb;

    struct mmu_gather tlb;

    The struct is never allocated dynamically and there is no API in include/asm-generic/tlb.h or include/linux/mm_types.h to achieve that. Instead it's allocated on the stack like in the examples above (19 cases in total) and the __tlb_gather_mmu() is used to initialize it, accessible publicly through tlb_gather_mmu() and tlb_gather_mmu_fullmm() defined in mm/mmu_gather.c. This means that if an external driver used this struct it would probably allocate it on stack as well and the binary interface would break. It could not have been established whether it's a sufficiently unlikely scenario for an external driver to use the the mmu_gather struct to warrant the suppression of kABI breakage warnings.

    However, it's important to remember that the mmu_gather struct itself is not whitelisted, only the pv_ops variable which uses the pointer to mmu_gather as an argument in one of its functions. It's possible that this function (.mmu.tlb_remove_table) is always called with the mmu_gather pointer provided only by the kernel, not the user, which would then mean the kABI isn't broken, as the __tlb_remove_page_size() function the .mmu.tlb_remove_table is reduced to remains unchanged, with the same API as before. However, it could not have been established, again, whether the mmu_gather is unlikely to ever be allocated by the user when using .mmu.tlb_remove_table.

    Moreover, even if it was the case that the kABI was not broken in practice, none of the tested macros RH_KABI_BROKEN_INSERT and RH_KABI_EXCLUDE actually succeeds in suppressing the kABI check error

    + python3 /data/src/ctrliq-github-haskell/kernel-dist-git-el-9.4/SOURCES/check-kabi -k /data/src/ctrliq-github-haskell/kernel-dist-git-el-9.4/SOURCES/Module.kabi_x86_64 -s vms/x86_64--build--ciqlts9_4/build_files/kernel-src-tree-ciqlts9_4-CVE-batch-18/Module.symvers
    *** ERROR - ABI BREAKAGE WAS DETECTED ***
    
    The following symbols have been changed (this will cause an ABI breakage):
    
    pv_ops
    

    It's unclear what could be the reason for this. The source of the break was identified to be definitely located in the modification of the mmu_gather struct by eliminating the change there (and only there), while preserving changes in all other places of the 8ce720d commit and obtaining a kABI-passing kernel build.

Commits

CVE-2025-38084

hugetlb: unshare some PMDs when splitting VMAs

jira VULN-71578
cve-pre CVE-2025-38084
commit-author James Houghton <[email protected]>
commit b30c14cd61025eeea2f2e8569606cd167ba9ad2d
mm/hugetlb: unshare page tables during VMA split, not before

jira VULN-71578
cve CVE-2025-38084
commit-author Jann Horn <[email protected]>
commit 081056dc00a27bccb55ccc3c6f230a3d5fd3f7e0
upstream-diff Used linux-5.15.y backport
  366298f2b04d2bf1f2f2b7078405bdf9df9bd5d0 as a base. Modified
  `hugetlb_unshare_pmds()' to wrap in the `take_lock == true' branches
  what was there originally. This change is the equivalent of applying
  upstream 081056d to the `hugetlb_unshare_pmds()' function and
  linux-5.15.y backport 366298f to everything else.

CVE-2025-38085 (+ CVE-2024-57883)

This fix for CVE-2024-57883 serves more as prerequisite for the following commit than a CVE fix in itself.

mm: hugetlb: independent PMD page table shared count

jira VULN-46930
cve CVE-2024-57883
commit-author Liu Shixin <[email protected]>
commit 59d9094df3d79443937add8700b2ef1a866b1081
upstream-diff Stable 6.1 backport
  02333ac1c35370517a19a4a131332a9690c6a5c7 was used for the actual
  (clean) cherry pick. Additionally the `atomic_t pt_share_count' field
  in `include/linux/mm_types.h' was wrapped in RH_KABI_BROKEN_INSERT
  macro to avoid kABI checker complains. It's justified, because the
  inserted field (it's included, as CONFIG_ARCH_WANT_HUGE_PMD_SHARE gets
  enabled for at least `kernel-x86_64-rhel.config') is placed within a
  union which already contained a field of the same type `atomic_t
  pt_frag_refcount', so the size of it cannot change. Moreover this
  union serves as a scratch space for the subsystems using the struct
  page. Upon releasing the ownership to buddy allocator the union
  contents no longer matter. When the page is allocated again the
  scratch space will be used by the new owner in its own way.
mm/hugetlb: fix huge_pmd_unshare() vs GUP-fast race

jira VULN-71587
cve CVE-2025-38085
commit-author Jann Horn <[email protected]>
commit 1013af4f585fccc4d3e5c5824d174de2257f7d6d
upstream-diff Stable 6.1 b7754d3aa7bf9f62218d096c0c8f6c13698fac8b was
  used for the actual (clean) cherry pick
mm/hugetlb: fix copy_hugetlb_page_range() to use ->pt_share_count

jira VULN-46930
cve-bf CVE-2024-57883
commit-author Jane Chu <[email protected]>
commit 14967a9c7d247841b0312c48dcf8cd29e55a4cc8
upstream-diff This commit fixes `mm: hugetlb: independent PMD page
  table shared count' which was included in ciqlts9_4 by cherry-picking
  stable-6.1 backport 02333ac1c35370517a19a4a131332a9690c6a5c7 of
  kernel-mainline 59d9094df3d79443937add8700b2ef1a866b1081. Differences
  between 02333ac and 59d9094 were driving the diffs between this commit
  and the upstrem 14967a9c7d247841b0312c48dcf8cd29e55a4cc8.
  include/linux/mm_types.h
        Removed the definition of `ptdesc_pmd_is_shared()' function in
        alignment with stable-5.15 backport 8410996 (it omits the
        definition of `ptdesc_pmd_pts_*()' functions family, to which
        `ptdesc_pmd_is_shared()' belongs).
  mm/hugetlb.c
        copy_hugetlb_page_range()
              1. Used CONFIG_ARCH_WANT_HUGE_PMD_SHARE instead of
                 CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING, because the latter
                 was introduced only in the non-backported commit
                 188cac58a8bcdf82c7f63275b68f7a46871e45d6.
              2. Since `ptdesc_pmd_is_shared()' was not defined, read the
                 `pt_share_count' field directly, as is done in the
                 stable-5.15 backport 8410996. (Compare changes to
                 `huge_pmd_unshare()' in `mm/hugetlb.c' between upstream
                 59d9094 and stable-5.15 8410996.)
        huge_pmd_unshare()
              No change to the conditional. It was arguably not needed in
              the upstream as well, probably introduced only for the sake
              of clarity in the presence of `ptdesc_pmd_is_shared()'
              function, which is missing here.
mm/hugetlb: fix hugetlb_pmd_shared()

jira VULN-46930
cve-bf CVE-2024-57883
commit-author David Hildenbrand (Red Hat) <[email protected]>
commit ca1a47cd3f5f4c46ca188b1c9a27af87d1ab2216
upstream-diff Adaptation analogous to
  3ab513de22e31391aaed3970c64b37bbf82c86a9 in relation to the upstream
  14967a9c7d247841b0312c48dcf8cd29e55a4cc8 - inlined missing
  `ptdesc_pmd_is_shared()', `ptdesc_pmd_pts_count()', `virt_to_ptdesc()'

To track the difference from the upstream refer to the definitions of related functions/macros from kernel-mainline:

ptdesc_pmd_is_shared()

static inline bool ptdesc_pmd_is_shared(struct ptdesc *ptdesc)
{
return !!ptdesc_pmd_pts_count(ptdesc);
}

ptdesc_pmd_pts_count()

static inline int ptdesc_pmd_pts_count(const struct ptdesc *ptdesc)
{
return atomic_read(&ptdesc->pt_share_count);
}

virt_to_ptdesc()

static inline struct ptdesc *virt_to_ptdesc(const void *x)
{
return page_ptdesc(virt_to_page(x));
}

page_ptdesc()

#define page_ptdesc(p) (_Generic((p), \
const struct page *: (const struct ptdesc *)(p), \
struct page *: (struct ptdesc *)(p)))

mm/hugetlb: fix two comments related to huge_pmd_unshare()

jira VULN-46930
cve-bf CVE-2024-57883
commit-author David Hildenbrand (Red Hat) <[email protected]>
commit 3937027caecb4f8251e82dd857ba1d749bb5a428
upstream-diff Resolved conflicts due to the
  4e1f5f690cf922466532cd84a32f5d0f2dfc174e backport incorporating a typo
  'refernece', which was fixed upstream (and expected by this patch) in
  b6c46600bfb28b4be4e9cff7bad4f2cf357e0fb7, but it didn't make it to
  ciqlts9_4. Could not have been picked as prerequisite due to multiple
  conflicts
mm/rmap: fix two comments related to huge_pmd_unshare()

jira VULN-46930
cve-bf CVE-2024-57883
commit-author David Hildenbrand (Red Hat) <[email protected]>
commit a8682d500f691b6dfaa16ae1502d990aeb86e8be

kABI check: passed

+ git -C /data/src/ctrliq-github-haskell/kernel-src-tree-ciqlts9_4-CVE-batch-18 log --format=%H -n 1
[1/2] kabi_check_kernel	Check ABI of kernel [ciqlts9_4-CVE-batch-18]	_kabi_check_kernel__x86_64--test--ciqlts9_4-CVE-batch-18
++ uname -m
+ python3 /data/src/ctrliq-github-haskell/kernel-dist-git-el-9.4/SOURCES/check-kabi -k /data/src/ctrliq-github-haskell/kernel-dist-git-el-9.4/SOURCES/Module.kabi_x86_64 -s vms/x86_64--build--ciqlts9_4/build_files/kernel-src-tree-ciqlts9_4-CVE-batch-18/Module.symvers
kABI check passed
+ touch state/kernels/ciqlts9_4-CVE-batch-18/x86_64/kabi_checked

Boot test: passed

boot-test.log

Kselftests: passed relative

Reference

kselftests–ciqlts9_4–run1.log

Patch

kselftests–ciqlts9_4-CVE-batch-18–run1.log
kselftests–ciqlts9_4-CVE-batch-18–run2.log
kselftests–ciqlts9_4-CVE-batch-18–run3.log

Comparison

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

$ ktests.xsh diff  kselftests*.log

Column    File
--------  --------------------------------------------
Status0   kselftests--ciqlts9_4--run1.log
Status1   kselftests--ciqlts9_4-CVE-batch-17--run1.log
Status2   kselftests--ciqlts9_4-CVE-batch-17--run2.log
Status3   kselftests--ciqlts9_4-CVE-batch-17--run3.log

TestCase                                               Status0  Status1  Status2  Status3  Summary
bpf:get_cgroup_id_user                                 pass     pass     pass     pass     same
bpf:test_cgroup_storage                                pass     pass     pass     pass     same
bpf:test_dev_cgroup                                    pass     pass     pass     pass     same
bpf:test_lpm_map                                       pass     pass     pass     pass     same
bpf:test_lru_map                                       pass     pass     pass     pass     same
bpf:test_sock                                          pass     pass     pass     pass     same
bpf:test_sysctl                                        pass     pass     pass     pass     same
bpf:test_tag                                           pass     pass     pass     pass     same
bpf:test_tcpnotify_user                                pass     pass     pass     pass     same
bpf:test_verifier                                      fail     fail     fail     fail     same
breakpoints:breakpoint_test                            pass     pass     pass     pass     same
capabilities:test_execve                               pass     pass     pass     pass     same
clone3:clone3                                          pass     pass     pass     pass     same
clone3:clone3_cap_checkpoint_restore                   pass     pass     pass     pass     same
clone3:clone3_clear_sighand                            pass     pass     pass     pass     same
clone3:clone3_set_tid                                  pass     pass     pass     pass     same
cpu-hotplug:cpu-on-off-test.sh                         pass     pass     pass     pass     same
cpufreq:main.sh                                        fail     fail     fail     fail     same
drivers/dma-buf:udmabuf                                pass     pass     pass     pass     same
drivers/net/bonding:bond-arp-interval-causes-panic.sh  pass     pass     pass     pass     same
drivers/net/bonding:bond-break-lacpdu-tx.sh            fail     fail     fail     fail     same
drivers/net/bonding:bond-eth-type-change.sh            pass     pass     pass     pass     same
drivers/net/bonding:bond-lladdr-target.sh              pass     pass     pass     pass     same
drivers/net/bonding:bond_options.sh                    fail     fail     fail     fail     same
drivers/net/bonding:dev_addr_lists.sh                  pass     pass     pass     pass     same
drivers/net/bonding:mode-1-recovery-updelay.sh         pass     pass     pass     pass     same
drivers/net/bonding:mode-2-recovery-updelay.sh         pass     pass     pass     pass     same
drivers/net/team:dev_addr_lists.sh                     pass     pass     pass     pass     same
exec:binfmt_script                                     pass     pass     pass     pass     same
exec:execveat                                          pass     pass     pass     pass     same
exec:load_address_16777216                             fail     fail     fail     fail     same
exec:load_address_2097152                              pass     pass     pass     pass     same
exec:load_address_4096                                 pass     pass     pass     pass     same
exec:non-regular                                       fail     fail     fail     fail     same
exec:recursion-depth                                   pass     pass     pass     pass     same
filesystems/binderfs:binderfs_test                     fail     fail     fail     fail     same
filesystems/epoll:epoll_wakeup_test                    pass     pass     pass     pass     same
firmware:fw_run_tests.sh                               skip     skip     skip     skip     same
fpu:run_test_fpu.sh                                    skip     skip     skip     skip     same
fpu:test_fpu                                           pass     pass     pass     pass     same
ftrace:ftracetest                                      fail     fail     fail     fail     same
futex:run.sh                                           pass     pass     pass     pass     same
gpio:gpio-mockup.sh                                    fail     fail     fail     fail     same
intel_pstate:run.sh                                    pass     pass     pass     pass     same
iommu:iommufd                                          fail     fail     fail     fail     same
iommu:iommufd_fail_nth                                 pass     pass     pass     pass     same
ipc:msgque                                             pass     pass     pass     pass     same
ir:ir_loopback.sh                                      skip     skip     skip     skip     same
kcmp:kcmp_test                                         pass     pass     pass     pass     same
kexec:test_kexec_file_load.sh                          skip     skip     skip     skip     same
kexec:test_kexec_load.sh                               skip     skip     skip     skip     same
kvm:access_tracking_perf_test                          pass     pass     pass     pass     same
kvm:amx_test                                           fail     fail     fail     fail     same
kvm:cpuid_test                                         fail     fail     fail     fail     same
kvm:cr4_cpuid_sync_test                                fail     fail     fail     fail     same
kvm:debug_regs                                         fail     fail     fail     fail     same
kvm:demand_paging_test                                 pass     pass     pass     pass     same
kvm:dirty_log_page_splitting_test                      fail     fail     fail     fail     same
kvm:dirty_log_perf_test                                pass     pass     pass     pass     same
kvm:dirty_log_test                                     fail     fail     fail     fail     same
kvm:exit_on_emulation_failure_test                     fail     fail     fail     fail     same
kvm:fix_hypercall_test                                 fail     fail     fail     fail     same
kvm:get_msr_index_features                             fail     fail     fail     fail     same
kvm:guest_memfd_test                                   pass     pass     pass     pass     same
kvm:guest_print_test                                   pass     pass     pass     pass     same
kvm:hardware_disable_test                              pass     pass     pass     pass     same
kvm:hyperv_clock                                       fail     fail     fail     fail     same
kvm:hyperv_cpuid                                       fail     fail     fail     fail     same
kvm:hyperv_evmcs                                       fail     fail     fail     fail     same
kvm:hyperv_extended_hypercalls                         fail     fail     fail     fail     same
kvm:hyperv_features                                    fail     fail     fail     fail     same
kvm:hyperv_ipi                                         fail     fail     fail     fail     same
kvm:hyperv_svm_test                                    fail     fail     fail     fail     same
kvm:hyperv_tlb_flush                                   fail     fail     fail     fail     same
kvm:kvm_binary_stats_test                              pass     pass     pass     pass     same
kvm:kvm_clock_test                                     fail     fail     fail     fail     same
kvm:kvm_create_max_vcpus                               pass     pass     pass     pass     same
kvm:kvm_page_table_test                                pass     pass     pass     pass     same
kvm:kvm_pv_test                                        fail     fail     fail     fail     same
kvm:max_guest_memory_test                              pass     pass     pass     pass     same
kvm:max_vcpuid_cap_test                                fail     fail     fail     fail     same
kvm:memslot_modification_stress_test                   pass     pass     pass     pass     same
kvm:memslot_perf_test                                  pass     pass     pass     pass     same
kvm:mmio_warning_test                                  fail     fail     fail     fail     same
kvm:monitor_mwait_test                                 fail     fail     fail     fail     same
kvm:nested_exceptions_test                             fail     fail     fail     fail     same
kvm:nx_huge_pages_test.sh                              fail     fail     fail     fail     same
kvm:platform_info_test                                 fail     fail     fail     fail     same
kvm:pmu_event_filter_test                              fail     fail     fail     fail     same
kvm:private_mem_conversions_test                       fail     fail     fail     fail     same
kvm:private_mem_kvm_exits_test                         fail     fail     fail     fail     same
kvm:recalc_apic_map_test                               fail     fail     fail     fail     same
kvm:rseq_test                                          fail     fail     fail     fail     same
kvm:set_boot_cpu_id                                    fail     fail     fail     fail     same
kvm:set_memory_region_test                             pass     pass     pass     pass     same
kvm:set_sregs_test                                     fail     fail     fail     fail     same
kvm:sev_migrate_tests                                  fail     fail     fail     fail     same
kvm:smaller_maxphyaddr_emulation_test                  fail     fail     fail     fail     same
kvm:smm_test                                           fail     fail     fail     fail     same
kvm:state_test                                         fail     fail     fail     fail     same
kvm:steal_time                                         pass     pass     pass     pass     same
kvm:svm_int_ctl_test                                   fail     fail     fail     fail     same
kvm:svm_nested_shutdown_test                           fail     fail     fail     fail     same
kvm:svm_nested_soft_inject_test                        fail     fail     fail     fail     same
kvm:svm_vmcall_test                                    fail     fail     fail     fail     same
kvm:sync_regs_test                                     fail     fail     fail     fail     same
kvm:system_counter_offset_test                         pass     pass     pass     pass     same
kvm:triple_fault_event_test                            fail     fail     fail     fail     same
kvm:tsc_msrs_test                                      fail     fail     fail     fail     same
kvm:tsc_scaling_sync                                   fail     fail     fail     fail     same
kvm:ucna_injection_test                                fail     fail     fail     fail     same
kvm:userspace_io_test                                  fail     fail     fail     fail     same
kvm:userspace_msr_exit_test                            fail     fail     fail     fail     same
kvm:vmx_apic_access_test                               fail     fail     fail     fail     same
kvm:vmx_close_while_nested_test                        fail     fail     fail     fail     same
kvm:vmx_dirty_log_test                                 fail     fail     fail     fail     same
kvm:vmx_exception_with_invalid_guest_state             fail     fail     fail     fail     same
kvm:vmx_invalid_nested_guest_state                     fail     fail     fail     fail     same
kvm:vmx_msrs_test                                      fail     fail     fail     fail     same
kvm:vmx_nested_tsc_scaling_test                        fail     fail     fail     fail     same
kvm:vmx_pmu_caps_test                                  fail     fail     fail     fail     same
kvm:vmx_preemption_timer_test                          fail     fail     fail     fail     same
kvm:vmx_set_nested_state_test                          fail     fail     fail     fail     same
kvm:vmx_tsc_adjust_test                                fail     fail     fail     fail     same
kvm:xapic_ipi_test                                     fail     fail     fail     fail     same
kvm:xapic_state_test                                   fail     fail     fail     fail     same
kvm:xcr0_cpuid_test                                    fail     fail     fail     fail     same
kvm:xen_shinfo_test                                    fail     fail     fail     fail     same
kvm:xen_vmcall_test                                    fail     fail     fail     fail     same
kvm:xss_msr_test                                       fail     fail     fail     fail     same
landlock:base_test                                     fail     fail     fail     fail     same
landlock:fs_test                                       fail     fail     fail     fail     same
landlock:ptrace_test                                   fail     fail     fail     fail     same
lib:bitmap.sh                                          skip     skip     skip     skip     same
lib:prime_numbers.sh                                   pass     pass     pass     pass     same
lib:printf.sh                                          skip     skip     skip     skip     same
lib:scanf.sh                                           skip     skip     skip     skip     same
lib:strscpy.sh                                         skip     skip     skip     skip     same
livepatch:test-callbacks.sh                            pass     pass     pass     pass     same
livepatch:test-ftrace.sh                               pass     pass     pass     pass     same
livepatch:test-livepatch.sh                            pass     pass     pass     pass     same
livepatch:test-shadow-vars.sh                          pass     pass     pass     pass     same
livepatch:test-state.sh                                pass     pass     pass     pass     same
livepatch:test-sysfs.sh                                pass     pass     pass     pass     same
membarrier:membarrier_test_multi_thread                pass     pass     pass     pass     same
membarrier:membarrier_test_single_thread               pass     pass     pass     pass     same
memfd:memfd_test                                       pass     pass     pass     pass     same
memfd:run_fuse_test.sh                                 pass     pass     pass     pass     same
memfd:run_hugetlbfs_test.sh                            pass     pass     pass     pass     same
memory-hotplug:mem-on-off-test.sh                      pass     pass     pass     pass     same
mincore:mincore_selftest                               fail     fail     fail     fail     same
mount:run_nosymfollow.sh                               pass     pass     pass     pass     same
mount:run_unprivileged_remount.sh                      pass     pass     pass     pass     same
mqueue:mq_open_tests                                   pass     pass     pass     pass     same
mqueue:mq_perf_tests                                   pass     pass     pass     pass     same
nci:nci_dev                                            fail     fail     fail     fail     same
net/forwarding:bridge_locked_port.sh                   pass     pass     pass     pass     same
net/forwarding:bridge_mdb.sh                           skip     skip     skip     skip     same
net/forwarding:bridge_mdb_host.sh                      pass     pass     pass     pass     same
net/forwarding:bridge_mdb_max.sh                       skip     skip     skip     skip     same
net/forwarding:bridge_mdb_port_down.sh                 pass     pass     pass     pass     same
net/forwarding:bridge_mld.sh                           pass     pass     pass     pass     same
net/forwarding:bridge_port_isolation.sh                pass     pass     pass     pass     same
net/forwarding:bridge_sticky_fdb.sh                    pass     pass     pass     pass     same
net/forwarding:bridge_vlan_aware.sh                    pass     pass     pass     pass     same
net/forwarding:bridge_vlan_mcast.sh                    pass     pass     pass     pass     same
net/forwarding:bridge_vlan_unaware.sh                  pass     pass     pass     pass     same
net/forwarding:custom_multipath_hash.sh                fail     fail     fail     fail     same
net/forwarding:ethtool.sh                              skip     skip     skip     skip     same
net/forwarding:ethtool_extended_state.sh               skip     skip     skip     skip     same
net/forwarding:gre_custom_multipath_hash.sh            fail     fail     fail     fail     same
net/forwarding:gre_inner_v4_multipath.sh               pass     pass     pass     pass     same
net/forwarding:gre_multipath.sh                        pass     pass     pass     pass     same
net/forwarding:gre_multipath_nh.sh                     fail     fail     fail     fail     same
net/forwarding:gre_multipath_nh_res.sh                 fail     fail     fail     fail     same
net/forwarding:hw_stats_l3.sh                          skip     skip     skip     skip     same
net/forwarding:hw_stats_l3_gre.sh                      skip     skip     skip     skip     same
net/forwarding:ip6_forward_instats_vrf.sh              skip     skip     skip     skip     same
net/forwarding:ip6gre_custom_multipath_hash.sh         fail     fail     fail     fail     same
net/forwarding:ip6gre_flat.sh                          pass     pass     pass     pass     same
net/forwarding:ip6gre_flat_key.sh                      pass     pass     pass     pass     same
net/forwarding:ip6gre_flat_keys.sh                     pass     pass     pass     pass     same
net/forwarding:ip6gre_hier.sh                          pass     pass     pass     pass     same
net/forwarding:ip6gre_hier_key.sh                      pass     pass     pass     pass     same
net/forwarding:ip6gre_hier_keys.sh                     pass     pass     pass     pass     same
net/forwarding:ip6gre_inner_v4_multipath.sh            pass     pass     pass     pass     same
net/forwarding:ipip_flat_gre.sh                        pass     pass     pass     pass     same
net/forwarding:ipip_flat_gre_key.sh                    pass     pass     pass     pass     same
net/forwarding:ipip_flat_gre_keys.sh                   pass     pass     pass     pass     same
net/forwarding:ipip_hier_gre.sh                        pass     pass     pass     pass     same
net/forwarding:ipip_hier_gre_key.sh                    pass     pass     pass     pass     same
net/forwarding:local_termination.sh                    skip     skip     skip     skip     same
net/forwarding:loopback.sh                             skip     skip     skip     skip     same
net/forwarding:mirror_gre.sh                           pass     pass     pass     pass     same
net/forwarding:mirror_gre_bound.sh                     pass     pass     pass     pass     same
net/forwarding:mirror_gre_bridge_1d.sh                 pass     pass     pass     pass     same
net/forwarding:mirror_gre_bridge_1q.sh                 pass     pass     pass     pass     same
net/forwarding:mirror_gre_bridge_1q_lag.sh             pass     pass     pass     pass     same
net/forwarding:mirror_gre_changes.sh                   pass     pass     pass     pass     same
net/forwarding:mirror_gre_flower.sh                    pass     pass     pass     pass     same
net/forwarding:mirror_gre_lag_lacp.sh                  pass     pass     pass     pass     same
net/forwarding:mirror_gre_neigh.sh                     pass     pass     pass     pass     same
net/forwarding:mirror_gre_nh.sh                        pass     pass     pass     pass     same
net/forwarding:mirror_gre_vlan.sh                      pass     pass     pass     pass     same
net/forwarding:mirror_vlan.sh                          pass     pass     pass     pass     same
net/forwarding:no_forwarding.sh                        pass     pass     pass     pass     same
net/forwarding:pedit_dsfield.sh                        pass     pass     pass     pass     same
net/forwarding:pedit_ip.sh                             pass     pass     pass     pass     same
net/forwarding:pedit_l4port.sh                         pass     pass     pass     pass     same
net/forwarding:q_in_vni_ipv6.sh                        pass     pass     pass     pass     same
net/forwarding:router.sh                               skip     skip     skip     skip     same
net/forwarding:router_bridge.sh                        pass     pass     pass     pass     same
net/forwarding:router_bridge_1d.sh                     pass     pass     pass     pass     same
net/forwarding:router_bridge_pvid_vlan_upper.sh        pass     pass     pass     pass     same
net/forwarding:router_bridge_vlan.sh                   pass     pass     pass     pass     same
net/forwarding:router_bridge_vlan_upper.sh             pass     pass     pass     pass     same
net/forwarding:router_bridge_vlan_upper_pvid.sh        pass     pass     pass     pass     same
net/forwarding:router_broadcast.sh                     pass     pass     pass     pass     same
net/forwarding:router_mpath_nh.sh                      fail     fail     fail     fail     same
net/forwarding:router_mpath_nh_res.sh                  pass     pass     pass     pass     same
net/forwarding:router_multicast.sh                     skip     skip     skip     skip     same
net/forwarding:router_multipath.sh                     fail     fail     fail     fail     same
net/forwarding:router_nh.sh                            pass     pass     pass     pass     same
net/forwarding:router_vid_1.sh                         pass     pass     pass     pass     same
net/forwarding:skbedit_priority.sh                     pass     pass     pass     pass     same
net/forwarding:tc_chains.sh                            pass     pass     pass     pass     same
net/forwarding:tc_flower.sh                            pass     pass     pass     pass     same
net/forwarding:tc_flower_cfm.sh                        fail     fail     fail     fail     same
net/forwarding:tc_flower_l2_miss.sh                    fail     fail     fail     fail     same
net/forwarding:tc_flower_router.sh                     pass     pass     pass     pass     same
net/forwarding:tc_mpls_l2vpn.sh                        pass     pass     pass     pass     same
net/forwarding:tc_shblocks.sh                          pass     pass     pass     pass     same
net/forwarding:tc_tunnel_key.sh                        skip     skip     skip     skip     same
net/forwarding:tc_vlan_modify.sh                       pass     pass     pass     pass     same
net/forwarding:vxlan_asymmetric.sh                     pass     pass     pass     pass     same
net/forwarding:vxlan_asymmetric_ipv6.sh                pass     pass     pass     pass     same
net/forwarding:vxlan_bridge_1d.sh                      pass     pass     pass     pass     same
net/forwarding:vxlan_bridge_1d_port_8472.sh            pass     pass     pass     pass     same
net/forwarding:vxlan_bridge_1d_port_8472_ipv6.sh       pass     pass     pass     pass     same
net/forwarding:vxlan_bridge_1q.sh                      pass     pass     pass     pass     same
net/forwarding:vxlan_bridge_1q_ipv6.sh                 pass     pass     pass     pass     same
net/forwarding:vxlan_bridge_1q_port_8472.sh            pass     pass     pass     pass     same
net/forwarding:vxlan_bridge_1q_port_8472_ipv6.sh       pass     pass     pass     pass     same
net/forwarding:vxlan_symmetric.sh                      pass     pass     pass     pass     same
net/forwarding:vxlan_symmetric_ipv6.sh                 pass     pass     pass     pass     same
net/hsr:hsr_ping.sh                                    fail     fail     fail     fail     same
net/mptcp:diag.sh                                      pass     pass     pass     pass     same
net/mptcp:mptcp_connect.sh                             pass     pass     pass     pass     same
net/mptcp:mptcp_sockopt.sh                             pass     pass     pass     pass     same
net/mptcp:pm_netlink.sh                                pass     pass     pass     pass     same
net:altnames.sh                                        pass     pass     pass     pass     same
net:bareudp.sh                                         pass     pass     pass     pass     same
net:big_tcp.sh                                         skip     skip     skip     skip     same
net:cmsg_so_mark.sh                                    pass     pass     pass     pass     same
net:devlink_port_split.py                              skip     skip     skip     skip     same
net:drop_monitor_tests.sh                              skip     skip     skip     skip     same
net:fcnal-test.sh                                      skip     skip     skip     skip     same
net:fib-onlink-tests.sh                                pass     pass     pass     pass     same
net:fib_nexthop_multiprefix.sh                         pass     pass     pass     pass     same
net:fib_nexthop_nongw.sh                               pass     pass     pass     pass     same
net:fib_rule_tests.sh                                  pass     pass     pass     pass     same
net:fib_tests.sh                                       fail     fail     fail     fail     same
net:fin_ack_lat.sh                                     pass     pass     pass     pass     same
net:gre_gso.sh                                         pass     pass     pass     pass     same
net:icmp.sh                                            fail     fail     fail     fail     same
net:icmp_redirect.sh                                   pass     pass     pass     pass     same
net:io_uring_zerocopy_tx.sh                            fail     fail     fail     fail     same
net:ip6_gre_headroom.sh                                pass     pass     pass     pass     same
net:ipv6_flowlabel.sh                                  pass     pass     pass     pass     same
net:l2_tos_ttl_inherit.sh                              skip     skip     skip     skip     same
net:l2tp.sh                                            pass     pass     pass     pass     same
net:msg_zerocopy.sh                                    pass     pass     pass     pass     same
net:netdevice.sh                                       pass     pass     pass     pass     same
net:pmtu.sh                                            fail     fail     fail     fail     same
net:psock_snd.sh                                       pass     pass     pass     pass     same
net:reuseaddr_conflict                                 pass     pass     pass     pass     same
net:reuseaddr_ports_exhausted.sh                       pass     pass     pass     pass     same
net:reuseport_bpf                                      pass     pass     pass     pass     same
net:reuseport_bpf_cpu                                  pass     pass     pass     pass     same
net:reuseport_bpf_numa                                 pass     pass     pass     pass     same
net:reuseport_dualstack                                pass     pass     pass     pass     same
net:route_localnet.sh                                  pass     pass     pass     pass     same
net:rps_default_mask.sh                                pass     pass     pass     pass     same
net:rtnetlink.sh                                       skip     skip     skip     skip     same
net:run_afpackettests                                  pass     pass     pass     pass     same
net:run_netsocktests                                   pass     pass     pass     pass     same
net:rxtimestamp.sh                                     pass     pass     pass     pass     same
net:so_txtime.sh                                       pass     pass     pass     pass     same
net:srv6_end_next_csid_l3vpn_test.sh                   pass     pass     pass     pass     same
net:srv6_hencap_red_l3vpn_test.sh                      pass     pass     pass     pass     same
net:srv6_hl2encap_red_l2vpn_test.sh                    pass     pass     pass     pass     same
net:stress_reuseport_listen.sh                         pass     pass     pass     pass     same
net:tcp_fastopen_backup_key.sh                         pass     pass     pass     pass     same
net:test_blackhole_dev.sh                              fail     fail     fail     fail     same
net:test_bpf.sh                                        pass     pass     pass     pass     same
net:test_bridge_neigh_suppress.sh                      skip     skip     skip     skip     same
net:test_vxlan_fdb_changelink.sh                       pass     pass     pass     pass     same
net:test_vxlan_under_vrf.sh                            pass     pass     pass     pass     same
net:tls                                                pass     pass     pass     pass     same
net:traceroute.sh                                      pass     pass     pass     pass     same
net:udpgro.sh                                          fail     fail     fail     fail     same
net:udpgro_bench.sh                                    fail     fail     fail     fail     same
net:udpgso.sh                                          pass     pass     pass     pass     same
net:unicast_extensions.sh                              pass     pass     pass     pass     same
net:veth.sh                                            fail     fail     fail     fail     same
net:vrf-xfrm-tests.sh                                  pass     pass     pass     pass     same
net:vrf_route_leaking.sh                               pass     pass     pass     pass     same
net:vrf_strict_mode_test.sh                            pass     pass     pass     pass     same
netfilter:bridge_brouter.sh                            skip     skip     skip     skip     same
netfilter:conntrack_icmp_related.sh                    fail     fail     fail     fail     same
netfilter:conntrack_tcp_unreplied.sh                   pass     pass     pass     pass     same
netfilter:conntrack_vrf.sh                             pass     pass     pass     pass     same
netfilter:ipvs.sh                                      pass     pass     pass     pass     same
netfilter:nf_nat_edemux.sh                             fail     fail     fail     fail     same
netfilter:nft_audit.sh                                 fail     fail     fail     fail     same
netfilter:nft_concat_range.sh                          fail     fail     fail     fail     same
netfilter:nft_conntrack_helper.sh                      skip     skip     skip     skip     same
netfilter:nft_fib.sh                                   skip     skip     skip     skip     same
netfilter:nft_flowtable.sh                             fail     fail     fail     fail     same
netfilter:nft_meta.sh                                  pass     pass     pass     pass     same
netfilter:nft_nat.sh                                   skip     skip     skip     skip     same
netfilter:nft_queue.sh                                 skip     skip     skip     skip     same
netfilter:rpath.sh                                     pass     pass     pass     pass     same
nsfs:owner                                             pass     pass     pass     pass     same
nsfs:pidns                                             pass     pass     pass     pass     same
pid_namespace:regression_enomem                        pass     pass     pass     pass     same
pidfd:pidfd_fdinfo_test                                pass     pass     pass     pass     same
pidfd:pidfd_getfd_test                                 pass     pass     pass     pass     same
pidfd:pidfd_open_test                                  pass     pass     pass     pass     same
pidfd:pidfd_poll_test                                  pass     pass     pass     pass     same
pidfd:pidfd_setns_test                                 pass     pass     pass     pass     same
pidfd:pidfd_test                                       pass     pass     pass     pass     same
pidfd:pidfd_wait                                       pass     pass     pass     pass     same
proc:fd-001-lookup                                     pass     pass     pass     pass     same
proc:fd-002-posix-eq                                   pass     pass     pass     pass     same
proc:fd-003-kthread                                    pass     pass     pass     pass     same
proc:proc-fsconfig-hidepid                             pass     pass     pass     pass     same
proc:proc-loadavg-001                                  pass     pass     pass     pass     same
proc:proc-multiple-procfs                              pass     pass     pass     pass     same
proc:proc-self-map-files-001                           pass     pass     pass     pass     same
proc:proc-self-map-files-002                           pass     pass     pass     pass     same
proc:proc-self-syscall                                 pass     pass     pass     pass     same
proc:proc-self-wchan                                   pass     pass     pass     pass     same
proc:proc-subset-pid                                   pass     pass     pass     pass     same
proc:proc-uptime-002                                   pass     pass     pass     pass     same
proc:read                                              pass     pass     pass     pass     same
proc:self                                              pass     pass     pass     pass     same
proc:setns-dcache                                      pass     pass     pass     pass     same
proc:setns-sysvipc                                     pass     pass     pass     pass     same
proc:thread-self                                       pass     pass     pass     pass     same
pstore:pstore_post_reboot_tests                        skip     skip     skip     skip     same
pstore:pstore_tests                                    fail     fail     fail     fail     same
ptrace:get_syscall_info                                pass     pass     pass     pass     same
ptrace:peeksiginfo                                     pass     pass     pass     pass     same
ptrace:vmaccess                                        fail     fail     fail     fail     same
rlimits:rlimits-per-userns                             pass     pass     pass     pass     same
rseq:basic_percpu_ops_test                             pass     pass     pass     pass     same
rseq:basic_test                                        pass     pass     pass     pass     same
rseq:param_test                                        pass     pass     pass     pass     same
rseq:param_test_benchmark                              pass     pass     pass     pass     same
rseq:param_test_compare_twice                          pass     pass     pass     pass     same
rseq:run_param_test.sh                                 pass     pass     pass     pass     same
seccomp:seccomp_benchmark                              pass     pass     pass     pass     same
seccomp:seccomp_bpf                                    pass     pass     pass     pass     same
sgx:test_sgx                                           fail     fail     fail     fail     same
sigaltstack:sas                                        pass     pass     pass     pass     same
size:get_size                                          pass     pass     pass     pass     same
splice:default_file_splice_read.sh                     pass     pass     pass     pass     same
splice:short_splice_read.sh                            fail     fail     fail     fail     same
static_keys:test_static_keys.sh                        skip     skip     skip     skip     same
syscall_user_dispatch:sud_benchmark                    pass     pass     pass     pass     same
syscall_user_dispatch:sud_test                         pass     pass     pass     pass     same
tc-testing:tdc.sh                                      fail     fail     fail     fail     same
tdx:tdx_guest_test                                     fail     fail     fail     fail     same
timens:clock_nanosleep                                 pass     pass     pass     pass     same
timens:exec                                            pass     pass     pass     pass     same
timens:futex                                           pass     pass     pass     pass     same
timens:procfs                                          pass     pass     pass     pass     same
timens:timens                                          pass     pass     pass     pass     same
timens:timer                                           pass     pass     pass     pass     same
timens:timerfd                                         pass     pass     pass     pass     same
timens:vfork_exec                                      pass     pass     pass     pass     same
timers:inconsistency-check                             pass     pass     pass     pass     same
timers:mqueue-lat                                      pass     pass     pass     pass     same
timers:nanosleep                                       pass     pass     pass     pass     same
timers:nsleep-lat                                      pass     pass     pass     pass     same
timers:posix_timers                                    pass     pass     pass     pass     same
timers:rtcpie                                          pass     pass     pass     pass     same
timers:set-timer-lat                                   pass     pass     pass     pass     same
timers:threadtest                                      pass     pass     pass     pass     same
tmpfs:bug-link-o-tmpfile                               pass     pass     pass     pass     same
tpm2:test_smoke.sh                                     skip     skip     skip     skip     same
tpm2:test_space.sh                                     skip     skip     skip     skip     same
tty:tty_tstamp_update                                  skip     skip     skip     skip     same
vDSO:vdso_standalone_test_x86                          pass     pass     pass     pass     same
vDSO:vdso_test_abi                                     pass     pass     pass     pass     same
vDSO:vdso_test_clock_getres                            pass     pass     pass     pass     same
vDSO:vdso_test_correctness                             pass     pass     pass     pass     same
vDSO:vdso_test_getcpu                                  pass     pass     pass     pass     same
vDSO:vdso_test_gettimeofday                            pass     pass     pass     pass     same
x86:amx_64                                             fail     fail     fail     fail     same
x86:check_initial_reg_state_64                         fail     fail     fail     fail     same
x86:corrupt_xstate_header_64                           fail     fail     fail     fail     same
x86:fsgsbase_64                                        fail     fail     fail     fail     same
x86:fsgsbase_restore_64                                fail     fail     fail     fail     same
x86:ioperm_64                                          fail     fail     fail     fail     same
x86:iopl_64                                            fail     fail     fail     fail     same
x86:lam_64                                             fail     fail     fail     fail     same
x86:mov_ss_trap_64                                     fail     fail     fail     fail     same
x86:sigaltstack_64                                     fail     fail     fail     fail     same
x86:sigreturn_64                                       fail     fail     fail     fail     same
x86:single_step_syscall_64                             fail     fail     fail     fail     same
x86:syscall_arg_fault_64                               fail     fail     fail     fail     same
x86:syscall_nt_64                                      fail     fail     fail     fail     same
x86:syscall_numbering_64                               fail     fail     fail     fail     same
x86:sysret_rip_64                                      fail     fail     fail     fail     same
x86:sysret_ss_attrs_64                                 fail     fail     fail     fail     same
x86:test_mremap_vdso_64                                fail     fail     fail     fail     same
x86:test_vsyscall_64                                   fail     fail     fail     fail     same
zram:zram.sh                                           pass     pass     pass     pass     same

Appendix: Backports Overview

Author Date Upstream Subject LTS 9.4 LTS 9.2 CentOS 10 CentOS 9 6.6 6.1 5.15 5.10 Assoc CVE
2025-09-15 14967a9 . `mm/hugetlb: fix copy_hugetlb_page_range() to use ->pt_share_count` be320bb b d6bf5cc b             CVE-2024-57883 (bf)
2025-05-27 1013af4 . `mm/hugetlb: fix huge_pmd_unshare() vs GUP-fast race` cadd0db b 338dd38 b 41f7eb5 b 12a6db3 b fe6842904 b b7754d3aa b a3d864c90 b 952596b08 b CVE-2025-38085 (fix)
2025-05-27 081056d . `mm/hugetlb: unshare page tables during VMA split, not before` df7493f b ad741c4 b f253fee b 320a3c8 b af6cfcd0e b 2511ac64b b 366298f2b b e8847d18c b CVE-2025-38084 (fix)
2025-05-23 ee40c99 . `mm: fix copy_vma() error handling for hugetlb mappings` x x f283d0c b 9f35408 b x x x x  
2024-12-16 59d9094 . `mm: hugetlb: independent PMD page table shared count` 3806623 b 8ce465b b fc9e2f1 x 56b2744 u 02333ac1c b 8410996eb b 94b4b41d0 b CVE-2025-38085 (pre), CVE-2024-57883 (fix)
2023-01-04 b30c14c . `hugetlb: unshare some PMDs when splitting VMAs` 563b6f5 b f45e262 b b30c14c . fe1df9d u b30c14c . 63f71b8 u bd9a23a u f1082f5f3 b CVE-2025-38084 (pre)
2022-11-25 2ba99c5 . `mm/khugepaged: fix GUP-fast interaction by sending IPI` f4c1e18 u 937d0cb b             CVE-2025-38085 (pre)
2022-08-16 3aa4ed8 . `mm/hugetlb: make detecting shared pte more reliable` 643137f u e12ebf6 b             CVE-2024-57883 (pre-bf)
b Backported as part of CVE solution
u Unrelated backport
. Upstream

@pvts-mat pvts-mat marked this pull request as ready for review January 20, 2026 17:13
@github-actions
Copy link

🤖 Validation Checks In Progress Workflow run: https://github.com/ctrliq/kernel-src-tree/actions/runs/21229505497

@github-actions
Copy link

🔍 Upstream Linux Kernel Commit Check

  • ⚠️ PR commit 38066238ac6 (mm: hugetlb: independent PMD page table shared count) references upstream commit
    59d9094df3d7 which has been referenced by a Fixes: tag in the upstream
    Linux kernel:
    a8682d500f6 mm/rmap: fix two comments related to huge_pmd_unshare() (David Hildenbrand (Red Hat))
    3937027caec mm/hugetlb: fix two comments related to huge_pmd_unshare() (David Hildenbrand (Red Hat))
    ca1a47cd3f5 mm/hugetlb: fix hugetlb_pmd_shared() (David Hildenbrand (Red Hat))
  • ⚠️ PR commit cadd0dbaf2e (mm/hugetlb: fix huge_pmd_unshare() vs GUP-fast race) references upstream commit
    1013af4f585f which has been referenced by a Fixes: tag in the upstream
    Linux kernel:
    8ce720d5bd9 mm/hugetlb: fix excessive IPI broadcasts when unsharing PMD tables using mmu_gather (David Hildenbrand (Red Hat))

This is an automated message from the kernel commit checker workflow.

@github-actions
Copy link

🔍 Interdiff Analysis

  • ⚠️ PR commit 563b6f5c75f (hugetlb: unshare some PMDs when splitting VMAs) → upstream b30c14cd6102
    Differences found:
diff -u b/mm/hugetlb.c b/mm/hugetlb.c
--- b/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -7358,9 +7377,6 @@ INTERDIFF: rejected hunk from patch2, cannot diff context
 	if (!(vma->vm_flags & VM_MAYSHARE))
 		return;
 
-	start = ALIGN(vma->vm_start, PUD_SIZE);
-	end = ALIGN_DOWN(vma->vm_end, PUD_SIZE);
-
 	if (start >= end)
 		return;
 
@@ -7375,9 +7394,6 @@ INTERDIFF: rejected hunk from patch1, cannot diff context
 	if (!(vma->vm_flags & VM_MAYSHARE))
 		return;
 
-	start = ALIGN(vma->vm_start, PUD_SIZE);
-	end = ALIGN_DOWN(vma->vm_end, PUD_SIZE);
-
 	if (start >= end)
 		return;
  • ⚠️ PR commit df7493f7311 (mm/hugetlb: unshare page tables during VMA split, not before) → upstream 081056dc00a2
    Differences found:
diff -u b/include/linux/hugetlb.h b/include/linux/hugetlb.h
--- b/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -255,6 +255,7 @@ INTERDIFF: rejected hunk from patch1, cannot diff context
 
 bool is_hugetlb_entry_migration(pte_t pte);
 void hugetlb_unshare_all_pmds(struct vm_area_struct *vma);
+void hugetlb_split(struct vm_area_struct *vma, unsigned long addr);
 
 #else /* !CONFIG_HUGETLB_PAGE */
 
@@ -279,6 +279,7 @@ INTERDIFF: rejected hunk from patch2, cannot diff context
 bool is_hugetlb_entry_hwpoisoned(pte_t pte);
 void hugetlb_unshare_all_pmds(struct vm_area_struct *vma);
 void fixup_hugetlb_reservations(struct vm_area_struct *vma);
+void hugetlb_split(struct vm_area_struct *vma, unsigned long addr);
 
 #else /* !CONFIG_HUGETLB_PAGE */
 
@@ -461,8 +461,8 @@
-{
-}
+
+static inline void hugetlb_unshare_all_pmds(struct vm_area_struct *vma) { }
 
 static inline void hugetlb_split(struct vm_area_struct *vma, unsigned long addr) {}
 
 #endif /* !CONFIG_HUGETLB_PAGE */
-
-#ifndef pgd_write
+/*
+ * hugepages at page global directory. If arch support
diff -u b/mm/hugetlb.c b/mm/hugetlb.c
--- b/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -95,7 +95,7 @@ INTERDIFF: rejected hunk from patch1, cannot diff context
 static void hugetlb_vma_lock_alloc(struct vm_area_struct *vma);
 static void __hugetlb_vma_unlock_write_free(struct vm_area_struct *vma);
 static void hugetlb_unshare_pmds(struct vm_area_struct *vma,
-		unsigned long start, unsigned long end);
+		unsigned long start, unsigned long end, bool take_locks);
 
 static inline bool subpool_is_free(struct hugepage_subpool *spool)
 {
@@ -121,7 +121,7 @@ INTERDIFF: rejected hunk from patch2, cannot diff context
 static void hugetlb_vma_lock_alloc(struct vm_area_struct *vma);
 static void __hugetlb_vma_unlock_write_free(struct vm_area_struct *vma);
 static void hugetlb_unshare_pmds(struct vm_area_struct *vma,
-		unsigned long start, unsigned long end);
+		unsigned long start, unsigned long end, bool take_locks);
 static struct resv_map *vma_resv_map(struct vm_area_struct *vma);
 
 static void hugetlb_free_folio(struct folio *folio)
@@ -4846,7 +4846,7 @@
 	 * MM, VMA and rmap all write-locked to prevent concurrent page table
 	 * walks (except hardware and gup_fast()).
 	 */
-	mmap_assert_write_locked(vma->vm_mm);
+	vma_assert_write_locked(vma);
 	i_mmap_assert_write_locked(vma->vm_file->f_mapping);
 
 	if (addr & ~PUD_MASK) {
@@ -7371,4 +7371,4 @@
-	spin_unlock_irq(&hugetlb_lock);
+	}
 }
 
 /*
@@ -7404,4 +7404,4 @@
-	mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm,
+	mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, mm,
 				start, end);
 	mmu_notifier_invalidate_range_start(&range);
 	if (take_locks) {
@@ -7444,4 +7444,4 @@
 			/* take_locks = */ true);
 }
 
-/*
+#ifdef CONFIG_CMA
reverted:
--- b/mm/mmap.c
+++ a/mm/mmap.c
@@ -815,15 +815,7 @@
 		}
 	}
 again:
-	/*
-	 * Get rid of huge pages and shared page tables straddling the split
-	 * boundary.
-	 */
 	vma_adjust_trans_huge(orig_vma, start, end, adjust_next);
-	if (is_vm_hugetlb_page(orig_vma)) {
-		hugetlb_split(orig_vma, start);
-		hugetlb_split(orig_vma, end);
-	}
 
 	if (file) {
 		mapping = file->f_mapping;
only in patch2:
unchanged:
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -539,7 +539,14 @@ __split_vma(struct vma_iterator *vmi, struct vm_area_struct *vma,
 	init_vma_prep(&vp, vma);
 	vp.insert = new;
 	vma_prepare(&vp);
+
+	/*
+	 * Get rid of huge pages and shared page tables straddling the split
+	 * boundary.
+	 */
 	vma_adjust_trans_huge(vma, vma->vm_start, addr, NULL);
+	if (is_vm_hugetlb_page(vma))
+		hugetlb_split(vma, addr);
 
 	if (new_below) {
 		vma->vm_start = addr;
only in patch2:
unchanged:
--- a/tools/testing/vma/vma_internal.h
+++ b/tools/testing/vma/vma_internal.h
@@ -932,6 +932,8 @@ static inline void vma_adjust_trans_huge(struct vm_area_struct *vma,
 	(void)next;
 }
 
+static inline void hugetlb_split(struct vm_area_struct *, unsigned long) {}
+
 static inline void vma_iter_free(struct vma_iterator *vmi)
 {
 	mas_destroy(&vmi->mas);
  • ⚠️ PR commit 38066238ac6 (mm: hugetlb: independent PMD page table shared count) → upstream 59d9094df3d7
    Differences found:
diff -u b/include/linux/mm.h b/include/linux/mm.h
--- b/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2536,6 +2536,6 @@
-	if (!pmd_ptlock_init(ptdesc))
+	if (!pmd_ptlock_init(page))
 		return false;
-	__folio_set_pgtable(folio);
-	lruvec_stat_add_folio(folio, NR_PAGETABLE);
+	__SetPageTable(page);
+	inc_lruvec_page_state(page, NR_PAGETABLE);
 	return true;
 }
@@ -2539,6 +2539,9 @@ INTERDIFF: rejected hunk from patch1, cannot diff context
 	if (!pmd_ptlock_init(page))
 		return false;
 	__SetPageTable(page);
+#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
+	atomic_set(&page->pt_share_count, 0);
+#endif
 	inc_lruvec_page_state(page, NR_PAGETABLE);
 	return true;
 }
@@ -3125,6 +3125,7 @@ INTERDIFF: rejected hunk from patch2, cannot diff context
 	if (!pmd_ptlock_init(ptdesc))
 		return false;
 	__folio_set_pgtable(folio);
+	ptdesc_pmd_pts_init(ptdesc);
 	lruvec_stat_add_folio(folio, NR_PAGETABLE);
 	return true;
 }
diff -u b/include/linux/mm_types.h b/include/linux/mm_types.h
--- b/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -170,6 +170,18446744073709551610 @@
-	const struct page *:		(const struct ptdesc *)(p),	\
-	struct page *:			(struct ptdesc *)(p)))
-
-/*
- * Used for sizing the vmemmap region on some architectures
- */
+			union {
+				struct mm_struct *pt_mm; /* x86 pgds only */
+				atomic_t pt_frag_refcount; /* powerpc */
+			};
+#if ALLOC_SPLIT_PTLOCKS
+			spinlock_t *ptl;
@@ -173,6 +173,9 @@ INTERDIFF: rejected hunk from patch1, cannot diff context
 			union {
 				struct mm_struct *pt_mm; /* x86 pgds only */
 				atomic_t pt_frag_refcount; /* powerpc */
+#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
+				RH_KABI_BROKEN_INSERT(atomic_t pt_share_count)
+#endif
 			};
 #if ALLOC_SPLIT_PTLOCKS
 			spinlock_t *ptl;
@@ -445,6 +445,7 @@ INTERDIFF: rejected hunk from patch2, cannot diff context
  * @pt_index:         Used for s390 gmap.
  * @pt_mm:            Used for x86 pgds.
  * @pt_frag_refcount: For fragmented page table tracking. Powerpc only.
+ * @pt_share_count:   Used for HugeTLB PMD page table share count.
  * @_pt_pad_2:        Padding to ensure proper alignment.
  * @ptl:              Lock for the page table.
  * @__page_type:      Same as page->page_type. Unused for page tables.
@@ -471,6 +472,9 @@ INTERDIFF: rejected hunk from patch2, cannot diff context
 		pgoff_t pt_index;
 		struct mm_struct *pt_mm;
 		atomic_t pt_frag_refcount;
+#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING
+		atomic_t pt_share_count;
+#endif
 	};
 
 	union {
@@ -516,6 +520,32 @@ INTERDIFF: rejected hunk from patch2, cannot diff context
 	const struct page *:		(const struct ptdesc *)(p),	\
 	struct page *:			(struct ptdesc *)(p)))
 
+#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING
+static inline void ptdesc_pmd_pts_init(struct ptdesc *ptdesc)
+{
+	atomic_set(&ptdesc->pt_share_count, 0);
+}
+
+static inline void ptdesc_pmd_pts_inc(struct ptdesc *ptdesc)
+{
+	atomic_inc(&ptdesc->pt_share_count);
+}
+
+static inline void ptdesc_pmd_pts_dec(struct ptdesc *ptdesc)
+{
+	atomic_dec(&ptdesc->pt_share_count);
+}
+
+static inline int ptdesc_pmd_pts_count(struct ptdesc *ptdesc)
+{
+	return atomic_read(&ptdesc->pt_share_count);
+}
+#else
+static inline void ptdesc_pmd_pts_init(struct ptdesc *ptdesc)
+{
+}
+#endif
+
 /*
  * Used for sizing the vmemmap region on some architectures
  */
  • ⚠️ PR commit cadd0dbaf2e (mm/hugetlb: fix huge_pmd_unshare() vs GUP-fast race) → upstream 1013af4f585f
    Differences found:
diff -u b/mm/hugetlb.c b/mm/hugetlb.c
--- b/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -7139,5 +7139,5 @@
 
 	pud_clear(pud);
-	ptdesc_pmd_pts_dec(virt_to_ptdesc(ptep));
+	atomic_dec(&virt_to_page(ptep)->pt_share_count);
 	mm_dec_nr_pmds(mm);
 	return 1;
@@ -7141,6 +7141,13 @@ INTERDIFF: rejected hunk from patch1, cannot diff context
 		return 0;
 
 	pud_clear(pud);
+	/*
+	 * Once our caller drops the rmap lock, some other process might be
+	 * using this page table as a normal, non-hugetlb page table.
+	 * Wait for pending gup_fast() in other threads to finish before letting
+	 * that happen.
+	 */
+	tlb_remove_table_sync_one();
 	atomic_dec(&virt_to_page(ptep)->pt_share_count);
 	mm_dec_nr_pmds(mm);
 	return 1;
@@ -7629,6 +7629,13 @@ INTERDIFF: rejected hunk from patch2, cannot diff context
 		return 0;
 
 	pud_clear(pud);
+	/*
+	 * Once our caller drops the rmap lock, some other process might be
+	 * using this page table as a normal, non-hugetlb page table.
+	 * Wait for pending gup_fast() in other threads to finish before letting
+	 * that happen.
+	 */
+	tlb_remove_table_sync_one();
 	ptdesc_pmd_pts_dec(virt_to_ptdesc(ptep));
 	mm_dec_nr_pmds(mm);
 	return 1;
  • ⚠️ PR commit e672b90b12c (mm/hugetlb: fix copy_hugetlb_page_range() to use ->pt_share_count) → upstream 14967a9c7d24
    Differences found:
diff -u b/mm/hugetlb.c b/mm/hugetlb.c
--- b/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -5013,9 +5013,9 @@
 			break;
 		}
 
-#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
+#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING
 		/* If the pagetables are shared, there is nothing to do */
-		if (atomic_read(&virt_to_page(dst_pte)->pt_share_count)) {
+		if (ptdesc_pmd_is_shared(virt_to_ptdesc(dst_pte))) {
 			addr |= last_addr_mask;
 			continue;
 		}
@@ -5023,7 +5023,0 @@
-	hugetlb_vma_assert_locked(vma);
-	if (sz != PMD_SIZE)
-		return 0;
-	if (!ptdesc_pmd_pts_count(virt_to_ptdesc(ptep)))
-		return 0;
-
-	pud_clear(pud);
@@ -7597,7 +7592,7 @@ INTERDIFF: rejected hunk from patch2, cannot diff context
 	hugetlb_vma_assert_locked(vma);
 	if (sz != PMD_SIZE)
 		return 0;
-	if (!ptdesc_pmd_pts_count(virt_to_ptdesc(ptep)))
+	if (!ptdesc_pmd_is_shared(virt_to_ptdesc(ptep)))
 		return 0;
 
 	pud_clear(pud);
only in patch2:
unchanged:
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -631,6 +631,11 @@ static inline int ptdesc_pmd_pts_count(struct ptdesc *ptdesc)
 {
 	return atomic_read(&ptdesc->pt_share_count);
 }
+
+static inline bool ptdesc_pmd_is_shared(struct ptdesc *ptdesc)
+{
+	return !!ptdesc_pmd_pts_count(ptdesc);
+}
 #else
 static inline void ptdesc_pmd_pts_init(struct ptdesc *ptdesc)
 {

This is an automated interdiff check for backported commits.

@github-actions
Copy link

JIRA PR Check Results

5 commit(s) with issues found:

Commit e672b90b12cb

Summary: mm/hugetlb: fix copy_hugetlb_page_range() to use ->pt_share_count

❌ Errors:

  • VULN-46930: Status is 'To Do', expected 'In Progress'

⚠️ Warnings:

  • VULN-46930: No time logged - please log time manually

Commit cadd0dbaf2e0

Summary: mm/hugetlb: fix huge_pmd_unshare() vs GUP-fast race

❌ Errors:

  • VULN-71587: Status is 'To Do', expected 'In Progress'

⚠️ Warnings:

  • VULN-71587: No time logged - please log time manually

Commit 38066238ac6b

Summary: mm: hugetlb: independent PMD page table shared count

❌ Errors:

  • VULN-46930: Status is 'To Do', expected 'In Progress'

⚠️ Warnings:

  • VULN-46930: No time logged - please log time manually

Commit df7493f7311e

Summary: mm/hugetlb: unshare page tables during VMA split, not before

❌ Errors:

  • VULN-71578: Status is 'To Do', expected 'In Progress'

⚠️ Warnings:

  • VULN-71578: No time logged - please log time manually

Commit 563b6f5c75f3

Summary: hugetlb: unshare some PMDs when splitting VMAs

❌ Errors:

  • VULN-71578: Status is 'To Do', expected 'In Progress'

⚠️ Warnings:

  • VULN-71578: No time logged - please log time manually

Summary: Checked 5 commit(s) total.

@github-actions
Copy link

Validation checks completed with issues View full results: https://github.com/ctrliq/kernel-src-tree/actions/runs/21229505497

@pvts-mat
Copy link
Contributor Author

🔍 Upstream Linux Kernel Commit Check

* ⚠️ PR commit `38066238ac6 (mm: hugetlb: independent PMD page table shared count)` references upstream commit
  `59d9094df3d7` which has been referenced by a `Fixes:` tag in the upstream
  Linux kernel:
    a8682d500f6 mm/rmap: fix two comments related to huge_pmd_unshare() (David Hildenbrand (Red Hat))
    3937027caec mm/hugetlb: fix two comments related to huge_pmd_unshare() (David Hildenbrand (Red Hat))
    ca1a47cd3f5 mm/hugetlb: fix hugetlb_pmd_shared() (David Hildenbrand (Red Hat))
* ⚠️ PR commit `cadd0dbaf2e (mm/hugetlb: fix huge_pmd_unshare() vs GUP-fast race)` references upstream commit
  `1013af4f585f` which has been referenced by a `Fixes:` tag in the upstream
  Linux kernel:
    8ce720d5bd9 mm/hugetlb: fix excessive IPI broadcasts when unsharing PMD tables using mmu_gather (David Hildenbrand (Red Hat))

This is an automated message from the kernel commit checker workflow.

Fresh fixes just from yesterday. Thanks, bot.
Include them in this PR @PlaidCat?

@roxanan1996
Copy link
Contributor

🔍 Upstream Linux Kernel Commit Check

* ⚠️ PR commit `38066238ac6 (mm: hugetlb: independent PMD page table shared count)` references upstream commit
  `59d9094df3d7` which has been referenced by a `Fixes:` tag in the upstream
  Linux kernel:
    a8682d500f6 mm/rmap: fix two comments related to huge_pmd_unshare() (David Hildenbrand (Red Hat))
    3937027caec mm/hugetlb: fix two comments related to huge_pmd_unshare() (David Hildenbrand (Red Hat))
    ca1a47cd3f5 mm/hugetlb: fix hugetlb_pmd_shared() (David Hildenbrand (Red Hat))
* ⚠️ PR commit `cadd0dbaf2e (mm/hugetlb: fix huge_pmd_unshare() vs GUP-fast race)` references upstream commit
  `1013af4f585f` which has been referenced by a `Fixes:` tag in the upstream
  Linux kernel:
    8ce720d5bd9 mm/hugetlb: fix excessive IPI broadcasts when unsharing PMD tables using mmu_gather (David Hildenbrand (Red Hat))

This is an automated message from the kernel commit checker workflow.

Fresh fixes just from yesterday. Thanks, bot. Include them in this PR @PlaidCat?

Yeah, please. It nice to have the cve-bf next to commit they fix. As long as the pr does not get too big.

@PlaidCat
Copy link
Collaborator

🔍 Upstream Linux Kernel Commit Check

* ⚠️ PR commit `38066238ac6 (mm: hugetlb: independent PMD page table shared count)` references upstream commit
  `59d9094df3d7` which has been referenced by a `Fixes:` tag in the upstream
  Linux kernel:
    a8682d500f6 mm/rmap: fix two comments related to huge_pmd_unshare() (David Hildenbrand (Red Hat))
    3937027caec mm/hugetlb: fix two comments related to huge_pmd_unshare() (David Hildenbrand (Red Hat))
    ca1a47cd3f5 mm/hugetlb: fix hugetlb_pmd_shared() (David Hildenbrand (Red Hat))
* ⚠️ PR commit `cadd0dbaf2e (mm/hugetlb: fix huge_pmd_unshare() vs GUP-fast race)` references upstream commit
  `1013af4f585f` which has been referenced by a `Fixes:` tag in the upstream
  Linux kernel:
    8ce720d5bd9 mm/hugetlb: fix excessive IPI broadcasts when unsharing PMD tables using mmu_gather (David Hildenbrand (Red Hat))

This is an automated message from the kernel commit checker workflow.

Fresh fixes just from yesterday. Thanks, bot. Include them in this PR @PlaidCat?

Yeah, please. It nice to have the cve-bf next to commit they fix. As long as the pr does not get too big.

@pvts-mat what @roxanan1996 said, if it gets super complex with the bug fixes and or additional pre-conditionals please note and we can potentially wave the Bug Fixes

@pvts-mat
Copy link
Contributor Author

Just dropping an update that this PR gets worked on, but this one bugfix mm/hugetlb: fix excessive IPI broadcasts when unsharing PMD tables using mmu_gather is just nasty - big, many conflicts, no other backports to compare with, and just when I got it nicely tailored to LTS 9.4 the kABI turned out to be broken. After much analysis it's still not clear whether it's a phony breakage to dismiss with one of RH_KABI_* magic spells, but the best part is that they don't work anyway...

I'll be arguing for dropping this fix, building the case now. Will update the PR soon.

@PlaidCat
Copy link
Collaborator

Just dropping an update that this PR gets worked on, but this one bugfix mm/hugetlb: fix excessive IPI broadcasts when unsharing PMD tables using mmu_gather is just nasty - big, many conflicts, no other backports to compare with, and just when I got it nicely tailored to LTS 9.4 the kABI turned out to be broken. After much analysis it's still not clear whether it's a phony breakage to dismiss with one of RH_KABI_* magic spells, but the best part is that they don't work anyway...

I'll be arguing for dropping this fix, building the case now. Will update the PR soon.

Not all bugfixes need to be backported as sometimes its a bigger issue than the fix

@PlaidCat
Copy link
Collaborator

PlaidCat commented Feb 3, 2026

Just dropping an update that this PR gets worked on, but this one bugfix mm/hugetlb: fix excessive IPI broadcasts when unsharing PMD tables using mmu_gather is just nasty - big, many conflicts,

In case this wasn't clear please don't include this

@pvts-mat
Copy link
Contributor Author

pvts-mat commented Feb 3, 2026

Just dropping an update that this PR gets worked on, but this one bugfix mm/hugetlb: fix excessive IPI broadcasts when unsharing PMD tables using mmu_gather is just nasty - big, many conflicts,

In case this wasn't clear please don't include this

Yeah, I just wanted to provide some explanation. Added the "CVE-2024-57883 fresh fixes" section and expanded the "Commits" one. Three out of four fixes were included.

jira VULN-71578
cve-pre CVE-2025-38084
commit-author James Houghton <[email protected]>
commit b30c14c

PMD sharing can only be done in PUD_SIZE-aligned pieces of VMAs; however,
it is possible that HugeTLB VMAs are split without unsharing the PMDs
first.

Without this fix, it is possible to hit the uffd-wp-related WARN_ON_ONCE
in hugetlb_change_protection [1].  The key there is that
hugetlb_unshare_all_pmds will not attempt to unshare PMDs in
non-PUD_SIZE-aligned sections of the VMA.

It might seem ideal to unshare in hugetlb_vm_op_open, but we need to
unshare in both the new and old VMAs, so unsharing in hugetlb_vm_op_split
seems natural.

[1]: https://lore.kernel.org/linux-mm/CADrL8HVeOkj0QH5VZZbRzybNE8CG-tEGFshnA+bG9nMgcWtBSg@mail.gmail.com/

Link: https://lkml.kernel.org/r/[email protected]
Fixes: 6dfeaff ("hugetlb/userfaultfd: unshare all pmds for hugetlbfs when register wp")
	Signed-off-by: James Houghton <[email protected]>
	Reviewed-by: Mike Kravetz <[email protected]>
	Acked-by: Peter Xu <[email protected]>
	Cc: Axel Rasmussen <[email protected]>
	Cc: Muchun Song <[email protected]>
	Cc: <[email protected]>
	Signed-off-by: Andrew Morton <[email protected]>
(cherry picked from commit b30c14c)
	Signed-off-by: Marcin Wcisło <[email protected]>
jira VULN-71578
cve CVE-2025-38084
commit-author Jann Horn <[email protected]>
commit 081056d
upstream-diff Used linux-5.15.y backport
  366298f2b04d2bf1f2f2b7078405bdf9df9bd5d0 as a base. Modified
  `hugetlb_unshare_pmds()' to wrap in the `take_lock == true' branches
  what was there originally. This change is the equivalent of applying
  upstream 081056d to the `hugetlb_unshare_pmds()' function and
  linux-5.15.y backport 366298f to everything else.

Currently, __split_vma() triggers hugetlb page table unsharing through
vm_ops->may_split().  This happens before the VMA lock and rmap locks are
taken - which is too early, it allows racing VMA-locked page faults in our
process and racing rmap walks from other processes to cause page tables to
be shared again before we actually perform the split.

Fix it by explicitly calling into the hugetlb unshare logic from
__split_vma() in the same place where THP splitting also happens.  At that
point, both the VMA and the rmap(s) are write-locked.

An annoying detail is that we can now call into the helper
hugetlb_unshare_pmds() from two different locking contexts:

1. from hugetlb_split(), holding:
    - mmap lock (exclusively)
    - VMA lock
    - file rmap lock (exclusively)
2. hugetlb_unshare_all_pmds(), which I think is designed to be able to
   call us with only the mmap lock held (in shared mode), but currently
   only runs while holding mmap lock (exclusively) and VMA lock

Backporting note:
This commit fixes a racy protection that was introduced in commit
b30c14c ("hugetlb: unshare some PMDs when splitting VMAs"); that
commit claimed to fix an issue introduced in 5.13, but it should actually
also go all the way back.

[[email protected]: v2]
  Link: https://lkml.kernel.org/r/[email protected]
Link: https://lkml.kernel.org/r/[email protected]
Link: https://lkml.kernel.org/r/[email protected]
Fixes: 39dde65 ("[PATCH] shared page table for hugetlb page")
	Signed-off-by: Jann Horn <[email protected]>
	Cc: Liam Howlett <[email protected]>
	Reviewed-by: Lorenzo Stoakes <[email protected]>
	Reviewed-by: Oscar Salvador <[email protected]>
	Cc: Lorenzo Stoakes <[email protected]>
	Cc: Vlastimil Babka <[email protected]>
	Cc: <[email protected]>	[b30c14c: hugetlb: unshare some PMDs when splitting VMAs]
	Cc: <[email protected]>
	Signed-off-by: Andrew Morton <[email protected]>
(cherry picked from commit 366298f2b04d2bf1f2f2b7078405bdf9df9bd5d0)
	Signed-off-by: Marcin Wcisło <[email protected]>
jira VULN-46930
cve CVE-2024-57883
commit-author Liu Shixin <[email protected]>
commit 59d9094
upstream-diff Stable 6.1 backport
  02333ac1c35370517a19a4a131332a9690c6a5c7 was used for the actual
  (clean) cherry pick. Additionally the `atomic_t pt_share_count' field
  in `include/linux/mm_types.h' was wrapped in RH_KABI_BROKEN_INSERT
  macro to avoid kABI checker complains. It's justified, because the
  inserted field (it's included, as CONFIG_ARCH_WANT_HUGE_PMD_SHARE gets
  enabled for at least `kernel-x86_64-rhel.config') is placed within a
  union which already contained a field of the same type `atomic_t
  pt_frag_refcount', so the size of it cannot change. Moreover this
  union serves as a scratch space for the subsystems using the struct
  page. Upon releasing the ownership to buddy allocator the union
  contents no longer matter. When the page is allocated again the
  scratch space will be used by the new owner in its own way.

The folio refcount may be increased unexpectly through try_get_folio() by
caller such as split_huge_pages.  In huge_pmd_unshare(), we use refcount
to check whether a pmd page table is shared.  The check is incorrect if
the refcount is increased by the above caller, and this can cause the page
table leaked:

 BUG: Bad page state in process sh  pfn:109324
 page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x66 pfn:0x109324
 flags: 0x17ffff800000000(node=0|zone=2|lastcpupid=0xfffff)
 page_type: f2(table)
 raw: 017ffff800000000 0000000000000000 0000000000000000 0000000000000000
 raw: 0000000000000066 0000000000000000 00000000f2000000 0000000000000000
 page dumped because: nonzero mapcount
 ...
 CPU: 31 UID: 0 PID: 7515 Comm: sh Kdump: loaded Tainted: G    B              6.13.0-rc2master+ ctrliq#7
 Tainted: [B]=BAD_PAGE
 Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
 Call trace:
  show_stack+0x20/0x38 (C)
  dump_stack_lvl+0x80/0xf8
  dump_stack+0x18/0x28
  bad_page+0x8c/0x130
  free_page_is_bad_report+0xa4/0xb0
  free_unref_page+0x3cc/0x620
  __folio_put+0xf4/0x158
  split_huge_pages_all+0x1e0/0x3e8
  split_huge_pages_write+0x25c/0x2d8
  full_proxy_write+0x64/0xd8
  vfs_write+0xcc/0x280
  ksys_write+0x70/0x110
  __arm64_sys_write+0x24/0x38
  invoke_syscall+0x50/0x120
  el0_svc_common.constprop.0+0xc8/0xf0
  do_el0_svc+0x24/0x38
  el0_svc+0x34/0x128
  el0t_64_sync_handler+0xc8/0xd0
  el0t_64_sync+0x190/0x198

The issue may be triggered by damon, offline_page, page_idle, etc, which
will increase the refcount of page table.

1. The page table itself will be discarded after reporting the
   "nonzero mapcount".

2. The HugeTLB page mapped by the page table miss freeing since we
   treat the page table as shared and a shared page table will not be
   unmapped.

Fix it by introducing independent PMD page table shared count.  As
described by comment, pt_index/pt_mm/pt_frag_refcount are used for s390
gmap, x86 pgds and powerpc, pt_share_count is used for x86/arm64/riscv
pmds, so we can reuse the field as pt_share_count.

Link: https://lkml.kernel.org/r/[email protected]
Fixes: 39dde65 ("[PATCH] shared page table for hugetlb page")
	Signed-off-by: Liu Shixin <[email protected]>
	Cc: Kefeng Wang <[email protected]>
	Cc: Ken Chen <[email protected]>
	Cc: Muchun Song <[email protected]>
	Cc: Nanyong Sun <[email protected]>
	Cc: Jane Chu <[email protected]>
	Cc: <[email protected]>
	Signed-off-by: Andrew Morton <[email protected]>
(cherry picked from commit 02333ac1c35370517a19a4a131332a9690c6a5c7)
	Signed-off-by: Marcin Wcisło <[email protected]>
jira VULN-71587
cve CVE-2025-38085
commit-author Jann Horn <[email protected]>
commit 1013af4
upstream-diff Stable 6.1 b7754d3aa7bf9f62218d096c0c8f6c13698fac8b was
  used for the actual (clean) cherry pick

huge_pmd_unshare() drops a reference on a page table that may have
previously been shared across processes, potentially turning it into a
normal page table used in another process in which unrelated VMAs can
afterwards be installed.

If this happens in the middle of a concurrent gup_fast(), gup_fast() could
end up walking the page tables of another process.  While I don't see any
way in which that immediately leads to kernel memory corruption, it is
really weird and unexpected.

Fix it with an explicit broadcast IPI through tlb_remove_table_sync_one(),
just like we do in khugepaged when removing page tables for a THP
collapse.

Link: https://lkml.kernel.org/r/[email protected]
Link: https://lkml.kernel.org/r/[email protected]
Fixes: 39dde65 ("[PATCH] shared page table for hugetlb page")
	Signed-off-by: Jann Horn <[email protected]>
	Reviewed-by: Lorenzo Stoakes <[email protected]>
	Cc: Liam Howlett <[email protected]>
	Cc: Muchun Song <[email protected]>
	Cc: Oscar Salvador <[email protected]>
	Cc: Vlastimil Babka <[email protected]>
	Cc: <[email protected]>
	Signed-off-by: Andrew Morton <[email protected]>
(cherry picked from commit b7754d3aa7bf9f62218d096c0c8f6c13698fac8b)
	Signed-off-by: Marcin Wcisło <[email protected]>
jira VULN-46930
cve-bf CVE-2024-57883
commit-author Jane Chu <[email protected]>
commit 14967a9
upstream-diff This commit fixes `mm: hugetlb: independent PMD page
  table shared count' which was included in ciqlts9_4 by cherry-picking
  stable-6.1 backport 02333ac1c35370517a19a4a131332a9690c6a5c7 of
  kernel-mainline 59d9094. Differences
  between 02333ac and 59d9094 were driving the diffs between this commit
  and the upstrem 14967a9.
  include/linux/mm_types.h
        Removed the definition of `ptdesc_pmd_is_shared()' function in
        alignment with stable-5.15 backport 8410996 (it omits the
        definition of `ptdesc_pmd_pts_*()' functions family, to which
        `ptdesc_pmd_is_shared()' belongs).
  mm/hugetlb.c
        copy_hugetlb_page_range()
              1. Used CONFIG_ARCH_WANT_HUGE_PMD_SHARE instead of
                 CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING, because the latter
                 was introduced only in the non-backported commit
                 188cac5.
              2. Since `ptdesc_pmd_is_shared()' was not defined, read the
                 `pt_share_count' field directly, as is done in the
                 stable-5.15 backport 8410996. (Compare changes to
                 `huge_pmd_unshare()' in `mm/hugetlb.c' between upstream
                 59d9094 and stable-5.15 8410996.)
        huge_pmd_unshare()
              No change to the conditional. It was arguably not needed in
              the upstream as well, probably introduced only for the sake
              of clarity in the presence of `ptdesc_pmd_is_shared()'
              function, which is missing here.

commit 59d9094 ("mm: hugetlb: independent PMD page table shared
count") introduced ->pt_share_count dedicated to hugetlb PMD share count
tracking, but omitted fixing copy_hugetlb_page_range(), leaving the
function relying on page_count() for tracking that no longer works.

When lazy page table copy for hugetlb is disabled, that is, revert commit
bcd51a3 ("hugetlb: lazy page table copies in fork()") fork()'ing with
hugetlb PMD sharing quickly lockup -

[  239.446559] watchdog: BUG: soft lockup - CPU#75 stuck for 27s!
[  239.446611] RIP: 0010:native_queued_spin_lock_slowpath+0x7e/0x2e0
[  239.446631] Call Trace:
[  239.446633]  <TASK>
[  239.446636]  _raw_spin_lock+0x3f/0x60
[  239.446639]  copy_hugetlb_page_range+0x258/0xb50
[  239.446645]  copy_page_range+0x22b/0x2c0
[  239.446651]  dup_mmap+0x3e2/0x770
[  239.446654]  dup_mm.constprop.0+0x5e/0x230
[  239.446657]  copy_process+0xd17/0x1760
[  239.446660]  kernel_clone+0xc0/0x3e0
[  239.446661]  __do_sys_clone+0x65/0xa0
[  239.446664]  do_syscall_64+0x82/0x930
[  239.446668]  ? count_memcg_events+0xd2/0x190
[  239.446671]  ? syscall_trace_enter+0x14e/0x1f0
[  239.446676]  ? syscall_exit_work+0x118/0x150
[  239.446677]  ? arch_exit_to_user_mode_prepare.constprop.0+0x9/0xb0
[  239.446681]  ? clear_bhb_loop+0x30/0x80
[  239.446684]  ? clear_bhb_loop+0x30/0x80
[  239.446686]  entry_SYSCALL_64_after_hwframe+0x76/0x7e

There are two options to resolve the potential latent issue:
  1. warn against PMD sharing in copy_hugetlb_page_range(),
  2. fix it.
This patch opts for the second option.
While at it, simplify the comment, the details are not actually relevant
anymore.

Link: https://lkml.kernel.org/r/[email protected]
Fixes: 59d9094 ("mm: hugetlb: independent PMD page table shared count")
	Signed-off-by: Jane Chu <[email protected]>
	Reviewed-by: Harry Yoo <[email protected]>
	Acked-by: Oscar Salvador <[email protected]>
	Acked-by: David Hildenbrand <[email protected]>
	Cc: Jann Horn <[email protected]>
	Cc: Liu Shixin <[email protected]>
	Cc: Muchun Song <[email protected]>
	Signed-off-by: Andrew Morton <[email protected]>
(cherry picked from commit 14967a9)
	Signed-off-by: Marcin Wcisło <[email protected]>
jira VULN-46930
cve-bf CVE-2024-57883
commit-author David Hildenbrand (Red Hat) <[email protected]>
commit ca1a47c
upstream-diff Adaptation analogous to
  3ab513d in relation to the upstream
  14967a9 - inlined missing
  `ptdesc_pmd_is_shared()', `ptdesc_pmd_pts_count()', `virt_to_ptdesc()'

Patch series "mm/hugetlb: fixes for PMD table sharing (incl.  using
mmu_gather)", v3.

One functional fix, one performance regression fix, and two related
comment fixes.

I cleaned up my prototype I recently shared [1] for the performance fix,
deferring most of the cleanups I had in the prototype to a later point.
While doing that I identified the other things.

The goal of this patch set is to be backported to stable trees "fairly"
easily. At least patch ctrliq#1 and ctrliq#4.

Patch ctrliq#1 fixes hugetlb_pmd_shared() not detecting any sharing
Patch ctrliq#2 + ctrliq#3 are simple comment fixes that patch ctrliq#4 interacts with.
Patch ctrliq#4 is a fix for the reported performance regression due to excessive
IPI broadcasts during fork()+exit().

The last patch is all about TLB flushes, IPIs and mmu_gather.
Read: complicated

There are plenty of cleanups in the future to be had + one reasonable
optimization on x86. But that's all out of scope for this series.

Runtime tested, with a focus on fixing the performance regression using
the original reproducer [2] on x86.

This patch (of 4):

We switched from (wrongly) using the page count to an independent shared
count.  Now, shared page tables have a refcount of 1 (excluding
speculative references) and instead use ptdesc->pt_share_count to identify
sharing.

We didn't convert hugetlb_pmd_shared(), so right now, we would never
detect a shared PMD table as such, because sharing/unsharing no longer
touches the refcount of a PMD table.

Page migration, like mbind() or migrate_pages() would allow for migrating
folios mapped into such shared PMD tables, even though the folios are not
exclusive.  In smaps we would account them as "private" although they are
"shared", and we would be wrongly setting the PM_MMAP_EXCLUSIVE in the
pagemap interface.

Fix it by properly using ptdesc_pmd_is_shared() in hugetlb_pmd_shared().

Link: https://lkml.kernel.org/r/[email protected]
Link: https://lkml.kernel.org/r/[email protected]
Link: https://lore.kernel.org/all/[email protected]/ [1]
Link: https://lore.kernel.org/all/[email protected]/ [2]
Fixes: 59d9094 ("mm: hugetlb: independent PMD page table shared count")
	Signed-off-by: David Hildenbrand (Red Hat) <[email protected]>
	Reviewed-by: Rik van Riel <[email protected]>
	Reviewed-by: Lance Yang <[email protected]>
	Tested-by: Lance Yang <[email protected]>
	Reviewed-by: Harry Yoo <[email protected]>
	Tested-by: Laurence Oberman <[email protected]>
	Reviewed-by: Lorenzo Stoakes <[email protected]>
	Acked-by: Oscar Salvador <[email protected]>
	Cc: Liu Shixin <[email protected]>
	Cc: Uschakow, Stanislav" <[email protected]>
	Cc: <[email protected]>
	Signed-off-by: Andrew Morton <[email protected]>
(cherry picked from commit ca1a47c)
	Signed-off-by: Marcin Wcisło <[email protected]>
jira VULN-46930
cve-bf CVE-2024-57883
commit-author David Hildenbrand (Red Hat) <[email protected]>
commit 3937027
upstream-diff Resolved conflicts due to the
  4e1f5f6 backport incorporating a typo
  'refernece', which was fixed upstream (and expected by this patch) in
  b6c4660, but it didn't make it to
  ciqlts9_4. Could not have been picked as prerequisite due to multiple
  conflicts

Ever since we stopped using the page count to detect shared PMD page
tables, these comments are outdated.

The only reason we have to flush the TLB early is because once we drop the
i_mmap_rwsem, the previously shared page table could get freed (to then
get reallocated and used for other purpose).  So we really have to flush
the TLB before that could happen.

So let's simplify the comments a bit.

The "If we unshared PMDs, the TLB flush was not recorded in mmu_gather."
part introduced as in commit a4a118f ("hugetlbfs: flush TLBs
correctly after huge_pmd_unshare") was confusing: sure it is recorded in
the mmu_gather, otherwise tlb_flush_mmu_tlbonly() wouldn't do anything.
So let's drop that comment while at it as well.

We'll centralize these comments in a single helper as we rework the code
next.

Link: https://lkml.kernel.org/r/[email protected]
Fixes: 59d9094 ("mm: hugetlb: independent PMD page table shared count")
	Signed-off-by: David Hildenbrand (Red Hat) <[email protected]>
	Reviewed-by: Rik van Riel <[email protected]>
	Tested-by: Laurence Oberman <[email protected]>
	Reviewed-by: Lorenzo Stoakes <[email protected]>
	Acked-by: Oscar Salvador <[email protected]>
	Reviewed-by: Harry Yoo <[email protected]>
	Cc: Liu Shixin <[email protected]>
	Cc: Lance Yang <[email protected]>
	Cc: "Uschakow, Stanislav" <[email protected]>
	Cc: <[email protected]>
	Signed-off-by: Andrew Morton <[email protected]>
(cherry picked from commit 3937027)
	Signed-off-by: Marcin Wcisło <[email protected]>
jira VULN-46930
cve-bf CVE-2024-57883
commit-author David Hildenbrand (Red Hat) <[email protected]>
commit a8682d5

PMD page table unsharing no longer touches the refcount of a PMD page
table.  Also, it is not about dropping the refcount of a "PMD page" but
the "PMD page table".

Let's just simplify by saying that the PMD page table was unmapped,
consequently also unmapping the folio that was mapped into this page.

This code should be deduplicated in the future.

Link: https://lkml.kernel.org/r/[email protected]
Fixes: 59d9094 ("mm: hugetlb: independent PMD page table shared count")
	Signed-off-by: David Hildenbrand (Red Hat) <[email protected]>
	Reviewed-by: Rik van Riel <[email protected]>
	Tested-by: Laurence Oberman <[email protected]>
	Reviewed-by: Lorenzo Stoakes <[email protected]>
	Acked-by: Oscar Salvador <[email protected]>
	Cc: Liu Shixin <[email protected]>
	Cc: Harry Yoo <[email protected]>
	Cc: Lance Yang <[email protected]>
	Cc: "Uschakow, Stanislav" <[email protected]>
	Cc: <[email protected]>
	Signed-off-by: Andrew Morton <[email protected]>
(cherry picked from commit a8682d5)
	Signed-off-by: Marcin Wcisło <[email protected]>
@pvts-mat pvts-mat force-pushed the ciqlts9_4-CVE-batch-18 branch from d0397e0 to db8be66 Compare February 3, 2026 21:58
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.

3 participants