}
 
 void * __must_check __kasan_slab_alloc(struct kmem_cache *s,
-                                      void *object, gfp_t flags);
+                                      void *object, gfp_t flags, bool init);
 static __always_inline void * __must_check kasan_slab_alloc(
-                               struct kmem_cache *s, void *object, gfp_t flags)
+               struct kmem_cache *s, void *object, gfp_t flags, bool init)
 {
        if (kasan_enabled())
-               return __kasan_slab_alloc(s, object, flags);
+               return __kasan_slab_alloc(s, object, flags, init);
        return object;
 }
 
 static inline void kasan_kfree_large(void *ptr) {}
 static inline void kasan_slab_free_mempool(void *ptr) {}
 static inline void *kasan_slab_alloc(struct kmem_cache *s, void *object,
-                                  gfp_t flags)
+                                  gfp_t flags, bool init)
 {
        return object;
 }
 
 }
 
 void * __must_check __kasan_slab_alloc(struct kmem_cache *cache,
-                                       void *object, gfp_t flags)
+                                       void *object, gfp_t flags, bool init)
 {
        u8 tag;
        void *tagged_object;
         * Unpoison the whole object.
         * For kmalloc() allocations, kasan_kmalloc() will do precise poisoning.
         */
-       kasan_unpoison(tagged_object, cache->object_size, false);
+       kasan_unpoison(tagged_object, cache->object_size, init);
 
        /* Save alloc info (if possible) for non-kmalloc() allocations. */
        if (kasan_stack_collection_enabled())
 
        void *ptr;
        int slab_node = numa_mem_id();
        struct obj_cgroup *objcg = NULL;
+       bool init = false;
 
        flags &= gfp_allowed_mask;
        cachep = slab_pre_alloc_hook(cachep, &objcg, 1, flags);
   out:
        local_irq_restore(save_flags);
        ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller);
-
-       if (unlikely(slab_want_init_on_alloc(flags, cachep)) && ptr)
-               memset(ptr, 0, cachep->object_size);
+       init = slab_want_init_on_alloc(flags, cachep);
 
 out_hooks:
-       slab_post_alloc_hook(cachep, objcg, flags, 1, &ptr);
+       slab_post_alloc_hook(cachep, objcg, flags, 1, &ptr, init);
        return ptr;
 }
 
        unsigned long save_flags;
        void *objp;
        struct obj_cgroup *objcg = NULL;
+       bool init = false;
 
        flags &= gfp_allowed_mask;
        cachep = slab_pre_alloc_hook(cachep, &objcg, 1, flags);
        local_irq_restore(save_flags);
        objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller);
        prefetchw(objp);
-
-       if (unlikely(slab_want_init_on_alloc(flags, cachep)) && objp)
-               memset(objp, 0, cachep->object_size);
+       init = slab_want_init_on_alloc(flags, cachep);
 
 out:
-       slab_post_alloc_hook(cachep, objcg, flags, 1, &objp);
+       slab_post_alloc_hook(cachep, objcg, flags, 1, &objp, init);
        return objp;
 }
 
 
        cache_alloc_debugcheck_after_bulk(s, flags, size, p, _RET_IP_);
 
-       /* Clear memory outside IRQ disabled section */
-       if (unlikely(slab_want_init_on_alloc(flags, s)))
-               for (i = 0; i < size; i++)
-                       memset(p[i], 0, s->object_size);
-
-       slab_post_alloc_hook(s, objcg, flags, size, p);
+       /*
+        * memcg and kmem_cache debug support and memory initialization.
+        * Done outside of the IRQ disabled section.
+        */
+       slab_post_alloc_hook(s, objcg, flags, size, p,
+                               slab_want_init_on_alloc(flags, s));
        /* FIXME: Trace call missing. Christoph would like a bulk variant */
        return size;
 error:
        local_irq_enable();
        cache_alloc_debugcheck_after_bulk(s, flags, i, p, _RET_IP_);
-       slab_post_alloc_hook(s, objcg, flags, i, p);
+       slab_post_alloc_hook(s, objcg, flags, i, p, false);
        __kmem_cache_free_bulk(s, i, p);
        return 0;
 }
 
 }
 
 static inline void slab_post_alloc_hook(struct kmem_cache *s,
-                                       struct obj_cgroup *objcg,
-                                       gfp_t flags, size_t size, void **p)
+                                       struct obj_cgroup *objcg, gfp_t flags,
+                                       size_t size, void **p, bool init)
 {
        size_t i;
 
        flags &= gfp_allowed_mask;
+
+       /*
+        * As memory initialization might be integrated into KASAN,
+        * kasan_slab_alloc and initialization memset must be
+        * kept together to avoid discrepancies in behavior.
+        *
+        * As p[i] might get tagged, memset and kmemleak hook come after KASAN.
+        */
        for (i = 0; i < size; i++) {
-               p[i] = kasan_slab_alloc(s, p[i], flags);
-               /* As p[i] might get tagged, call kmemleak hook after KASAN. */
+               p[i] = kasan_slab_alloc(s, p[i], flags, init);
+               if (p[i] && init && !kasan_has_integrated_init())
+                       memset(p[i], 0, s->object_size);
                kmemleak_alloc_recursive(p[i], s->object_size, 1,
                                         s->flags, flags);
        }
 
        struct page *page;
        unsigned long tid;
        struct obj_cgroup *objcg = NULL;
+       bool init = false;
 
        s = slab_pre_alloc_hook(s, &objcg, 1, gfpflags);
        if (!s)
        }
 
        maybe_wipe_obj_freeptr(s, object);
-
-       if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object)
-               memset(kasan_reset_tag(object), 0, s->object_size);
+       init = slab_want_init_on_alloc(gfpflags, s);
 
 out:
-       slab_post_alloc_hook(s, objcg, gfpflags, 1, &object);
+       slab_post_alloc_hook(s, objcg, gfpflags, 1, &object, init);
 
        return object;
 }
        c->tid = next_tid(c->tid);
        local_irq_enable();
 
-       /* Clear memory outside IRQ disabled fastpath loop */
-       if (unlikely(slab_want_init_on_alloc(flags, s))) {
-               int j;
-
-               for (j = 0; j < i; j++)
-                       memset(kasan_reset_tag(p[j]), 0, s->object_size);
-       }
-
-       /* memcg and kmem_cache debug support */
-       slab_post_alloc_hook(s, objcg, flags, size, p);
+       /*
+        * memcg and kmem_cache debug support and memory initialization.
+        * Done outside of the IRQ disabled fastpath loop.
+        */
+       slab_post_alloc_hook(s, objcg, flags, size, p,
+                               slab_want_init_on_alloc(flags, s));
        return i;
 error:
        local_irq_enable();
-       slab_post_alloc_hook(s, objcg, flags, i, p);
+       slab_post_alloc_hook(s, objcg, flags, i, p, false);
        __kmem_cache_free_bulk(s, i, p);
        return 0;
 }
        init_object(kmem_cache_node, n, SLUB_RED_ACTIVE);
        init_tracking(kmem_cache_node, n);
 #endif
-       n = kasan_slab_alloc(kmem_cache_node, n, GFP_KERNEL);
+       n = kasan_slab_alloc(kmem_cache_node, n, GFP_KERNEL, false);
        page->freelist = get_freepointer(kmem_cache_node, n);
        page->inuse = 1;
        page->frozen = 0;