From: Anton Protopopov <a.s.protopopov@gmail.com>
To: Eduard Zingerman <eddyz87@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 v5 bpf-next 10/15] bpf, x86: add support for indirect jumps
Date: Fri, 3 Oct 2025 07:04:33 +0000 [thread overview]
Message-ID: <aN91gcBNptvX6wQJ@mail.gmail.com> (raw)
In-Reply-To: <f25e1970100d4d39572839e86bbed0fa819d7a05.camel@gmail.com>
On 25/10/02 12:52PM, Eduard Zingerman wrote:
> On Thu, 2025-10-02 at 09:27 +0000, Anton Protopopov wrote:
>
> [...]
>
> > > > @@ -14685,6 +14723,11 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
> > > > dst);
> > > > return -EACCES;
> > > > }
> > > > + if (ptr_to_insn_array) {
> > > > + verbose(env, "R%d subtraction from pointer to instruction prohibited\n",
> > > > + dst);
> > > > + return -EACCES;
> > > > + }
> > >
> > > Is anything going to break if subtraction is allowed?
> > > The bounds are still maintained, so seem to be ok.
> >
> > Ok, I just haven't seen any reason to add because such code
> > is not generated on practice. I will add in the next version.
>
> Just less code and less tests if there is no special case.
>
> [...]
>
> > > > @@ -17786,6 +17830,210 @@ static struct bpf_iarray *iarray_realloc(struct bpf_iarray *old, size_t n_elem)
> > > > return new;
> > > > }
> > > >
> > > > +#define SET_HIGH(STATE, LAST) STATE = (STATE & 0xffffU) | ((LAST) << 16)
> > > > +#define GET_HIGH(STATE) ((u16)((STATE) >> 16))
> > > > +
> > > > +static int push_gotox_edge(int t, struct bpf_verifier_env *env, struct bpf_iarray *jt)
> > > > +{
> > > > + int *insn_stack = env->cfg.insn_stack;
> > > > + int *insn_state = env->cfg.insn_state;
> > > > + u16 prev;
> > > > + int w;
> > > > +
> > >
> > > push_insn() checks if `t` is in range [0, env->prog->len],
> > > is the same check needed here?
> >
> > You wanted to say `w`? (I think `t` is guaranteed to be a valid one.)
> > In cas of push_gotox_edge `w` is taken from a jump table which is
> > guaranteed to have only correct instructions.
>
> Yes, I meant `w`, sorry.
> So, the invalid offsets would be rejected at map construction time?
> I'd put a check here just to be consistent with push_insn, but skip it
> if you think it's not really necessary.
I will add a check for consistency.
> [...]
>
> > > > +static struct bpf_iarray *
> > > > +create_jt(int t, struct bpf_verifier_env *env, int fd)
> > > > +{
> > > > + static struct bpf_subprog_info *subprog;
> > > > + int subprog_idx, subprog_start, subprog_end;
> > > > + struct bpf_iarray *jt;
> > > > + int i;
> > > > +
> > > > + if (env->subprog_cnt == 0)
> > > > + return ERR_PTR(-EFAULT);
> > > > +
> > > > + subprog_idx = bpf_find_containing_subprog_idx(env, t);
> > > > + if (subprog_idx < 0) {
> > > > + verbose(env, "can't find subprog containing instruction %d\n", t);
> > > > + return ERR_PTR(-EFAULT);
> > > > + }
> > >
> > > Nit: There is now verifier_bug() for such cases.
> > > Also, it seems that all bpf_find_containing_subprog() users
> > > assume that the function can't fail.
> > > Like in this case, there is already access `jt = env->insn_aux_data[t].jt;`
> > > in visit_gotox_insn() that will be an error if `t` is bogus.
> >
> > Could you please explain this once again? The error from
> > bpf_find_containing_subprog* funcs is checked in this code.
>
> Point being that there is no need to check if bpf_find_containing_subprog()
> returns error:
> - If we guarantee that `t` is within program bounds it can't fail
> (which I think we do). In other places where this function is
> called it's return value is not checked for errors.
> - In case if we don't guarantee that `t` is within program bounds,
> then just before call to create_jt() there is an access `jt =
> env->insn_aux_data[t].jt;` which would read from some undefined
> location. So, it's already too late to check here.
Ah, ok, I see, thanks.
> [...]
>
> > > /* "conditional jump with N edges" */
> > > static int visit_gotox_insn(int t, struct bpf_verifier_env *env, int fd)
> > > {
> > > int *insn_stack = env->cfg.insn_stack;
> > > int *insn_state = env->cfg.insn_state;
> > > bool keep_exploring = false;
> > > struct bpf_iarray *jt;
> > > int i, w;
> > >
> > > jt = env->insn_aux_data[t].jt;
> > > if (!jt) {
> > > jt = create_jt(t, env, fd);
> > > if (IS_ERR(ptr: jt))
> >
> > (BTW, out of curiosity, do these "ptr: jt" type hints and alike
> > come from your environment? What is it, if this is not a secret?)
>
> Oh... sorry about that, I'll suppress those moving forward.
> It's a copy-paste from tmux window.
> In tmux there is a terminal running emacs in console mode.
> Emacs uses eglot mode to integrate with clangd language server.
> Eglot displays these parameter name hints, provided by clangd.
> The whole thing ends up in copy-paste because in console mode all of
> this is just text. Had I run emacs in gui mode, it wouldn't be
> copy-pasted. But that's a remote machine, so here were are.
Thanks for the explanations. (Also, no problem if this appears.)
> [...]
>
> > > > +static int check_indirect_jump(struct bpf_verifier_env *env, struct bpf_insn *insn)
> > > > +{
>
> [...]
>
> > > > + n = copy_insn_array_uniq(map, min_index, max_index, env->gotox_tmp_buf);
> > >
> > > I still think this might be a problem for big jump tables if gotox is
> > > in a loop body. Can you check a perf report for such scenario?
> > > E.g. 256 entries in the jump table, some duplicates, dispatched in a loop.
> >
> > Well, for "big jump tables" I want to follow up with some changes in any case,
> > just didn't get there with this patchset yet. Namely, the `insn_inxed \mapto
> > jump table map` must be optimized, otherwise the JIT spends too much time on
> > this. So, this would require bin/serach or better a hash to optimize this. In
> > the latter case, this piece might also be optimized by caching a lookup
> > (by the "map[start,end]" key).
>
> Ok, if follow-up is planned, we can stick with a simple implementation
> for this patch.
>
> [...]
next prev parent reply other threads:[~2025-10-03 6:58 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-30 12:50 [PATCH v5 bpf-next 00/15] BPF indirect jumps Anton Protopopov
2025-09-30 12:50 ` [PATCH v5 bpf-next 01/15] bpf: fix the return value of push_stack Anton Protopopov
2025-09-30 12:50 ` [PATCH v5 bpf-next 02/15] bpf: save the start of functions in bpf_prog_aux Anton Protopopov
2025-10-01 21:53 ` Eduard Zingerman
2025-09-30 12:50 ` [PATCH v5 bpf-next 03/15] bpf: generalize and export map_get_next_key for arrays Anton Protopopov
2025-10-01 21:56 ` Eduard Zingerman
2025-09-30 12:51 ` [PATCH v5 bpf-next 04/15] bpf, x86: add new map type: instructions array Anton Protopopov
2025-10-03 0:50 ` Eduard Zingerman
2025-10-03 7:39 ` Anton Protopopov
2025-10-03 8:48 ` Eduard Zingerman
2025-10-03 9:13 ` Anton Protopopov
2025-10-03 17:22 ` Eduard Zingerman
2025-09-30 12:51 ` [PATCH v5 bpf-next 05/15] selftests/bpf: add selftests for new insn_array map Anton Protopopov
2025-10-03 1:16 ` Eduard Zingerman
2025-10-03 7:46 ` Anton Protopopov
2025-10-03 8:15 ` Eduard Zingerman
2025-09-30 12:51 ` [PATCH v5 bpf-next 06/15] bpf: support instructions arrays with constants blinding Anton Protopopov
2025-10-03 17:38 ` Eduard Zingerman
2025-09-30 12:51 ` [PATCH v5 bpf-next 07/15] selftests/bpf: test instructions arrays with blinding Anton Protopopov
2025-10-03 9:00 ` Eduard Zingerman
2025-09-30 12:51 ` [PATCH v5 bpf-next 08/15] bpf, x86: allow indirect jumps to r8...r15 Anton Protopopov
2025-10-01 22:03 ` Eduard Zingerman
2025-09-30 12:51 ` [PATCH v5 bpf-next 09/15] bpf: make bpf_insn_successors to return a pointer Anton Protopopov
2025-10-01 22:39 ` Eduard Zingerman
2025-10-01 23:49 ` Alexei Starovoitov
2025-10-02 8:19 ` Anton Protopopov
2025-10-02 16:07 ` Alexei Starovoitov
2025-10-02 8:16 ` Anton Protopopov
2025-10-02 19:35 ` Eduard Zingerman
2025-09-30 12:51 ` [PATCH v5 bpf-next 10/15] bpf, x86: add support for indirect jumps Anton Protopopov
2025-10-02 0:15 ` Eduard Zingerman
2025-10-02 9:27 ` Anton Protopopov
2025-10-02 19:52 ` Eduard Zingerman
2025-10-03 7:04 ` Anton Protopopov [this message]
2025-09-30 12:51 ` [PATCH v5 bpf-next 11/15] bpf: disasm: add support for BPF_JMP|BPF_JA|BPF_X Anton Protopopov
2025-10-02 0:18 ` Eduard Zingerman
2025-10-02 7:49 ` Anton Protopopov
2025-09-30 12:51 ` [PATCH v5 bpf-next 12/15] libbpf: fix formatting of bpf_object__append_subprog_code Anton Protopopov
2025-09-30 12:51 ` [PATCH v5 bpf-next 13/15] libbpf: support llvm-generated indirect jumps Anton Protopopov
2025-10-02 21:01 ` Eduard Zingerman
2025-10-03 7:19 ` Anton Protopopov
2025-10-15 15:32 ` Yonghong Song
2025-10-15 17:35 ` Anton Protopopov
2025-09-30 12:51 ` [PATCH v5 bpf-next 14/15] bpftool: Recognize insn_array map type Anton Protopopov
2025-09-30 12:51 ` [PATCH v5 bpf-next 15/15] selftests/bpf: add selftests for indirect jumps Anton Protopopov
2025-10-02 21:07 ` Eduard Zingerman
2025-10-03 7:22 ` Anton Protopopov
2025-10-03 7:29 ` Eduard Zingerman
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=aN91gcBNptvX6wQJ@mail.gmail.com \
--to=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=eddyz87@gmail.com \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.