]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: add bpf_strncasecmp kfunc
authorYuzuki Ishiyama <ishiyama@hpc.is.uec.ac.jp>
Wed, 21 Jan 2026 03:33:27 +0000 (12:33 +0900)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 21 Jan 2026 17:42:53 +0000 (09:42 -0800)
bpf_strncasecmp() function performs same like bpf_strcasecmp() except
limiting the comparison to a specific length.

Signed-off-by: Yuzuki Ishiyama <ishiyama@hpc.is.uec.ac.jp>
Acked-by: Viktor Malik <vmalik@redhat.com>
Acked-by: Mykyta Yatsenko <mykyta.yatsenko5@gmail.com>
Link: https://lore.kernel.org/r/20260121033328.1850010-2-ishiyama@hpc.is.uec.ac.jp
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/helpers.c

index 637677815365fdd0f7aa568d4fb36ec17c8a2bff..b54ec0e945aa383d560319ed978a98f146e3992d 100644 (file)
@@ -3413,7 +3413,7 @@ __bpf_kfunc void __bpf_trap(void)
  * __get_kernel_nofault instead of plain dereference to make them safe.
  */
 
-static int __bpf_strcasecmp(const char *s1, const char *s2, bool ignore_case)
+static int __bpf_strncasecmp(const char *s1, const char *s2, bool ignore_case, size_t len)
 {
        char c1, c2;
        int i;
@@ -3424,7 +3424,7 @@ static int __bpf_strcasecmp(const char *s1, const char *s2, bool ignore_case)
        }
 
        guard(pagefault)();
-       for (i = 0; i < XATTR_SIZE_MAX; i++) {
+       for (i = 0; i < len && i < XATTR_SIZE_MAX; i++) {
                __get_kernel_nofault(&c1, s1, char, err_out);
                __get_kernel_nofault(&c2, s2, char, err_out);
                if (ignore_case) {
@@ -3438,7 +3438,7 @@ static int __bpf_strcasecmp(const char *s1, const char *s2, bool ignore_case)
                s1++;
                s2++;
        }
-       return -E2BIG;
+       return i == XATTR_SIZE_MAX ? -E2BIG : 0;
 err_out:
        return -EFAULT;
 }
@@ -3458,7 +3458,7 @@ err_out:
  */
 __bpf_kfunc int bpf_strcmp(const char *s1__ign, const char *s2__ign)
 {
-       return __bpf_strcasecmp(s1__ign, s2__ign, false);
+       return __bpf_strncasecmp(s1__ign, s2__ign, false, XATTR_SIZE_MAX);
 }
 
 /**
@@ -3476,7 +3476,26 @@ __bpf_kfunc int bpf_strcmp(const char *s1__ign, const char *s2__ign)
  */
 __bpf_kfunc int bpf_strcasecmp(const char *s1__ign, const char *s2__ign)
 {
-       return __bpf_strcasecmp(s1__ign, s2__ign, true);
+       return __bpf_strncasecmp(s1__ign, s2__ign, true, XATTR_SIZE_MAX);
+}
+
+/*
+ * bpf_strncasecmp - Compare two length-limited strings, ignoring case
+ * @s1__ign: One string
+ * @s2__ign: Another string
+ * @len: The maximum number of characters to compare
+ *
+ * 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_strncasecmp(const char *s1__ign, const char *s2__ign, size_t len)
+{
+       return __bpf_strncasecmp(s1__ign, s2__ign, true, len);
 }
 
 /**
@@ -4526,6 +4545,7 @@ BTF_ID_FLAGS(func, bpf_iter_dmabuf_destroy, KF_ITER_DESTROY | KF_SLEEPABLE)
 BTF_ID_FLAGS(func, __bpf_trap)
 BTF_ID_FLAGS(func, bpf_strcmp);
 BTF_ID_FLAGS(func, bpf_strcasecmp);
+BTF_ID_FLAGS(func, bpf_strncasecmp);
 BTF_ID_FLAGS(func, bpf_strchr);
 BTF_ID_FLAGS(func, bpf_strchrnul);
 BTF_ID_FLAGS(func, bpf_strnchr);