From: Andrey Ryabinin <ryabinin.a.a@gmail.com>
To: Alexander Potapenko <glider@google.com>,
adech.fo@gmail.com, cl@linux.com, dvyukov@google.com,
akpm@linux-foundation.org, rostedt@goodmis.org,
iamjoonsoo.kim@lge.com, js1304@gmail.com, kcc@google.com
Cc: kasan-dev@googlegroups.com, linux-kernel@vger.kernel.org,
linux-mm@kvack.org
Subject: Re: [PATCH v4 2/7] mm, kasan: SLAB support
Date: Mon, 29 Feb 2016 18:10:31 +0300 [thread overview]
Message-ID: <56D45F67.8050508@gmail.com> (raw)
In-Reply-To: <5c5a22a3daee19ff5940605b946dc144515ebd63.1456504662.git.glider@google.com>
On 02/26/2016 07:48 PM, Alexander Potapenko wrote:
> Add KASAN hooks to SLAB allocator.
>
> This patch is based on the "mm: kasan: unified support for SLUB and
> SLAB allocators" patch originally prepared by Dmitry Chernenkov.
>
> Signed-off-by: Alexander Potapenko <glider@google.com>
> ---
> v3: - minor description changes
> - store deallocation info in kasan_slab_free()
>
> v4: - fix kbuild compile-time warnings in print_track()
> ---
> diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
> index bc0a8d8..d26ffb4 100644
> --- a/mm/kasan/kasan.c
> +++ b/mm/kasan/kasan.c
> @@ -314,6 +314,59 @@ void kasan_free_pages(struct page *page, unsigned int order)
> KASAN_FREE_PAGE);
> }
>
> +#ifdef CONFIG_SLAB
> +/*
> + * Adaptive redzone policy taken from the userspace AddressSanitizer runtime.
> + * For larger allocations larger redzones are used.
> + */
> +static size_t optimal_redzone(size_t object_size)
> +{
> + int rz =
> + object_size <= 64 - 16 ? 16 :
> + object_size <= 128 - 32 ? 32 :
> + object_size <= 512 - 64 ? 64 :
> + object_size <= 4096 - 128 ? 128 :
> + object_size <= (1 << 14) - 256 ? 256 :
> + object_size <= (1 << 15) - 512 ? 512 :
> + object_size <= (1 << 16) - 1024 ? 1024 : 2048;
> + return rz;
> +}
> +
> +void kasan_cache_create(struct kmem_cache *cache, size_t *size,
> + unsigned long *flags)
> +{
> + int redzone_adjust;
> + /* Make sure the adjusted size is still less than
> + * KMALLOC_MAX_CACHE_SIZE.
> + * TODO: this check is only useful for SLAB, but not SLUB. We'll need
> + * to skip it for SLUB when it starts using kasan_cache_create().
> + */
> + if (*size > KMALLOC_MAX_CACHE_SIZE -
> + sizeof(struct kasan_alloc_meta) -
> + sizeof(struct kasan_free_meta))
> + return;
> + *flags |= SLAB_KASAN;
> + /* Add alloc meta. */
> + cache->kasan_info.alloc_meta_offset = *size;
> + *size += sizeof(struct kasan_alloc_meta);
> +
> + /* Add free meta. */
> + if (cache->flags & SLAB_DESTROY_BY_RCU || cache->ctor ||
> + cache->object_size < sizeof(struct kasan_free_meta)) {
> + cache->kasan_info.free_meta_offset = *size;
> + *size += sizeof(struct kasan_free_meta);
> + }
> + redzone_adjust = optimal_redzone(cache->object_size) -
> + (*size - cache->object_size);
> + if (redzone_adjust > 0)
> + *size += redzone_adjust;
> + *size = min(KMALLOC_MAX_CACHE_SIZE,
> + max(*size,
> + cache->object_size +
> + optimal_redzone(cache->object_size)));
> +}
> +#endif
> +
> void kasan_poison_slab(struct page *page)
> {
> kasan_poison_shadow(page_address(page),
> @@ -331,8 +384,36 @@ void kasan_poison_object_data(struct kmem_cache *cache, void *object)
> kasan_poison_shadow(object,
> round_up(cache->object_size, KASAN_SHADOW_SCALE_SIZE),
> KASAN_KMALLOC_REDZONE);
> +#ifdef CONFIG_SLAB
> + if (cache->flags & SLAB_KASAN) {
> + struct kasan_alloc_meta *alloc_info =
> + get_alloc_info(cache, object);
> + alloc_info->state = KASAN_STATE_INIT;
> + }
> +#endif
> +}
> +
> +static inline void set_track(struct kasan_track *track)
> +{
> + track->cpu = raw_smp_processor_id();
> + track->pid = current->pid;
> + track->when = jiffies;
> }
>
> +#ifdef CONFIG_SLAB
> +struct kasan_alloc_meta *get_alloc_info(struct kmem_cache *cache,
> + const void *object)
> +{
> + return (void *)object + cache->kasan_info.alloc_meta_offset;
> +}
> +
> +struct kasan_free_meta *get_free_info(struct kmem_cache *cache,
> + const void *object)
> +{
> + return (void *)object + cache->kasan_info.free_meta_offset;
> +}
> +#endif
> +
> void kasan_slab_alloc(struct kmem_cache *cache, void *object)
> {
> kasan_kmalloc(cache, object, cache->object_size);
> @@ -347,6 +428,17 @@ void kasan_slab_free(struct kmem_cache *cache, void *object)
> if (unlikely(cache->flags & SLAB_DESTROY_BY_RCU))
> return;
>
> +#ifdef CONFIG_SLAB
> + if (cache->flags & SLAB_KASAN) {
> + struct kasan_free_meta *free_info =
> + get_free_info(cache, object);
> + struct kasan_alloc_meta *alloc_info =
> + get_alloc_info(cache, object);
> + alloc_info->state = KASAN_STATE_FREE;
> + set_track(&free_info->track);
> + }
> +#endif
> +
> kasan_poison_shadow(object, rounded_up_size, KASAN_KMALLOC_FREE);
> }
>
> @@ -366,6 +458,16 @@ void kasan_kmalloc(struct kmem_cache *cache, const void *object, size_t size)
> kasan_unpoison_shadow(object, size);
> kasan_poison_shadow((void *)redzone_start, redzone_end - redzone_start,
> KASAN_KMALLOC_REDZONE);
> +#ifdef CONFIG_SLAB
> + if (cache->flags & SLAB_KASAN) {
> + struct kasan_alloc_meta *alloc_info =
> + get_alloc_info(cache, object);
> +
> + alloc_info->state = KASAN_STATE_ALLOC;
> + alloc_info->alloc_size = size;
> + set_track(&alloc_info->track);
> + }
> +#endif
> }
> EXPORT_SYMBOL(kasan_kmalloc);
>
> diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
> index 4f6c62e..7b9e4ab9 100644
> --- a/mm/kasan/kasan.h
> +++ b/mm/kasan/kasan.h
> @@ -54,6 +54,40 @@ struct kasan_global {
> #endif
> };
>
> +/**
> + * Structures to keep alloc and free tracks *
> + */
> +
> +enum kasan_state {
> + KASAN_STATE_INIT,
> + KASAN_STATE_ALLOC,
> + KASAN_STATE_FREE
> +};
> +
> +struct kasan_track {
> + u64 cpu : 6; /* for NR_CPUS = 64 */
> + u64 pid : 16; /* 65536 processes */
> + u64 when : 42; /* ~140 years */
> +};
> +
> +struct kasan_alloc_meta {
> + u32 state : 2; /* enum kasan_state */
> + u32 alloc_size : 30;
> + struct kasan_track track;
> +};
> +
> +struct kasan_free_meta {
> + /* Allocator freelist pointer, unused by KASAN. */
> + void **freelist;
> + struct kasan_track track;
> +};
> +
> +struct kasan_alloc_meta *get_alloc_info(struct kmem_cache *cache,
> + const void *object);
> +struct kasan_free_meta *get_free_info(struct kmem_cache *cache,
> + const void *object);
> +
> +
Basically, all this big pile of code above is implementation of yet another SLAB_STORE_USER and SLAB_RED_ZONE
exclusively for KASAN. It would be so much better to alter existing code to satisfy all you needs.
> static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
> {
> return (void *)(((unsigned long)shadow_addr - KASAN_SHADOW_OFFSET)
> diff --git a/mm/kasan/report.c b/mm/kasan/report.c
> index 12f222d..2c1407f 100644
> --- a/mm/kasan/report.c
> +++ b/mm/kasan/report.c
> @@ -115,6 +115,44 @@ static inline bool init_task_stack_addr(const void *addr)
> sizeof(init_thread_union.stack));
> }
>
> +#ifdef CONFIG_SLAB
> +static void print_track(struct kasan_track *track)
> +{
> + pr_err("PID = %u, CPU = %u, timestamp = %lu\n", track->pid,
> + track->cpu, (unsigned long)track->when);
> +}
> +
> +static void print_object(struct kmem_cache *cache, void *object)
> +{
> + struct kasan_alloc_meta *alloc_info = get_alloc_info(cache, object);
> + struct kasan_free_meta *free_info;
> +
> + pr_err("Object at %p, in cache %s\n", object, cache->name);
> + if (!(cache->flags & SLAB_KASAN))
> + return;
> + switch (alloc_info->state) {
'->state' seems useless. It's used only here, but object's state could be determined by shadow value.
> + case KASAN_STATE_INIT:
> + pr_err("Object not allocated yet\n");
> + break;
> + case KASAN_STATE_ALLOC:
> + pr_err("Object allocated with size %u bytes.\n",
> + alloc_info->alloc_size);
> + pr_err("Allocation:\n");
> + print_track(&alloc_info->track);
> + break;
> + case KASAN_STATE_FREE:
> + pr_err("Object freed, allocated with size %u bytes\n",
> + alloc_info->alloc_size);
> + free_info = get_free_info(cache, object);
> + pr_err("Allocation:\n");
> + print_track(&alloc_info->track);
> + pr_err("Deallocation:\n");
> + print_track(&free_info->track);
> + break;
> + }
> +}
> +#endif
> +
> static void print_address_description(struct kasan_access_info *info)
> {
> const void *addr = info->access_addr;
> @@ -126,17 +164,14 @@ static void print_address_description(struct kasan_access_info *info)
> if (PageSlab(page)) {
> void *object;
> struct kmem_cache *cache = page->slab_cache;
> - void *last_object;
> -
> - object = virt_to_obj(cache, page_address(page), addr);
> - last_object = page_address(page) +
> - page->objects * cache->size;
> -
> - if (unlikely(object > last_object))
> - object = last_object; /* we hit into padding */
> -
> + object = nearest_obj(cache, page,
> + (void *)info->access_addr);
> +#ifdef CONFIG_SLAB
> + print_object(cache, object);
> +#else
Instead of these ifdefs, please, make universal API for printing object's information.
> object_err(cache, page, object,
> - "kasan: bad access detected");
> + "kasan: bad access detected");
> +#endif
> return;
> }
> dump_page(page, "kasan: bad access detected");
> @@ -146,8 +181,9 @@ static void print_address_description(struct kasan_access_info *info)
> if (!init_task_stack_addr(addr))
> pr_err("Address belongs to variable %pS\n", addr);
> }
> -
> +#ifdef CONFIG_SLUB
???
> dump_stack();
> +#endif
> }
>
> static bool row_is_guilty(const void *row, const void *guilty)
> @@ -233,6 +269,9 @@ static void kasan_report_error(struct kasan_access_info *info)
> dump_stack();
> } else {
> print_error_description(info);
> +#ifdef CONFIG_SLAB
I'm lost here. What's the point of reordering dump_stack() for CONFIG_SLAB=y?
> + dump_stack();
> +#endif
> print_address_description(info);
> print_shadow_for_address(info->first_bad_addr);
> }
> diff --git a/mm/slab.c b/mm/slab.c
> index 621fbcb..805b39b 100644
>
> if (gfpflags_allow_blocking(local_flags))
> @@ -3364,7 +3374,10 @@ free_done:
> static inline void __cache_free(struct kmem_cache *cachep, void *objp,
> unsigned long caller)
> {
> - struct array_cache *ac = cpu_cache_get(cachep);
> + struct array_cache *ac;
> +
> + kasan_slab_free(cachep, objp);
> + ac = cpu_cache_get(cachep);
Why cpu_cache_get() was moved? Looks like unnecessary change.
>
> check_irq_off();
> kmemleak_free_recursive(objp, cachep->flags);
> @@ -3403,6 +3416,8 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp,
> void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
> {
> void *ret = slab_alloc(cachep, flags, _RET_IP_);
> + if (ret)
kasan_slab_alloc() should deal fine with ret == NULL.
> + kasan_slab_alloc(cachep, ret);
>
> trace_kmem_cache_alloc(_RET_IP_, ret,
> cachep->object_size, cachep->size, flags);
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
WARNING: multiple messages have this Message-ID (diff)
From: Andrey Ryabinin <ryabinin.a.a@gmail.com>
To: Alexander Potapenko <glider@google.com>,
adech.fo@gmail.com, cl@linux.com, dvyukov@google.com,
akpm@linux-foundation.org, rostedt@goodmis.org,
iamjoonsoo.kim@lge.com, js1304@gmail.com, kcc@google.com
Cc: kasan-dev@googlegroups.com, linux-kernel@vger.kernel.org,
linux-mm@kvack.org
Subject: Re: [PATCH v4 2/7] mm, kasan: SLAB support
Date: Mon, 29 Feb 2016 18:10:31 +0300 [thread overview]
Message-ID: <56D45F67.8050508@gmail.com> (raw)
In-Reply-To: <5c5a22a3daee19ff5940605b946dc144515ebd63.1456504662.git.glider@google.com>
On 02/26/2016 07:48 PM, Alexander Potapenko wrote:
> Add KASAN hooks to SLAB allocator.
>
> This patch is based on the "mm: kasan: unified support for SLUB and
> SLAB allocators" patch originally prepared by Dmitry Chernenkov.
>
> Signed-off-by: Alexander Potapenko <glider@google.com>
> ---
> v3: - minor description changes
> - store deallocation info in kasan_slab_free()
>
> v4: - fix kbuild compile-time warnings in print_track()
> ---
> diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
> index bc0a8d8..d26ffb4 100644
> --- a/mm/kasan/kasan.c
> +++ b/mm/kasan/kasan.c
> @@ -314,6 +314,59 @@ void kasan_free_pages(struct page *page, unsigned int order)
> KASAN_FREE_PAGE);
> }
>
> +#ifdef CONFIG_SLAB
> +/*
> + * Adaptive redzone policy taken from the userspace AddressSanitizer runtime.
> + * For larger allocations larger redzones are used.
> + */
> +static size_t optimal_redzone(size_t object_size)
> +{
> + int rz =
> + object_size <= 64 - 16 ? 16 :
> + object_size <= 128 - 32 ? 32 :
> + object_size <= 512 - 64 ? 64 :
> + object_size <= 4096 - 128 ? 128 :
> + object_size <= (1 << 14) - 256 ? 256 :
> + object_size <= (1 << 15) - 512 ? 512 :
> + object_size <= (1 << 16) - 1024 ? 1024 : 2048;
> + return rz;
> +}
> +
> +void kasan_cache_create(struct kmem_cache *cache, size_t *size,
> + unsigned long *flags)
> +{
> + int redzone_adjust;
> + /* Make sure the adjusted size is still less than
> + * KMALLOC_MAX_CACHE_SIZE.
> + * TODO: this check is only useful for SLAB, but not SLUB. We'll need
> + * to skip it for SLUB when it starts using kasan_cache_create().
> + */
> + if (*size > KMALLOC_MAX_CACHE_SIZE -
> + sizeof(struct kasan_alloc_meta) -
> + sizeof(struct kasan_free_meta))
> + return;
> + *flags |= SLAB_KASAN;
> + /* Add alloc meta. */
> + cache->kasan_info.alloc_meta_offset = *size;
> + *size += sizeof(struct kasan_alloc_meta);
> +
> + /* Add free meta. */
> + if (cache->flags & SLAB_DESTROY_BY_RCU || cache->ctor ||
> + cache->object_size < sizeof(struct kasan_free_meta)) {
> + cache->kasan_info.free_meta_offset = *size;
> + *size += sizeof(struct kasan_free_meta);
> + }
> + redzone_adjust = optimal_redzone(cache->object_size) -
> + (*size - cache->object_size);
> + if (redzone_adjust > 0)
> + *size += redzone_adjust;
> + *size = min(KMALLOC_MAX_CACHE_SIZE,
> + max(*size,
> + cache->object_size +
> + optimal_redzone(cache->object_size)));
> +}
> +#endif
> +
> void kasan_poison_slab(struct page *page)
> {
> kasan_poison_shadow(page_address(page),
> @@ -331,8 +384,36 @@ void kasan_poison_object_data(struct kmem_cache *cache, void *object)
> kasan_poison_shadow(object,
> round_up(cache->object_size, KASAN_SHADOW_SCALE_SIZE),
> KASAN_KMALLOC_REDZONE);
> +#ifdef CONFIG_SLAB
> + if (cache->flags & SLAB_KASAN) {
> + struct kasan_alloc_meta *alloc_info =
> + get_alloc_info(cache, object);
> + alloc_info->state = KASAN_STATE_INIT;
> + }
> +#endif
> +}
> +
> +static inline void set_track(struct kasan_track *track)
> +{
> + track->cpu = raw_smp_processor_id();
> + track->pid = current->pid;
> + track->when = jiffies;
> }
>
> +#ifdef CONFIG_SLAB
> +struct kasan_alloc_meta *get_alloc_info(struct kmem_cache *cache,
> + const void *object)
> +{
> + return (void *)object + cache->kasan_info.alloc_meta_offset;
> +}
> +
> +struct kasan_free_meta *get_free_info(struct kmem_cache *cache,
> + const void *object)
> +{
> + return (void *)object + cache->kasan_info.free_meta_offset;
> +}
> +#endif
> +
> void kasan_slab_alloc(struct kmem_cache *cache, void *object)
> {
> kasan_kmalloc(cache, object, cache->object_size);
> @@ -347,6 +428,17 @@ void kasan_slab_free(struct kmem_cache *cache, void *object)
> if (unlikely(cache->flags & SLAB_DESTROY_BY_RCU))
> return;
>
> +#ifdef CONFIG_SLAB
> + if (cache->flags & SLAB_KASAN) {
> + struct kasan_free_meta *free_info =
> + get_free_info(cache, object);
> + struct kasan_alloc_meta *alloc_info =
> + get_alloc_info(cache, object);
> + alloc_info->state = KASAN_STATE_FREE;
> + set_track(&free_info->track);
> + }
> +#endif
> +
> kasan_poison_shadow(object, rounded_up_size, KASAN_KMALLOC_FREE);
> }
>
> @@ -366,6 +458,16 @@ void kasan_kmalloc(struct kmem_cache *cache, const void *object, size_t size)
> kasan_unpoison_shadow(object, size);
> kasan_poison_shadow((void *)redzone_start, redzone_end - redzone_start,
> KASAN_KMALLOC_REDZONE);
> +#ifdef CONFIG_SLAB
> + if (cache->flags & SLAB_KASAN) {
> + struct kasan_alloc_meta *alloc_info =
> + get_alloc_info(cache, object);
> +
> + alloc_info->state = KASAN_STATE_ALLOC;
> + alloc_info->alloc_size = size;
> + set_track(&alloc_info->track);
> + }
> +#endif
> }
> EXPORT_SYMBOL(kasan_kmalloc);
>
> diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
> index 4f6c62e..7b9e4ab9 100644
> --- a/mm/kasan/kasan.h
> +++ b/mm/kasan/kasan.h
> @@ -54,6 +54,40 @@ struct kasan_global {
> #endif
> };
>
> +/**
> + * Structures to keep alloc and free tracks *
> + */
> +
> +enum kasan_state {
> + KASAN_STATE_INIT,
> + KASAN_STATE_ALLOC,
> + KASAN_STATE_FREE
> +};
> +
> +struct kasan_track {
> + u64 cpu : 6; /* for NR_CPUS = 64 */
> + u64 pid : 16; /* 65536 processes */
> + u64 when : 42; /* ~140 years */
> +};
> +
> +struct kasan_alloc_meta {
> + u32 state : 2; /* enum kasan_state */
> + u32 alloc_size : 30;
> + struct kasan_track track;
> +};
> +
> +struct kasan_free_meta {
> + /* Allocator freelist pointer, unused by KASAN. */
> + void **freelist;
> + struct kasan_track track;
> +};
> +
> +struct kasan_alloc_meta *get_alloc_info(struct kmem_cache *cache,
> + const void *object);
> +struct kasan_free_meta *get_free_info(struct kmem_cache *cache,
> + const void *object);
> +
> +
Basically, all this big pile of code above is implementation of yet another SLAB_STORE_USER and SLAB_RED_ZONE
exclusively for KASAN. It would be so much better to alter existing code to satisfy all you needs.
> static inline const void *kasan_shadow_to_mem(const void *shadow_addr)
> {
> return (void *)(((unsigned long)shadow_addr - KASAN_SHADOW_OFFSET)
> diff --git a/mm/kasan/report.c b/mm/kasan/report.c
> index 12f222d..2c1407f 100644
> --- a/mm/kasan/report.c
> +++ b/mm/kasan/report.c
> @@ -115,6 +115,44 @@ static inline bool init_task_stack_addr(const void *addr)
> sizeof(init_thread_union.stack));
> }
>
> +#ifdef CONFIG_SLAB
> +static void print_track(struct kasan_track *track)
> +{
> + pr_err("PID = %u, CPU = %u, timestamp = %lu\n", track->pid,
> + track->cpu, (unsigned long)track->when);
> +}
> +
> +static void print_object(struct kmem_cache *cache, void *object)
> +{
> + struct kasan_alloc_meta *alloc_info = get_alloc_info(cache, object);
> + struct kasan_free_meta *free_info;
> +
> + pr_err("Object at %p, in cache %s\n", object, cache->name);
> + if (!(cache->flags & SLAB_KASAN))
> + return;
> + switch (alloc_info->state) {
'->state' seems useless. It's used only here, but object's state could be determined by shadow value.
> + case KASAN_STATE_INIT:
> + pr_err("Object not allocated yet\n");
> + break;
> + case KASAN_STATE_ALLOC:
> + pr_err("Object allocated with size %u bytes.\n",
> + alloc_info->alloc_size);
> + pr_err("Allocation:\n");
> + print_track(&alloc_info->track);
> + break;
> + case KASAN_STATE_FREE:
> + pr_err("Object freed, allocated with size %u bytes\n",
> + alloc_info->alloc_size);
> + free_info = get_free_info(cache, object);
> + pr_err("Allocation:\n");
> + print_track(&alloc_info->track);
> + pr_err("Deallocation:\n");
> + print_track(&free_info->track);
> + break;
> + }
> +}
> +#endif
> +
> static void print_address_description(struct kasan_access_info *info)
> {
> const void *addr = info->access_addr;
> @@ -126,17 +164,14 @@ static void print_address_description(struct kasan_access_info *info)
> if (PageSlab(page)) {
> void *object;
> struct kmem_cache *cache = page->slab_cache;
> - void *last_object;
> -
> - object = virt_to_obj(cache, page_address(page), addr);
> - last_object = page_address(page) +
> - page->objects * cache->size;
> -
> - if (unlikely(object > last_object))
> - object = last_object; /* we hit into padding */
> -
> + object = nearest_obj(cache, page,
> + (void *)info->access_addr);
> +#ifdef CONFIG_SLAB
> + print_object(cache, object);
> +#else
Instead of these ifdefs, please, make universal API for printing object's information.
> object_err(cache, page, object,
> - "kasan: bad access detected");
> + "kasan: bad access detected");
> +#endif
> return;
> }
> dump_page(page, "kasan: bad access detected");
> @@ -146,8 +181,9 @@ static void print_address_description(struct kasan_access_info *info)
> if (!init_task_stack_addr(addr))
> pr_err("Address belongs to variable %pS\n", addr);
> }
> -
> +#ifdef CONFIG_SLUB
???
> dump_stack();
> +#endif
> }
>
> static bool row_is_guilty(const void *row, const void *guilty)
> @@ -233,6 +269,9 @@ static void kasan_report_error(struct kasan_access_info *info)
> dump_stack();
> } else {
> print_error_description(info);
> +#ifdef CONFIG_SLAB
I'm lost here. What's the point of reordering dump_stack() for CONFIG_SLAB=y?
> + dump_stack();
> +#endif
> print_address_description(info);
> print_shadow_for_address(info->first_bad_addr);
> }
> diff --git a/mm/slab.c b/mm/slab.c
> index 621fbcb..805b39b 100644
>
> if (gfpflags_allow_blocking(local_flags))
> @@ -3364,7 +3374,10 @@ free_done:
> static inline void __cache_free(struct kmem_cache *cachep, void *objp,
> unsigned long caller)
> {
> - struct array_cache *ac = cpu_cache_get(cachep);
> + struct array_cache *ac;
> +
> + kasan_slab_free(cachep, objp);
> + ac = cpu_cache_get(cachep);
Why cpu_cache_get() was moved? Looks like unnecessary change.
>
> check_irq_off();
> kmemleak_free_recursive(objp, cachep->flags);
> @@ -3403,6 +3416,8 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp,
> void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
> {
> void *ret = slab_alloc(cachep, flags, _RET_IP_);
> + if (ret)
kasan_slab_alloc() should deal fine with ret == NULL.
> + kasan_slab_alloc(cachep, ret);
>
> trace_kmem_cache_alloc(_RET_IP_, ret,
> cachep->object_size, cachep->size, flags);
next prev parent reply other threads:[~2016-02-29 15:10 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-02-26 16:48 [PATCH v4 0/7] SLAB support for KASAN Alexander Potapenko
2016-02-26 16:48 ` Alexander Potapenko
2016-02-26 16:48 ` [PATCH v4 1/7] kasan: Modify kmalloc_large_oob_right(), add kmalloc_pagealloc_oob_right() Alexander Potapenko
2016-02-26 16:48 ` Alexander Potapenko
2016-02-26 16:48 ` [PATCH v4 2/7] mm, kasan: SLAB support Alexander Potapenko
2016-02-26 16:48 ` Alexander Potapenko
2016-02-29 15:10 ` Andrey Ryabinin [this message]
2016-02-29 15:10 ` Andrey Ryabinin
2016-02-29 18:28 ` Alexander Potapenko
2016-02-29 18:28 ` Alexander Potapenko
2016-02-29 18:33 ` Alexander Potapenko
2016-02-29 18:33 ` Alexander Potapenko
2016-03-01 14:34 ` Andrey Ryabinin
2016-03-01 14:34 ` Andrey Ryabinin
2016-02-26 16:48 ` [PATCH v4 3/7] mm, kasan: Added GFP flags to KASAN API Alexander Potapenko
2016-02-26 16:48 ` Alexander Potapenko
2016-02-26 16:48 ` [PATCH v4 4/7] arch, ftrace: For KASAN put hard/soft IRQ entries into separate sections Alexander Potapenko
2016-02-26 16:48 ` Alexander Potapenko
2016-02-27 1:44 ` kbuild test robot
2016-03-02 17:41 ` Steven Rostedt
2016-03-02 17:41 ` Steven Rostedt
2016-02-26 16:48 ` [PATCH v4 5/7] mm, kasan: Stackdepot implementation. Enable stackdepot for SLAB Alexander Potapenko
2016-02-26 16:48 ` Alexander Potapenko
2016-02-29 16:29 ` Andrey Ryabinin
2016-02-29 16:29 ` Andrey Ryabinin
2016-02-29 17:12 ` Dmitry Vyukov
2016-02-29 17:12 ` Dmitry Vyukov
2016-03-01 11:57 ` Andrey Ryabinin
2016-03-01 11:57 ` Andrey Ryabinin
2016-03-04 14:52 ` Alexander Potapenko
2016-03-04 14:52 ` Alexander Potapenko
2016-03-04 15:01 ` Andrey Ryabinin
2016-03-04 15:01 ` Andrey Ryabinin
2016-03-04 15:06 ` Alexander Potapenko
2016-03-04 15:06 ` Alexander Potapenko
2016-03-04 16:30 ` Andrey Ryabinin
2016-03-04 16:30 ` Andrey Ryabinin
2016-03-08 11:42 ` Alexander Potapenko
2016-03-08 11:42 ` Alexander Potapenko
2016-03-10 16:58 ` Andrey Ryabinin
2016-03-10 16:58 ` Andrey Ryabinin
2016-03-11 11:18 ` Alexander Potapenko
2016-03-11 11:18 ` Alexander Potapenko
2016-03-11 11:43 ` Andrey Ryabinin
2016-03-11 11:43 ` Andrey Ryabinin
2016-03-11 14:49 ` Alexander Potapenko
2016-03-11 14:49 ` Alexander Potapenko
2016-03-11 16:10 ` Steven Rostedt
2016-03-11 16:10 ` Steven Rostedt
2016-03-08 11:30 ` Alexander Potapenko
2016-03-08 11:30 ` Alexander Potapenko
2016-02-26 16:48 ` [PATCH v4 6/7] kasan: Test fix: Warn if the UAF could not be detected in kmalloc_uaf2 Alexander Potapenko
2016-02-26 16:48 ` Alexander Potapenko
2016-02-29 16:31 ` Andrey Ryabinin
2016-02-29 16:31 ` Andrey Ryabinin
2016-02-26 16:48 ` [PATCH v4 7/7] mm: kasan: Initial memory quarantine implementation Alexander Potapenko
2016-02-26 16:48 ` Alexander Potapenko
2016-02-26 22:28 ` [PATCH v4 0/7] SLAB support for KASAN Andrew Morton
2016-02-26 22:28 ` Andrew Morton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=56D45F67.8050508@gmail.com \
--to=ryabinin.a.a@gmail.com \
--cc=adech.fo@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=cl@linux.com \
--cc=dvyukov@google.com \
--cc=glider@google.com \
--cc=iamjoonsoo.kim@lge.com \
--cc=js1304@gmail.com \
--cc=kasan-dev@googlegroups.com \
--cc=kcc@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=rostedt@goodmis.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.