linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH bpf-next v3 1/2] bpf: add bpf_strcasecmp kfunc
       [not found] <cover.1756804522.git.rtoax@foxmail.com>
@ 2025-09-02  9:19 ` Rong Tao
  2025-09-02  9:45   ` Viktor Malik
  2025-09-02 16:54   ` Yonghong Song
  2025-09-02  9:19 ` [PATCH bpf-next v3 2/2] selftests/bpf: Test kfunc bpf_strcasecmp Rong Tao
  1 sibling, 2 replies; 6+ messages in thread
From: Rong Tao @ 2025-09-02  9:19 UTC (permalink / raw)
  To: andrii, ast, vmalik
  Cc: rtoax, Rong Tao, Daniel Borkmann, Martin KaFai Lau,
	Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Mykola Lysenko,
	Shuah Khan,
	open list:BPF [GENERAL] (Safe Dynamic Programs and Tools),
	open list, open list:KERNEL SELFTEST FRAMEWORK

From: Rong Tao <rongtao@cestc.cn>

bpf_strcasecmp() function performs same like bpf_strcmp() except ignoring
the case of the characters.

Signed-off-by: Rong Tao <rongtao@cestc.cn>
---
 kernel/bpf/helpers.c | 68 +++++++++++++++++++++++++++++++-------------
 1 file changed, 48 insertions(+), 20 deletions(-)

diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 401b4932cc49..238fd992c786 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -3349,45 +3349,72 @@ __bpf_kfunc void __bpf_trap(void)
  * __get_kernel_nofault instead of plain dereference to make them safe.
  */
 
