AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/08/07 22:56 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "KMSANReasoning": "",
  "NeedsKMSAN": false,
  "Reasoning": "The patch only modifies userspace selftests (tools/testing/selftests/net/ipv6_flowlabel_mgr.c and ipv6_flowlabel.sh) by rewriting the test to use the kselftest harness. It does not make any functional changes to the kernel code itself.",
  "WorthFuzzing": false
}

1/1 2026/08/07 22:56 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 31866571fbbccfbda06c9954ea7ac92d7970417c\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Fri Aug 7 22:56:02 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/tools/testing/selftests/net/ipv6_flowlabel.sh b/tools/testing/selftests/net/ipv6_flowlabel.sh\nindex cee95e252bee5..2eeda39bf64cb 100755\n--- a/tools/testing/selftests/net/ipv6_flowlabel.sh\n+++ b/tools/testing/selftests/net/ipv6_flowlabel.sh\n@@ -8,7 +8,7 @@\n set -e\n \n echo \"TEST management\"\n-./in_netns.sh ./ipv6_flowlabel_mgr\n+./ipv6_flowlabel_mgr\n \n echo \"TEST datapath\"\n ./in_netns.sh \\\ndiff --git a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c b/tools/testing/selftests/net/ipv6_flowlabel_mgr.c\nindex af95b48acea90..072fb3a9b1217 100644\n--- a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c\n+++ b/tools/testing/selftests/net/ipv6_flowlabel_mgr.c\n@@ -6,45 +6,36 @@\n #include \u003carpa/inet.h\u003e\n #include \u003cerror.h\u003e\n #include \u003cerrno.h\u003e\n+#include \u003cfcntl.h\u003e\n #include \u003climits.h\u003e\n #include \u003clinux/in6.h\u003e\n+#include \u003cnet/if.h\u003e\n+#include \u003csched.h\u003e\n #include \u003cstdbool.h\u003e\n #include \u003cstdio.h\u003e\n #include \u003cstdint.h\u003e\n #include \u003cstdlib.h\u003e\n #include \u003cstring.h\u003e\n+#include \u003csys/ioctl.h\u003e\n #include \u003csys/socket.h\u003e\n #include \u003csys/stat.h\u003e\n #include \u003csys/time.h\u003e\n #include \u003csys/types.h\u003e\n #include \u003csys/wait.h\u003e\n #include \u003cunistd.h\u003e\n+#include \"kselftest_harness.h\"\n \n /* uapi/glibc weirdness may leave this undefined */\n #ifndef IPV6_FLOWLABEL_MGR\n #define IPV6_FLOWLABEL_MGR\t32\n #endif\n+#ifndef IPV6_FLOWINFO_SEND\n+#define IPV6_FLOWINFO_SEND\t33\n+#endif\n \n /* from net/ipv6/ip6_flowlabel.c */\n #define FL_MIN_LINGER\t\t6\n \n-#define explain(x)\t\t\t\t\t\t\t\\\n-\tdo { if (cfg_verbose) fprintf(stderr, \"       \" x \"\\n\"); } while (0)\n-\n-#define __expect(x)\t\t\t\t\t\t\t\\\n-\tdo {\t\t\t\t\t\t\t\t\\\n-\t\tif (!(x))\t\t\t\t\t\t\\\n-\t\t\tfprintf(stderr, \"[OK]   \" #x \"\\n\");\t\t\\\n-\t\telse\t\t\t\t\t\t\t\\\n-\t\t\terror(1, 0, \"[ERR]  \" #x \" (line %d)\", __LINE__); \\\n-\t} while (0)\n-\n-#define expect_pass(x)\t__expect(x)\n-#define expect_fail(x)\t__expect(!(x))\n-\n-static bool cfg_long_running;\n-static bool cfg_verbose;\n-\n static int flowlabel_get(int fd, uint32_t label, uint8_t share, uint16_t flags)\n {\n \tstruct in6_flowlabel_req req = {\n@@ -71,129 +62,484 @@ static int flowlabel_put(int fd, uint32_t label)\n \treturn setsockopt(fd, SOL_IPV6, IPV6_FLOWLABEL_MGR, \u0026req, sizeof(req));\n }\n \n-static void run_tests(int fd)\n+static int flowlabel_renew(int fd, uint32_t label, uint8_t share,\n+\t\t\t   uint16_t linger)\n {\n-\tint wstatus;\n-\tpid_t pid;\n+\tstruct in6_flowlabel_req req = {\n+\t\t.flr_action = IPV6_FL_A_RENEW,\n+\t\t.flr_label = htonl(label),\n+\t\t.flr_share = share,\n+\t\t.flr_linger = linger,\n+\t};\n+\n+\treturn setsockopt(fd, SOL_IPV6, IPV6_FLOWLABEL_MGR, \u0026req, sizeof(req));\n+}\n+\n+static struct sockaddr_in6 loopback_addr(void)\n+{\n+\tstruct sockaddr_in6 addr = {\n+\t\t.sin6_family\t= AF_INET6,\n+\t\t.sin6_addr\t= IN6ADDR_LOOPBACK_INIT,\n+\t\t.sin6_port\t= htons(8888),\n+\t};\n+\n+\treturn addr;\n+}\n+\n+static int tcp_listen(void)\n+{\n+\tstruct sockaddr_in6 addr = loopback_addr();\n+\tconst int one = 1;\n+\tint fd;\n+\n+\tfd = socket(PF_INET6, SOCK_STREAM, 0);\n+\tif (fd == -1)\n+\t\terror(1, errno, \"socket listener\");\n+\tif (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, \u0026one, sizeof(one)))\n+\t\terror(1, errno, \"setsockopt SO_REUSEADDR\");\n+\tif (bind(fd, (void *)\u0026addr, sizeof(addr)))\n+\t\terror(1, errno, \"bind\");\n+\tif (listen(fd, 1))\n+\t\terror(1, errno, \"listen\");\n+\n+\treturn fd;\n+}\n+\n+static void tcp_connect(int listener, uint32_t flowlabel,\n+\t\t\tint *client, int *accepted)\n+{\n+\tstruct sockaddr_in6 addr = loopback_addr();\n+\tconst int one = 1;\n+\tint cfd, afd;\n+\n+\tcfd = socket(PF_INET6, SOCK_STREAM, 0);\n+\tif (cfd == -1)\n+\t\terror(1, errno, \"socket client\");\n+\n+\tif (flowlabel_get(cfd, flowlabel, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE))\n+\t\terror(1, errno, \"flowlabel_get\");\n+\tif (setsockopt(cfd, SOL_IPV6, IPV6_FLOWINFO_SEND, \u0026one, sizeof(one)))\n+\t\terror(1, errno, \"setsockopt flowinfo_send\");\n+\taddr.sin6_flowinfo = htonl(flowlabel);\n+\n+\tif (connect(cfd, (void *)\u0026addr, sizeof(addr)))\n+\t\terror(1, errno, \"connect\");\n+\n+\tafd = accept(listener, NULL, NULL);\n+\tif (afd == -1)\n+\t\terror(1, errno, \"accept\");\n+\n+\tif (flowlabel_put(cfd, flowlabel))\n+\t\terror(1, errno, \"flowlabel_put\");\n+\n+\t*client = cfd;\n+\t*accepted = afd;\n+}\n+\n+static int bringup_loopback(void)\n+{\n+\tstruct ifreq ifr = {\n+\t\t.ifr_name = \"lo\"\n+\t};\n+\tint fd;\n+\n+\tfd = socket(AF_LOCAL, SOCK_STREAM, 0);\n+\tif (fd \u003c 0)\n+\t\treturn -1;\n+\n+\tif (ioctl(fd, SIOCGIFFLAGS, \u0026ifr) \u003c 0)\n+\t\tgoto err;\n+\n+\tifr.ifr_flags = ifr.ifr_flags | IFF_UP;\n+\n+\tif (ioctl(fd, SIOCSIFFLAGS, \u0026ifr) \u003c 0)\n+\t\tgoto err;\n+\n+\tclose(fd);\n+\treturn 0;\n \n-\texplain(\"cannot get non-existent label\");\n-\texpect_fail(flowlabel_get(fd, 1, IPV6_FL_S_ANY, 0));\n-\n-\texplain(\"cannot put non-existent label\");\n-\texpect_fail(flowlabel_put(fd, 1));\n-\n-\texplain(\"cannot create label greater than 20 bits\");\n-\texpect_fail(flowlabel_get(fd, 0x1FFFFF, IPV6_FL_S_ANY,\n-\t\t\t\t  IPV6_FL_F_CREATE));\n-\n-\texplain(\"create a new label (FL_F_CREATE)\");\n-\texpect_pass(flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE));\n-\texplain(\"can get the label (without FL_F_CREATE)\");\n-\texpect_pass(flowlabel_get(fd, 1, IPV6_FL_S_ANY, 0));\n-\texplain(\"can get it again with create flag set, too\");\n-\texpect_pass(flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE));\n-\texplain(\"cannot get it again with the exclusive (FL_FL_EXCL) flag\");\n-\texpect_fail(flowlabel_get(fd, 1, IPV6_FL_S_ANY,\n-\t\t\t\t\t IPV6_FL_F_CREATE | IPV6_FL_F_EXCL));\n-\texplain(\"can now put exactly three references\");\n-\texpect_pass(flowlabel_put(fd, 1));\n-\texpect_pass(flowlabel_put(fd, 1));\n-\texpect_pass(flowlabel_put(fd, 1));\n-\texpect_fail(flowlabel_put(fd, 1));\n-\n-\texplain(\"create a new exclusive label (FL_S_EXCL)\");\n-\texpect_pass(flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE));\n-\texplain(\"cannot get it again in non-exclusive mode\");\n-\texpect_fail(flowlabel_get(fd, 2, IPV6_FL_S_ANY,  IPV6_FL_F_CREATE));\n-\texplain(\"cannot get it again in exclusive mode either\");\n-\texpect_fail(flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE));\n-\texpect_pass(flowlabel_put(fd, 2));\n-\n-\tif (cfg_long_running) {\n-\t\texplain(\"cannot reuse the label, due to linger\");\n-\t\texpect_fail(flowlabel_get(fd, 2, IPV6_FL_S_ANY,\n-\t\t\t\t\t  IPV6_FL_F_CREATE));\n-\t\texplain(\"after sleep, can reuse\");\n-\t\tsleep(FL_MIN_LINGER * 2 + 1);\n-\t\texpect_pass(flowlabel_get(fd, 2, IPV6_FL_S_ANY,\n-\t\t\t\t\t  IPV6_FL_F_CREATE));\n+err:\n+\tclose(fd);\n+\treturn -1;\n+}\n+\n+FIXTURE(flowlabel) {};\n+\n+FIXTURE_SETUP(flowlabel)\n+{\n+\tint ret;\n+\n+\tret = unshare(CLONE_NEWNET);\n+\tASSERT_EQ(ret, 0) {\n+\t\tTH_LOG(\"unshare(CLONE_NEWNET) failed: %s\", strerror(errno));\n \t}\n \n-\texplain(\"create a new user-private label (FL_S_USER)\");\n-\texpect_pass(flowlabel_get(fd, 3, IPV6_FL_S_USER, IPV6_FL_F_CREATE));\n-\texplain(\"cannot get it again in non-exclusive mode\");\n-\texpect_fail(flowlabel_get(fd, 3, IPV6_FL_S_ANY, 0));\n-\texplain(\"cannot get it again in exclusive mode\");\n-\texpect_fail(flowlabel_get(fd, 3, IPV6_FL_S_EXCL, 0));\n-\texplain(\"can get it again in user mode\");\n-\texpect_pass(flowlabel_get(fd, 3, IPV6_FL_S_USER, 0));\n-\texplain(\"child process can get it too, but not after setuid(nobody)\");\n+\tret = bringup_loopback();\n+\tASSERT_EQ(ret, 0) TH_LOG(\"Failed to bring up loopback interface\");\n+}\n+\n+FIXTURE_TEARDOWN(flowlabel)\n+{\n+}\n+\n+TEST_F(flowlabel, cannot_get_non_existent_label)\n+{\n+\tint fd, err;\n+\n+\tfd = socket(PF_INET6, SOCK_DGRAM, 0);\n+\tASSERT_GE(fd, 0) TH_LOG(\"socket failed\");\n+\n+\terr = flowlabel_get(fd, 9, IPV6_FL_S_ANY, 0);\n+\tEXPECT_TRUE(err) TH_LOG(\"expected get of a non-existent label to fail\");\n+\tEXPECT_EQ(ENOENT, errno) TH_LOG(\"expected ENOENT, got %d\", errno);\n+\n+\tEXPECT_EQ(0, close(fd));\n+}\n+\n+TEST_F(flowlabel, cannot_put_non_existent_label)\n+{\n+\tint fd, err;\n+\n+\tfd = socket(PF_INET6, SOCK_DGRAM, 0);\n+\tASSERT_GE(fd, 0) TH_LOG(\"socket failed\");\n+\n+\terr = flowlabel_put(fd, 10);\n+\tEXPECT_TRUE(err) TH_LOG(\"expected put of a non-existent label to fail\");\n+\tEXPECT_EQ(ESRCH, errno) TH_LOG(\"expected ESRCH, got %d\", errno);\n+\n+\tEXPECT_EQ(0, close(fd));\n+}\n+\n+TEST_F(flowlabel, cannot_create_label_greater_than_20_bits)\n+{\n+\tint fd, err;\n+\n+\tfd = socket(PF_INET6, SOCK_DGRAM, 0);\n+\tASSERT_GE(fd, 0) TH_LOG(\"socket failed\");\n+\n+\terr = flowlabel_get(fd, 0x1FFFFF, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);\n+\tEXPECT_TRUE(err) TH_LOG(\"expected label \u003e 20 bits to be rejected\");\n+\tEXPECT_EQ(EINVAL, errno) TH_LOG(\"expected EINVAL, got %d\", errno);\n+\n+\tEXPECT_EQ(0, close(fd));\n+}\n+\n+TEST_F(flowlabel, can_create_and_get_and_put_labels)\n+{\n+\tint fd, err;\n+\n+\tfd = socket(PF_INET6, SOCK_DGRAM, 0);\n+\tASSERT_GE(fd, 0) TH_LOG(\"socket failed\");\n+\n+\terr = flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);\n+\tEXPECT_TRUE(!err) TH_LOG(\"failed to create label (FL_F_CREATE)\");\n+\n+\terr = flowlabel_get(fd, 1, IPV6_FL_S_ANY, 0);\n+\tEXPECT_TRUE(!err) TH_LOG(\"failed to get the label without FL_F_CREATE\");\n+\n+\terr = flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);\n+\tEXPECT_TRUE(!err)\n+\t\tTH_LOG(\"failed to get it again with create flag set, too\");\n+\n+\terr = flowlabel_get(fd, 1, IPV6_FL_S_ANY,\n+\t\t\t    IPV6_FL_F_CREATE | IPV6_FL_F_EXCL);\n+\tEXPECT_TRUE(err)\n+\t\tTH_LOG(\"expected FL_F_EXCL to reject existing label\");\n+\tEXPECT_EQ(EEXIST, errno) TH_LOG(\"expected EEXIST, got %d\", errno);\n+\n+\terr = flowlabel_put(fd, 1);\n+\tEXPECT_TRUE(!err) TH_LOG(\"failed to put first reference\");\n+\terr = flowlabel_put(fd, 1);\n+\tEXPECT_TRUE(!err) TH_LOG(\"failed to put second reference\");\n+\terr = flowlabel_put(fd, 1);\n+\tEXPECT_TRUE(!err) TH_LOG(\"failed to put third reference\");\n+\terr = flowlabel_put(fd, 1);\n+\tEXPECT_TRUE(err)\n+\t\tTH_LOG(\"expected fourth put to fail, no references left\");\n+\tEXPECT_EQ(ESRCH, errno) TH_LOG(\"expected ESRCH, got %d\", errno);\n+\n+\tEXPECT_EQ(0, close(fd));\n+}\n+\n+TEST_F(flowlabel, exclusive_label_share)\n+{\n+\tint fd, err;\n+\n+\tfd = socket(PF_INET6, SOCK_DGRAM, 0);\n+\tASSERT_GE(fd, 0) TH_LOG(\"socket failed\");\n+\n+\terr = flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE);\n+\tEXPECT_TRUE(!err)\n+\t\tTH_LOG(\"failed to create a new exclusive label (FL_S_EXCL)\");\n+\n+\terr = flowlabel_get(fd, 2, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);\n+\tEXPECT_TRUE(err) TH_LOG(\"expected reuse in non-exclusive mode to fail\");\n+\tEXPECT_EQ(EPERM, errno) TH_LOG(\"expected EPERM, got %d\", errno);\n+\n+\terr = flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE);\n+\tEXPECT_TRUE(err) TH_LOG(\"expected reuse in exclusive mode to fail too\");\n+\tEXPECT_EQ(EPERM, errno) TH_LOG(\"expected EPERM, got %d\", errno);\n+\n+\terr = flowlabel_put(fd, 2);\n+\tEXPECT_TRUE(!err) TH_LOG(\"failed to put the exclusive label\");\n+\n+\terr = flowlabel_get(fd, 2, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);\n+\tEXPECT_TRUE(err) TH_LOG(\"expected reuse to fail, due to linger\");\n+\tEXPECT_EQ(EPERM, errno) TH_LOG(\"expected EPERM, got %d\", errno);\n+\n+\tsleep(FL_MIN_LINGER * 2 + 1);\n+\n+\terr = flowlabel_get(fd, 2, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);\n+\tEXPECT_TRUE(!err) TH_LOG(\"expected reuse to succeed after linger\");\n+\n+\tEXPECT_EQ(0, close(fd));\n+}\n+\n+TEST_F(flowlabel, user_private_label_share)\n+{\n+\tint fd, err, wstatus;\n+\tpid_t pid;\n+\n+\tfd = socket(PF_INET6, SOCK_DGRAM, 0);\n+\tASSERT_GE(fd, 0) TH_LOG(\"socket failed\");\n+\n+\terr = flowlabel_get(fd, 3, IPV6_FL_S_USER, IPV6_FL_F_CREATE);\n+\tEXPECT_TRUE(!err)\n+\t\tTH_LOG(\"failed to create a new user-private label (FL_S_USER)\");\n+\n+\terr = flowlabel_get(fd, 3, IPV6_FL_S_ANY, 0);\n+\tEXPECT_TRUE(err) TH_LOG(\"expected get in non-exclusive mode to fail\");\n+\tEXPECT_EQ(EPERM, errno) TH_LOG(\"expected EPERM, got %d\", errno);\n+\n+\terr = flowlabel_get(fd, 3, IPV6_FL_S_EXCL, 0);\n+\tEXPECT_TRUE(err) TH_LOG(\"expected get in exclusive mode to fail\");\n+\tEXPECT_EQ(EPERM, errno) TH_LOG(\"expected EPERM, got %d\", errno);\n+\n+\terr = flowlabel_get(fd, 3, IPV6_FL_S_USER, 0);\n+\tEXPECT_TRUE(!err) TH_LOG(\"failed to get it again in user mode\");\n+\n \tpid = fork();\n-\tif (pid == -1)\n-\t\terror(1, errno, \"fork\");\n+\tASSERT_NE(-1, pid) TH_LOG(\"fork failed\");\n \tif (!pid) {\n-\t\texpect_pass(flowlabel_get(fd, 3, IPV6_FL_S_USER, 0));\n+\t\terr = flowlabel_get(fd, 3, IPV6_FL_S_USER, 0);\n+\t\tEXPECT_TRUE(!err)\n+\t\t\tTH_LOG(\"child failed to get the user-private label\");\n+\n \t\tif (setuid(USHRT_MAX))\n-\t\t\tfprintf(stderr, \"[INFO] skip setuid child test\\n\");\n-\t\telse\n-\t\t\texpect_fail(flowlabel_get(fd, 3, IPV6_FL_S_USER, 0));\n+\t\t\texit(KSFT_SKIP);\n+\n+\t\terr = flowlabel_get(fd, 3, IPV6_FL_S_USER, 0);\n+\t\tEXPECT_TRUE(err)\n+\t\t\tTH_LOG(\"child unexpectedly got label after setuid\");\n+\t\tEXPECT_EQ(EPERM, errno) TH_LOG(\"expected EPERM, got %d\", errno);\n \t\texit(0);\n \t}\n-\tif (wait(\u0026wstatus) == -1)\n-\t\terror(1, errno, \"wait\");\n-\tif (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0)\n-\t\terror(1, errno, \"wait: unexpected child result\");\n-\n-\texplain(\"create a new process-private label (FL_S_PROCESS)\");\n-\texpect_pass(flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, IPV6_FL_F_CREATE));\n-\texplain(\"can get it again\");\n-\texpect_pass(flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0));\n-\texplain(\"child process cannot can get it\");\n+\tASSERT_EQ(pid, wait(\u0026wstatus)) TH_LOG(\"wait failed\");\n+\tASSERT_TRUE(WIFEXITED(wstatus)) TH_LOG(\"child did not exit normally\");\n+\tif (WEXITSTATUS(wstatus) == KSFT_SKIP)\n+\t\tSKIP(return,\n+\t\t     \"setuid(USHRT_MAX) unavailable (no CAP_SETUID or uid unmapped)\");\n+\tEXPECT_EQ(0, WEXITSTATUS(wstatus))\n+\t\tTH_LOG(\"child reported unexpected result\");\n+\n+\tEXPECT_EQ(0, close(fd));\n+}\n+\n+TEST_F(flowlabel, process_private_label_share)\n+{\n+\tint fd, err, wstatus;\n+\tpid_t pid;\n+\n+\tfd = socket(PF_INET6, SOCK_DGRAM, 0);\n+\tASSERT_GE(fd, 0) TH_LOG(\"socket failed\");\n+\n+\terr = flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, IPV6_FL_F_CREATE);\n+\tEXPECT_TRUE(!err)\n+\t\tTH_LOG(\"failed to create a new process-private label\");\n+\n+\terr = flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0);\n+\tEXPECT_TRUE(!err) TH_LOG(\"failed to get it again\");\n+\n \tpid = fork();\n-\tif (pid == -1)\n-\t\terror(1, errno, \"fork\");\n+\tASSERT_NE(-1, pid) TH_LOG(\"fork failed\");\n \tif (!pid) {\n-\t\texpect_fail(flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0));\n+\t\terr = flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0);\n+\t\tEXPECT_TRUE(err)\n+\t\t\tTH_LOG(\"child unexpectedly got process-private label\");\n+\t\tEXPECT_EQ(EPERM, errno) TH_LOG(\"expected EPERM, got %d\", errno);\n \t\texit(0);\n \t}\n-\tif (wait(\u0026wstatus) == -1)\n-\t\terror(1, errno, \"wait\");\n-\tif (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0)\n-\t\terror(1, errno, \"wait: unexpected child result\");\n-}\n-\n-static void parse_opts(int argc, char **argv)\n-{\n-\tint c;\n-\n-\twhile ((c = getopt(argc, argv, \"lv\")) != -1) {\n-\t\tswitch (c) {\n-\t\tcase 'l':\n-\t\t\tcfg_long_running = true;\n-\t\t\tbreak;\n-\t\tcase 'v':\n-\t\t\tcfg_verbose = true;\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\terror(1, 0, \"%s: parse error\", argv[0]);\n-\t\t}\n-\t}\n+\tASSERT_EQ(pid, wait(\u0026wstatus)) TH_LOG(\"wait failed\");\n+\tASSERT_TRUE(WIFEXITED(wstatus)) TH_LOG(\"child did not exit normally\");\n+\tEXPECT_EQ(0, WEXITSTATUS(wstatus))\n+\t\tTH_LOG(\"child reported unexpected result\");\n+\n+\tEXPECT_EQ(0, close(fd));\n }\n \n-int main(int argc, char **argv)\n+TEST_F(flowlabel, cannot_renew_non_existent_label)\n {\n-\tint fd;\n+\tint fd, err;\n+\n+\tfd = socket(PF_INET6, SOCK_DGRAM, 0);\n+\tASSERT_GE(fd, 0) TH_LOG(\"socket failed\");\n+\n+\terr = flowlabel_renew(fd, 5, IPV6_FL_S_EXCL,\n+\t\t\t      2 * (FL_MIN_LINGER * 2 + 1));\n+\tEXPECT_TRUE(err)\n+\t\tTH_LOG(\"expected renew of a non-existent label to fail\");\n+\tEXPECT_EQ(ESRCH, errno) TH_LOG(\"expected ESRCH, got %d\", errno);\n \n-\tparse_opts(argc, argv);\n+\tEXPECT_EQ(0, close(fd));\n+}\n+\n+TEST_F(flowlabel, can_renew_existing_label)\n+{\n+\tint fd, err;\n \n \tfd = socket(PF_INET6, SOCK_DGRAM, 0);\n+\tASSERT_GE(fd, 0) TH_LOG(\"socket failed\");\n+\n+\terr = flowlabel_get(fd, 5, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE);\n+\tEXPECT_TRUE(!err)\n+\t\tTH_LOG(\"failed to create a new label for renew validation\");\n+\n+\terr = flowlabel_renew(fd, 5, IPV6_FL_S_EXCL,\n+\t\t\t      2 * (FL_MIN_LINGER * 2 + 1));\n+\tEXPECT_TRUE(!err) TH_LOG(\"failed to renew an existing valid label\");\n+\n+\terr = flowlabel_put(fd, 5);\n+\tEXPECT_TRUE(!err) TH_LOG(\"failed to put the label\");\n+\n+\tEXPECT_EQ(0, close(fd));\n+}\n+\n+TEST_F(flowlabel, renew_label_linger)\n+{\n+\t/* RENEW must extend a label's linger period: putting a renewed\n+\t * label and waiting out its original linger time must not be\n+\t * enough to allow the label to be recreated.\n+\t */\n+\tint fd, err;\n+\n+\tfd = socket(PF_INET6, SOCK_DGRAM, 0);\n+\tASSERT_GE(fd, 0) TH_LOG(\"socket failed\");\n+\n+\terr = flowlabel_get(fd, 6, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE);\n+\tEXPECT_TRUE(!err)\n+\t\tTH_LOG(\"failed to create label with FL_MIN_LINGER linger time\");\n+\n+\terr = flowlabel_renew(fd, 6, IPV6_FL_S_EXCL,\n+\t\t\t      2 * (FL_MIN_LINGER * 2 + 1));\n+\tEXPECT_TRUE(!err)\n+\t\tTH_LOG(\"failed to renew the label to increase its linger time\");\n+\n+\terr = flowlabel_put(fd, 6);\n+\tEXPECT_TRUE(!err) TH_LOG(\"failed to put the label\");\n+\n+\tsleep(FL_MIN_LINGER * 2 + 1);\n+\n+\terr = flowlabel_get(fd, 6, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);\n+\tEXPECT_TRUE(err)\n+\t\tTH_LOG(\"expected reuse to fail, new linger time not over yet\");\n+\tEXPECT_EQ(EPERM, errno) TH_LOG(\"expected EPERM, got %d\", errno);\n+\n+\tEXPECT_EQ(0, close(fd));\n+}\n+\n+TEST_F(flowlabel, remote_flag)\n+{\n+\t/* The REMOTE flag, used for getsockopt, is expected to retrieve the\n+\t * label from the latest received header.\n+\t */\n+\tstruct in6_flowlabel_req freq = {\n+\t\t.flr_action = IPV6_FL_A_GET,\n+\t\t.flr_flags = IPV6_FL_F_REMOTE,\n+\t};\n+\tsocklen_t freq_len = sizeof(freq);\n+\tint listener, cfd, afd, err;\n+\n+\tlistener = tcp_listen();\n+\ttcp_connect(listener, 7, \u0026cfd, \u0026afd);\n+\n+\terr = getsockopt(afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, \u0026freq, \u0026freq_len);\n+\tEXPECT_TRUE(!err) TH_LOG(\"getsockopt with IPV6_FL_F_REMOTE failed\");\n+\tEXPECT_EQ(7, ntohl(freq.flr_label))\n+\t\tTH_LOG(\"unexpected remote flow label\");\n+\n+\tEXPECT_EQ(0, close(afd));\n+\tEXPECT_EQ(0, close(cfd));\n+\tEXPECT_EQ(0, close(listener));\n+}\n+\n+static bool disable_flowlabel_consistency(void)\n+{\n+\tint fd;\n+\n+\tfd = open(\"/proc/sys/net/ipv6/flowlabel_consistency\", O_WRONLY);\n \tif (fd == -1)\n-\t\terror(1, errno, \"socket\");\n+\t\treturn false;\n \n-\trun_tests(fd);\n+\tif (write(fd, \"0\", 1) != 1) {\n+\t\tclose(fd);\n+\t\treturn false;\n+\t}\n+\tclose(fd);\n \n-\tif (close(fd))\n-\t\terror(1, errno, \"close\");\n+\treturn true;\n+}\n \n-\treturn 0;\n+TEST_F(flowlabel, reflect_flag)\n+{\n+\t/* The REFLECT flag acts as a trigger to the REPFLOW bit. When REPFLOW\n+\t * is triggered for a socket, it adopts the label received from the\n+\t * connected socket.\n+\t */\n+\tstruct in6_flowlabel_req reflect_on = {\n+\t\t.flr_action = IPV6_FL_A_GET,\n+\t\t.flr_flags = IPV6_FL_F_REFLECT,\n+\t};\n+\tstruct in6_flowlabel_req reflect_query = {\n+\t\t.flr_action = IPV6_FL_A_GET,\n+\t};\n+\tstruct in6_flowlabel_req reflect_off = {\n+\t\t.flr_action = IPV6_FL_A_PUT,\n+\t\t.flr_flags = IPV6_FL_F_REFLECT,\n+\t};\n+\tsocklen_t reflect_query_len = sizeof(reflect_query);\n+\tint listener, cfd, afd, err;\n+\n+\tif (!disable_flowlabel_consistency())\n+\t\tSKIP(return,\n+\t\t     \"cannot disable net.ipv6.flowlabel_consistency\");\n+\n+\tlistener = tcp_listen();\n+\terr = setsockopt(listener, SOL_IPV6, IPV6_FLOWLABEL_MGR,\n+\t\t\t \u0026reflect_on, sizeof(reflect_on));\n+\tEXPECT_TRUE(!err) TH_LOG(\"failed to enable REFLECT on the listener\");\n+\n+\ttcp_connect(listener, 8, \u0026cfd, \u0026afd);\n+\n+\terr = getsockopt(afd, SOL_IPV6, IPV6_FLOWLABEL_MGR,\n+\t\t\t \u0026reflect_query, \u0026reflect_query_len);\n+\tEXPECT_TRUE(!err)\n+\t\tTH_LOG(\"failed to query the accepted socket's outgoing label\");\n+\tEXPECT_EQ(8, ntohl(reflect_query.flr_label))\n+\t\tTH_LOG(\"accepted socket did not reflect client's label\");\n+\n+\terr = setsockopt(afd, SOL_IPV6, IPV6_FLOWLABEL_MGR,\n+\t\t\t \u0026reflect_off, sizeof(reflect_off));\n+\tEXPECT_TRUE(!err)\n+\t\tTH_LOG(\"failed to disable REFLECT on the accepted socket\");\n+\n+\terr = setsockopt(afd, SOL_IPV6, IPV6_FLOWLABEL_MGR,\n+\t\t\t \u0026reflect_off, sizeof(reflect_off));\n+\tEXPECT_TRUE(err) TH_LOG(\"expected disabling REFLECT twice to fail\");\n+\tEXPECT_EQ(ESRCH, errno) TH_LOG(\"expected ESRCH, got %d\", errno);\n+\n+\tEXPECT_EQ(0, close(afd));\n+\tEXPECT_EQ(0, close(cfd));\n+\tEXPECT_EQ(0, close(listener));\n }\n+\n+TEST_HARNESS_MAIN\n"
}

