Commit e9121076 authored by Andrey Konovalov's avatar Andrey Konovalov Committed by Linus Torvalds

kasan: update reported bug types for not user nor kernel memory accesses

Each access with address lower than
kasan_shadow_to_mem(KASAN_SHADOW_START) is reported as user-memory-access.
This is not always true, the accessed address might not be in user space.
Fix this by reporting such accesses as null-ptr-derefs or
wild-memory-accesses.

There's another reason for this change.  For userspace ASan we have a
bunch of systems that analyze error types for the purpose of
classification and deduplication.  Sooner of later we will write them to
KASAN as well.  Then clearly and explicitly stated error types will bring
value.
Signed-off-by: default avatarAndrey Konovalov <andreyknvl@google.com>
Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Konstantin Serebryany <kcc@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent fc5aeeaf
...@@ -235,18 +235,12 @@ static __always_inline bool memory_is_poisoned(unsigned long addr, size_t size) ...@@ -235,18 +235,12 @@ static __always_inline bool memory_is_poisoned(unsigned long addr, size_t size)
static __always_inline void check_memory_region(unsigned long addr, static __always_inline void check_memory_region(unsigned long addr,
size_t size, bool write) size_t size, bool write)
{ {
struct kasan_access_info info;
if (unlikely(size == 0)) if (unlikely(size == 0))
return; return;
if (unlikely((void *)addr < if (unlikely((void *)addr <
kasan_shadow_to_mem((void *)KASAN_SHADOW_START))) { kasan_shadow_to_mem((void *)KASAN_SHADOW_START))) {
info.access_addr = (void *)addr; kasan_report(addr, size, write, _RET_IP_);
info.access_size = size;
info.is_write = write;
info.ip = _RET_IP_;
kasan_report_user_access(&info);
return; return;
} }
......
...@@ -54,9 +54,6 @@ struct kasan_global { ...@@ -54,9 +54,6 @@ struct kasan_global {
#endif #endif
}; };
void kasan_report_error(struct kasan_access_info *info);
void kasan_report_user_access(struct kasan_access_info *info);
static inline const void *kasan_shadow_to_mem(const void *shadow_addr) static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
{ {
return (void *)(((unsigned long)shadow_addr - KASAN_SHADOW_OFFSET) return (void *)(((unsigned long)shadow_addr - KASAN_SHADOW_OFFSET)
......
...@@ -189,9 +189,10 @@ static void print_shadow_for_address(const void *addr) ...@@ -189,9 +189,10 @@ static void print_shadow_for_address(const void *addr)
static DEFINE_SPINLOCK(report_lock); static DEFINE_SPINLOCK(report_lock);
void kasan_report_error(struct kasan_access_info *info) static void kasan_report_error(struct kasan_access_info *info)
{ {
unsigned long flags; unsigned long flags;
const char *bug_type;
/* /*
* Make sure we don't end up in loop. * Make sure we don't end up in loop.
...@@ -200,32 +201,26 @@ void kasan_report_error(struct kasan_access_info *info) ...@@ -200,32 +201,26 @@ void kasan_report_error(struct kasan_access_info *info)
spin_lock_irqsave(&report_lock, flags); spin_lock_irqsave(&report_lock, flags);
pr_err("=================================" pr_err("================================="
"=================================\n"); "=================================\n");
print_error_description(info); if (info->access_addr <
print_address_description(info); kasan_shadow_to_mem((void *)KASAN_SHADOW_START)) {
print_shadow_for_address(info->first_bad_addr); if ((unsigned long)info->access_addr < PAGE_SIZE)
pr_err("=================================" bug_type = "null-ptr-deref";
"=================================\n"); else if ((unsigned long)info->access_addr < TASK_SIZE)
spin_unlock_irqrestore(&report_lock, flags); bug_type = "user-memory-access";
kasan_enable_current(); else
} bug_type = "wild-memory-access";
pr_err("BUG: KASan: %s on address %p\n",
void kasan_report_user_access(struct kasan_access_info *info) bug_type, info->access_addr);
{ pr_err("%s of size %zu by task %s/%d\n",
unsigned long flags; info->is_write ? "Write" : "Read",
info->access_size, current->comm,
/* task_pid_nr(current));
* Make sure we don't end up in loop. dump_stack();
*/ } else {
kasan_disable_current(); print_error_description(info);
spin_lock_irqsave(&report_lock, flags); print_address_description(info);
pr_err("=================================" print_shadow_for_address(info->first_bad_addr);
"=================================\n"); }
pr_err("BUG: KASan: user-memory-access on address %p\n",
info->access_addr);
pr_err("%s of size %zu by task %s/%d\n",
info->is_write ? "Write" : "Read",
info->access_size, current->comm, task_pid_nr(current));
dump_stack();
pr_err("=================================" pr_err("================================="
"=================================\n"); "=================================\n");
spin_unlock_irqrestore(&report_lock, flags); spin_unlock_irqrestore(&report_lock, flags);
...@@ -244,6 +239,7 @@ void kasan_report(unsigned long addr, size_t size, ...@@ -244,6 +239,7 @@ void kasan_report(unsigned long addr, size_t size,
info.access_size = size; info.access_size = size;
info.is_write = is_write; info.is_write = is_write;
info.ip = ip; info.ip = ip;
kasan_report_error(&info); kasan_report_error(&info);
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment