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: Trap MTE access and discovery when MTE is disabled

If MTE is not supported by the hardware, or is disabled in the kernel
configuration (`CONFIG_ARM64_MTE=n`) or command line (`arm64.nomte`),
the kernel stops advertising MTE to userspace and avoids using MTE
instructions. However, this is a software-level disable only.

When MTE hardware is present and enabled by EL3 firmware, leaving
`HCR_EL2.ATA` set allows the host to execute MTE instructions (STG, LDG,
etc.) and access allocation tags in physical memory.

Prevent this by clearing `HCR_EL2.ATA` when MTE is disabled. Remove it
from the `HCR_HOST_NVHE_FLAGS` default, and conditionally set it in
`cpu_prepare_hyp_mode()` only when `system_supports_mte()` returns true.
This causes MTE instructions to trap to EL2 when `HCR_EL2.ATA` is
cleared.

Additionally, set `HCR_EL2.TID5` when MTE is disabled. This traps reads
of `GMID_EL1` (Multiple tag transfer ID register) to EL2, preventing the
discovery of MTE parameters (such as tag block size) when the feature is
suppressed.

Early boot code in `head.S` temporarily keeps `HCR_ATA` set to avoid
special-casing initialization paths. This is safe because this code
executes before untrusted code runs and will clear `HCR_ATA` if MTE is
disabled.

Signed-off-by: Fuad Tabba <tabba@google.com>
Link: https://patch.msgid.link/20260122112218.531948-3-tabba@google.com
Signed-off-by: Marc Zyngier <maz@kernel.org>

authored by

Fuad Tabba and committed by
Marc Zyngier
f35abcbb c103c2df

+8 -2
+1 -1
arch/arm64/include/asm/kvm_arm.h
··· 101 101 HCR_BSU_IS | HCR_FB | HCR_TACR | \ 102 102 HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW | HCR_TLOR | \ 103 103 HCR_FMO | HCR_IMO | HCR_PTW | HCR_TID3 | HCR_TID1) 104 - #define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK | HCR_ATA) 104 + #define HCR_HOST_NVHE_FLAGS (HCR_RW | HCR_API | HCR_APK) 105 105 #define HCR_HOST_NVHE_PROTECTED_FLAGS (HCR_HOST_NVHE_FLAGS | HCR_TSC) 106 106 #define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H | HCR_AMO | HCR_IMO | HCR_FMO) 107 107
+1 -1
arch/arm64/kernel/head.S
··· 299 299 isb 300 300 0: 301 301 302 - init_el2_hcr HCR_HOST_NVHE_FLAGS 302 + init_el2_hcr HCR_HOST_NVHE_FLAGS | HCR_ATA 303 303 init_el2_state 304 304 305 305 /* Hypervisor stub */
+6
arch/arm64/kvm/arm.c
··· 2044 2044 params->hcr_el2 = HCR_HOST_NVHE_PROTECTED_FLAGS; 2045 2045 else 2046 2046 params->hcr_el2 = HCR_HOST_NVHE_FLAGS; 2047 + 2048 + if (system_supports_mte()) 2049 + params->hcr_el2 |= HCR_ATA; 2050 + else 2051 + params->hcr_el2 |= HCR_TID5; 2052 + 2047 2053 if (cpus_have_final_cap(ARM64_KVM_HVHE)) 2048 2054 params->hcr_el2 |= HCR_E2H; 2049 2055 params->vttbr = params->vtcr = 0;