Skip to content

Commit

Permalink
kmsan: force initialize the result of get_freepointer_safe()
Browse files Browse the repository at this point in the history
The uninitialized value returned by get_freepointer_safe() may be
passed into CAS, where KMSAN will check it regardless of whether
CAS failed or not.
  • Loading branch information
ramosian-glider committed Sep 27, 2018
1 parent 38662b3 commit a5bff9b
Showing 1 changed file with 11 additions and 2 deletions.
13 changes: 11 additions & 2 deletions mm/slub.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,17 +274,26 @@ 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 INIT_PTR() 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 INIT_PTR(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 INIT_PTR(freelist_ptr(s, p, freepointer_addr));
}

static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
Expand Down

0 comments on commit a5bff9b

Please sign in to comment.