2/1 2026/08/07 22:56 agent patch-evaluator
0m Model:
best-expensive

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch only modifies userspace selftests (tools/testing/selftests/net/ipv6_flowlabel_mgr.c and ipv6_flowlabel.sh) by rewriting the test to use the kselftest harness. It does not make any functional changes to the kernel code itself.",
  "WorthFuzzing": false
}

Instruction:
You are an expert Linux kernel maintainer.
Your job is to review a provided patch series and determine
if it makes functional changes to the kernel that should be fuzzed.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively
use your code access tools to examine the actual source code and confirm any assumptions.

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
  even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).
- Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed,
  ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU.
- Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove)
  that are executed only during PCI hot-unplug or sysfs driver unbind operations.

If it modifies reachable core kernel logic, drivers, or architectures, use your code search
tools to verify the code can be executed, then return WorthFuzzing=true.

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
   Prefer non-static, non-inlined API entrypoint functions over internal static helper functions
   (which are inlined by the compiler and do not have distinct symbol addresses).
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs
   needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs
   output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
For your convenience, here is the diff of the changes:
commit 31866571fbbccfbda06c9954ea7ac92d7970417c
Author: syz-cluster <triage@syzkaller.com>
Date:   Fri Aug 7 22:56:02 2026 +0000

    syz-cluster: applied patch under review

