diff --git a/include/linux/kfence.h b/include/linux/kfence.h index 1591b242ebd47951271b1f9f40e55a2d27532ad7..76bf6198bef09004c1ac5bb5342b845cb6a83c54 100644 --- a/include/linux/kfence.h +++ b/include/linux/kfence.h @@ -31,6 +31,7 @@ DECLARE_STATIC_KEY_FALSE(kfence_allocation_key); extern atomic_t kfence_allocation_gate; #endif DECLARE_STATIC_KEY_FALSE(kfence_skip_interval); +DECLARE_STATIC_KEY_FALSE(kfence_once_inited); #define GFP_KFENCE_NOT_ALLOC ((GFP_ZONEMASK & ~__GFP_HIGHMEM) | __GFP_NOKFENCE | __GFP_THISNODE) /** @@ -69,7 +70,7 @@ static __always_inline bool is_kfence_address_node(const void *addr, const int n */ static __always_inline bool is_kfence_address(const void *addr) { - if (unlikely(!virt_addr_valid(addr))) + if (!static_branch_unlikely(&kfence_once_inited) || unlikely(!virt_addr_valid(addr))) return false; return unlikely(is_kfence_address_node(addr, page_to_nid(virt_to_page(addr)))); diff --git a/mm/kfence/core.c b/mm/kfence/core.c index a328c90841710f1df96b5cd02763871d8d84738f..77ca870957a47aa6b6bc0f497d47509828776c10 100644 --- a/mm/kfence/core.c +++ b/mm/kfence/core.c @@ -59,6 +59,8 @@ EXPORT_SYMBOL(kfence_pool_size); DEFINE_STATIC_KEY_FALSE(kfence_allocation_key); #endif DEFINE_STATIC_KEY_FALSE(kfence_skip_interval); +DEFINE_STATIC_KEY_FALSE(kfence_once_inited); +EXPORT_SYMBOL(kfence_once_inited); static int param_set_sample_interval(const char *val, const struct kernel_param *kp) { @@ -560,6 +562,9 @@ static struct page *kfence_guarded_alloc_page(int node) page = virt_to_page(addr); __ClearPageSlab(page); +#ifdef CONFIG_DEBUG_VM + atomic_set(&page->_refcount, 0); +#endif raw_spin_unlock_irqrestore(&meta->lock, flags); @@ -1093,6 +1098,8 @@ void __init kfence_init(void) pr_cont("\n"); } + static_branch_enable(&kfence_once_inited); + return; fail: @@ -1273,7 +1280,12 @@ struct page *__kfence_alloc_page(int node, gfp_t flags) size_t kfence_ksize(const void *addr) { - const struct kfence_metadata *meta = addr_to_metadata((unsigned long)addr); + struct kfence_metadata *meta; + + if (!static_branch_unlikely(&kfence_once_inited)) + return 0; + + meta = addr_to_metadata((unsigned long)addr); /* * Read locklessly -- if there is a race with __kfence_alloc(), this is