[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAADnVQLhWFKcxno53zqGtuiWwUcw+TU8gB2eCBRPQC=2y5vrFw@mail.gmail.com>
Date: Wed, 22 Nov 2023 16:43:05 -0800
From: Alexei Starovoitov <alexei.starovoitov@...il.com>
To: Peter Zijlstra <peterz@...radead.org>
Cc: Paul Walmsley <paul.walmsley@...ive.com>, Palmer Dabbelt <palmer@...belt.com>,
Albert Ou <aou@...s.berkeley.edu>, Thomas Gleixner <tglx@...utronix.de>,
Ingo Molnar <mingo@...hat.com>, Borislav Petkov <bp@...en8.de>,
Dave Hansen <dave.hansen@...ux.intel.com>, X86 ML <x86@...nel.org>,
"H. Peter Anvin" <hpa@...or.com>, "David S. Miller" <davem@...emloft.net>, David Ahern <dsahern@...nel.org>,
Alexei Starovoitov <ast@...nel.org>, Daniel Borkmann <daniel@...earbox.net>,
Andrii Nakryiko <andrii@...nel.org>, Martin KaFai Lau <martin.lau@...ux.dev>, Song Liu <song@...nel.org>,
Yonghong Song <yonghong.song@...ux.dev>, John Fastabend <john.fastabend@...il.com>,
KP Singh <kpsingh@...nel.org>, Stanislav Fomichev <sdf@...gle.com>, Hao Luo <haoluo@...gle.com>,
Jiri Olsa <jolsa@...nel.org>, Arnd Bergmann <arnd@...db.de>,
Sami Tolvanen <samitolvanen@...gle.com>, Kees Cook <keescook@...omium.org>,
Nathan Chancellor <nathan@...nel.org>, Nick Desaulniers <ndesaulniers@...gle.com>,
linux-riscv <linux-riscv@...ts.infradead.org>, LKML <linux-kernel@...r.kernel.org>,
Network Development <netdev@...r.kernel.org>, bpf <bpf@...r.kernel.org>,
linux-arch <linux-arch@...r.kernel.org>, clang-built-linux <llvm@...ts.linux.dev>,
Josh Poimboeuf <jpoimboe@...nel.org>, Joao Moreira <joao@...rdrivepizza.com>,
Mark Rutland <mark.rutland@....com>
Subject: Re: [PATCH 2/2] x86/cfi,bpf: Fix BPF JIT call
On Wed, Nov 22, 2023 at 3:15 AM Peter Zijlstra <peterz@...radead.org> wrote:
>
>
> To be very explicit, let me list all the various forms of function
> calls:
>
> Traditional:
>
> foo:
> ... code here ...
> ret
>
> direct caller:
>
> call foo
>
> indirect caller:
>
> lea foo(%rip), %r11
> call *%r11
>
> IBT:
>
> foo:
> endbr64
> ... code here ...
> ret
>
> direct caller:
>
> call foo / call foo+4
>
> indirect caller:
>
> lea foo(%rip), %r11
> ...
> call *%r11
>
>
> kCFI:
>
> __cfi_foo:
> movl $0x12345678, %rax
> (11 nops when CALL_PADDING)
> foo:
> endbr64 (when also IBT)
> ... code here ...
> ret
>
> direct caller:
>
> call foo / call foo+4
>
> indirect caller:
>
> lea foo(%rip), %r11
> ...
> movl $(-0x12345678), %r10d
> addl -15(%r11), %r10d (or -4 without CALL_PADDING)
> je 1f
> ud2
> 1:call *%r11
>
>
> FineIBT (builds as kCFI + CALL_PADDING + IBT + RETPOLINE and runtime
> patches things to look like):
>
> __cfi_foo:
> endbr64
> subl $0x12345678, %r10d
> jz foo
> ud2
> nop
> foo:
> osp nop3 (was endbr64)
> ... code here ...
> ret
>
> direct caller:
>
> call foo / call foo+4
>
> indirect caller:
>
> lea foo(%rip), %r11
> ...
> movl $0x12345678, %r10d
> subl $16, %r11
> nop4
> call *%r11
Got it. That helps a lot!
You kind of have this comment scattered through arch/x86/kernel/alternative.c
but having it in one place like above would go a long way.
Could you please add it to arch/x86/net/bpf_jit_comp.c
or arch/x86/include/asm/cfi.h next to enum cfi_mode ?
> > I'm not sure doing cfi_bpf_hash check in JITed code is completely solving the problem.
> > From bpf_dispatcher_*_func() calling into JITed will work,
> > but this emit_prologue() is doing the same job for all bpf progs.
> > Some bpf progs call each other directly and indirectly.
> > bpf_dispatcher_*_func() -> JITed_BPF_A -> JITed_BPF_B.
> > A into B can be a direct call (which cfi doesn't care about) and
> > indirect via emit_bpf_tail_call_indirect()->emit_indirect_jump().
> > Should we care about fineibt/kcfi there too?
>
> The way I understood the tail-call thing to work is that it jumps to
> bpf_prog + X86_TAIL_CALL_OFFSET, we already emit an extra ENDBR there to
> make this work.
>
> So the A -> B indirect call is otherwise unadornen and only needs ENDBR.
>
> Ideally that would use kCFI/FineIBT but since it also skips some of the
> setup, this gets to be non-trivial, so I've let this be as is.
I see. yeah. The setup is not trivial indeed. Keep as-is is fine.
> So the kCFI thing is 'new' but readily inspected by objdump or godbolt:
>
> https://godbolt.org/z/sGe18z3ca
>
> (@Sami, that .Ltmp15 thing, I don't see that in the kernel, what
> compiler flag makes that go away?)
I also noticed this discrepancy. It doesn't seem to be used.
Looks weird to spend 8 bytes to store -sizeof(ud2)
> As to FineIBT, that has a big comment in arch/x86/kernel/alternative.c
> where I rewrite the kCFI thing into FineIBT. I can refer there to avoid
> duplicating comments, would that work?
Just the above comment somewhere would work.
I wouldn't worry about duplication. This is tricky stuff.
When gcc folks get around implementing kcfi they will find it useful too.
Powered by blists - more mailing lists