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:   Fri, 25 Feb 2022 16:28:32 +0100
From:   Peter Zijlstra <peterz@...radead.org>
To:     Josh Poimboeuf <jpoimboe@...hat.com>
Cc:     x86@...nel.org, joao@...rdrivepizza.com, hjl.tools@...il.com,
        andrew.cooper3@...rix.com, linux-kernel@...r.kernel.org,
        ndesaulniers@...gle.com, keescook@...omium.org,
        samitolvanen@...gle.com, mark.rutland@....com,
        alyssa.milburn@...el.com, mbenes@...e.cz, rostedt@...dmis.org,
        mhiramat@...nel.org, alexei.starovoitov@...il.com
Subject: Re: [PATCH v2 00/39] x86: Kernel IBT

On Thu, Feb 24, 2022 at 12:26:02PM -0800, Josh Poimboeuf wrote:

> Bricked my SPR:
> 
> [   21.602888] jump_label: Fatal kernel bug, unexpected op at sched_clock_stable+0x4/0x20 [0000000074a0db20] (eb 06 b8 01 00 != eb 0a 00 00 00)) size:2 type:0

> ffffffff81120a70 <sched_clock_stable>:
> ffffffff81120a70:       f3 0f 1e fa             endbr64
> ffffffff81120a74:       eb 06                   jmp    ffffffff81120a7c <sched_clock_stable+0xc>
> ffffffff81120a76:       b8 01 00 00 00          mov    $0x1,%eax
> ffffffff81120a7b:       c3                      retq
> ffffffff81120a7c:       f3 0f 1e fa             endbr64
> ffffffff81120a80:       31 c0                   xor    %eax,%eax
> ffffffff81120a82:       c3                      retq
> ffffffff81120a83:       66 66 2e 0f 1f 84 00    data16 nopw %cs:0x0(%rax,%rax,1)
> ffffffff81120a8a:       00 00 00 00
> ffffffff81120a8e:       66 90                   xchg   %ax,%ax

This is due to you having a very old (and arguably buggy) compiler :-( I
can reproduce with gcc-8.4 and gcc-9.4, my gcc-10.3 compiler no longer
generates daft code like that, nor do any later.

That said, I can fix objtool to also re-write jumps to in-the-middle
ENDBR like this, but then I do get a bunch of:

OBJTOOL vmlinux.o
vmlinux.o: warning: objtool: displacement doesn't fit
vmlinux.o: warning: objtool: ep_insert()+0xbc5: Direct IMM jump to ENDBR; cannot fix
vmlinux.o: warning: objtool: displacement doesn't fit
vmlinux.o: warning: objtool: configfs_depend_prep()+0x76: Direct IMM jump to ENDBR; cannot fix
vmlinux.o: warning: objtool: displacement doesn't fit
vmlinux.o: warning: objtool: request_key_and_link()+0x17b: Direct IMM jump to ENDBR; cannot fix
vmlinux.o: warning: objtool: displacement doesn't fit
vmlinux.o: warning: objtool: blk_mq_poll()+0x2e0: Direct IMM jump to ENDBR; cannot fix

The alternative is only skipping endbr at +0 I suppose, lemme go try
that with the brand spanking new skip_endbr() function.

Yep,.. that seems to cure things. It noaw boats when build with old
crappy compilers too.


--- a/arch/x86/include/asm/ibt.h
+++ b/arch/x86/include/asm/ibt.h
@@ -47,6 +47,8 @@ static inline bool is_endbr(unsigned int
 	return val == gen_endbr();
 }
 
+extern void *skip_endbr(void *);
+
 extern __noendbr u64 ibt_save(void);
 extern __noendbr void ibt_restore(u64 save);
 
@@ -71,6 +73,7 @@ extern __noendbr void ibt_restore(u64 sa
 #define __noendbr
 
 static inline bool is_endbr(unsigned int val) { return false; }
+static inline void *skip_endbr(void *addr) { return addr; }
 
 static inline u64 ibt_save(void) { return 0; }
 static inline void ibt_restore(u64 save) { }
--- a/arch/x86/include/asm/text-patching.h
+++ b/arch/x86/include/asm/text-patching.h
@@ -112,10 +112,7 @@ void __text_gen_insn(void *buf, u8 opcod
 	OPTIMIZER_HIDE_VAR(addr);
 	OPTIMIZER_HIDE_VAR(dest);
 
-#ifdef CONFIG_X86_KERNEL_IBT
-	if (is_endbr(*(u32 *)dest))
-		dest += 4;
-#endif
+	dest = skip_endbr((void *)dest);
 
 	insn->opcode = opcode;
 
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -620,6 +620,19 @@ __noendbr void ibt_restore(u64 save)
 	}
 }
 
+
+void *skip_endbr(void *addr)
+{
+	unsigned long size, offset;
+
+	if (is_endbr(*(unsigned int *)addr) &&
+	    kallsyms_lookup_size_offset((unsigned long)addr, &size, &offset) &&
+	    !offset)
+		addr += 4;
+
+	return addr;
+}
+
 #endif
 
 static __always_inline void setup_cet(struct cpuinfo_x86 *c)
@@ -636,7 +649,10 @@ static __always_inline void setup_cet(st
 	if (!ibt_selftest()) {
 		pr_err("IBT selftest: Failed!\n");
 		setup_clear_cpu_cap(X86_FEATURE_IBT);
+		return;
 	}
+
+	pr_info("CET detected: Indirect Branch Tracking enabled\n");
 }
 
 __noendbr void cet_disable(void)
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -350,18 +350,12 @@ static int __bpf_arch_text_poke(void *ip
 	u8 *prog;
 	int ret;
 
-#ifdef CONFIG_X86_KERNEL_IBT
-	if (is_endbr(*(u32 *)ip))
-		ip += 4;
-#endif
+	ip = skip_endbr(ip);
 
 	memcpy(old_insn, nop_insn, X86_PATCH_SIZE);
 	if (old_addr) {
 		prog = old_insn;
-#ifdef CONFIG_X86_KERNEL_IBT
-		if (is_endbr(*(u32 *)old_addr))
-			old_addr += 4;
-#endif
+		old_addr = skip_endbr(old_addr);
 		ret = t == BPF_MOD_CALL ?
 		      emit_call(&prog, old_addr, ip) :
 		      emit_jump(&prog, old_addr, ip);
@@ -372,10 +366,7 @@ static int __bpf_arch_text_poke(void *ip
 	memcpy(new_insn, nop_insn, X86_PATCH_SIZE);
 	if (new_addr) {
 		prog = new_insn;
-#ifdef CONFIG_X86_KERNEL_IBT
-		if (is_endbr(*(u32 *)new_addr))
-			new_addr += 4;
-#endif
+		new_addr = skip_endbr(new_addr);
 		ret = t == BPF_MOD_CALL ?
 		      emit_call(&prog, new_addr, ip) :
 		      emit_jump(&prog, new_addr, ip);

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