kasan, slab: make freelist stored without tags [Linux 5.0]

This Linux kernel change "kasan, slab: make freelist stored without tags" is included in the Linux 5.0 release. This change is authored by Andrey Konovalov <andreyknvl [at] google.com> on Wed Feb 20 22:20:28 2019 -0800. The commit for this change in Linux stable tree is 51dedad (patch).

kasan, slab: make freelist stored without tags

Similarly to "kasan, slub: move kasan_poison_slab hook before
page_address", move kasan_poison_slab() before alloc_slabmgmt(), which
calls page_address(), to make page_address() return value to be
non-tagged.  This, combined with calling kasan_reset_tag() for off-slab
slab management object, leads to freelist being stored non-tagged.

Link: http://lkml.kernel.org/r/dfb[email protected]google.com
Signed-off-by: Andrey Konovalov <[email protected]>
Tested-by: Qian Cai <[email protected]>
Cc: Alexander Potapenko <[email protected]>
Cc: Andrey Ryabinin <[email protected]>
Cc: Catalin Marinas <[email protected]>
Cc: Dmitry Vyukov <[email protected]>
Cc: Evgeniy Stepanov <[email protected]>
Cc: Kostya Serebryany <[email protected]>
Cc: Vincenzo Frascino <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>

There are 11 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 mm/slab.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/mm/slab.c b/mm/slab.c
index c844582..4ad95fc 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -2359,7 +2359,7 @@ static void *alloc_slabmgmt(struct kmem_cache *cachep,
    void *freelist;
    void *addr = page_address(page);

-   page->s_mem = kasan_reset_tag(addr) + colour_off;
+   page->s_mem = addr + colour_off;
    page->active = 0;

    if (OBJFREELIST_SLAB(cachep))
@@ -2368,6 +2368,7 @@ static void *alloc_slabmgmt(struct kmem_cache *cachep,
        /* Slab management obj is off-slab. */
        freelist = kmem_cache_alloc_node(cachep->freelist_cache,
                          local_flags, nodeid);
+       freelist = kasan_reset_tag(freelist);
        if (!freelist)
            return NULL;
    } else {
@@ -2681,6 +2682,13 @@ static struct page *cache_grow_begin(struct kmem_cache *cachep,

    offset *= cachep->colour_off;

+   /*
+    * Call kasan_poison_slab() before calling alloc_slabmgmt(), so
+    * page_address() in the latter returns a non-tagged pointer,
+    * as it should be for slab pages.
+    */
+   kasan_poison_slab(page);
+
    /* Get slab management. */
    freelist = alloc_slabmgmt(cachep, page, offset,
            local_flags & ~GFP_CONSTRAINT_MASK, page_node);
@@ -2689,7 +2697,6 @@ static struct page *cache_grow_begin(struct kmem_cache *cachep,

    slab_map_pages(cachep, page, freelist);

-   kasan_poison_slab(page);
    cache_init_objs(cachep, page);

    if (gfpflags_allow_blocking(local_flags))

Leave a Reply

Your email address will not be published. Required fields are marked *