From baa802d2aa5c220d82499fd1c81fb735c74729b2 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 21 Oct 2024 17:28:08 +0200 Subject: selftests/bpf: Add test for writes to .rodata Add a small test to write a (verification-time) fixed vs unknown but bounded-sized buffer into .rodata BPF map and assert that both get rejected. # ./vmtest.sh -- ./test_progs -t verifier_const [...] ./test_progs -t verifier_const [ 1.418717] tsc: Refined TSC clocksource calibration: 3407.994 MHz [ 1.419113] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x311fcde90a1, max_idle_ns: 440795222066 ns [ 1.419972] clocksource: Switched to clocksource tsc [ 1.449596] bpf_testmod: loading out-of-tree module taints kernel. [ 1.449958] bpf_testmod: module verification failed: signature and/or required key missing - tainting kernel #475/1 verifier_const/rodata/strtol: write rejected:OK #475/2 verifier_const/bss/strtol: write accepted:OK #475/3 verifier_const/data/strtol: write accepted:OK #475/4 verifier_const/rodata/mtu: write rejected:OK #475/5 verifier_const/bss/mtu: write accepted:OK #475/6 verifier_const/data/mtu: write accepted:OK #475/7 verifier_const/rodata/mark: write with unknown reg rejected:OK #475/8 verifier_const/rodata/mark: write with unknown reg rejected:OK #475 verifier_const:OK #476/1 verifier_const_or/constant register |= constant should keep constant type:OK #476/2 verifier_const_or/constant register |= constant should not bypass stack boundary checks:OK #476/3 verifier_const_or/constant register |= constant register should keep constant type:OK #476/4 verifier_const_or/constant register |= constant register should not bypass stack boundary checks:OK #476 verifier_const_or:OK Summary: 2/12 PASSED, 0 SKIPPED, 0 FAILED Signed-off-by: Daniel Borkmann Acked-by: Kumar Kartikeya Dwivedi Link: https://lore.kernel.org/r/20241021152809.33343-4-daniel@iogearbox.net Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/progs/verifier_const.c | 31 +++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) (limited to 'tools/testing') diff --git a/tools/testing/selftests/bpf/progs/verifier_const.c b/tools/testing/selftests/bpf/progs/verifier_const.c index 2e533d7eec2f..e118dbb768bf 100644 --- a/tools/testing/selftests/bpf/progs/verifier_const.c +++ b/tools/testing/selftests/bpf/progs/verifier_const.c @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2024 Isovalent */ -#include +#include "vmlinux.h" #include +#include #include "bpf_misc.h" const volatile long foo = 42; @@ -66,4 +67,32 @@ int tcx6(struct __sk_buff *skb) return TCX_PASS; } +static inline void write_fixed(volatile void *p, __u32 val) +{ + *(volatile __u32 *)p = val; +} + +static inline void write_dyn(void *p, void *val, int len) +{ + bpf_copy_from_user(p, len, val); +} + +SEC("tc/ingress") +__description("rodata/mark: write with unknown reg rejected") +__failure __msg("write into map forbidden") +int tcx7(struct __sk_buff *skb) +{ + write_fixed((void *)&foo, skb->mark); + return TCX_PASS; +} + +SEC("lsm.s/bprm_committed_creds") +__description("rodata/mark: write with unknown reg rejected") +__failure __msg("write into map forbidden") +int BPF_PROG(bprm, struct linux_binprm *bprm) +{ + write_dyn((void *)&foo, &bart, bpf_get_prandom_u32() & 3); + return 0; +} + char LICENSE[] SEC("license") = "GPL"; -- cgit v1.2.3 From 82bbe133312b37bbef29f96e56e177ebe240f700 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 21 Oct 2024 17:28:09 +0200 Subject: selftests/bpf: Add test for passing in uninit mtu_len Add a small test to pass an uninitialized mtu_len to the bpf_check_mtu() helper to probe whether the verifier rejects it under !CAP_PERFMON. # ./vmtest.sh -- ./test_progs -t verifier_mtu [...] ./test_progs -t verifier_mtu [ 1.414712] tsc: Refined TSC clocksource calibration: 3407.993 MHz [ 1.415327] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x311fcd52370, max_idle_ns: 440795242006 ns [ 1.416463] clocksource: Switched to clocksource tsc [ 1.429842] bpf_testmod: loading out-of-tree module taints kernel. [ 1.430283] bpf_testmod: module verification failed: signature and/or required key missing - tainting kernel #510/1 verifier_mtu/uninit/mtu: write rejected:OK #510 verifier_mtu:OK Summary: 1/1 PASSED, 0 SKIPPED, 0 FAILED Signed-off-by: Daniel Borkmann Acked-by: Kumar Kartikeya Dwivedi Link: https://lore.kernel.org/r/20241021152809.33343-5-daniel@iogearbox.net Signed-off-by: Alexei Starovoitov --- tools/testing/selftests/bpf/prog_tests/verifier.c | 19 +++++++++++++++++++ tools/testing/selftests/bpf/progs/verifier_mtu.c | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/verifier_mtu.c (limited to 'tools/testing') diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c index 5356f26bbb3f..75f7a2ce334b 100644 --- a/tools/testing/selftests/bpf/prog_tests/verifier.c +++ b/tools/testing/selftests/bpf/prog_tests/verifier.c @@ -54,6 +54,7 @@ #include "verifier_masking.skel.h" #include "verifier_meta_access.skel.h" #include "verifier_movsx.skel.h" +#include "verifier_mtu.skel.h" #include "verifier_netfilter_ctx.skel.h" #include "verifier_netfilter_retcode.skel.h" #include "verifier_bpf_fastcall.skel.h" @@ -223,6 +224,24 @@ void test_verifier_xdp_direct_packet_access(void) { RUN(verifier_xdp_direct_pack void test_verifier_bits_iter(void) { RUN(verifier_bits_iter); } void test_verifier_lsm(void) { RUN(verifier_lsm); } +void test_verifier_mtu(void) +{ + __u64 caps = 0; + int ret; + + /* In case CAP_BPF and CAP_PERFMON is not set */ + ret = cap_enable_effective(1ULL << CAP_BPF | 1ULL << CAP_NET_ADMIN, &caps); + if (!ASSERT_OK(ret, "set_cap_bpf_cap_net_admin")) + return; + ret = cap_disable_effective(1ULL << CAP_SYS_ADMIN | 1ULL << CAP_PERFMON, NULL); + if (!ASSERT_OK(ret, "disable_cap_sys_admin")) + goto restore_cap; + RUN(verifier_mtu); +restore_cap: + if (caps) + cap_enable_effective(caps, NULL); +} + static int init_test_val_map(struct bpf_object *obj, char *map_name) { struct test_val value = { diff --git a/tools/testing/selftests/bpf/progs/verifier_mtu.c b/tools/testing/selftests/bpf/progs/verifier_mtu.c new file mode 100644 index 000000000000..70c7600a26a0 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/verifier_mtu.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include "vmlinux.h" +#include +#include "bpf_misc.h" + +SEC("tc/ingress") +__description("uninit/mtu: write rejected") +__failure __msg("invalid indirect read from stack") +int tc_uninit_mtu(struct __sk_buff *ctx) +{ + __u32 mtu; + + bpf_check_mtu(ctx, 0, &mtu, 0, 0); + return TCX_PASS; +} + +char LICENSE[] SEC("license") = "GPL"; -- cgit v1.2.3