diff --git a/tools/testing/selftests/net/ipv6_flowlabel.sh b/tools/testing/selftests/net/ipv6_flowlabel.sh
index cee95e252bee5..2eeda39bf64cb 100755
--- a/tools/testing/selftests/net/ipv6_flowlabel.sh
+++ b/tools/testing/selftests/net/ipv6_flowlabel.sh
@@ -8,7 +8,7 @@
 set -e
 
 echo "TEST management"
-./in_netns.sh ./ipv6_flowlabel_mgr
+./ipv6_flowlabel_mgr
 
 echo "TEST datapath"
 ./in_netns.sh \
diff --git a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c b/tools/testing/selftests/net/ipv6_flowlabel_mgr.c
index af95b48acea90..072fb3a9b1217 100644
--- a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c
+++ b/tools/testing/selftests/net/ipv6_flowlabel_mgr.c
@@ -6,45 +6,36 @@
 #include <arpa/inet.h>
 #include <error.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <limits.h>
 #include <linux/in6.h>
+#include <net/if.h>
+#include <sched.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include "kselftest_harness.h"
 
 /* uapi/glibc weirdness may leave this undefined */
 #ifndef IPV6_FLOWLABEL_MGR
 #define IPV6_FLOWLABEL_MGR	32
 #endif
