From 2e47c3f45c6ac0fe94a0dad999f93c66dc50cd01 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Mon, 24 Aug 2026 17:04:46 +0100 Subject: [PATCH 1/7] arm64: uaccess: Add batched kernel nofault accessors With Hardware Tag-Based KASAN in asynchronous or asymmetric mode, arm64 sets and clears PSTATE.TCO around every kernel nofault load or store. A loop pays that cost for every access even though tag checking can stay disabled until the operation finishes. Separate TCO management from the fault-tolerant access and add begin and end hooks for callers that want to batch several accesses. Keep the existing accessors self-contained, and provide aliases and no-op hooks for architectures that do not need special handling. A context switch re-enables tag checking, so a batched region must not schedule. Continue to evaluate accessor arguments before overriding TCO, as those expressions may block. Signed-off-by: Muhammad Usama Anjum --- arch/arm64/include/asm/uaccess.h | 71 ++++++++++++++++++++++++-------- include/linux/uaccess.h | 16 +++++++ 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 9f5bd9c69c249..1a14eb2a51dce 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -270,28 +270,43 @@ do { \ #define get_user __get_user /* - * We must not call into the scheduler between __mte_enable_tco_async() and - * __mte_disable_tco_async(). As `dst` and `src` may contain blocking - * functions, we must evaluate these outside of the critical section. + * Nofault load without TCO management for use inside a + * __begin/__end_kernel_nofault_bare() region. */ -#define __get_kernel_nofault(dst, src, type, err_label) \ +#define __get_kernel_nofault_bare(dst, src, type, err_label) \ do { \ __typeof__(dst) __gkn_dst = (dst); \ __typeof__(src) __gkn_src = (src); \ do { \ __label__ __gkn_label; \ - \ - __mte_enable_tco_async(); \ __raw_get_mem("ldr", *((type *)(__gkn_dst)), \ (__force type *)(__gkn_src), __gkn_label, K); \ - __mte_disable_tco_async(); \ break; \ __gkn_label: \ - __mte_disable_tco_async(); \ goto err_label; \ } while (0); \ } while (0) +/* + * We must not call into the scheduler between __mte_enable_tco_async() and + * __mte_disable_tco_async(). As dst and src may contain blocking functions, + * evaluate them before overriding TCO. + */ +#define __get_kernel_nofault(dst, src, type, err_label) \ +do { \ + __label__ __gkn_tco_err; \ + __typeof__(dst) __gkn_tco_dst = (dst); \ + __typeof__(src) __gkn_tco_src = (src); \ + __mte_enable_tco_async(); \ + __get_kernel_nofault_bare(__gkn_tco_dst, __gkn_tco_src, type, \ + __gkn_tco_err); \ + __mte_disable_tco_async(); \ + break; \ +__gkn_tco_err: \ + __mte_disable_tco_async(); \ + goto err_label; \ +} while (0) + #define __put_mem_asm(store, reg, x, addr, label, type) \ asm goto( \ "1: " store " " reg "0, [%1]\n" \ @@ -366,28 +381,48 @@ do { \ #define put_user __put_user -/* - * We must not call into the scheduler between __mte_enable_tco_async() and - * __mte_disable_tco_async(). As `dst` and `src` may contain blocking - * functions, we must evaluate these outside of the critical section. - */ -#define __put_kernel_nofault(dst, src, type, err_label) \ +/* Nofault store without TCO management; see __get_kernel_nofault_bare. */ +#define __put_kernel_nofault_bare(dst, src, type, err_label) \ do { \ __typeof__(dst) __pkn_dst = (dst); \ __typeof__(src) __pkn_src = (src); \ \ do { \ __label__ __pkn_err; \ - __mte_enable_tco_async(); \ __raw_put_mem("str", *((type *)(__pkn_src)), \ (__force type *)(__pkn_dst), __pkn_err, K); \ - __mte_disable_tco_async(); \ break; \ __pkn_err: \ - __mte_disable_tco_async(); \ goto err_label; \ } while (0); \ -} while(0) +} while (0) + +/* + * We must not call into the scheduler between __mte_enable_tco_async() and + * __mte_disable_tco_async(). As `dst` and `src` may contain blocking + * functions, we must evaluate these outside of the critical section. + */ +#define __put_kernel_nofault(dst, src, type, err_label) \ +do { \ + __label__ __pkn_tco_err; \ + __typeof__(dst) __pkn_tco_dst = (dst); \ + __typeof__(src) __pkn_tco_src = (src); \ + __mte_enable_tco_async(); \ + __put_kernel_nofault_bare(__pkn_tco_dst, __pkn_tco_src, type, \ + __pkn_tco_err); \ + __mte_disable_tco_async(); \ + break; \ +__pkn_tco_err: \ + __mte_disable_tco_async(); \ + goto err_label; \ +} while (0) + +/* + * A context switch re-enables tag checking, hence the no-scheduling + * requirement for a bare nofault region. + */ +#define __begin_kernel_nofault_bare() __mte_enable_tco_async() +#define __end_kernel_nofault_bare() __mte_disable_tco_async() extern unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n); #define raw_copy_from_user(to, from, n) \ diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index eddbbb65ccc4f..7ae1854673471 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h @@ -637,6 +637,22 @@ do { \ #endif /* !__get_kernel_nofault */ +/* + * Architectures may use the begin/end hooks to establish state shared by a + * sequence of bare nofault accesses. Every path out of the region must call + * the end hook. The region, including expressions passed to the bare + * accessors, must not call into the scheduler. + */ +#ifndef __get_kernel_nofault_bare +#define __get_kernel_nofault_bare __get_kernel_nofault +#define __put_kernel_nofault_bare __put_kernel_nofault +#endif + +#ifndef __begin_kernel_nofault_bare +#define __begin_kernel_nofault_bare() do {} while (0) +#define __end_kernel_nofault_bare() do {} while (0) +#endif + /** * get_kernel_nofault(): safely attempt to read from a location * @val: read into this variable From 4ab7c49002216a95957bc674f98cdac1758ab1a6 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Mon, 24 Aug 2026 17:04:47 +0100 Subject: [PATCH 2/7] uaccess: Add scope guard for bare kernel nofault regions A batched nofault region must run its end hook on every exit. Pairing the hooks by hand makes early returns and error paths easy to get wrong. Add a scope guard that starts the region on entry and ends it when the scope is left. Callers can keep their natural control flow while the architecture state remains balanced on success and failure. No functional change until a caller uses the guard. Signed-off-by: Muhammad Usama Anjum --- include/linux/uaccess.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h index 7ae1854673471..b25e778ddc38a 100644 --- a/include/linux/uaccess.h +++ b/include/linux/uaccess.h @@ -653,6 +653,10 @@ do { \ #define __end_kernel_nofault_bare() do {} while (0) #endif +DEFINE_LOCK_GUARD_0(__kernel_nofault_bare, + __begin_kernel_nofault_bare(), + __end_kernel_nofault_bare()) + /** * get_kernel_nofault(): safely attempt to read from a location * @val: read into this variable From 3591004a5dd4193a9cb291044a07734187961ce6 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Mon, 24 Aug 2026 17:04:48 +0100 Subject: [PATCH 3/7] maccess: Skip setup for zero-sized kernel nofault copies A zero-sized kernel nofault copy does not enter an access loop, but it still disables and re-enables page faults. Zero sizes are valid. BPF probe-read helpers accept them, and KGDB memory packets may carry a zero length. Return before changing page-fault state when there is nothing to copy. For reads, keep architecture-specific address validation before the fast path so its behavior is unchanged. Signed-off-by: Muhammad Usama Anjum --- mm/maccess.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mm/maccess.c b/mm/maccess.c index 486559d688583..c59a0e092d24a 100644 --- a/mm/maccess.c +++ b/mm/maccess.c @@ -35,6 +35,8 @@ long copy_from_kernel_nofault(void *dst, const void *src, size_t size) if (!copy_from_kernel_nofault_allowed(src, size)) return -ERANGE; + if (!size) + return 0; pagefault_disable(); if (!(align & 7)) @@ -65,6 +67,9 @@ long copy_to_kernel_nofault(void *dst, const void *src, size_t size) { unsigned long align = 0; + if (!size) + return 0; + if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) align = (unsigned long)dst | (unsigned long)src; From 1ac186beb8f6ca342c0709cd439b3d9570e8abd4 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Mon, 24 Aug 2026 17:04:49 +0100 Subject: [PATCH 4/7] maccess: Use a scoped guard for page faults Kernel nofault copy and string paths open-code page-fault disable and enable around label-based loops, duplicating cleanup on success and failure. Use a page-fault scope guard instead. Leaving the scope now re-enables page faults on both paths without separate cleanup at the fault label. No functional change. Signed-off-by: Muhammad Usama Anjum --- mm/maccess.c | 53 +++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/mm/maccess.c b/mm/maccess.c index c59a0e092d24a..f695ceefe6fcc 100644 --- a/mm/maccess.c +++ b/mm/maccess.c @@ -38,18 +38,17 @@ long copy_from_kernel_nofault(void *dst, const void *src, size_t size) if (!size) return 0; - pagefault_disable(); - if (!(align & 7)) - copy_from_kernel_nofault_loop(dst, src, size, u64, Efault); - if (!(align & 3)) - copy_from_kernel_nofault_loop(dst, src, size, u32, Efault); - if (!(align & 1)) - copy_from_kernel_nofault_loop(dst, src, size, u16, Efault); - copy_from_kernel_nofault_loop(dst, src, size, u8, Efault); - pagefault_enable(); + scoped_guard(pagefault) { + if (!(align & 7)) + copy_from_kernel_nofault_loop(dst, src, size, u64, Efault); + if (!(align & 3)) + copy_from_kernel_nofault_loop(dst, src, size, u32, Efault); + if (!(align & 1)) + copy_from_kernel_nofault_loop(dst, src, size, u16, Efault); + copy_from_kernel_nofault_loop(dst, src, size, u8, Efault); + } return 0; Efault: - pagefault_enable(); return -EFAULT; } EXPORT_SYMBOL_GPL(copy_from_kernel_nofault); @@ -73,18 +72,17 @@ long copy_to_kernel_nofault(void *dst, const void *src, size_t size) if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) align = (unsigned long)dst | (unsigned long)src; - pagefault_disable(); - if (!(align & 7)) - copy_to_kernel_nofault_loop(dst, src, size, u64, Efault); - if (!(align & 3)) - copy_to_kernel_nofault_loop(dst, src, size, u32, Efault); - if (!(align & 1)) - copy_to_kernel_nofault_loop(dst, src, size, u16, Efault); - copy_to_kernel_nofault_loop(dst, src, size, u8, Efault); - pagefault_enable(); + scoped_guard(pagefault) { + if (!(align & 7)) + copy_to_kernel_nofault_loop(dst, src, size, u64, Efault); + if (!(align & 3)) + copy_to_kernel_nofault_loop(dst, src, size, u32, Efault); + if (!(align & 1)) + copy_to_kernel_nofault_loop(dst, src, size, u16, Efault); + copy_to_kernel_nofault_loop(dst, src, size, u8, Efault); + } return 0; Efault: - pagefault_enable(); return -EFAULT; } @@ -97,18 +95,17 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count) if (!copy_from_kernel_nofault_allowed(unsafe_addr, count)) return -ERANGE; - pagefault_disable(); - do { - __get_kernel_nofault(dst, src, u8, Efault); - dst++; - src++; - } while (dst[-1] && src - unsafe_addr < count); - pagefault_enable(); + scoped_guard(pagefault) { + do { + __get_kernel_nofault(dst, src, u8, Efault); + dst++; + src++; + } while (dst[-1] && src - unsafe_addr < count); + } dst[-1] = '\0'; return src - unsafe_addr; Efault: - pagefault_enable(); dst[0] = '\0'; return -EFAULT; } From 4d9ca93ac9e54d008578b23fc4c0aa56008479b4 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Mon, 24 Aug 2026 17:04:51 +0100 Subject: [PATCH 5/7] maccess: Batch TCO handling in kernel nofault loops With Hardware Tag-Based KASAN in asynchronous or asymmetric mode, every arm64 kernel nofault access sets and clears PSTATE.TCO. Copy and string loops repeat that pair even though tag checking can stay disabled for the whole operation. Cover each non-empty operation with one bare nofault region and use bare accessors in the loop. Leaving the region restores TCO before page faults are enabled again, including after an access fault. Existing empty-work checks ensure that every new region performs at least one access. The number of dynamic MSR TCO executions therefore changes as follows: Work Before After N nofault accesses 2N 2 4 KiB nofault copy 1,024 2 N-byte strncpy 2N 2 The 4 KiB case assumes 512 64-bit accesses. These figures come from the control flow rather than a runtime measurement, so the time saved depends on the CPU and workload. Generic fallbacks leave other architectures unchanged. Signed-off-by: Muhammad Usama Anjum --- mm/maccess.c | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/mm/maccess.c b/mm/maccess.c index f695ceefe6fcc..87486bf98d15a 100644 --- a/mm/maccess.c +++ b/mm/maccess.c @@ -19,7 +19,7 @@ bool __weak copy_from_kernel_nofault_allowed(const void *unsafe_src, */ #define copy_from_kernel_nofault_loop(dst, src, len, type, err_label) \ while (len >= sizeof(type)) { \ - __get_kernel_nofault(dst, src, type, err_label); \ + __get_kernel_nofault_bare(dst, src, type, err_label); \ kmsan_check_memory(src, sizeof(type)); \ dst += sizeof(type); \ src += sizeof(type); \ @@ -39,13 +39,15 @@ long copy_from_kernel_nofault(void *dst, const void *src, size_t size) return 0; scoped_guard(pagefault) { - if (!(align & 7)) - copy_from_kernel_nofault_loop(dst, src, size, u64, Efault); - if (!(align & 3)) - copy_from_kernel_nofault_loop(dst, src, size, u32, Efault); - if (!(align & 1)) - copy_from_kernel_nofault_loop(dst, src, size, u16, Efault); - copy_from_kernel_nofault_loop(dst, src, size, u8, Efault); + scoped_guard(__kernel_nofault_bare) { + if (!(align & 7)) + copy_from_kernel_nofault_loop(dst, src, size, u64, Efault); + if (!(align & 3)) + copy_from_kernel_nofault_loop(dst, src, size, u32, Efault); + if (!(align & 1)) + copy_from_kernel_nofault_loop(dst, src, size, u16, Efault); + copy_from_kernel_nofault_loop(dst, src, size, u8, Efault); + } } return 0; Efault: @@ -55,7 +57,7 @@ EXPORT_SYMBOL_GPL(copy_from_kernel_nofault); #define copy_to_kernel_nofault_loop(dst, src, len, type, err_label) \ while (len >= sizeof(type)) { \ - __put_kernel_nofault(dst, src, type, err_label); \ + __put_kernel_nofault_bare(dst, src, type, err_label); \ instrument_write(dst, sizeof(type)); \ dst += sizeof(type); \ src += sizeof(type); \ @@ -73,13 +75,15 @@ long copy_to_kernel_nofault(void *dst, const void *src, size_t size) align = (unsigned long)dst | (unsigned long)src; scoped_guard(pagefault) { - if (!(align & 7)) - copy_to_kernel_nofault_loop(dst, src, size, u64, Efault); - if (!(align & 3)) - copy_to_kernel_nofault_loop(dst, src, size, u32, Efault); - if (!(align & 1)) - copy_to_kernel_nofault_loop(dst, src, size, u16, Efault); - copy_to_kernel_nofault_loop(dst, src, size, u8, Efault); + scoped_guard(__kernel_nofault_bare) { + if (!(align & 7)) + copy_to_kernel_nofault_loop(dst, src, size, u64, Efault); + if (!(align & 3)) + copy_to_kernel_nofault_loop(dst, src, size, u32, Efault); + if (!(align & 1)) + copy_to_kernel_nofault_loop(dst, src, size, u16, Efault); + copy_to_kernel_nofault_loop(dst, src, size, u8, Efault); + } } return 0; Efault: @@ -96,11 +100,13 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count) return -ERANGE; scoped_guard(pagefault) { - do { - __get_kernel_nofault(dst, src, u8, Efault); - dst++; - src++; - } while (dst[-1] && src - unsafe_addr < count); + scoped_guard(__kernel_nofault_bare) { + do { + __get_kernel_nofault_bare(dst, src, u8, Efault); + dst++; + src++; + } while (dst[-1] && src - unsafe_addr < count); + } } dst[-1] = '\0'; From 5e0462810d6ec7d2ff1a6b8001c12d2b0dfa58ea Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Mon, 24 Aug 2026 17:04:52 +0100 Subject: [PATCH 6/7] bpf: Skip setup for zero-length string kfunc operations A zero limit is valid for several length-bounded BPF string operations. Their loops perform no load in that case, but they still enter and leave a page-fault-disabled region. Return the existing empty result before changing page-fault state. Keep address validation first so an invalid pointer continues to return -ERANGE. Signed-off-by: Muhammad Usama Anjum --- kernel/bpf/helpers.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c index b3cc5c8fc8756..3574a9a5721ec 100644 --- a/kernel/bpf/helpers.c +++ b/kernel/bpf/helpers.c @@ -3738,6 +3738,8 @@ static int __bpf_strncasecmp(const char *s1, const char *s2, bool ignore_case, s !copy_from_kernel_nofault_allowed(s2, 1)) { return -ERANGE; } + if (!len) + return 0; guard(pagefault)(); for (i = 0; i < len && i < XATTR_SIZE_MAX; i++) { @@ -3837,6 +3839,8 @@ __bpf_kfunc int bpf_strnchr(const char *s__ign, size_t count, char c) if (!copy_from_kernel_nofault_allowed(s__ign, 1)) return -ERANGE; + if (!count) + return -ENOENT; guard(pagefault)(); for (i = 0; i < count && i < XATTR_SIZE_MAX; i++) { @@ -3956,6 +3960,8 @@ __bpf_kfunc int bpf_strnlen(const char *s__ign, size_t count) if (!copy_from_kernel_nofault_allowed(s__ign, 1)) return -ERANGE; + if (!count) + return 0; guard(pagefault)(); for (i = 0; i < count && i < XATTR_SIZE_MAX; i++) { From 8c4c3a2bc5fa852f9a86deb9b5913f753efd8a34 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Mon, 24 Aug 2026 17:04:53 +0100 Subject: [PATCH 7/7] bpf: Batch TCO handling in string kfuncs 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 --- 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);