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]
Date:   Tue, 7 Apr 2020 22:45:30 +0200
From:   Peter Zijlstra <peterz@...radead.org>
To:     Andrew Cooper <andrew.cooper3@...rix.com>
Cc:     tglx@...utronix.de, linux-kernel@...r.kernel.org,
        hch@...radead.org, sean.j.christopherson@...el.com,
        mingo@...hat.com, bp@...en8.de, hpa@...or.com, x86@...nel.org,
        kenny@...ix.com, jeyu@...nel.org, rasmus.villemoes@...vas.dk,
        pbonzini@...hat.com, fenghua.yu@...el.com, xiaoyao.li@...el.com,
        nadav.amit@...il.com, thellstrom@...are.com, tony.luck@...el.com,
        rostedt@...dmis.org, gregkh@...uxfoundation.org, jannh@...gle.com,
        keescook@...omium.org, David.Laight@...lab.com,
        dcovelli@...are.com, mhiramat@...nel.org
Subject: Re: [PATCH 0/4] x86/module: Out-of-tree module decode and sanitize

On Tue, Apr 07, 2020 at 09:11:17PM +0100, Andrew Cooper wrote:

> Sorry - should have been more clear.  By friends, I meant LGDT, LIDT,
> LLDT and LTR which are the 4 system table loading instructions.  LLDT
> and LTR depend on being able to write into the GDT, but still have no
> business being used.
> 
> Also, LMSW if you care about it, but its utility is somewhere close to 0
> these days, so probably not worth the cycles searching for.
> 
> The Sxxx instructions have no business being used, but are also harmless
> and similarly, probably not worth spending cycles searching for.
> 
> L{D,E,F,S}S are functional equivalents to "MOV val1, %sreg; mov val2,
> %reg"  so harmless (also mode specific as to whether they are useable).

OK, LxDT + LTR it is.

> Other things to consider, while we're on a roll:
> 
> WRMSR and RDMSR:  There is a lot of damage which can be done with these,
> and at least forcing people to use the regular hooks will get proper
> paravirt support and/or exception support.  That said, this might cause
> large carnage to out-of-tree modules which are a device driver for
> random platform things.

Yeah, I had already considered that, didn't want to touch that just yet.

> POPF: Don't really want someone being able to set IOPL3.  However, this
> might quite easily show up as a false positive depending on how the
> irqsafe infrastructure gets inlined.

local_irq_restore() will be a POPF :/

> SYSRET/SYSEXIT/IRET: Don't want a module returning to userspace behind
> the kernels back. 

Good thinking, let me add this.

> IRET may be a false positive for serialising
> purposes, as may be a write to CR2 for that matter.

We can out-of-line and export sync_core() for that.

> Looking over the list of other privileged instructions, CLTS,
> {,WB,WBNO}INVD, INVLPG and HLT might be candidates for "clearly doing
> something which shouldn't be done".  Not on the list is INVPCID which
> falls into the same category.
> 
> Come to think about it, it might be easier to gauge on CPL0 instructions
> and whitelist the ok ones, such as VMX and SVM for out-of-tree hypervisors.

Fair enough, I'll go over those tomorrow.

For now I ended up with:

---
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -282,6 +282,68 @@ static bool insn_is_mov_DRn(struct insn
 	return false;
 }

+static bool insn_is_GDT_modifier(struct insn *insn)
+{
+	u8 modrm = insn->modrm.bytes[0];
+	u8 modrm_mod = X86_MODRM_MOD(modrm);
+	u8 modrm_reg = X86_MODRM_REG(modrm);
+
+	if (insn->opcode.bytes[0] != 0x0f)
+		return false;
+
+	switch (insn->opcode.bytes[1]) {
+	case 0x00: /* Grp6 */
+		switch (modrm_reg) {
+		/* case 0x0: SLDT */
+		case 0x2: /* LLDT */
+		case 0x3: /* LTR */
+			return true;
+
+		default:
+			break;
+		}
+		break;
+
+	case 0x01: /* Grp7 */
+		if (modrm_mod == 0x03)
+			break;
+
+		switch (modrm_reg) {
+		/* case 0x0: SGDT */
+		/* case 0x1: SIDT */
+		case 0x2: /* LGDT */
+		case 0x3: /* LIDT */
+			return true;
+
+		default:
+			break;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return false;
+}
+
+static bool insn_is_xRET(struct insn *insn)
+{
+	u8 op1 = insn->opcode.bytes[0];
+	u8 op2 = insn->opcode.bytes[1];
+
+	if (op1 == 0xcf) /* IRET */
+		return true;
+
+	if (op1 != 0x0f)
+		return false;
+
+	if (op2 == 0x07 || op2 == 0x35) /* SYSRET, SYSEXIT */
+		return true;
+
+	return false;
+}
+
 static int decode_module(struct module *mod, void *text, void *text_end, bool sld_safe)
 {
 	bool allow_vmx = sld_safe || !split_lock_enabled();

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