lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20210916210509.GG4323@worktop.programming.kicks-ass.net>
Date:   Thu, 16 Sep 2021 23:05:09 +0200
From:   Peter Zijlstra <peterz@...radead.org>
To:     Ondrej Zary <linux@...y.sk>
Cc:     Thomas Gleixner <tglx@...utronix.de>, x86@...nel.org,
        linux-kernel@...r.kernel.org
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 = &current->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;
 

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