UPSTREAM: x86/sev: Check for user-space IOIO pointing to kernel space

Upstream commit: 63e44bc52047f182601e7817da969a105aa1f721

Check the memory operand of INS/OUTS before emulating the instruction.
The #VC exception can get raised from user-space, but the memory operand
can be manipulated to access kernel memory before the emulation actually
begins and after the exception handler has run.

  [ bp: Massage commit message. ]

Bug: 309733863
Fixes: 597cfe4821 ("x86/boot/compressed/64: Setup a GHCB-based VC Exception handler")
Reported-by: Tom Dohrmann <erbse.13@gmx.de>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Cc: <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 6550cbe25d)
Signed-off-by: Lee Jones <joneslee@google.com>
Change-Id: Ie21d33ca750d1668244c9a954cb7ab6872066c2e
This commit is contained in:
Joerg Roedel
2023-10-16 14:42:50 +02:00
committed by Treehugger Robot
parent 5b118b5b1d
commit 718225bcc1
2 changed files with 34 additions and 2 deletions

View File

@@ -111,6 +111,11 @@ static enum es_result vc_ioio_check(struct es_em_ctxt *ctxt, u16 port, size_t si
return ES_OK; return ES_OK;
} }
static bool fault_in_kernel_space(unsigned long address)
{
return false;
}
#undef __init #undef __init
#undef __pa #undef __pa
#define __init #define __init

View File

@@ -217,6 +217,23 @@ fail:
asm volatile("hlt\n"); asm volatile("hlt\n");
} }
static enum es_result vc_insn_string_check(struct es_em_ctxt *ctxt,
unsigned long address,
bool write)
{
if (user_mode(ctxt->regs) && fault_in_kernel_space(address)) {
ctxt->fi.vector = X86_TRAP_PF;
ctxt->fi.error_code = X86_PF_USER;
ctxt->fi.cr2 = address;
if (write)
ctxt->fi.error_code |= X86_PF_WRITE;
return ES_EXCEPTION;
}
return ES_OK;
}
static enum es_result vc_insn_string_read(struct es_em_ctxt *ctxt, static enum es_result vc_insn_string_read(struct es_em_ctxt *ctxt,
void *src, char *buf, void *src, char *buf,
unsigned int data_size, unsigned int data_size,
@@ -224,7 +241,12 @@ static enum es_result vc_insn_string_read(struct es_em_ctxt *ctxt,
bool backwards) bool backwards)
{ {
int i, b = backwards ? -1 : 1; int i, b = backwards ? -1 : 1;
enum es_result ret = ES_OK; unsigned long address = (unsigned long)src;
enum es_result ret;
ret = vc_insn_string_check(ctxt, address, false);
if (ret != ES_OK)
return ret;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
void *s = src + (i * data_size * b); void *s = src + (i * data_size * b);
@@ -245,7 +267,12 @@ static enum es_result vc_insn_string_write(struct es_em_ctxt *ctxt,
bool backwards) bool backwards)
{ {
int i, s = backwards ? -1 : 1; int i, s = backwards ? -1 : 1;
enum es_result ret = ES_OK; unsigned long address = (unsigned long)dst;
enum es_result ret;
ret = vc_insn_string_check(ctxt, address, true);
if (ret != ES_OK)
return ret;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
void *d = dst + (i * data_size * s); void *d = dst + (i * data_size * s);