Skip to content
This repository has been archived by the owner on Dec 14, 2022. It is now read-only.

Commit

Permalink
kasan: support use-after-scope detection
Browse files Browse the repository at this point in the history
Gcc revision 241896 implements use-after-scope detection.  Will be
available in gcc 7.  Support it in KASAN.

Gcc emits 2 new callbacks to poison/unpoison large stack objects when
they go in/out of scope.  Implement the callbacks and add a test.

[[email protected]: v3]
  Link: http://lkml.kernel.org/r/[email protected]
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Dmitry Vyukov <[email protected]>
Acked-by: Andrey Ryabinin <[email protected]>
Cc: Alexander Potapenko <[email protected]>
Cc: <[email protected]>	[4.0+]
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
dvyukov authored and torvalds committed Dec 1, 2016
1 parent 045d599 commit 828347f
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 0 deletions.
29 changes: 29 additions & 0 deletions lib/test_kasan.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
#include <linux/uaccess.h>
#include <linux/module.h>

/*
* Note: test functions are marked noinline so that their names appear in
* reports.
*/

static noinline void __init kmalloc_oob_right(void)
{
char *ptr;
Expand Down Expand Up @@ -411,6 +416,29 @@ static noinline void __init copy_user_test(void)
kfree(kmem);
}

static noinline void __init use_after_scope_test(void)
{
volatile char *volatile p;

pr_info("use-after-scope on int\n");
{
int local = 0;

p = (char *)&local;
}
p[0] = 1;
p[3] = 1;

pr_info("use-after-scope on array\n");
{
char local[1024] = {0};

p = local;
}
p[0] = 1;
p[1023] = 1;
}

static int __init kmalloc_tests_init(void)
{
kmalloc_oob_right();
Expand All @@ -436,6 +464,7 @@ static int __init kmalloc_tests_init(void)
kasan_global_oob();
ksize_unpoisons_memory();
copy_user_test();
use_after_scope_test();
return -EAGAIN;
}

Expand Down
19 changes: 19 additions & 0 deletions mm/kasan/kasan.c
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,25 @@ EXPORT_SYMBOL(__asan_storeN_noabort);
void __asan_handle_no_return(void) {}
EXPORT_SYMBOL(__asan_handle_no_return);

/* Emitted by compiler to poison large objects when they go out of scope. */
void __asan_poison_stack_memory(const void *addr, size_t size)
{
/*
* Addr is KASAN_SHADOW_SCALE_SIZE-aligned and the object is surrounded
* by redzones, so we simply round up size to simplify logic.
*/
kasan_poison_shadow(addr, round_up(size, KASAN_SHADOW_SCALE_SIZE),
KASAN_USE_AFTER_SCOPE);
}
EXPORT_SYMBOL(__asan_poison_stack_memory);

/* Emitted by compiler to unpoison large objects when they go into scope. */
void __asan_unpoison_stack_memory(const void *addr, size_t size)
{
kasan_unpoison_shadow(addr, size);
}
EXPORT_SYMBOL(__asan_unpoison_stack_memory);

#ifdef CONFIG_MEMORY_HOTPLUG
static int kasan_mem_notifier(struct notifier_block *nb,
unsigned long action, void *data)
Expand Down
1 change: 1 addition & 0 deletions mm/kasan/kasan.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#define KASAN_STACK_MID 0xF2
#define KASAN_STACK_RIGHT 0xF3
#define KASAN_STACK_PARTIAL 0xF4
#define KASAN_USE_AFTER_SCOPE 0xF8

/* Don't break randconfig/all*config builds */
#ifndef KASAN_ABI_VERSION
Expand Down
3 changes: 3 additions & 0 deletions mm/kasan/report.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ static void print_error_description(struct kasan_access_info *info)
case KASAN_KMALLOC_FREE:
bug_type = "use-after-free";
break;
case KASAN_USE_AFTER_SCOPE:
bug_type = "use-after-scope";
break;
}

pr_err("BUG: KASAN: %s in %pS at addr %p\n",
Expand Down

0 comments on commit 828347f

Please sign in to comment.