From: Eduard Zingerman <eddyz87@gmail.com>
To: Anton Protopopov <a.s.protopopov@gmail.com>
Cc: bpf@vger.kernel.org, Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
Anton Protopopov <aspsk@isovalent.com>,
Daniel Borkmann <daniel@iogearbox.net>,
Quentin Monnet <qmo@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>
Subject: Re: [PATCH v1 bpf-next 08/11] bpf, x86: add support for indirect jumps
Date: Thu, 28 Aug 2025 09:30:40 -0700 [thread overview]
Message-ID: <08cb366465da990279460c1d56b2fb4492c45cf5.camel@gmail.com> (raw)
In-Reply-To: <aLAoUK22+PpuAbhy@mail.gmail.com>
On Thu, 2025-08-28 at 09:58 +0000, Anton Protopopov wrote:
[...]
> > > @@ -16943,7 +17016,8 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn)
> > > }
> > > dst_reg->type = PTR_TO_MAP_VALUE;
> > > dst_reg->off = aux->map_off;
> > > - WARN_ON_ONCE(map->max_entries != 1);
> > > + WARN_ON_ONCE(map->map_type != BPF_MAP_TYPE_INSN_ARRAY &&
> > > + map->max_entries != 1);
> >
> > Q: when is this necessary?
>
> For all maps except INSN_ARRAY only (map->max_entries == 1) is
> allowed. This change adds an exception for INSN_ARRAY.
I see, thank you for explaining.
[...]
> > > +static int cmp_ptr_to_u32(const void *a, const void *b)
> > > +{
> > > + return *(u32 *)a - *(u32 *)b;
> > > +}
> >
> > This will overflow for e.g. `0 - 8`.
>
> Why? 0U - 8U = 0xfffffff8U (it's not an UB because values are
> unsigned). Then it's cast to int on return which is -8.
Uh-oh. Ok, looks like this works.
[...]
> > > +static int jt_from_subprog(struct bpf_verifier_env *env,
> > > + int subprog_start,
> > > + int subprog_end,
> > > + struct jt *jt)
> > > +{
> > > + struct bpf_map *map;
> > > + struct jt jt_cur;
> > > + u32 *off;
> > > + int err;
> > > + int i;
> > > +
> > > + jt->off = NULL;
> > > + jt->off_cnt = 0;
> > > +
> > > + for (i = 0; i < env->insn_array_map_cnt; i++) {
> > > + /*
> > > + * TODO (when needed): collect only jump tables, not static keys
> > > + * or maps for indirect calls
> > > + */
> > > + map = env->insn_array_maps[i];
> > > +
> > > + err = jt_from_map(map, &jt_cur);
> > > + if (err) {
> > > + kvfree(jt->off);
> > > + return err;
> > > + }
> > > +
> > > + /*
> > > + * This is enough to check one element. The full table is
> > > + * checked to fit inside the subprog later in create_jt()
> > > + */
> > > + if (jt_cur.off[0] >= subprog_start && jt_cur.off[0] < subprog_end) {
> >
> > This won't always catch cases when insn array references offsets from
> > several subprograms. Also is one subprogram limitation really necessary?
>
> This was intentional. If you have a switch or a jump table
> defined in C, then corresponding jump tables belong to one function.
> Also, what if you have a jt which can jump from function f() to g(),
> but then g() is livepatched by another function?
Ok, yes, for gotox such limitation makes sense.
[...]
> > > @@ -18679,6 +19000,10 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,
> > > return regs_exact(rold, rcur, idmap) && rold->frameno == rcur->frameno;
> > > case PTR_TO_ARENA:
> > > return true;
> > > + case PTR_TO_INSN:
> > > + /* cur ⊆ old */
> >
> > Out of curiosity: are unicode symbols allowed in kernel source code?
>
> I've replaced with words, don't see other examples of unicode around
> (but also can't find "don't use unicode" in coding-style.rst).
Personally, I like unicode symbols :)
> > > + return (rcur->min_index >= rold->min_index &&
> > > + rcur->max_index <= rold->max_index);
> > > default:
> > > return regs_exact(rold, rcur, idmap);
> > > }
> > > @@ -19825,6 +20150,67 @@ static int process_bpf_exit_full(struct bpf_verifier_env *env,
> > > return PROCESS_BPF_EXIT;
> > > }
> > >
> > > +/* gotox *dst_reg */
> > > +static int check_indirect_jump(struct bpf_verifier_env *env, struct bpf_insn *insn)
> > > +{
[...]
> > > + if (dst_reg->max_index >= map->max_entries) {
> > > + verbose(env, "BPF_JA|BPF_X R%d is out of map boundaries: index=%u, max_index=%u\n",
> > > + insn->dst_reg, dst_reg->max_index, map->max_entries-1);
> > > + return -EINVAL;
> > > + }
> > > +
> > > + xoff = kvcalloc(dst_reg->max_index - dst_reg->min_index + 1, sizeof(u32), GFP_KERNEL_ACCOUNT);
> > > + if (!xoff)
> > > + return -ENOMEM;
> > > +
> > > + n = copy_insn_array_uniq(map, dst_reg->min_index, dst_reg->max_index, xoff);
> >
> > Nit: I'd avoid this allocation and do a loop for(i = min_index; i <= max_index; i++),
> > with map->ops->map_lookup_elem(map, &i) (or a wrapper) inside it.
>
> But it should be a list of unique values, how would you sort it
> without allocating memory (in a reqsonable time)?
Because of the push_state() loop below, right?
Makes sense.
> > > + if (n < 0) {
> > > + err = n;
> > > + goto free_off;
> > > + }
> > > + if (n == 0) {
> > > + verbose(env, "register R%d doesn't point to any offset in map id=%d\n",
> > > + insn->dst_reg, map->id);
> > > + err = -EINVAL;
> > > + goto free_off;
> > > + }
> > > +
> > > + for (i = 0; i < n - 1; i++) {
> > > + other_branch = push_stack(env, xoff[i], env->insn_idx, false);
> > > + if (IS_ERR(other_branch)) {
> > > + err = PTR_ERR(other_branch);
> > > + goto free_off;
> > > + }
> > > + }
> > > + env->insn_idx = xoff[n-1];
> > > +
> > > +free_off:
> > > + kvfree(xoff);
> > > + return err;
> > > +}
> > > +
[...]
next prev parent reply other threads:[~2025-08-28 16:30 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-16 18:06 [PATCH v1 bpf-next 00/11] BPF indirect jumps Anton Protopopov
2025-08-16 18:06 ` [PATCH v1 bpf-next 01/11] bpf: fix the return value of push_stack Anton Protopopov
2025-08-25 18:12 ` Eduard Zingerman
2025-08-26 15:00 ` Anton Protopopov
2025-08-16 18:06 ` [PATCH v1 bpf-next 02/11] bpf: save the start of functions in bpf_prog_aux Anton Protopopov
2025-08-16 18:06 ` [PATCH v1 bpf-next 03/11] bpf, x86: add new map type: instructions array Anton Protopopov
2025-08-25 21:05 ` Eduard Zingerman
2025-08-26 15:52 ` Anton Protopopov
2025-08-26 16:04 ` Eduard Zingerman
2025-08-16 18:06 ` [PATCH v1 bpf-next 04/11] selftests/bpf: add selftests for new insn_array map Anton Protopopov
2025-08-16 18:06 ` [PATCH v1 bpf-next 05/11] bpf: support instructions arrays with constants blinding Anton Protopopov
2025-08-17 5:50 ` kernel test robot
2025-08-18 8:24 ` Anton Protopopov
2025-08-25 23:29 ` Eduard Zingerman
2025-08-27 9:20 ` Anton Protopopov
2025-08-16 18:06 ` [PATCH v1 bpf-next 06/11] selftests/bpf: test instructions arrays with blinding Anton Protopopov
2025-08-16 18:06 ` [PATCH v1 bpf-next 07/11] bpf, x86: allow indirect jumps to r8...r15 Anton Protopopov
2025-08-16 18:06 ` [PATCH v1 bpf-next 08/11] bpf, x86: add support for indirect jumps Anton Protopopov
2025-08-18 7:57 ` Dan Carpenter
2025-08-18 8:22 ` Anton Protopopov
2025-08-25 23:15 ` Eduard Zingerman
2025-08-27 15:34 ` Anton Protopopov
2025-08-27 18:58 ` Eduard Zingerman
2025-08-28 9:58 ` Anton Protopopov
2025-08-28 14:15 ` Anton Protopopov
2025-08-28 16:10 ` Eduard Zingerman
2025-08-28 16:30 ` Eduard Zingerman [this message]
2025-08-16 18:06 ` [PATCH v1 bpf-next 09/11] bpf: disasm: add support for BPF_JMP|BPF_JA|BPF_X Anton Protopopov
2025-08-16 18:06 ` [PATCH v1 bpf-next 10/11] libbpf: support llvm-generated indirect jumps Anton Protopopov
2025-08-21 0:20 ` Andrii Nakryiko
2025-08-21 13:05 ` Anton Protopopov
2025-08-21 18:14 ` Andrii Nakryiko
2025-08-21 19:12 ` Anton Protopopov
2025-08-26 0:06 ` Eduard Zingerman
2025-08-26 16:15 ` Anton Protopopov
2025-08-26 16:51 ` Anton Protopopov
2025-08-26 16:47 ` Eduard Zingerman
2025-08-16 18:06 ` [PATCH v1 bpf-next 11/11] selftests/bpf: add selftests for " Anton Protopopov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=08cb366465da990279460c1d56b2fb4492c45cf5.camel@gmail.com \
--to=eddyz87@gmail.com \
--cc=a.s.protopopov@gmail.com \
--cc=andrii@kernel.org \
--cc=aspsk@isovalent.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=qmo@kernel.org \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).