* [PATCH bpf-next v2 1/2] bpf: add bpf_strcat,bpf_strncat kfunc [not found] <cover.1784078494.git.rtoax@foxmail.com> @ 2026-07-15 1:27 ` Rong Tao 2026-07-15 8:56 ` Viktor Malik 2026-07-15 1:27 ` [PATCH bpf-next v2 2/2] selftests/bpf: Test bpf_strcat,bpf_strncat kfuncs Rong Tao 1 sibling, 1 reply; 6+ messages in thread From: Rong Tao @ 2026-07-15 1:27 UTC (permalink / raw) To: andrii, vmalik, ast Cc: rtoax, Rong Tao, Daniel Borkmann, Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan, Yuzuki Ishiyama, open list:BPF [GENERAL] (Safe Dynamic Programs and Tools), open list, open list:KERNEL SELFTEST FRAMEWORK From: Rong Tao <rongtao@cestc.cn> Add string concatenation kfuncs, prototype: int bpf_strcat(char *dst__ign, u32 dst__sz, const char *src__ign); int bpf_strncat(char *dst__ign, u32 dst__sz, const char *src__ign, u32 len); This differs from the glibc library functions strcat and strncat, which, for safety reasons, require the size of the target string's memory space as a parameter. Signed-off-by: Rong Tao <rongtao@cestc.cn> --- kernel/bpf/helpers.c | 92 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index c18f1e16edee..401f94efd687 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -4195,6 +4195,96 @@ __bpf_kfunc int bpf_strncasestr(const char *s1__ign, const char *s2__ign, return __bpf_strnstr(s1__ign, s2__ign, len, true); } +static int __bpf_strncat(char *dst, u32 dsz, const char *src, u32 sz) +{ + int dlen, slen, space, copied; + char cs = '?'; + + if (!copy_from_kernel_nofault_allowed(dst, 1) || + !copy_from_kernel_nofault_allowed(src, 1)) { + return -ERANGE; + } + + dlen = bpf_strnlen(dst, dsz); + if (dlen < 0) + return dlen; + slen = bpf_strnlen(src, sz); + if (slen < 0) + return slen; + + if (dlen >= dsz || sz == 0 || dsz == 0) + return -EINVAL; + + space = dsz - dlen; + if (space <= 1 || space < min(slen, sz) + 1) + return -E2BIG; + + guard(pagefault)(); + for (copied = 0; copied < space - 1 && copied < slen; copied++) { + __get_kernel_nofault(&cs, src, char, err_out); + if (cs == '\0') + break; + + __put_kernel_nofault(dst + dlen + copied, &cs, char, err_out); + + src++; + } + cs = '\0'; + __put_kernel_nofault(dst + dlen + copied, &cs, char, err_out); + + __get_kernel_nofault(&cs, src, char, err_out); + if (cs != '\0' && sz > copied) + return -E2BIG; + + return dlen + copied; +err_out: + return -EFAULT; +} + +/** + * bpf_strcat - Append non-null bytes from a source string, and null-terminate + * the result + * @dst: Destination string. + * @dst__sz: Maximum bytes of @dst__ign, includes the trailing NUL. + * @src__ign: Source string. + * + * Return: + * * >=0 - Length of the concatenated string. + * + * * %-EINVAL - String @dst__ign is invalid. + * * %-EFAULT - Cannot read or write one of the strings. + * * %-E2BIG - String @src__ign is too large or the remaining space in + * @dst__ign is too small. + * * %-ERANGE - One of the strings is outside of kernel address space + */ +__bpf_kfunc int bpf_strcat(char *dst, u32 dst__sz, const char *src__ign) +{ + return __bpf_strncat(dst, dst__sz, src__ign, XATTR_SIZE_MAX); +} + +/** + * bpf_strncat - Append non-null bytes from a source string, and null-terminate + * the result + * @dst: Destination string. + * @dst__sz: Maximum bytes of @dst__ign, includes the trailing NUL. + * @src__ign: Source string. + * @len: the maximum number of characters to concatenate + * + * Return: + * * >=0 - Length of the concatenated string. + * + * * %-EINVAL - String @dst__ign is invalid. + * * %-EFAULT - Cannot read or write one of the strings. + * * %-E2BIG - String @src__ign is too large or the remaining space in + * @dst__ign is too small. + * * %-ERANGE - One of the strings is outside of kernel address space + */ +__bpf_kfunc int bpf_strncat(char *dst, u32 dst__sz, const char *src__ign, + u32 len) +{ + return __bpf_strncat(dst, dst__sz, src__ign, len); +} + #ifdef CONFIG_KEYS /** * bpf_lookup_user_key - lookup a key by its serial @@ -4958,6 +5048,8 @@ BTF_ID_FLAGS(func, bpf_strstr); BTF_ID_FLAGS(func, bpf_strcasestr); BTF_ID_FLAGS(func, bpf_strnstr); BTF_ID_FLAGS(func, bpf_strncasestr); +BTF_ID_FLAGS(func, bpf_strcat); +BTF_ID_FLAGS(func, bpf_strncat); #if defined(CONFIG_BPF_LSM) && defined(CONFIG_CGROUPS) BTF_ID_FLAGS(func, bpf_cgroup_read_xattr, KF_RCU) #endif -- 2.55.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next v2 1/2] bpf: add bpf_strcat,bpf_strncat kfunc 2026-07-15 1:27 ` [PATCH bpf-next v2 1/2] bpf: add bpf_strcat,bpf_strncat kfunc Rong Tao @ 2026-07-15 8:56 ` Viktor Malik 2026-07-16 8:16 ` Rong Tao 0 siblings, 1 reply; 6+ messages in thread From: Viktor Malik @ 2026-07-15 8:56 UTC (permalink / raw) To: Rong Tao, andrii, ast Cc: Rong Tao, Daniel Borkmann, Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan, Yuzuki Ishiyama, open list:BPF [GENERAL] (Safe Dynamic Programs and Tools), open list, open list:KERNEL SELFTEST FRAMEWORK On 7/15/26 03:27, Rong Tao wrote: > From: Rong Tao <rongtao@cestc.cn> > > Add string concatenation kfuncs, prototype: > > int bpf_strcat(char *dst__ign, u32 dst__sz, const char *src__ign); > int bpf_strncat(char *dst__ign, u32 dst__sz, const char *src__ign, u32 len); > > This differs from the glibc library functions strcat and strncat, which, > for safety reasons, require the size of the target string's memory space > as a parameter. > > Signed-off-by: Rong Tao <rongtao@cestc.cn> > --- > kernel/bpf/helpers.c | 92 ++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 92 insertions(+) > > diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c > index c18f1e16edee..401f94efd687 100644 > --- a/kernel/bpf/helpers.c > +++ b/kernel/bpf/helpers.c > @@ -4195,6 +4195,96 @@ __bpf_kfunc int bpf_strncasestr(const char *s1__ign, const char *s2__ign, > return __bpf_strnstr(s1__ign, s2__ign, len, true); > } > > +static int __bpf_strncat(char *dst, u32 dsz, const char *src, u32 sz) > +{ > + int dlen, slen, space, copied; > + char cs = '?'; > + > + if (!copy_from_kernel_nofault_allowed(dst, 1) || > + !copy_from_kernel_nofault_allowed(src, 1)) { > + return -ERANGE; > + } > + > + dlen = bpf_strnlen(dst, dsz); > + if (dlen < 0) > + return dlen; > + slen = bpf_strnlen(src, sz); > + if (slen < 0) > + return slen; > + > + if (dlen >= dsz || sz == 0 || dsz == 0) > + return -EINVAL; > + > + space = dsz - dlen; > + if (space <= 1 || space < min(slen, sz) + 1) > + return -E2BIG; > + > + guard(pagefault)(); > + for (copied = 0; copied < space - 1 && copied < slen; copied++) { > + __get_kernel_nofault(&cs, src, char, err_out); > + if (cs == '\0') > + break; > + > + __put_kernel_nofault(dst + dlen + copied, &cs, char, err_out); I don't think that we need __put_kernel_nofault() here. My understanding is that since we don't use the `__ign` suffix for the destination string, the verifier should make sure that `dst` points to a valid memory with sufficient capacity (thanks to the `dst__sz` arg). We could use `strncpy_from_kernel_nofault(dst + dlen, src, space)`, which makes me wonder how would `bpf_strcat` be different from directly using bpf_probe_read_kernel_str(). Viktor > + > + src++; > + } > + cs = '\0'; > + __put_kernel_nofault(dst + dlen + copied, &cs, char, err_out); > + > + __get_kernel_nofault(&cs, src, char, err_out); > + if (cs != '\0' && sz > copied) > + return -E2BIG; > + > + return dlen + copied; > +err_out: > + return -EFAULT; > +} > + > +/** > + * bpf_strcat - Append non-null bytes from a source string, and null-terminate > + * the result > + * @dst: Destination string. > + * @dst__sz: Maximum bytes of @dst__ign, includes the trailing NUL. > + * @src__ign: Source string. > + * > + * Return: > + * * >=0 - Length of the concatenated string. > + * > + * * %-EINVAL - String @dst__ign is invalid. > + * * %-EFAULT - Cannot read or write one of the strings. > + * * %-E2BIG - String @src__ign is too large or the remaining space in > + * @dst__ign is too small. > + * * %-ERANGE - One of the strings is outside of kernel address space > + */ > +__bpf_kfunc int bpf_strcat(char *dst, u32 dst__sz, const char *src__ign) > +{ > + return __bpf_strncat(dst, dst__sz, src__ign, XATTR_SIZE_MAX); > +} > + > +/** > + * bpf_strncat - Append non-null bytes from a source string, and null-terminate > + * the result > + * @dst: Destination string. > + * @dst__sz: Maximum bytes of @dst__ign, includes the trailing NUL. > + * @src__ign: Source string. > + * @len: the maximum number of characters to concatenate > + * > + * Return: > + * * >=0 - Length of the concatenated string. > + * > + * * %-EINVAL - String @dst__ign is invalid. > + * * %-EFAULT - Cannot read or write one of the strings. > + * * %-E2BIG - String @src__ign is too large or the remaining space in > + * @dst__ign is too small. > + * * %-ERANGE - One of the strings is outside of kernel address space > + */ > +__bpf_kfunc int bpf_strncat(char *dst, u32 dst__sz, const char *src__ign, > + u32 len) > +{ > + return __bpf_strncat(dst, dst__sz, src__ign, len); > +} > + > #ifdef CONFIG_KEYS > /** > * bpf_lookup_user_key - lookup a key by its serial > @@ -4958,6 +5048,8 @@ BTF_ID_FLAGS(func, bpf_strstr); > BTF_ID_FLAGS(func, bpf_strcasestr); > BTF_ID_FLAGS(func, bpf_strnstr); > BTF_ID_FLAGS(func, bpf_strncasestr); > +BTF_ID_FLAGS(func, bpf_strcat); > +BTF_ID_FLAGS(func, bpf_strncat); > #if defined(CONFIG_BPF_LSM) && defined(CONFIG_CGROUPS) > BTF_ID_FLAGS(func, bpf_cgroup_read_xattr, KF_RCU) > #endif ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next v2 1/2] bpf: add bpf_strcat,bpf_strncat kfunc 2026-07-15 8:56 ` Viktor Malik @ 2026-07-16 8:16 ` Rong Tao 0 siblings, 0 replies; 6+ messages in thread From: Rong Tao @ 2026-07-16 8:16 UTC (permalink / raw) To: Viktor Malik, andrii, ast Cc: Rong Tao, Daniel Borkmann, Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan, Yuzuki Ishiyama, open list:BPF [GENERAL] (Safe Dynamic Programs and Tools), open list, open list:KERNEL SELFTEST FRAMEWORK On 7/15/26 16:56, Viktor Malik wrote: > On 7/15/26 03:27, Rong Tao wrote: >> From: Rong Tao <rongtao@cestc.cn> >> >> Add string concatenation kfuncs, prototype: >> >> int bpf_strcat(char *dst__ign, u32 dst__sz, const char *src__ign); >> int bpf_strncat(char *dst__ign, u32 dst__sz, const char *src__ign, u32 len); >> >> This differs from the glibc library functions strcat and strncat, which, >> for safety reasons, require the size of the target string's memory space >> as a parameter. >> >> Signed-off-by: Rong Tao <rongtao@cestc.cn> >> --- >> kernel/bpf/helpers.c | 92 ++++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 92 insertions(+) >> >> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c >> index c18f1e16edee..401f94efd687 100644 >> --- a/kernel/bpf/helpers.c >> +++ b/kernel/bpf/helpers.c >> @@ -4195,6 +4195,96 @@ __bpf_kfunc int bpf_strncasestr(const char *s1__ign, const char *s2__ign, >> return __bpf_strnstr(s1__ign, s2__ign, len, true); >> } >> >> +static int __bpf_strncat(char *dst, u32 dsz, const char *src, u32 sz) >> +{ >> + int dlen, slen, space, copied; >> + char cs = '?'; >> + >> + if (!copy_from_kernel_nofault_allowed(dst, 1) || >> + !copy_from_kernel_nofault_allowed(src, 1)) { >> + return -ERANGE; >> + } >> + >> + dlen = bpf_strnlen(dst, dsz); >> + if (dlen < 0) >> + return dlen; >> + slen = bpf_strnlen(src, sz); >> + if (slen < 0) >> + return slen; >> + >> + if (dlen >= dsz || sz == 0 || dsz == 0) >> + return -EINVAL; >> + >> + space = dsz - dlen; >> + if (space <= 1 || space < min(slen, sz) + 1) >> + return -E2BIG; >> + >> + guard(pagefault)(); >> + for (copied = 0; copied < space - 1 && copied < slen; copied++) { >> + __get_kernel_nofault(&cs, src, char, err_out); >> + if (cs == '\0') >> + break; >> + >> + __put_kernel_nofault(dst + dlen + copied, &cs, char, err_out); > I don't think that we need __put_kernel_nofault() here. My understanding > is that since we don't use the `__ign` suffix for the destination > string, the verifier should make sure that `dst` points to a valid > memory with sufficient capacity (thanks to the `dst__sz` arg). We could > use `strncpy_from_kernel_nofault(dst + dlen, src, space)`, which makes > me wonder how would `bpf_strcat` be different from directly using > bpf_probe_read_kernel_str(). Indeed, bpf_probe_read_kernel_str() and bpf_strcat() seem to have no fundamental difference. Perhaps helpers are not as convenient to use as kfunc? For example, in bpftrace's stdlib, to avoid including certain header files that would make it inconvenient to use helpers, one would have to use a complex method like asm() + BPF_FUNC_ to call the helper. Using kfunc is much more convenient. Rong Tao > > Viktor > >> + >> + src++; >> + } >> + cs = '\0'; >> + __put_kernel_nofault(dst + dlen + copied, &cs, char, err_out); >> + >> + __get_kernel_nofault(&cs, src, char, err_out); >> + if (cs != '\0' && sz > copied) >> + return -E2BIG; >> + >> + return dlen + copied; >> +err_out: >> + return -EFAULT; >> +} >> + >> +/** >> + * bpf_strcat - Append non-null bytes from a source string, and null-terminate >> + * the result >> + * @dst: Destination string. >> + * @dst__sz: Maximum bytes of @dst__ign, includes the trailing NUL. >> + * @src__ign: Source string. >> + * >> + * Return: >> + * * >=0 - Length of the concatenated string. >> + * >> + * * %-EINVAL - String @dst__ign is invalid. >> + * * %-EFAULT - Cannot read or write one of the strings. >> + * * %-E2BIG - String @src__ign is too large or the remaining space in >> + * @dst__ign is too small. >> + * * %-ERANGE - One of the strings is outside of kernel address space >> + */ >> +__bpf_kfunc int bpf_strcat(char *dst, u32 dst__sz, const char *src__ign) >> +{ >> + return __bpf_strncat(dst, dst__sz, src__ign, XATTR_SIZE_MAX); >> +} >> + >> +/** >> + * bpf_strncat - Append non-null bytes from a source string, and null-terminate >> + * the result >> + * @dst: Destination string. >> + * @dst__sz: Maximum bytes of @dst__ign, includes the trailing NUL. >> + * @src__ign: Source string. >> + * @len: the maximum number of characters to concatenate >> + * >> + * Return: >> + * * >=0 - Length of the concatenated string. >> + * >> + * * %-EINVAL - String @dst__ign is invalid. >> + * * %-EFAULT - Cannot read or write one of the strings. >> + * * %-E2BIG - String @src__ign is too large or the remaining space in >> + * @dst__ign is too small. >> + * * %-ERANGE - One of the strings is outside of kernel address space >> + */ >> +__bpf_kfunc int bpf_strncat(char *dst, u32 dst__sz, const char *src__ign, >> + u32 len) >> +{ >> + return __bpf_strncat(dst, dst__sz, src__ign, len); >> +} >> + >> #ifdef CONFIG_KEYS >> /** >> * bpf_lookup_user_key - lookup a key by its serial >> @@ -4958,6 +5048,8 @@ BTF_ID_FLAGS(func, bpf_strstr); >> BTF_ID_FLAGS(func, bpf_strcasestr); >> BTF_ID_FLAGS(func, bpf_strnstr); >> BTF_ID_FLAGS(func, bpf_strncasestr); >> +BTF_ID_FLAGS(func, bpf_strcat); >> +BTF_ID_FLAGS(func, bpf_strncat); >> #if defined(CONFIG_BPF_LSM) && defined(CONFIG_CGROUPS) >> BTF_ID_FLAGS(func, bpf_cgroup_read_xattr, KF_RCU) >> #endif ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH bpf-next v2 2/2] selftests/bpf: Test bpf_strcat,bpf_strncat kfuncs [not found] <cover.1784078494.git.rtoax@foxmail.com> 2026-07-15 1:27 ` [PATCH bpf-next v2 1/2] bpf: add bpf_strcat,bpf_strncat kfunc Rong Tao @ 2026-07-15 1:27 ` Rong Tao 2026-08-07 21:58 ` kernel test robot 2026-08-08 2:59 ` kernel test robot 1 sibling, 2 replies; 6+ messages in thread From: Rong Tao @ 2026-07-15 1:27 UTC (permalink / raw) To: andrii, vmalik, ast Cc: rtoax, Rong Tao, Daniel Borkmann, Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan, Yuzuki Ishiyama, open list:BPF [GENERAL] (Safe Dynamic Programs and Tools), open list:KERNEL SELFTEST FRAMEWORK, open list From: Rong Tao <rongtao@cestc.cn> Add tests for new kfuncs bpf_strcat() and bpf_strncat(). Signed-off-by: Rong Tao <rongtao@cestc.cn> --- .../selftests/bpf/prog_tests/string_kfuncs.c | 2 ++ .../selftests/bpf/progs/string_kfuncs_failure1.c | 13 +++++++++++++ .../selftests/bpf/progs/string_kfuncs_failure2.c | 2 ++ .../selftests/bpf/progs/string_kfuncs_success.c | 3 +++ 4 files changed, 20 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/string_kfuncs.c b/tools/testing/selftests/bpf/prog_tests/string_kfuncs.c index 300032a19445..460567ef622a 100644 --- a/tools/testing/selftests/bpf/prog_tests/string_kfuncs.c +++ b/tools/testing/selftests/bpf/prog_tests/string_kfuncs.c @@ -24,6 +24,8 @@ static const char * const test_cases[] = { "strcasestr", "strnstr", "strncasestr", + "strcat", + "strncat", }; void run_too_long_tests(void) diff --git a/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c b/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c index bddc4e8579d2..29bc7eabbb6a 100644 --- a/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c +++ b/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c @@ -8,6 +8,7 @@ char *user_ptr = (char *)1; char *invalid_kern_ptr = (char *)-1; +char kern_buf[32] = { "hello" }; /* * When passing userspace pointers, the error code differs based on arch: @@ -53,6 +54,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_strcat_null1(void *ctx) { return bpf_strcat(NULL, 6, "hello"); } +SEC("syscall") __retval(USER_PTR_ERR)int test_strcat_null2(void *ctx) { return bpf_strcat(kern_buf, sizeof(kern_buf), NULL); } +SEC("syscall") __retval(USER_PTR_ERR)int test_strncat_null1(void *ctx) { return bpf_strncat(NULL, 6, "hello", 2); } +SEC("syscall") __retval(USER_PTR_ERR)int test_strncat_null2(void *ctx) { return bpf_strncat(kern_buf, sizeof(kern_buf), NULL, 2); } /* 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 +84,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_strcat_user_ptr1(void *ctx) { return bpf_strcat(user_ptr, 1, "hello"); } +SEC("syscall") __retval(USER_PTR_ERR) int test_strcat_user_ptr2(void *ctx) { return bpf_strcat(kern_buf, sizeof(kern_buf), user_ptr); } +SEC("syscall") __retval(USER_PTR_ERR) int test_strncat_user_ptr1(void *ctx) { return bpf_strncat(user_ptr, 1, "hello", 2); } +SEC("syscall") __retval(USER_PTR_ERR) int test_strncat_user_ptr2(void *ctx) { return bpf_strncat(kern_buf, sizeof(kern_buf), user_ptr, 1); } #endif /* __TARGET_ARCH_s390 */ @@ -107,5 +116,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_strcat_pagefault1(void *ctx) { return bpf_strcat(invalid_kern_ptr, 1, "hello"); } +SEC("syscall") __retval(-EFAULT) int test_strcat_pagefault2(void *ctx) { return bpf_strcat(kern_buf, sizeof(kern_buf), invalid_kern_ptr); } +SEC("syscall") __retval(-EFAULT) int test_strncat_pagefault1(void *ctx) { return bpf_strncat(invalid_kern_ptr, 1, "hello", 2); } +SEC("syscall") __retval(-EFAULT) int test_strncat_pagefault2(void *ctx) { return bpf_strncat(kern_buf, sizeof(kern_buf), invalid_kern_ptr, 2); } char _license[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/bpf/progs/string_kfuncs_failure2.c b/tools/testing/selftests/bpf/progs/string_kfuncs_failure2.c index 412c53b87b18..38f0a5f326b5 100644 --- a/tools/testing/selftests/bpf/progs/string_kfuncs_failure2.c +++ b/tools/testing/selftests/bpf/progs/string_kfuncs_failure2.c @@ -23,5 +23,7 @@ SEC("syscall") int test_strstr_too_long(void *ctx) { return bpf_strstr(long_str, SEC("syscall") int test_strcasestr_too_long(void *ctx) { return bpf_strcasestr(long_str, "hello"); } SEC("syscall") int test_strnstr_too_long(void *ctx) { return bpf_strnstr(long_str, "hello", sizeof(long_str)); } SEC("syscall") int test_strncasestr_too_long(void *ctx) { return bpf_strncasestr(long_str, "hello", sizeof(long_str)); } +SEC("syscall") int test_strcat_too_long(void *ctx) { return bpf_strcat(long_str, sizeof(long_str), "hello"); } +SEC("syscall") int test_strncat_too_long(void *ctx) { return bpf_strncat(long_str, sizeof(long_str), "hello", 3); } 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 f65b1226a81a..93996b0e9595 100644 --- a/tools/testing/selftests/bpf/progs/string_kfuncs_success.c +++ b/tools/testing/selftests/bpf/progs/string_kfuncs_success.c @@ -6,6 +6,7 @@ #include "errno.h" char str[] = "hello world"; +char buf[32] = "hello"; #define __test(retval) SEC("syscall") __success __retval(retval) @@ -59,5 +60,7 @@ __test(-ENOENT) int test_strncasestr_notfound1(void *ctx) { return bpf_strncases __test(-ENOENT) int test_strncasestr_notfound2(void *ctx) { return bpf_strncasestr(str, "hello", 4); } __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); } +__test(10) int test_strcat_success(void *ctx) { return bpf_strcat(buf, sizeof(buf), "world"); } +__test(13) int test_strncat_success(void *ctx) { return bpf_strncat(buf, sizeof(buf), "world", 3); } char _license[] SEC("license") = "GPL"; -- 2.55.0 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next v2 2/2] selftests/bpf: Test bpf_strcat,bpf_strncat kfuncs 2026-07-15 1:27 ` [PATCH bpf-next v2 2/2] selftests/bpf: Test bpf_strcat,bpf_strncat kfuncs Rong Tao @ 2026-08-07 21:58 ` kernel test robot 2026-08-08 2:59 ` kernel test robot 1 sibling, 0 replies; 6+ messages in thread From: kernel test robot @ 2026-08-07 21:58 UTC (permalink / raw) To: Rong Tao, andrii, vmalik, ast Cc: oe-kbuild-all, rtoax, Rong Tao, Daniel Borkmann, Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan, Yuzuki Ishiyama, (open list:BPF \(Safe Dynamic Programs and Tools\)), linux-kselftest, linux-kernel Hi Rong, kernel test robot noticed the following build errors: [auto build test ERROR on bpf-next/master] url: https://github.com/intel-lab-lkp/linux/commits/Rong-Tao/selftests-bpf-Test-bpf_strcat-bpf_strncat-kfuncs/20260807-065842 base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master patch link: https://lore.kernel.org/r/tencent_DB0510330C3A8574B3C62E6154165FCB4709%40qq.com patch subject: [PATCH bpf-next v2 2/2] selftests/bpf: Test bpf_strcat,bpf_strncat kfuncs config: s390-randconfig-r052-20260807 (https://download.01.org/0day-ci/archive/20260808/202608080502.lI7AVjty-lkp@intel.com/config) compiler: clang version 24.0.0git (https://github.com/llvm/llvm-project 12df34b8469b8095359de8c249cb1b2753fadeea) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260808/202608080502.lI7AVjty-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202608080502.lI7AVjty-lkp@intel.com/ All errors (new ones prefixed by >>): >> kernel/bpf/helpers.c:4228:3: error: invalid lvalue in asm output 4228 | __put_kernel_nofault(dst + dlen + copied, &cs, char, err_out); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/uaccess.h:612:2: note: expanded from macro '__put_kernel_nofault' 612 | arch_put_kernel_nofault(dst, src, type, local_label); \ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ arch/s390/include/asm/uaccess.h:471:33: note: expanded from macro 'arch_put_kernel_nofault' 471 | #define arch_put_kernel_nofault __mvc_kernel_nofault | ^ arch/s390/include/asm/uaccess.h:424:19: note: expanded from macro '__mvc_kernel_nofault' 424 | : [_dst] "=Q" (*(type *)dst) \ | ^~~~~~~~~~~~ kernel/bpf/helpers.c:4233:2: error: invalid lvalue in asm output 4233 | __put_kernel_nofault(dst + dlen + copied, &cs, char, err_out); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/uaccess.h:612:2: note: expanded from macro '__put_kernel_nofault' 612 | arch_put_kernel_nofault(dst, src, type, local_label); \ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ arch/s390/include/asm/uaccess.h:471:33: note: expanded from macro 'arch_put_kernel_nofault' 471 | #define arch_put_kernel_nofault __mvc_kernel_nofault | ^ arch/s390/include/asm/uaccess.h:424:19: note: expanded from macro '__mvc_kernel_nofault' 424 | : [_dst] "=Q" (*(type *)dst) \ | ^~~~~~~~~~~~ 2 errors generated. vim +4228 kernel/bpf/helpers.c 4197 4198 static int __bpf_strncat(char *dst, u32 dsz, const char *src, u32 sz) 4199 { 4200 int dlen, slen, space, copied; 4201 char cs = '?'; 4202 4203 if (!copy_from_kernel_nofault_allowed(dst, 1) || 4204 !copy_from_kernel_nofault_allowed(src, 1)) { 4205 return -ERANGE; 4206 } 4207 4208 dlen = bpf_strnlen(dst, dsz); 4209 if (dlen < 0) 4210 return dlen; 4211 slen = bpf_strnlen(src, sz); 4212 if (slen < 0) 4213 return slen; 4214 4215 if (dlen >= dsz || sz == 0 || dsz == 0) 4216 return -EINVAL; 4217 4218 space = dsz - dlen; 4219 if (space <= 1 || space < min(slen, sz) + 1) 4220 return -E2BIG; 4221 4222 guard(pagefault)(); 4223 for (copied = 0; copied < space - 1 && copied < slen; copied++) { 4224 __get_kernel_nofault(&cs, src, char, err_out); 4225 if (cs == '\0') 4226 break; 4227 > 4228 __put_kernel_nofault(dst + dlen + copied, &cs, char, err_out); 4229 4230 src++; 4231 } 4232 cs = '\0'; 4233 __put_kernel_nofault(dst + dlen + copied, &cs, char, err_out); 4234 4235 __get_kernel_nofault(&cs, src, char, err_out); 4236 if (cs != '\0' && sz > copied) 4237 return -E2BIG; 4238 4239 return dlen + copied; 4240 err_out: 4241 return -EFAULT; 4242 } 4243 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next v2 2/2] selftests/bpf: Test bpf_strcat,bpf_strncat kfuncs 2026-07-15 1:27 ` [PATCH bpf-next v2 2/2] selftests/bpf: Test bpf_strcat,bpf_strncat kfuncs Rong Tao 2026-08-07 21:58 ` kernel test robot @ 2026-08-08 2:59 ` kernel test robot 1 sibling, 0 replies; 6+ messages in thread From: kernel test robot @ 2026-08-08 2:59 UTC (permalink / raw) To: Rong Tao, andrii, vmalik, ast Cc: oe-kbuild-all, rtoax, Rong Tao, Daniel Borkmann, Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, Shuah Khan, Yuzuki Ishiyama, (open list:BPF \(Safe Dynamic Programs and Tools\)), linux-kselftest, linux-kernel Hi Rong, kernel test robot noticed the following build errors: [auto build test ERROR on bpf-next/master] url: https://github.com/intel-lab-lkp/linux/commits/Rong-Tao/selftests-bpf-Test-bpf_strcat-bpf_strncat-kfuncs/20260807-065842 base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master patch link: https://lore.kernel.org/r/tencent_DB0510330C3A8574B3C62E6154165FCB4709%40qq.com patch subject: [PATCH bpf-next v2 2/2] selftests/bpf: Test bpf_strcat,bpf_strncat kfuncs config: riscv-randconfig-r131-20260807 (https://download.01.org/0day-ci/archive/20260808/202608081054.Y56a5ufe-lkp@intel.com/config) compiler: riscv64-linux-gcc (GCC) 8.5.0 sparse: v0.6.5-rc1 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260808/202608081054.Y56a5ufe-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202608081054.Y56a5ufe-lkp@intel.com/ All errors (new ones prefixed by >>): In file included from include/uapi/linux/filter.h:9, from include/linux/bpf.h:8, from kernel/bpf/helpers.c:4: kernel/bpf/helpers.c: In function '__bpf_strncat': >> include/linux/compiler_types.h:702:38: error: call to '__compiletime_assert_851' declared with attribute error: min(slen, sz) signedness error _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) ^ include/linux/compiler.h:68:3: note: in definition of macro '__trace_if_value' (cond) ? \ ^~~~ include/linux/compiler.h:55:28: note: in expansion of macro '__trace_if_var' #define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) ) ^~~~~~~~~~~~~~ kernel/bpf/helpers.c:4219:2: note: in expansion of macro 'if' if (space <= 1 || space < min(slen, sz) + 1) ^~ include/linux/compiler_types.h:690:2: note: in expansion of macro '__compiletime_assert' __compiletime_assert(condition, msg, prefix, suffix) ^~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:702:2: note: in expansion of macro '_compiletime_assert' _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) ^~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:40:37: note: in expansion of macro 'compiletime_assert' #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:93:2: note: in expansion of macro 'BUILD_BUG_ON_MSG' BUILD_BUG_ON_MSG(!__types_ok(ux, uy), \ ^~~~~~~~~~~~~~~~ include/linux/minmax.h:98:2: note: in expansion of macro '__careful_cmp_once' __careful_cmp_once(op, x, y, __UNIQUE_ID(x_), __UNIQUE_ID(y_)) ^~~~~~~~~~~~~~~~~~ include/linux/minmax.h:105:19: note: in expansion of macro '__careful_cmp' #define min(x, y) __careful_cmp(min, x, y) ^~~~~~~~~~~~~ kernel/bpf/helpers.c:4219:28: note: in expansion of macro 'min' if (space <= 1 || space < min(slen, sz) + 1) ^~~ vim +/__compiletime_assert_851 +702 include/linux/compiler_types.h eb5c2d4b45e3d2 Will Deacon 2020-07-21 688 eb5c2d4b45e3d2 Will Deacon 2020-07-21 689 #define _compiletime_assert(condition, msg, prefix, suffix) \ eb5c2d4b45e3d2 Will Deacon 2020-07-21 690 __compiletime_assert(condition, msg, prefix, suffix) eb5c2d4b45e3d2 Will Deacon 2020-07-21 691 eb5c2d4b45e3d2 Will Deacon 2020-07-21 692 /** eb5c2d4b45e3d2 Will Deacon 2020-07-21 693 * compiletime_assert - break build and emit msg if condition is false eb5c2d4b45e3d2 Will Deacon 2020-07-21 694 * @condition: a compile-time constant condition to check eb5c2d4b45e3d2 Will Deacon 2020-07-21 695 * @msg: a message to emit if condition is false eb5c2d4b45e3d2 Will Deacon 2020-07-21 696 * eb5c2d4b45e3d2 Will Deacon 2020-07-21 697 * In tradition of POSIX assert, this macro will break the build if the eb5c2d4b45e3d2 Will Deacon 2020-07-21 698 * supplied condition is *false*, emitting the supplied error message if the eb5c2d4b45e3d2 Will Deacon 2020-07-21 699 * compiler has support to do so. eb5c2d4b45e3d2 Will Deacon 2020-07-21 700 */ eb5c2d4b45e3d2 Will Deacon 2020-07-21 701 #define compiletime_assert(condition, msg) \ eb5c2d4b45e3d2 Will Deacon 2020-07-21 @702 _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) eb5c2d4b45e3d2 Will Deacon 2020-07-21 703 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-08 3:00 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <cover.1784078494.git.rtoax@foxmail.com>
2026-07-15 1:27 ` [PATCH bpf-next v2 1/2] bpf: add bpf_strcat,bpf_strncat kfunc Rong Tao
2026-07-15 8:56 ` Viktor Malik
2026-07-16 8:16 ` Rong Tao
2026-07-15 1:27 ` [PATCH bpf-next v2 2/2] selftests/bpf: Test bpf_strcat,bpf_strncat kfuncs Rong Tao
2026-08-07 21:58 ` kernel test robot
2026-08-08 2:59 ` kernel test robot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox