Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Make sure bpf_{g,s}et_retval is exposed everywhere

For each hook, have a simple bpf_set_retval(bpf_get_retval) program
and make sure it loads for the hooks we want. The exceptions are
the hooks which don't propagate the error to the callers:

- sockops
- recvmsg
- getpeername
- getsockname
- cg_skb ingress and egress

Acked-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Stanislav Fomichev <sdf@google.com>
Link: https://lore.kernel.org/r/20220823222555.523590-6-sdf@google.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Stanislav Fomichev and committed by
Alexei Starovoitov
e7215f57 2172fb80

+90
+1
tools/testing/selftests/bpf/Makefile
··· 323 323 $(OUTPUT)/test_xdp_noinline.o: BPF_CFLAGS += -fno-inline 324 324 325 325 $(OUTPUT)/flow_dissector_load.o: flow_dissector_load.h 326 + $(OUTPUT)/cgroup_getset_retval_hooks.o: cgroup_getset_retval_hooks.h 326 327 327 328 # Build BPF object using Clang 328 329 # $1 - input .c file
+25
tools/testing/selftests/bpf/cgroup_getset_retval_hooks.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + BPF_RETVAL_HOOK(ingress, "cgroup_skb/ingress", __sk_buff, -EINVAL) 4 + BPF_RETVAL_HOOK(egress, "cgroup_skb/egress", __sk_buff, -EINVAL) 5 + BPF_RETVAL_HOOK(sock_create, "cgroup/sock_create", bpf_sock, 0) 6 + BPF_RETVAL_HOOK(sock_ops, "sockops", bpf_sock_ops, -EINVAL) 7 + BPF_RETVAL_HOOK(dev, "cgroup/dev", bpf_cgroup_dev_ctx, 0) 8 + BPF_RETVAL_HOOK(bind4, "cgroup/bind4", bpf_sock_addr, 0) 9 + BPF_RETVAL_HOOK(bind6, "cgroup/bind6", bpf_sock_addr, 0) 10 + BPF_RETVAL_HOOK(connect4, "cgroup/connect4", bpf_sock_addr, 0) 11 + BPF_RETVAL_HOOK(connect6, "cgroup/connect6", bpf_sock_addr, 0) 12 + BPF_RETVAL_HOOK(post_bind4, "cgroup/post_bind4", bpf_sock_addr, 0) 13 + BPF_RETVAL_HOOK(post_bind6, "cgroup/post_bind6", bpf_sock_addr, 0) 14 + BPF_RETVAL_HOOK(sendmsg4, "cgroup/sendmsg4", bpf_sock_addr, 0) 15 + BPF_RETVAL_HOOK(sendmsg6, "cgroup/sendmsg6", bpf_sock_addr, 0) 16 + BPF_RETVAL_HOOK(sysctl, "cgroup/sysctl", bpf_sysctl, 0) 17 + BPF_RETVAL_HOOK(recvmsg4, "cgroup/recvmsg4", bpf_sock_addr, -EINVAL) 18 + BPF_RETVAL_HOOK(recvmsg6, "cgroup/recvmsg6", bpf_sock_addr, -EINVAL) 19 + BPF_RETVAL_HOOK(getsockopt, "cgroup/getsockopt", bpf_sockopt, 0) 20 + BPF_RETVAL_HOOK(setsockopt, "cgroup/setsockopt", bpf_sockopt, 0) 21 + BPF_RETVAL_HOOK(getpeername4, "cgroup/getpeername4", bpf_sock_addr, -EINVAL) 22 + BPF_RETVAL_HOOK(getpeername6, "cgroup/getpeername6", bpf_sock_addr, -EINVAL) 23 + BPF_RETVAL_HOOK(getsockname4, "cgroup/getsockname4", bpf_sock_addr, -EINVAL) 24 + BPF_RETVAL_HOOK(getsockname6, "cgroup/getsockname6", bpf_sock_addr, -EINVAL) 25 + BPF_RETVAL_HOOK(sock_release, "cgroup/sock_release", bpf_sock, 0)
+48
tools/testing/selftests/bpf/prog_tests/cgroup_getset_retval.c
··· 10 10 11 11 #include "cgroup_getset_retval_setsockopt.skel.h" 12 12 #include "cgroup_getset_retval_getsockopt.skel.h" 13 + #include "cgroup_getset_retval_hooks.skel.h" 13 14 14 15 #define SOL_CUSTOM 0xdeadbeef 15 16 ··· 434 433 cgroup_getset_retval_getsockopt__destroy(obj); 435 434 } 436 435 436 + struct exposed_hook { 437 + const char *name; 438 + int expected_err; 439 + } exposed_hooks[] = { 440 + 441 + #define BPF_RETVAL_HOOK(NAME, SECTION, CTX, EXPECTED_ERR) \ 442 + { \ 443 + .name = #NAME, \ 444 + .expected_err = EXPECTED_ERR, \ 445 + }, 446 + 447 + #include "cgroup_getset_retval_hooks.h" 448 + 449 + #undef BPF_RETVAL_HOOK 450 + }; 451 + 452 + static void test_exposed_hooks(int cgroup_fd, int sock_fd) 453 + { 454 + struct cgroup_getset_retval_hooks *skel; 455 + struct bpf_program *prog; 456 + int err; 457 + int i; 458 + 459 + for (i = 0; i < ARRAY_SIZE(exposed_hooks); i++) { 460 + skel = cgroup_getset_retval_hooks__open(); 461 + if (!ASSERT_OK_PTR(skel, "cgroup_getset_retval_hooks__open")) 462 + continue; 463 + 464 + prog = bpf_object__find_program_by_name(skel->obj, exposed_hooks[i].name); 465 + if (!ASSERT_NEQ(prog, NULL, "bpf_object__find_program_by_name")) 466 + goto close_skel; 467 + 468 + err = bpf_program__set_autoload(prog, true); 469 + if (!ASSERT_OK(err, "bpf_program__set_autoload")) 470 + goto close_skel; 471 + 472 + err = cgroup_getset_retval_hooks__load(skel); 473 + ASSERT_EQ(err, exposed_hooks[i].expected_err, "expected_err"); 474 + 475 + close_skel: 476 + cgroup_getset_retval_hooks__destroy(skel); 477 + } 478 + } 479 + 437 480 void test_cgroup_getset_retval(void) 438 481 { 439 482 int cgroup_fd = -1; ··· 520 475 521 476 if (test__start_subtest("getsockopt-retval_sync")) 522 477 test_getsockopt_retval_sync(cgroup_fd, sock_fd); 478 + 479 + if (test__start_subtest("exposed_hooks")) 480 + test_exposed_hooks(cgroup_fd, sock_fd); 523 481 524 482 close_fd: 525 483 close(cgroup_fd);
+16
tools/testing/selftests/bpf/progs/cgroup_getset_retval_hooks.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + 3 + #include <linux/bpf.h> 4 + #include <bpf/bpf_helpers.h> 5 + 6 + #define BPF_RETVAL_HOOK(name, section, ctx, expected_err) \ 7 + __attribute__((__section__("?" section))) \ 8 + int name(struct ctx *_ctx) \ 9 + { \ 10 + bpf_set_retval(bpf_get_retval()); \ 11 + return 1; \ 12 + } 13 + 14 + #include "cgroup_getset_retval_hooks.h" 15 + 16 + #undef BPF_RETVAL_HOOK