-/**
- * bpf_strcmp - Compare two strings
- * @s1__ign: One string
- * @s2__ign: Another string
- *
- * Return:
- * * %0       - Strings are equal
- * * %-1      - @s1__ign is smaller
- * * %1       - @s2__ign is smaller
- * * %-EFAULT - Cannot read one of the strings
- * * %-E2BIG  - One of strings is too large
- * * %-ERANGE - One of strings is outside of kernel address space
- */
-__bpf_kfunc int bpf_strcmp(const char *s1__ign, const char *s2__ign)
+int __bpf_strcasecmp(const char *s1, const char *s2, bool ignore_case)
 {
 	char c1, c2;
 	int i;
 
-	if (!copy_from_kernel_nofault_allowed(s1__ign, 1) ||
-	    !copy_from_kernel_nofault_allowed(s2__ign, 1)) {
+	if (!copy_from_kernel_nofault_allowed(s1, 1) ||
+	    !copy_from_kernel_nofault_allowed(s2, 1)) {
 		return -ERANGE;
 	}
 
 	guard(pagefault)();
 	for (i = 0; i < XATTR_SIZE_MAX; i++) {
-		__get_kernel_nofault(&c1, s1__ign, char, err_out);
-		__get_kernel_nofault(&c2, s2__ign, char, err_out);
+		__get_kernel_nofault(&c1, s1, char, err_out);
+		__get_kernel_nofault(&c2, s2, char, err_out);
+		if (ignore_case) {
+			c1 = tolower(c1);
+			c2 = tolower(c2);
+		}
 		if (c1 != c2)
 			return c1 < c2 ? -1 : 1;
 		if (c1 == '\0')
 			return 0;
-		s1__ign++;
-		s2__ign++;
+		s1++;
+		s2++;
 	}
 	return -E2BIG;
 err_out:
 	return -EFAULT;
 }
 
+/**
+ * bpf_strcmp - Compare two strings
+ * @s1__ign: One string
+ * @s2__ign: Another string
+ *
+ * Return:
+ * * %0       - Strings are equal
+ * * %-1      - @s1__ign is smaller
+ * * %1       - @s2__ign is smaller
+ * * %-EFAULT - Cannot read one of the strings
+ * * %-E2BIG  - One of strings is too large
+ * * %-ERANGE - One of strings is outside of kernel address space
+ */
+__bpf_kfunc int bpf_strcmp(const char *s1__ign, const char *s2__ign)
+{
+	return __bpf_strcasecmp(s1__ign, s2__ign, false);
+}
+
+/**
+ * bpf_strcasecmp - Compare two strings, ignoring the case of the characters
+ * @s1__ign: One string
+ * @s2__ign: Another string
+ *
+ * Return:
+ * * %0       - Strings are equal
+ * * %-1      - @s1__ign is smaller
+ * * %1       - @s2__ign is smaller
+ * * %-EFAULT - Cannot read one of the strings
+ * * %-E2BIG  - One of strings is too large
+ * * %-ERANGE - One of strings is outside of kernel address space
+ */
+__bpf_kfunc int bpf_strcasecmp(const char *s1__ign, const char *s2__ign)
+{
+	return __bpf_strcasecmp(s1__ign, s2__ign, true);
+}
+
 /**
  * bpf_strnchr - Find a character in a length limited string
  * @s__ign: The string to be searched
@@ -3832,6 +3859,7 @@ BTF_ID_FLAGS(func, bpf_iter_dmabuf_destroy, KF_ITER_DESTROY | KF_SLEEPABLE)
 #endif
 BTF_ID_FLAGS(func, __bpf_trap)
 BTF_ID_FLAGS(func, bpf_strcmp);
+BTF_ID_FLAGS(func, bpf_strcasecmp);
 BTF_ID_FLAGS(func, bpf_strchr);
 BTF_ID_FLAGS(func, bpf_strchrnul);
 BTF_ID_FLAGS(func, bpf_strnchr);
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH bpf-next v3 2/2] selftests/bpf: Test kfunc bpf_strcasecmp
       [not found] <cover.1756804522.git.rtoax@foxmail.com>
  2025-09-02  9:19 ` [PATCH bpf-next v3 1/2] bpf: add bpf_strcasecmp kfunc Rong Tao
@ 2025-09-02  9:19 ` Rong Tao
  1 sibling, 0 replies; 6+ messages in thread
From: Rong Tao @ 2025-09-02  9:19 UTC (permalink / raw)
  To: andrii, ast, vmalik
  Cc: rtoax, Rong Tao, Daniel Borkmann, Martin KaFai Lau,
	Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend,
	KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Mykola Lysenko,
	Shuah Khan,
	open list:BPF [GENERAL] (Safe Dynamic Programs and Tools),
	open list, open list:KERNEL SELFTEST FRAMEWORK

From: Rong Tao <rongtao@cestc.cn>

Add testsuites for kfunc bpf_strcasecmp.

Signed-off-by: Rong Tao <rongtao@cestc.cn>
---
 tools/testing/selftests/bpf/prog_tests/string_kfuncs.c     | 1 +
 tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c | 6 ++++++
 tools/testing/selftests/bpf/progs/string_kfuncs_failure2.c | 1 +
 tools/testing/selftests/bpf/progs/string_kfuncs_success.c  | 5 +++++
 4 files changed, 13 insertions(+)

diff --git a/tools/testing/selftests/bpf/prog_tests/string_kfuncs.c b/tools/testing/selftests/bpf/prog_tests/string_kfuncs.c
index 35af8044d059..4d66fad3c8bd 100644
--- a/tools/testing/selftests/bpf/prog_tests/string_kfuncs.c
+++ b/tools/testing/selftests/bpf/prog_tests/string_kfuncs.c
@@ -8,6 +8,7 @@
 
 static const char * const test_cases[] = {
 	"strcmp",
+	"strcasecmp",
 	"strchr",
 	"strchrnul",
 	"strnchr",
diff --git a/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c b/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c
index 53af438bd998..99d72c68f76a 100644
--- a/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c
+++ b/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c
@@ -31,6 +31,8 @@ char *invalid_kern_ptr = (char *)-1;
 /* Passing NULL to string kfuncs (treated as a userspace ptr) */
 SEC("syscall") __retval(USER_PTR_ERR) int test_strcmp_null1(void *ctx) { return bpf_strcmp(NULL, "hello"); }
 SEC("syscall")  __retval(USER_PTR_ERR)int test_strcmp_null2(void *ctx) { return bpf_strcmp("hello", NULL); }
+SEC("syscall") __retval(USER_PTR_ERR) int test_strcasecmp_null1(void *ctx) { return bpf_strcasecmp(NULL, "HELLO"); }
+SEC("syscall")  __retval(USER_PTR_ERR)int test_strcasecmp_null2(void *ctx) { return bpf_strcasecmp("HELLO", NULL); }
 SEC("syscall")  __retval(USER_PTR_ERR)int test_strchr_null(void *ctx) { return bpf_strchr(NULL, 'a'); }
 SEC("syscall")  __retval(USER_PTR_ERR)int test_strchrnul_null(void *ctx) { return bpf_strchrnul(NULL, 'a'); }
 SEC("syscall")  __retval(USER_PTR_ERR)int test_strnchr_null(void *ctx) { return bpf_strnchr(NULL, 1, 'a'); }
@@ -49,6 +51,8 @@ SEC("syscall")  __retval(USER_PTR_ERR)int test_strnstr_null2(void *ctx) { return
 /* 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"); }
 SEC("syscall") __retval(USER_PTR_ERR) int test_strcmp_user_ptr2(void *ctx) { return bpf_strcmp("hello", user_ptr); }
+SEC("syscall") __retval(USER_PTR_ERR) int test_strcasecmp_user_ptr1(void *ctx) { return bpf_strcasecmp(user_ptr, "HELLO"); }
+SEC("syscall") __retval(USER_PTR_ERR) int test_strcasecmp_user_ptr2(void *ctx) { return bpf_strcasecmp("HELLO", user_ptr); }
 SEC("syscall") __retval(USER_PTR_ERR) int test_strchr_user_ptr(void *ctx) { return bpf_strchr(user_ptr, 'a'); }
 SEC("syscall") __retval(USER_PTR_ERR) int test_strchrnul_user_ptr(void *ctx) { return bpf_strchrnul(user_ptr, 'a'); }
 SEC("syscall") __retval(USER_PTR_ERR) int test_strnchr_user_ptr(void *ctx) { return bpf_strnchr(user_ptr, 1, 'a'); }
@@ -69,6 +73,8 @@ SEC("syscall") __retval(USER_PTR_ERR) int test_strnstr_user_ptr2(void *ctx) { re
 /* Passing invalid kernel ptr to string kfuncs should always return -EFAULT */
 SEC("syscall") __retval(-EFAULT) int test_strcmp_pagefault1(void *ctx) { return bpf_strcmp(invalid_kern_ptr, "hello"); }
 SEC("syscall") __retval(-EFAULT) int test_strcmp_pagefault2(void *ctx) { return bpf_strcmp("hello", invalid_kern_ptr); }
+SEC("syscall") __retval(-EFAULT) int test_strcasecmp_pagefault1(void *ctx) { return bpf_strcasecmp(invalid_kern_ptr, "HELLO"); }
+SEC("syscall") __retval(-EFAULT) int test_strcasecmp_pagefault2(void *ctx) { return bpf_strcasecmp("HELLO", invalid_kern_ptr); }
 SEC("syscall") __retval(-EFAULT) int test_strchr_pagefault(void *ctx) { return bpf_strchr(invalid_kern_ptr, 'a'); }
 SEC("syscall") __retval(-EFAULT) int test_strchrnul_pagefault(void *ctx) { return bpf_strchrnul(invalid_kern_ptr, 'a'); }
 SEC("syscall") __retval(-EFAULT) int test_strnchr_pagefault(void *ctx) { return bpf_strnchr(invalid_kern_ptr, 1, 'a'); }
diff --git a/tools/testing/selftests/bpf/progs/string_kfuncs_failure2.c b/tools/testing/selftests/bpf/progs/string_kfuncs_failure2.c
index 89fb4669b0e9..e41cc5601994 100644
--- a/tools/testing/selftests/bpf/progs/string_kfuncs_failure2.c
+++ b/tools/testing/selftests/bpf/progs/string_kfuncs_failure2.c
@@ -7,6 +7,7 @@
 char long_str[XATTR_SIZE_MAX + 1];
 
 SEC("syscall") int test_strcmp_too_long(void *ctx) { return bpf_strcmp(long_str, long_str); }
+SEC("syscall") int test_strcasecmp_too_long(void *ctx) { return bpf_strcasecmp(long_str, long_str); }
 SEC("syscall") int test_strchr_too_long(void *ctx) { return bpf_strchr(long_str, 'b'); }
 SEC("syscall") int test_strchrnul_too_long(void *ctx) { return bpf_strchrnul(long_str, 'b'); }
 SEC("syscall") int test_strnchr_too_long(void *ctx) { return bpf_strnchr(long_str, sizeof(long_str), 'b'); }
diff --git a/tools/testing/selftests/bpf/progs/string_kfuncs_success.c b/tools/testing/selftests/bpf/progs/string_kfuncs_success.c
index 46697f381878..67830456637b 100644
--- a/tools/testing/selftests/bpf/progs/string_kfuncs_success.c
+++ b/tools/testing/selftests/bpf/progs/string_kfuncs_success.c
@@ -12,6 +12,11 @@ char str[] = "hello world";
 /* Functional tests */
 __test(0) int test_strcmp_eq(void *ctx) { return bpf_strcmp(str, "hello world"); }
 __test(1) int test_strcmp_neq(void *ctx) { return bpf_strcmp(str, "hello"); }
+__test(0) int test_strcasecmp_eq1(void *ctx) { return bpf_strcasecmp(str, "hello world"); }
+__test(0) int test_strcasecmp_eq2(void *ctx) { return bpf_strcasecmp(str, "HELLO WORLD"); }
+__test(0) int test_strcasecmp_eq3(void *ctx) { return bpf_strcasecmp(str, "HELLO world"); }
+__test(1) int test_strcasecmp_neq1(void *ctx) { return bpf_strcasecmp(str, "hello"); }
+__test(1) int test_strcasecmp_neq2(void *ctx) { return bpf_strcasecmp(str, "HELLO"); }
 __test(1) int test_strchr_found(void *ctx) { return bpf_strchr(str, 'e'); }
 __test(11) int test_strchr_null(void *ctx) { return bpf_strchr(str, '\0'); }
 __test(-ENOENT) int test_strchr_notfound(void *ctx) { return bpf_strchr(str, 'x'); }
-- 
2.51.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH bpf-next v3 1/2] bpf: add bpf_strcasecmp kfunc
  2025-09-02  9:19 ` [PATCH bpf-next v3 1/2] bpf: add bpf_strcasecmp kfunc Rong Tao
@ 2025-09-02  9:45   ` Viktor Malik
  2025-09-02 16:54   ` Yonghong Song
  1 sibling, 0 replies; 6+ messages in thread
From: Viktor Malik @ 2025-09-02  9:45 UTC (permalink / raw)
  To: Rong Tao, andrii, ast
  Cc: Rong Tao, Daniel Borkmann, Martin KaFai Lau, Eduard Zingerman,
	Song Liu, Yonghong Song, John Fastabend, KP Singh,
	Stanislav Fomichev, Hao Luo, Jiri Olsa, Mykola Lysenko,
	Shuah Khan,
	open list:BPF [GENERAL] (Safe Dynamic Programs and Tools),
	open list, open list:KERNEL SELFTEST FRAMEWORK

On 9/2/25 11:19, Rong Tao wrote:
> From: Rong Tao <rongtao@cestc.cn>
> 
> bpf_strcasecmp() function performs same like bpf_strcmp() except ignoring
> the case of the characters.
> 
> Signed-off-by: Rong Tao <rongtao@cestc.cn>

For the series:

Acked-by: Viktor Malik <vmalik@redhat.com>

> ---
>  kernel/bpf/helpers.c | 68 +++++++++++++++++++++++++++++++-------------
>  1 file changed, 48 insertions(+), 20 deletions(-)
> 
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index 401b4932cc49..238fd992c786 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -3349,45 +3349,72 @@ __bpf_kfunc void __bpf_trap(void)
>   * __get_kernel_nofault instead of plain dereference to make them safe.
>   */
>  
> -/**
> - * bpf_strcmp - Compare two strings
> - * @s1__ign: One string
> - * @s2__ign: Another string
> - *
> - * Return:
> - * * %0       - Strings are equal
> - * * %-1      - @s1__ign is smaller
> - * * %1       - @s2__ign is smaller
> - * * %-EFAULT - Cannot read one of the strings
> - * * %-E2BIG  - One of strings is too large
> - * * %-ERANGE - One of strings is outside of kernel address space
> - */
> -__bpf_kfunc int bpf_strcmp(const char *s1__ign, const char *s2__ign)
> +int __bpf_strcasecmp(const char *s1, const char *s2, bool ignore_case)
>  {
>  	char c1, c2;
>  	int i;
>  
> -	if (!copy_from_kernel_nofault_allowed(s1__ign, 1) ||
> -	    !copy_from_kernel_nofault_allowed(s2__ign, 1)) {
> +	if (!copy_from_kernel_nofault_allowed(s1, 1) ||
> +	    !copy_from_kernel_nofault_allowed(s2, 1)) {
>  		return -ERANGE;
>  	}
>  
>  	guard(pagefault)();
>  	for (i = 0; i < XATTR_SIZE_MAX; i++) {
> -		__get_kernel_nofault(&c1, s1__ign, char, err_out);
> -		__get_kernel_nofault(&c2, s2__ign, char, err_out);
> +		__get_kernel_nofault(&c1, s1, char, err_out);
> +		__get_kernel_nofault(&c2, s2, char, err_out);
> +		if (ignore_case) {
> +			c1 = tolower(c1);
> +			c2 = tolower(c2);
> +		}
>  		if (c1 != c2)
>  			return c1 < c2 ? -1 : 1;
>  		if (c1 == '\0')
>  			return 0;
> -		s1__ign++;
> -		s2__ign++;
> +		s1++;
> +		s2++;
>  	}
>  	return -E2BIG;
>  err_out:
>  	return -EFAULT;
>  }
>  
> +/**
> + * bpf_strcmp - Compare two strings
> + * @s1__ign: One string
> + * @s2__ign: Another string
> + *
> + * Return:
> + * * %0       - Strings are equal
> + * * %-1      - @s1__ign is smaller
> + * * %1       - @s2__ign is smaller
> + * * %-EFAULT - Cannot read one of the strings
> + * * %-E2BIG  - One of strings is too large
> + * * %-ERANGE - One of strings is outside of kernel address space
> + */
> +__bpf_kfunc int bpf_strcmp(const char *s1__ign, const char *s2__ign)
> +{
> +	return __bpf_strcasecmp(s1__ign, s2__ign, false);
> +}
> +
> +/**
> + * bpf_strcasecmp - Compare two strings, ignoring the case of the characters
> + * @s1__ign: One string
> + * @s2__ign: Another string
> + *
> + * Return:
> + * * %0       - Strings are equal
> + * * %-1      - @s1__ign is smaller
> + * * %1       - @s2__ign is smaller
> + * * %-EFAULT - Cannot read one of the strings
> + * * %-E2BIG  - One of strings is too large
> + * * %-ERANGE - One of strings is outside of kernel address space
> + */
> +__bpf_kfunc int bpf_strcasecmp(const char *s1__ign, const char *s2__ign)
> +{
> +	return __bpf_strcasecmp(s1__ign, s2__ign, true);
> +}
> +
>  /**
>   * bpf_strnchr - Find a character in a length limited string
>   * @s__ign: The string to be searched
> @@ -3832,6 +3859,7 @@ BTF_ID_FLAGS(func, bpf_iter_dmabuf_destroy, KF_ITER_DESTROY | KF_SLEEPABLE)
>  #endif
>  BTF_ID_FLAGS(func, __bpf_trap)
>  BTF_ID_FLAGS(func, bpf_strcmp);
> +BTF_ID_FLAGS(func, bpf_strcasecmp);
>  BTF_ID_FLAGS(func, bpf_strchr);
>  BTF_ID_FLAGS(func, bpf_strchrnul);
>  BTF_ID_FLAGS(func, bpf_strnchr);


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH bpf-next v3 1/2] bpf: add bpf_strcasecmp kfunc
  2025-09-02  9:19 ` [PATCH bpf-next v3 1/2] bpf: add bpf_strcasecmp kfunc Rong Tao
  2025-09-02  9:45   ` Viktor Malik
@ 2025-09-02 16:54   ` Yonghong Song
  2025-09-02 23:49     ` Rong Tao
  1 sibling, 1 reply; 6+ messages in thread
From: Yonghong Song @ 2025-09-02 16:54 UTC (permalink / raw)
  To: Rong Tao, andrii, ast, vmalik
  Cc: Rong Tao, Daniel Borkmann, Martin KaFai Lau, Eduard Zingerman,
	Song Liu, John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo,
	Jiri Olsa, Mykola Lysenko, Shuah Khan,
	open list:BPF [GENERAL] (Safe Dynamic Programs and Tools),
	open list, open list:KERNEL SELFTEST FRAMEWORK



On 9/2/25 2:19 AM, Rong Tao wrote:
> From: Rong Tao <rongtao@cestc.cn>
>
> bpf_strcasecmp() function performs same like bpf_strcmp() except ignoring
> the case of the characters.
>
> Signed-off-by: Rong Tao <rongtao@cestc.cn>
> ---
>   kernel/bpf/helpers.c | 68 +++++++++++++++++++++++++++++++-------------
>   1 file changed, 48 insertions(+), 20 deletions(-)
>
> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
> index 401b4932cc49..238fd992c786 100644
> --- a/kernel/bpf/helpers.c
> +++ b/kernel/bpf/helpers.c
> @@ -3349,45 +3349,72 @@ __bpf_kfunc void __bpf_trap(void)
>    * __get_kernel_nofault instead of plain dereference to make them safe.
>    */
>   
> -/**
> - * bpf_strcmp - Compare two strings
> - * @s1__ign: One string
> - * @s2__ign: Another string
> - *
> - * Return:
> - * * %0       - Strings are equal
> - * * %-1      - @s1__ign is smaller
> - * * %1       - @s2__ign is smaller
> - * * %-EFAULT - Cannot read one of the strings
> - * * %-E2BIG  - One of strings is too large
> - * * %-ERANGE - One of strings is outside of kernel address space
> - */
> -__bpf_kfunc int bpf_strcmp(const char *s1__ign, const char *s2__ign)
> +int __bpf_strcasecmp(const char *s1, const char *s2, bool ignore_case)

The function __bpf_strcasecmp should be a static function.

>   {
>   	char c1, c2;
>   	int i;
>   
> -	if (!copy_from_kernel_nofault_allowed(s1__ign, 1) ||
> -	    !copy_from_kernel_nofault_allowed(s2__ign, 1)) {
> +	if (!copy_from_kernel_nofault_allowed(s1, 1) ||
> +	    !copy_from_kernel_nofault_allowed(s2, 1)) {
>   		return -ERANGE;
>   	}
>   
>   	guard(pagefault)();
>   	for (i = 0; i < XATTR_SIZE_MAX; i++) {
> -		__get_kernel_nofault(&c1, s1__ign, char, err_out);
> -		__get_kernel_nofault(&c2, s2__ign, char, err_out);
> +		__get_kernel_nofault(&c1, s1, char, err_out);
> +		__get_kernel_nofault(&c2, s2, char, err_out);
> +		if (ignore_case) {
> +			c1 = tolower(c1);
> +			c2 = tolower(c2);
> +		}
>   		if (c1 != c2)
>   			return c1 < c2 ? -1 : 1;
>   		if (c1 == '\0')
>   			return 0;
> -		s1__ign++;
> -		s2__ign++;
> +		s1++;
> +		s2++;
>   	}
>   	return -E2BIG;
>   err_out:
>   	return -EFAULT;
>   }
>   
> +/**
> + * bpf_strcmp - Compare two strings
> + * @s1__ign: One string
> + * @s2__ign: Another string
> + *
> + * Return:
> + * * %0       - Strings are equal
> + * * %-1      - @s1__ign is smaller
> + * * %1       - @s2__ign is smaller
> + * * %-EFAULT - Cannot read one of the strings
> + * * %-E2BIG  - One of strings is too large
> + * * %-ERANGE - One of strings is outside of kernel address space
> + */
> +__bpf_kfunc int bpf_strcmp(const char *s1__ign, const char *s2__ign)
> +{
> +	return __bpf_strcasecmp(s1__ign, s2__ign, false);
> +}
> +
> +/**
> + * bpf_strcasecmp - Compare two strings, ignoring the case of the characters
> + * @s1__ign: One string
> + * @s2__ign: Another string
> + *
> + * Return:
> + * * %0       - Strings are equal
> + * * %-1      - @s1__ign is smaller
> + * * %1       - @s2__ign is smaller
> + * * %-EFAULT - Cannot read one of the strings
> + * * %-E2BIG  - One of strings is too large
> + * * %-ERANGE - One of strings is outside of kernel address space
> + */
> +__bpf_kfunc int bpf_strcasecmp(const char *s1__ign, const char *s2__ign)
> +{
> +	return __bpf_strcasecmp(s1__ign, s2__ign, true);
> +}
> +
>   /**
>    * bpf_strnchr - Find a character in a length limited string
>    * @s__ign: The string to be searched
> @@ -3832,6 +3859,7 @@ BTF_ID_FLAGS(func, bpf_iter_dmabuf_destroy, KF_ITER_DESTROY | KF_SLEEPABLE)
>   #endif
>   BTF_ID_FLAGS(func, __bpf_trap)
>   BTF_ID_FLAGS(func, bpf_strcmp);
> +BTF_ID_FLAGS(func, bpf_strcasecmp);
>   BTF_ID_FLAGS(func, bpf_strchr);
>   BTF_ID_FLAGS(func, bpf_strchrnul);
>   BTF_ID_FLAGS(func, bpf_strnchr);


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH bpf-next v3 1/2] bpf: add bpf_strcasecmp kfunc
  2025-09-02 16:54   ` Yonghong Song
@ 2025-09-02 23:49     ` Rong Tao
  0 siblings, 0 replies; 6+ messages in thread
From: Rong Tao @ 2025-09-02 23:49 UTC (permalink / raw)
  To: Yonghong Song, andrii, ast, vmalik
  Cc: Rong Tao, Daniel Borkmann, Martin KaFai Lau, Eduard Zingerman,
	Song Liu, John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo,
	Jiri Olsa, Mykola Lysenko, Shuah Khan,
	open list:BPF [GENERAL] (Safe Dynamic Programs and Tools),
	open list, open list:KERNEL SELFTEST FRAMEWORK


On 9/3/25 00:54, Yonghong Song wrote:
>
>
> On 9/2/25 2:19 AM, Rong Tao wrote:
>> From: Rong Tao <rongtao@cestc.cn>
>>
>> bpf_strcasecmp() function performs same like bpf_strcmp() except 
>> ignoring
>> the case of the characters.
>>
>> Signed-off-by: Rong Tao <rongtao@cestc.cn>
>> ---
>>   kernel/bpf/helpers.c | 68 +++++++++++++++++++++++++++++++-------------
>>   1 file changed, 48 insertions(+), 20 deletions(-)
>>
>> diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
>> index 401b4932cc49..238fd992c786 100644
>> --- a/kernel/bpf/helpers.c
>> +++ b/kernel/bpf/helpers.c
>> @@ -3349,45 +3349,72 @@ __bpf_kfunc void __bpf_trap(void)
>>    * __get_kernel_nofault instead of plain dereference to make them 
>> safe.
>>    */
>>   -/**
>> - * bpf_strcmp - Compare two strings
>> - * @s1__ign: One string
>> - * @s2__ign: Another string
>> - *
>> - * Return:
>> - * * %0       - Strings are equal
>> - * * %-1      - @s1__ign is smaller
>> - * * %1       - @s2__ign is smaller
>> - * * %-EFAULT - Cannot read one of the strings
>> - * * %-E2BIG  - One of strings is too large
>> - * * %-ERANGE - One of strings is outside of kernel address space
>> - */
>> -__bpf_kfunc int bpf_strcmp(const char *s1__ign, const char *s2__ign)
>> +int __bpf_strcasecmp(const char *s1, const char *s2, bool ignore_case)
>
> The function __bpf_strcasecmp should be a static function.

Thanks a lot, I just add 'static' and tested it, submit V4, please review.

Rong Tao

>
>>   {
>>       char c1, c2;
>>       int i;
>>   -    if (!copy_from_kernel_nofault_allowed(s1__ign, 1) ||
>> -        !copy_from_kernel_nofault_allowed(s2__ign, 1)) {
>> +    if (!copy_from_kernel_nofault_allowed(s1, 1) ||
>> +        !copy_from_kernel_nofault_allowed(s2, 1)) {
>>           return -ERANGE;
>>       }
>>         guard(pagefault)();
>>       for (i = 0; i < XATTR_SIZE_MAX; i++) {
>> -        __get_kernel_nofault(&c1, s1__ign, char, err_out);
>> -        __get_kernel_nofault(&c2, s2__ign, char, err_out);
>> +        __get_kernel_nofault(&c1, s1, char, err_out);
>> +        __get_kernel_nofault(&c2, s2, char, err_out);
>> +        if (ignore_case) {
>> +            c1 = tolower(c1);
>> +            c2 = tolower(c2);
>> +        }
>>           if (c1 != c2)
>>               return c1 < c2 ? -1 : 1;
>>           if (c1 == '\0')
>>               return 0;
>> -        s1__ign++;
>> -        s2__ign++;
>> +        s1++;
>> +        s2++;
>>       }
>>       return -E2BIG;
>>   err_out:
>>       return -EFAULT;
>>   }
>>   +/**
>> + * bpf_strcmp - Compare two strings
>> + * @s1__ign: One string
>> + * @s2__ign: Another string
>> + *
>> + * Return:
>> + * * %0       - Strings are equal
>> + * * %-1      - @s1__ign is smaller
>> + * * %1       - @s2__ign is smaller
>> + * * %-EFAULT - Cannot read one of the strings
>> + * * %-E2BIG  - One of strings is too large
>> + * * %-ERANGE - One of strings is outside of kernel address space
>> + */
>> +__bpf_kfunc int bpf_strcmp(const char *s1__ign, const char *s2__ign)
>> +{
>> +    return __bpf_strcasecmp(s1__ign, s2__ign, false);
>> +}
>> +
>> +/**
>> + * bpf_strcasecmp - Compare two strings, ignoring the case of the 
>> characters
>> + * @s1__ign: One string
>> + * @s2__ign: Another string
>> + *
>> + * Return:
>> + * * %0       - Strings are equal
>> + * * %-1      - @s1__ign is smaller
>> + * * %1       - @s2__ign is smaller
>> + * * %-EFAULT - Cannot read one of the strings
>> + * * %-E2BIG  - One of strings is too large
>> + * * %-ERANGE - One of strings is outside of kernel address space
>> + */
>> +__bpf_kfunc int bpf_strcasecmp(const char *s1__ign, const char 
>> *s2__ign)
>> +{
>> +    return __bpf_strcasecmp(s1__ign, s2__ign, true);
>> +}
>> +
>>   /**
>>    * bpf_strnchr - Find a character in a length limited string
>>    * @s__ign: The string to be searched
>> @@ -3832,6 +3859,7 @@ BTF_ID_FLAGS(func, bpf_iter_dmabuf_destroy, 
>> KF_ITER_DESTROY | KF_SLEEPABLE)
>>   #endif
>>   BTF_ID_FLAGS(func, __bpf_trap)
>>   BTF_ID_FLAGS(func, bpf_strcmp);
>> +BTF_ID_FLAGS(func, bpf_strcasecmp);
>>   BTF_ID_FLAGS(func, bpf_strchr);
>>   BTF_ID_FLAGS(func, bpf_strchrnul);
>>   BTF_ID_FLAGS(func, bpf_strnchr);
>


^ permalink raw reply	[flat|nested] 6+ messages in thread

* re: [PATCH bpf-next v3 1/2] bpf: add bpf_strcasecmp kfunc
@ 2025-09-03 11:35 Sebastian Ramadan
  0 siblings, 0 replies; 6+ messages in thread
From: Sebastian Ramadan @ 2025-09-03 11:35 UTC (permalink / raw)
  To: linux-kernel@vger.kernel.org

Hi,

While reviewing the recent patch ([PATCH bpf-next v3 1/2] bpf: add
bpf_strcasecmp kfunc), I noticed a small but important standards
compliance issue regarding the use of tolower() with char variables:

char c1, c2;
// ...
if (ignore_case) {
    c1 = tolower(c1);
    c2 = tolower(c2);
}

According to the ISO C standard, functions and macros in <ctype.h>
(such as tolower()) are only defined for arguments that are either:
1/ Representable as an unsigned char, or
2/ Equal to the special value EOF.

Passing a plain char that contains a negative value (other than EOF)
results in undefined behavior. This can easily go unnoticed in
environments where char defaults to unsigned (such as GCC on x86), but
will break or behave unpredictably on platforms where char is signed.

To ensure portable and defined behavior, it's typically recommended to
cast to unsigned char before passing to tolower():

c1 = tolower((unsigned char)c1);
c2 = tolower((unsigned char)c2);

This ensures compliance with the standard and avoids silent issues
across different toolchains and architectures.

While this may not cause immediate problems in the GNU-C ecosystem,
implicitly relying on compiler-specific behavior can gradually reduce
the kernel's portability. Keeping these cases in check helps maintain
the kernel's long-standing goal of wide platform support.

Thanks for your time, and for the ongoing work toward clean and
portable kernel code.

Regards, Sebastian Ramadan

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-09-03 11:35 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <cover.1756804522.git.rtoax@foxmail.com>
2025-09-02  9:19 ` [PATCH bpf-next v3 1/2] bpf: add bpf_strcasecmp kfunc Rong Tao
2025-09-02  9:45   ` Viktor Malik
2025-09-02 16:54   ` Yonghong Song
2025-09-02 23:49     ` Rong Tao
2025-09-02  9:19 ` [PATCH bpf-next v3 2/2] selftests/bpf: Test kfunc bpf_strcasecmp Rong Tao
2025-09-03 11:35 [PATCH bpf-next v3 1/2] bpf: add bpf_strcasecmp kfunc Sebastian Ramadan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).