[PATCH v6 5/9] mm, kfence: insert KFENCE hooks for SLUB

Jann Horn jannh at google.com
Thu Oct 29 22:49:41 EDT 2020


On Thu, Oct 29, 2020 at 2:17 PM Marco Elver <elver at google.com> wrote:
> Inserts KFENCE hooks into the SLUB allocator.
>
> To pass the originally requested size to KFENCE, add an argument
> 'orig_size' to slab_alloc*(). The additional argument is required to
> preserve the requested original size for kmalloc() allocations, which
> uses size classes (e.g. an allocation of 272 bytes will return an object
> of size 512). Therefore, kmem_cache::size does not represent the
> kmalloc-caller's requested size, and we must introduce the argument
> 'orig_size' to propagate the originally requested size to KFENCE.
>
> Without the originally requested size, we would not be able to detect
> out-of-bounds accesses for objects placed at the end of a KFENCE object
> page if that object is not equal to the kmalloc-size class it was
> bucketed into.
>
> When KFENCE is disabled, there is no additional overhead, since
> slab_alloc*() functions are __always_inline.
>
> Reviewed-by: Dmitry Vyukov <dvyukov at google.com>
> Co-developed-by: Marco Elver <elver at google.com>
> Signed-off-by: Marco Elver <elver at google.com>
> Signed-off-by: Alexander Potapenko <glider at google.com>

Reviewed-by: Jann Horn <jannh at google.com>

if you fix one nit:

[...]
> diff --git a/mm/slub.c b/mm/slub.c
[...]
> @@ -2658,7 +2664,8 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page)
>   * already disabled (which is the case for bulk allocation).
>   */
>  static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
> -                         unsigned long addr, struct kmem_cache_cpu *c)
> +                         unsigned long addr, struct kmem_cache_cpu *c,
> +                         size_t orig_size)

orig_size is added as a new argument, but never used. (And if you
remove this argument, __slab_alloc will also not be using its
orig_size argument anymore.)



>  {
>         void *freelist;
>         struct page *page;
> @@ -2763,7 +2770,8 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
>   * cpu changes by refetching the per cpu area pointer.
>   */
>  static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
> -                         unsigned long addr, struct kmem_cache_cpu *c)
> +                         unsigned long addr, struct kmem_cache_cpu *c,
> +                         size_t orig_size)
>  {
>         void *p;
>         unsigned long flags;
> @@ -2778,7 +2786,7 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
>         c = this_cpu_ptr(s->cpu_slab);
>  #endif
>
> -       p = ___slab_alloc(s, gfpflags, node, addr, c);
> +       p = ___slab_alloc(s, gfpflags, node, addr, c, orig_size);
>         local_irq_restore(flags);
>         return p;
>  }



More information about the linux-arm-kernel mailing list