Messages in this thread Patch in this message | | | Date | Thu, 16 Sep 2021 23:05:09 +0200 | From | Peter Zijlstra <> | Subject | Re: IOPL emulation breaks hpasmd (hp-health) needed by HP DL380 G4 servers |
| |
On Thu, Sep 16, 2021 at 10:27:17PM +0200, Ondrej Zary wrote: > (gdb) run > Starting program: /opt/hp/hp-health/bin/IrqRouteTbl > > Program received signal SIGSEGV, Segmentation fault. > 0xf7fc509b in ?? () > (gdb) bt > #0 0xf7fc509b in ?? () > #1 0x08048848 in ?? () > #2 0x08048aa1 in ?? () > #3 0x08048e05 in ?? () > #4 0xf7df9e46 in __libc_start_main () from /lib32/libc.so.6 > #5 0xf7ffd000 in ?? () from /lib/ld-linux.so.2 > Backtrace stopped: previous frame inner to this frame (corrupt stack?) > (gdb) x/3i $pc > => 0xf7fc509b: cli > 0xf7fc509c: push %ebp > 0xf7fc509d: mov %esp,%ebp > > OMG, maybe is it calling into the mmapped BIOS area?
Lol... does something like the below (which *really* wants to be behind something like sysctl.iopl_fake_if) work for you?
---
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index a58800973aed..55c3904e656d 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -528,6 +528,34 @@ static enum kernel_gp_hint get_kernel_gp_address(struct pt_regs *regs, #define GPFSTR "general protection fault" +bool fixup_iopl_exception(struct pt_regs *regs) +{ + struct thread_struct *t = ¤t->thread; + unsigned char buf[MAX_INSN_SIZE]; + struct insn insn; + int nr_copied; + + if (!IS_ENABLED(CONFIG_X86_IOPL_IOPERM) || t->iopl_emul != 3 || !regs) + return false; + + nr_copied = insn_fetch_from_user(regs, buf); + if (nr_copied <= 0) + return false; + + if (!insn_decode_from_regs(&insn, regs, buf, nr_copied)) + return false; + + if (insn.length != 1) + return false; + + if (insn.opcode.bytes[0] != 0xfa && + insn.opcode.bytes[0] != 0xfb) + return false; + + regs->ip += 1; + return true; +} + DEFINE_IDTENTRY_ERRORCODE(exc_general_protection) { char desc[sizeof(GPFSTR) + 50 + 2*sizeof(unsigned long) + 1] = GPFSTR; @@ -553,6 +581,9 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection) tsk = current; if (user_mode(regs)) { + if (fixup_iopl_exception(regs)) + goto exit; + tsk->thread.error_code = error_code; tsk->thread.trap_nr = X86_TRAP_GP;
| |