[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20220301231022.5jb7rkzgpe7mwwku@treble>
Date: Tue, 1 Mar 2022 15:10:22 -0800
From: Josh Poimboeuf <jpoimboe@...hat.com>
To: Peter Zijlstra <peterz@...radead.org>
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 Fri, Feb 25, 2022 at 04:28:32PM +0100, Peter Zijlstra wrote:
> 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");
This is a little excessive on my 192 CPUs :-)
It also messes with the pr_cont()s in announce_cpu():
[ 3.733446] x86: Booting SMP configuration:
[ 3.734342] .... node #0, CPUs: #1
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 3.770955] #2
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 3.802979] #3
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 3.835459] #4
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 3.866826] #5
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 3.898690] #6
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 3.930355] #7
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 3.961493] #8
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 3.993500] #9
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 4.024952] #10
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 4.056491] #11
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 4.087493] #12
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 4.118907] #13
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 4.150494] #14
[ 3.534902] CET detected: Indirect Branch Tracking enabled
[ 4.181425] #15
--
Josh
Powered by blists - more mailing lists