Skip to content

[PW_SID:1120351] mm: pgtable: free kernel page tables via RCU to fix ptdump UAF#2200

Closed
linux-riscv-bot wants to merge 1 commit into
workflow__riscv__fixesfrom
pw1120351
Closed

[PW_SID:1120351] mm: pgtable: free kernel page tables via RCU to fix ptdump UAF#2200
linux-riscv-bot wants to merge 1 commit into
workflow__riscv__fixesfrom
pw1120351

Conversation

@linux-riscv-bot

Copy link
Copy Markdown

PR for series 1120351 applied to workflow__riscv__fixes

Name: mm: pgtable: free kernel page tables via RCU to fix ptdump UAF
URL: https://patchwork.kernel.org/project/linux-riscv/list/?series=1120351
Version: 1

ptdump_walk_pgd() walks the kernel page tables under get_online_mems().
That does not stop vmalloc from freeing a kernel PTE page underneath the
walk.

When vmap_try_huge_pmd() promotes a range to a huge PMD it collapses the
existing PTE table and frees it via pmd_free_pte_page(). On x86, riscv and
powerpc this runs without the init_mm mmap lock; only arm64 takes it, and
not on the block-split path. So ptdump can dereference a just-freed PTE
page, which is the use after free syzbot hit in ptdump_pte_entry().

The race is not new. ptdump walks the whole kernel address space, including
ranges other code is actively mapping, so it reads page tables it does not
own. 5ba2f0a ("mm: introduce deferred freeing for kernel page tables")
only widened the window; the Fixes tag points there for that reason.

Every other walker works on a range it owns and is the only one mutating
it: set_memory() on arm64/riscv/loongarch, the arm64 block-split path, the
openrisc DMA path and the hugetlb_vmemmap remap. Nothing frees those ranges
concurrently, so they cannot race and do not need RCU. ptdump is the only
walker that traverses ranges it does not own.

Defer the free by an RCU grace period. pagetable_free_kernel() now frees
via call_rcu() in both the async and non-async configs. The async path
still flushes the TLB first, then queues the per-page RCU free. The page
stays valid until any walk that may have observed it drops its RCU read
lock.

On the read side walk_page_range_debug() walks the init_mm range in bounded
chunks, taking rcu_read_lock() around each chunk and calling cond_resched()
between them. A walker either sees the cleared PMD and skips, or keeps the
page alive until it drops the lock; chunking keeps the read section short
on a large kernel address space instead of holding RCU across the whole
walk. The owned-range walkers are unchanged.

Drop the mmap_write_lock() in ptdump_walk_pgd(). It never guarded against
this free -- most architectures free the collapsed PTE table without it --
and RCU now provides the synchronisation.

ptdump callbacks run under RCU within a chunk, so they must not sleep. The
arch note_page() and effective_prot() callbacks only format into the
preallocated seq_file buffer; the only GFP_KERNEL marker setup runs before
the walk, and cond_resched() happens between chunks, outside the read lock.

Fixes: 5ba2f0a ("mm: introduce deferred freeing for kernel page tables")
Reported-by: syzbot+fd95a72470f5a44e464c@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/6a287988.39669fcc.33b062.00a0.GAE@google.com/T/
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: David Carlier <devnexen@gmail.com>
Signed-off-by: Linux RISC-V bot <linux.riscv.bot@gmail.com>
@linux-riscv-bot

Copy link
Copy Markdown
Author

Patch 1: "mm: pgtable: free kernel page tables via RCU to fix ptdump UAF"
build-rv32-defconfig
Desc: Builds riscv32 defconfig
Duration: 145.38 seconds
Result: PASS

@linux-riscv-bot

Copy link
Copy Markdown
Author

Patch 1: "mm: pgtable: free kernel page tables via RCU to fix ptdump UAF"
build-rv64-clang-allmodconfig
Desc: Builds riscv64 allmodconfig with Clang, and checks for errors and added warnings
Duration: 2114.84 seconds
Result: PASS

@linux-riscv-bot

Copy link
Copy Markdown
Author

Patch 1: "mm: pgtable: free kernel page tables via RCU to fix ptdump UAF"
build-rv64-gcc-allmodconfig
Desc: Builds riscv64 allmodconfig with GCC, and checks for errors and added warnings
Duration: 2729.06 seconds
Result: PASS

@linux-riscv-bot

Copy link
Copy Markdown
Author

Patch 1: "mm: pgtable: free kernel page tables via RCU to fix ptdump UAF"
build-rv64-nommu-k210-defconfig
Desc: Builds riscv64 defconfig with NOMMU for K210
Duration: 28.24 seconds
Result: PASS

@linux-riscv-bot

Copy link
Copy Markdown
Author

Patch 1: "mm: pgtable: free kernel page tables via RCU to fix ptdump UAF"
build-rv64-nommu-k210-virt
Desc: Builds riscv64 defconfig with NOMMU for the virt platform
Duration: 30.25 seconds
Result: PASS

@linux-riscv-bot

Copy link
Copy Markdown
Author

Patch 1: "mm: pgtable: free kernel page tables via RCU to fix ptdump UAF"
checkpatch
Desc: Runs checkpatch.pl on the patch
Duration: 1.68 seconds
Result: PASS

@linux-riscv-bot

Copy link
Copy Markdown
Author

Patch 1: "mm: pgtable: free kernel page tables via RCU to fix ptdump UAF"
dtb-warn-rv64
Desc: Checks for Device Tree warnings/errors
Duration: 88.39 seconds
Result: PASS

@linux-riscv-bot

Copy link
Copy Markdown
Author

Patch 1: "mm: pgtable: free kernel page tables via RCU to fix ptdump UAF"
header-inline
Desc: Detects static functions without inline keyword in header files
Duration: 0.24 seconds
Result: PASS

@linux-riscv-bot

Copy link
Copy Markdown
Author

Patch 1: "mm: pgtable: free kernel page tables via RCU to fix ptdump UAF"
kdoc
Desc: Detects for kdoc errors
Duration: 0.92 seconds
Result: PASS

@linux-riscv-bot

Copy link
Copy Markdown
Author

Patch 1: "mm: pgtable: free kernel page tables via RCU to fix ptdump UAF"
module-param
Desc: Detect module_param changes
Duration: 0.27 seconds
Result: PASS

@linux-riscv-bot

Copy link
Copy Markdown
Author

Patch 1: "mm: pgtable: free kernel page tables via RCU to fix ptdump UAF"
verify-fixes
Desc: Verifies that the Fixes: tags exist
Duration: 0.27 seconds
Result: PASS

@linux-riscv-bot

Copy link
Copy Markdown
Author

Patch 1: "mm: pgtable: free kernel page tables via RCU to fix ptdump UAF"
verify-signedoff
Desc: Verifies that Signed-off-by: tags are correct
Duration: 0.30 seconds
Result: PASS

@linux-riscv-bot
linux-riscv-bot deleted the pw1120351 branch July 2, 2026 12:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants