* [PATCH bpf v3 0/2] bpf: reject negative CO-RE accessor indices
@ 2026-04-04 16:12 Weiming Shi
2026-04-04 16:12 ` [PATCH bpf v3 1/2] bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec() Weiming Shi
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Weiming Shi @ 2026-04-04 16:12 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi
Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf,
Xiang Mei, Weiming Shi
bpf_core_parse_spec() parses CO-RE accessor strings with sscanf("%d"),
which accepts negative values. The downstream bounds checks only test
the upper bound, so a negative index like -1 slips through, gets cast
to u32 0xffffffff in btf_member_bit_offset(), and crashes the kernel.
To clarify the kernel-side concern from v2 review:
tools/lib/bpf/relo_core.c is shared code -- the kernel compiles it
directly via kernel/bpf/relo_core.c (#include). So the fix does
apply in the kernel's BPF_PROG_LOAD -> check_core_relo() ->
bpf_core_apply() -> bpf_core_parse_spec() path.
v3: added selftest (patch 2/2)
v2: fix typo Signed-off-by tag (missing leading 'S')
Weiming Shi (2):
bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec()
selftests/bpf: add test for negative CO-RE accessor index rejection
tools/lib/bpf/relo_core.c | 2 +
.../selftests/bpf/prog_tests/core_reloc_raw.c | 94 +++++++++++++++++++
2 files changed, 96 insertions(+)
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH bpf v3 1/2] bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec() 2026-04-04 16:12 [PATCH bpf v3 0/2] bpf: reject negative CO-RE accessor indices Weiming Shi @ 2026-04-04 16:12 ` Weiming Shi 2026-04-04 18:07 ` Emil Tsalapatis 2026-04-06 15:01 ` Paul Chaignon 2026-04-04 16:12 ` [PATCH bpf v3 2/2] selftests/bpf: add test for negative CO-RE accessor index rejection Weiming Shi ` (2 subsequent siblings) 3 siblings, 2 replies; 9+ messages in thread From: Weiming Shi @ 2026-04-04 16:12 UTC (permalink / raw) To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf, Xiang Mei, Weiming Shi CO-RE accessor strings are colon-separated indices that describe a path from a root BTF type to a target field, e.g. "0:1:2" walks through nested struct members. bpf_core_parse_spec() parses each component with sscanf("%d"), so negative values like -1 are silently accepted. The subsequent bounds checks (access_idx >= btf_vlen(t)) only guard the upper bound and always pass for negative values because C integer promotion converts the __u16 btf_vlen result to int, making the comparison (int)(-1) >= (int)(N) false for any positive N. When -1 reaches btf_member_bit_offset() it gets cast to u32 0xffffffff, producing an out-of-bounds read far past the members array. A crafted BPF program with a negative CO-RE accessor on any struct that exists in vmlinux BTF (e.g. task_struct) crashes the kernel deterministically during BPF_PROG_LOAD on any system with CONFIG_DEBUG_INFO_BTF=y (default on major distributions). The bug is reachable with CAP_BPF: BUG: unable to handle page fault for address: ffffed11818b6626 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page Oops: Oops: 0000 [#1] SMP KASAN NOPTI CPU: 0 UID: 0 PID: 85 Comm: poc Not tainted 7.0.0-rc6 #18 PREEMPT(full) RIP: 0010:bpf_core_parse_spec (tools/lib/bpf/relo_core.c:354) RAX: 00000000ffffffff Call Trace: <TASK> bpf_core_calc_relo_insn (tools/lib/bpf/relo_core.c:1321) bpf_core_apply (kernel/bpf/btf.c:9507) check_core_relo (kernel/bpf/verifier.c:19475) bpf_check (kernel/bpf/verifier.c:26031) bpf_prog_load (kernel/bpf/syscall.c:3089) __sys_bpf (kernel/bpf/syscall.c:6228) </TASK> CO-RE accessor indices are inherently non-negative (struct member index, array element index, or enumerator index), so reject them immediately after parsing. Fixes: ddc7c3042614 ("libbpf: implement BPF CO-RE offset relocation algorithm") Reported-by: Xiang Mei <xmei5@asu.edu> Signed-off-by: Weiming Shi <bestswngs@gmail.com> --- v3: added selftest v2: fix typo Signed-off-by tag (missing leading 'S') tools/lib/bpf/relo_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/lib/bpf/relo_core.c b/tools/lib/bpf/relo_core.c index 6eea5edba58a..0ccc8f548cba 100644 --- a/tools/lib/bpf/relo_core.c +++ b/tools/lib/bpf/relo_core.c @@ -292,6 +292,8 @@ int bpf_core_parse_spec(const char *prog_name, const struct btf *btf, ++spec_str; if (sscanf(spec_str, "%d%n", &access_idx, &parsed_len) != 1) return -EINVAL; + if (access_idx < 0) + return -EINVAL; if (spec->raw_len == BPF_CORE_SPEC_MAX_LEN) return -E2BIG; spec_str += parsed_len; -- 2.43.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH bpf v3 1/2] bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec() 2026-04-04 16:12 ` [PATCH bpf v3 1/2] bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec() Weiming Shi @ 2026-04-04 18:07 ` Emil Tsalapatis 2026-04-06 15:01 ` Paul Chaignon 1 sibling, 0 replies; 9+ messages in thread From: Emil Tsalapatis @ 2026-04-04 18:07 UTC (permalink / raw) To: Weiming Shi, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf, Xiang Mei On Sat Apr 4, 2026 at 12:12 PM EDT, Weiming Shi wrote: > CO-RE accessor strings are colon-separated indices that describe a path > from a root BTF type to a target field, e.g. "0:1:2" walks through > nested struct members. bpf_core_parse_spec() parses each component with > sscanf("%d"), so negative values like -1 are silently accepted. The > subsequent bounds checks (access_idx >= btf_vlen(t)) only guard the > upper bound and always pass for negative values because C integer > promotion converts the __u16 btf_vlen result to int, making the > comparison (int)(-1) >= (int)(N) false for any positive N. > > When -1 reaches btf_member_bit_offset() it gets cast to u32 0xffffffff, > producing an out-of-bounds read far past the members array. A crafted > BPF program with a negative CO-RE accessor on any struct that exists in > vmlinux BTF (e.g. task_struct) crashes the kernel deterministically > during BPF_PROG_LOAD on any system with CONFIG_DEBUG_INFO_BTF=y > (default on major distributions). The bug is reachable with CAP_BPF: > > BUG: unable to handle page fault for address: ffffed11818b6626 > #PF: supervisor read access in kernel mode > #PF: error_code(0x0000) - not-present page > Oops: Oops: 0000 [#1] SMP KASAN NOPTI > CPU: 0 UID: 0 PID: 85 Comm: poc Not tainted 7.0.0-rc6 #18 PREEMPT(full) > RIP: 0010:bpf_core_parse_spec (tools/lib/bpf/relo_core.c:354) > RAX: 00000000ffffffff > Call Trace: > <TASK> > bpf_core_calc_relo_insn (tools/lib/bpf/relo_core.c:1321) > bpf_core_apply (kernel/bpf/btf.c:9507) > check_core_relo (kernel/bpf/verifier.c:19475) > bpf_check (kernel/bpf/verifier.c:26031) > bpf_prog_load (kernel/bpf/syscall.c:3089) > __sys_bpf (kernel/bpf/syscall.c:6228) > </TASK> > > CO-RE accessor indices are inherently non-negative (struct member index, > array element index, or enumerator index), so reject them immediately > after parsing. > > Fixes: ddc7c3042614 ("libbpf: implement BPF CO-RE offset relocation algorithm") > Reported-by: Xiang Mei <xmei5@asu.edu> > Signed-off-by: Weiming Shi <bestswngs@gmail.com> Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com> > --- > v3: added selftest > v2: fix typo Signed-off-by tag (missing leading 'S') > > tools/lib/bpf/relo_core.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/tools/lib/bpf/relo_core.c b/tools/lib/bpf/relo_core.c > index 6eea5edba58a..0ccc8f548cba 100644 > --- a/tools/lib/bpf/relo_core.c > +++ b/tools/lib/bpf/relo_core.c > @@ -292,6 +292,8 @@ int bpf_core_parse_spec(const char *prog_name, const struct btf *btf, > ++spec_str; > if (sscanf(spec_str, "%d%n", &access_idx, &parsed_len) != 1) > return -EINVAL; > + if (access_idx < 0) > + return -EINVAL; > if (spec->raw_len == BPF_CORE_SPEC_MAX_LEN) > return -E2BIG; > spec_str += parsed_len; ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH bpf v3 1/2] bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec() 2026-04-04 16:12 ` [PATCH bpf v3 1/2] bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec() Weiming Shi 2026-04-04 18:07 ` Emil Tsalapatis @ 2026-04-06 15:01 ` Paul Chaignon 1 sibling, 0 replies; 9+ messages in thread From: Paul Chaignon @ 2026-04-06 15:01 UTC (permalink / raw) To: Weiming Shi Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf, Xiang Mei On Sun, Apr 05, 2026 at 12:12:20AM +0800, Weiming Shi wrote: > CO-RE accessor strings are colon-separated indices that describe a path > from a root BTF type to a target field, e.g. "0:1:2" walks through > nested struct members. bpf_core_parse_spec() parses each component with > sscanf("%d"), so negative values like -1 are silently accepted. The > subsequent bounds checks (access_idx >= btf_vlen(t)) only guard the > upper bound and always pass for negative values because C integer > promotion converts the __u16 btf_vlen result to int, making the > comparison (int)(-1) >= (int)(N) false for any positive N. > > When -1 reaches btf_member_bit_offset() it gets cast to u32 0xffffffff, > producing an out-of-bounds read far past the members array. A crafted > BPF program with a negative CO-RE accessor on any struct that exists in > vmlinux BTF (e.g. task_struct) crashes the kernel deterministically > during BPF_PROG_LOAD on any system with CONFIG_DEBUG_INFO_BTF=y > (default on major distributions). The bug is reachable with CAP_BPF: > > BUG: unable to handle page fault for address: ffffed11818b6626 > #PF: supervisor read access in kernel mode > #PF: error_code(0x0000) - not-present page > Oops: Oops: 0000 [#1] SMP KASAN NOPTI > CPU: 0 UID: 0 PID: 85 Comm: poc Not tainted 7.0.0-rc6 #18 PREEMPT(full) > RIP: 0010:bpf_core_parse_spec (tools/lib/bpf/relo_core.c:354) > RAX: 00000000ffffffff > Call Trace: > <TASK> > bpf_core_calc_relo_insn (tools/lib/bpf/relo_core.c:1321) > bpf_core_apply (kernel/bpf/btf.c:9507) > check_core_relo (kernel/bpf/verifier.c:19475) > bpf_check (kernel/bpf/verifier.c:26031) > bpf_prog_load (kernel/bpf/syscall.c:3089) > __sys_bpf (kernel/bpf/syscall.c:6228) > </TASK> > > CO-RE accessor indices are inherently non-negative (struct member index, > array element index, or enumerator index), so reject them immediately > after parsing. > > Fixes: ddc7c3042614 ("libbpf: implement BPF CO-RE offset relocation algorithm") > Reported-by: Xiang Mei <xmei5@asu.edu> > Signed-off-by: Weiming Shi <bestswngs@gmail.com> Acked-by: Paul Chaignon <paul.chaignon@gmail.com> > --- > v3: added selftest > v2: fix typo Signed-off-by tag (missing leading 'S') > > tools/lib/bpf/relo_core.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/tools/lib/bpf/relo_core.c b/tools/lib/bpf/relo_core.c > index 6eea5edba58a..0ccc8f548cba 100644 > --- a/tools/lib/bpf/relo_core.c > +++ b/tools/lib/bpf/relo_core.c > @@ -292,6 +292,8 @@ int bpf_core_parse_spec(const char *prog_name, const struct btf *btf, > ++spec_str; > if (sscanf(spec_str, "%d%n", &access_idx, &parsed_len) != 1) > return -EINVAL; > + if (access_idx < 0) > + return -EINVAL; > if (spec->raw_len == BPF_CORE_SPEC_MAX_LEN) > return -E2BIG; > spec_str += parsed_len; > -- > 2.43.0 > > ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH bpf v3 2/2] selftests/bpf: add test for negative CO-RE accessor index rejection 2026-04-04 16:12 [PATCH bpf v3 0/2] bpf: reject negative CO-RE accessor indices Weiming Shi 2026-04-04 16:12 ` [PATCH bpf v3 1/2] bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec() Weiming Shi @ 2026-04-04 16:12 ` Weiming Shi 2026-04-04 18:12 ` Emil Tsalapatis 2026-04-06 15:03 ` Paul Chaignon 2026-04-04 18:06 ` [PATCH bpf v3 0/2] bpf: reject negative CO-RE accessor indices Emil Tsalapatis 2026-04-07 15:30 ` patchwork-bot+netdevbpf 3 siblings, 2 replies; 9+ messages in thread From: Weiming Shi @ 2026-04-04 16:12 UTC (permalink / raw) To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf, Xiang Mei, Weiming Shi Add a selftest to verify that the kernel rejects BPF programs containing CO-RE relocations with negative accessor indices. The test constructs a minimal BTF blob with a struct type and a CO-RE relocation whose access string is "0:-1". Without the fix in the previous patch, this triggers an out-of-bounds read in bpf_core_parse_spec(); with the fix, the program load fails cleanly with -EINVAL. Signed-off-by: Weiming Shi <bestswngs@gmail.com> --- .../selftests/bpf/prog_tests/core_reloc_raw.c | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc_raw.c b/tools/testing/selftests/bpf/prog_tests/core_reloc_raw.c index a18d3680fb16..f7bf6c237d59 100644 --- a/tools/testing/selftests/bpf/prog_tests/core_reloc_raw.c +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc_raw.c @@ -118,8 +118,102 @@ static void test_bad_local_id(void) close(btf_fd); } +/* Check that verifier rejects BPF program containing CO-RE relocation + * with a negative accessor index (e.g. "0:-1"). + */ +static void test_negative_accessor(void) +{ + struct test_btf { + struct btf_header hdr; + __u32 types[18]; + char strings[20]; + } raw_btf = { + .hdr = { + .magic = BTF_MAGIC, + .version = BTF_VERSION, + .hdr_len = sizeof(struct btf_header), + .type_off = 0, + .type_len = sizeof(raw_btf.types), + .str_off = offsetof(struct test_btf, strings) - + offsetof(struct test_btf, types), + .str_len = sizeof(raw_btf.strings), + }, + .types = { + /* [1] int */ + BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), + /* [2] struct s { int x; } */ + BTF_STRUCT_ENC(5, 1, 4), + BTF_MEMBER_ENC(7, 1, 0), + /* [3] int (*)(int a) */ + BTF_FUNC_PROTO_ENC(1, 1), + BTF_FUNC_PROTO_ARG_ENC(13, 1), + /* [4] FUNC 'foo' */ + BTF_FUNC_ENC(9, 3), + }, + /* offsets: 0:NUL 1:"int" 5:"s" 7:"x" 9:"foo" 13:"a" 15:"0:-1" */ + .strings = "\0int\0s\0x\0foo\0a\0" "0:-1", + }; + __u32 log_level = 1 | 2 | 4; + LIBBPF_OPTS(bpf_btf_load_opts, opts, + .log_buf = log, + .log_size = sizeof(log), + .log_level = log_level, + ); + struct bpf_insn insns[] = { + BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), + BPF_EXIT_INSN(), + }; + struct bpf_func_info funcs[] = { + { .insn_off = 0, .type_id = 4 } + }; + struct bpf_core_relo relos[] = { + { + .insn_off = 0, + .type_id = 2, /* struct s */ + .access_str_off = 15, /* "0:-1" */ + .kind = BPF_CORE_FIELD_BYTE_OFFSET, + } + }; + union bpf_attr attr; + int prog_fd = -1; + int btf_fd = -1; + + btf_fd = bpf_btf_load(&raw_btf, sizeof(raw_btf), &opts); + if (!ASSERT_GE(btf_fd, 0, "btf_load")) + return; + + log[0] = 0; + memset(&attr, 0, sizeof(attr)); + attr.prog_btf_fd = btf_fd; + attr.prog_type = BPF_TRACE_RAW_TP; + attr.license = (__u64)"GPL"; + attr.insns = (__u64)&insns; + attr.insn_cnt = sizeof(insns) / sizeof(*insns); + attr.log_buf = (__u64)log; + attr.log_size = sizeof(log); + attr.log_level = log_level; + attr.func_info = (__u64)funcs; + attr.func_info_cnt = sizeof(funcs) / sizeof(*funcs); + attr.func_info_rec_size = sizeof(*funcs); + attr.core_relos = (__u64)relos; + attr.core_relo_cnt = sizeof(relos) / sizeof(*relos); + attr.core_relo_rec_size = sizeof(*relos); + prog_fd = sys_bpf_prog_load(&attr, sizeof(attr), 1); + if (prog_fd >= 0) { + PRINT_FAIL("sys_bpf_prog_load() expected to fail\n"); + goto out; + } + ASSERT_HAS_SUBSTR(log, "failed: -22", "prog_load_log"); + +out: + close(prog_fd); + close(btf_fd); +} + void test_core_reloc_raw(void) { if (test__start_subtest("bad_local_id")) test_bad_local_id(); + if (test__start_subtest("negative_accessor")) + test_negative_accessor(); } -- 2.43.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH bpf v3 2/2] selftests/bpf: add test for negative CO-RE accessor index rejection 2026-04-04 16:12 ` [PATCH bpf v3 2/2] selftests/bpf: add test for negative CO-RE accessor index rejection Weiming Shi @ 2026-04-04 18:12 ` Emil Tsalapatis 2026-04-06 15:03 ` Paul Chaignon 1 sibling, 0 replies; 9+ messages in thread From: Emil Tsalapatis @ 2026-04-04 18:12 UTC (permalink / raw) To: Weiming Shi, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf, Xiang Mei On Sat Apr 4, 2026 at 12:12 PM EDT, Weiming Shi wrote: > Add a selftest to verify that the kernel rejects BPF programs containing > CO-RE relocations with negative accessor indices. The test constructs a > minimal BTF blob with a struct type and a CO-RE relocation whose access > string is "0:-1". Without the fix in the previous patch, this triggers > an out-of-bounds read in bpf_core_parse_spec(); with the fix, the > program load fails cleanly with -EINVAL. > > Signed-off-by: Weiming Shi <bestswngs@gmail.com> Thank you for adding the selftest. Some nits below, but otherwise: Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com> > --- > .../selftests/bpf/prog_tests/core_reloc_raw.c | 94 +++++++++++++++++++ > 1 file changed, 94 insertions(+) > > diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc_raw.c b/tools/testing/selftests/bpf/prog_tests/core_reloc_raw.c > index a18d3680fb16..f7bf6c237d59 100644 > --- a/tools/testing/selftests/bpf/prog_tests/core_reloc_raw.c > +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc_raw.c > @@ -118,8 +118,102 @@ static void test_bad_local_id(void) > close(btf_fd); > } > > +/* Check that verifier rejects BPF program containing CO-RE relocation > + * with a negative accessor index (e.g. "0:-1"). > + */ > +static void test_negative_accessor(void) > +{ > + struct test_btf { > + struct btf_header hdr; > + __u32 types[18]; > + char strings[20]; > + } raw_btf = { > + .hdr = { > + .magic = BTF_MAGIC, > + .version = BTF_VERSION, > + .hdr_len = sizeof(struct btf_header), > + .type_off = 0, > + .type_len = sizeof(raw_btf.types), > + .str_off = offsetof(struct test_btf, strings) - > + offsetof(struct test_btf, types), > + .str_len = sizeof(raw_btf.strings), > + }, > + .types = { > + /* [1] int */ > + BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), > + /* [2] struct s { int x; } */ > + BTF_STRUCT_ENC(5, 1, 4), > + BTF_MEMBER_ENC(7, 1, 0), > + /* [3] int (*)(int a) */ > + BTF_FUNC_PROTO_ENC(1, 1), > + BTF_FUNC_PROTO_ARG_ENC(13, 1), Nit: If you make this BPF_PROG_TYPE_TRACING (see below) you can change this to be void(void) and skip the extra member. > + /* [4] FUNC 'foo' */ > + BTF_FUNC_ENC(9, 3), > + }, > + /* offsets: 0:NUL 1:"int" 5:"s" 7:"x" 9:"foo" 13:"a" 15:"0:-1" */ > + .strings = "\0int\0s\0x\0foo\0a\0" "0:-1", > + }; > + __u32 log_level = 1 | 2 | 4; > + LIBBPF_OPTS(bpf_btf_load_opts, opts, > + .log_buf = log, > + .log_size = sizeof(log), > + .log_level = log_level, > + ); > + struct bpf_insn insns[] = { > + BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), > + BPF_EXIT_INSN(), > + }; > + struct bpf_func_info funcs[] = { > + { .insn_off = 0, .type_id = 4 } > + }; > + struct bpf_core_relo relos[] = { > + { > + .insn_off = 0, > + .type_id = 2, /* struct s */ > + .access_str_off = 15, /* "0:-1" */ > + .kind = BPF_CORE_FIELD_BYTE_OFFSET, > + } > + }; > + union bpf_attr attr; > + int prog_fd = -1; > + int btf_fd = -1; > + > + btf_fd = bpf_btf_load(&raw_btf, sizeof(raw_btf), &opts); > + if (!ASSERT_GE(btf_fd, 0, "btf_load")) > + return; > + > + log[0] = 0; No need for setting 0, the log is guaranteed to be NULL-terminated after load() is called provided the user running the selftests has the appropriate privilege. > + memset(&attr, 0, sizeof(attr)); > + attr.prog_btf_fd = btf_fd; > + attr.prog_type = BPF_TRACE_RAW_TP; As the bot in sashiko.dev points out, this is an attach type and not a load type. Can you change it so BPF_PROG_TYPE_TRACING? The same holds for the pre-existing test that has the same issue - I think a drive-by fix is fine in this case as long as you mention it in the commit message. > + attr.license = (__u64)"GPL"; > + attr.insns = (__u64)&insns; > + attr.insn_cnt = sizeof(insns) / sizeof(*insns); > + attr.log_buf = (__u64)log; > + attr.log_size = sizeof(log); > + attr.log_level = log_level; > + attr.func_info = (__u64)funcs; > + attr.func_info_cnt = sizeof(funcs) / sizeof(*funcs); > + attr.func_info_rec_size = sizeof(*funcs); > + attr.core_relos = (__u64)relos; > + attr.core_relo_cnt = sizeof(relos) / sizeof(*relos); > + attr.core_relo_rec_size = sizeof(*relos); > + prog_fd = sys_bpf_prog_load(&attr, sizeof(attr), 1); > + if (prog_fd >= 0) { > + PRINT_FAIL("sys_bpf_prog_load() expected to fail\n"); > + goto out; > + } > + ASSERT_HAS_SUBSTR(log, "failed: -22", "prog_load_log"); > + > +out: > + close(prog_fd); > + close(btf_fd); > +} > + > void test_core_reloc_raw(void) > { > if (test__start_subtest("bad_local_id")) > test_bad_local_id(); > + if (test__start_subtest("negative_accessor")) > + test_negative_accessor(); > } ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH bpf v3 2/2] selftests/bpf: add test for negative CO-RE accessor index rejection 2026-04-04 16:12 ` [PATCH bpf v3 2/2] selftests/bpf: add test for negative CO-RE accessor index rejection Weiming Shi 2026-04-04 18:12 ` Emil Tsalapatis @ 2026-04-06 15:03 ` Paul Chaignon 1 sibling, 0 replies; 9+ messages in thread From: Paul Chaignon @ 2026-04-06 15:03 UTC (permalink / raw) To: Weiming Shi Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf, Xiang Mei On Sun, Apr 05, 2026 at 12:12:21AM +0800, Weiming Shi wrote: > Add a selftest to verify that the kernel rejects BPF programs containing > CO-RE relocations with negative accessor indices. The test constructs a > minimal BTF blob with a struct type and a CO-RE relocation whose access > string is "0:-1". Without the fix in the previous patch, this triggers > an out-of-bounds read in bpf_core_parse_spec(); with the fix, the > program load fails cleanly with -EINVAL. > > Signed-off-by: Weiming Shi <bestswngs@gmail.com> I checked that the new selftest does fail, in the expected manner, when applied without the corresponding fix. Tested-by: Paul Chaignon <paul.chaignon@gmail.com> > --- > .../selftests/bpf/prog_tests/core_reloc_raw.c | 94 +++++++++++++++++++ > 1 file changed, 94 insertions(+) > > diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc_raw.c b/tools/testing/selftests/bpf/prog_tests/core_reloc_raw.c > index a18d3680fb16..f7bf6c237d59 100644 > --- a/tools/testing/selftests/bpf/prog_tests/core_reloc_raw.c > +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc_raw.c > @@ -118,8 +118,102 @@ static void test_bad_local_id(void) > close(btf_fd); > } > > +/* Check that verifier rejects BPF program containing CO-RE relocation > + * with a negative accessor index (e.g. "0:-1"). > + */ > +static void test_negative_accessor(void) > +{ > + struct test_btf { > + struct btf_header hdr; > + __u32 types[18]; > + char strings[20]; > + } raw_btf = { > + .hdr = { > + .magic = BTF_MAGIC, > + .version = BTF_VERSION, > + .hdr_len = sizeof(struct btf_header), > + .type_off = 0, > + .type_len = sizeof(raw_btf.types), > + .str_off = offsetof(struct test_btf, strings) - > + offsetof(struct test_btf, types), > + .str_len = sizeof(raw_btf.strings), > + }, > + .types = { > + /* [1] int */ > + BTF_TYPE_INT_ENC(1, BTF_INT_SIGNED, 0, 32, 4), > + /* [2] struct s { int x; } */ > + BTF_STRUCT_ENC(5, 1, 4), > + BTF_MEMBER_ENC(7, 1, 0), > + /* [3] int (*)(int a) */ > + BTF_FUNC_PROTO_ENC(1, 1), > + BTF_FUNC_PROTO_ARG_ENC(13, 1), > + /* [4] FUNC 'foo' */ > + BTF_FUNC_ENC(9, 3), > + }, > + /* offsets: 0:NUL 1:"int" 5:"s" 7:"x" 9:"foo" 13:"a" 15:"0:-1" */ > + .strings = "\0int\0s\0x\0foo\0a\0" "0:-1", > + }; > + __u32 log_level = 1 | 2 | 4; > + LIBBPF_OPTS(bpf_btf_load_opts, opts, > + .log_buf = log, > + .log_size = sizeof(log), > + .log_level = log_level, > + ); > + struct bpf_insn insns[] = { > + BPF_ALU64_IMM(BPF_MOV, BPF_REG_0, 0), > + BPF_EXIT_INSN(), > + }; > + struct bpf_func_info funcs[] = { > + { .insn_off = 0, .type_id = 4 } > + }; > + struct bpf_core_relo relos[] = { > + { > + .insn_off = 0, > + .type_id = 2, /* struct s */ > + .access_str_off = 15, /* "0:-1" */ > + .kind = BPF_CORE_FIELD_BYTE_OFFSET, > + } > + }; > + union bpf_attr attr; > + int prog_fd = -1; > + int btf_fd = -1; > + > + btf_fd = bpf_btf_load(&raw_btf, sizeof(raw_btf), &opts); > + if (!ASSERT_GE(btf_fd, 0, "btf_load")) > + return; > + > + log[0] = 0; > + memset(&attr, 0, sizeof(attr)); > + attr.prog_btf_fd = btf_fd; > + attr.prog_type = BPF_TRACE_RAW_TP; > + attr.license = (__u64)"GPL"; > + attr.insns = (__u64)&insns; > + attr.insn_cnt = sizeof(insns) / sizeof(*insns); > + attr.log_buf = (__u64)log; > + attr.log_size = sizeof(log); > + attr.log_level = log_level; > + attr.func_info = (__u64)funcs; > + attr.func_info_cnt = sizeof(funcs) / sizeof(*funcs); > + attr.func_info_rec_size = sizeof(*funcs); > + attr.core_relos = (__u64)relos; > + attr.core_relo_cnt = sizeof(relos) / sizeof(*relos); > + attr.core_relo_rec_size = sizeof(*relos); > + prog_fd = sys_bpf_prog_load(&attr, sizeof(attr), 1); > + if (prog_fd >= 0) { > + PRINT_FAIL("sys_bpf_prog_load() expected to fail\n"); > + goto out; > + } > + ASSERT_HAS_SUBSTR(log, "failed: -22", "prog_load_log"); > + > +out: > + close(prog_fd); > + close(btf_fd); > +} > + > void test_core_reloc_raw(void) > { > if (test__start_subtest("bad_local_id")) > test_bad_local_id(); > + if (test__start_subtest("negative_accessor")) > + test_negative_accessor(); > } > -- > 2.43.0 > > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH bpf v3 0/2] bpf: reject negative CO-RE accessor indices 2026-04-04 16:12 [PATCH bpf v3 0/2] bpf: reject negative CO-RE accessor indices Weiming Shi 2026-04-04 16:12 ` [PATCH bpf v3 1/2] bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec() Weiming Shi 2026-04-04 16:12 ` [PATCH bpf v3 2/2] selftests/bpf: add test for negative CO-RE accessor index rejection Weiming Shi @ 2026-04-04 18:06 ` Emil Tsalapatis 2026-04-07 15:30 ` patchwork-bot+netdevbpf 3 siblings, 0 replies; 9+ messages in thread From: Emil Tsalapatis @ 2026-04-04 18:06 UTC (permalink / raw) To: Weiming Shi, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi Cc: Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, bpf, Xiang Mei On Sat Apr 4, 2026 at 12:12 PM EDT, Weiming Shi wrote: > bpf_core_parse_spec() parses CO-RE accessor strings with sscanf("%d"), > which accepts negative values. The downstream bounds checks only test > the upper bound, so a negative index like -1 slips through, gets cast > to u32 0xffffffff in btf_member_bit_offset(), and crashes the kernel. > > To clarify the kernel-side concern from v2 review: > tools/lib/bpf/relo_core.c is shared code -- the kernel compiles it > directly via kernel/bpf/relo_core.c (#include). So the fix does > apply in the kernel's BPF_PROG_LOAD -> check_core_relo() -> > bpf_core_apply() -> bpf_core_parse_spec() path. > Since this text ends up in the git log, I think you can remove this paragraph - especially since there is no permalink in the version history below. > v3: added selftest (patch 2/2) > v2: fix typo Signed-off-by tag (missing leading 'S') > > Weiming Shi (2): > bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec() > selftests/bpf: add test for negative CO-RE accessor index rejection > > tools/lib/bpf/relo_core.c | 2 + > .../selftests/bpf/prog_tests/core_reloc_raw.c | 94 +++++++++++++++++++ > 2 files changed, 96 insertions(+) ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH bpf v3 0/2] bpf: reject negative CO-RE accessor indices 2026-04-04 16:12 [PATCH bpf v3 0/2] bpf: reject negative CO-RE accessor indices Weiming Shi ` (2 preceding siblings ...) 2026-04-04 18:06 ` [PATCH bpf v3 0/2] bpf: reject negative CO-RE accessor indices Emil Tsalapatis @ 2026-04-07 15:30 ` patchwork-bot+netdevbpf 3 siblings, 0 replies; 9+ messages in thread From: patchwork-bot+netdevbpf @ 2026-04-07 15:30 UTC (permalink / raw) To: Weiming Shi Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song, yonghong.song, jolsa, bpf, xmei5 Hello: This series was applied to bpf/bpf-next.git (master) by Alexei Starovoitov <ast@kernel.org>: On Sun, 5 Apr 2026 00:12:19 +0800 you wrote: > bpf_core_parse_spec() parses CO-RE accessor strings with sscanf("%d"), > which accepts negative values. The downstream bounds checks only test > the upper bound, so a negative index like -1 slips through, gets cast > to u32 0xffffffff in btf_member_bit_offset(), and crashes the kernel. > > To clarify the kernel-side concern from v2 review: > tools/lib/bpf/relo_core.c is shared code -- the kernel compiles it > directly via kernel/bpf/relo_core.c (#include). So the fix does > apply in the kernel's BPF_PROG_LOAD -> check_core_relo() -> > bpf_core_apply() -> bpf_core_parse_spec() path. > > [...] Here is the summary with links: - [bpf,v3,1/2] bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec() https://git.kernel.org/bpf/bpf-next/c/1c22483a2c4b - [bpf,v3,2/2] selftests/bpf: add test for negative CO-RE accessor index rejection (no matching commit) You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-04-07 15:30 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-04-04 16:12 [PATCH bpf v3 0/2] bpf: reject negative CO-RE accessor indices Weiming Shi 2026-04-04 16:12 ` [PATCH bpf v3 1/2] bpf: reject negative CO-RE accessor indices in bpf_core_parse_spec() Weiming Shi 2026-04-04 18:07 ` Emil Tsalapatis 2026-04-06 15:01 ` Paul Chaignon 2026-04-04 16:12 ` [PATCH bpf v3 2/2] selftests/bpf: add test for negative CO-RE accessor index rejection Weiming Shi 2026-04-04 18:12 ` Emil Tsalapatis 2026-04-06 15:03 ` Paul Chaignon 2026-04-04 18:06 ` [PATCH bpf v3 0/2] bpf: reject negative CO-RE accessor indices Emil Tsalapatis 2026-04-07 15:30 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox