AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/06/23 03:34 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [
    "bpf_strpbrk",
    "bpf_memcmp"
  ],
  "Reasoning": "The patch adds two new BPF kfuncs, `bpf_strpbrk` and `bpf_memcmp`, which allow BPF programs to perform string and memory comparisons. These are functional changes to the core BPF helper library and should be fuzzed to ensure they handle various inputs safely, especially since they deal with memory access and potential page faults.",
  "WorthFuzzing": true
}

1/1 2026/06/23 03:34 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 33dd54f2193f5421d17ed6aa3749567f34327422\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Tue Jun 23 03:34:35 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c\nindex b5314c9fed3cf0..f24cfdb22635c7 100644\n--- a/kernel/bpf/helpers.c\n+++ b/kernel/bpf/helpers.c\n@@ -3971,6 +3971,109 @@ __bpf_kfunc int bpf_strcspn(const char *s__ign, const char *reject__ign)\n \treturn -EFAULT;\n }\n \n+/**\n+ * bpf_memcmp - Compare two memory regions byte by byte\n+ * @ptr1__ign: First memory region\n+ * @ptr2__ign: Second memory region\n+ * @size: Number of bytes to compare\n+ *\n+ * Compares the first @size bytes of the memory areas @ptr1__ign and\n+ * @ptr2__ign. Unlike bpf_strcmp, null bytes do not terminate the comparison.\n+ *\n+ * Return:\n+ * * %0       - The memory regions are equal\n+ * * %-1      - @ptr1__ign is less than @ptr2__ign\n+ * * %1       - @ptr1__ign is greater than @ptr2__ign\n+ * * %-EFAULT - Cannot read one of the memory regions\n+ * * %-E2BIG  - @size exceeds the maximum allowed size\n+ * * %-ERANGE - One of the memory regions is outside of kernel address space\n+ */\n+/**\n+ * bpf_strpbrk - Find the first occurrence of a set of characters in a string\n+ * @s__ign: The string to be searched\n+ * @accept__ign: The string containing the characters to search for\n+ *\n+ * Return:\n+ * * \u003e=0      - Index of the first character in @s__ign that matches any\n+ *              character in @accept__ign\n+ * * %-ENOENT - No character of @accept__ign found in @s__ign\n+ * * %-EFAULT - Cannot read one of the strings\n+ * * %-E2BIG  - One of the strings is too large\n+ * * %-ERANGE - One of the strings is outside of kernel address space\n+ */\n+__bpf_kfunc int bpf_strpbrk(const char *s__ign, const char *accept__ign)\n+{\n+\tchar cs, ca;\n+\tint i, j;\n+\n+\tif (!copy_from_kernel_nofault_allowed(s__ign, 1) ||\n+\t    !copy_from_kernel_nofault_allowed(accept__ign, 1)) {\n+\t\treturn -ERANGE;\n+\t}\n+\n+\tguard(pagefault)();\n+\tfor (i = 0; i \u003c XATTR_SIZE_MAX; i++) {\n+\t\t__get_kernel_nofault(\u0026cs, s__ign, char, err_out);\n+\t\tif (cs == '\\0')\n+\t\t\treturn -ENOENT;\n+\t\tfor (j = 0; j \u003c XATTR_SIZE_MAX; j++) {\n+\t\t\t__get_kernel_nofault(\u0026ca, accept__ign + j, char, err_out);\n+\t\t\tif (ca == '\\0')\n+\t\t\t\tbreak;\n+\t\t\tif (cs == ca)\n+\t\t\t\treturn i;\n+\t\t}\n+\t\tif (j == XATTR_SIZE_MAX)\n+\t\t\treturn -E2BIG;\n+\t\ts__ign++;\n+\t}\n+\treturn -E2BIG;\n+err_out:\n+\treturn -EFAULT;\n+}\n+\n+/**\n+ * bpf_memcmp - Compare two memory regions byte by byte\n+ * @ptr1__ign: First memory region\n+ * @ptr2__ign: Second memory region\n+ * @size: Number of bytes to compare\n+ *\n+ * Compares the first @size bytes of the memory areas @ptr1__ign and\n+ * @ptr2__ign. Unlike bpf_strcmp, null bytes do not terminate the comparison.\n+ *\n+ * Return:\n+ * * %0       - The memory regions are equal\n+ * * %-1      - @ptr1__ign is less than @ptr2__ign\n+ * * %1       - @ptr1__ign is greater than @ptr2__ign\n+ * * %-EFAULT - Cannot read one of the memory regions\n+ * * %-E2BIG  - @size exceeds the maximum allowed size\n+ * * %-ERANGE - One of the memory regions is outside of kernel address space\n+ */\n+__bpf_kfunc int bpf_memcmp(const void *ptr1__ign, const void *ptr2__ign,\n+\t\t\t   size_t size)\n+{\n+\tconst char *p1 = ptr1__ign, *p2 = ptr2__ign;\n+\tchar c1, c2;\n+\tsize_t i;\n+\n+\tif (size \u003e XATTR_SIZE_MAX)\n+\t\treturn -E2BIG;\n+\tif (!copy_from_kernel_nofault_allowed(p1, size) ||\n+\t    !copy_from_kernel_nofault_allowed(p2, size))\n+\t\treturn -ERANGE;\n+\n+\tguard(pagefault)();\n+\tfor (i = 0; i \u003c size; i++) {\n+\t\t__get_kernel_nofault(\u0026c1, p1 + i, char, err_out);\n+\t\t__get_kernel_nofault(\u0026c2, p2 + i, char, err_out);\n+\t\tif (c1 != c2)\n+\t\t\treturn c1 \u003c c2 ? -1 : 1;\n+\t}\n+\treturn 0;\n+err_out:\n+\treturn -EFAULT;\n+}\n+\n static int __bpf_strnstr(const char *s1, const char *s2, size_t len,\n \t\t\t bool ignore_case)\n {\n@@ -4850,6 +4953,8 @@ BTF_ID_FLAGS(func, bpf_strlen);\n BTF_ID_FLAGS(func, bpf_strnlen);\n BTF_ID_FLAGS(func, bpf_strspn);\n BTF_ID_FLAGS(func, bpf_strcspn);\n+BTF_ID_FLAGS(func, bpf_strpbrk);\n+BTF_ID_FLAGS(func, bpf_memcmp);\n BTF_ID_FLAGS(func, bpf_strstr);\n BTF_ID_FLAGS(func, bpf_strcasestr);\n BTF_ID_FLAGS(func, bpf_strnstr);\ndiff --git a/tools/testing/selftests/bpf/progs/dynptr_success.c b/tools/testing/selftests/bpf/progs/dynptr_success.c\nindex e0d672d93adf85..071581ff0833f3 100644\n--- a/tools/testing/selftests/bpf/progs/dynptr_success.c\n+++ b/tools/testing/selftests/bpf/progs/dynptr_success.c\n@@ -624,7 +624,7 @@ int BPF_PROG(test_dynptr_skb_tp_btf, void *skb, void *location)\n \treturn 1;\n }\n \n-static inline int bpf_memcmp(const char *a, const char *b, u32 size)\n+static inline int local_memcmp(const char *a, const char *b, u32 size)\n {\n \tint i;\n \n@@ -650,12 +650,12 @@ int test_dynptr_copy(void *ctx)\n \terr = bpf_dynptr_write(\u0026src, 0, data, sz, 0);\n \terr = err ?: bpf_dynptr_copy(\u0026dst, 0, \u0026src, 0, sz);\n \terr = err ?: bpf_dynptr_read(buf, sz, \u0026dst, 0, 0);\n-\terr = err ?: bpf_memcmp(data, buf, sz);\n+\terr = err ?: local_memcmp(data, buf, sz);\n \n \t/* Test that offsets are handled correctly */\n \terr = err ?: bpf_dynptr_copy(\u0026dst, 3, \u0026src, 5, sz - 5);\n \terr = err ?: bpf_dynptr_read(buf, sz - 5, \u0026dst, 3, 0);\n-\terr = err ?: bpf_memcmp(data + 5, buf, sz - 5);\n+\terr = err ?: local_memcmp(data + 5, buf, sz - 5);\n \n \tbpf_ringbuf_discard_dynptr(\u0026src, 0);\n \tbpf_ringbuf_discard_dynptr(\u0026dst, 0);\n@@ -692,7 +692,7 @@ int test_dynptr_copy_xdp(struct xdp_md *xdp)\n \t\terr = bpf_dynptr_read(\u0026buf, len, \u0026ptr_xdp, i * len, 0);\n \t\tif (err)\n \t\t\tgoto out;\n-\t\tif (bpf_memcmp(data, buf, len) != 0)\n+\t\tif (local_memcmp(data, buf, len) != 0)\n \t\t\tgoto out;\n \t}\n \n@@ -713,7 +713,7 @@ int test_dynptr_copy_xdp(struct xdp_md *xdp)\n \t\terr = bpf_dynptr_read(\u0026buf, len, \u0026ptr_buf, i * len, 0);\n \t\tif (err)\n \t\t\tgoto out;\n-\t\tif (bpf_memcmp(data, buf, len) != 0)\n+\t\tif (local_memcmp(data, buf, len) != 0)\n \t\t\tgoto out;\n \t}\n \n@@ -727,7 +727,7 @@ int test_dynptr_copy_xdp(struct xdp_md *xdp)\n \t\terr = bpf_dynptr_read(\u0026buf, len, \u0026ptr_xdp, 2 + i * len, 0);\n \t\tif (err)\n \t\t\tgoto out;\n-\t\tif (bpf_memcmp(data, buf, len) != 0)\n+\t\tif (local_memcmp(data, buf, len) != 0)\n \t\t\tgoto out;\n \t}\n \n@@ -750,7 +750,7 @@ int test_dynptr_memset_zero(void *ctx)\n \n \terr = bpf_dynptr_from_mem(memset_zero_data, data_sz, 0, \u0026ptr);\n \terr = err ?: bpf_dynptr_memset(\u0026ptr, 0, data_sz, 0);\n-\terr = err ?: bpf_memcmp(zeroes, memset_zero_data, data_sz);\n+\terr = err ?: local_memcmp(zeroes, memset_zero_data, data_sz);\n \n \treturn 0;\n }\n@@ -770,7 +770,7 @@ int test_dynptr_memset_notzero(void *ctx)\n \n \terr = bpf_dynptr_from_mem(memset_notzero_data, data_sz, 0, \u0026ptr);\n \terr = err ?: bpf_dynptr_memset(\u0026ptr, 0, data_sz, DYNPTR_MEMSET_VAL);\n-\terr = err ?: bpf_memcmp(expected, memset_notzero_data, data_sz);\n+\terr = err ?: local_memcmp(expected, memset_notzero_data, data_sz);\n \n \treturn 0;\n }\n@@ -786,7 +786,7 @@ int test_dynptr_memset_zero_offset(void *ctx)\n \n \terr = bpf_dynptr_from_mem(memset_zero_offset_data, data_sz, 0, \u0026ptr);\n \terr = err ?: bpf_dynptr_memset(\u0026ptr, 8, 4, 0);\n-\terr = err ?: bpf_memcmp(expected, memset_zero_offset_data, data_sz);\n+\terr = err ?: local_memcmp(expected, memset_zero_offset_data, data_sz);\n \n \treturn 0;\n }\n@@ -803,7 +803,7 @@ int test_dynptr_memset_zero_adjusted(void *ctx)\n \terr = bpf_dynptr_from_mem(memset_zero_adjusted_data, data_sz, 0, \u0026ptr);\n \terr = err ?: bpf_dynptr_adjust(\u0026ptr, 4, 8);\n \terr = err ?: bpf_dynptr_memset(\u0026ptr, 0, bpf_dynptr_size(\u0026ptr), 0);\n-\terr = err ?: bpf_memcmp(expected, memset_zero_adjusted_data, data_sz);\n+\terr = err ?: local_memcmp(expected, memset_zero_adjusted_data, data_sz);\n \n \treturn 0;\n }\n@@ -898,7 +898,7 @@ int test_dynptr_memset_xdp_chunks(struct xdp_md *xdp)\n \t\terr = bpf_dynptr_read(\u0026buf, chunk_sz, \u0026ptr_xdp, offset, 0);\n \t\tif (err)\n \t\t\tgoto out;\n-\t\terr = bpf_memcmp(buf, expected_buf, sizeof(buf));\n+\t\terr = local_memcmp(buf, expected_buf, sizeof(buf));\n \t\tif (err)\n \t\t\tgoto out;\n \t}\n@@ -952,7 +952,7 @@ static __always_inline void test_dynptr_probe(void *ptr, bpf_read_dynptr_fn_t bp\n \t\t\tbreak;\n \t\terr = err ?: bpf_dynptr_read(\u0026buf, len, \u0026ptr_buf, 0, 0);\n \n-\t\tif (err || bpf_memcmp(expected_str, buf, len))\n+\t\tif (err || local_memcmp(expected_str, buf, len))\n \t\t\terr = 1;\n \n \t\t/* Reset buffer and dynptr */\n@@ -986,7 +986,7 @@ static __always_inline void test_dynptr_probe_str(void *ptr,\n \t\terr = err ?: bpf_dynptr_read(\u0026buf, len, \u0026ptr_buf, 0, 0);\n \t\tif (!len)\n \t\t\tcontinue;\n-\t\tif (err || bpf_memcmp(expected_str, buf, len - 1) || buf[len - 1] != '\\0')\n+\t\tif (err || local_memcmp(expected_str, buf, len - 1) || buf[len - 1] != '\\0')\n \t\t\terr = 1;\n \t}\n \tbpf_ringbuf_discard_dynptr(\u0026ptr_buf, 0);\n@@ -1012,7 +1012,7 @@ static __always_inline void test_dynptr_probe_xdp(struct xdp_md *xdp, void *ptr,\n \t\tif (len \u003e sizeof(buf))\n \t\t\tcontinue;\n \t\terr = err ?: bpf_dynptr_read(\u0026buf, len, \u0026ptr_xdp, off, 0);\n-\t\tif (err || bpf_memcmp(expected_str, buf, len))\n+\t\tif (err || local_memcmp(expected_str, buf, len))\n \t\t\terr = 1;\n \t\t/* Reset buffer and dynptr */\n \t\t__builtin_memset(buf, 0, sizeof(buf));\n@@ -1048,7 +1048,7 @@ static __always_inline void test_dynptr_probe_str_xdp(struct xdp_md *xdp, void *\n \n \t\tif (!len)\n \t\t\tcontinue;\n-\t\tif (err || bpf_memcmp(expected_str, buf, len - 1) || buf[len - 1] != '\\0')\n+\t\tif (err || local_memcmp(expected_str, buf, len - 1) || buf[len - 1] != '\\0')\n \t\t\terr = 1;\n \n \t\t__builtin_memset(buf, 0, sizeof(buf));\ndiff --git a/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c b/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c\nindex bddc4e8579d244..e67fe9700e593c 100644\n--- a/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c\n+++ b/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c\n@@ -9,6 +9,10 @@\n char *user_ptr = (char *)1;\n char *invalid_kern_ptr = (char *)-1;\n \n+extern int bpf_strpbrk(const char *s__ign, const char *accept__ign) __ksym;\n+extern int bpf_memcmp(const void *ptr1__ign, const void *ptr2__ign,\n+\t\t      size_t size) __ksym;\n+\n /*\n  * When passing userspace pointers, the error code differs based on arch:\n  *   -ERANGE on arches with non-overlapping address spaces\n@@ -53,6 +57,10 @@ SEC(\"syscall\")  __retval(USER_PTR_ERR)int test_strnstr_null1(void *ctx) { return\n SEC(\"syscall\")  __retval(USER_PTR_ERR)int test_strnstr_null2(void *ctx) { return bpf_strnstr(\"hello\", NULL, 1); }\n SEC(\"syscall\")  __retval(USER_PTR_ERR)int test_strncasestr_null1(void *ctx) { return bpf_strncasestr(NULL, \"hello\", 1); }\n SEC(\"syscall\")  __retval(USER_PTR_ERR)int test_strncasestr_null2(void *ctx) { return bpf_strncasestr(\"hello\", NULL, 1); }\n+SEC(\"syscall\")  __retval(USER_PTR_ERR)int test_memcmp_null1(void *ctx) { return bpf_memcmp(NULL, \"x\", 1); }\n+SEC(\"syscall\")  __retval(USER_PTR_ERR)int test_memcmp_null2(void *ctx) { return bpf_memcmp(\"x\", NULL, 1); }\n+SEC(\"syscall\")  __retval(USER_PTR_ERR)int test_strpbrk_null1(void *ctx) { return bpf_strpbrk(NULL, \"x\"); }\n+SEC(\"syscall\")  __retval(USER_PTR_ERR)int test_strpbrk_null2(void *ctx) { return bpf_strpbrk(\"x\", NULL); }\n \n /* Passing userspace ptr to string kfuncs */\n SEC(\"syscall\") __retval(USER_PTR_ERR) int test_strcmp_user_ptr1(void *ctx) { return bpf_strcmp(user_ptr, \"hello\"); }\n@@ -79,6 +87,10 @@ SEC(\"syscall\") __retval(USER_PTR_ERR) int test_strnstr_user_ptr1(void *ctx) { re\n SEC(\"syscall\") __retval(USER_PTR_ERR) int test_strnstr_user_ptr2(void *ctx) { return bpf_strnstr(\"hello\", user_ptr, 1); }\n SEC(\"syscall\") __retval(USER_PTR_ERR) int test_strncasestr_user_ptr1(void *ctx) { return bpf_strncasestr(user_ptr, \"hello\", 1); }\n SEC(\"syscall\") __retval(USER_PTR_ERR) int test_strncasestr_user_ptr2(void *ctx) { return bpf_strncasestr(\"hello\", user_ptr, 1); }\n+SEC(\"syscall\") __retval(USER_PTR_ERR) int test_memcmp_user_ptr1(void *ctx) { return bpf_memcmp(user_ptr, \"x\", 1); }\n+SEC(\"syscall\") __retval(USER_PTR_ERR) int test_memcmp_user_ptr2(void *ctx) { return bpf_memcmp(\"x\", user_ptr, 1); }\n+SEC(\"syscall\") __retval(USER_PTR_ERR) int test_strpbrk_user_ptr1(void *ctx) { return bpf_strpbrk(user_ptr, \"x\"); }\n+SEC(\"syscall\") __retval(USER_PTR_ERR) int test_strpbrk_user_ptr2(void *ctx) { return bpf_strpbrk(\"x\", user_ptr); }\n \n #endif /* __TARGET_ARCH_s390 */\n \n@@ -107,5 +119,9 @@ SEC(\"syscall\") __retval(-EFAULT) int test_strnstr_pagefault1(void *ctx) { return\n SEC(\"syscall\") __retval(-EFAULT) int test_strnstr_pagefault2(void *ctx) { return bpf_strnstr(\"hello\", invalid_kern_ptr, 1); }\n SEC(\"syscall\") __retval(-EFAULT) int test_strncasestr_pagefault1(void *ctx) { return bpf_strncasestr(invalid_kern_ptr, \"hello\", 1); }\n SEC(\"syscall\") __retval(-EFAULT) int test_strncasestr_pagefault2(void *ctx) { return bpf_strncasestr(\"hello\", invalid_kern_ptr, 1); }\n+SEC(\"syscall\") __retval(-EFAULT) int test_memcmp_pagefault1(void *ctx) { return bpf_memcmp(invalid_kern_ptr, \"x\", 1); }\n+SEC(\"syscall\") __retval(-EFAULT) int test_memcmp_pagefault2(void *ctx) { return bpf_memcmp(\"x\", invalid_kern_ptr, 1); }\n+SEC(\"syscall\") __retval(-EFAULT) int test_strpbrk_pagefault1(void *ctx) { return bpf_strpbrk(invalid_kern_ptr, \"x\"); }\n+SEC(\"syscall\") __retval(-EFAULT) int test_strpbrk_pagefault2(void *ctx) { return bpf_strpbrk(\"x\", invalid_kern_ptr); }\n \n char _license[] SEC(\"license\") = \"GPL\";\ndiff --git a/tools/testing/selftests/bpf/progs/string_kfuncs_success.c b/tools/testing/selftests/bpf/progs/string_kfuncs_success.c\nindex f65b1226a81a37..e67b80ab3cd2c9 100644\n--- a/tools/testing/selftests/bpf/progs/string_kfuncs_success.c\n+++ b/tools/testing/selftests/bpf/progs/string_kfuncs_success.c\n@@ -7,6 +7,10 @@\n \n char str[] = \"hello world\";\n \n+extern int bpf_strpbrk(const char *s__ign, const char *accept__ign) __ksym;\n+extern int bpf_memcmp(const void *ptr1__ign, const void *ptr2__ign,\n+\t\t      size_t size) __ksym;\n+\n #define __test(retval) SEC(\"syscall\") __success __retval(retval)\n \n /* Functional tests */\n@@ -60,4 +64,25 @@ __test(-ENOENT) int test_strncasestr_notfound2(void *ctx) { return bpf_strncases\n __test(-ENOENT) int test_strncasestr_notfound3(void *ctx) { return bpf_strncasestr(\"\", \"a\", 0); }\n __test(0) int test_strncasestr_empty(void *ctx) { return bpf_strncasestr(str, \"\", 1); }\n \n+/* bpf_strpbrk - functional tests */\n+__test(0) int test_strpbrk_found_first(void *ctx) { return bpf_strpbrk(str, \"h\"); }\n+__test(4) int test_strpbrk_found_middle(void *ctx) { return bpf_strpbrk(str, \"ow\"); }\n+__test(6) int test_strpbrk_found_multiple(void *ctx) { return bpf_strpbrk(str, \"w\"); }\n+__test(-ENOENT) int test_strpbrk_notfound(void *ctx) { return bpf_strpbrk(str, \"xyz\"); }\n+__test(-ENOENT) int test_strpbrk_empty_accept(void *ctx) { return bpf_strpbrk(str, \"\"); }\n+\n+/* bpf_memcmp - functional tests */\n+char data1[] = \"hello world\";\n+char data2[] = \"hello world\";\n+char data3[] = \"hello worle\";\n+__test(0) int test_memcmp_eq(void *ctx) { return bpf_memcmp(data1, data2, sizeof(data1)); }\n+__test(-1) int test_memcmp_neq_less(void *ctx) { return bpf_memcmp(data1, data3, sizeof(data1)); }\n+__test(1) int test_memcmp_neq_greater(void *ctx) { return bpf_memcmp(data3, data1, sizeof(data1)); }\n+__test(0) int test_memcmp_size_zero(void *ctx) { return bpf_memcmp(data1, data3, 0); }\n+/* memcmp should NOT stop at null byte - compare past '\\0' */\n+char bin1[] = { 'a', '\\0', 'c' };\n+char bin2[] = { 'a', '\\0', 'd' };\n+__test(0) int test_memcmp_null_byte_eq(void *ctx) { return bpf_memcmp(bin1, bin1, sizeof(bin1)); }\n+__test(-1) int test_memcmp_null_byte_neq(void *ctx) { return bpf_memcmp(bin1, bin2, sizeof(bin1)); }\n+\n char _license[] SEC(\"license\") = \"GPL\";\n"
}

2/1 2026/06/23 03:34 agent patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [
    "bpf_strpbrk",
    "bpf_memcmp"
  ],
  "Reasoning": "The patch adds two new BPF kfuncs, `bpf_strpbrk` and `bpf_memcmp`, which allow BPF programs to perform string and memory comparisons. These are functional changes to the core BPF helper library and should be fuzzed to ensure they handle various inputs safely, especially since they deal with memory access and potential page faults.",
  "WorthFuzzing": true
}

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).

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.
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.
   Do not list too generic configs (we already have them enabled). Only list those that
   specifically cover the modified code. 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 33dd54f2193f5421d17ed6aa3749567f34327422
Author: syz-cluster <triage@syzkaller.com>
Date:   Tue Jun 23 03:34:35 2026 +0000

    syz-cluster: applied patch under review

diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index b5314c9fed3cf0..f24cfdb22635c7 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -3971,6 +3971,109 @@ __bpf_kfunc int bpf_strcspn(const char *s__ign, const char *reject__ign)
 	return -EFAULT;
 }
 
+/**
+ * bpf_memcmp - Compare two memory regions byte by byte
+ * @ptr1__ign: First memory region
+ * @ptr2__ign: Second memory region
+ * @size: Number of bytes to compare
+ *
+ * Compares the first @size bytes of the memory areas @ptr1__ign and
+ * @ptr2__ign. Unlike bpf_strcmp, null bytes do not terminate the comparison.
+ *
+ * Return:
+ * * %0       - The memory regions are equal
+ * * %-1      - @ptr1__ign is less than @ptr2__ign
+ * * %1       - @ptr1__ign is greater than @ptr2__ign
+ * * %-EFAULT - Cannot read one of the memory regions
+ * * %-E2BIG  - @size exceeds the maximum allowed size
+ * * %-ERANGE - One of the memory regions is outside of kernel address space
+ */
+/**
+ * bpf_strpbrk - Find the first occurrence of a set of characters in a string
+ * @s__ign: The string to be searched
+ * @accept__ign: The string containing the characters to search for
+ *
+ * Return:
+ * * >=0      - Index of the first character in @s__ign that matches any
+ *              character in @accept__ign
+ * * %-ENOENT - No character of @accept__ign found in @s__ign
+ * * %-EFAULT - Cannot read one of the strings
+ * * %-E2BIG  - One of the strings is too large
+ * * %-ERANGE - One of the strings is outside of kernel address space
+ */
+__bpf_kfunc int bpf_strpbrk(const char *s__ign, const char *accept__ign)
+{
+	char cs, ca;
+	int i, j;
+
+	if (!copy_from_kernel_nofault_allowed(s__ign, 1) ||
+	    !copy_from_kernel_nofault_allowed(accept__ign, 1)) {
+		return -ERANGE;
+	}
+
+	guard(pagefault)();
+	for (i = 0; i < XATTR_SIZE_MAX; i++) {
+		__get_kernel_nofault(&cs, s__ign, char, err_out);
+		if (cs == '\0')
+			return -ENOENT;
+		for (j = 0; j < XATTR_SIZE_MAX; j++) {
+			__get_kernel_nofault(&ca, accept__ign + j, char, err_out);
+			if (ca == '\0')
+				break;
+			if (cs == ca)
+				return i;
+		}
+		if (j == XATTR_SIZE_MAX)
+			return -E2BIG;
+		s__ign++;
+	}
+	return -E2BIG;
+err_out:
+	return -EFAULT;
+}
+
+/**
+ * bpf_memcmp - Compare two memory regions byte by byte
+ * @ptr1__ign: First memory region
+ * @ptr2__ign: Second memory region
+ * @size: Number of bytes to compare
+ *
+ * Compares the first @size bytes of the memory areas @ptr1__ign and
+ * @ptr2__ign. Unlike bpf_strcmp, null bytes do not terminate the comparison.
+ *
+ * Return:
+ * * %0       - The memory regions are equal
+ * * %-1      - @ptr1__ign is less than @ptr2__ign
+ * * %1       - @ptr1__ign is greater than @ptr2__ign
+ * * %-EFAULT - Cannot read one of the memory regions
+ * * %-E2BIG  - @size exceeds the maximum allowed size
+ * * %-ERANGE - One of the memory regions is outside of kernel address space
+ */
+__bpf_kfunc int bpf_memcmp(const void *ptr1__ign, const void *ptr2__ign,
+			   size_t size)
+{
+	const char *p1 = ptr1__ign, *p2 = ptr2__ign;
+	char c1, c2;
+	size_t i;
+
+	if (size > XATTR_SIZE_MAX)
+		return -E2BIG;
+	if (!copy_from_kernel_nofault_allowed(p1, size) ||
+	    !copy_from_kernel_nofault_allowed(p2, size))
+		return -ERANGE;
+
+	guard(pagefault)();
+	for (i = 0; i < size; i++) {
+		__get_kernel_nofault(&c1, p1 + i, char, err_out);
+		__get_kernel_nofault(&c2, p2 + i, char, err_out);
+		if (c1 != c2)
+			return c1 < c2 ? -1 : 1;
+	}
+	return 0;
+err_out:
+	return -EFAULT;
+}
+
 static int __bpf_strnstr(const char *s1, const char *s2, size_t len,
 			 bool ignore_case)
 {
@@ -4850,6 +4953,8 @@ BTF_ID_FLAGS(func, bpf_strlen);
 BTF_ID_FLAGS(func, bpf_strnlen);
 BTF_ID_FLAGS(func, bpf_strspn);
 BTF_ID_FLAGS(func, bpf_strcspn);
+BTF_ID_FLAGS(func, bpf_strpbrk);
+BTF_ID_FLAGS(func, bpf_memcmp);
 BTF_ID_FLAGS(func, bpf_strstr);
 BTF_ID_FLAGS(func, bpf_strcasestr);
 BTF_ID_FLAGS(func, bpf_strnstr);
diff --git a/tools/testing/selftests/bpf/progs/dynptr_success.c b/tools/testing/selftests/bpf/progs/dynptr_success.c
index e0d672d93adf85..071581ff0833f3 100644
--- a/tools/testing/selftests/bpf/progs/dynptr_success.c
+++ b/tools/testing/selftests/bpf/progs/dynptr_success.c
@@ -624,7 +624,7 @@ int BPF_PROG(test_dynptr_skb_tp_btf, void *skb, void *location)
 	return 1;
 }
 
-static inline int bpf_memcmp(const char *a, const char *b, u32 size)
+static inline int local_memcmp(const char *a, const char *b, u32 size)
 {
 	int i;
 
@@ -650,12 +650,12 @@ int test_dynptr_copy(void *ctx)
 	err = bpf_dynptr_write(&src, 0, data, sz, 0);
 	err = err ?: bpf_dynptr_copy(&dst, 0, &src, 0, sz);
 	err = err ?: bpf_dynptr_read(buf, sz, &dst, 0, 0);
-	err = err ?: bpf_memcmp(data, buf, sz);
+	err = err ?: local_memcmp(data, buf, sz);
 
 	/* Test that offsets are handled correctly */
 	err = err ?: bpf_dynptr_copy(&dst, 3, &src, 5, sz - 5);
 	err = err ?: bpf_dynptr_read(buf, sz - 5, &dst, 3, 0);
-	err = err ?: bpf_memcmp(data + 5, buf, sz - 5);
+	err = err ?: local_memcmp(data + 5, buf, sz - 5);
 
 	bpf_ringbuf_discard_dynptr(&src, 0);
 	bpf_ringbuf_discard_dynptr(&dst, 0);
@@ -692,7 +692,7 @@ int test_dynptr_copy_xdp(struct xdp_md *xdp)
 		err = bpf_dynptr_read(&buf, len, &ptr_xdp, i * len, 0);
 		if (err)
 			goto out;
-		if (bpf_memcmp(data, buf, len) != 0)
+		if (local_memcmp(data, buf, len) != 0)
 			goto out;
 	}
 
