[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aMsk43I7UkGbmL88@google.com>
Date: Wed, 17 Sep 2025 14:15:15 -0700
From: Sean Christopherson <seanjc@...gle.com>
To: Chao Gao <chao.gao@...el.com>
Cc: Paolo Bonzini <pbonzini@...hat.com>, kvm@...r.kernel.org, linux-kernel@...r.kernel.org,
Tom Lendacky <thomas.lendacky@....com>, Mathias Krause <minipli@...ecurity.net>,
John Allen <john.allen@....com>, Rick Edgecombe <rick.p.edgecombe@...el.com>,
Maxim Levitsky <mlevitsk@...hat.com>, Xiaoyao Li <xiaoyao.li@...el.com>,
Zhang Yi Z <yi.z.zhang@...ux.intel.com>
Subject: Re: [PATCH v15 18/41] KVM: x86: Don't emulate instructions affected
by CET features
On Wed, Sep 17, 2025, Chao Gao wrote:
> On Fri, Sep 12, 2025 at 04:22:56PM -0700, Sean Christopherson wrote:
> >From: Yang Weijiang <weijiang.yang@...el.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.
>
> I modified KUT's cet.c to verify that near jumps, near returns, and far
> transfers (e.g., IRET) trigger the emulation failure logic added by this
> patch when guests enable Shadow Stack or IBT.
>
> I found only one minor issue: near return instructions were not tagged with
> ShadowStack.
Heh, I had just found this through inspection.
> The following diff fixes this issue:
>
> diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
> index e4be54a677b0..b1c9816bd5c6 100644
> --- a/arch/x86/kvm/emulate.c
> +++ b/arch/x86/kvm/emulate.c
> @@ -4326,8 +4326,8 @@ static const struct opcode opcode_table[256] = {
> X8(I(DstReg | SrcImm64 | Mov, em_mov)),
> /* 0xC0 - 0xC7 */
> G(ByteOp | Src2ImmByte, group2), G(Src2ImmByte, group2),
> - I(ImplicitOps | NearBranch | SrcImmU16 | IsBranch, em_ret_near_imm),
> - I(ImplicitOps | NearBranch | IsBranch, em_ret),
> + I(ImplicitOps | NearBranch | SrcImmU16 | IsBranch | ShadowStack, em_ret_near_imm),
> + I(ImplicitOps | NearBranch | IsBranch | ShadowStack, em_ret),
Tangentially directly related to this bug, I think we should manual annotation
where possible. I don't see an easy way to do that for ShadowStack, but for IBT
we can use IsBranch, NearBranch and the SrcXXX operance to detect IBT-affected
instructions. It's obviously more complex, but programmatically detecting
indirect branches should be less error prone. I'll do so in the next version.
> I(DstReg | SrcMemFAddr | ModRM | No64 | Src2ES, em_lseg),
> I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg),
> G(ByteOp, group11), G(0, group11),
>
>
> And for reference, below are the changes I made to KUT's cet.c
I now have a more comprehensive set of testcases, and it can be upstreamed
(relies on KVM's default behavior of injecting #UD at CPL==3 on failed emulation).
Powered by blists - more mailing lists