Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'slab-for-6.9-rc7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab

Pull slab fixes from Vlastimil Babka:

- Fix for cleanup infrastructure (Dan Carpenter)

This makes the __free(kfree) cleanup hooks not crash on error
pointers.

- SLUB fix for freepointer checking (Nicolas Bouchinet)

This fixes a recently introduced bug that manifests when
init_on_free, CONFIG_SLAB_FREELIST_HARDENED and consistency checks
(slub_debug=F) are all enabled, and results in false-positive
freepointer corrupt reports for caches that store freepointer outside
of the object area.

* tag 'slab-for-6.9-rc7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vbabka/slab:
mm/slab: make __free(kfree) accept error pointers
mm/slub: avoid zeroing outside-object freepointer for single free

+31 -25
+2 -2
include/linux/slab.h
··· 266 266 void kfree_sensitive(const void *objp); 267 267 size_t __ksize(const void *objp); 268 268 269 - DEFINE_FREE(kfree, void *, if (_T) kfree(_T)) 269 + DEFINE_FREE(kfree, void *, if (!IS_ERR_OR_NULL(_T)) kfree(_T)) 270 270 271 271 /** 272 272 * ksize - Report actual allocation size of associated object ··· 792 792 extern void *kvrealloc(const void *p, size_t oldsize, size_t newsize, gfp_t flags) 793 793 __realloc_size(3); 794 794 extern void kvfree(const void *addr); 795 - DEFINE_FREE(kvfree, void *, if (_T) kvfree(_T)) 795 + DEFINE_FREE(kvfree, void *, if (!IS_ERR_OR_NULL(_T)) kvfree(_T)) 796 796 797 797 extern void kvfree_sensitive(const void *addr, size_t len); 798 798
+29 -23
mm/slub.c
··· 557 557 *(freeptr_t *)freeptr_addr = freelist_ptr_encode(s, fp, freeptr_addr); 558 558 } 559 559 560 + /* 561 + * See comment in calculate_sizes(). 562 + */ 563 + static inline bool freeptr_outside_object(struct kmem_cache *s) 564 + { 565 + return s->offset >= s->inuse; 566 + } 567 + 568 + /* 569 + * Return offset of the end of info block which is inuse + free pointer if 570 + * not overlapping with object. 571 + */ 572 + static inline unsigned int get_info_end(struct kmem_cache *s) 573 + { 574 + if (freeptr_outside_object(s)) 575 + return s->inuse + sizeof(void *); 576 + else 577 + return s->inuse; 578 + } 579 + 560 580 /* Loop over all objects in a slab */ 561 581 #define for_each_object(__p, __s, __addr, __objects) \ 562 582 for (__p = fixup_red_left(__s, __addr); \ ··· 863 843 print_hex_dump(level, text, DUMP_PREFIX_ADDRESS, 864 844 16, 1, kasan_reset_tag((void *)addr), length, 1); 865 845 metadata_access_disable(); 866 - } 867 - 868 - /* 869 - * See comment in calculate_sizes(). 870 - */ 871 - static inline bool freeptr_outside_object(struct kmem_cache *s) 872 - { 873 - return s->offset >= s->inuse; 874 - } 875 - 876 - /* 877 - * Return offset of the end of info block which is inuse + free pointer if 878 - * not overlapping with object. 879 - */ 880 - static inline unsigned int get_info_end(struct kmem_cache *s) 881 - { 882 - if (freeptr_outside_object(s)) 883 - return s->inuse + sizeof(void *); 884 - else 885 - return s->inuse; 886 846 } 887 847 888 848 static struct track *get_track(struct kmem_cache *s, void *object, ··· 2092 2092 * 2093 2093 * The initialization memset's clear the object and the metadata, 2094 2094 * but don't touch the SLAB redzone. 2095 + * 2096 + * The object's freepointer is also avoided if stored outside the 2097 + * object. 2095 2098 */ 2096 2099 if (unlikely(init)) { 2097 2100 int rsize; 2101 + unsigned int inuse; 2098 2102 2103 + inuse = get_info_end(s); 2099 2104 if (!kasan_has_integrated_init()) 2100 2105 memset(kasan_reset_tag(x), 0, s->object_size); 2101 2106 rsize = (s->flags & SLAB_RED_ZONE) ? s->red_left_pad : 0; 2102 - memset((char *)kasan_reset_tag(x) + s->inuse, 0, 2103 - s->size - s->inuse - rsize); 2107 + memset((char *)kasan_reset_tag(x) + inuse, 0, 2108 + s->size - inuse - rsize); 2104 2109 } 2105 2110 /* KASAN might put x into memory quarantine, delaying its reuse. */ 2106 2111 return !kasan_slab_free(s, x, init); ··· 3727 3722 static __always_inline void maybe_wipe_obj_freeptr(struct kmem_cache *s, 3728 3723 void *obj) 3729 3724 { 3730 - if (unlikely(slab_want_init_on_free(s)) && obj) 3725 + if (unlikely(slab_want_init_on_free(s)) && obj && 3726 + !freeptr_outside_object(s)) 3731 3727 memset((void *)((char *)kasan_reset_tag(obj) + s->offset), 3732 3728 0, sizeof(void *)); 3733 3729 }