diff options
author | Linus Torvalds | 2016-09-07 09:29:36 -0700 |
---|---|---|
committer | Linus Torvalds | 2016-09-07 09:29:36 -0700 |
commit | 08411a7554248009f26e85635f445a209604bfb5 (patch) | |
tree | 49e7af67ee59422c7b2129da1d8448e4c6a45724 /drivers | |
parent | d060e0f603a4156087813d221d818bb39ec91429 (diff) | |
parent | 3c17648c2816f6d28bd2be9293032a2901994a36 (diff) |
Merge tag 'usercopy-v4.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull hardened usercopy fixes from Kees Cook:
- inline copy_*_user() for correct use of __builtin_const_p() for
hardened usercopy and the recent compile-time checks.
- switch hardened usercopy to only check non-const size arguments to
avoid meaningless checks on likely-sane const values.
- update lkdtm usercopy tests to compenstate for the const checking.
* tag 'usercopy-v4.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
lkdtm: adjust usercopy tests to bypass const checks
usercopy: fold builtin_const check into inline function
x86/uaccess: force copy_*_user() to be inlined
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/misc/lkdtm_usercopy.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/drivers/misc/lkdtm_usercopy.c b/drivers/misc/lkdtm_usercopy.c index 5525a204db93..1dd611423d8b 100644 --- a/drivers/misc/lkdtm_usercopy.c +++ b/drivers/misc/lkdtm_usercopy.c @@ -9,7 +9,15 @@ #include <linux/uaccess.h> #include <asm/cacheflush.h> -static size_t cache_size = 1024; +/* + * Many of the tests here end up using const sizes, but those would + * normally be ignored by hardened usercopy, so force the compiler + * into choosing the non-const path to make sure we trigger the + * hardened usercopy checks by added "unconst" to all the const copies, + * and making sure "cache_size" isn't optimized into a const. + */ +static volatile size_t unconst = 0; +static volatile size_t cache_size = 1024; static struct kmem_cache *bad_cache; static const unsigned char test_text[] = "This is a test.\n"; @@ -67,14 +75,14 @@ static noinline void do_usercopy_stack(bool to_user, bool bad_frame) if (to_user) { pr_info("attempting good copy_to_user of local stack\n"); if (copy_to_user((void __user *)user_addr, good_stack, - sizeof(good_stack))) { + unconst + sizeof(good_stack))) { pr_warn("copy_to_user failed unexpectedly?!\n"); goto free_user; } pr_info("attempting bad copy_to_user of distant stack\n"); if (copy_to_user((void __user *)user_addr, bad_stack, - sizeof(good_stack))) { + unconst + sizeof(good_stack))) { pr_warn("copy_to_user failed, but lacked Oops\n"); goto free_user; } @@ -88,14 +96,14 @@ static noinline void do_usercopy_stack(bool to_user, bool bad_frame) pr_info("attempting good copy_from_user of local stack\n"); if (copy_from_user(good_stack, (void __user *)user_addr, - sizeof(good_stack))) { + unconst + sizeof(good_stack))) { pr_warn("copy_from_user failed unexpectedly?!\n"); goto free_user; } pr_info("attempting bad copy_from_user of distant stack\n"); if (copy_from_user(bad_stack, (void __user *)user_addr, - sizeof(good_stack))) { + unconst + sizeof(good_stack))) { pr_warn("copy_from_user failed, but lacked Oops\n"); goto free_user; } @@ -109,7 +117,7 @@ static void do_usercopy_heap_size(bool to_user) { unsigned long user_addr; unsigned char *one, *two; - const size_t size = 1024; + size_t size = unconst + 1024; one = kmalloc(size, GFP_KERNEL); two = kmalloc(size, GFP_KERNEL); @@ -285,13 +293,14 @@ void lkdtm_USERCOPY_KERNEL(void) pr_info("attempting good copy_to_user from kernel rodata\n"); if (copy_to_user((void __user *)user_addr, test_text, - sizeof(test_text))) { + unconst + sizeof(test_text))) { pr_warn("copy_to_user failed unexpectedly?!\n"); goto free_user; } pr_info("attempting bad copy_to_user from kernel text\n"); - if (copy_to_user((void __user *)user_addr, vm_mmap, PAGE_SIZE)) { + if (copy_to_user((void __user *)user_addr, vm_mmap, + unconst + PAGE_SIZE)) { pr_warn("copy_to_user failed, but lacked Oops\n"); goto free_user; } |