summaryrefslogtreecommitdiff
path: root/tools/lib/python/kdoc/parse_data_structs.py
diff options
context:
space:
mode:
authorZhao Gongyi <zhaogongyi@bytedance.com>2026-10-23 20:12:33 +0800
committerCatalin Marinas <catalin.marinas@arm.com>2026-10-27 16:52:43 +0000
commit486d396b19e93f6e56e0a0ba96c14a9ccc1a5977 (patch)
treeddd9ce844c316c1e380c385116003b9c6097bbbe /tools/lib/python/kdoc/parse_data_structs.py
parent643b64025650d0ac5d57bd522d2eb0996a278081 (diff)
arm64/mm: restrict transparent contpte mappings to valid PTEs
The transparent contpte layer treats PTE_CONT as software grouping state. When a valid PTE has PTE_CONT set, the contpte helpers may align an operation to a CONT_PTE_SIZE block and operate on the whole block. The current single-PTE helpers use pte_valid_cont() to identify such groups; this is a helper contract, not an architectural restriction on using PTE_CONT with present-invalid descriptors. Explicit users such as hugetlb manage their contiguous encodings separately. contpte_set_ptes() currently sets PTE_CONT from alignment alone. Batched set_ptes() users can therefore install present-invalid PTEs with PTE_CONT set, for example mprotect(PROT_NONE), NUMA hinting through modify_prot_commit_ptes(), fork() copying a PROT_NONE large folio, or a PMD split installing PAGE_NONE PTEs. This is not a hardware programming problem: invalid descriptors are not translated, so the hardware ignores descriptor bits such as PTE_CONT. It is a software-state problem. Some arm64 fast paths, such as test_and_clear_young_ptes(), test pte_cont() directly instead of pte_valid_cont(). In the observed failure, mprotect(PROT_NONE) installed a full CONT_PTE_SIZE range of present-invalid PTEs with PTE_CONT set. MADV_GUARD_INSTALL then zapped one PTE. The nr == 1 clear_full_ptes() path only unfolds pte_valid_cont() entries, so the neighbouring present-invalid entries kept PTE_CONT while the target entry became a guard marker. clear_refs_pte_range() then reached the marker through: ptep_test_and_clear_young() test_and_clear_young_ptes() contpte_test_and_clear_young_ptes() contpte_align_addr_ptep() __ptep_test_and_clear_young() The marker changed from old_pte=0x00000000000047c0 to new_pte=0x00000000000043c0 by clearing PTE_AF. For swap PTEs, bit 10 is part of the swap type field, bits 6-10: 0x47c0 is SWP_PTE_MARKER with offset 4, while 0x43c0 has type 15 and is decoded as an ordinary swap entry. Zap later warned in swap_put_entries_direct() with a bad swap entry. Present-invalid PTEs could retain PTE_CONT as software grouping state, but their single-PTE modification paths would then need to recognize and unfold those groups consistently. Since current helpers mostly use pte_valid_cont() for membership, avoid creating present-invalid transparent contpte groups in contpte_set_ptes(). They bring no hardware benefit while invalid, and eligible valid ranges can be grouped again when they are installed. The public set_ptes() wrapper already clears PTE_CONT before calling contpte_set_ptes(). Return invalid PTEs through __set_ptes() directly, and warn if a future direct caller unexpectedly passes an invalid PTE with PTE_CONT set. This is triggerable by a user process against its own address space. On systems running with panic_on_warn, the warning becomes a denial of service. Fixes: 4602e5757bcc ("arm64/mm: wire up PTE_CONT for user mappings") Cc: stable@vger.kernel.org Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com> Tested-by: Lance Yang <lance.yang@linux.dev> Signed-off-by: Zhao Gongyi <zhaogongyi@bytedance.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'tools/lib/python/kdoc/parse_data_structs.py')
0 files changed, 0 insertions, 0 deletions