summaryrefslogtreecommitdiff
path: root/drivers/misc/lkdtm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/lkdtm')
-rw-r--r--drivers/misc/lkdtm/bugs.c53
-rw-r--r--drivers/misc/lkdtm/heap.c9
-rw-r--r--drivers/misc/lkdtm/lkdtm.h2
-rw-r--r--drivers/misc/lkdtm/perms.c22
-rw-r--r--drivers/misc/lkdtm/usercopy.c7
5 files changed, 53 insertions, 40 deletions
diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c
index 736675f0a246..4dfbfd51bdf7 100644
--- a/drivers/misc/lkdtm/bugs.c
+++ b/drivers/misc/lkdtm/bugs.c
@@ -13,7 +13,7 @@
#include <linux/uaccess.h>
#include <linux/slab.h>
-#ifdef CONFIG_X86_32
+#if IS_ENABLED(CONFIG_X86_32) && !IS_ENABLED(CONFIG_UML)
#include <asm/desc.h>
#endif
@@ -118,9 +118,8 @@ noinline void lkdtm_CORRUPT_STACK(void)
/* Use default char array length that triggers stack protection. */
char data[8] __aligned(sizeof(void *));
- __lkdtm_CORRUPT_STACK(&data);
-
- pr_info("Corrupted stack containing char array ...\n");
+ pr_info("Corrupting stack containing char array ...\n");
+ __lkdtm_CORRUPT_STACK((void *)&data);
}
/* Same as above but will only get a canary with -fstack-protector-strong */
@@ -131,9 +130,8 @@ noinline void lkdtm_CORRUPT_STACK_STRONG(void)
unsigned long *ptr;
} data __aligned(sizeof(void *));
- __lkdtm_CORRUPT_STACK(&data);
-
- pr_info("Corrupted stack containing union ...\n");
+ pr_info("Corrupting stack containing union ...\n");
+ __lkdtm_CORRUPT_STACK((void *)&data);
}
void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void)
@@ -248,6 +246,7 @@ void lkdtm_ARRAY_BOUNDS(void)
kfree(not_checked);
kfree(checked);
+ pr_err("FAIL: survived array bounds overflow!\n");
}
void lkdtm_CORRUPT_LIST_ADD(void)
@@ -334,7 +333,7 @@ void lkdtm_STACK_GUARD_PAGE_LEADING(void)
byte = *ptr;
- pr_err("FAIL: accessed page before stack!\n");
+ pr_err("FAIL: accessed page before stack! (byte: %x)\n", byte);
}
/* Test that VMAP_STACK is actually allocating with a trailing guard page */
@@ -348,7 +347,7 @@ void lkdtm_STACK_GUARD_PAGE_TRAILING(void)
byte = *ptr;
- pr_err("FAIL: accessed page after stack!\n");
+ pr_err("FAIL: accessed page after stack! (byte: %x)\n", byte);
}
void lkdtm_UNSET_SMEP(void)
@@ -419,7 +418,7 @@ void lkdtm_UNSET_SMEP(void)
void lkdtm_DOUBLE_FAULT(void)
{
-#ifdef CONFIG_X86_32
+#if IS_ENABLED(CONFIG_X86_32) && !IS_ENABLED(CONFIG_UML)
/*
* Trigger #DF by setting the stack limit to zero. This clobbers
* a GDT TLS slot, which is okay because the current task will die
@@ -454,38 +453,42 @@ void lkdtm_DOUBLE_FAULT(void)
#endif
}
-#ifdef CONFIG_ARM64_PTR_AUTH
+#ifdef CONFIG_ARM64
static noinline void change_pac_parameters(void)
{
- /* Reset the keys of current task */
- ptrauth_thread_init_kernel(current);
- ptrauth_thread_switch_kernel(current);
+ if (IS_ENABLED(CONFIG_ARM64_PTR_AUTH)) {
+ /* Reset the keys of current task */
+ ptrauth_thread_init_kernel(current);
+ ptrauth_thread_switch_kernel(current);
+ }
}
+#endif
-#define CORRUPT_PAC_ITERATE 10
noinline void lkdtm_CORRUPT_PAC(void)
{
+#ifdef CONFIG_ARM64
+#define CORRUPT_PAC_ITERATE 10
int i;
+ if (!IS_ENABLED(CONFIG_ARM64_PTR_AUTH))
+ pr_err("FAIL: kernel not built with CONFIG_ARM64_PTR_AUTH\n");
+
if (!system_supports_address_auth()) {
- pr_err("FAIL: arm64 pointer authentication feature not present\n");
+ pr_err("FAIL: CPU lacks pointer authentication feature\n");
return;
}
- pr_info("Change the PAC parameters to force function return failure\n");
+ pr_info("changing PAC parameters to force function return failure...\n");
/*
- * Pac is a hash value computed from input keys, return address and
+ * PAC is a hash value computed from input keys, return address and
* stack pointer. As pac has fewer bits so there is a chance of
* collision, so iterate few times to reduce the collision probability.
*/
for (i = 0; i < CORRUPT_PAC_ITERATE; i++)
change_pac_parameters();
- pr_err("FAIL: %s test failed. Kernel may be unstable from here\n", __func__);
-}
-#else /* !CONFIG_ARM64_PTR_AUTH */
-noinline void lkdtm_CORRUPT_PAC(void)
-{
- pr_err("FAIL: arm64 pointer authentication config disabled\n");
-}
+ pr_err("FAIL: survived PAC changes! Kernel may be unstable from here\n");
+#else
+ pr_err("XFAIL: this test is arm64-only\n");
#endif
+}
diff --git a/drivers/misc/lkdtm/heap.c b/drivers/misc/lkdtm/heap.c
index 3c5cec85edce..1323bc16f113 100644
--- a/drivers/misc/lkdtm/heap.c
+++ b/drivers/misc/lkdtm/heap.c
@@ -58,11 +58,12 @@ void lkdtm_READ_AFTER_FREE(void)
int *base, *val, saw;
size_t len = 1024;
/*
- * The slub allocator uses the first word to store the free
- * pointer in some configurations. Use the middle of the
- * allocation to avoid running into the freelist
+ * The slub allocator will use the either the first word or
+ * the middle of the allocation to store the free pointer,
+ * depending on configurations. Store in the second word to
+ * avoid running into the freelist.
*/
- size_t offset = (len / sizeof(*base)) / 2;
+ size_t offset = sizeof(*base);
base = kmalloc(len, GFP_KERNEL);
if (!base) {
diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h
index 601a2156a0d4..8878538b2c13 100644
--- a/drivers/misc/lkdtm/lkdtm.h
+++ b/drivers/misc/lkdtm/lkdtm.h
@@ -31,9 +31,7 @@ void lkdtm_CORRUPT_USER_DS(void);
void lkdtm_STACK_GUARD_PAGE_LEADING(void);
void lkdtm_STACK_GUARD_PAGE_TRAILING(void);
void lkdtm_UNSET_SMEP(void);
-#ifdef CONFIG_X86_32
void lkdtm_DOUBLE_FAULT(void);
-#endif
void lkdtm_CORRUPT_PAC(void);
/* lkdtm_heap.c */
diff --git a/drivers/misc/lkdtm/perms.c b/drivers/misc/lkdtm/perms.c
index 62f76d506f04..2dede2ef658f 100644
--- a/drivers/misc/lkdtm/perms.c
+++ b/drivers/misc/lkdtm/perms.c
@@ -57,6 +57,7 @@ static noinline void execute_location(void *dst, bool write)
}
pr_info("attempting bad execution at %px\n", func);
func();
+ pr_err("FAIL: func returned\n");
}
static void execute_user_location(void *dst)
@@ -75,20 +76,22 @@ static void execute_user_location(void *dst)
return;
pr_info("attempting bad execution at %px\n", func);
func();
+ pr_err("FAIL: func returned\n");
}
void lkdtm_WRITE_RO(void)
{
- /* Explicitly cast away "const" for the test. */
- unsigned long *ptr = (unsigned long *)&rodata;
+ /* Explicitly cast away "const" for the test and make volatile. */
+ volatile unsigned long *ptr = (unsigned long *)&rodata;
pr_info("attempting bad rodata write at %px\n", ptr);
*ptr ^= 0xabcd1234;
+ pr_err("FAIL: survived bad write\n");
}
void lkdtm_WRITE_RO_AFTER_INIT(void)
{
- unsigned long *ptr = &ro_after_init;
+ volatile unsigned long *ptr = &ro_after_init;
/*
* Verify we were written to during init. Since an Oops
@@ -102,19 +105,21 @@ void lkdtm_WRITE_RO_AFTER_INIT(void)
pr_info("attempting bad ro_after_init write at %px\n", ptr);
*ptr ^= 0xabcd1234;
+ pr_err("FAIL: survived bad write\n");
}
void lkdtm_WRITE_KERN(void)
{
size_t size;
- unsigned char *ptr;
+ volatile unsigned char *ptr;
size = (unsigned long)do_overwritten - (unsigned long)do_nothing;
ptr = (unsigned char *)do_overwritten;
pr_info("attempting bad %zu byte write at %px\n", size, ptr);
- memcpy(ptr, (unsigned char *)do_nothing, size);
+ memcpy((void *)ptr, (unsigned char *)do_nothing, size);
flush_icache_range((unsigned long)ptr, (unsigned long)(ptr + size));
+ pr_err("FAIL: survived bad write\n");
do_overwritten();
}
@@ -193,9 +198,11 @@ void lkdtm_ACCESS_USERSPACE(void)
pr_info("attempting bad read at %px\n", ptr);
tmp = *ptr;
tmp += 0xc0dec0de;
+ pr_err("FAIL: survived bad read\n");
pr_info("attempting bad write at %px\n", ptr);
*ptr = tmp;
+ pr_err("FAIL: survived bad write\n");
vm_munmap(user_addr, PAGE_SIZE);
}
@@ -203,19 +210,20 @@ void lkdtm_ACCESS_USERSPACE(void)
void lkdtm_ACCESS_NULL(void)
{
unsigned long tmp;
- unsigned long *ptr = (unsigned long *)NULL;
+ volatile unsigned long *ptr = (unsigned long *)NULL;
pr_info("attempting bad read at %px\n", ptr);
tmp = *ptr;
tmp += 0xc0dec0de;
+ pr_err("FAIL: survived bad read\n");
pr_info("attempting bad write at %px\n", ptr);
*ptr = tmp;
+ pr_err("FAIL: survived bad write\n");
}
void __init lkdtm_perms_init(void)
{
/* Make sure we can write to __ro_after_init values during __init */
ro_after_init |= 0xAA;
-
}
diff --git a/drivers/misc/lkdtm/usercopy.c b/drivers/misc/lkdtm/usercopy.c
index e172719dd86d..b833367a45d0 100644
--- a/drivers/misc/lkdtm/usercopy.c
+++ b/drivers/misc/lkdtm/usercopy.c
@@ -304,19 +304,22 @@ void lkdtm_USERCOPY_KERNEL(void)
return;
}
- pr_info("attempting good copy_to_user from kernel rodata\n");
+ pr_info("attempting good copy_to_user from kernel rodata: %px\n",
+ test_text);
if (copy_to_user((void __user *)user_addr, 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");
+ pr_info("attempting bad copy_to_user from kernel text: %px\n",
+ vm_mmap);
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;
}
+ pr_err("FAIL: survived bad copy_to_user()\n");
free_user:
vm_munmap(user_addr, PAGE_SIZE);