mirror of
https://github.com/torvalds/linux.git
synced 2025-11-30 23:16:01 +07:00
mm: security: Check early if HARDENED_USERCOPY is enabled
HARDENED_USERCOPY is checked within a function so even if disabled, the function overhead still exists. Move the static check inline. This is at best a micro-optimisation and any difference in performance was within noise but it is relatively consistent with the init_on_* implementations. Suggested-by: Kees Cook <kees@kernel.org> Signed-off-by: Mel Gorman <mgorman@techsingularity.net> Link: https://lore.kernel.org/r/20250123221115.19722-4-mgorman@techsingularity.net Signed-off-by: Kees Cook <kees@kernel.org>
This commit is contained in:
@@ -6,14 +6,21 @@
|
|||||||
#include <linux/bug.h>
|
#include <linux/bug.h>
|
||||||
|
|
||||||
#ifdef CONFIG_HARDENED_USERCOPY
|
#ifdef CONFIG_HARDENED_USERCOPY
|
||||||
|
#include <linux/jump_label.h>
|
||||||
extern void __check_object_size(const void *ptr, unsigned long n,
|
extern void __check_object_size(const void *ptr, unsigned long n,
|
||||||
bool to_user);
|
bool to_user);
|
||||||
|
|
||||||
|
DECLARE_STATIC_KEY_MAYBE(CONFIG_HARDENED_USERCOPY_DEFAULT_ON,
|
||||||
|
validate_usercopy_range);
|
||||||
|
|
||||||
static __always_inline void check_object_size(const void *ptr, unsigned long n,
|
static __always_inline void check_object_size(const void *ptr, unsigned long n,
|
||||||
bool to_user)
|
bool to_user)
|
||||||
{
|
{
|
||||||
if (!__builtin_constant_p(n))
|
if (!__builtin_constant_p(n) &&
|
||||||
|
static_branch_maybe(CONFIG_HARDENED_USERCOPY_DEFAULT_ON,
|
||||||
|
&validate_usercopy_range)) {
|
||||||
__check_object_size(ptr, n, to_user);
|
__check_object_size(ptr, n, to_user);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static inline void check_object_size(const void *ptr, unsigned long n,
|
static inline void check_object_size(const void *ptr, unsigned long n,
|
||||||
|
|||||||
@@ -201,7 +201,9 @@ static inline void check_heap_object(const void *ptr, unsigned long n,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFINE_STATIC_KEY_FALSE_RO(bypass_usercopy_checks);
|
DEFINE_STATIC_KEY_MAYBE_RO(CONFIG_HARDENED_USERCOPY_DEFAULT_ON,
|
||||||
|
validate_usercopy_range);
|
||||||
|
EXPORT_SYMBOL(validate_usercopy_range);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validates that the given object is:
|
* Validates that the given object is:
|
||||||
@@ -212,9 +214,6 @@ static DEFINE_STATIC_KEY_FALSE_RO(bypass_usercopy_checks);
|
|||||||
*/
|
*/
|
||||||
void __check_object_size(const void *ptr, unsigned long n, bool to_user)
|
void __check_object_size(const void *ptr, unsigned long n, bool to_user)
|
||||||
{
|
{
|
||||||
if (static_branch_unlikely(&bypass_usercopy_checks))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Skip all tests if size is zero. */
|
/* Skip all tests if size is zero. */
|
||||||
if (!n)
|
if (!n)
|
||||||
return;
|
return;
|
||||||
@@ -270,8 +269,10 @@ __setup("hardened_usercopy=", parse_hardened_usercopy);
|
|||||||
|
|
||||||
static int __init set_hardened_usercopy(void)
|
static int __init set_hardened_usercopy(void)
|
||||||
{
|
{
|
||||||
if (enable_checks == false)
|
if (enable_checks)
|
||||||
static_branch_enable(&bypass_usercopy_checks);
|
static_branch_enable(&validate_usercopy_range);
|
||||||
|
else
|
||||||
|
static_branch_disable(&validate_usercopy_range);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user