Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

kasan, mm: optimize krealloc poisoning

Currently, krealloc() always calls ksize(), which unpoisons the whole
object including the redzone. This is inefficient, as kasan_krealloc()
repoisons the redzone for objects that fit into the same buffer.

This patch changes krealloc() instrumentation to use uninstrumented
__ksize() that doesn't unpoison the memory. Instead, kasan_kreallos() is
changed to unpoison the memory excluding the redzone.

For objects that don't fit into the old allocation, this patch disables
KASAN accessibility checks when copying memory into a new object instead
of unpoisoning it.

Link: https://lkml.kernel.org/r/9bef90327c9cb109d736c40115684fd32f49e6b0.1612546384.git.andreyknvl@google.com
Signed-off-by: Andrey Konovalov <andreyknvl@google.com>
Reviewed-by: Marco Elver <elver@google.com>
Cc: Alexander Potapenko <glider@google.com>
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Branislav Rankov <Branislav.Rankov@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Evgenii Stepanov <eugenis@google.com>
Cc: Kevin Brodsky <kevin.brodsky@arm.com>
Cc: Peter Collingbourne <pcc@google.com>
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Andrey Konovalov and committed by
Linus Torvalds
d12d9ad8 26a5ca7a

+24 -8
+10 -2
mm/kasan/common.c
··· 476 476 477 477 /* 478 478 * The object has already been unpoisoned by kasan_slab_alloc() for 479 - * kmalloc() or by ksize() for krealloc(). 479 + * kmalloc() or by kasan_krealloc() for krealloc(). 480 480 */ 481 481 482 482 /* ··· 526 526 527 527 /* 528 528 * The object has already been unpoisoned by kasan_alloc_pages() for 529 - * alloc_pages() or by ksize() for krealloc(). 529 + * alloc_pages() or by kasan_krealloc() for krealloc(). 530 530 */ 531 531 532 532 /* ··· 554 554 if (unlikely(object == ZERO_SIZE_PTR)) 555 555 return (void *)object; 556 556 557 + /* 558 + * Unpoison the object's data. 559 + * Part of it might already have been unpoisoned, but it's unknown 560 + * how big that part is. 561 + */ 562 + kasan_unpoison(object, size); 563 + 557 564 page = virt_to_head_page(object); 558 565 566 + /* Piggy-back on kmalloc() instrumentation to poison the redzone. */ 559 567 if (unlikely(!PageSlab(page))) 560 568 return __kasan_kmalloc_large(object, size, flags); 561 569 else
+14 -6
mm/slab_common.c
··· 1136 1136 void *ret; 1137 1137 size_t ks; 1138 1138 1139 - if (likely(!ZERO_OR_NULL_PTR(p)) && !kasan_check_byte(p)) 1140 - return NULL; 1139 + /* Don't use instrumented ksize to allow precise KASAN poisoning. */ 1140 + if (likely(!ZERO_OR_NULL_PTR(p))) { 1141 + if (!kasan_check_byte(p)) 1142 + return NULL; 1143 + ks = kfence_ksize(p) ?: __ksize(p); 1144 + } else 1145 + ks = 0; 1141 1146 1142 - ks = ksize(p); 1143 - 1147 + /* If the object still fits, repoison it precisely. */ 1144 1148 if (ks >= new_size) { 1145 1149 p = kasan_krealloc((void *)p, new_size, flags); 1146 1150 return (void *)p; 1147 1151 } 1148 1152 1149 1153 ret = kmalloc_track_caller(new_size, flags); 1150 - if (ret && p) 1151 - memcpy(ret, p, ks); 1154 + if (ret && p) { 1155 + /* Disable KASAN checks as the object's redzone is accessed. */ 1156 + kasan_disable_current(); 1157 + memcpy(ret, kasan_reset_tag(p), ks); 1158 + kasan_enable_current(); 1159 + } 1152 1160 1153 1161 return ret; 1154 1162 }