diff options
author | Andy Lutomirski <luto@kernel.org> | 2021-02-19 21:18:54 -0800 |
---|---|---|
committer | Andy Lutomirski <luto@kernel.org> | 2021-02-19 21:18:54 -0800 |
commit | bfaecaf0dad8f61e80285125f4895c9737e3d6d8 (patch) | |
tree | d5f48d736a45bda394e3cbee97ac491158b02724 | |
parent | bf85057ed696c8996a5f5b924a3fd58698450511 (diff) | |
download | linux-x86/no_sce.tar.gz |
[EVIL] Run with EFER.SCE = 0x86/no_sce
Don't think too hard about this patch. Definitely don't expect it to
work reliably.
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 6 | ||||
-rw-r--r-- | arch/x86/kernel/traps.c | 15 |
2 files changed, 21 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index cf43d7eef5a7a2..190ccf8281fa2f 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1748,6 +1748,8 @@ EXPORT_PER_CPU_SYMBOL(__preempt_count); /* May not be marked __init: used by software suspend */ void syscall_init(void) { + u64 val; + wrmsr(MSR_STAR, 0, (__USER32_CS << 16) | __KERNEL_CS); wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64); wrmsrl(MSR_CSTAR, (unsigned long)entry_SYSCALL_compat); @@ -1774,6 +1776,10 @@ void syscall_init(void) wrmsrl(MSR_SYSCALL_MASK, X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF| X86_EFLAGS_IOPL|X86_EFLAGS_AC|X86_EFLAGS_NT); + + rdmsrl(MSR_EFER, val); + val &= ~EFER_SCE; + wrmsrl(MSR_EFER, val); } #else /* CONFIG_X86_64 */ diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 7f5aec758f0eea..a71421de74f3b5 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -61,6 +61,7 @@ #include <asm/insn.h> #include <asm/insn-eval.h> #include <asm/vdso.h> +#include <asm/syscall.h> #ifdef CONFIG_X86_64 #include <asm/x86_init.h> @@ -259,6 +260,20 @@ DEFINE_IDTENTRY_RAW(exc_invalid_op) if (!user_mode(regs) && handle_bug(regs)) return; + if (user_mode(regs)) { + /* + * emulate SYSCALL. I have no idea why ax is a separate + * argument. it's probably my fault. + * + * Don't think too hard about the entry mess here. + * This needs to be cleaned up so that syscalls can + * be cleanly executed from "irqentry" context. + */ + regs->ip += 2; /* world's best emulator */ + do_syscall_64(regs->ax, regs); + return; + } + state = irqentry_enter(regs); instrumentation_begin(); handle_invalid_op(regs); |