forked from Minki/linux
kasan: support use-after-scope detection
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. [dvyukov@google.com: v3] Link: http://lkml.kernel.org/r/1479998292-144502-1-git-send-email-dvyukov@google.com Link: http://lkml.kernel.org/r/1479226045-145148-1-git-send-email-dvyukov@google.com Signed-off-by: Dmitry Vyukov <dvyukov@google.com> Acked-by: Andrey Ryabinin <aryabinin@virtuozzo.com> Cc: Alexander Potapenko <glider@google.com> Cc: <stable@vger.kernel.org> [4.0+] Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
045d599a28
commit
828347f8f9
@ -20,6 +20,11 @@
|
|||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/module.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)
|
static noinline void __init kmalloc_oob_right(void)
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
@ -411,6 +416,29 @@ static noinline void __init copy_user_test(void)
|
|||||||
kfree(kmem);
|
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)
|
static int __init kmalloc_tests_init(void)
|
||||||
{
|
{
|
||||||
kmalloc_oob_right();
|
kmalloc_oob_right();
|
||||||
@ -436,6 +464,7 @@ static int __init kmalloc_tests_init(void)
|
|||||||
kasan_global_oob();
|
kasan_global_oob();
|
||||||
ksize_unpoisons_memory();
|
ksize_unpoisons_memory();
|
||||||
copy_user_test();
|
copy_user_test();
|
||||||
|
use_after_scope_test();
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -764,6 +764,25 @@ EXPORT_SYMBOL(__asan_storeN_noabort);
|
|||||||
void __asan_handle_no_return(void) {}
|
void __asan_handle_no_return(void) {}
|
||||||
EXPORT_SYMBOL(__asan_handle_no_return);
|
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
|
#ifdef CONFIG_MEMORY_HOTPLUG
|
||||||
static int kasan_mem_notifier(struct notifier_block *nb,
|
static int kasan_mem_notifier(struct notifier_block *nb,
|
||||||
unsigned long action, void *data)
|
unsigned long action, void *data)
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define KASAN_STACK_MID 0xF2
|
#define KASAN_STACK_MID 0xF2
|
||||||
#define KASAN_STACK_RIGHT 0xF3
|
#define KASAN_STACK_RIGHT 0xF3
|
||||||
#define KASAN_STACK_PARTIAL 0xF4
|
#define KASAN_STACK_PARTIAL 0xF4
|
||||||
|
#define KASAN_USE_AFTER_SCOPE 0xF8
|
||||||
|
|
||||||
/* Don't break randconfig/all*config builds */
|
/* Don't break randconfig/all*config builds */
|
||||||
#ifndef KASAN_ABI_VERSION
|
#ifndef KASAN_ABI_VERSION
|
||||||
|
@ -90,6 +90,9 @@ static void print_error_description(struct kasan_access_info *info)
|
|||||||
case KASAN_KMALLOC_FREE:
|
case KASAN_KMALLOC_FREE:
|
||||||
bug_type = "use-after-free";
|
bug_type = "use-after-free";
|
||||||
break;
|
break;
|
||||||
|
case KASAN_USE_AFTER_SCOPE:
|
||||||
|
bug_type = "use-after-scope";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_err("BUG: KASAN: %s in %pS at addr %p\n",
|
pr_err("BUG: KASAN: %s in %pS at addr %p\n",
|
||||||
|
Loading…
Reference in New Issue
Block a user