* [PATCH bpf-next v1 0/2] Fix for untrusted BTF pointer writes @ 2026-07-07 19:02 Kumar Kartikeya Dwivedi 2026-07-07 19:02 ` [PATCH bpf-next v1 1/2] bpf: Reject writes through untrusted BTF pointers Kumar Kartikeya Dwivedi 2026-07-07 19:02 ` [PATCH bpf-next v1 2/2] selftests/bpf: Add untrusted BTF write regression Kumar Kartikeya Dwivedi 0 siblings, 2 replies; 8+ messages in thread From: Kumar Kartikeya Dwivedi @ 2026-07-07 19:02 UTC (permalink / raw) To: bpf Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann, Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team When using custom btf_struct_access() callbacks, we miss rejecting unstrusted BTF pointer writes. Fix and add a selftest for coverage. Kumar Kartikeya Dwivedi (1): selftests/bpf: Add untrusted BTF write regression Nicholas Dudar (1): bpf: Reject writes through untrusted BTF pointers kernel/bpf/verifier.c | 8 ++++-- .../selftests/bpf/prog_tests/bpf_tcp_ca.c | 12 +++++++++ .../bpf/progs/tcp_ca_untrusted_btf_write.c | 26 +++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c base-commit: f425a0443b7f0221a4b34f6acc0c2924bf5877f2 -- 2.53.0 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH bpf-next v1 1/2] bpf: Reject writes through untrusted BTF pointers 2026-07-07 19:02 [PATCH bpf-next v1 0/2] Fix for untrusted BTF pointer writes Kumar Kartikeya Dwivedi @ 2026-07-07 19:02 ` Kumar Kartikeya Dwivedi 2026-07-07 19:48 ` bot+bpf-ci 2026-07-07 22:10 ` Amery Hung 2026-07-07 19:02 ` [PATCH bpf-next v1 2/2] selftests/bpf: Add untrusted BTF write regression Kumar Kartikeya Dwivedi 1 sibling, 2 replies; 8+ messages in thread From: Kumar Kartikeya Dwivedi @ 2026-07-07 19:02 UTC (permalink / raw) To: bpf Cc: Nicholas Dudar, Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann, Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team From: Nicholas Dudar <main.kalliope@gmail.com> check_ptr_to_btf_access() lets program-type btf_struct_access callbacks validate writes before the default BTF access path rejects non-read accesses. That bypasses the read-only policy for untrusted BTF pointers created by helpers such as bpf_rdonly_cast(). Reject non-read accesses through PTR_UNTRUSTED BTF pointers at the common entry point, before the callback branch to handle all cases. Signed-off-by: Nicholas Dudar <main.kalliope@gmail.com> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> --- kernel/bpf/verifier.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 3193b473762b..7cf555a7026c 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -5813,6 +5813,11 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, return -EACCES; } + if (atype != BPF_READ && (type_flag(reg->type) & PTR_UNTRUSTED)) { + verbose(env, "only read is supported\n"); + return -EACCES; + } + if (env->ops->btf_struct_access && !type_is_alloc(reg->type) && atype == BPF_WRITE) { if (!btf_is_kernel(reg->btf)) { verifier_bug(env, "reg->btf must be kernel btf"); @@ -5825,8 +5830,7 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, reg_arg_name(env, argno), tname, off, size); } else { /* Writes are permitted with default btf_struct_access for - * program allocated objects (which always have id > 0), - * but not for untrusted PTR_TO_BTF_ID | MEM_ALLOC. + * program allocated objects (which always have id > 0). */ if (atype != BPF_READ && !type_is_ptr_alloc_obj(reg->type)) { verbose(env, "only read is supported\n"); -- 2.53.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next v1 1/2] bpf: Reject writes through untrusted BTF pointers 2026-07-07 19:02 ` [PATCH bpf-next v1 1/2] bpf: Reject writes through untrusted BTF pointers Kumar Kartikeya Dwivedi @ 2026-07-07 19:48 ` bot+bpf-ci 2026-07-07 22:10 ` Amery Hung 1 sibling, 0 replies; 8+ messages in thread From: bot+bpf-ci @ 2026-07-07 19:48 UTC (permalink / raw) To: memxor, bpf Cc: main.kalliope, ast, andrii, daniel, eddyz87, emil, kkd, kernel-team, ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai [-- Attachment #1: Type: text/plain, Size: 1250 bytes --] > check_ptr_to_btf_access() lets program-type btf_struct_access callbacks > validate writes before the default BTF access path rejects non-read > accesses. That bypasses the read-only policy for untrusted BTF pointers > created by helpers such as bpf_rdonly_cast(). > > Reject non-read accesses through PTR_UNTRUSTED BTF pointers at the > common entry point, before the callback branch to handle all cases. > > Signed-off-by: Nicholas Dudar <main.kalliope@gmail.com> > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> This fixes a write path that bypassed the read-only policy for untrusted BTF pointers, but there is no Fixes: tag. The write-dispatch branch that took precedence over the untrusted read-only check in check_ptr_to_btf_access(), along with the "but not for untrusted PTR_TO_BTF_ID | MEM_ALLOC" comment that this patch removes, was added when program allocated objects support was introduced. Should this include: Fixes: 282de143ead9 ("bpf: Introduce allocated objects support") --- AI reviewed your patch. Please fix the bug or email reply why it's not a bug. See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md CI run summary: https://github.com/kernel-patches/bpf/actions/runs/28892378159 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next v1 1/2] bpf: Reject writes through untrusted BTF pointers 2026-07-07 19:02 ` [PATCH bpf-next v1 1/2] bpf: Reject writes through untrusted BTF pointers Kumar Kartikeya Dwivedi 2026-07-07 19:48 ` bot+bpf-ci @ 2026-07-07 22:10 ` Amery Hung 1 sibling, 0 replies; 8+ messages in thread From: Amery Hung @ 2026-07-07 22:10 UTC (permalink / raw) To: Kumar Kartikeya Dwivedi Cc: bpf, Nicholas Dudar, Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann, Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team On Tue, Jul 7, 2026 at 12:02 PM Kumar Kartikeya Dwivedi <memxor@gmail.com> wrote: > > From: Nicholas Dudar <main.kalliope@gmail.com> > > check_ptr_to_btf_access() lets program-type btf_struct_access callbacks > validate writes before the default BTF access path rejects non-read > accesses. That bypasses the read-only policy for untrusted BTF pointers > created by helpers such as bpf_rdonly_cast(). > > Reject non-read accesses through PTR_UNTRUSTED BTF pointers at the > common entry point, before the callback branch to handle all cases. > > Signed-off-by: Nicholas Dudar <main.kalliope@gmail.com> > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Reviewed-by: Amery Hung <ameryhung@gmail.com> > --- > kernel/bpf/verifier.c | 8 ++++++-- > 1 file changed, 6 insertions(+), 2 deletions(-) > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > index 3193b473762b..7cf555a7026c 100644 > --- a/kernel/bpf/verifier.c > +++ b/kernel/bpf/verifier.c > @@ -5813,6 +5813,11 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, > return -EACCES; > } > > + if (atype != BPF_READ && (type_flag(reg->type) & PTR_UNTRUSTED)) { > + verbose(env, "only read is supported\n"); > + return -EACCES; > + } > + > if (env->ops->btf_struct_access && !type_is_alloc(reg->type) && atype == BPF_WRITE) { > if (!btf_is_kernel(reg->btf)) { > verifier_bug(env, "reg->btf must be kernel btf"); > @@ -5825,8 +5830,7 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, > reg_arg_name(env, argno), tname, off, size); > } else { > /* Writes are permitted with default btf_struct_access for > - * program allocated objects (which always have id > 0), > - * but not for untrusted PTR_TO_BTF_ID | MEM_ALLOC. > + * program allocated objects (which always have id > 0). > */ > if (atype != BPF_READ && !type_is_ptr_alloc_obj(reg->type)) { > verbose(env, "only read is supported\n"); > -- > 2.53.0 > > ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH bpf-next v1 2/2] selftests/bpf: Add untrusted BTF write regression 2026-07-07 19:02 [PATCH bpf-next v1 0/2] Fix for untrusted BTF pointer writes Kumar Kartikeya Dwivedi 2026-07-07 19:02 ` [PATCH bpf-next v1 1/2] bpf: Reject writes through untrusted BTF pointers Kumar Kartikeya Dwivedi @ 2026-07-07 19:02 ` Kumar Kartikeya Dwivedi 2026-07-07 22:31 ` Amery Hung 1 sibling, 1 reply; 8+ messages in thread From: Kumar Kartikeya Dwivedi @ 2026-07-07 19:02 UTC (permalink / raw) To: bpf Cc: Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann, Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team Add a TCP congestion-control struct_ops load test for a write through a BTF pointer produced by bpf_rdonly_cast(). The test expects the verifier to reject the program before the TCP CA btf_struct_access callback can whitelist the tcp_sock field write. Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> --- .../selftests/bpf/prog_tests/bpf_tcp_ca.c | 12 +++++++++ .../bpf/progs/tcp_ca_untrusted_btf_write.c | 26 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c index fe30181e6336..eb05fc82f81b 100644 --- a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c +++ b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c @@ -14,6 +14,7 @@ #include "tcp_ca_incompl_cong_ops.skel.h" #include "tcp_ca_unsupp_cong_op.skel.h" #include "tcp_ca_kfunc.skel.h" +#include "tcp_ca_untrusted_btf_write.skel.h" #include "bpf_cc_cubic.skel.h" static const unsigned int total_bytes = 10 * 1024 * 1024; @@ -579,6 +580,15 @@ static void test_tcp_ca_kfunc(void) tcp_ca_kfunc__destroy(skel); } +static void test_untrusted_btf_write(void) +{ + struct tcp_ca_untrusted_btf_write *skel; + + skel = tcp_ca_untrusted_btf_write__open_and_load(); + ASSERT_ERR_PTR(skel, "tcp_ca_untrusted_btf_write__open_and_load"); + tcp_ca_untrusted_btf_write__destroy(skel); +} + static void test_cc_cubic(void) { struct cb_opts cb_opts = { @@ -637,6 +647,8 @@ void test_bpf_tcp_ca(void) test_link_replace(); if (test__start_subtest("tcp_ca_kfunc")) test_tcp_ca_kfunc(); + if (test__start_subtest("untrusted_btf_write")) + test_untrusted_btf_write(); if (test__start_subtest("cc_cubic")) test_cc_cubic(); if (test__start_subtest("dctcp_autoattach_map")) diff --git a/tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c b/tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c new file mode 100644 index 000000000000..eda4697aac80 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "bpf_tracing_net.h" +#include <bpf/bpf_core_read.h> +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> + +char _license[] SEC("license") = "GPL"; + +SEC("struct_ops") +void BPF_PROG(untrusted_btf_write_init, struct sock *sk) +{ + struct tcp_sock *tp; + int v = 1; + void *p; + + p = bpf_rdonly_cast(&v, 0); + tp = bpf_rdonly_cast(p, bpf_core_type_id_kernel(struct tcp_sock)); + tp->snd_cwnd = 1; +} + +SEC(".struct_ops") +struct tcp_congestion_ops untrusted_btf_write = { + .init = (void *)untrusted_btf_write_init, + .name = "bpf_ro_btf", +}; -- 2.53.0 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next v1 2/2] selftests/bpf: Add untrusted BTF write regression 2026-07-07 19:02 ` [PATCH bpf-next v1 2/2] selftests/bpf: Add untrusted BTF write regression Kumar Kartikeya Dwivedi @ 2026-07-07 22:31 ` Amery Hung 2026-07-07 22:36 ` Kumar Kartikeya Dwivedi 0 siblings, 1 reply; 8+ messages in thread From: Amery Hung @ 2026-07-07 22:31 UTC (permalink / raw) To: Kumar Kartikeya Dwivedi Cc: bpf, Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann, Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team On Tue, Jul 7, 2026 at 12:02 PM Kumar Kartikeya Dwivedi <memxor@gmail.com> wrote: > > Add a TCP congestion-control struct_ops load test for a write through a > BTF pointer produced by bpf_rdonly_cast(). > > The test expects the verifier to reject the program before the TCP CA > btf_struct_access callback can whitelist the tcp_sock field write. > > Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> > --- > .../selftests/bpf/prog_tests/bpf_tcp_ca.c | 12 +++++++++ > .../bpf/progs/tcp_ca_untrusted_btf_write.c | 26 +++++++++++++++++++ > 2 files changed, 38 insertions(+) > create mode 100644 tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c > > diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c > index fe30181e6336..eb05fc82f81b 100644 > --- a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c > +++ b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c > @@ -14,6 +14,7 @@ > #include "tcp_ca_incompl_cong_ops.skel.h" > #include "tcp_ca_unsupp_cong_op.skel.h" > #include "tcp_ca_kfunc.skel.h" > +#include "tcp_ca_untrusted_btf_write.skel.h" > #include "bpf_cc_cubic.skel.h" > > static const unsigned int total_bytes = 10 * 1024 * 1024; > @@ -579,6 +580,15 @@ static void test_tcp_ca_kfunc(void) > tcp_ca_kfunc__destroy(skel); > } > > +static void test_untrusted_btf_write(void) > +{ > + struct tcp_ca_untrusted_btf_write *skel; > + > + skel = tcp_ca_untrusted_btf_write__open_and_load(); > + ASSERT_ERR_PTR(skel, "tcp_ca_untrusted_btf_write__open_and_load"); > + tcp_ca_untrusted_btf_write__destroy(skel); > +} > + > static void test_cc_cubic(void) > { > struct cb_opts cb_opts = { > @@ -637,6 +647,8 @@ void test_bpf_tcp_ca(void) > test_link_replace(); > if (test__start_subtest("tcp_ca_kfunc")) > test_tcp_ca_kfunc(); > + if (test__start_subtest("untrusted_btf_write")) > + test_untrusted_btf_write(); > if (test__start_subtest("cc_cubic")) > test_cc_cubic(); > if (test__start_subtest("dctcp_autoattach_map")) > diff --git a/tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c b/tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c > new file mode 100644 > index 000000000000..eda4697aac80 > --- /dev/null > +++ b/tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c > @@ -0,0 +1,26 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#include "bpf_tracing_net.h" > +#include <bpf/bpf_core_read.h> > +#include <bpf/bpf_helpers.h> > +#include <bpf/bpf_tracing.h> > + > +char _license[] SEC("license") = "GPL"; > + > +SEC("struct_ops") > +void BPF_PROG(untrusted_btf_write_init, struct sock *sk) > +{ > + struct tcp_sock *tp; > + int v = 1; > + void *p; > + > + p = bpf_rdonly_cast(&v, 0); > + tp = bpf_rdonly_cast(p, bpf_core_type_id_kernel(struct tcp_sock)); Do we need two bpf_rdonly_cast()? I tested the following and it also works: tp = bpf_rdonly_cast(&v, bpf_core_type_id_kernel(struct tcp_sock)); > + tp->snd_cwnd = 1; > +} > + > +SEC(".struct_ops") > +struct tcp_congestion_ops untrusted_btf_write = { > + .init = (void *)untrusted_btf_write_init, > + .name = "bpf_ro_btf", > +}; > -- > 2.53.0 > > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next v1 2/2] selftests/bpf: Add untrusted BTF write regression 2026-07-07 22:31 ` Amery Hung @ 2026-07-07 22:36 ` Kumar Kartikeya Dwivedi 2026-07-07 22:58 ` Amery Hung 0 siblings, 1 reply; 8+ messages in thread From: Kumar Kartikeya Dwivedi @ 2026-07-07 22:36 UTC (permalink / raw) To: Amery Hung, Kumar Kartikeya Dwivedi Cc: bpf, Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann, Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team On Wed Jul 8, 2026 at 12:31 AM CEST, Amery Hung wrote: > On Tue, Jul 7, 2026 at 12:02 PM Kumar Kartikeya Dwivedi > <memxor@gmail.com> wrote: >> >> Add a TCP congestion-control struct_ops load test for a write through a >> BTF pointer produced by bpf_rdonly_cast(). >> >> The test expects the verifier to reject the program before the TCP CA >> btf_struct_access callback can whitelist the tcp_sock field write. >> >> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> >> --- >> .../selftests/bpf/prog_tests/bpf_tcp_ca.c | 12 +++++++++ >> .../bpf/progs/tcp_ca_untrusted_btf_write.c | 26 +++++++++++++++++++ >> 2 files changed, 38 insertions(+) >> create mode 100644 tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c >> >> diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c >> index fe30181e6336..eb05fc82f81b 100644 >> --- a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c >> +++ b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c >> @@ -14,6 +14,7 @@ >> #include "tcp_ca_incompl_cong_ops.skel.h" >> #include "tcp_ca_unsupp_cong_op.skel.h" >> #include "tcp_ca_kfunc.skel.h" >> +#include "tcp_ca_untrusted_btf_write.skel.h" >> #include "bpf_cc_cubic.skel.h" >> >> static const unsigned int total_bytes = 10 * 1024 * 1024; >> @@ -579,6 +580,15 @@ static void test_tcp_ca_kfunc(void) >> tcp_ca_kfunc__destroy(skel); >> } >> >> +static void test_untrusted_btf_write(void) >> +{ >> + struct tcp_ca_untrusted_btf_write *skel; >> + >> + skel = tcp_ca_untrusted_btf_write__open_and_load(); >> + ASSERT_ERR_PTR(skel, "tcp_ca_untrusted_btf_write__open_and_load"); >> + tcp_ca_untrusted_btf_write__destroy(skel); >> +} >> + >> static void test_cc_cubic(void) >> { >> struct cb_opts cb_opts = { >> @@ -637,6 +647,8 @@ void test_bpf_tcp_ca(void) >> test_link_replace(); >> if (test__start_subtest("tcp_ca_kfunc")) >> test_tcp_ca_kfunc(); >> + if (test__start_subtest("untrusted_btf_write")) >> + test_untrusted_btf_write(); >> if (test__start_subtest("cc_cubic")) >> test_cc_cubic(); >> if (test__start_subtest("dctcp_autoattach_map")) >> diff --git a/tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c b/tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c >> new file mode 100644 >> index 000000000000..eda4697aac80 >> --- /dev/null >> +++ b/tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c >> @@ -0,0 +1,26 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> + >> +#include "bpf_tracing_net.h" >> +#include <bpf/bpf_core_read.h> >> +#include <bpf/bpf_helpers.h> >> +#include <bpf/bpf_tracing.h> >> + >> +char _license[] SEC("license") = "GPL"; >> + >> +SEC("struct_ops") >> +void BPF_PROG(untrusted_btf_write_init, struct sock *sk) >> +{ >> + struct tcp_sock *tp; >> + int v = 1; >> + void *p; >> + >> + p = bpf_rdonly_cast(&v, 0); >> + tp = bpf_rdonly_cast(p, bpf_core_type_id_kernel(struct tcp_sock)); > > Do we need two bpf_rdonly_cast()? I tested the following and it also works: > Yeah, single case works too, I mostly kept these two because of the original report. > tp = bpf_rdonly_cast(&v, bpf_core_type_id_kernel(struct tcp_sock)); > >> + tp->snd_cwnd = 1; >> +} >> + >> +SEC(".struct_ops") >> +struct tcp_congestion_ops untrusted_btf_write = { >> + .init = (void *)untrusted_btf_write_init, >> + .name = "bpf_ro_btf", >> +}; >> -- >> 2.53.0 >> >> ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf-next v1 2/2] selftests/bpf: Add untrusted BTF write regression 2026-07-07 22:36 ` Kumar Kartikeya Dwivedi @ 2026-07-07 22:58 ` Amery Hung 0 siblings, 0 replies; 8+ messages in thread From: Amery Hung @ 2026-07-07 22:58 UTC (permalink / raw) To: Kumar Kartikeya Dwivedi Cc: bpf, Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann, Eduard Zingerman, Emil Tsalapatis, kkd, kernel-team On Tue, Jul 7, 2026 at 3:36 PM Kumar Kartikeya Dwivedi <memxor@gmail.com> wrote: > > On Wed Jul 8, 2026 at 12:31 AM CEST, Amery Hung wrote: > > On Tue, Jul 7, 2026 at 12:02 PM Kumar Kartikeya Dwivedi > > <memxor@gmail.com> wrote: > >> > >> Add a TCP congestion-control struct_ops load test for a write through a > >> BTF pointer produced by bpf_rdonly_cast(). > >> > >> The test expects the verifier to reject the program before the TCP CA > >> btf_struct_access callback can whitelist the tcp_sock field write. > >> > >> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> > >> --- > >> .../selftests/bpf/prog_tests/bpf_tcp_ca.c | 12 +++++++++ > >> .../bpf/progs/tcp_ca_untrusted_btf_write.c | 26 +++++++++++++++++++ > >> 2 files changed, 38 insertions(+) > >> create mode 100644 tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c > >> > >> diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c > >> index fe30181e6336..eb05fc82f81b 100644 > >> --- a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c > >> +++ b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c > >> @@ -14,6 +14,7 @@ > >> #include "tcp_ca_incompl_cong_ops.skel.h" > >> #include "tcp_ca_unsupp_cong_op.skel.h" > >> #include "tcp_ca_kfunc.skel.h" > >> +#include "tcp_ca_untrusted_btf_write.skel.h" > >> #include "bpf_cc_cubic.skel.h" > >> > >> static const unsigned int total_bytes = 10 * 1024 * 1024; > >> @@ -579,6 +580,15 @@ static void test_tcp_ca_kfunc(void) > >> tcp_ca_kfunc__destroy(skel); > >> } > >> > >> +static void test_untrusted_btf_write(void) > >> +{ > >> + struct tcp_ca_untrusted_btf_write *skel; > >> + > >> + skel = tcp_ca_untrusted_btf_write__open_and_load(); > >> + ASSERT_ERR_PTR(skel, "tcp_ca_untrusted_btf_write__open_and_load"); > >> + tcp_ca_untrusted_btf_write__destroy(skel); > >> +} > >> + > >> static void test_cc_cubic(void) > >> { > >> struct cb_opts cb_opts = { > >> @@ -637,6 +647,8 @@ void test_bpf_tcp_ca(void) > >> test_link_replace(); > >> if (test__start_subtest("tcp_ca_kfunc")) > >> test_tcp_ca_kfunc(); > >> + if (test__start_subtest("untrusted_btf_write")) > >> + test_untrusted_btf_write(); > >> if (test__start_subtest("cc_cubic")) > >> test_cc_cubic(); > >> if (test__start_subtest("dctcp_autoattach_map")) > >> diff --git a/tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c b/tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c > >> new file mode 100644 > >> index 000000000000..eda4697aac80 > >> --- /dev/null > >> +++ b/tools/testing/selftests/bpf/progs/tcp_ca_untrusted_btf_write.c > >> @@ -0,0 +1,26 @@ > >> +// SPDX-License-Identifier: GPL-2.0 > >> + > >> +#include "bpf_tracing_net.h" > >> +#include <bpf/bpf_core_read.h> > >> +#include <bpf/bpf_helpers.h> > >> +#include <bpf/bpf_tracing.h> > >> + > >> +char _license[] SEC("license") = "GPL"; > >> + > >> +SEC("struct_ops") > >> +void BPF_PROG(untrusted_btf_write_init, struct sock *sk) > >> +{ > >> + struct tcp_sock *tp; > >> + int v = 1; > >> + void *p; > >> + > >> + p = bpf_rdonly_cast(&v, 0); > >> + tp = bpf_rdonly_cast(p, bpf_core_type_id_kernel(struct tcp_sock)); > > > > Do we need two bpf_rdonly_cast()? I tested the following and it also works: > > > > Yeah, single case works too, I mostly kept these two because of the original > report. I see. I was wondering whether the first cast has some special purposes. Single cast reads a bit cleaner to me, but no strong preference. Reviewed-by: Amery Hung <ameryhung@gmail.com> > > > tp = bpf_rdonly_cast(&v, bpf_core_type_id_kernel(struct tcp_sock)); > > > >> + tp->snd_cwnd = 1; > >> +} > >> + > >> +SEC(".struct_ops") > >> +struct tcp_congestion_ops untrusted_btf_write = { > >> + .init = (void *)untrusted_btf_write_init, > >> + .name = "bpf_ro_btf", > >> +}; > >> -- > >> 2.53.0 > >> > >> > ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-07-07 22:58 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-07 19:02 [PATCH bpf-next v1 0/2] Fix for untrusted BTF pointer writes Kumar Kartikeya Dwivedi 2026-07-07 19:02 ` [PATCH bpf-next v1 1/2] bpf: Reject writes through untrusted BTF pointers Kumar Kartikeya Dwivedi 2026-07-07 19:48 ` bot+bpf-ci 2026-07-07 22:10 ` Amery Hung 2026-07-07 19:02 ` [PATCH bpf-next v1 2/2] selftests/bpf: Add untrusted BTF write regression Kumar Kartikeya Dwivedi 2026-07-07 22:31 ` Amery Hung 2026-07-07 22:36 ` Kumar Kartikeya Dwivedi 2026-07-07 22:58 ` Amery Hung
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox