diff options
author | Renato Botelho <renato@netgate.com> | 2018-05-08 13:01:44 -0300 |
---|---|---|
committer | Renato Botelho <renato@netgate.com> | 2018-05-08 13:01:44 -0300 |
commit | 70d1caf0ad967030b2ce835dc0f116ed1733c82c (patch) | |
tree | d8d3e5c39f96c4f1a230eb163d57b858f4339f57 /sys/i386 | |
parent | 77c0e2e68638110a69edb20c8beaf1f288912b09 (diff) | |
download | FreeBSD-src-70d1caf0ad967030b2ce835dc0f116ed1733c82c.zip FreeBSD-src-70d1caf0ad967030b2ce835dc0f116ed1733c82c.tar.gz |
Proposed fix for CVE-2018-8897
Diffstat (limited to 'sys/i386')
-rw-r--r-- | sys/i386/i386/trap.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c index 000ff17..7fa94f4 100644 --- a/sys/i386/i386/trap.c +++ b/sys/i386/i386/trap.c @@ -116,6 +116,8 @@ void dblfault_handler(void); extern inthand_t IDTVEC(lcall_syscall); +extern inthand_t IDTVEC(bpt), IDTVEC(dbg), IDTVEC(int0x80_syscall); + #define MAX_TRAP_MSG 32 static char *trap_msg[] = { "", /* 0 unused */ @@ -668,6 +670,34 @@ kernel_trctrap: load_dr6(rdr6() & ~0xf); goto out; } + + /* + * Malicious user code can configure a debug + * register watchpoint to trap on data access + * to the top of stack and then execute 'pop + * %ss; int 3'. Due to exception deferral for + * 'pop %ss', the CPU will not interrupt 'int + * 3' to raise the DB# exception for the debug + * register but will postpone the DB# until + * execution of the first instruction of the + * BP# handler (in kernel mode). Normally the + * previous check would ignore DB# exceptions + * for watchpoints on user addresses raised in + * kernel mode. However, some CPU errata + * include cases where DB# exceptions do not + * properly set bits in %dr6, e.g. Haswell + * HSD23 and Skylake-X SKZ24. + * + * A deferred DB# can also be raised on the + * first instructions of system call entry + * points or single-step traps via similar use + * of 'pop %ss' or 'mov xxx, %ss'. + */ + if (frame->tf_eip == + (uintptr_t)IDTVEC(int0x80_syscall) || + frame->tf_eip == (uintptr_t)IDTVEC(bpt) || + frame->tf_eip == (uintptr_t)IDTVEC(dbg)) + return; /* * FALLTHROUGH (TRCTRAP kernel mode, kernel address) */ |