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 05/15] selftests/bpf: add selftests for new insn_array map
Date: Fri, 3 Oct 2025 07:46:38 +0000 [thread overview]
Message-ID: <aN9/XoodAYHN5Lm7@mail.gmail.com> (raw)
In-Reply-To: <b7ed4bb22cd73006f761888305ed7ed2f70a5071.camel@gmail.com>
On 25/10/02 06:16PM, Eduard Zingerman wrote:
> On Tue, 2025-09-30 at 12:51 +0000, Anton Protopopov wrote:
>
> Overall lgtm, some code duplication worth removing, I think.
>
> [...]
>
> > +/*
> > + * Try to load a program with a map which points to outside of the program
> > + */
> > +static void check_out_of_bounds_index(void)
> > +{
> > + struct bpf_insn insns[] = {
> > + BPF_MOV64_IMM(BPF_REG_0, 4),
> > + BPF_MOV64_IMM(BPF_REG_0, 3),
> > + BPF_MOV64_IMM(BPF_REG_0, 2),
> > + BPF_MOV64_IMM(BPF_REG_0, 1),
> > + BPF_MOV64_IMM(BPF_REG_0, 0),
> > + BPF_EXIT_INSN(),
> > + };
> > + int prog_fd, map_fd;
> > + struct bpf_insn_array_value val = {};
> > + int key;
> > +
> > + map_fd = map_create(BPF_MAP_TYPE_INSN_ARRAY, 1);
> > + if (!ASSERT_GE(map_fd, 0, "map_create"))
> > + return;
> > +
> > + key = 0;
> > + val.xlated_off = ARRAY_SIZE(insns); /* too big */
> > + if (!ASSERT_EQ(bpf_map_update_elem(map_fd, &key, &val, 0), 0, "bpf_map_update_elem"))
> > + goto cleanup;
> > +
> > + if (!ASSERT_EQ(bpf_map_freeze(map_fd), 0, "bpf_map_freeze"))
> > + goto cleanup;
> > +
> > + errno = 0;
>
> Nit: errno is not used in the check below, hence there is no need to reset it.
> (here and in other tests below)
Ok, will do.
> > + prog_fd = prog_load(insns, ARRAY_SIZE(insns), &map_fd, 1);
> > + if (!ASSERT_EQ(prog_fd, -EINVAL, "program should have been rejected (prog_fd != -EINVAL)")) {
> > + close(prog_fd);
> > + goto cleanup;
> > + }
> > +
> > +cleanup:
> > + close(map_fd);
> > +}
>
> [...]
>
> > +/*
> > + * Load a program with two patches (get jiffies, for simplicity). Add an
> > + * insn_array map pointing to every instruction. Check how it was changed
> > + * after the program load.
> > + */
> > +static void check_simple(void)
> > +{
> > + struct bpf_insn insns[] = {
> > + BPF_MOV64_IMM(BPF_REG_0, 2),
> > + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
> > + BPF_MOV64_IMM(BPF_REG_0, 1),
> > + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_jiffies64),
> > + BPF_MOV64_IMM(BPF_REG_0, 0),
> > + BPF_EXIT_INSN(),
> > + };
> > + int prog_fd = -1, map_fd;
> > + __u32 map_in[] = {0, 1, 2, 3, 4, 5};
> > + __u32 map_out[] = {0, 1, 4, 5, 8, 9};
> > + struct bpf_insn_array_value val = {};
> > + int i;
> > +
> > + map_fd = map_create(BPF_MAP_TYPE_INSN_ARRAY, ARRAY_SIZE(insns));
> > + if (!ASSERT_GE(map_fd, 0, "map_create"))
> > + return;
> > +
> > + for (i = 0; i < ARRAY_SIZE(insns); i++) {
> > + val.xlated_off = map_in[i];
> > + if (!ASSERT_EQ(bpf_map_update_elem(map_fd, &i, &val, 0), 0,
> > + "bpf_map_update_elem"))
> > + goto cleanup;
> > + }
> > +
> > + if (!ASSERT_EQ(bpf_map_freeze(map_fd), 0, "bpf_map_freeze"))
> > + goto cleanup;
> > +
> > + prog_fd = prog_load(insns, ARRAY_SIZE(insns), &map_fd, 1);
> > + if (!ASSERT_GE(prog_fd, 0, "bpf(BPF_PROG_LOAD)"))
> > + goto cleanup;
> > +
> > + for (i = 0; i < ARRAY_SIZE(insns); i++) {
> > + if (!ASSERT_EQ(bpf_map_lookup_elem(map_fd, &i, &val), 0, "bpf_map_lookup_elem"))
> > + goto cleanup;
> > +
> > + ASSERT_EQ(val.xlated_off, map_out[i], "val should be equal map_out[i]");
>
> Nit: maybe print `i`, `xlated_off` and `map_out[i]` here?
+1
> If this test fails, debugging it with -vvv would be inconvenient,
> as there is no way to see xlated program. Maybe extend load_prog()
> to check debug level and add capability to print xlated?
> See __xlated annotation implementation in selftests.
Ok, nice, will do.
Just in case, typically, when I write selftests I add smth like
if (getenv("HANG") && *(getenv("HANG")))
for (;;)
pause();
before destroying skeleton, so I can examine what was loaded, if needed.
>
> > + }
> > +
> > +cleanup:
> > + close(prog_fd);
> > + close(map_fd);
> > +}
> > +
> > +/*
> > + * Verifier can delete code in two cases: nops & dead code. From insn
> > + * array's point of view, the two cases are the same, so test using
> > + * the simplest method: by loading some nops
> > + */
> > +static void check_deletions(void)
> > +{
> > + struct bpf_insn insns[] = {
> > + BPF_MOV64_IMM(BPF_REG_0, 2),
> > + BPF_JMP_IMM(BPF_JA, 0, 0, 0), /* nop */
> > + BPF_MOV64_IMM(BPF_REG_0, 1),
> > + BPF_JMP_IMM(BPF_JA, 0, 0, 0), /* nop */
> > + BPF_MOV64_IMM(BPF_REG_0, 0),
> > + BPF_EXIT_INSN(),
> > + };
>
> Success test cases follow identical pattern, ultimately having 3 input
> parameters:
> - program
> - map_in
> - map_out
>
> Would it make sense to write a generic utility function accepting
> exactly these three params and hiding the boilerplate?
Will do.
Are you ok with the contexts of tests? Any more test cases, maybe?
> > + int prog_fd = -1, map_fd;
> > + __u32 map_in[] = {0, 1, 2, 3, 4, 5};
> > + __u32 map_out[] = {0, -1, 1, -1, 2, 3};
> > + struct bpf_insn_array_value val = {};
> > + int i;
> > +
> > + map_fd = map_create(BPF_MAP_TYPE_INSN_ARRAY, ARRAY_SIZE(insns));
> > + if (!ASSERT_GE(map_fd, 0, "map_create"))
> > + return;
> > +
> > + for (i = 0; i < ARRAY_SIZE(insns); i++) {
> > + val.xlated_off = map_in[i];
> > + if (!ASSERT_EQ(bpf_map_update_elem(map_fd, &i, &val, 0), 0,
> > + "bpf_map_update_elem"))
> > + goto cleanup;
> > + }
> > +
> > + if (!ASSERT_EQ(bpf_map_freeze(map_fd), 0, "bpf_map_freeze"))
> > + goto cleanup;
> > +
> > + prog_fd = prog_load(insns, ARRAY_SIZE(insns), &map_fd, 1);
> > + if (!ASSERT_GE(prog_fd, 0, "bpf(BPF_PROG_LOAD)"))
> > + goto cleanup;
> > +
> > + for (i = 0; i < ARRAY_SIZE(insns); i++) {
> > + if (!ASSERT_EQ(bpf_map_lookup_elem(map_fd, &i, &val), 0, "bpf_map_lookup_elem"))
> > + goto cleanup;
> > +
> > + ASSERT_EQ(val.xlated_off, map_out[i], "val should be equal map_out[i]");
> > + }
> > +
> > +cleanup:
> > + close(prog_fd);
> > + close(map_fd);
> > +}
>
> [...]
next prev parent reply other threads:[~2025-10-03 7:40 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 [this message]
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
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=aN9/XoodAYHN5Lm7@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox