如果内核开启CONFIG_HARDENED_USERCOPY,则在从user space copy 数据到kernel space 时做一些检查,如果
不是有效数据,则assert
这部分代码在mm/usercopy.c 中,即使开启CONFIG_HARDENED_USERCOPY,也可以通过命令行来禁止这个特性来提高部分
性能
static bool enable_checks __initdata = true;
static int __init parse_hardened_usercopy(char *str)
{
return strtobool(str, &enable_checks);
}
__setup("hardened_usercopy=", parse_hardened_usercopy);
static int __init set_hardened_usercopy(void)
{
if (enable_checks == false)
static_branch_enable(&bypass_usercopy_checks);
return 1;
}
late_initcall(set_hardened_usercopy);
这里的enable_checks 默认是true,则当用户通过命令行hardened_usercopy=0,则可以关掉这个特性。
void __check_object_size(const void *ptr, unsigned long n, bool to_user)
{
#当enable_checks 被命令行被设置成0时,则在这里就返回了
if (static_branch_unlikely(&bypass_usercopy_checks))
return;
/* Skip all tests if size is zero. */
if (!n)
return;
#检查地址是否有效
/* Check for invalid addresses. */
check_bogus_address((const unsigned long)ptr, n, to_user);
#检查堆栈中数据是否正确
/* Check for bad stack object. */
switch (check_stack_object(ptr, n)) {
case NOT_STACK:
/* Object is not touching the current process stack. */
break;
case GOOD_FRAME:
case GOOD_STACK:
/*
* Object is either in the correct frame (when it
* is possible to check) or just generally on the
* process stack (when frame checking not available).
*/
return;
default:
usercopy_abort("process stack", NULL, to_user, 0, n);
}
#检查heap
/* Check for bad heap object. */
check_heap_object(ptr, n, to_user);
#检查代码段是否有问题
/* Check for object in kernel to avoid text exposure. */
check_kernel_text_object((const unsigned long)ptr, n, to_user);
}
可见开启了CONFIG_HARDENED_USERCOPY 后,则在从用户态拷贝数据时会做上述四个方面的检查来加固内核