On Sun, Apr 26, 2020 at 10:02:12PM -0400, Waiman Long wrote: > In a couple of places in the slub memory allocator, the code uses > "s->offset" as a check to see if the free pointer is put right after the > object. That check is no longer true with commit 3202fa62fb43 ("slub: > relocate freelist pointer to middle of object"). > > As a result, echoing "1" into the validate sysfs file, e.g. of dentry, > may cause a bunch of "Freepointer corrupt" error reports to appear with > the system in panic afterwards. > > To fix it, use the check "s->offset == s->inuse" instead. I think a little refactoring would make this more clear. unsigned int track_offset(const struct kmem_cache *s) { return s->inuse + (s->offset == s->inuse) ? sizeof(void *) : 0; } > @@ -556,10 +556,8 @@ static struct track *get_track(struct kmem_cache *s, void *object, > { > struct track *p; > > - if (s->offset) > - p = object + s->offset + sizeof(void *); > - else > - p = object + s->inuse; > + p = object + s->inuse + > + ((s->offset == s->inuse) ? sizeof(void *) : 0); p = object + track_offset(s); > return p + alloc; > } > @@ -693,10 +691,8 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p) > print_section(KERN_ERR, "Redzone ", p + s->object_size, > s->inuse - s->object_size); > > - if (s->offset) > - off = s->offset + sizeof(void *); > - else > - off = s->inuse; > + off = s->inuse + > + ((s->offset == s->inuse) ? sizeof(void *) : 0); off = track_offset(s); > @@ -826,7 +822,7 @@ static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p) > { > unsigned long off = s->inuse; /* The end of info */ > > - if (s->offset) > + if (s->offset == s->inuse) > /* Freepointer is placed after the object. */ > off += sizeof(void *); unsigned long off = track_offset(s);