All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Potapenko <glider@google.com>
To: Qian Cai <cai@lca.pw>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	Vegard Nossum <vegard.nossum@oracle.com>,
	 Dmitry Vyukov <dvyukov@google.com>,
	Linux Memory Management List <linux-mm@kvack.org>
Subject: Re: [PATCH RFC v1 18/26] kmsan: mm: call KMSAN hooks from SLUB code
Date: Fri, 18 Oct 2019 16:54:51 +0200	[thread overview]
Message-ID: <CAG_fn=V8MaATp_6swC3u_8kNDNiMrC5N80g1TRFGv2vvB7V6uQ@mail.gmail.com> (raw)
In-Reply-To: <1571409732.5937.76.camel@lca.pw>

On Fri, Oct 18, 2019 at 4:42 PM Qian Cai <cai@lca.pw> wrote:
>
> On Fri, 2019-10-18 at 15:55 +0200, Alexander Potapenko wrote:
> > On Fri, Oct 18, 2019 at 3:42 PM Qian Cai <cai@lca.pw> wrote:
> > >
> > > On Fri, 2019-10-18 at 15:33 +0200, Alexander Potapenko wrote:
> > > > On Fri, Oct 18, 2019 at 3:22 PM Qian Cai <cai@lca.pw> wrote:
> > > > >
> > > > > On Fri, 2019-10-18 at 11:42 +0200, glider@google.com wrote:
> > > > > > In order to report uninitialized memory coming from heap allocations
> > > > > > KMSAN has to poison them unless they're created with __GFP_ZERO.
> > > > > >
> > > > > > It's handy that we need KMSAN hooks in the places where
> > > > > > init_on_alloc/init_on_free initialization is performed.
> > > > >
> > > > > Well, there is SLUB debug which has red zoning and poisoning checks. What's
> > > > > value of this patch?
> > > >
> > > > Sorry, are you talking about the whole patchset or just this patch?
> > >
> > > Just this patch.
> > >
> > > > Note that SLUB debug is unable to detect uninitialized values with
> > > > bit-to-bit precision, neither have I heard of anyone using it for
> > > > detecting uses of uninitialized memory in the kernel at all.
> > > > The purpose of SLUB debug is to detect corruptions of freed memory.
> > >
> > > The point is if developers have SLUB debug enabled, all the free objects will be
> > > poisoned, so what's the point of checking uninitialized memory there?
> >
> > You are right, SLUB debug has to be handled separately. If I'm
> > understanding correctly, right now KMSAN poisons freed memory before
> > SLUB debug wipes it, therefore the memory will count as initialized.
> > On the other hand, newly allocated memory is still marked as
> > uninitialized, so a lot of bugs still remain detectable.
>
> Yes, but newly allocated slub objects will be poisoned as well.
As far as I can tell, KMSAN hook marking newly allocated objects as
uninitialized is called after slub poisoning.
Therefore these allocations will be treated by KMSAN as uninitialized.
> > TBH, I haven't tested KMSAN with SLUB debug good enough. Note that
> > it's anyway a separate build that requires Clang, so right now it
> > doesn't make much sense to combine KMSAN and SLUB debug together.
>
> Can't you just build a debug kernel with SLUB debug enabled but dropping this
> patch? If there is an uninitialized memory here leading to data corruption, SLUB
> debug should be detected as well as this patch. If not, it needs to understand
> why.
Sorry, there might be some misunderstanding here.
KMSAN keeps the state of heap objects separately by keeping exactly
the same amount of initialized/uninitialized bits for every
allocation.
A call to kmsan_slab_alloc()/kmsan_slab_free() will mark an allocation
as uninitialized for KMSAN. Not doing so will result in false reports.
A call to memset(object, POISON_FREE, object_size) performed by SLAB
debug will actually mark this allocation as initialized from KMSAN
point of view, because we're memsetting a range with initialized data.
Note that use of uninitialized data doesn't necessarily lead to
immediate data corruption, so there might be nothing to detect for
SLUB debug.
>
> > > > > >
> > > > > > Signed-off-by: Alexander Potapenko <glider@google.com>
> > > > > > To: Alexander Potapenko <glider@google.com>
> > > > > > Cc: Andrew Morton <akpm@linux-foundation.org>
> > > > > > Cc: Vegard Nossum <vegard.nossum@oracle.com>
> > > > > > Cc: Dmitry Vyukov <dvyukov@google.com>
> > > > > > Cc: linux-mm@kvack.org
> > > > > > ---
> > > > > >
> > > > > > Change-Id: I51103b7981d3aabed747d0c85cbdc85568665871
> > > > > > ---
> > > > > >  mm/slub.c | 37 +++++++++++++++++++++++++++++++------
> > > > > >  1 file changed, 31 insertions(+), 6 deletions(-)
> > > > > >
> > > > > > diff --git a/mm/slub.c b/mm/slub.c
> > > > > > index 3d63ae320d31..3d6d4c63446e 100644
> > > > > > --- a/mm/slub.c
> > > > > > +++ b/mm/slub.c
> > > > > > @@ -21,6 +21,8 @@
> > > > > >  #include <linux/proc_fs.h>
> > > > > >  #include <linux/seq_file.h>
> > > > > >  #include <linux/kasan.h>
> > > > > > +#include <linux/kmsan.h>
> > > > > > +#include <linux/kmsan-checks.h> /* KMSAN_INIT_VALUE */
> > > > > >  #include <linux/cpu.h>
> > > > > >  #include <linux/cpuset.h>
> > > > > >  #include <linux/mempolicy.h>
> > > > > > @@ -285,17 +287,27 @@ static void prefetch_freepointer(const struct kmem_cache *s, void *object)
> > > > > >       prefetch(object + s->offset);
> > > > > >  }
> > > > > >
> > > > > > +/*
> > > > > > + * When running under KMSAN, get_freepointer_safe() may return an uninitialized
> > > > > > + * pointer value in the case the current thread loses the race for the next
> > > > > > + * memory chunk in the freelist. In that case this_cpu_cmpxchg_double() in
> > > > > > + * slab_alloc_node() will fail, so the uninitialized value won't be used, but
> > > > > > + * KMSAN will still check all arguments of cmpxchg because of imperfect
> > > > > > + * handling of inline assembly.
> > > > > > + * To work around this problem, use KMSAN_INIT_VALUE() to force initialize the
> > > > > > + * return value of get_freepointer_safe().
> > > > > > + */
> > > > > >  static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
> > > > > >  {
> > > > > >       unsigned long freepointer_addr;
> > > > > >       void *p;
> > > > > >
> > > > > >       if (!debug_pagealloc_enabled())
> > > > > > -             return get_freepointer(s, object);
> > > > > > +             return KMSAN_INIT_VALUE(get_freepointer(s, object));
> > > > > >
> > > > > >       freepointer_addr = (unsigned long)object + s->offset;
> > > > > >       probe_kernel_read(&p, (void **)freepointer_addr, sizeof(p));
> > > > > > -     return freelist_ptr(s, p, freepointer_addr);
> > > > > > +     return KMSAN_INIT_VALUE(freelist_ptr(s, p, freepointer_addr));
> > > > > >  }
> > > > > >
> > > > > >  static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
> > > > > > @@ -1390,6 +1402,7 @@ static inline void *kmalloc_large_node_hook(void *ptr, size_t size, gfp_t flags)
> > > > > >       ptr = kasan_kmalloc_large(ptr, size, flags);
> > > > > >       /* As ptr might get tagged, call kmemleak hook after KASAN. */
> > > > > >       kmemleak_alloc(ptr, size, 1, flags);
> > > > > > +     kmsan_kmalloc_large(ptr, size, flags);
> > > > > >       return ptr;
> > > > > >  }
> > > > > >
> > > > > > @@ -1397,6 +1410,7 @@ static __always_inline void kfree_hook(void *x)
> > > > > >  {
> > > > > >       kmemleak_free(x);
> > > > > >       kasan_kfree_large(x, _RET_IP_);
> > > > > > +     kmsan_kfree_large(x);
> > > > > >  }
> > > > > >
> > > > > >  static __always_inline bool slab_free_hook(struct kmem_cache *s, void *x)
> > > > > > @@ -1453,6 +1467,12 @@ static inline bool slab_free_freelist_hook(struct kmem_cache *s,
> > > > > >               } while (object != old_tail);
> > > > > >       }
> > > > > >
> > > > > > +     do {
> > > > > > +             object = next;
> > > > > > +             next = get_freepointer(s, object);
> > > > > > +             kmsan_slab_free(s, object);
> > > > > > +     } while (object != old_tail);
> > > > > > +
> > > > > >  /*
> > > > > >   * Compiler cannot detect this function can be removed if slab_free_hook()
> > > > > >   * evaluates to nothing.  Thus, catch all relevant config debug options here.
> > > > > > @@ -2769,6 +2789,7 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s,
> > > > > >       if (unlikely(slab_want_init_on_alloc(gfpflags, s)) && object)
> > > > > >               memset(object, 0, s->object_size);
> > > > > >
> > > > > > +     kmsan_slab_alloc(s, object, gfpflags);
> > > > > >       slab_post_alloc_hook(s, gfpflags, 1, &object);
> > > > > >
> > > > > >       return object;
> > > > > > @@ -2797,6 +2818,7 @@ void *kmem_cache_alloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size)
> > > > > >       void *ret = slab_alloc(s, gfpflags, _RET_IP_);
> > > > > >       trace_kmalloc(_RET_IP_, ret, size, s->size, gfpflags);
> > > > > >       ret = kasan_kmalloc(s, ret, size, gfpflags);
> > > > > > +
> > > > > >       return ret;
> > > > > >  }
> > > > > >  EXPORT_SYMBOL(kmem_cache_alloc_trace);
> > > > > > @@ -2809,7 +2831,6 @@ void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node)
> > > > > >
> > > > > >       trace_kmem_cache_alloc_node(_RET_IP_, ret,
> > > > > >                                   s->object_size, s->size, gfpflags, node);
> > > > > > -
> > > > > >       return ret;
> > > > > >  }
> > > > > >  EXPORT_SYMBOL(kmem_cache_alloc_node);
> > > > > > @@ -2825,6 +2846,7 @@ void *kmem_cache_alloc_node_trace(struct kmem_cache *s,
> > > > > >                          size, s->size, gfpflags, node);
> > > > > >
> > > > > >       ret = kasan_kmalloc(s, ret, size, gfpflags);
> > > > > > +
> > > > > >       return ret;
> > > > > >  }
> > > > > >  EXPORT_SYMBOL(kmem_cache_alloc_node_trace);
> > > > > > @@ -3150,7 +3172,7 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
> > > > > >                         void **p)
> > > > > >  {
> > > > > >       struct kmem_cache_cpu *c;
> > > > > > -     int i;
> > > > > > +     int i, j;
> > > > > >
> > > > > >       /* memcg and kmem_cache debug support */
> > > > > >       s = slab_pre_alloc_hook(s, flags);
> > > > > > @@ -3188,11 +3210,11 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
> > > > > >
> > > > > >       /* 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(p[j], 0, s->object_size);
> > > > > >       }
> > > > > > +     for (j = 0; j < i; j++)
> > > > > > +             kmsan_slab_alloc(s, p[j], flags);
> > > > > >
> > > > > >       /* memcg and kmem_cache debug support */
> > > > > >       slab_post_alloc_hook(s, flags, size, p);
> > > > > > @@ -3793,6 +3815,7 @@ static int __init setup_slub_min_objects(char *str)
> > > > > >
> > > > > >  __setup("slub_min_objects=", setup_slub_min_objects);
> > > > > >
> > > > > > +__no_sanitize_memory
> > > > > >  void *__kmalloc(size_t size, gfp_t flags)
> > > > > >  {
> > > > > >       struct kmem_cache *s;
> > > > > > @@ -5698,6 +5721,7 @@ static char *create_unique_id(struct kmem_cache *s)
> > > > > >       p += sprintf(p, "%07u", s->size);
> > > > > >
> > > > > >       BUG_ON(p > name + ID_STR_LENGTH - 1);
> > > > > > +     kmsan_unpoison_shadow(name, p - name);
> > > > > >       return name;
> > > > > >  }
> > > > > >
> > > > > > @@ -5847,6 +5871,7 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name)
> > > > > >       al->name = name;
> > > > > >       al->next = alias_list;
> > > > > >       alias_list = al;
> > > > > > +     kmsan_unpoison_shadow(al, sizeof(struct saved_alias));
> > > > > >       return 0;
> > > > > >  }
> > > > > >
> > > >
> > > >
> > > >
> >
> >
> >



