Re: [PATCH 2/4] mm/kasan: print name of mem[set,cpy,move]() caller in report

From: Alexander Potapenko
Date: Fri May 13 2016 - 08:15:35 EST


On Fri, May 6, 2016 at 2:45 PM, Andrey Ryabinin <aryabinin@xxxxxxxxxxxxx> wrote:
> When bogus memory access happens in mem[set,cpy,move]() it's usually
> caller's fault. So don't blame mem[set,cpy,move]() in bug report, blame
> the caller instead.
>
> Before:
> BUG: KASAN: out-of-bounds access in memset+0x23/0x40 at <address>
> After:
> BUG: KASAN: out-of-bounds access in <memset_caller> at <address>
>
> Signed-off-by: Andrey Ryabinin <aryabinin@xxxxxxxxxxxxx>
> Cc: Alexander Potapenko <glider@xxxxxxxxxx>
> Cc: Dmitry Vyukov <dvyukov@xxxxxxxxxx>
> ---
> mm/kasan/kasan.c | 64 ++++++++++++++++++++++++++++++--------------------------
> 1 file changed, 34 insertions(+), 30 deletions(-)
>
> diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
> index ef2e87b..6e4072c 100644
> --- a/mm/kasan/kasan.c
> +++ b/mm/kasan/kasan.c
> @@ -273,32 +273,36 @@ static __always_inline bool memory_is_poisoned(unsigned long addr, size_t size)
> return memory_is_poisoned_n(addr, size);
> }
>
> -
> -static __always_inline void check_memory_region(unsigned long addr,
> - size_t size, bool write)
> +static __always_inline void check_memory_region_inline(unsigned long addr,
> + size_t size, bool write,
> + unsigned long ret_ip)
> {
> if (unlikely(size == 0))
> return;
>
> if (unlikely((void *)addr <
> kasan_shadow_to_mem((void *)KASAN_SHADOW_START))) {
> - kasan_report(addr, size, write, _RET_IP_);
> + kasan_report(addr, size, write, ret_ip);
> return;
> }
>
> if (likely(!memory_is_poisoned(addr, size)))
> return;
>
> - kasan_report(addr, size, write, _RET_IP_);
> + kasan_report(addr, size, write, ret_ip);
> }
>
> -void __asan_loadN(unsigned long addr, size_t size);
> -void __asan_storeN(unsigned long addr, size_t size);
> +static void check_memory_region(unsigned long addr,
> + size_t size, bool write,
> + unsigned long ret_ip)
> +{
> + check_memory_region_inline(addr, size, write, ret_ip);
> +}
>
> #undef memset
> void *memset(void *addr, int c, size_t len)
> {
> - __asan_storeN((unsigned long)addr, len);
> + check_memory_region((unsigned long)addr, len, true, _RET_IP_);
>
> return __memset(addr, c, len);
> }
> @@ -306,8 +310,8 @@ void *memset(void *addr, int c, size_t len)
> #undef memmove
> void *memmove(void *dest, const void *src, size_t len)
> {
> - __asan_loadN((unsigned long)src, len);
> - __asan_storeN((unsigned long)dest, len);
> + check_memory_region((unsigned long)src, len, false, _RET_IP_);
> + check_memory_region((unsigned long)dest, len, true, _RET_IP_);
>
> return __memmove(dest, src, len);
> }
> @@ -315,8 +319,8 @@ void *memmove(void *dest, const void *src, size_t len)
> #undef memcpy
> void *memcpy(void *dest, const void *src, size_t len)
> {
> - __asan_loadN((unsigned long)src, len);
> - __asan_storeN((unsigned long)dest, len);
> + check_memory_region((unsigned long)src, len, false, _RET_IP_);
> + check_memory_region((unsigned long)dest, len, true, _RET_IP_);
>
> return __memcpy(dest, src, len);
> }
> @@ -698,22 +702,22 @@ void __asan_unregister_globals(struct kasan_global *globals, size_t size)
> }
> EXPORT_SYMBOL(__asan_unregister_globals);
>
> -#define DEFINE_ASAN_LOAD_STORE(size) \
> - void __asan_load##size(unsigned long addr) \
> - { \
> - check_memory_region(addr, size, false); \
> - } \
> - EXPORT_SYMBOL(__asan_load##size); \
> - __alias(__asan_load##size) \
> - void __asan_load##size##_noabort(unsigned long); \
> - EXPORT_SYMBOL(__asan_load##size##_noabort); \
> - void __asan_store##size(unsigned long addr) \
> - { \
> - check_memory_region(addr, size, true); \
> - } \
> - EXPORT_SYMBOL(__asan_store##size); \
> - __alias(__asan_store##size) \
> - void __asan_store##size##_noabort(unsigned long); \
> +#define DEFINE_ASAN_LOAD_STORE(size) \
> + void __asan_load##size(unsigned long addr) \
> + { \
> + check_memory_region_inline(addr, size, false, _RET_IP_);\
> + } \
> + EXPORT_SYMBOL(__asan_load##size); \
> + __alias(__asan_load##size) \
> + void __asan_load##size##_noabort(unsigned long); \
> + EXPORT_SYMBOL(__asan_load##size##_noabort); \
> + void __asan_store##size(unsigned long addr) \
> + { \
> + check_memory_region_inline(addr, size, true, _RET_IP_); \
> + } \
> + EXPORT_SYMBOL(__asan_store##size); \
> + __alias(__asan_store##size) \
> + void __asan_store##size##_noabort(unsigned long); \
> EXPORT_SYMBOL(__asan_store##size##_noabort)
>
> DEFINE_ASAN_LOAD_STORE(1);
> @@ -724,7 +728,7 @@ DEFINE_ASAN_LOAD_STORE(16);
>
> void __asan_loadN(unsigned long addr, size_t size)
> {
> - check_memory_region(addr, size, false);
> + check_memory_region(addr, size, false, _RET_IP_);
> }
> EXPORT_SYMBOL(__asan_loadN);
>
> @@ -734,7 +738,7 @@ EXPORT_SYMBOL(__asan_loadN_noabort);
>
> void __asan_storeN(unsigned long addr, size_t size)
> {
> - check_memory_region(addr, size, true);
> + check_memory_region(addr, size, true, _RET_IP_);
> }
> EXPORT_SYMBOL(__asan_storeN);
>
> --Reviewed-by:
> 2.7.3
>
Acked-by: Alexander Potapenko <glider@xxxxxxxxxx>



--
Alexander Potapenko
Software Engineer

Google Germany GmbH
Erika-Mann-StraÃe, 33
80636 MÃnchen

GeschÃftsfÃhrer: Matthew Scott Sucherman, Paul Terence Manicle
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg