selftests/bpf: Check freeing sk->sk_local_storage with sk_local_storage->smap is...
authorMartin KaFai Lau <martin.lau@kernel.org>
Wed, 8 Mar 2023 06:59:35 +0000 (22:59 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 10 Mar 2023 19:06:02 +0000 (11:06 -0800)
This patch tweats the socket_bind bpf prog to test the
local_storage->smap == NULL case in the bpf_local_storage_free()
code path. The idea is to create the local_storage with
the sk_storage_map's selem first. Then add the sk_storage_map2's selem
and then delete the earlier sk_storeage_map's selem.

Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://lore.kernel.org/r/20230308065936.1550103-17-martin.lau@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/progs/local_storage.c

index 01c74bc870aeafee9d6169d9495004de14d3b068..c8ba7207f5a58054d3d368ccadd1f96d215f1860 100644 (file)
@@ -108,18 +108,17 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,
 {
        __u32 pid = bpf_get_current_pid_tgid() >> 32;
        struct local_storage *storage;
-       int err;
 
        if (pid != monitored_pid)
                return 0;
 
-       storage = bpf_sk_storage_get(&sk_storage_map, sock->sk, 0,
-                                    BPF_LOCAL_STORAGE_GET_F_CREATE);
+       storage = bpf_sk_storage_get(&sk_storage_map, sock->sk, 0, 0);
        if (!storage)
                return 0;
 
+       sk_storage_result = -1;
        if (storage->value != DUMMY_STORAGE_VALUE)
-               sk_storage_result = -1;
+               return 0;
 
        /* This tests that we can associate multiple elements
         * with the local storage.
@@ -129,14 +128,26 @@ int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,
        if (!storage)
                return 0;
 
-       err = bpf_sk_storage_delete(&sk_storage_map, sock->sk);
-       if (err)
+       if (bpf_sk_storage_delete(&sk_storage_map2, sock->sk))
                return 0;
 
-       err = bpf_sk_storage_delete(&sk_storage_map2, sock->sk);
-       if (!err)
-               sk_storage_result = err;
+       storage = bpf_sk_storage_get(&sk_storage_map2, sock->sk, 0,
+                                    BPF_LOCAL_STORAGE_GET_F_CREATE);
+       if (!storage)
+               return 0;
+
+       if (bpf_sk_storage_delete(&sk_storage_map, sock->sk))
+               return 0;
+
+       /* Ensure that the sk_storage_map is disconnected from the storage.
+        * The storage memory should not be freed back to the
+        * bpf_mem_alloc of the sk_bpf_storage_map because
+        * sk_bpf_storage_map may have been gone.
+        */
+       if (!sock->sk->sk_bpf_storage || sock->sk->sk_bpf_storage->smap)
+               return 0;
 
+       sk_storage_result = 0;
        return 0;
 }