-- 
Alexander Potapenko
Software Engineer

Google Germany GmbH
Erika-Mann-Straße, 33
80636 München

Geschäftsführer: Paul Manicle, Halimah DeLaine Prado
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg


  reply	other threads:[~2019-10-18 14:55 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-18  9:42 [PATCH RFC v1 00/26] Add KernelMemorySanitizer infrastructure glider
2019-10-18  9:42 ` [PATCH RFC v1 01/26] stackdepot: check depot_index before accessing the stack slab glider
2019-10-18  9:42 ` [PATCH RFC v1 02/26] stackdepot: prevent Clang from optimizing away stackdepot_memcmp() glider
2019-10-18  9:42 ` [PATCH RFC v1 03/26] kasan: stackdepot: move filter_irq_stacks() to stackdepot.c glider
2019-10-18  9:42 ` [PATCH RFC v1 04/26] stackdepot: reserve 5 extra bits in depot_stack_handle_t glider
2019-10-18  9:42 ` [PATCH RFC v1 05/26] printk_safe: externalize printk_context glider
2019-10-21  9:09   ` Petr Mladek
2019-10-23 17:57     ` Alexander Potapenko
2019-10-23 18:00       ` Alexander Potapenko
2019-10-24 12:46       ` Petr Mladek
2019-10-28 13:09         ` Alexander Potapenko
2019-10-29 12:02           ` Petr Mladek
2019-10-29 12:45             ` Alexander Potapenko
2019-10-18  9:42 ` [PATCH RFC v1 06/26] kasan: compiler.h: rename __no_kasan_or_inline into __no_memory_tool_or_inline glider
2019-10-18  9:42 ` [PATCH RFC v1 07/26] kmsan: add ReST documentation glider
2019-10-18  9:42 ` [PATCH RFC v1 08/26] kmsan: gfp: introduce __GFP_NO_KMSAN_SHADOW glider
2019-10-18  9:42 ` [PATCH RFC v1 09/26] kmsan: introduce __no_sanitize_memory and __SANITIZE_MEMORY__ glider
2019-10-18  9:42 ` [PATCH RFC v1 10/26] kmsan: reduce vmalloc space glider
2019-10-18  9:42 ` [PATCH RFC v1 11/26] kmsan: add KMSAN runtime glider
2019-10-18  9:42 ` [PATCH RFC v1 12/26] kmsan: x86: sync metadata pages on page fault glider
2019-10-18  9:42 ` [PATCH RFC v1 13/26] kmsan: add tests for KMSAN glider
2019-10-18  9:42 ` [PATCH RFC v1 14/26] kmsan: make READ_ONCE_TASK_STACK() return initialized values glider
2019-10-18  9:42 ` [PATCH RFC v1 15/26] kmsan: Kconfig changes to disable options incompatible with KMSAN glider
2019-10-21 14:11   ` Harry Wentland
2019-10-18  9:42 ` [PATCH RFC v1 16/26] kmsan: Changing existing files to enable KMSAN builds glider
2019-10-18  9:42 ` [PATCH RFC v1 17/26] kmsan: disable KMSAN instrumentation for certain kernel parts glider
2019-10-18  9:42 ` [PATCH RFC v1 18/26] kmsan: mm: call KMSAN hooks from SLUB code glider
2019-10-18 13:22   ` Qian Cai
2019-10-18 13:33     ` Alexander Potapenko
2019-10-18 13:41       ` Qian Cai
2019-10-18 13:55         ` Alexander Potapenko
2019-10-18 14:42           ` Qian Cai
2019-10-18 14:54             ` Alexander Potapenko [this message]
2019-10-18 15:13               ` Qian Cai
2019-10-18 15:30                 ` Alexander Potapenko
2019-10-18 16:08                   ` Qian Cai
2019-10-18  9:42 ` [PATCH RFC v1 19/26] kmsan: call KMSAN hooks where needed glider
2019-10-18 15:02   ` Qian Cai
2019-10-29 14:09     ` Alexander Potapenko
2019-10-29 14:56       ` Qian Cai
2019-10-21  9:25   ` Petr Mladek
2019-10-29 13:59     ` Alexander Potapenko
2019-10-18  9:42 ` [PATCH RFC v1 20/26] kmsan: disable instrumentation of certain functions glider
2019-10-18  9:42 ` [PATCH RFC v1 21/26] kmsan: unpoison |tlb| in arch_tlb_gather_mmu() glider
2019-10-18  9:43 ` [PATCH RFC v1 22/26] kmsan: use __msan_memcpy() where possible glider
2019-10-18  9:43 ` [PATCH RFC v1 23/26] kmsan: unpoisoning buffers from devices etc glider
2019-10-18 15:27   ` Christoph Hellwig
2019-10-18 16:22   ` Matthew Wilcox
2019-10-29 14:45     ` Alexander Potapenko
2019-10-30 12:43       ` Alexander Potapenko
2019-10-18  9:43 ` [PATCH RFC v1 24/26] kmsan: hooks for copy_to_user() and friends glider
2019-10-18  9:43 ` [PATCH RFC v1 25/26] kmsan: disable strscpy() optimization under KMSAN glider
2019-10-18  9:43 ` [PATCH RFC v1 26/26] net: kasan: kmsan: support CONFIG_GENERIC_CSUM on x86, enable it for KASAN/KMSAN glider
2019-10-19  3:20   ` Randy Dunlap

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='CAG_fn=V8MaATp_6swC3u_8kNDNiMrC5N80g1TRFGv2vvB7V6uQ@mail.gmail.com' \
    --to=glider@google.com \
    --cc=akpm@linux-foundation.org \
    --cc=cai@lca.pw \
    --cc=dvyukov@google.com \
    --cc=linux-mm@kvack.org \
    --cc=vegard.nossum@oracle.com \
    /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.