@@ -713,7 +713,7 @@ int test_dynptr_copy_xdp(struct xdp_md *xdp)
 		err = bpf_dynptr_read(&buf, len, &ptr_buf, i * len, 0);
 		if (err)
 			goto out;
-		if (bpf_memcmp(data, buf, len) != 0)
+		if (local_memcmp(data, buf, len) != 0)
 			goto out;
 	}
 
@@ -727,7 +727,7 @@ int test_dynptr_copy_xdp(struct xdp_md *xdp)
 		err = bpf_dynptr_read(&buf, len, &ptr_xdp, 2 + i * len, 0);
 		if (err)
 			goto out;
-		if (bpf_memcmp(data, buf, len) != 0)
+		if (local_memcmp(data, buf, len) != 0)
 			goto out;
 	}
 
@@ -750,7 +750,7 @@ int test_dynptr_memset_zero(void *ctx)
 
 	err = bpf_dynptr_from_mem(memset_zero_data, data_sz, 0, &ptr);
 	err = err ?: bpf_dynptr_memset(&ptr, 0, data_sz, 0);
-	err = err ?: bpf_memcmp(zeroes, memset_zero_data, data_sz);
+	err = err ?: local_memcmp(zeroes, memset_zero_data, data_sz);
 
 	return 0;
 }
@@ -770,7 +770,7 @@ int test_dynptr_memset_notzero(void *ctx)
 
 	err = bpf_dynptr_from_mem(memset_notzero_data, data_sz, 0, &ptr);
 	err = err ?: bpf_dynptr_memset(&ptr, 0, data_sz, DYNPTR_MEMSET_VAL);
-	err = err ?: bpf_memcmp(expected, memset_notzero_data, data_sz);
+	err = err ?: local_memcmp(expected, memset_notzero_data, data_sz);
 
 	return 0;
 }
@@ -786,7 +786,7 @@ int test_dynptr_memset_zero_offset(void *ctx)
 
 	err = bpf_dynptr_from_mem(memset_zero_offset_data, data_sz, 0, &ptr);
 	err = err ?: bpf_dynptr_memset(&ptr, 8, 4, 0);
-	err = err ?: bpf_memcmp(expected, memset_zero_offset_data, data_sz);
+	err = err ?: local_memcmp(expected, memset_zero_offset_data, data_sz);
 
 	return 0;
 }
@@ -803,7 +803,7 @@ int test_dynptr_memset_zero_adjusted(void *ctx)
 	err = bpf_dynptr_from_mem(memset_zero_adjusted_data, data_sz, 0, &ptr);
 	err = err ?: bpf_dynptr_adjust(&ptr, 4, 8);
 	err = err ?: bpf_dynptr_memset(&ptr, 0, bpf_dynptr_size(&ptr), 0);
-	err = err ?: bpf_memcmp(expected, memset_zero_adjusted_data, data_sz);
+	err = err ?: local_memcmp(expected, memset_zero_adjusted_data, data_sz);
 
 	return 0;
 }
@@ -898,7 +898,7 @@ int test_dynptr_memset_xdp_chunks(struct xdp_md *xdp)
 		err = bpf_dynptr_read(&buf, chunk_sz, &ptr_xdp, offset, 0);
 		if (err)
 			goto out;
-		err = bpf_memcmp(buf, expected_buf, sizeof(buf));
+		err = local_memcmp(buf, expected_buf, sizeof(buf));
 		if (err)
 			goto out;
 	}
