anolis: kfence: add order0 page switch

ANBZ: #28

Add a interface at /sys/module/kfence/parameters/order0_page to control
order0 page switch.
Default 1 (enabled).
To disable KFENCE monitoring order0 page, write 0 to the interface, or
set kfence.order0_page=0 in boot cmdline.

Signed-off-by: Tianchen Ding <dtcccc@linux.alibaba.com>
Reviewed-by: Xunlei Pang <xlpang@linux.alibaba.com>
This commit is contained in:
Tianchen Ding 2022-02-24 11:08:50 +08:00 committed by Qiao Ma
parent d8074acfa2
commit 834302bf07
2 changed files with 33 additions and 2 deletions

View File

@ -38,6 +38,7 @@ extern atomic_t kfence_allocation_gate;
#endif
DECLARE_STATIC_KEY_FALSE(kfence_once_inited);
#define GFP_KFENCE_NOT_ALLOC ((GFP_ZONEMASK & ~__GFP_HIGHMEM) | __GFP_NOKFENCE | __GFP_THISNODE)
DECLARE_STATIC_KEY_TRUE(kfence_order0_page);
/**
* is_kfence_address_area() - check if an address belongs to KFENCE pool in given area
@ -189,10 +190,12 @@ static __always_inline void *kfence_alloc_node(struct kmem_cache *s, size_t size
static __always_inline struct page *kfence_alloc_page(unsigned int order, int node, gfp_t flags)
{
#ifdef CONFIG_KFENCE_STATIC_KEYS
if (static_branch_unlikely(&kfence_allocation_key) && !order &&
if (static_branch_unlikely(&kfence_allocation_key) &&
static_branch_likely(&kfence_order0_page) && !order &&
!((flags & GFP_KFENCE_NOT_ALLOC) || (flags & GFP_USER) == GFP_USER))
#else
if (unlikely(!atomic_read(&kfence_allocation_gate)) && !order &&
if (unlikely(!atomic_read(&kfence_allocation_gate)) &&
static_branch_likely(&kfence_order0_page) && !order &&
!((flags & GFP_KFENCE_NOT_ALLOC) || (flags & GFP_USER) == GFP_USER))
#endif
return __kfence_alloc_page(node, flags);

View File

@ -81,6 +81,7 @@ DEFINE_STATIC_KEY_FALSE(kfence_short_canary);
DEFINE_STATIC_KEY_FALSE(kfence_skip_interval);
DEFINE_STATIC_KEY_FALSE(kfence_once_inited);
EXPORT_SYMBOL(kfence_once_inited);
DEFINE_STATIC_KEY_TRUE(kfence_order0_page);
#define KFENCE_MAX_OBJECTS_PER_AREA (PUD_SIZE / PAGE_SIZE / 2 - 1)
@ -185,6 +186,33 @@ static const struct kernel_param_ops pool_mode_param_ops = {
};
module_param_cb(pool_mode, &pool_mode_param_ops, &kfence_pool_node_mode, 0600);
static int param_set_order0_page(const char *val, const struct kernel_param *kp)
{
bool res;
int ret = kstrtobool(val, &res);
if (ret < 0)
return ret;
if (res)
static_branch_enable(&kfence_order0_page);
else
static_branch_disable(&kfence_order0_page);
return 0;
}
static int param_get_order0_page(char *buffer, const struct kernel_param *kp)
{
return sprintf(buffer, "%d\n", static_branch_likely(&kfence_order0_page) ? 1 : 0);
}
static const struct kernel_param_ops order0_page_param_ops = {
.set = param_set_order0_page,
.get = param_get_order0_page,
};
module_param_cb(order0_page, &order0_page_param_ops, NULL, 0600);
/*
* The pool of pages used for guard pages and objects.
* Only used in booting init state. Will be cleared after that.