+#ifndef IPV6_FLOWINFO_SEND
+#define IPV6_FLOWINFO_SEND	33
+#endif
 
 /* from net/ipv6/ip6_flowlabel.c */
 #define FL_MIN_LINGER		6
 
-#define explain(x)							\
-	do { if (cfg_verbose) fprintf(stderr, "       " x "\n"); } while (0)
-
-#define __expect(x)							\
-	do {								\
-		if (!(x))						\
-			fprintf(stderr, "[OK]   " #x "\n");		\
-		else							\
-			error(1, 0, "[ERR]  " #x " (line %d)", __LINE__); \
-	} while (0)
-
-#define expect_pass(x)	__expect(x)
-#define expect_fail(x)	__expect(!(x))
-
-static bool cfg_long_running;
-static bool cfg_verbose;
-
 static int flowlabel_get(int fd, uint32_t label, uint8_t share, uint16_t flags)
 {
 	struct in6_flowlabel_req req = {
@@ -71,129 +62,484 @@ static int flowlabel_put(int fd, uint32_t label)
 	return setsockopt(fd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &req, sizeof(req));
 }
 
-static void run_tests(int fd)
+static int flowlabel_renew(int fd, uint32_t label, uint8_t share,
+			   uint16_t linger)
 {
-	int wstatus;
-	pid_t pid;
+	struct in6_flowlabel_req req = {
+		.flr_action = IPV6_FL_A_RENEW,
+		.flr_label = htonl(label),
+		.flr_share = share,
+		.flr_linger = linger,
+	};
+
+	return setsockopt(fd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &req, sizeof(req));
+}
+
+static struct sockaddr_in6 loopback_addr(void)
+{
+	struct sockaddr_in6 addr = {
+		.sin6_family	= AF_INET6,
+		.sin6_addr	= IN6ADDR_LOOPBACK_INIT,
+		.sin6_port	= htons(8888),
+	};
+
+	return addr;
+}
+
+static int tcp_listen(void)
+{
+	struct sockaddr_in6 addr = loopback_addr();
+	const int one = 1;
+	int fd;
+
+	fd = socket(PF_INET6, SOCK_STREAM, 0);
+	if (fd == -1)
+		error(1, errno, "socket listener");
+	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)))
+		error(1, errno, "setsockopt SO_REUSEADDR");
+	if (bind(fd, (void *)&addr, sizeof(addr)))
+		error(1, errno, "bind");
+	if (listen(fd, 1))
+		error(1, errno, "listen");
+
+	return fd;
+}
+
+static void tcp_connect(int listener, uint32_t flowlabel,
+			int *client, int *accepted)
+{
+	struct sockaddr_in6 addr = loopback_addr();
+	const int one = 1;
+	int cfd, afd;
+
+	cfd = socket(PF_INET6, SOCK_STREAM, 0);
+	if (cfd == -1)
+		error(1, errno, "socket client");
+
+	if (flowlabel_get(cfd, flowlabel, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE))
+		error(1, errno, "flowlabel_get");
+	if (setsockopt(cfd, SOL_IPV6, IPV6_FLOWINFO_SEND, &one, sizeof(one)))
+		error(1, errno, "setsockopt flowinfo_send");
+	addr.sin6_flowinfo = htonl(flowlabel);
+
+	if (connect(cfd, (void *)&addr, sizeof(addr)))
+		error(1, errno, "connect");
+
+	afd = accept(listener, NULL, NULL);
+	if (afd == -1)
+		error(1, errno, "accept");
+
+	if (flowlabel_put(cfd, flowlabel))
+		error(1, errno, "flowlabel_put");
+
+	*client = cfd;
+	*accepted = afd;
+}
+
+static int bringup_loopback(void)
+{
+	struct ifreq ifr = {
+		.ifr_name = "lo"
+	};
+	int fd;
+
+	fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+	if (fd < 0)
+		return -1;
+
+	if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
+		goto err;
+
+	ifr.ifr_flags = ifr.ifr_flags | IFF_UP;
+
+	if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0)
+		goto err;
+
+	close(fd);
+	return 0;
 
