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

KVM: VMX: Introduce CET VMCS fields and control bits

Control-flow Enforcement Technology (CET) is a kind of CPU feature used
to prevent Return/CALL/Jump-Oriented Programming (ROP/COP/JOP) attacks.
It provides two sub-features(SHSTK,IBT) to defend against ROP/COP/JOP
style control-flow subversion attacks.

Shadow Stack (SHSTK):
A shadow stack is a second stack used exclusively for control transfer
operations. The shadow stack is separate from the data/normal stack and
can be enabled individually in user and kernel mode. When shadow stack
is enabled, CALL pushes the return address on both the data and shadow
stack. RET pops the return address from both stacks and compares them.
If the return addresses from the two stacks do not match, the processor
generates a #CP.

Indirect Branch Tracking (IBT):
IBT introduces instruction(ENDBRANCH)to mark valid target addresses of
indirect branches (CALL, JMP etc...). If an indirect branch is executed
and the next instruction is _not_ an ENDBRANCH, the processor generates
a #CP. These instruction behaves as a NOP on platforms that have no CET.

Several new CET MSRs are defined to support CET:
MSR_IA32_{U,S}_CET: CET settings for {user,supervisor} CET respectively.

MSR_IA32_PL{0,1,2,3}_SSP: SHSTK pointer linear address for CPL{0,1,2,3}.

MSR_IA32_INT_SSP_TAB: Linear address of SHSTK pointer table, whose entry
is indexed by IST of interrupt gate desc.

Two XSAVES state bits are introduced for CET:
IA32_XSS:[bit 11]: Control saving/restoring user mode CET states
IA32_XSS:[bit 12]: Control saving/restoring supervisor mode CET states.

Six VMCS fields are introduced for CET:
{HOST,GUEST}_S_CET: Stores CET settings for kernel mode.
{HOST,GUEST}_SSP: Stores current active SSP.
{HOST,GUEST}_INTR_SSP_TABLE: Stores current active MSR_IA32_INT_SSP_TAB.

On Intel platforms, two additional bits are defined in VM_EXIT and VM_ENTRY
control fields:
If VM_EXIT_LOAD_CET_STATE = 1, host CET states are loaded from following
VMCS fields at VM-Exit:
HOST_S_CET
HOST_SSP
HOST_INTR_SSP_TABLE

If VM_ENTRY_LOAD_CET_STATE = 1, guest CET states are loaded from following
VMCS fields at VM-Entry:
GUEST_S_CET
GUEST_SSP
GUEST_INTR_SSP_TABLE

Co-developed-by: Zhang Yi Z <yi.z.zhang@linux.intel.com>
Signed-off-by: Zhang Yi Z <yi.z.zhang@linux.intel.com>
Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
Reviewed-by: Chao Gao <chao.gao@intel.com>
Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
Tested-by: Mathias Krause <minipli@grsecurity.net>
Tested-by: John Allen <john.allen@amd.com>
Tested-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Chao Gao <chao.gao@intel.com>
Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com>
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
Link: https://lore.kernel.org/r/20250919223258.1604852-13-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>

authored by

Yang Weijiang and committed by
Sean Christopherson
d6c387fc 6a11c860

+8
+8
arch/x86/include/asm/vmx.h
··· 106 106 #define VM_EXIT_CLEAR_BNDCFGS 0x00800000 107 107 #define VM_EXIT_PT_CONCEAL_PIP 0x01000000 108 108 #define VM_EXIT_CLEAR_IA32_RTIT_CTL 0x02000000 109 + #define VM_EXIT_LOAD_CET_STATE 0x10000000 109 110 110 111 #define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR 0x00036dff 111 112 ··· 120 119 #define VM_ENTRY_LOAD_BNDCFGS 0x00010000 121 120 #define VM_ENTRY_PT_CONCEAL_PIP 0x00020000 122 121 #define VM_ENTRY_LOAD_IA32_RTIT_CTL 0x00040000 122 + #define VM_ENTRY_LOAD_CET_STATE 0x00100000 123 123 124 124 #define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR 0x000011ff 125 125 ··· 371 369 GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822, 372 370 GUEST_SYSENTER_ESP = 0x00006824, 373 371 GUEST_SYSENTER_EIP = 0x00006826, 372 + GUEST_S_CET = 0x00006828, 373 + GUEST_SSP = 0x0000682a, 374 + GUEST_INTR_SSP_TABLE = 0x0000682c, 374 375 HOST_CR0 = 0x00006c00, 375 376 HOST_CR3 = 0x00006c02, 376 377 HOST_CR4 = 0x00006c04, ··· 386 381 HOST_IA32_SYSENTER_EIP = 0x00006c12, 387 382 HOST_RSP = 0x00006c14, 388 383 HOST_RIP = 0x00006c16, 384 + HOST_S_CET = 0x00006c18, 385 + HOST_SSP = 0x00006c1a, 386 + HOST_INTR_SSP_TABLE = 0x00006c1c 389 387 }; 390 388 391 389 /*