From 9484ee8820c6329ad72ed7e29b0c0b59d7a8caa7 Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Wed, 9 Jun 2021 14:05:25 +0200 Subject: [PATCH] ANDROID: kasan: fix interoperability with KFENCE MTE-related KASAN changes were preceded by noticeable KASAN refactorings that were backported to android12-5.10, but not android12-5.4. As a result, some last-minute mm changes fixing "kfence, kasan: make KFENCE compatible with KASAN" (https://android.googlesource.com/kernel/common/+/f03825db4d6834a9d97e96eee2404a36ca79dafa) did not make it to android12-5.4. Given that they do not exist as separate upstream commits and do not apply cleanly to 5.4 kernels, reimplement them. These changes boil down to skipping KASAN poisoning for KFENCE-allocated objects and to resetting the object tag in __kasan_kmalloc(). Bug: 172318110 Bug: 190593700 Signed-off-by: Alexander Potapenko Change-Id: I117ea37a1d41514a3c5beaf87386bb5f2f0046c8 --- mm/kasan/common.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/mm/kasan/common.c b/mm/kasan/common.c index f8e330596664..b71b16da066e 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -141,6 +141,10 @@ void kasan_poison_shadow(const void *address, size_t size, u8 value) */ address = reset_tag(address); + /* Skip KFENCE memory if called explicitly outside of sl*b. */ + if (is_kfence_address(address)) + return; + shadow_start = kasan_mem_to_shadow(address); shadow_end = kasan_mem_to_shadow(address + size); @@ -158,6 +162,14 @@ void kasan_unpoison_shadow(const void *address, size_t size) */ address = reset_tag(address); + /* + * Skip KFENCE memory if called explicitly outside of sl*b. Also note + * that calls to ksize(), where size is not a multiple of machine-word + * size, would otherwise poison the invalid portion of the word. + */ + if (is_kfence_address(address)) + return; + kasan_poison_shadow(address, size, tag); if (size & KASAN_SHADOW_MASK) { @@ -497,7 +509,7 @@ static void *__kasan_kmalloc(struct kmem_cache *cache, const void *object, if (unlikely(object == NULL)) return NULL; - if (is_kfence_address(object)) + if (is_kfence_address(kasan_reset_tag(object))) return (void *)object; redzone_start = round_up((unsigned long)(object + size),