From: Andrey Konovalov Date: Thu, 21 Feb 2019 06:19:28 +0000 (-0800) Subject: kasan, slub: fix conflicts with CONFIG_SLAB_FREELIST_HARDENED X-Git-Tag: v5.0-rc8~16^2~16 X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=18e506610238eda2b0c5a19a123d3d6ec0ab2de6;p=linux-block.git kasan, slub: fix conflicts with CONFIG_SLAB_FREELIST_HARDENED CONFIG_SLAB_FREELIST_HARDENED hashes freelist pointer with the address of the object where the pointer gets stored. With tag based KASAN we don't account for that when building freelist, as we call set_freepointer() with the first argument untagged. This patch changes the code to properly propagate tags throughout the loop. Link: http://lkml.kernel.org/r/3df171559c52201376f246bf7ce3184fe21c1dc7.1549921721.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov Reported-by: Qian Cai Cc: Andrey Ryabinin Cc: Alexander Potapenko Cc: Dmitry Vyukov Cc: Catalin Marinas Cc: Christoph Lameter Cc: Pekka Enberg Cc: David Rientjes Cc: Joonsoo Kim Cc: Vincenzo Frascino Cc: Kostya Serebryany Cc: Evgeniy Stepanov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- diff --git a/mm/slub.c b/mm/slub.c index a7e7c7f719f9..80da3a40b74d 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -303,11 +303,6 @@ static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp) __p < (__addr) + (__objects) * (__s)->size; \ __p += (__s)->size) -#define for_each_object_idx(__p, __idx, __s, __addr, __objects) \ - for (__p = fixup_red_left(__s, __addr), __idx = 1; \ - __idx <= __objects; \ - __p += (__s)->size, __idx++) - /* Determine object index from a given position */ static inline unsigned int slab_index(void *p, struct kmem_cache *s, void *addr) { @@ -1664,17 +1659,16 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) shuffle = shuffle_freelist(s, page); if (!shuffle) { - for_each_object_idx(p, idx, s, start, page->objects) { - if (likely(idx < page->objects)) { - next = p + s->size; - next = setup_object(s, page, next); - set_freepointer(s, p, next); - } else - set_freepointer(s, p, NULL); - } start = fixup_red_left(s, start); start = setup_object(s, page, start); page->freelist = start; + for (idx = 0, p = start; idx < page->objects - 1; idx++) { + next = p + s->size; + next = setup_object(s, page, next); + set_freepointer(s, p, next); + p = next; + } + set_freepointer(s, p, NULL); } page->inuse = page->objects;