From 2bf8496f6e9b7e9a557f65eb95eab16fea7958c7 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Sat, 6 Apr 2019 08:52:11 -0700 Subject: lkdtm/usercopy: Moves the KERNEL_DS test to non-canonical The prior implementation of the KERNEL_DS fault checking would work on any unmapped kernel address, but this was narrowed to the non-canonical range instead. This adjusts the LKDTM test to match. Fixes: 00c42373d397 ("x86-64: add warning for non-canonical user access address dereferences") Signed-off-by: Kees Cook --- drivers/misc/lkdtm/usercopy.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/misc/lkdtm') diff --git a/drivers/misc/lkdtm/usercopy.c b/drivers/misc/lkdtm/usercopy.c index d5a0e7f1813b..e172719dd86d 100644 --- a/drivers/misc/lkdtm/usercopy.c +++ b/drivers/misc/lkdtm/usercopy.c @@ -324,14 +324,16 @@ free_user: void lkdtm_USERCOPY_KERNEL_DS(void) { - char __user *user_ptr = (char __user *)ERR_PTR(-EINVAL); + char __user *user_ptr = + (char __user *)(0xFUL << (sizeof(unsigned long) * 8 - 4)); mm_segment_t old_fs = get_fs(); char buf[10] = {0}; - pr_info("attempting copy_to_user on unmapped kernel address\n"); + pr_info("attempting copy_to_user() to noncanonical address: %px\n", + user_ptr); set_fs(KERNEL_DS); - if (copy_to_user(user_ptr, buf, sizeof(buf))) - pr_info("copy_to_user un unmapped kernel address failed\n"); + if (copy_to_user(user_ptr, buf, sizeof(buf)) == 0) + pr_err("copy_to_user() to noncanonical address succeeded!?\n"); set_fs(old_fs); } -- cgit v1.2.3 From 24cccab42c4199c6daa0a6981e6f6a1ffb0b5a09 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Sat, 6 Apr 2019 08:59:19 -0700 Subject: lkdtm/bugs: Adjust recursion test to avoid elision While I was able to trick gcc into keeping a pathological recursion, Clang was not so easily fooled. Instead, switch to using "volatile" and side-effects to keep the stack variable allocated and to run the function. Additionally renames "OVERFLOW" to "EXHAUST_STACK" to better describe the test. Signed-off-by: Kees Cook --- drivers/misc/lkdtm/bugs.c | 23 +++++++++++++++++------ drivers/misc/lkdtm/core.c | 6 +++--- drivers/misc/lkdtm/lkdtm.h | 2 +- 3 files changed, 21 insertions(+), 10 deletions(-) (limited to 'drivers/misc/lkdtm') diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c index 7eebbdfbcacd..17f839dee976 100644 --- a/drivers/misc/lkdtm/bugs.c +++ b/drivers/misc/lkdtm/bugs.c @@ -32,12 +32,20 @@ static int recur_count = REC_NUM_DEFAULT; static DEFINE_SPINLOCK(lock_me_up); -static int recursive_loop(int remaining) +/* + * Make sure compiler does not optimize this function or stack frame away: + * - function marked noinline + * - stack variables are marked volatile + * - stack variables are written (memset()) and read (pr_info()) + * - function has external effects (pr_info()) + * */ +static int noinline recursive_loop(int remaining) { - char buf[REC_STACK_SIZE]; + volatile char buf[REC_STACK_SIZE]; - /* Make sure compiler does not optimize this away. */ - memset(buf, (remaining & 0xff) | 0x1, REC_STACK_SIZE); + memset((void *)buf, remaining & 0xFF, sizeof(buf)); + pr_info("loop %d/%d ...\n", (int)buf[remaining % sizeof(buf)], + recur_count); if (!remaining) return 0; else @@ -81,9 +89,12 @@ void lkdtm_LOOP(void) ; } -void lkdtm_OVERFLOW(void) +void lkdtm_EXHAUST_STACK(void) { - (void) recursive_loop(recur_count); + pr_info("Calling function with %d frame size to depth %d ...\n", + REC_STACK_SIZE, recur_count); + recursive_loop(recur_count); + pr_info("FAIL: survived without exhausting stack?!\n"); } static noinline void __lkdtm_CORRUPT_STACK(void *stack) diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c index b51cf182b031..4f3a6e1cd331 100644 --- a/drivers/misc/lkdtm/core.c +++ b/drivers/misc/lkdtm/core.c @@ -119,12 +119,12 @@ static const struct crashtype crashtypes[] = { CRASHTYPE(WARNING), CRASHTYPE(EXCEPTION), CRASHTYPE(LOOP), - CRASHTYPE(OVERFLOW), + CRASHTYPE(EXHAUST_STACK), + CRASHTYPE(CORRUPT_STACK), + CRASHTYPE(CORRUPT_STACK_STRONG), CRASHTYPE(CORRUPT_LIST_ADD), CRASHTYPE(CORRUPT_LIST_DEL), CRASHTYPE(CORRUPT_USER_DS), - CRASHTYPE(CORRUPT_STACK), - CRASHTYPE(CORRUPT_STACK_STRONG), CRASHTYPE(STACK_GUARD_PAGE_LEADING), CRASHTYPE(STACK_GUARD_PAGE_TRAILING), CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE), diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h index b69ee004a3f7..23dc565b4307 100644 --- a/drivers/misc/lkdtm/lkdtm.h +++ b/drivers/misc/lkdtm/lkdtm.h @@ -13,7 +13,7 @@ void lkdtm_BUG(void); void lkdtm_WARNING(void); void lkdtm_EXCEPTION(void); void lkdtm_LOOP(void); -void lkdtm_OVERFLOW(void); +void lkdtm_EXHAUST_STACK(void); void lkdtm_CORRUPT_STACK(void); void lkdtm_CORRUPT_STACK_STRONG(void); void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void); -- cgit v1.2.3