-	explain("cannot get non-existent label");
-	expect_fail(flowlabel_get(fd, 1, IPV6_FL_S_ANY, 0));
-
-	explain("cannot put non-existent label");
-	expect_fail(flowlabel_put(fd, 1));
-
-	explain("cannot create label greater than 20 bits");
-	expect_fail(flowlabel_get(fd, 0x1FFFFF, IPV6_FL_S_ANY,
-				  IPV6_FL_F_CREATE));
-
-	explain("create a new label (FL_F_CREATE)");
-	expect_pass(flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE));
-	explain("can get the label (without FL_F_CREATE)");
-	expect_pass(flowlabel_get(fd, 1, IPV6_FL_S_ANY, 0));
-	explain("can get it again with create flag set, too");
-	expect_pass(flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE));
-	explain("cannot get it again with the exclusive (FL_FL_EXCL) flag");
-	expect_fail(flowlabel_get(fd, 1, IPV6_FL_S_ANY,
-					 IPV6_FL_F_CREATE | IPV6_FL_F_EXCL));
-	explain("can now put exactly three references");
-	expect_pass(flowlabel_put(fd, 1));
-	expect_pass(flowlabel_put(fd, 1));
-	expect_pass(flowlabel_put(fd, 1));
-	expect_fail(flowlabel_put(fd, 1));
-
-	explain("create a new exclusive label (FL_S_EXCL)");
-	expect_pass(flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE));
-	explain("cannot get it again in non-exclusive mode");
-	expect_fail(flowlabel_get(fd, 2, IPV6_FL_S_ANY,  IPV6_FL_F_CREATE));
-	explain("cannot get it again in exclusive mode either");
-	expect_fail(flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE));
-	expect_pass(flowlabel_put(fd, 2));
-
-	if (cfg_long_running) {
-		explain("cannot reuse the label, due to linger");
-		expect_fail(flowlabel_get(fd, 2, IPV6_FL_S_ANY,
-					  IPV6_FL_F_CREATE));
-		explain("after sleep, can reuse");
-		sleep(FL_MIN_LINGER * 2 + 1);
-		expect_pass(flowlabel_get(fd, 2, IPV6_FL_S_ANY,
-					  IPV6_FL_F_CREATE));
+err:
+	close(fd);
+	return -1;
+}
+
+FIXTURE(flowlabel) {};
+
+FIXTURE_SETUP(flowlabel)
+{
+	int ret;
+
+	ret = unshare(CLONE_NEWNET);
+	ASSERT_EQ(ret, 0) {
+		TH_LOG("unshare(CLONE_NEWNET) failed: %s", strerror(errno));
 	}
 
-	explain("create a new user-private label (FL_S_USER)");
-	expect_pass(flowlabel_get(fd, 3, IPV6_FL_S_USER, IPV6_FL_F_CREATE));
-	explain("cannot get it again in non-exclusive mode");
-	expect_fail(flowlabel_get(fd, 3, IPV6_FL_S_ANY, 0));
-	explain("cannot get it again in exclusive mode");
-	expect_fail(flowlabel_get(fd, 3, IPV6_FL_S_EXCL, 0));
-	explain("can get it again in user mode");
-	expect_pass(flowlabel_get(fd, 3, IPV6_FL_S_USER, 0));
-	explain("child process can get it too, but not after setuid(nobody)");
+	ret = bringup_loopback();
+	ASSERT_EQ(ret, 0) TH_LOG("Failed to bring up loopback interface");
+}
+
+FIXTURE_TEARDOWN(flowlabel)
+{
+}
+
+TEST_F(flowlabel, cannot_get_non_existent_label)
+{
+	int fd, err;
+
+	fd = socket(PF_INET6, SOCK_DGRAM, 0);
+	ASSERT_GE(fd, 0) TH_LOG("socket failed");
+
+	err = flowlabel_get(fd, 9, IPV6_FL_S_ANY, 0);
+	EXPECT_TRUE(err) TH_LOG("expected get of a non-existent label to fail");
+	EXPECT_EQ(ENOENT, errno) TH_LOG("expected ENOENT, got %d", errno);
+
+	EXPECT_EQ(0, close(fd));
+}
+
+TEST_F(flowlabel, cannot_put_non_existent_label)
+{
+	int fd, err;
+
+	fd = socket(PF_INET6, SOCK_DGRAM, 0);
+	ASSERT_GE(fd, 0) TH_LOG("socket failed");
+
+	err = flowlabel_put(fd, 10);
+	EXPECT_TRUE(err) TH_LOG("expected put of a non-existent label to fail");
+	EXPECT_EQ(ESRCH, errno) TH_LOG("expected ESRCH, got %d", errno);
+
+	EXPECT_EQ(0, close(fd));
+}
+
+TEST_F(flowlabel, cannot_create_label_greater_than_20_bits)
+{
+	int fd, err;
+
+	fd = socket(PF_INET6, SOCK_DGRAM, 0);
+	ASSERT_GE(fd, 0) TH_LOG("socket failed");
+
+	err = flowlabel_get(fd, 0x1FFFFF, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);
+	EXPECT_TRUE(err) TH_LOG("expected label > 20 bits to be rejected");
+	EXPECT_EQ(EINVAL, errno) TH_LOG("expected EINVAL, got %d", errno);
+
+	EXPECT_EQ(0, close(fd));
+}
+
+TEST_F(flowlabel, can_create_and_get_and_put_labels)
+{
+	int fd, err;
+
+	fd = socket(PF_INET6, SOCK_DGRAM, 0);
+	ASSERT_GE(fd, 0) TH_LOG("socket failed");
+
+	err = flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);
+	EXPECT_TRUE(!err) TH_LOG("failed to create label (FL_F_CREATE)");
+
+	err = flowlabel_get(fd, 1, IPV6_FL_S_ANY, 0);
+	EXPECT_TRUE(!err) TH_LOG("failed to get the label without FL_F_CREATE");
+
+	err = flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);
+	EXPECT_TRUE(!err)
+		TH_LOG("failed to get it again with create flag set, too");
+
+	err = flowlabel_get(fd, 1, IPV6_FL_S_ANY,
+			    IPV6_FL_F_CREATE | IPV6_FL_F_EXCL);
+	EXPECT_TRUE(err)
+		TH_LOG("expected FL_F_EXCL to reject existing label");
+	EXPECT_EQ(EEXIST, errno) TH_LOG("expected EEXIST, got %d", errno);
+
+	err = flowlabel_put(fd, 1);
+	EXPECT_TRUE(!err) TH_LOG("failed to put first reference");
+	err = flowlabel_put(fd, 1);
+	EXPECT_TRUE(!err) TH_LOG("failed to put second reference");
+	err = flowlabel_put(fd, 1);
+	EXPECT_TRUE(!err) TH_LOG("failed to put third reference");
+	err = flowlabel_put(fd, 1);
+	EXPECT_TRUE(err)
+		TH_LOG("expected fourth put to fail, no references left");
+	EXPECT_EQ(ESRCH, errno) TH_LOG("expected ESRCH, got %d", errno);
+
+	EXPECT_EQ(0, close(fd));
+}
+
+TEST_F(flowlabel, exclusive_label_share)
+{
+	int fd, err;
+
+	fd = socket(PF_INET6, SOCK_DGRAM, 0);
+	ASSERT_GE(fd, 0) TH_LOG("socket failed");
+
+	err = flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE);
+	EXPECT_TRUE(!err)
+		TH_LOG("failed to create a new exclusive label (FL_S_EXCL)");
+
+	err = flowlabel_get(fd, 2, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);
+	EXPECT_TRUE(err) TH_LOG("expected reuse in non-exclusive mode to fail");
+	EXPECT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno);
+
+	err = flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE);
+	EXPECT_TRUE(err) TH_LOG("expected reuse in exclusive mode to fail too");
+	EXPECT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno);
+
+	err = flowlabel_put(fd, 2);
+	EXPECT_TRUE(!err) TH_LOG("failed to put the exclusive label");
+
+	err = flowlabel_get(fd, 2, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);
+	EXPECT_TRUE(err) TH_LOG("expected reuse to fail, due to linger");
+	EXPECT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno);
+
+	sleep(FL_MIN_LINGER * 2 + 1);
+
+	err = flowlabel_get(fd, 2, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);
+	EXPECT_TRUE(!err) TH_LOG("expected reuse to succeed after linger");
+
+	EXPECT_EQ(0, close(fd));
+}
+
+TEST_F(flowlabel, user_private_label_share)
+{
+	int fd, err, wstatus;
+	pid_t pid;
+
+	fd = socket(PF_INET6, SOCK_DGRAM, 0);
+	ASSERT_GE(fd, 0) TH_LOG("socket failed");
+
+	err = flowlabel_get(fd, 3, IPV6_FL_S_USER, IPV6_FL_F_CREATE);
+	EXPECT_TRUE(!err)
+		TH_LOG("failed to create a new user-private label (FL_S_USER)");
+
+	err = flowlabel_get(fd, 3, IPV6_FL_S_ANY, 0);
+	EXPECT_TRUE(err) TH_LOG("expected get in non-exclusive mode to fail");
+	EXPECT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno);
+
+	err = flowlabel_get(fd, 3, IPV6_FL_S_EXCL, 0);
+	EXPECT_TRUE(err) TH_LOG("expected get in exclusive mode to fail");
+	EXPECT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno);
+
+	err = flowlabel_get(fd, 3, IPV6_FL_S_USER, 0);
+	EXPECT_TRUE(!err) TH_LOG("failed to get it again in user mode");
+
 	pid = fork();
-	if (pid == -1)
-		error(1, errno, "fork");
+	ASSERT_NE(-1, pid) TH_LOG("fork failed");
 	if (!pid) {
-		expect_pass(flowlabel_get(fd, 3, IPV6_FL_S_USER, 0));
+		err = flowlabel_get(fd, 3, IPV6_FL_S_USER, 0);
+		EXPECT_TRUE(!err)
+			TH_LOG("child failed to get the user-private label");
+
 		if (setuid(USHRT_MAX))
-			fprintf(stderr, "[INFO] skip setuid child test\n");
-		else
-			expect_fail(flowlabel_get(fd, 3, IPV6_FL_S_USER, 0));
+			exit(KSFT_SKIP);
+
+		err = flowlabel_get(fd, 3, IPV6_FL_S_USER, 0);
+		EXPECT_TRUE(err)
+			TH_LOG("child unexpectedly got label after setuid");
+		EXPECT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno);
 		exit(0);
 	}
-	if (wait(&wstatus) == -1)
-		error(1, errno, "wait");
-	if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0)
-		error(1, errno, "wait: unexpected child result");
-
-	explain("create a new process-private label (FL_S_PROCESS)");
-	expect_pass(flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, IPV6_FL_F_CREATE));
-	explain("can get it again");
-	expect_pass(flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0));
-	explain("child process cannot can get it");
+	ASSERT_EQ(pid, wait(&wstatus)) TH_LOG("wait failed");
+	ASSERT_TRUE(WIFEXITED(wstatus)) TH_LOG("child did not exit normally");
+	if (WEXITSTATUS(wstatus) == KSFT_SKIP)
+		SKIP(return,
+		     "setuid(USHRT_MAX) unavailable (no CAP_SETUID or uid unmapped)");
+	EXPECT_EQ(0, WEXITSTATUS(wstatus))
+		TH_LOG("child reported unexpected result");
+
+	EXPECT_EQ(0, close(fd));
+}
+
+TEST_F(flowlabel, process_private_label_share)
+{
+	int fd, err, wstatus;
+	pid_t pid;
+
+	fd = socket(PF_INET6, SOCK_DGRAM, 0);
+	ASSERT_GE(fd, 0) TH_LOG("socket failed");
+
+	err = flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, IPV6_FL_F_CREATE);
+	EXPECT_TRUE(!err)
+		TH_LOG("failed to create a new process-private label");
+
+	err = flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0);
+	EXPECT_TRUE(!err) TH_LOG("failed to get it again");
+
 	pid = fork();
