summaryrefslogtreecommitdiffstats
path: root/kernel/cfi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-06-15 14:20:26 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-06-15 14:20:26 -0700
commit30306f6194cadcc29c77f6ddcd416a75bf5c0232 (patch)
tree6a438e6e9d527a05d7f724fe765d18e4075e6f95 /kernel/cfi.c
parentafe9eb14ea1cbac5d91ca04eb64810d2d9fa22b0 (diff)
parent1dfbe9fcda4afc957f0e371e207ae3cb7e8f3b0e (diff)
downloadlinux-30306f6194cadcc29c77f6ddcd416a75bf5c0232.tar.bz2
Merge tag 'hardening-v5.19-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull hardening fixes from Kees Cook: - Correctly handle vm_map areas in hardened usercopy (Matthew Wilcox) - Adjust CFI RCU usage to avoid boot splats with cpuidle (Sami Tolvanen) * tag 'hardening-v5.19-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: usercopy: Make usercopy resilient against ridiculously large copies usercopy: Cast pointer to an integer once usercopy: Handle vm_map_ram() areas cfi: Fix __cfi_slowpath_diag RCU usage with cpuidle
Diffstat (limited to 'kernel/cfi.c')
-rw-r--r--kernel/cfi.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/kernel/cfi.c b/kernel/cfi.c
index 9594cfd1cf2c..08102d19ec15 100644
--- a/kernel/cfi.c
+++ b/kernel/cfi.c
@@ -281,6 +281,8 @@ static inline cfi_check_fn find_module_check_fn(unsigned long ptr)
static inline cfi_check_fn find_check_fn(unsigned long ptr)
{
cfi_check_fn fn = NULL;
+ unsigned long flags;
+ bool rcu_idle;
if (is_kernel_text(ptr))
return __cfi_check;
@@ -290,13 +292,21 @@ static inline cfi_check_fn find_check_fn(unsigned long ptr)
* the shadow and __module_address use RCU, so we need to wake it
* up if necessary.
*/
- RCU_NONIDLE({
- if (IS_ENABLED(CONFIG_CFI_CLANG_SHADOW))
- fn = find_shadow_check_fn(ptr);
+ rcu_idle = !rcu_is_watching();
+ if (rcu_idle) {
+ local_irq_save(flags);
+ rcu_irq_enter();
+ }
+
+ if (IS_ENABLED(CONFIG_CFI_CLANG_SHADOW))
+ fn = find_shadow_check_fn(ptr);
+ if (!fn)
+ fn = find_module_check_fn(ptr);
- if (!fn)
- fn = find_module_check_fn(ptr);
- });
+ if (rcu_idle) {
+ rcu_irq_exit();
+ local_irq_restore(flags);
+ }
return fn;
}