[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAGn_itzSC7K_eF7Lbm-im83VObqqoz6rvYMqVAOCXdD0pQ+M6Q@mail.gmail.com>
Date: Wed, 31 Dec 2025 08:06:03 +0100
From: Anton Protopopov <a.s.protopopov@...il.com>
To: Xu Kuohai <xukuohai@...weicloud.com>
Cc: Alexei Starovoitov <alexei.starovoitov@...il.com>, bpf <bpf@...r.kernel.org>,
LKML <linux-kernel@...r.kernel.org>, Alexei Starovoitov <ast@...nel.org>,
Daniel Borkmann <daniel@...earbox.net>, Andrii Nakryiko <andrii@...nel.org>,
Martin KaFai Lau <martin.lau@...ux.dev>, Eduard Zingerman <eddyz87@...il.com>,
Yonghong Song <yonghong.song@...ux.dev>, Puranjay Mohan <puranjay@...nel.org>,
Catalin Marinas <catalin.marinas@....com>, Will Deacon <will@...nel.org>
Subject: Re: [PATCH bpf-next v3] bpf: arm64: Fix panic due to missing BTI at
indirect jump targets
On Wed, Dec 31, 2025 at 7:47 AM Xu Kuohai <xukuohai@...weicloud.com> wrote:
>
> On 12/31/2025 10:16 AM, Alexei Starovoitov wrote:
> > On Tue, Dec 30, 2025 at 6:05 PM Xu Kuohai <xukuohai@...weicloud.com> wrote:
> >>
> >> On 12/31/2025 2:20 AM, Alexei Starovoitov wrote:
> >>> On Fri, Dec 26, 2025 at 11:49 PM Xu Kuohai <xukuohai@...weicloud.com> wrote:
> >>>>
> >>>> From: Xu Kuohai <xukuohai@...wei.com>
> >>>>
> >>>> When BTI is enabled, the indirect jump selftest triggers BTI exception:
> >>>>
> >>>> Internal error: Oops - BTI: 0000000036000003 [#1] SMP
> >>>> ...
> >>>> Call trace:
> >>>> bpf_prog_2e5f1c71c13ac3e0_big_jump_table+0x54/0xf8 (P)
> >>>> bpf_prog_run_pin_on_cpu+0x140/0x464
> >>>> bpf_prog_test_run_syscall+0x274/0x3ac
> >>>> bpf_prog_test_run+0x224/0x2b0
> >>>> __sys_bpf+0x4cc/0x5c8
> >>>> __arm64_sys_bpf+0x7c/0x94
> >>>> invoke_syscall+0x78/0x20c
> >>>> el0_svc_common+0x11c/0x1c0
> >>>> do_el0_svc+0x48/0x58
> >>>> el0_svc+0x54/0x19c
> >>>> el0t_64_sync_handler+0x84/0x12c
> >>>> el0t_64_sync+0x198/0x19c
> >>>>
> >>>> This happens because no BTI instruction is generated by the JIT for
> >>>> indirect jump targets.
> >>>>
> >>>> Fix it by emitting BTI instruction for every possible indirect jump
> >>>> targets when BTI is enabled. The targets are identified by traversing
> >>>> all instruction arrays of jump table type used by the BPF program,
> >>>> since indirect jump targets can only be read from instruction arrays
> >>>> of jump table type.
> >>>
> >>> earlier you said:
> >>>
> >>>> As Anton noted, even though jump tables are currently the only type
> >>>> of instruction array, users may still create insn_arrays that are not
> >>>> used as jump tables. In such cases, there is no need to emit BTIs.
> >>>
> >>> yes, but it's not worth it to make this micro optimization in JIT.
> >>> If it's in insn_array just emit BTI unconditionally.
> >>> No need to do this filtering.
> >>>
> >>
> >> Hmm, that is what the v1 version does. Please take a look. If it’s okay,
> >> I’ll resend a rebased version.
> >>
> >> v1: https://lore.kernel.org/bpf/20251127140318.3944249-1-xukuohai@huaweicloud.com/
> >
> > I don't think you need bitmap and bpf_prog_collect_indirect_targets().
> > Just look up each insn in the insn_array one at a time.
> > It's slower, but array is sorted, so binary search should work.
>
> No, an insn_array is not always sorted, as its ordering depends on how
> it is initialized.
>
> For example, with the following change to the selftest:
>
> --- a/tools/testing/selftests/bpf/prog_tests/bpf_insn_array.c
> +++ b/tools/testing/selftests/bpf/prog_tests/bpf_insn_array.c
> @@ -75,7 +75,7 @@ static void check_one_to_one_mapping(void)
> BPF_MOV64_IMM(BPF_REG_0, 0),
> BPF_EXIT_INSN(),
> };
> - __u32 map_in[] = {0, 1, 2, 3, 4, 5};
> + __u32 map_in[] = {0, 3, 1, 2, 4, 5};
> __u32 map_out[] = {0, 1, 2, 3, 4, 5};
>
> __check_success(insns, ARRAY_SIZE(insns), map_in, map_out);
>
> the selftest will create an unsorted map, as shown below:
>
> # bpftool m d i 74
> key: 00 00 00 00 value: 00 00 00 00 00 00 00 00 24 00 00 00 00 00 00 00
> key: 01 00 00 00 value: 03 00 00 00 03 00 00 00 30 00 00 00 00 00 00 00
> key: 02 00 00 00 value: 01 00 00 00 01 00 00 00 28 00 00 00 00 00 00 00
> key: 03 00 00 00 value: 02 00 00 00 02 00 00 00 2c 00 00 00 00 00 00 00
> key: 04 00 00 00 value: 04 00 00 00 04 00 00 00 34 00 00 00 00 00 00 00
> key: 05 00 00 00 value: 05 00 00 00 05 00 00 00 38 00 00 00 00 00 00 00
> Found 6 elements
Yes, it is not always sorted (jump tables aren't guaranteed to be
sorted or have unique values).
To get rid of bpf_prog_collect_indirect_targets() in internal API,
this is possible to just implement this inside arm JIT. If later it is
needed in more cases, it can be generalized.
Also, how bad is this to generate BTI instructions not only for jump
targets (say, for all instructions in the program)? If this is ok-ish
(this is a really rare condition now), then `bool is_jump_table` might
be dropped for now. (I will add similar code when add static keys and
indirect calls such that they aren't counted for BTI.)
Powered by blists - more mailing lists