-	if (pid == -1)
-		error(1, errno, "fork");
+	ASSERT_NE(-1, pid) TH_LOG("fork failed");
 	if (!pid) {
-		expect_fail(flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0));
+		err = flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0);
+		EXPECT_TRUE(err)
+			TH_LOG("child unexpectedly got process-private label");
+		EXPECT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno);
 		exit(0);
 	}
-	if (wait(&wstatus) == -1)
-		error(1, errno, "wait");
-	if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) != 0)
-		error(1, errno, "wait: unexpected child result");
-}
-
-static void parse_opts(int argc, char **argv)
-{
-	int c;
-
-	while ((c = getopt(argc, argv, "lv")) != -1) {
-		switch (c) {
-		case 'l':
-			cfg_long_running = true;
-			break;
-		case 'v':
-			cfg_verbose = true;
-			break;
-		default:
-			error(1, 0, "%s: parse error", argv[0]);
-		}
-	}
+	ASSERT_EQ(pid, wait(&wstatus)) TH_LOG("wait failed");
+	ASSERT_TRUE(WIFEXITED(wstatus)) TH_LOG("child did not exit normally");
+	EXPECT_EQ(0, WEXITSTATUS(wstatus))
+		TH_LOG("child reported unexpected result");
+
+	EXPECT_EQ(0, close(fd));
 }
 
