Re: [PATCH v4 01/11] mm: add Kernel Electric-Fence infrastructure

Marco Elver
2020-10-12T14:22:48Z

[ Sorry for delay, just noticed this one doesn't have a reply yet. ]

On Sat, 3 Oct 2020 at 00:27, Jann Horn <jannh@google.com> wrote:
> On Fri, Oct 2, 2020 at 11:28 PM Marco Elver <elver@google.com> wrote:
> > On Fri, 2 Oct 2020 at 21:32, Jann Horn <jannh@google.com> wrote:
> > > > That's another check; we don't want to make this more expensive.
> > >
> > > Ah, right, I missed that this is the one piece of KFENCE that is
> > > actually really hot code until Dmitry pointed that out.
> > >
> > > But actually, can't you reduce how hot this is for SLUB by moving
> > > is_kfence_address() down into the freeing slowpath? At the moment you
> > > use it in slab_free_freelist_hook(), which is in the super-hot
> > > fastpath, but you should be able to at least move it down into
> > > __slab_free()...
> > >
> > > Actually, you already have hooked into __slab_free(), so can't you
> > > just get rid of the check in the slab_free_freelist_hook()?
> >
> > I missed this bit: the loop that follows wants the free pointer, so I
> > currently see how this might work. :-/
>
> reverse call graph:
> __slab_free
> do_slab_free
> slab_free
> kmem_cache_free (frees a single non-kmalloc allocation)
> kmem_cache_free_bulk (frees multiple)
> kfree (frees a single kmalloc allocation)
> ___cache_free (frees a single allocation for KASAN)
>
> So the only path for which we can actually loop in __slab_free() is
> kmem_cache_free_bulk(); and you've already changed
> build_detached_freelist() (which is used by kmem_cache_free_bulk() to
> group objects from the same page) to consume KFENCE allocations before
> they can ever reach __slab_free(). So we know that if we've reached
> __slab_free(), then we are being called with either a single object
> (which may be a KFENCE object) or with a list of objects that all
> belong to the same page and don't contain any KFENCE allocations.

Yes, while that is true, we still cannot execute the code in
slab_free_freelist_hook(). There are several problems:

- getting the freepointer which accesses object + s->offset, may
result in KFENCE OOB errors.

- similarly for setting the freepointer.

- slab_want_init_on_free zeroing object according to memcache
object_size, because it'll corrupt KFENCE's redzone if memcache
object_size > actual allocation size.

Leaving this here is fine, since we have determined that recent
optimizations make the check in slab_free_freelist_hook() negligible.

Thanks,
-- Marco