From: Muhammad Usama Anjum <usama.anjum@arm.com>
To: Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Mark Rutland <mark.rutland@arm.com>,
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>,
Andrew Morton <akpm@linux-foundation.org>,
David Hildenbrand <david@kernel.org>,
Lorenzo Stoakes <ljs@kernel.org>,
"Liam R. Howlett" <liam@infradead.org>,
Vlastimil Babka <vbabka@kernel.org>,
Mike Rapoport <rppt@kernel.org>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>,
linux-arm-kernel@lists.infradead.org (moderated list:ARM64 PORT
(AARCH64 ARCHITECTURE)), linux-kernel@vger.kernel.org (open list),
bpf@vger.kernel.org (open list:BPF [GENERAL] (Safe Dynamic
Programs and Tools)),
linux-mm@kvack.org (open list:MEMORY MANAGEMENT - CORE)
Cc: Muhammad Usama Anjum <usama.anjum@arm.com>
Subject: [PATCH 7/7] bpf: Batch TCO handling in string kfuncs
Date: Mon, 24 Aug 2026 17:04:53 +0100 [thread overview]
Message-ID: <20260824160523.3907021-9-usama.anjum@arm.com> (raw)
In-Reply-To: <20260824160523.3907021-1-usama.anjum@arm.com>
BPF string kfuncs cannot rely on NUL termination, so they scan memory with
kernel nofault loads. With Hardware Tag-Based KASAN in asynchronous or
asymmetric mode, every arm64 load sets and clears PSTATE.TCO.
Use bare loads and hold one nofault region across each string operation.
The scope guard restores TCO before page faults are enabled again on every
exit, including an access fault.
A character comparison performs two nofault loads. For N compared
characters, the number of dynamic MSR TCO executions therefore falls from
4N to 2.
Signed-off-by: Muhammad Usama Anjum <usama.anjum@arm.com>
---
kernel/bpf/helpers.c | 35 ++++++++++++++++++++++-------------
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index 3574a9a5721ec..f8c557161584e 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -3726,7 +3726,8 @@ __bpf_kfunc void __bpf_trap(void)
*
* Since strings are not necessarily %NUL-terminated, we cannot directly call
* in-kernel implementations. Instead, we open-code the implementations using
- * __get_kernel_nofault instead of plain dereference to make them safe.
+ * __get_kernel_nofault_bare under guard(__kernel_nofault_bare)() to make them
+ * safe.
*/
static int __bpf_strncasecmp(const char *s1, const char *s2, bool ignore_case, size_t len)
@@ -3742,9 +3743,10 @@ static int __bpf_strncasecmp(const char *s1, const char *s2, bool ignore_case, s
return 0;
guard(pagefault)();
+ guard(__kernel_nofault_bare)();
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);
+ __get_kernel_nofault_bare(&c1, s1, char, err_out);
+ __get_kernel_nofault_bare(&c2, s2, char, err_out);
if (ignore_case) {
c1 = tolower(c1);
c2 = tolower(c2);
@@ -3843,8 +3845,9 @@ __bpf_kfunc int bpf_strnchr(const char *s__ign, size_t count, char c)
return -ENOENT;
guard(pagefault)();
+ guard(__kernel_nofault_bare)();
for (i = 0; i < count && i < XATTR_SIZE_MAX; i++) {
- __get_kernel_nofault(&sc, s__ign, char, err_out);
+ __get_kernel_nofault_bare(&sc, s__ign, char, err_out);
if (sc == c)
return i;
if (sc == '\0')
@@ -3897,8 +3900,9 @@ __bpf_kfunc int bpf_strchrnul(const char *s__ign, char c)
return -ERANGE;
guard(pagefault)();
+ guard(__kernel_nofault_bare)();
for (i = 0; i < XATTR_SIZE_MAX; i++) {
- __get_kernel_nofault(&sc, s__ign, char, err_out);
+ __get_kernel_nofault_bare(&sc, s__ign, char, err_out);
if (sc == '\0' || sc == c)
return i;
s__ign++;
@@ -3929,8 +3933,9 @@ __bpf_kfunc int bpf_strrchr(const char *s__ign, int c)
return -ERANGE;
guard(pagefault)();
+ guard(__kernel_nofault_bare)();
for (i = 0; i < XATTR_SIZE_MAX; i++) {
- __get_kernel_nofault(&sc, s__ign, char, err_out);
+ __get_kernel_nofault_bare(&sc, s__ign, char, err_out);
if (sc == c)
last = i;
if (sc == '\0')
@@ -3964,8 +3969,9 @@ __bpf_kfunc int bpf_strnlen(const char *s__ign, size_t count)
return 0;
guard(pagefault)();
+ guard(__kernel_nofault_bare)();
for (i = 0; i < count && i < XATTR_SIZE_MAX; i++) {
- __get_kernel_nofault(&c, s__ign, char, err_out);
+ __get_kernel_nofault_bare(&c, s__ign, char, err_out);
if (c == '\0')
return i;
s__ign++;
@@ -4014,12 +4020,13 @@ __bpf_kfunc int bpf_strspn(const char *s__ign, const char *accept__ign)
}
guard(pagefault)();
+ guard(__kernel_nofault_bare)();
for (i = 0; i < XATTR_SIZE_MAX; i++) {
- __get_kernel_nofault(&cs, s__ign, char, err_out);
+ __get_kernel_nofault_bare(&cs, s__ign, char, err_out);
if (cs == '\0')
return i;
for (j = 0; j < XATTR_SIZE_MAX; j++) {
- __get_kernel_nofault(&ca, accept__ign + j, char, err_out);
+ __get_kernel_nofault_bare(&ca, accept__ign + j, char, err_out);
if (cs == ca || ca == '\0')
break;
}
@@ -4058,12 +4065,13 @@ __bpf_kfunc int bpf_strcspn(const char *s__ign, const char *reject__ign)
}
guard(pagefault)();
+ guard(__kernel_nofault_bare)();
for (i = 0; i < XATTR_SIZE_MAX; i++) {
- __get_kernel_nofault(&cs, s__ign, char, err_out);
+ __get_kernel_nofault_bare(&cs, s__ign, char, err_out);
if (cs == '\0')
return i;
for (j = 0; j < XATTR_SIZE_MAX; j++) {
- __get_kernel_nofault(&cr, reject__ign + j, char, err_out);
+ __get_kernel_nofault_bare(&cr, reject__ign + j, char, err_out);
if (cs == cr || cr == '\0')
break;
}
@@ -4090,9 +4098,10 @@ static int __bpf_strnstr(const char *s1, const char *s2, size_t len,
}
guard(pagefault)();
+ guard(__kernel_nofault_bare)();
for (i = 0; i < XATTR_SIZE_MAX; i++) {
for (j = 0; i + j <= len && j < XATTR_SIZE_MAX; j++) {
- __get_kernel_nofault(&c2, s2 + j, char, err_out);
+ __get_kernel_nofault_bare(&c2, s2 + j, char, err_out);
if (c2 == '\0')
return i;
/*
@@ -4102,7 +4111,7 @@ static int __bpf_strnstr(const char *s1, const char *s2, size_t len,
*/
if (i + j == len)
break;
- __get_kernel_nofault(&c1, s1 + j, char, err_out);
+ __get_kernel_nofault_bare(&c1, s1 + j, char, err_out);
if (ignore_case) {
c1 = tolower(c1);
--
2.47.3
next prev parent reply other threads:[~2026-08-24 16:06 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-24 16:04 [PATCH 0/7] arm64: Batch PSTATE.TCO handling in kernel nofault loops Muhammad Usama Anjum
2026-08-24 16:04 ` [PATCH 1/7] arm64: uaccess: Add batched kernel nofault accessors Muhammad Usama Anjum
2026-08-24 17:02 ` bot+bpf-ci
2026-08-24 16:04 ` [PATCH 2/7] uaccess: Add scope guard for bare kernel nofault regions Muhammad Usama Anjum
2026-08-24 17:02 ` bot+bpf-ci
2026-08-24 16:04 ` [PATCH 3/7] maccess: Skip setup for zero-sized kernel nofault copies Muhammad Usama Anjum
2026-08-24 17:02 ` bot+bpf-ci
2026-08-24 16:04 ` [PATCH 4/7] maccess: Use a scoped guard for page faults Muhammad Usama Anjum
2026-08-24 17:02 ` bot+bpf-ci
2026-08-25 10:36 ` David Hildenbrand (Arm)
2026-08-25 12:07 ` Muhammad Usama Anjum
2026-08-24 16:04 ` [PATCH 4/7] maccess: Use a scoped guard to re-enable " Muhammad Usama Anjum
2026-08-24 16:04 ` [PATCH 5/7] maccess: Batch TCO handling in kernel nofault loops Muhammad Usama Anjum
2026-08-24 17:02 ` bot+bpf-ci
2026-08-24 16:04 ` [PATCH 6/7] bpf: Skip setup for zero-length string kfunc operations Muhammad Usama Anjum
2026-08-24 16:04 ` Muhammad Usama Anjum [this message]
2026-08-24 17:02 ` [PATCH 7/7] bpf: Batch TCO handling in string kfuncs bot+bpf-ci
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=20260824160523.3907021-9-usama.anjum@arm.com \
--to=usama.anjum@arm.com \
--cc=akpm@linux-foundation.org \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=catalin.marinas@arm.com \
--cc=daniel@iogearbox.net \
--cc=david@kernel.org \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=ihor.solodrai@linux.dev \
--cc=jolsa@kernel.org \
--cc=liam@infradead.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mark.rutland@arm.com \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=mhocko@suse.com \
--cc=rppt@kernel.org \
--cc=song@kernel.org \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=will@kernel.org \
--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