public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Xiaoyao Li <xiaoyao.li@intel.com>
To: Sean Christopherson <seanjc@google.com>,
	Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Mathias Krause <minipli@grsecurity.net>,
	John Allen <john.allen@amd.com>,
	Rick Edgecombe <rick.p.edgecombe@intel.com>,
	Chao Gao <chao.gao@intel.com>,
	Maxim Levitsky <mlevitsk@redhat.com>,
	Zhang Yi Z <yi.z.zhang@linux.intel.com>
Subject: Re: [PATCH v15 18/41] KVM: x86: Don't emulate instructions affected by CET features
Date: Wed, 17 Sep 2025 16:19:58 +0800	[thread overview]
Message-ID: <55ab5774-0fcc-469a-8edc-59512def2bae@intel.com> (raw)
In-Reply-To: <20250912232319.429659-19-seanjc@google.com>

On 9/13/2025 7:22 AM, Sean Christopherson wrote:
> From: Yang Weijiang <weijiang.yang@intel.com>
> 
> Don't emulate branch instructions, e.g. CALL/RET/JMP etc., that are
> affected by Shadow Stacks and/or Indirect Branch Tracking when said
> features are enabled in the guest, as fully emulating CET would require
> significant complexity for no practical benefit (KVM shouldn't need to
> emulate branch instructions on modern hosts).  Simply doing nothing isn't
> an option as that would allow a malicious entity to subvert CET
> protections via the emulator.
> 
> Note!  On far transfers, do NOT consult the current privilege level and
> instead treat SHSTK/IBT as being enabled if they're enabled for User *or*
> Supervisor mode.  On inter-privilege level far transfers, SHSTK and IBT
> can be in play for the target privilege level, i.e. checking the current
> privilege could get a false negative, and KVM doesn't know the target
> privilege level until emulation gets under way.
> 
> Suggested-by: Chao Gao <chao.gao@intel.com>
> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> Cc: Mathias Krause <minipli@grsecurity.net>
> Cc: John Allen <john.allen@amd.com>
> Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
> Signed-off-by: Chao Gao <chao.gao@intel.com>
> Co-developed-by: Sean Christopherson <seanjc@google.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>   arch/x86/kvm/emulate.c | 58 ++++++++++++++++++++++++++++++++++--------
>   1 file changed, 47 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
> index 542d3664afa3..e4be54a677b0 100644
> --- a/arch/x86/kvm/emulate.c
> +++ b/arch/x86/kvm/emulate.c
> @@ -178,6 +178,8 @@
>   #define IncSP       ((u64)1 << 54)  /* SP is incremented before ModRM calc */
>   #define TwoMemOp    ((u64)1 << 55)  /* Instruction has two memory operand */
>   #define IsBranch    ((u64)1 << 56)  /* Instruction is considered a branch. */
> +#define ShadowStack ((u64)1 << 57)  /* Instruction protected by Shadow Stack. */
> +#define IndirBrnTrk ((u64)1 << 58)  /* Instruction protected by IBT. */
>   
>   #define DstXacc     (DstAccLo | SrcAccHi | SrcWrite)
>   
> @@ -4068,9 +4070,9 @@ static const struct opcode group4[] = {
>   static const struct opcode group5[] = {
>   	F(DstMem | SrcNone | Lock,		em_inc),
>   	F(DstMem | SrcNone | Lock,		em_dec),
> -	I(SrcMem | NearBranch | IsBranch,       em_call_near_abs),
> -	I(SrcMemFAddr | ImplicitOps | IsBranch, em_call_far),
> -	I(SrcMem | NearBranch | IsBranch,       em_jmp_abs),
> +	I(SrcMem | NearBranch | IsBranch | ShadowStack | IndirBrnTrk, em_call_near_abs),
> +	I(SrcMemFAddr | ImplicitOps | IsBranch | ShadowStack | IndirBrnTrk, em_call_far),
> +	I(SrcMem | NearBranch | IsBranch | IndirBrnTrk, em_jmp_abs),

>   	I(SrcMemFAddr | ImplicitOps | IsBranch, em_jmp_far),

It seems this entry for 'FF 05' (Jump far, absolute indirect) needs to 
set ShadowStack and IndirBrnTrk as well?

>   	I(SrcMem | Stack | TwoMemOp,		em_push), D(Undefined),
>   };
> @@ -4332,11 +4334,11 @@ static const struct opcode opcode_table[256] = {
>   	/* 0xC8 - 0xCF */
>   	I(Stack | SrcImmU16 | Src2ImmByte | IsBranch, em_enter),
>   	I(Stack | IsBranch, em_leave),
> -	I(ImplicitOps | SrcImmU16 | IsBranch, em_ret_far_imm),
> -	I(ImplicitOps | IsBranch, em_ret_far),
> -	D(ImplicitOps | IsBranch), DI(SrcImmByte | IsBranch, intn),
> +	I(ImplicitOps | SrcImmU16 | IsBranch | ShadowStack, em_ret_far_imm),
> +	I(ImplicitOps | IsBranch | ShadowStack, em_ret_far),
> +	D(ImplicitOps | IsBranch), DI(SrcImmByte | IsBranch | ShadowStack, intn),
>   	D(ImplicitOps | No64 | IsBranch),
> -	II(ImplicitOps | IsBranch, em_iret, iret),
> +	II(ImplicitOps | IsBranch | ShadowStack, em_iret, iret),
>   	/* 0xD0 - 0xD7 */
>   	G(Src2One | ByteOp, group2), G(Src2One, group2),
>   	G(Src2CL | ByteOp, group2), G(Src2CL, group2),
> @@ -4352,7 +4354,7 @@ static const struct opcode opcode_table[256] = {
>   	I2bvIP(SrcImmUByte | DstAcc, em_in,  in,  check_perm_in),
>   	I2bvIP(SrcAcc | DstImmUByte, em_out, out, check_perm_out),
>   	/* 0xE8 - 0xEF */
> -	I(SrcImm | NearBranch | IsBranch, em_call),
> +	I(SrcImm | NearBranch | IsBranch | ShadowStack, em_call),
>   	D(SrcImm | ImplicitOps | NearBranch | IsBranch),
>   	I(SrcImmFAddr | No64 | IsBranch, em_jmp_far),
>   	D(SrcImmByte | ImplicitOps | NearBranch | IsBranch),
> @@ -4371,7 +4373,7 @@ static const struct opcode opcode_table[256] = {
>   static const struct opcode twobyte_table[256] = {
>   	/* 0x00 - 0x0F */
>   	G(0, group6), GD(0, &group7), N, N,
> -	N, I(ImplicitOps | EmulateOnUD | IsBranch, em_syscall),
> +	N, I(ImplicitOps | EmulateOnUD | IsBranch | ShadowStack | IndirBrnTrk, em_syscall),
>   	II(ImplicitOps | Priv, em_clts, clts), N,
>   	DI(ImplicitOps | Priv, invd), DI(ImplicitOps | Priv, wbinvd), N, N,
>   	N, D(ImplicitOps | ModRM | SrcMem | NoAccess), N, N,
> @@ -4402,8 +4404,8 @@ static const struct opcode twobyte_table[256] = {
>   	IIP(ImplicitOps, em_rdtsc, rdtsc, check_rdtsc),
>   	II(ImplicitOps | Priv, em_rdmsr, rdmsr),
>   	IIP(ImplicitOps, em_rdpmc, rdpmc, check_rdpmc),
> -	I(ImplicitOps | EmulateOnUD | IsBranch, em_sysenter),
> -	I(ImplicitOps | Priv | EmulateOnUD | IsBranch, em_sysexit),
> +	I(ImplicitOps | EmulateOnUD | IsBranch | ShadowStack | IndirBrnTrk, em_sysenter),
> +	I(ImplicitOps | Priv | EmulateOnUD | IsBranch | ShadowStack, em_sysexit),
>   	N, N,
>   	N, N, N, N, N, N, N, N,
>   	/* 0x40 - 0x4F */
> @@ -4941,6 +4943,40 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
>   	if (ctxt->d == 0)
>   		return EMULATION_FAILED;
>   
> +	/*
> +	 * Reject emulation if KVM might need to emulate shadow stack updates
> +	 * and/or indirect branch tracking enforcement, which the emulator
> +	 * doesn't support.
> +	 */
> +	if (opcode.flags & (ShadowStack | IndirBrnTrk) &&
> +	    ctxt->ops->get_cr(ctxt, 4) & X86_CR4_CET) {
> +		u64 u_cet = 0, s_cet = 0;
> +
> +		/*
> +		 * Check both User and Supervisor on far transfers as inter-
> +		 * privilege level transfers are impacted by CET at the target
> +		 * privilege levels, and that is not known at this time.  The
> +		 * the expectation is that the guest will not require emulation
> +		 * of any CET-affected instructions at any privilege level.
> +		 */
> +		if (!(opcode.flags & NearBranch))
> +			u_cet = s_cet = CET_SHSTK_EN | CET_ENDBR_EN;
> +		else if (ctxt->ops->cpl(ctxt) == 3)
> +			u_cet = CET_SHSTK_EN | CET_ENDBR_EN;
> +		else
> +			s_cet = CET_SHSTK_EN | CET_ENDBR_EN;
> +
> +		if ((u_cet && ctxt->ops->get_msr(ctxt, MSR_IA32_U_CET, &u_cet)) ||
> +		    (s_cet && ctxt->ops->get_msr(ctxt, MSR_IA32_S_CET, &s_cet)))
> +			return EMULATION_FAILED;
> +
> +		if ((u_cet | s_cet) & CET_SHSTK_EN && opcode.flags & ShadowStack)
> +			return EMULATION_FAILED;
> +
> +		if ((u_cet | s_cet) & CET_ENDBR_EN && opcode.flags & IndirBrnTrk)
> +			return EMULATION_FAILED;
> +	}

I'm not sure other than 'jmp far' case I pointed above, if any more 
instruction/case that are protected by shadow stack or IBT are missed.
(I'm not really good at identifying all of them. Just identify one case 
drains my energy)

At least, the part to return EMULATION_FAILED for the cases where shadow 
stack/IBT protection is needed looks good to me. So, for this part:

Reviewed-by: Xiaoyao Li <xiaoyao.li@Intel.com>

>   	ctxt->execute = opcode.u.execute;
>   
>   	if (unlikely(emulation_type & EMULTYPE_TRAP_UD) &&


  parent reply	other threads:[~2025-09-17  8:20 UTC|newest]

Thread overview: 130+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-12 23:22 [PATCH v15 00/41] KVM: x86: Mega-CET Sean Christopherson
2025-09-12 23:22 ` [PATCH v15 01/41] KVM: SEV: Rename kvm_ghcb_get_sw_exit_code() to kvm_get_cached_sw_exit_code() Sean Christopherson
2025-09-15 16:15   ` Tom Lendacky
2025-09-15 16:30     ` Sean Christopherson
2025-09-12 23:22 ` [PATCH v15 02/41] KVM: SEV: Read save fields from GHCB exactly once Sean Christopherson
2025-09-15 17:32   ` Tom Lendacky
2025-09-15 21:08     ` Sean Christopherson
2025-09-17 21:47       ` Sean Christopherson
2025-09-12 23:22 ` [PATCH v15 03/41] KVM: SEV: Validate XCR0 provided by guest in GHCB Sean Christopherson
2025-09-15 18:41   ` Tom Lendacky
2025-09-15 21:22     ` Sean Christopherson
2025-09-12 23:22 ` [PATCH v15 04/41] KVM: x86: Introduce KVM_{G,S}ET_ONE_REG uAPIs support Sean Christopherson
2025-09-15  6:29   ` Xiaoyao Li
2025-09-16  7:10   ` Binbin Wu
2025-09-17 13:14     ` Sean Christopherson
2025-09-12 23:22 ` [PATCH v15 05/41] KVM: x86: Report XSS as to-be-saved if there are supported features Sean Christopherson
2025-09-16  7:12   ` Binbin Wu
2025-09-12 23:22 ` [PATCH v15 06/41] KVM: x86: Check XSS validity against guest CPUIDs Sean Christopherson
2025-09-16  7:20   ` Binbin Wu
2025-09-12 23:22 ` [PATCH v15 07/41] KVM: x86: Refresh CPUID on write to guest MSR_IA32_XSS Sean Christopherson
2025-09-16  7:23   ` Binbin Wu
2025-09-12 23:22 ` [PATCH v15 08/41] KVM: x86: Initialize kvm_caps.supported_xss Sean Christopherson
2025-09-16  7:29   ` Binbin Wu
2025-09-12 23:22 ` [PATCH v15 09/41] KVM: x86: Load guest FPU state when access XSAVE-managed MSRs Sean Christopherson
2025-09-15 17:04   ` Xin Li
2025-09-16  6:51   ` Xiaoyao Li
2025-09-16  8:28   ` Binbin Wu
2025-09-17  2:51     ` Binbin Wu
2025-09-17 12:47     ` Sean Christopherson
2025-09-17 21:56       ` Sean Christopherson
2025-09-12 23:22 ` [PATCH v15 10/41] KVM: x86: Add fault checks for guest CR4.CET setting Sean Christopherson
2025-09-16  8:33   ` Binbin Wu
2025-09-12 23:22 ` [PATCH v15 11/41] KVM: x86: Report KVM supported CET MSRs as to-be-saved Sean Christopherson
2025-09-15  6:30   ` Xiaoyao Li
2025-09-16  8:46   ` Binbin Wu
2025-09-12 23:22 ` [PATCH v15 12/41] KVM: VMX: Introduce CET VMCS fields and control bits Sean Christopherson
2025-09-15  6:31   ` Xiaoyao Li
2025-09-16  9:00   ` Binbin Wu
2025-09-12 23:22 ` [PATCH v15 13/41] KVM: x86: Enable guest SSP read/write interface with new uAPIs Sean Christopherson
2025-09-15  6:55   ` Xiaoyao Li
2025-09-15 22:12     ` Sean Christopherson
2025-09-16  5:52       ` Xiaoyao Li
2025-09-19 17:47         ` Sean Christopherson
2025-09-19 17:58           ` Sean Christopherson
2025-09-12 23:22 ` [PATCH v15 14/41] KVM: VMX: Emulate read and write to CET MSRs Sean Christopherson
2025-09-16  7:07   ` Xiaoyao Li
2025-09-16  7:48     ` Chao Gao
2025-09-16  8:10       ` Xiaoyao Li
2025-09-19 22:11     ` Sean Christopherson
2025-09-17  7:52   ` Binbin Wu
2025-09-12 23:22 ` [PATCH v15 15/41] KVM: x86: Save and reload SSP to/from SMRAM Sean Christopherson
2025-09-16  7:37   ` Xiaoyao Li
2025-09-17  7:53   ` Binbin Wu
2025-09-12 23:22 ` [PATCH v15 16/41] KVM: VMX: Set up interception for CET MSRs Sean Christopherson
2025-09-15 17:21   ` Xin Li
2025-09-16  7:40   ` Xiaoyao Li
2025-09-17  8:32   ` Binbin Wu
2025-09-17 13:44     ` Sean Christopherson
2025-09-12 23:22 ` [PATCH v15 17/41] KVM: VMX: Set host constant supervisor states to VMCS fields Sean Christopherson
2025-09-16  7:44   ` Xiaoyao Li
2025-09-17  8:48   ` Xiaoyao Li
2025-09-17 21:25     ` Sean Christopherson
2025-09-12 23:22 ` [PATCH v15 18/41] KVM: x86: Don't emulate instructions affected by CET features Sean Christopherson
2025-09-17  8:16   ` Chao Gao
2025-09-17 21:15     ` Sean Christopherson
2025-09-18 14:54       ` Chao Gao
2025-09-18 18:02         ` Sean Christopherson
2025-09-17  8:19   ` Xiaoyao Li [this message]
2025-09-18 14:15     ` Chao Gao
2025-09-19  1:25       ` Sean Christopherson
2025-09-17  8:45   ` Binbin Wu
2025-09-12 23:22 ` [PATCH v15 19/41] KVM: x86: Enable CET virtualization for VMX and advertise to userspace Sean Christopherson
2025-09-18  1:57   ` Binbin Wu
2025-09-19 22:57     ` Sean Christopherson
2025-09-18  2:18   ` Binbin Wu
2025-09-18 18:05     ` Sean Christopherson
2025-09-19  7:10       ` Xiaoyao Li
2025-09-19 14:25         ` Sean Christopherson
2025-09-12 23:22 ` [PATCH v15 20/41] KVM: nVMX: Virtualize NO_HW_ERROR_CODE_CC for L1 event injection to L2 Sean Christopherson
2025-09-18  2:27   ` Binbin Wu
2025-09-12 23:22 ` [PATCH v15 21/41] KVM: nVMX: Prepare for enabling CET support for nested guest Sean Christopherson
2025-09-15 17:45   ` Xin Li
2025-09-18  4:48   ` Xin Li
2025-09-18 18:05     ` Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 22/41] KVM: nVMX: Add consistency checks for CR0.WP and CR4.CET Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 23/41] KVM: nVMX: Add consistency checks for CET states Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 24/41] KVM: nVMX: Advertise new VM-Entry/Exit control bits for CET state Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 25/41] KVM: x86: SVM: Emulate reads and writes to shadow stack MSRs Sean Christopherson
2025-09-15 17:56   ` Xin Li
2025-09-15 20:43     ` Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 26/41] KVM: nSVM: Save/load CET Shadow Stack state to/from vmcb12/vmcb02 Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 27/41] KVM: x86: SVM: Update dump_vmcb with shadow stack save area additions Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 28/41] KVM: x86: SVM: Pass through shadow stack MSRs as appropriate Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 29/41] KVM: SEV: Synchronize MSR_IA32_XSS from the GHCB when it's valid Sean Christopherson
2025-09-16 18:55   ` John Allen
2025-09-16 19:53     ` Sean Christopherson
2025-09-16 20:33       ` John Allen
2025-09-16 21:38         ` Sean Christopherson
2025-09-16 22:55           ` John Allen
2025-09-18 19:48             ` John Allen
2025-09-18 20:34               ` Sean Christopherson
2025-09-18 20:44                 ` Sean Christopherson
2025-09-18 21:23                   ` John Allen
2025-09-18 21:42                     ` Edgecombe, Rick P
2025-09-18 22:18                       ` John Allen
2025-09-19 13:40                         ` Tom Lendacky
2025-09-19 16:13                           ` John Allen
2025-09-19 17:29                           ` Edgecombe, Rick P
2025-09-19 20:58                             ` Edgecombe, Rick P
2025-09-22  9:19                               ` Kiryl Shutsemau
2025-09-22  9:33                                 ` Upadhyay, Neeraj
2025-09-22  9:54                                   ` Kiryl Shutsemau
2025-09-12 23:23 ` [PATCH v15 30/41] KVM: SVM: Enable shadow stack virtualization for SVM Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 31/41] KVM: x86: Add human friendly formatting for #XM, and #VE Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 32/41] KVM: x86: Define Control Protection Exception (#CP) vector Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 33/41] KVM: x86: Define AMD's #HV, #VC, and #SX exception vectors Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 34/41] KVM: selftests: Add ex_str() to print human friendly name of " Sean Christopherson
2025-09-15  9:07   ` Chao Gao
2025-09-12 23:23 ` [PATCH v15 35/41] KVM: selftests: Add an MSR test to exercise guest/host and read/write Sean Christopherson
2025-09-15  8:22   ` Chao Gao
2025-09-15 17:00     ` Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 36/41] KVM: selftests: Add support for MSR_IA32_{S,U}_CET to MSRs test Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 37/41] KVM: selftests: Extend MSRs test to validate vCPUs without supported features Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 38/41] KVM: selftests: Add KVM_{G,S}ET_ONE_REG coverage to MSRs test Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 39/41] KVM: selftests: Add coverate for KVM-defined registers in " Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 40/41] KVM: selftests: Verify MSRs are (not) in save/restore list when (un)supported Sean Christopherson
2025-09-12 23:23 ` [PATCH v15 41/41] KVM: VMX: Make CR4.CET a guest owned bit Sean Christopherson
2025-09-15 13:18 ` [PATCH v15 00/41] KVM: x86: Mega-CET Mathias Krause
2025-09-15 21:20 ` John Allen
2025-09-16 13:53 ` Chao Gao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=55ab5774-0fcc-469a-8edc-59512def2bae@intel.com \
    --to=xiaoyao.li@intel.com \
    --cc=chao.gao@intel.com \
    --cc=john.allen@amd.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=minipli@grsecurity.net \
    --cc=mlevitsk@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=rick.p.edgecombe@intel.com \
    --cc=seanjc@google.com \
    --cc=thomas.lendacky@amd.com \
    --cc=yi.z.zhang@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox