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

selftests/bpf: Check bpf_sk_storage has uncharged sk_omem_alloc

This patch checks the sk_omem_alloc has been uncharged by bpf_sk_storage
during the __sk_destruct.

Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20230901231129.578493-4-martin.lau@linux.dev

authored by

Martin KaFai Lau and committed by
Daniel Borkmann
a96d1cfb 55d49f75

+118
+56
tools/testing/selftests/bpf/prog_tests/sk_storage_omem_uncharge.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2023 Facebook */ 3 + #include <test_progs.h> 4 + #include <bpf/libbpf.h> 5 + #include <sys/types.h> 6 + #include <sys/socket.h> 7 + #include "sk_storage_omem_uncharge.skel.h" 8 + 9 + void test_sk_storage_omem_uncharge(void) 10 + { 11 + struct sk_storage_omem_uncharge *skel; 12 + int sk_fd = -1, map_fd, err, value; 13 + socklen_t optlen; 14 + 15 + skel = sk_storage_omem_uncharge__open_and_load(); 16 + if (!ASSERT_OK_PTR(skel, "skel open_and_load")) 17 + return; 18 + map_fd = bpf_map__fd(skel->maps.sk_storage); 19 + 20 + /* A standalone socket not binding to addr:port, 21 + * so nentns is not needed. 22 + */ 23 + sk_fd = socket(AF_INET6, SOCK_STREAM, 0); 24 + if (!ASSERT_GE(sk_fd, 0, "socket")) 25 + goto done; 26 + 27 + optlen = sizeof(skel->bss->cookie); 28 + err = getsockopt(sk_fd, SOL_SOCKET, SO_COOKIE, &skel->bss->cookie, &optlen); 29 + if (!ASSERT_OK(err, "getsockopt(SO_COOKIE)")) 30 + goto done; 31 + 32 + value = 0; 33 + err = bpf_map_update_elem(map_fd, &sk_fd, &value, 0); 34 + if (!ASSERT_OK(err, "bpf_map_update_elem(value=0)")) 35 + goto done; 36 + 37 + value = 0xdeadbeef; 38 + err = bpf_map_update_elem(map_fd, &sk_fd, &value, 0); 39 + if (!ASSERT_OK(err, "bpf_map_update_elem(value=0xdeadbeef)")) 40 + goto done; 41 + 42 + err = sk_storage_omem_uncharge__attach(skel); 43 + if (!ASSERT_OK(err, "attach")) 44 + goto done; 45 + 46 + close(sk_fd); 47 + sk_fd = -1; 48 + 49 + ASSERT_EQ(skel->bss->cookie_found, 2, "cookie_found"); 50 + ASSERT_EQ(skel->bss->omem, 0, "omem"); 51 + 52 + done: 53 + sk_storage_omem_uncharge__destroy(skel); 54 + if (sk_fd != -1) 55 + close(sk_fd); 56 + }
+1
tools/testing/selftests/bpf/progs/bpf_tracing_net.h
··· 88 88 #define sk_v6_rcv_saddr __sk_common.skc_v6_rcv_saddr 89 89 #define sk_flags __sk_common.skc_flags 90 90 #define sk_reuse __sk_common.skc_reuse 91 + #define sk_cookie __sk_common.skc_cookie 91 92 92 93 #define s6_addr32 in6_u.u6_addr32 93 94
+61
tools/testing/selftests/bpf/progs/sk_storage_omem_uncharge.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2023 Facebook */ 3 + #include "vmlinux.h" 4 + #include "bpf_tracing_net.h" 5 + #include <bpf/bpf_helpers.h> 6 + #include <bpf/bpf_tracing.h> 7 + #include <bpf/bpf_core_read.h> 8 + 9 + void *local_storage_ptr = NULL; 10 + void *sk_ptr = NULL; 11 + int cookie_found = 0; 12 + __u64 cookie = 0; 13 + __u32 omem = 0; 14 + 15 + void *bpf_rdonly_cast(void *, __u32) __ksym; 16 + 17 + struct { 18 + __uint(type, BPF_MAP_TYPE_SK_STORAGE); 19 + __uint(map_flags, BPF_F_NO_PREALLOC); 20 + __type(key, int); 21 + __type(value, int); 22 + } sk_storage SEC(".maps"); 23 + 24 + SEC("fexit/bpf_local_storage_destroy") 25 + int BPF_PROG(bpf_local_storage_destroy, struct bpf_local_storage *local_storage) 26 + { 27 + struct sock *sk; 28 + 29 + if (local_storage_ptr != local_storage) 30 + return 0; 31 + 32 + sk = bpf_rdonly_cast(sk_ptr, bpf_core_type_id_kernel(struct sock)); 33 + if (sk->sk_cookie.counter != cookie) 34 + return 0; 35 + 36 + cookie_found++; 37 + omem = sk->sk_omem_alloc.counter; 38 + local_storage_ptr = NULL; 39 + 40 + return 0; 41 + } 42 + 43 + SEC("fentry/inet6_sock_destruct") 44 + int BPF_PROG(inet6_sock_destruct, struct sock *sk) 45 + { 46 + int *value; 47 + 48 + if (!cookie || sk->sk_cookie.counter != cookie) 49 + return 0; 50 + 51 + value = bpf_sk_storage_get(&sk_storage, sk, 0, 0); 52 + if (value && *value == 0xdeadbeef) { 53 + cookie_found++; 54 + sk_ptr = sk; 55 + local_storage_ptr = sk->sk_bpf_storage; 56 + } 57 + 58 + return 0; 59 + } 60 + 61 + char _license[] SEC("license") = "GPL";