Linux Kernel Selftest development
 help / color / mirror / Atom feed
From: Leon Hwang <leon.hwang@linux.dev>
To: bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>,
	Andrii Nakryiko <andrii@kernel.org>,
	Eduard Zingerman <eddyz87@gmail.com>,
	Kumar Kartikeya Dwivedi <memxor@gmail.com>,
	Martin KaFai Lau <martin.lau@linux.dev>,
	Song Liu <song@kernel.org>,
	Yonghong Song <yonghong.song@linux.dev>,
	Jiri Olsa <jolsa@kernel.org>,
	Emil Tsalapatis <emil@etsalapatis.com>,
	Ihor Solodrai <ihor.solodrai@linux.dev>,
	Shuah Khan <shuah@kernel.org>, Leon Hwang <leon.hwang@linux.dev>,
	Rong Tao <rongtao@cestc.cn>,
	Yuzuki Ishiyama <ishiyama@hpc.is.uec.ac.jp>,
	Viktor Malik <vmalik@redhat.com>,
	linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org
Subject: [RFC PATCH bpf-next 5/6] selftests/bpf: Exercise word-at-a-time string kfuncs
Date: Tue, 28 Jul 2026 22:57:26 +0800	[thread overview]
Message-ID: <20260728145727.45153-6-leon.hwang@linux.dev> (raw)
In-Reply-To: <20260728145727.45153-1-leon.hwang@linux.dev>

Add functional coverage for aligned and unaligned strings across
the scan, comparison, span, and substring families. Cover matches and
mismatches beyond the first word as well as the length-limited substring
suffix rule.

Use aligned invalid kernel addresses to exercise a failed
word-sized nofault load and its byte-sized retry.

Assisted-by: Codex:gpt-5.6-sol
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
 .../bpf/progs/string_kfuncs_failure1.c        | 58 +++++++++++++
 .../bpf/progs/string_kfuncs_success.c         | 86 +++++++++++++++++++
 2 files changed, 144 insertions(+)

diff --git a/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c b/tools/testing/selftests/bpf/progs/string_kfuncs_failure1.c
index bddc4e8579d2..05f93c7cd07c 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 *invalid_aligned_kern_ptr = (char *)-8;
 
 /*
  * When passing userspace pointers, the error code differs based on arch:
@@ -108,4 +109,61 @@ SEC("syscall") __retval(-EFAULT) int test_strnstr_pagefault2(void *ctx) { return
 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); }
 
+/* Exercise word-load faults and the byte retry at the same address. */
+SEC("syscall")
+__retval(-EFAULT)
+int test_strncasecmp_word_pagefault(void *ctx)
+{
+	return bpf_strncasecmp(invalid_aligned_kern_ptr, "12345678", 8);
+}
+
+SEC("syscall")
+__retval(-EFAULT)
+int test_strnchr_word_pagefault(void *ctx)
+{
+	return bpf_strnchr(invalid_aligned_kern_ptr, 8, 'a');
+}
+
+SEC("syscall")
+__retval(-EFAULT)
+int test_strrchr_word_pagefault(void *ctx)
+{
+	return bpf_strrchr(invalid_aligned_kern_ptr, 'a');
+}
+
+SEC("syscall")
+__retval(-EFAULT)
+int test_strnlen_word_pagefault(void *ctx)
+{
+	return bpf_strnlen(invalid_aligned_kern_ptr, 8);
+}
+
+SEC("syscall")
+__retval(-EFAULT)
+int test_strspn_word_pagefault(void *ctx)
+{
+	return bpf_strspn(invalid_aligned_kern_ptr, "a");
+}
+
+SEC("syscall")
+__retval(-EFAULT)
+int test_strspn_set_word_pagefault(void *ctx)
+{
+	return bpf_strspn("a", invalid_aligned_kern_ptr);
+}
+
+SEC("syscall")
+__retval(-EFAULT)
+int test_strnstr_word_pagefault1(void *ctx)
+{
+	return bpf_strnstr(invalid_aligned_kern_ptr, "12345678", 8);
+}
+
+SEC("syscall")
+__retval(-EFAULT)
+int test_strnstr_word_pagefault2(void *ctx)
+{
+	return bpf_strnstr("12345678", invalid_aligned_kern_ptr, 8);
+}
+
 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..ec72410e17a1 100644
--- a/tools/testing/selftests/bpf/progs/string_kfuncs_success.c
+++ b/tools/testing/selftests/bpf/progs/string_kfuncs_success.c
@@ -6,6 +6,11 @@
 #include "errno.h"
 
 char str[] = "hello world";
+char aligned_str[] __aligned(8) = "0123456789abcdef0123456789ABCDEF";
+char unaligned_str[] __aligned(8) = "_0123456789abcdef0123456789ABCDEF";
+char scan_order[] __aligned(8) = { 'a', 'H', '\0', 'H', 'x', 'x', 'x', 'x' };
+char compare_order1[] __aligned(8) = { 'a', 'b', '\0', 'x', 'x', 'x', 'x', 'x' };
+char compare_order2[] __aligned(8) = { 'a', 'b', '\0', 'y', 'y', 'y', 'y', 'y' };
 
 #define __test(retval) SEC("syscall") __success __retval(retval)
 
@@ -60,4 +65,85 @@ __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); }
 
+/* Exercise aligned word loads, mask ordering, and unaligned prefixes. */
+__test(30) int test_strnchr_word(void *ctx) { return bpf_strnchr(aligned_str, 32, 'E'); }
+
+__test(1) int test_strnchr_word_before_null(void *ctx)
+{
+	return bpf_strnchr(scan_order, sizeof(scan_order), 'H');
+}
+
+__test(-ENOENT) int test_strnchr_word_after_null(void *ctx)
+{
+	return bpf_strnchr(scan_order, sizeof(scan_order), 'x');
+}
+
+__test(2) int test_strchrnul_word_after_null(void *ctx)
+{
+	return bpf_strchrnul(scan_order, 'x');
+}
+
+__test(1) int test_strrchr_word_after_null(void *ctx)
+{
+	return bpf_strrchr(scan_order, 'H');
+}
+
+__test(2) int test_strnlen_word_null(void *ctx)
+{
+	return bpf_strnlen(scan_order, sizeof(scan_order));
+}
+
+__test(32) int test_strlen_word(void *ctx) { return bpf_strlen(aligned_str); }
+
+__test(0) int test_strcmp_word(void *ctx) { return bpf_strcmp(aligned_str, unaligned_str + 1); }
+
+__test(0) int test_strcmp_word_after_null(void *ctx)
+{
+	return bpf_strcmp(compare_order1, compare_order2);
+}
+
+__test(-1) int test_strcmp_word_mismatch(void *ctx)
+{
+	return bpf_strcmp(aligned_str, "0123456789abcdef1123456789abcdef");
+}
+
+__test(32) int test_strspn_word(void *ctx)
+{
+	return bpf_strspn(aligned_str, "0123456789abcdefABCDEF");
+}
+
+__test(0) int test_strspn_word_set_after_null(void *ctx)
+{
+	return bpf_strspn("xx", scan_order);
+}
+
+__test(30) int test_strcspn_word(void *ctx) { return bpf_strcspn(unaligned_str + 1, "E"); }
+
+__test(16) int test_strstr_word(void *ctx) { return bpf_strstr(aligned_str, "0123456789ABCDEF"); }
+
+__test(16) int test_strstr_unaligned(void *ctx)
+{
+	return bpf_strstr(unaligned_str + 1, "0123456789ABCDEF");
+}
+
+__test(15) int test_strcasestr_word(void *ctx)
+{
+	return bpf_strcasestr(aligned_str, "F0123456789ABCDEF");
+}
+
+__test(0) int test_strnstr_word_suffix(void *ctx)
+{
+	return bpf_strnstr(aligned_str, "0123456789abcdef", 16);
+}
+
+__test(-ENOENT) int test_strnstr_word_truncated(void *ctx)
+{
+	return bpf_strnstr(aligned_str, "0123456789abcdef0", 16);
+}
+
+__test(0) int test_strnstr_word_after_null(void *ctx)
+{
+	return bpf_strnstr(compare_order1, compare_order2, sizeof(compare_order1));
+}
+
 char _license[] SEC("license") = "GPL";
-- 
2.55.0


  parent reply	other threads:[~2026-07-28 14:59 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-28 14:57 [RFC PATCH bpf-next 0/6] bpf: Optimize string kfuncs Leon Hwang
2026-07-28 14:57 ` [RFC PATCH bpf-next 1/6] bpf: Optimize string scan kfuncs Leon Hwang
2026-07-28 14:57 ` [RFC PATCH bpf-next 2/6] bpf: Optimize string comparison kfuncs Leon Hwang
2026-07-28 14:57 ` [RFC PATCH bpf-next 3/6] bpf: Optimize string span kfuncs Leon Hwang
2026-07-28 14:57 ` [RFC PATCH bpf-next 4/6] bpf: Optimize string substring kfuncs Leon Hwang
2026-07-28 14:57 ` Leon Hwang [this message]
2026-07-28 14:57 ` [RFC PATCH bpf-next 6/6] selftests/bpf: Benchmark string kfuncs Leon Hwang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260728145727.45153-6-leon.hwang@linux.dev \
    --to=leon.hwang@linux.dev \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=emil@etsalapatis.com \
    --cc=ihor.solodrai@linux.dev \
    --cc=ishiyama@hpc.is.uec.ac.jp \
    --cc=jolsa@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=memxor@gmail.com \
    --cc=rongtao@cestc.cn \
    --cc=shuah@kernel.org \
    --cc=song@kernel.org \
    --cc=vmalik@redhat.com \
    --cc=yonghong.song@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox