aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/kasan/common.c63
1 files changed, 43 insertions, 20 deletions
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 44390392d4c9..73c9cbfdedf4 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -347,28 +347,43 @@ void kasan_poison_object_data(struct kmem_cache *cache, void *object)
347} 347}
348 348
349/* 349/*
350 * Since it's desirable to only call object contructors once during slab 350 * This function assigns a tag to an object considering the following:
351 * allocation, we preassign tags to all such objects. Also preassign tags for 351 * 1. A cache might have a constructor, which might save a pointer to a slab
352 * SLAB_TYPESAFE_BY_RCU slabs to avoid use-after-free reports. 352 * object somewhere (e.g. in the object itself). We preassign a tag for
353 * For SLAB allocator we can't preassign tags randomly since the freelist is 353 * each object in caches with constructors during slab creation and reuse
354 * stored as an array of indexes instead of a linked list. Assign tags based 354 * the same tag each time a particular object is allocated.
355 * on objects indexes, so that objects that are next to each other get 355 * 2. A cache might be SLAB_TYPESAFE_BY_RCU, which means objects can be
356 * different tags. 356 * accessed after being freed. We preassign tags for objects in these
357 * After a tag is assigned, the object always gets allocated with the same tag. 357 * caches as well.
358 * The reason is that we can't change tags for objects with constructors on 358 * 3. For SLAB allocator we can't preassign tags randomly since the freelist
359 * reallocation (even for non-SLAB_TYPESAFE_BY_RCU), because the constructor 359 * is stored as an array of indexes instead of a linked list. Assign tags
360 * code can save the pointer to the object somewhere (e.g. in the object 360 * based on objects indexes, so that objects that are next to each other
361 * itself). Then if we retag it, the old saved pointer will become invalid. 361 * get different tags.
362 */ 362 */
363static u8 assign_tag(struct kmem_cache *cache, const void *object, bool new) 363static u8 assign_tag(struct kmem_cache *cache, const void *object,
364 bool init, bool krealloc)
364{ 365{
366 /* Reuse the same tag for krealloc'ed objects. */
367 if (krealloc)
368 return get_tag(object);
369
370 /*
371 * If the cache neither has a constructor nor has SLAB_TYPESAFE_BY_RCU
372 * set, assign a tag when the object is being allocated (init == false).
373 */
365 if (!cache->ctor && !(cache->flags & SLAB_TYPESAFE_BY_RCU)) 374 if (!cache->ctor && !(cache->flags & SLAB_TYPESAFE_BY_RCU))
366 return new ? KASAN_TAG_KERNEL : random_tag(); 375 return init ? KASAN_TAG_KERNEL : random_tag();
367 376
377 /* For caches that either have a constructor or SLAB_TYPESAFE_BY_RCU: */
368#ifdef CONFIG_SLAB 378#ifdef CONFIG_SLAB
379 /* For SLAB assign tags based on the object index in the freelist. */
369 return (u8)obj_to_index(cache, virt_to_page(object), (void *)object); 380 return (u8)obj_to_index(cache, virt_to_page(object), (void *)object);
370#else 381#else
371 return new ? random_tag() : get_tag(object); 382 /*
383 * For SLUB assign a random tag during slab creation, otherwise reuse
384 * the already assigned tag.
385 */
386 return init ? random_tag() : get_tag(object);
372#endif 387#endif
373} 388}
374 389
@@ -384,7 +399,8 @@ void * __must_check kasan_init_slab_obj(struct kmem_cache *cache,
384 __memset(alloc_info, 0, sizeof(*alloc_info)); 399 __memset(alloc_info, 0, sizeof(*alloc_info));
385 400
386 if (IS_ENABLED(CONFIG_KASAN_SW_TAGS)) 401 if (IS_ENABLED(CONFIG_KASAN_SW_TAGS))
387 object = set_tag(object, assign_tag(cache, object, true)); 402 object = set_tag(object,
403 assign_tag(cache, object, true, false));
388 404
389 return (void *)object; 405 return (void *)object;
390} 406}
@@ -450,8 +466,8 @@ bool kasan_slab_free(struct kmem_cache *cache, void *object, unsigned long ip)
450 return __kasan_slab_free(cache, object, ip, true); 466 return __kasan_slab_free(cache, object, ip, true);
451} 467}
452 468
453void * __must_check kasan_kmalloc(struct kmem_cache *cache, const void *object, 469static void *__kasan_kmalloc(struct kmem_cache *cache, const void *object,
454 size_t size, gfp_t flags) 470 size_t size, gfp_t flags, bool krealloc)
455{ 471{
456 unsigned long redzone_start; 472 unsigned long redzone_start;
457 unsigned long redzone_end; 473 unsigned long redzone_end;
@@ -469,7 +485,7 @@ void * __must_check kasan_kmalloc(struct kmem_cache *cache, const void *object,
469 KASAN_SHADOW_SCALE_SIZE); 485 KASAN_SHADOW_SCALE_SIZE);
470 486
471 if (IS_ENABLED(CONFIG_KASAN_SW_TAGS)) 487 if (IS_ENABLED(CONFIG_KASAN_SW_TAGS))
472 tag = assign_tag(cache, object, false); 488 tag = assign_tag(cache, object, false, krealloc);
473 489
474 /* Tag is ignored in set_tag without CONFIG_KASAN_SW_TAGS */ 490 /* Tag is ignored in set_tag without CONFIG_KASAN_SW_TAGS */
475 kasan_unpoison_shadow(set_tag(object, tag), size); 491 kasan_unpoison_shadow(set_tag(object, tag), size);
@@ -481,6 +497,12 @@ void * __must_check kasan_kmalloc(struct kmem_cache *cache, const void *object,
481 497
482 return set_tag(object, tag); 498 return set_tag(object, tag);
483} 499}
500
501void * __must_check kasan_kmalloc(struct kmem_cache *cache, const void *object,
502 size_t size, gfp_t flags)
503{
504 return __kasan_kmalloc(cache, object, size, flags, false);
505}
484EXPORT_SYMBOL(kasan_kmalloc); 506EXPORT_SYMBOL(kasan_kmalloc);
485 507
486void * __must_check kasan_kmalloc_large(const void *ptr, size_t size, 508void * __must_check kasan_kmalloc_large(const void *ptr, size_t size,
@@ -520,7 +542,8 @@ void * __must_check kasan_krealloc(const void *object, size_t size, gfp_t flags)
520 if (unlikely(!PageSlab(page))) 542 if (unlikely(!PageSlab(page)))
521 return kasan_kmalloc_large(object, size, flags); 543 return kasan_kmalloc_large(object, size, flags);
522 else 544 else
523 return kasan_kmalloc(page->slab_cache, object, size, flags); 545 return __kasan_kmalloc(page->slab_cache, object, size,
546 flags, true);
524} 547}
525 548
526void kasan_poison_kfree(void *ptr, unsigned long ip) 549void kasan_poison_kfree(void *ptr, unsigned long ip)