x86/sev: Check for user-space IOIO pointing to kernel space
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. ]
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>
This commit is contained in:
Родитель
b9cb9c4558
Коммит
63e44bc520
|
@ -108,6 +108,11 @@ static enum es_result vc_ioio_check(struct es_em_ctxt *ctxt, u16 port, size_t si
|
|||
return ES_OK;
|
||||
}
|
||||
|
||||
static bool fault_in_kernel_space(unsigned long address)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#undef __init
|
||||
#define __init
|
||||
|
||||
|
|
|
@ -592,6 +592,23 @@ fail:
|
|||
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
|
||||
}
|
||||
|
||||
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,
|
||||
void *src, char *buf,
|
||||
unsigned int data_size,
|
||||
|
@ -599,7 +616,12 @@ static enum es_result vc_insn_string_read(struct es_em_ctxt *ctxt,
|
|||
bool backwards)
|
||||
{
|
||||
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++) {
|
||||
void *s = src + (i * data_size * b);
|
||||
|
@ -620,7 +642,12 @@ static enum es_result vc_insn_string_write(struct es_em_ctxt *ctxt,
|
|||
bool backwards)
|
||||
{
|
||||
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++) {
|
||||
void *d = dst + (i * data_size * s);
|
||||
|
|
Загрузка…
Ссылка в новой задаче