@@ -952,7 +952,7 @@ static __always_inline void test_dynptr_probe(void *ptr, bpf_read_dynptr_fn_t bp
 			break;
 		err = err ?: bpf_dynptr_read(&buf, len, &ptr_buf, 0, 0);
 
-		if (err || bpf_memcmp(expected_str, buf, len))
+		if (err || local_memcmp(expected_str, buf, len))
 			err = 1;
 
 		/* Reset buffer and dynptr */
@@ -986,7 +986,7 @@ static __always_inline void test_dynptr_probe_str(void *ptr,
 		err = err ?: bpf_dynptr_read(&buf, len, &ptr_buf, 0, 0);
 		if (!len)
 			continue;
-		if (err || bpf_memcmp(expected_str, buf, len - 1) || buf[len - 1] != '\0')
+		if (err || local_memcmp(expected_str, buf, len - 1) || buf[len - 1] != '\0')
 			err = 1;
 	}
 	bpf_ringbuf_discard_dynptr(&ptr_buf, 0);
@@ -1012,7 +1012,7 @@ static __always_inline void test_dynptr_probe_xdp(struct xdp_md *xdp, void *ptr,
 		if (len > sizeof(buf))
 			continue;
 		err = err ?: bpf_dynptr_read(&buf, len, &ptr_xdp, off, 0);
-		if (err || bpf_memcmp(expected_str, buf, len))
+		if (err || local_memcmp(expected_str, buf, len))
 			err = 1;
 		/* Reset buffer and dynptr */
 		__builtin_memset(buf, 0, sizeof(buf));
@@ -1048,7 +1048,7 @@ static __always_inline void test_dynptr_probe_str_xdp(struct xdp_md *xdp, void *
 
 		if (!len)
 			continue;
-		if (err || bpf_memcmp(expected_str, buf, len - 1) || buf[len - 1] != '\0')
+		if (err || local_memcmp(expected_str, buf, len - 1) || buf[len - 1] != '\0')
 			err = 1;
 
 		__builtin_memset(buf, 0, sizeof(buf));
diff --git a/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c b/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c
index bddc4e8579d244..e67fe9700e593c 100644
--- a/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c
+++ b/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c
@@ -9,6 +9,10 @@
 char *user_ptr = (char *)1;
 char *invalid_kern_ptr = (char *)-1;
 
+extern int bpf_strpbrk(const char *s__ign, const char *accept__ign) __ksym;
+extern int bpf_memcmp(const void *ptr1__ign, const void *ptr2__ign,
+		      size_t size) __ksym;
+
 /*
  * When passing userspace pointers, the error code differs based on arch:
  *   -ERANGE on arches with non-overlapping address spaces
@@ -53,6 +57,10 @@ SEC("syscall")  __retval(USER_PTR_ERR)int test_strnstr_null1(void *ctx) { return
 SEC("syscall")  __retval(USER_PTR_ERR)int test_strnstr_null2(void *ctx) { return bpf_strnstr("hello", NULL, 1); }
 SEC("syscall")  __retval(USER_PTR_ERR)int test_strncasestr_null1(void *ctx) { return bpf_strncasestr(NULL, "hello", 1); }
 SEC("syscall")  __retval(USER_PTR_ERR)int test_strncasestr_null2(void *ctx) { return bpf_strncasestr("hello", NULL, 1); }
+SEC("syscall")  __retval(USER_PTR_ERR)int test_memcmp_null1(void *ctx) { return bpf_memcmp(NULL, "x", 1); }
+SEC("syscall")  __retval(USER_PTR_ERR)int test_memcmp_null2(void *ctx) { return bpf_memcmp("x", NULL, 1); }
+SEC("syscall")  __retval(USER_PTR_ERR)int test_strpbrk_null1(void *ctx) { return bpf_strpbrk(NULL, "x"); }
+SEC("syscall")  __retval(USER_PTR_ERR)int test_strpbrk_null2(void *ctx) { return bpf_strpbrk("x", NULL); }
 
 /* Passing userspace ptr to string kfuncs */
 SEC("syscall") __retval(USER_PTR_ERR) int test_strcmp_user_ptr1(void *ctx) { return bpf_strcmp(user_ptr, "hello"); }
@@ -79,6 +87,10 @@ SEC("syscall") __retval(USER_PTR_ERR) int test_strnstr_user_ptr1(void *ctx) { re
 SEC("syscall") __retval(USER_PTR_ERR) int test_strnstr_user_ptr2(void *ctx) { return bpf_strnstr("hello", user_ptr, 1); }
 SEC("syscall") __retval(USER_PTR_ERR) int test_strncasestr_user_ptr1(void *ctx) { return bpf_strncasestr(user_ptr, "hello", 1); }
 SEC("syscall") __retval(USER_PTR_ERR) int test_strncasestr_user_ptr2(void *ctx) { return bpf_strncasestr("hello", user_ptr, 1); }
+SEC("syscall") __retval(USER_PTR_ERR) int test_memcmp_user_ptr1(void *ctx) { return bpf_memcmp(user_ptr, "x", 1); }
+SEC("syscall") __retval(USER_PTR_ERR) int test_memcmp_user_ptr2(void *ctx) { return bpf_memcmp("x", user_ptr, 1); }
+SEC("syscall") __retval(USER_PTR_ERR) int test_strpbrk_user_ptr1(void *ctx) { return bpf_strpbrk(user_ptr, "x"); }
+SEC("syscall") __retval(USER_PTR_ERR) int test_strpbrk_user_ptr2(void *ctx) { return bpf_strpbrk("x", user_ptr); }
 
 #endif /* __TARGET_ARCH_s390 */
 
@@ -107,5 +119,9 @@ SEC("syscall") __retval(-EFAULT) int test_strnstr_pagefault1(void *ctx) { return
 SEC("syscall") __retval(-EFAULT) int test_strnstr_pagefault2(void *ctx) { return bpf_strnstr("hello", invalid_kern_ptr, 1); }
 SEC("syscall") __retval(-EFAULT) int test_strncasestr_pagefault1(void *ctx) { return bpf_strncasestr(invalid_kern_ptr, "hello", 1); }
 SEC("syscall") __retval(-EFAULT) int test_strncasestr_pagefault2(void *ctx) { return bpf_strncasestr("hello", invalid_kern_ptr, 1); }
+SEC("syscall") __retval(-EFAULT) int test_memcmp_pagefault1(void *ctx) { return bpf_memcmp(invalid_kern_ptr, "x", 1); }
+SEC("syscall") __retval(-EFAULT) int test_memcmp_pagefault2(void *ctx) { return bpf_memcmp("x", invalid_kern_ptr, 1); }
+SEC("syscall") __retval(-EFAULT) int test_strpbrk_pagefault1(void *ctx) { return bpf_strpbrk(invalid_kern_ptr, "x"); }
+SEC("syscall") __retval(-EFAULT) int test_strpbrk_pagefault2(void *ctx) { return bpf_strpbrk("x", invalid_kern_ptr); }
 
 char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/string_kfuncs_success.c b/tools/testing/selftests/bpf/progs/string_kfuncs_success.c
index f65b1226a81a37..e67b80ab3cd2c9 100644
--- a/tools/testing/selftests/bpf/progs/string_kfuncs_success.c
+++ b/tools/testing/selftests/bpf/progs/string_kfuncs_success.c
@@ -7,6 +7,10 @@
 
 char str[] = "hello world";
 
+extern int bpf_strpbrk(const char *s__ign, const char *accept__ign) __ksym;
+extern int bpf_memcmp(const void *ptr1__ign, const void *ptr2__ign,
+		      size_t size) __ksym;
+
 #define __test(retval) SEC("syscall") __success __retval(retval)
 
 /* Functional tests */
@@ -60,4 +64,25 @@ __test(-ENOENT) int test_strncasestr_notfound2(void *ctx) { return bpf_strncases
 __test(-ENOENT) int test_strncasestr_notfound3(void *ctx) { return bpf_strncasestr("", "a", 0); }
 __test(0) int test_strncasestr_empty(void *ctx) { return bpf_strncasestr(str, "", 1); }
 
+/* bpf_strpbrk - functional tests */
+__test(0) int test_strpbrk_found_first(void *ctx) { return bpf_strpbrk(str, "h"); }
+__test(4) int test_strpbrk_found_middle(void *ctx) { return bpf_strpbrk(str, "ow"); }
+__test(6) int test_strpbrk_found_multiple(void *ctx) { return bpf_strpbrk(str, "w"); }
+__test(-ENOENT) int test_strpbrk_notfound(void *ctx) { return bpf_strpbrk(str, "xyz"); }
+__test(-ENOENT) int test_strpbrk_empty_accept(void *ctx) { return bpf_strpbrk(str, ""); }
+
+/* bpf_memcmp - functional tests */
+char data1[] = "hello world";
+char data2[] = "hello world";
+char data3[] = "hello worle";
+__test(0) int test_memcmp_eq(void *ctx) { return bpf_memcmp(data1, data2, sizeof(data1)); }
+__test(-1) int test_memcmp_neq_less(void *ctx) { return bpf_memcmp(data1, data3, sizeof(data1)); }
+__test(1) int test_memcmp_neq_greater(void *ctx) { return bpf_memcmp(data3, data1, sizeof(data1)); }
+__test(0) int test_memcmp_size_zero(void *ctx) { return bpf_memcmp(data1, data3, 0); }
+/* memcmp should NOT stop at null byte - compare past '\0' */
+char bin1[] = { 'a', '\0', 'c' };
+char bin2[] = { 'a', '\0', 'd' };
+__test(0) int test_memcmp_null_byte_eq(void *ctx) { return bpf_memcmp(bin1, bin1, sizeof(bin1)); }
+__test(-1) int test_memcmp_null_byte_neq(void *ctx) { return bpf_memcmp(bin1, bin2, sizeof(bin1)); }
+
 char _license[] SEC("license") = "GPL";

3/2 2026/06/23 03:34 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 8068
							output: 35
							thoughts: 274
						

Thoughts:
**My Assessment of the BPF Kfunc Patch**

Okay, so this patch is adding two new BPF kfuncs: `bpf_strpbrk` and `bpf_memcmp`. I see that they're implemented in `kernel/bpf/helpers.c` and registered using `BTF_ID_FLAGS`. Good, standard practice there. I also see that there's been some renaming of an existing `bpf_memcmp` to `local_memcmp` in `dynptr_success.c` to avoid a name collision. That's prudent; it avoids potential headaches later. And it looks like proper test coverage has been added. There are failure cases in `string_kfuncs_failure1.c` and success cases in `string_kfuncs_success.c`. Nice.

The fact that this adds new, callable kfuncs means this is a functional change to the BPF infrastructure, and I need to treat it as such. This screams "fuzzing candidate." We need to make sure these new functions are robust.

Let's dive into `kernel/bpf/helpers.c` and make sure there are no obvious configuration dependencies or anything unexpected. I'm going to quickly grep for `bpf_strpbrk` and `bpf_memcmp` within that file to get a good handle on their inclusion and any dependencies that I may need to take into account.



4/2 2026/06/23 03:34 tool grepper
0m Args:
{
  "Expression": "bpf_strpbrk",
  "PathPrefix": "kernel/bpf/helpers.c"
}

Results:
{
  "Output": "kernel/bpf/helpers.c=3943=__bpf_kfunc int bpf_strcspn(const char *s__ign, const char *reject__ign)\n--\nkernel/bpf/helpers.c-3991-/**\nkernel/bpf/helpers.c:3992: * bpf_strpbrk - Find the first occurrence of a set of characters in a string\nkernel/bpf/helpers.c-3993- * @s__ign: The string to be searched\n--\nkernel/bpf/helpers.c-4003- */\nkernel/bpf/helpers.c:4004:__bpf_kfunc int bpf_strpbrk(const char *s__ign, const char *accept__ign)\nkernel/bpf/helpers.c-4005-{\n--\nkernel/bpf/helpers.c=4955=BTF_ID_FLAGS(func, bpf_strcspn);\nkernel/bpf/helpers.c:4956:BTF_ID_FLAGS(func, bpf_strpbrk);\nkernel/bpf/helpers.c-4957-BTF_ID_FLAGS(func, bpf_memcmp);\n"
}

5/2 2026/06/23 03:34 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 8987
							output: 30
							thoughts: 17
						

Thoughts:
Okay, let's dive into this. Here's how I'd approach summarizing the prompt:

**Initial Assessment: Navigating the Kernel BPF Landscape**

Alright, the directive is to look at the configurations associated with `kernel/bpf/helpers.c`. My mind immediately starts to consider the implications. BPF, the Berkeley Packet Filter, is a critical component of modern Linux systems, allowing for in-kernel execution of bytecode. It's used for everything from network filtering and security monitoring to tracing and performance analysis. `helpers.c` is likely where the BPF helper functions are implemented, the low-level functions that BPF programs call to interact with the kernel. Given my expertise, I already know a fair bit about how this works, and have a good understanding of the security implications and performance trade-offs.

I'd want to examine any configuration files that influence how these helpers are compiled, enabled, or exposed. Specifically, I'd immediately be looking for:

*   **Compiler Flags**: How the code is compiled. Are there any optimization flags that could affect performance or code size? Are there security hardening options being used, such as `-fstack-protector`? Are there compiler flags specifically for BPF, like those controlling verifier behavior or debugging output?
*   **Kconfig Options**: The Kconfig file (likely in the same directory or a parent one) would be my next stop. It dictates what features are compiled into the kernel. What Kconfig options enable or disable BPF functionality or helper functions? What are the default values and what potential dependencies might affect how the helpers are used?
*   **Module Configuration**: If the helpers are compiled as a module, what are the relevant module parameters? How are they loaded and unloaded? What's the module's dependencies, if any, that would influence the configuration of the helper functions?
*   **Security Mechanisms**: Are there any security-related Kconfig options that restrict the capabilities of BPF programs or the helper functions? Is the BPF verifier enabled and configured securely? Are there any specific settings for the use of BPF in specific contexts, such as container environments?
*   **Build System Settings**: How does the build system (e.g., `make`) handle the compilation and linking of this code? Are there any special targets or rules for BPF-related code? Are there any environment variables or other settings that could affect how it's built or configured?
*   **Documentation**: Of course, any documentation associated with this specific file or the BPF system would be helpful to understand any caveats or assumptions regarding the configurations.

Essentially, I want to get a complete picture of the build environment and the potential influence on the behavior of `helpers.c` within the kernel. This is essential for troubleshooting, understanding security vulnerabilities, and optimizing performance.



6/2 2026/06/23 03:34 tool grepper
0m Args:
{
  "Expression": "CONFIG_",
  "PathPrefix": "kernel/bpf/helpers.c"
}

Results:
{
  "Output": "kernel/bpf/helpers.c=276=const struct bpf_func_proto bpf_get_current_comm_proto = {\n--\nkernel/bpf/helpers.c-283-\nkernel/bpf/helpers.c:284:#if defined(CONFIG_QUEUED_SPINLOCKS) || defined(CONFIG_BPF_ARCH_SPINLOCK)\nkernel/bpf/helpers.c-285-\n--\nkernel/bpf/helpers.c=399=const struct bpf_func_proto bpf_jiffies64_proto = {\n--\nkernel/bpf/helpers.c-404-\nkernel/bpf/helpers.c:405:#ifdef CONFIG_CGROUPS\nkernel/bpf/helpers.c-406-BPF_CALL_0(bpf_get_current_cgroup_id)\n--\nkernel/bpf/helpers.c=440=const struct bpf_func_proto bpf_get_current_ancestor_cgroup_id_proto = {\n--\nkernel/bpf/helpers.c-445-};\nkernel/bpf/helpers.c:446:#endif /* CONFIG_CGROUPS */\nkernel/bpf/helpers.c-447-\n--\nkernel/bpf/helpers.c=744=static int bpf_trace_copy_string(char *buf, void *unsafe_ptr, char fmt_ptype,\n--\nkernel/bpf/helpers.c-752-\tcase 's':\nkernel/bpf/helpers.c:753:#ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE\nkernel/bpf/helpers.c-754-\t\tif ((unsigned long)unsafe_ptr \u003c TASK_SIZE)\n--\nkernel/bpf/helpers.c=2067=bpf_base_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)\n--\nkernel/bpf/helpers.c-2167-\t\treturn \u0026bpf_dynptr_data_proto;\nkernel/bpf/helpers.c:2168:#ifdef CONFIG_CGROUPS\nkernel/bpf/helpers.c-2169-\tcase BPF_FUNC_cgrp_storage_get:\n--\nkernel/bpf/helpers.c-2179-#endif\nkernel/bpf/helpers.c:2180:#ifdef CONFIG_CGROUP_NET_CLASSID\nkernel/bpf/helpers.c-2181-\tcase BPF_FUNC_get_cgroup_classid:\n--\nkernel/bpf/helpers.c=2753=CFI_NOSEAL(bpf_task_release_dtor);\nkernel/bpf/helpers.c-2754-\nkernel/bpf/helpers.c:2755:#ifdef CONFIG_CGROUPS\nkernel/bpf/helpers.c-2756-/**\n--\nkernel/bpf/helpers.c=2876=bpf_task_get_cgroup1(struct task_struct *task, int hierarchy_id)\n--\nkernel/bpf/helpers.c-2883-}\nkernel/bpf/helpers.c:2884:#endif /* CONFIG_CGROUPS */\nkernel/bpf/helpers.c-2885-\n--\nkernel/bpf/helpers.c=3289=__bpf_kfunc void bpf_throw(u64 cookie)\n--\nkernel/bpf/helpers.c-3298-\tWARN_ON_ONCE(!ctx.cnt);\nkernel/bpf/helpers.c:3299:\t/* Prevent KASAN false positives for CONFIG_KASAN_STACK by unpoisoning\nkernel/bpf/helpers.c-3300-\t * deeper stack depths than ctx.sp as we do not return from bpf_throw,\n--\nkernel/bpf/helpers.c=4196=__bpf_kfunc int bpf_strncasestr(const char *s1__ign, const char *s2__ign,\n--\nkernel/bpf/helpers.c-4201-\nkernel/bpf/helpers.c:4202:#ifdef CONFIG_KEYS\nkernel/bpf/helpers.c-4203-/**\n--\nkernel/bpf/helpers.c=4320=__bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,\n--\nkernel/bpf/helpers.c-4323-{\nkernel/bpf/helpers.c:4324:#ifdef CONFIG_SYSTEM_DATA_VERIFICATION\nkernel/bpf/helpers.c-4325-\tstruct bpf_dynptr_kern *data_ptr = (struct bpf_dynptr_kern *)data_p;\n--\nkernel/bpf/helpers.c-4360-\treturn -EOPNOTSUPP;\nkernel/bpf/helpers.c:4361:#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */\nkernel/bpf/helpers.c-4362-}\nkernel/bpf/helpers.c:4363:#endif /* CONFIG_KEYS */\nkernel/bpf/helpers.c-4364-\n--\nkernel/bpf/helpers.c=4806=BTF_KFUNCS_START(generic_btf_ids)\nkernel/bpf/helpers.c:4807:#ifdef CONFIG_CRASH_DUMP\nkernel/bpf/helpers.c-4808-BTF_ID_FLAGS(func, crash_kexec, KF_DESTRUCTIVE)\n--\nkernel/bpf/helpers.c=4836=BTF_ID_FLAGS(func, bpf_rbtree_right, KF_RET_NULL)\nkernel/bpf/helpers.c-4837-\nkernel/bpf/helpers.c:4838:#ifdef CONFIG_CGROUPS\nkernel/bpf/helpers.c-4839-BTF_ID_FLAGS(func, bpf_cgroup_acquire, KF_ACQUIRE | KF_RCU | KF_RET_NULL)\n--\nkernel/bpf/helpers.c=4848=BTF_ID_FLAGS(func, bpf_throw)\nkernel/bpf/helpers.c:4849:#ifdef CONFIG_BPF_EVENTS\nkernel/bpf/helpers.c-4850-BTF_ID_FLAGS(func, bpf_send_signal_task)\nkernel/bpf/helpers.c-4851-#endif\nkernel/bpf/helpers.c:4852:#ifdef CONFIG_KEYS\nkernel/bpf/helpers.c-4853-BTF_ID_FLAGS(func, bpf_lookup_user_key, KF_ACQUIRE | KF_RET_NULL | KF_SLEEPABLE)\n--\nkernel/bpf/helpers.c=4855=BTF_ID_FLAGS(func, bpf_key_put, KF_RELEASE)\nkernel/bpf/helpers.c:4856:#ifdef CONFIG_SYSTEM_DATA_VERIFICATION\nkernel/bpf/helpers.c-4857-BTF_ID_FLAGS(func, bpf_verify_pkcs7_signature, KF_SLEEPABLE)\n--\nkernel/bpf/helpers.c-4859-#endif\nkernel/bpf/helpers.c:4860:#ifdef CONFIG_S390\nkernel/bpf/helpers.c-4861-BTF_ID_FLAGS(func, bpf_get_lowcore)\n--\nkernel/bpf/helpers.c=4873=BTF_ID(func, bpf_task_release_dtor)\nkernel/bpf/helpers.c:4874:#ifdef CONFIG_CGROUPS\nkernel/bpf/helpers.c-4875-BTF_ID(struct, cgroup)\n--\nkernel/bpf/helpers.c=4891=BTF_ID_FLAGS(func, bpf_iter_task_vma_destroy, KF_ITER_DESTROY)\nkernel/bpf/helpers.c:4892:#ifdef CONFIG_CGROUPS\nkernel/bpf/helpers.c-4893-BTF_ID_FLAGS(func, bpf_iter_css_task_new, KF_ITER_NEW)\n--\nkernel/bpf/helpers.c=4909=BTF_ID_FLAGS(func, bpf_dynptr_memset)\nkernel/bpf/helpers.c:4910:#ifdef CONFIG_NET\nkernel/bpf/helpers.c-4911-BTF_ID_FLAGS(func, bpf_modify_return_test_tp)\n--\nkernel/bpf/helpers.c=4928=BTF_ID_FLAGS(func, bpf_local_irq_restore)\nkernel/bpf/helpers.c:4929:#ifdef CONFIG_BPF_EVENTS\nkernel/bpf/helpers.c-4930-BTF_ID_FLAGS(func, bpf_probe_read_user_dynptr)\n--\nkernel/bpf/helpers.c=4937=BTF_ID_FLAGS(func, bpf_copy_from_user_task_str_dynptr, KF_SLEEPABLE)\nkernel/bpf/helpers.c-4938-#endif\nkernel/bpf/helpers.c:4939:#ifdef CONFIG_DMA_SHARED_BUFFER\nkernel/bpf/helpers.c-4940-BTF_ID_FLAGS(func, bpf_iter_dmabuf_new, KF_ITER_NEW | KF_SLEEPABLE)\n--\nkernel/bpf/helpers.c=4961=BTF_ID_FLAGS(func, bpf_strncasestr);\nkernel/bpf/helpers.c:4962:#if defined(CONFIG_BPF_LSM) \u0026\u0026 defined(CONFIG_CGROUPS)\nkernel/bpf/helpers.c-4963-BTF_ID_FLAGS(func, bpf_cgroup_read_xattr, KF_RCU)\n--\nkernel/bpf/helpers.c=4979=static int __init kfunc_init(void)\n--\nkernel/bpf/helpers.c-4986-\t\t},\nkernel/bpf/helpers.c:4987:#ifdef CONFIG_CGROUPS\nkernel/bpf/helpers.c-4988-\t\t{\n"
}

7/2 2026/06/23 03:34 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 12171
							output: 124
							thoughts: 481
						

Thoughts:
**Analysis of New BPF Kfuncs for Fuzzing**

Okay, so looking at this patch, it seems straightforward. The new `bpf_strpbrk` and `bpf_memcmp` kfuncs are being added to the generic BTF kfuncs, which means they're automatically available if BPF is enabled. No specific config options are required beyond the standard BPF configurations, which is as expected.

My focus is naturally on these two functions: `bpf_strpbrk` and `bpf_memcmp`. I need to ensure they're robust. The patch itself modifies these functions within `kernel/bpf/helpers.c`, which is the core of BPF helper functionality. It's also renaming `bpf_memcmp` to `local_memcmp` in a test file, so I need to account for that rename in my analysis. Additionally, there are new tests added in `string_kfuncs_failure1.c` and `string_kfuncs_success.c`, so I need to check those too.

Functionally, these additions enable string and memory comparisons directly within BPF programs. This is a significant change, especially because these functions involve memory access. They are potential points of vulnerability that need rigorous testing to prevent page faults or other memory-related issues.

Therefore, the output I'm generating for fuzzing will be:

*   **WorthFuzzing: true** - Definitely, these are new core functions.
*   **FocusSymbols: ["bpf_strpbrk", "bpf_memcmp"]** - These are the two functions that need the most attention.
*   **EnableConfigs: []** - No additional configurations are required.
*   **Reasoning: "The patch adds two new BPF kfuncs, `bpf_strpbrk` and `bpf_memcmp`, which allow BPF programs to perform string and memory comparisons. These are functional changes to the core BPF helper library and should be fuzzed to ensure they handle various inputs safely, especially since they deal with memory access and potential page faults."** - This sums up the core risk assessment and justification for fuzzing.



8/2 2026/06/23 03:35 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [
    "bpf_strpbrk",
    "bpf_memcmp"
  ],
  "Reasoning": "The patch adds two new BPF kfuncs, `bpf_strpbrk` and `bpf_memcmp`, which allow BPF programs to perform string and memory comparisons. These are functional changes to the core BPF helper library and should be fuzzed to ensure they handle various inputs safely, especially since they deal with memory access and potential page faults.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [
    "bpf_strpbrk",
    "bpf_memcmp"
  ],
  "Reasoning": "The patch adds two new BPF kfuncs, `bpf_strpbrk` and `bpf_memcmp`, which allow BPF programs to perform string and memory comparisons. These are functional changes to the core BPF helper library and should be fuzzed to ensure they handle various inputs safely, especially since they deal with memory access and potential page faults.",
  "WorthFuzzing": true
}

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)