Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: add bpf_strcasecmp kfunc

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

Signed-off-by: Rong Tao <rongtao@cestc.cn>
Acked-by: Yonghong Song <yonghong.song@linux.dev>
Acked-by: Viktor Malik <vmalik@redhat.com>
Link: https://lore.kernel.org/r/tencent_292BD3682A628581AA904996D8E59F4ACD06@qq.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Rong Tao and committed by
Alexei Starovoitov
19559e84 525ac69b

+49 -21
+49 -21
kernel/bpf/helpers.c
··· 3349 3349 * __get_kernel_nofault instead of plain dereference to make them safe. 3350 3350 */ 3351 3351 3352 + static int __bpf_strcasecmp(const char *s1, const char *s2, bool ignore_case) 3353 + { 3354 + char c1, c2; 3355 + int i; 3356 + 3357 + if (!copy_from_kernel_nofault_allowed(s1, 1) || 3358 + !copy_from_kernel_nofault_allowed(s2, 1)) { 3359 + return -ERANGE; 3360 + } 3361 + 3362 + guard(pagefault)(); 3363 + for (i = 0; i < XATTR_SIZE_MAX; i++) { 3364 + __get_kernel_nofault(&c1, s1, char, err_out); 3365 + __get_kernel_nofault(&c2, s2, char, err_out); 3366 + if (ignore_case) { 3367 + c1 = tolower(c1); 3368 + c2 = tolower(c2); 3369 + } 3370 + if (c1 != c2) 3371 + return c1 < c2 ? -1 : 1; 3372 + if (c1 == '\0') 3373 + return 0; 3374 + s1++; 3375 + s2++; 3376 + } 3377 + return -E2BIG; 3378 + err_out: 3379 + return -EFAULT; 3380 + } 3381 + 3352 3382 /** 3353 3383 * bpf_strcmp - Compare two strings 3354 3384 * @s1__ign: One string ··· 3394 3364 */ 3395 3365 __bpf_kfunc int bpf_strcmp(const char *s1__ign, const char *s2__ign) 3396 3366 { 3397 - char c1, c2; 3398 - int i; 3367 + return __bpf_strcasecmp(s1__ign, s2__ign, false); 3368 + } 3399 3369 3400 - if (!copy_from_kernel_nofault_allowed(s1__ign, 1) || 3401 - !copy_from_kernel_nofault_allowed(s2__ign, 1)) { 3402 - return -ERANGE; 3403 - } 3404 - 3405 - guard(pagefault)(); 3406 - for (i = 0; i < XATTR_SIZE_MAX; i++) { 3407 - __get_kernel_nofault(&c1, s1__ign, char, err_out); 3408 - __get_kernel_nofault(&c2, s2__ign, char, err_out); 3409 - if (c1 != c2) 3410 - return c1 < c2 ? -1 : 1; 3411 - if (c1 == '\0') 3412 - return 0; 3413 - s1__ign++; 3414 - s2__ign++; 3415 - } 3416 - return -E2BIG; 3417 - err_out: 3418 - return -EFAULT; 3370 + /** 3371 + * bpf_strcasecmp - Compare two strings, ignoring the case of the characters 3372 + * @s1__ign: One string 3373 + * @s2__ign: Another string 3374 + * 3375 + * Return: 3376 + * * %0 - Strings are equal 3377 + * * %-1 - @s1__ign is smaller 3378 + * * %1 - @s2__ign is smaller 3379 + * * %-EFAULT - Cannot read one of the strings 3380 + * * %-E2BIG - One of strings is too large 3381 + * * %-ERANGE - One of strings is outside of kernel address space 3382 + */ 3383 + __bpf_kfunc int bpf_strcasecmp(const char *s1__ign, const char *s2__ign) 3384 + { 3385 + return __bpf_strcasecmp(s1__ign, s2__ign, true); 3419 3386 } 3420 3387 3421 3388 /** ··· 3859 3832 #endif 3860 3833 BTF_ID_FLAGS(func, __bpf_trap) 3861 3834 BTF_ID_FLAGS(func, bpf_strcmp); 3835 + BTF_ID_FLAGS(func, bpf_strcasecmp); 3862 3836 BTF_ID_FLAGS(func, bpf_strchr); 3863 3837 BTF_ID_FLAGS(func, bpf_strchrnul); 3864 3838 BTF_ID_FLAGS(func, bpf_strnchr);