Skip to content

Commit 88cf2d1

Browse files
pvts-matPlaidCat
authored andcommitted
x86/sev: Check IOBM for IOIO exceptions from user-space
jira VULN-6719 cve CVE-2023-46813 commit-author Joerg Roedel <jroedel@suse.de> commit b9cb9c4 Check the IO permission bitmap (if present) before emulating IOIO #VC exceptions for user-space. These permissions are checked by hardware already before the #VC is raised, but due to the VC-handler decoding race it needs to be checked again in software. Fixes: 25189d0 ("x86/sev-es: Add support for handling IOIO exceptions") 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> Tested-by: Tom Dohrmann <erbse.13@gmx.de> Cc: <stable@kernel.org> (cherry picked from commit b9cb9c4) Signed-off-by: Marcin Wcisło <marcin.wcislo@conclusive.pl>
1 parent 1ba2ed4 commit 88cf2d1

File tree

3 files changed

+47
-7
lines changed

3 files changed

+47
-7
lines changed

arch/x86/boot/compressed/sev.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt,
103103
return ES_OK;
104104
}
105105

106+
static enum es_result vc_ioio_check(struct es_em_ctxt *ctxt, u16 port, size_t size)
107+
{
108+
return ES_OK;
109+
}
110+
106111
#undef __init
107112
#undef __pa
108113
#define __init

arch/x86/kernel/sev-shared.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,9 @@ static enum es_result vc_insn_string_write(struct es_em_ctxt *ctxt,
663663
static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo)
664664
{
665665
struct insn *insn = &ctxt->insn;
666+
size_t size;
667+
u64 port;
668+
666669
*exitinfo = 0;
667670

668671
switch (insn->opcode.bytes[0]) {
@@ -671,49 +674,51 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo)
671674
case 0x6d:
672675
*exitinfo |= IOIO_TYPE_INS;
673676
*exitinfo |= IOIO_SEG_ES;
674-
*exitinfo |= (ctxt->regs->dx & 0xffff) << 16;
677+
port = ctxt->regs->dx & 0xffff;
675678
break;
676679

677680
/* OUTS opcodes */
678681
case 0x6e:
679682
case 0x6f:
680683
*exitinfo |= IOIO_TYPE_OUTS;
681684
*exitinfo |= IOIO_SEG_DS;
682-
*exitinfo |= (ctxt->regs->dx & 0xffff) << 16;
685+
port = ctxt->regs->dx & 0xffff;
683686
break;
684687

685688
/* IN immediate opcodes */
686689
case 0xe4:
687690
case 0xe5:
688691
*exitinfo |= IOIO_TYPE_IN;
689-
*exitinfo |= (u8)insn->immediate.value << 16;
692+
port = (u8)insn->immediate.value & 0xffff;
690693
break;
691694

692695
/* OUT immediate opcodes */
693696
case 0xe6:
694697
case 0xe7:
695698
*exitinfo |= IOIO_TYPE_OUT;
696-
*exitinfo |= (u8)insn->immediate.value << 16;
699+
port = (u8)insn->immediate.value & 0xffff;
697700
break;
698701

699702
/* IN register opcodes */
700703
case 0xec:
701704
case 0xed:
702705
*exitinfo |= IOIO_TYPE_IN;
703-
*exitinfo |= (ctxt->regs->dx & 0xffff) << 16;
706+
port = ctxt->regs->dx & 0xffff;
704707
break;
705708

706709
/* OUT register opcodes */
707710
case 0xee:
708711
case 0xef:
709712
*exitinfo |= IOIO_TYPE_OUT;
710-
*exitinfo |= (ctxt->regs->dx & 0xffff) << 16;
713+
port = ctxt->regs->dx & 0xffff;
711714
break;
712715

713716
default:
714717
return ES_DECODE_FAILED;
715718
}
716719

720+
*exitinfo |= port << 16;
721+
717722
switch (insn->opcode.bytes[0]) {
718723
case 0x6c:
719724
case 0x6e:
@@ -723,12 +728,15 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo)
723728
case 0xee:
724729
/* Single byte opcodes */
725730
*exitinfo |= IOIO_DATA_8;
731+
size = 1;
726732
break;
727733
default:
728734
/* Length determined by instruction parsing */
729735
*exitinfo |= (insn->opnd_bytes == 2) ? IOIO_DATA_16
730736
: IOIO_DATA_32;
737+
size = (insn->opnd_bytes == 2) ? 2 : 4;
731738
}
739+
732740
switch (insn->addr_bytes) {
733741
case 2:
734742
*exitinfo |= IOIO_ADDR_16;
@@ -744,7 +752,7 @@ static enum es_result vc_ioio_exitinfo(struct es_em_ctxt *ctxt, u64 *exitinfo)
744752
if (insn_has_rep_prefix(insn))
745753
*exitinfo |= IOIO_REP;
746754

747-
return ES_OK;
755+
return vc_ioio_check(ctxt, (u16)port, size);
748756
}
749757

750758
static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)

arch/x86/kernel/sev.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,33 @@ static enum es_result vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt
493493
return ES_OK;
494494
}
495495

496+
static enum es_result vc_ioio_check(struct es_em_ctxt *ctxt, u16 port, size_t size)
497+
{
498+
BUG_ON(size > 4);
499+
500+
if (user_mode(ctxt->regs)) {
501+
struct thread_struct *t = &current->thread;
502+
struct io_bitmap *iobm = t->io_bitmap;
503+
size_t idx;
504+
505+
if (!iobm)
506+
goto fault;
507+
508+
for (idx = port; idx < port + size; ++idx) {
509+
if (test_bit(idx, iobm->bitmap))
510+
goto fault;
511+
}
512+
}
513+
514+
return ES_OK;
515+
516+
fault:
517+
ctxt->fi.vector = X86_TRAP_GP;
518+
ctxt->fi.error_code = 0;
519+
520+
return ES_EXCEPTION;
521+
}
522+
496523
/* Include code shared with pre-decompression boot stage */
497524
#include "sev-shared.c"
498525

0 commit comments

Comments
 (0)