-int main(int argc, char **argv)
+TEST_F(flowlabel, cannot_renew_non_existent_label)
 {
-	int fd;
+	int fd, err;
+
+	fd = socket(PF_INET6, SOCK_DGRAM, 0);
+	ASSERT_GE(fd, 0) TH_LOG("socket failed");
+
+	err = flowlabel_renew(fd, 5, IPV6_FL_S_EXCL,
+			      2 * (FL_MIN_LINGER * 2 + 1));
+	EXPECT_TRUE(err)
+		TH_LOG("expected renew of a non-existent label to fail");
+	EXPECT_EQ(ESRCH, errno) TH_LOG("expected ESRCH, got %d", errno);
 
-	parse_opts(argc, argv);
+	EXPECT_EQ(0, close(fd));
+}
+
+TEST_F(flowlabel, can_renew_existing_label)
+{
+	int fd, err;
 
 	fd = socket(PF_INET6, SOCK_DGRAM, 0);
+	ASSERT_GE(fd, 0) TH_LOG("socket failed");
+
+	err = flowlabel_get(fd, 5, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE);
+	EXPECT_TRUE(!err)
+		TH_LOG("failed to create a new label for renew validation");
+
+	err = flowlabel_renew(fd, 5, IPV6_FL_S_EXCL,
+			      2 * (FL_MIN_LINGER * 2 + 1));
+	EXPECT_TRUE(!err) TH_LOG("failed to renew an existing valid label");
+
+	err = flowlabel_put(fd, 5);
+	EXPECT_TRUE(!err) TH_LOG("failed to put the label");
+
+	EXPECT_EQ(0, close(fd));
+}
+
+TEST_F(flowlabel, renew_label_linger)
+{
+	/* RENEW must extend a label's linger period: putting a renewed
+	 * label and waiting out its original linger time must not be
+	 * enough to allow the label to be recreated.
+	 */
+	int fd, err;
+
+	fd = socket(PF_INET6, SOCK_DGRAM, 0);
+	ASSERT_GE(fd, 0) TH_LOG("socket failed");
+
+	err = flowlabel_get(fd, 6, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE);
+	EXPECT_TRUE(!err)
+		TH_LOG("failed to create label with FL_MIN_LINGER linger time");
+
+	err = flowlabel_renew(fd, 6, IPV6_FL_S_EXCL,
+			      2 * (FL_MIN_LINGER * 2 + 1));
+	EXPECT_TRUE(!err)
+		TH_LOG("failed to renew the label to increase its linger time");
+
+	err = flowlabel_put(fd, 6);
+	EXPECT_TRUE(!err) TH_LOG("failed to put the label");
+
+	sleep(FL_MIN_LINGER * 2 + 1);
+
+	err = flowlabel_get(fd, 6, IPV6_FL_S_ANY, IPV6_FL_F_CREATE);
+	EXPECT_TRUE(err)
+		TH_LOG("expected reuse to fail, new linger time not over yet");
+	EXPECT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno);
+
+	EXPECT_EQ(0, close(fd));
+}
+
+TEST_F(flowlabel, remote_flag)
+{
+	/* The REMOTE flag, used for getsockopt, is expected to retrieve the
+	 * label from the latest received header.
+	 */
+	struct in6_flowlabel_req freq = {
+		.flr_action = IPV6_FL_A_GET,
+		.flr_flags = IPV6_FL_F_REMOTE,
+	};
+	socklen_t freq_len = sizeof(freq);
+	int listener, cfd, afd, err;
+
+	listener = tcp_listen();
+	tcp_connect(listener, 7, &cfd, &afd);
+
+	err = getsockopt(afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &freq, &freq_len);
+	EXPECT_TRUE(!err) TH_LOG("getsockopt with IPV6_FL_F_REMOTE failed");
+	EXPECT_EQ(7, ntohl(freq.flr_label))
+		TH_LOG("unexpected remote flow label");
+
+	EXPECT_EQ(0, close(afd));
+	EXPECT_EQ(0, close(cfd));
+	EXPECT_EQ(0, close(listener));
+}
+
+static bool disable_flowlabel_consistency(void)
+{
+	int fd;
+
+	fd = open("/proc/sys/net/ipv6/flowlabel_consistency", O_WRONLY);
 	if (fd == -1)
-		error(1, errno, "socket");
+		return false;
 
-	run_tests(fd);
+	if (write(fd, "0", 1) != 1) {
+		close(fd);
+		return false;
+	}
+	close(fd);
 
-	if (close(fd))
-		error(1, errno, "close");
+	return true;
+}
 
-	return 0;
+TEST_F(flowlabel, reflect_flag)
+{
+	/* The REFLECT flag acts as a trigger to the REPFLOW bit. When REPFLOW
+	 * is triggered for a socket, it adopts the label received from the
+	 * connected socket.
+	 */
+	struct in6_flowlabel_req reflect_on = {
+		.flr_action = IPV6_FL_A_GET,
+		.flr_flags = IPV6_FL_F_REFLECT,
+	};
+	struct in6_flowlabel_req reflect_query = {
+		.flr_action = IPV6_FL_A_GET,
+	};
+	struct in6_flowlabel_req reflect_off = {
+		.flr_action = IPV6_FL_A_PUT,
+		.flr_flags = IPV6_FL_F_REFLECT,
+	};
+	socklen_t reflect_query_len = sizeof(reflect_query);
+	int listener, cfd, afd, err;
+
+	if (!disable_flowlabel_consistency())
+		SKIP(return,
+		     "cannot disable net.ipv6.flowlabel_consistency");
+
+	listener = tcp_listen();
+	err = setsockopt(listener, SOL_IPV6, IPV6_FLOWLABEL_MGR,
+			 &reflect_on, sizeof(reflect_on));
+	EXPECT_TRUE(!err) TH_LOG("failed to enable REFLECT on the listener");
+
+	tcp_connect(listener, 8, &cfd, &afd);
+
+	err = getsockopt(afd, SOL_IPV6, IPV6_FLOWLABEL_MGR,
+			 &reflect_query, &reflect_query_len);
+	EXPECT_TRUE(!err)
+		TH_LOG("failed to query the accepted socket's outgoing label");
+	EXPECT_EQ(8, ntohl(reflect_query.flr_label))
+		TH_LOG("accepted socket did not reflect client's label");
+
+	err = setsockopt(afd, SOL_IPV6, IPV6_FLOWLABEL_MGR,
+			 &reflect_off, sizeof(reflect_off));
+	EXPECT_TRUE(!err)
+		TH_LOG("failed to disable REFLECT on the accepted socket");
+
+	err = setsockopt(afd, SOL_IPV6, IPV6_FLOWLABEL_MGR,
+			 &reflect_off, sizeof(reflect_off));
+	EXPECT_TRUE(err) TH_LOG("expected disabling REFLECT twice to fail");
+	EXPECT_EQ(ESRCH, errno) TH_LOG("expected ESRCH, got %d", errno);
+
+	EXPECT_EQ(0, close(afd));
+	EXPECT_EQ(0, close(cfd));
+	EXPECT_EQ(0, close(listener));
 }
+
+TEST_HARNESS_MAIN

3/2 2026/08/07 22:56 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 10181
							output: 94
							thoughts: 667
						

Thoughts:
**WorthFuzzing=false: IPv6 Flow Label Selftest Patch Analysis**

Okay, so I'm looking at this patch and my initial thought is, "Hmm, `ipv6_flowlabel.sh` and `ipv6_flowlabel_mgr.c` are being touched."  I need to figure out if this means we should fuzz based on this, or not. The patch seems to be rewriting the `ipv6_flowlabel_mgr.c` test using `kselftest_harness.h` and removing that `in_netns.sh` wrapper, since it's now handling the network namespace unsharing itself.

First instinct is to check if kernel code is changed. Let's see...  Nope, the diff is only in `tools/testing/selftests/net/ipv6_flowlabel.sh` and `tools/testing/selftests/net/ipv6_flowlabel_mgr.c`. Nothing in the core kernel.

The instructions say to return `WorthFuzzing=false` under certain conditions. They list things like documentation, comments, decorative changes, unreachable code, etc.  It doesn't *explicitly* mention `tools/testing/selftests/`, but common sense tells me selftests are *userspace* tests, not kernel code. They don't affect the kernel's execution flow directly.  A change to a test doesn't mean we need to fuzz the kernel itself.

Just to be absolutely sure, I'm quickly confirming there are *no* other files changed. Nope, just those two.

Therefore, this patch is a no-go for fuzzing. It's strictly about modifying the selftests, specifically to use a different testing framework. It does *not* modify any kernel code or introduce any functional changes that warrant fuzzing.

My conclusion is: `WorthFuzzing=false`. Time to call set-results.



4/2 2026/08/07 22:56 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch only modifies userspace selftests (tools/testing/selftests/net/ipv6_flowlabel_mgr.c and ipv6_flowlabel.sh) by rewriting the test to use the kselftest harness. It does not make any functional changes to the kernel code itself.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch only modifies userspace selftests (tools/testing/selftests/net/ipv6_flowlabel_mgr.c and ipv6_flowlabel.sh) by rewriting the test to use the kselftest harness. It does not make any functional changes to the kernel code itself.",
  "WorthFuzzing": false
}

5/1 2026/08/07 22:56 action If
0m Args:
{
  "WorthFuzzing": false
}

Results:
null

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)