]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
selftest: bpf: Add test for bpf_tcp_sock() and RAW socket.
authorKuniyuki Iwashima <kuniyu@google.com>
Mon, 4 May 2026 21:04:49 +0000 (21:04 +0000)
committerMartin KaFai Lau <martin.lau@kernel.org>
Fri, 8 May 2026 18:38:08 +0000 (11:38 -0700)
Let's extend sockopt_sk.c to cover bpf_tcp_sock() for the
wrong socket type.

Before:
  # ./test_progs -t sockopt_sk
  [  151.948613] ==================================================================
  [  151.951376] BUG: KASAN: slab-out-of-bounds in sol_tcp_sockopt+0xc7/0x8e0
  [  151.954159] Read of size 8 at addr ffff88801083d760 by task test_progs/1259
  ...
  run_test:FAIL:getsetsockopt unexpected error: -1 (errno 0)
  #427     sockopt_sk:FAIL

After:
  #427     sockopt_sk:OK

While at it, missing free() is fixed up.

Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://patch.msgid.link/20260504210610.180150-3-kuniyu@google.com
tools/testing/selftests/bpf/prog_tests/sockopt_sk.c
tools/testing/selftests/bpf/progs/sockopt_sk.c

index 53637431ec5de3b78ed41813ff1f42897e645158..3a41c517b9182b43bf48ef501526e4be7cc2b6fa 100644 (file)
@@ -190,7 +190,7 @@ static int getsetsockopt(void)
        fd = socket(AF_NETLINK, SOCK_RAW, 0);
        if (fd < 0) {
                log_err("Failed to create AF_NETLINK socket");
-               return -1;
+               goto err;
        }
 
        buf.u32 = 1;
@@ -211,6 +211,21 @@ static int getsetsockopt(void)
        }
        ASSERT_EQ(optlen, 8, "Unexpected NETLINK_LIST_MEMBERSHIPS value");
 
+       /* Trick bpf_tcp_sock() with IPPROTO_TCP */
+       close(fd);
+       fd = socket(AF_INET, SOCK_RAW, IPPROTO_TCP);
+       if (!ASSERT_OK_FD(fd, "socket"))
+               goto err;
+
+       /* The BPF prog intercepts this before the kernel sees it, any
+        * optlen works. Go with 4 bytes for simplicity.
+        */
+       buf.u32 = 1;
+       optlen = sizeof(buf.u32);
+       err = setsockopt(fd, SOL_TCP, TCP_SAVED_SYN, &buf, optlen);
+       if (!ASSERT_ERR(err, "setsockopt(TCP_SAVED_SYN)"))
+               goto err;
+
        free(big_buf);
        close(fd);
        return 0;
index cb990a7d3d4586431339860a0546d5e0a29822d9..5e0b27e7855cb8ad3bd2d132dc46828c55352ba3 100644 (file)
@@ -149,6 +149,20 @@ int _setsockopt(struct bpf_sockopt *ctx)
        if (sk && sk->family == AF_NETLINK)
                goto out;
 
+       if (sk && sk->family == AF_INET && sk->type == SOCK_RAW) {
+               struct bpf_tcp_sock *tp = bpf_tcp_sock(sk);
+
+               if (tp) {
+                       char saved_syn[60];
+
+                       bpf_getsockopt(sk, SOL_TCP, TCP_SAVED_SYN,
+                                      &saved_syn, sizeof(saved_syn));
+                       goto consumed;
+               }
+
+               goto out;
+       }
+
        /* Make sure bpf_get_netns_cookie is callable.
         */
        if (bpf_get_netns_cookie(NULL) == 0)
@@ -224,6 +238,8 @@ int _setsockopt(struct bpf_sockopt *ctx)
                return 0; /* couldn't get sk storage */
 
        storage->val = optval[0];
+
+consumed:
        ctx->optlen = -1; /* BPF has consumed this option, don't call kernel
                           * setsockopt handler.
                           */