Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: arm64: Honor UX/PX attributes for EL2 S1 mappings

Now that we potentially have two bits to deal with when setting
execution permissions, make sure we correctly handle them when both
when building the page tables and when reading back from them.

Reported-by: Alexandru Elisei <alexandru.elisei@arm.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Joey Gouly <joey.gouly@arm.com>
Tested-by: Fuad Tabba <tabba@google.com>
Link: https://patch.msgid.link/20251210173024.561160-7-maz@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>

+24 -12
+3 -9
arch/arm64/include/asm/kvm_pgtable.h
··· 87 87 88 88 #define KVM_PTE_LEAF_ATTR_HI_SW GENMASK(58, 55) 89 89 90 - #define __KVM_PTE_LEAF_ATTR_HI_S1_XN BIT(54) 91 - #define __KVM_PTE_LEAF_ATTR_HI_S1_UXN BIT(54) 92 - #define __KVM_PTE_LEAF_ATTR_HI_S1_PXN BIT(53) 93 - 94 - #define KVM_PTE_LEAF_ATTR_HI_S1_XN \ 95 - ({ cpus_have_final_cap(ARM64_KVM_HVHE) ? \ 96 - (__KVM_PTE_LEAF_ATTR_HI_S1_UXN | \ 97 - __KVM_PTE_LEAF_ATTR_HI_S1_PXN) : \ 98 - __KVM_PTE_LEAF_ATTR_HI_S1_XN; }) 90 + #define KVM_PTE_LEAF_ATTR_HI_S1_XN BIT(54) 91 + #define KVM_PTE_LEAF_ATTR_HI_S1_UXN BIT(54) 92 + #define KVM_PTE_LEAF_ATTR_HI_S1_PXN BIT(53) 99 93 100 94 #define KVM_PTE_LEAF_ATTR_HI_S2_XN GENMASK(54, 53) 101 95
+21 -3
arch/arm64/kvm/hyp/pgtable.c
··· 342 342 if (!(prot & KVM_PGTABLE_PROT_R)) 343 343 return -EINVAL; 344 344 345 + if (!cpus_have_final_cap(ARM64_KVM_HVHE)) 346 + prot &= ~KVM_PGTABLE_PROT_UX; 347 + 345 348 if (prot & KVM_PGTABLE_PROT_X) { 346 349 if (prot & KVM_PGTABLE_PROT_W) 347 350 return -EINVAL; ··· 354 351 355 352 if (system_supports_bti_kernel()) 356 353 attr |= KVM_PTE_LEAF_ATTR_HI_S1_GP; 354 + } 355 + 356 + if (cpus_have_final_cap(ARM64_KVM_HVHE)) { 357 + if (!(prot & KVM_PGTABLE_PROT_PX)) 358 + attr |= KVM_PTE_LEAF_ATTR_HI_S1_PXN; 359 + if (!(prot & KVM_PGTABLE_PROT_UX)) 360 + attr |= KVM_PTE_LEAF_ATTR_HI_S1_UXN; 357 361 } else { 358 - attr |= KVM_PTE_LEAF_ATTR_HI_S1_XN; 362 + if (!(prot & KVM_PGTABLE_PROT_PX)) 363 + attr |= KVM_PTE_LEAF_ATTR_HI_S1_XN; 359 364 } 360 365 361 366 attr |= FIELD_PREP(KVM_PTE_LEAF_ATTR_LO_S1_AP, ap); ··· 384 373 if (!kvm_pte_valid(pte)) 385 374 return prot; 386 375 387 - if (!(pte & KVM_PTE_LEAF_ATTR_HI_S1_XN)) 388 - prot |= KVM_PGTABLE_PROT_X; 376 + if (cpus_have_final_cap(ARM64_KVM_HVHE)) { 377 + if (!(pte & KVM_PTE_LEAF_ATTR_HI_S1_PXN)) 378 + prot |= KVM_PGTABLE_PROT_PX; 379 + if (!(pte & KVM_PTE_LEAF_ATTR_HI_S1_UXN)) 380 + prot |= KVM_PGTABLE_PROT_UX; 381 + } else { 382 + if (!(pte & KVM_PTE_LEAF_ATTR_HI_S1_XN)) 383 + prot |= KVM_PGTABLE_PROT_PX; 384 + } 389 385 390 386 ap = FIELD_GET(KVM_PTE_LEAF_ATTR_LO_S1_AP, pte); 391 387 if (ap == KVM_PTE_LEAF_ATTR_LO_S1_AP_RO)