diff options
Diffstat (limited to 'drivers/misc/lkdtm_usercopy.c')
-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 @@ | |||
9 | #include <linux/uaccess.h> | 9 | #include <linux/uaccess.h> |
10 | #include <asm/cacheflush.h> | 10 | #include <asm/cacheflush.h> |
11 | 11 | ||
12 | static size_t cache_size = 1024; | 12 | /* |
13 | * Many of the tests here end up using const sizes, but those would | ||
14 | * normally be ignored by hardened usercopy, so force the compiler | ||
15 | * into choosing the non-const path to make sure we trigger the | ||
16 | * hardened usercopy checks by added "unconst" to all the const copies, | ||
17 | * and making sure "cache_size" isn't optimized into a const. | ||
18 | */ | ||
19 | static volatile size_t unconst = 0; | ||
20 | static volatile size_t cache_size = 1024; | ||
13 | static struct kmem_cache *bad_cache; | 21 | static struct kmem_cache *bad_cache; |
14 | 22 | ||
15 | static const unsigned char test_text[] = "This is a test.\n"; | 23 | 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) | |||
67 | if (to_user) { | 75 | if (to_user) { |
68 | pr_info("attempting good copy_to_user of local stack\n"); | 76 | pr_info("attempting good copy_to_user of local stack\n"); |
69 | if (copy_to_user((void __user *)user_addr, good_stack, | 77 | if (copy_to_user((void __user *)user_addr, good_stack, |
70 | sizeof(good_stack))) { | 78 | unconst + sizeof(good_stack))) { |
71 | pr_warn("copy_to_user failed unexpectedly?!\n"); | 79 | pr_warn("copy_to_user failed unexpectedly?!\n"); |
72 | goto free_user; | 80 | goto free_user; |
73 | } | 81 | } |
74 | 82 | ||
75 | pr_info("attempting bad copy_to_user of distant stack\n"); | 83 | pr_info("attempting bad copy_to_user of distant stack\n"); |
76 | if (copy_to_user((void __user *)user_addr, bad_stack, | 84 | if (copy_to_user((void __user *)user_addr, bad_stack, |
77 | sizeof(good_stack))) { | 85 | unconst + sizeof(good_stack))) { |
78 | pr_warn("copy_to_user failed, but lacked Oops\n"); | 86 | pr_warn("copy_to_user failed, but lacked Oops\n"); |
79 | goto free_user; | 87 | goto free_user; |
80 | } | 88 | } |
@@ -88,14 +96,14 @@ static noinline void do_usercopy_stack(bool to_user, bool bad_frame) | |||
88 | 96 | ||
89 | pr_info("attempting good copy_from_user of local stack\n"); | 97 | pr_info("attempting good copy_from_user of local stack\n"); |
90 | if (copy_from_user(good_stack, (void __user *)user_addr, | 98 | if (copy_from_user(good_stack, (void __user *)user_addr, |
91 | sizeof(good_stack))) { | 99 | unconst + sizeof(good_stack))) { |
92 | pr_warn("copy_from_user failed unexpectedly?!\n"); | 100 | pr_warn("copy_from_user failed unexpectedly?!\n"); |
93 | goto free_user; | 101 | goto free_user; |
94 | } | 102 | } |
95 | 103 | ||
96 | pr_info("attempting bad copy_from_user of distant stack\n"); | 104 | pr_info("attempting bad copy_from_user of distant stack\n"); |
97 | if (copy_from_user(bad_stack, (void __user *)user_addr, | 105 | if (copy_from_user(bad_stack, (void __user *)user_addr, |
98 | sizeof(good_stack))) { | 106 | unconst + sizeof(good_stack))) { |
99 | pr_warn("copy_from_user failed, but lacked Oops\n"); | 107 | pr_warn("copy_from_user failed, but lacked Oops\n"); |
100 | goto free_user; | 108 | goto free_user; |
101 | } | 109 | } |
@@ -109,7 +117,7 @@ static void do_usercopy_heap_size(bool to_user) | |||
109 | { | 117 | { |
110 | unsigned long user_addr; | 118 | unsigned long user_addr; |
111 | unsigned char *one, *two; | 119 | unsigned char *one, *two; |
112 | const size_t size = 1024; | 120 | size_t size = unconst + 1024; |
113 | 121 | ||
114 | one = kmalloc(size, GFP_KERNEL); | 122 | one = kmalloc(size, GFP_KERNEL); |
115 | two = kmalloc(size, GFP_KERNEL); | 123 | two = kmalloc(size, GFP_KERNEL); |
@@ -285,13 +293,14 @@ void lkdtm_USERCOPY_KERNEL(void) | |||
285 | 293 | ||
286 | pr_info("attempting good copy_to_user from kernel rodata\n"); | 294 | pr_info("attempting good copy_to_user from kernel rodata\n"); |
287 | if (copy_to_user((void __user *)user_addr, test_text, | 295 | if (copy_to_user((void __user *)user_addr, test_text, |
288 | sizeof(test_text))) { | 296 | unconst + sizeof(test_text))) { |
289 | pr_warn("copy_to_user failed unexpectedly?!\n"); | 297 | pr_warn("copy_to_user failed unexpectedly?!\n"); |
290 | goto free_user; | 298 | goto free_user; |
291 | } | 299 | } |
292 | 300 | ||
293 | pr_info("attempting bad copy_to_user from kernel text\n"); | 301 | pr_info("attempting bad copy_to_user from kernel text\n"); |
294 | if (copy_to_user((void __user *)user_addr, vm_mmap, PAGE_SIZE)) { | 302 | if (copy_to_user((void __user *)user_addr, vm_mmap, |
303 | unconst + PAGE_SIZE)) { | ||
295 | pr_warn("copy_to_user failed, but lacked Oops\n"); | 304 | pr_warn("copy_to_user failed, but lacked Oops\n"); |
296 | goto free_user; | 305 | goto free_user; |
297 | } | 306 | } |