From: Hans-Jörg Höxer Subject: SEV-ES guest: In vctrap() only allow CPUID from userspace To: Date: Tue, 1 Jul 2025 10:36:33 +0200 Hi, this diff restricts #VC trap handling. Take care, HJ. ----------- commit bbf8ca5bfcd41771b0ecac3597bf033a603a54c3 Author: Hans-Joerg Hoexer Date: Thu Mar 20 17:17:31 2025 +0100 SEV-ES guest: In vctrap() only allow CPUID also from userspace CPUID is the only instruction we allow to raise a #VC exception also from user space. All other instructions are limited to raise #VC from kernel space only. With respect to rdmsr/wrmsr this is an additional safe-guard, as these two instructions will raise a #GP anyway when the CPL is greater than 0. With respect to in/out userland can be allowed to access IO ports. Howerver, for now we do not want to support this. diff --git a/sys/arch/amd64/amd64/trap.c b/sys/arch/amd64/amd64/trap.c index f68cb2c90d5..9c532846c41 100644 --- a/sys/arch/amd64/amd64/trap.c +++ b/sys/arch/amd64/amd64/trap.c @@ -97,7 +97,7 @@ int upageflttrap(struct trapframe *, uint64_t); int kpageflttrap(struct trapframe *, uint64_t); -int vctrap(struct trapframe *); +int vctrap(struct trapframe *, int); void kerntrap(struct trapframe *); void usertrap(struct trapframe *); void ast(struct trapframe *); @@ -302,7 +302,7 @@ kpageflttrap(struct trapframe *frame, uint64_t cr2) } int -vctrap(struct trapframe *frame) +vctrap(struct trapframe *frame, int user) { uint64_t sw_exitcode, sw_exitinfo1, sw_exitinfo2; uint8_t *rip = (uint8_t *)(frame->tf_rip); @@ -340,6 +340,8 @@ vctrap(struct trapframe *frame) frame->tf_rip += 2; break; case SVM_VMEXIT_MSR: { + if (user) + return 0; /* not allowed from userspace */ if (*rip == 0x0f && *(rip + 1) == 0x30) { /* WRMSR */ ghcb_sync_val(GHCB_RAX, GHCB_SZ32, &syncout); @@ -357,6 +359,8 @@ vctrap(struct trapframe *frame) break; } case SVM_VMEXIT_IOIO: { + if (user) + return 0; /* not allowed from userspace */ switch (*rip) { case 0x66: { switch (*(rip + 1)) { @@ -505,7 +509,7 @@ kerntrap(struct trapframe *frame) #endif /* NISA > 0 */ case T_VC: - if (vctrap(frame)) + if (vctrap(frame, 0)) return; goto we_re_toast; } @@ -588,9 +592,11 @@ usertrap(struct trapframe *frame) : ILL_BADSTK; break; case T_VC: - vctrap(frame); - goto out; - + if (vctrap(frame, 1)) + goto out; + sig = SIGILL; + code = ILL_PRVOPC; + break; case T_PAGEFLT: /* page fault */ if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), "[%s]%d/%d sp=%lx inside %lx-%lx: not MAP_STACK\n", diff --git a/sys/arch/amd64/amd64/vector.S b/sys/arch/amd64/amd64/vector.S index 59823862c18..4181ab216d0 100644 --- a/sys/arch/amd64/amd64/vector.S +++ b/sys/arch/amd64/amd64/vector.S @@ -553,6 +553,7 @@ IDTVEC(vctrap_early) TRAP_ENTRY_KERN /* early #VC has to be in kernel mode */ cld movq %rsp, %rdi + movq $0x0, %rsi call vctrap movq $0,-8(%rsp) INTRFASTEXIT