Skip to content

Commit 9ed9cac

Browse files
keestehcaster
authored andcommitted
slab: Remove __malloc attribute from realloc functions
The __malloc attribute should not be applied to "realloc" functions, as the returned pointer may alias the storage of the prior pointer. Instead of splitting __malloc from __alloc_size, which would be a huge amount of churn, just create __realloc_size for the few cases where it is needed. Thanks to Geert Uytterhoeven <geert@linux-m68k.org> for reporting build failures with gcc-8 in earlier version which tried to remove the #ifdef. While the "alloc_size" attribute is available on all GCC versions, I forgot that it gets disabled explicitly by the kernel in GCC < 9.1 due to misbehaviors. Add a note to the compiler_attributes.h entry for it. Cc: Christoph Lameter <cl@linux.com> Cc: Pekka Enberg <penberg@kernel.org> Cc: David Rientjes <rientjes@google.com> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: Hyeonggon Yoo <42.hyeyoo@gmail.com> Cc: Marco Elver <elver@google.com> Cc: linux-mm@kvack.org Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
1 parent e45cc28 commit 9ed9cac

File tree

4 files changed

+15
-12
lines changed

4 files changed

+15
-12
lines changed

include/linux/compiler_attributes.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535

3636
/*
3737
* Note: do not use this directly. Instead, use __alloc_size() since it is conditionally
38-
* available and includes other attributes.
38+
* available and includes other attributes. For GCC < 9.1, __alloc_size__ gets undefined
39+
* in compiler-gcc.h, due to misbehaviors.
3940
*
4041
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alloc_005fsize-function-attribute
4142
* clang: https://clang.llvm.org/docs/AttributeReference.html#alloc-size

include/linux/compiler_types.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,14 +271,16 @@ struct ftrace_likely_data {
271271

272272
/*
273273
* Any place that could be marked with the "alloc_size" attribute is also
274-
* a place to be marked with the "malloc" attribute. Do this as part of the
275-
* __alloc_size macro to avoid redundant attributes and to avoid missing a
276-
* __malloc marking.
274+
* a place to be marked with the "malloc" attribute, except those that may
275+
* be performing a _reallocation_, as that may alias the existing pointer.
276+
* For these, use __realloc_size().
277277
*/
278278
#ifdef __alloc_size__
279279
# define __alloc_size(x, ...) __alloc_size__(x, ## __VA_ARGS__) __malloc
280+
# define __realloc_size(x, ...) __alloc_size__(x, ## __VA_ARGS__)
280281
#else
281282
# define __alloc_size(x, ...) __malloc
283+
# define __realloc_size(x, ...)
282284
#endif
283285

284286
#ifndef asm_volatile_goto

include/linux/slab.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ int kmem_cache_shrink(struct kmem_cache *s);
184184
/*
185185
* Common kmalloc functions provided by all allocators
186186
*/
187-
void * __must_check krealloc(const void *objp, size_t new_size, gfp_t flags) __alloc_size(2);
187+
void * __must_check krealloc(const void *objp, size_t new_size, gfp_t flags) __realloc_size(2);
188188
void kfree(const void *objp);
189189
void kfree_sensitive(const void *objp);
190190
size_t __ksize(const void *objp);
@@ -647,10 +647,10 @@ static inline __alloc_size(1, 2) void *kmalloc_array(size_t n, size_t size, gfp_
647647
* @new_size: new size of a single member of the array
648648
* @flags: the type of memory to allocate (see kmalloc)
649649
*/
650-
static inline __alloc_size(2, 3) void * __must_check krealloc_array(void *p,
651-
size_t new_n,
652-
size_t new_size,
653-
gfp_t flags)
650+
static inline __realloc_size(2, 3) void * __must_check krealloc_array(void *p,
651+
size_t new_n,
652+
size_t new_size,
653+
gfp_t flags)
654654
{
655655
size_t bytes;
656656

@@ -774,7 +774,7 @@ static inline __alloc_size(1, 2) void *kvcalloc(size_t n, size_t size, gfp_t fla
774774
}
775775

776776
extern void *kvrealloc(const void *p, size_t oldsize, size_t newsize, gfp_t flags)
777-
__alloc_size(3);
777+
__realloc_size(3);
778778
extern void kvfree(const void *addr);
779779
extern void kvfree_sensitive(const void *addr, size_t len);
780780

mm/slab_common.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1150,8 +1150,8 @@ module_init(slab_proc_init);
11501150

11511151
#endif /* CONFIG_SLAB || CONFIG_SLUB_DEBUG */
11521152

1153-
static __always_inline void *__do_krealloc(const void *p, size_t new_size,
1154-
gfp_t flags)
1153+
static __always_inline __realloc_size(2) void *
1154+
__do_krealloc(const void *p, size_t new_size, gfp_t flags)
11551155
{
11561156
void *ret;
11571157
size_t ks;

0 commit comments

Comments
 (0)