From 007213b1d080e3cdbc2833cb1e6991f7dcdcf8a7 Mon Sep 17 00:00:00 2001 From: Yee Lee Date: Tue, 13 Jul 2021 13:39:59 +0800 Subject: [PATCH] BACKPORT: FROMLIST: kasan: add memzero int for unaligned size at DEBUG Issue: when SLUB debug is on, hwtag kasan_unpoison() would overwrite the redzone of object with unaligned size. An additional memzero_explicit() path is added to replacing init by hwtag instruction for those unaligned size at SLUB debug mode. The penalty is acceptable since they are only enabled in debug mode, not production builds. A block of comment is added for explanation. Link: https://lore.kernel.org/lkml/20210705103229.8505-3-yee.lee@mediatek.com/ Signed-off-by: Yee Lee Suggested-by: Andrey Konovalov Suggested-by: Marco Elver Cc: Andrey Ryabinin Cc: Alexander Potapenko Cc: Dmitry Vyukov Cc: Nicholas Tang Cc: Kuan-Ying Lee Cc: Chinwen Chang Cc: Matthew Wilcox Signed-off-by: Andrew Morton Bug: 193482732 Change-Id: Ie0f6a15637d212f5a273e13b7d271376c074cb91 Signed-off-by: Yee Lee --- mm/kasan/kasan.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h index 3820ca54743b..ed9c45a63f9a 100644 --- a/mm/kasan/kasan.h +++ b/mm/kasan/kasan.h @@ -9,6 +9,7 @@ #ifdef CONFIG_KASAN_HW_TAGS #include +#include "../slab.h" DECLARE_STATIC_KEY_FALSE(kasan_flag_stacktrace); extern bool kasan_flag_async __ro_after_init; @@ -387,6 +388,17 @@ static inline void kasan_unpoison(const void *addr, size_t size, bool init) if (WARN_ON((unsigned long)addr & KASAN_GRANULE_MASK)) return; + /* + * Explicitly initialize the memory with the precise object size to + * avoid overwriting the SLAB redzone. This disables initialization in + * the arch code and may thus lead to performance penalty. The penalty + * is accepted since SLAB redzones aren't enabled in production builds. + */ + if (__slub_debug_enabled() && + init && ((unsigned long)size & KASAN_GRANULE_MASK)) { + init = false; + memzero_explicit((void *)addr, size); + } size = round_up(size, KASAN_GRANULE_SIZE); hw_set_mem_tag_range((void *)addr, size, tag, init);