From 0fc1bd38a19c108395d8338fb034f90c2d3fbe55 Mon Sep 17 00:00:00 2001 From: Marco Elver Date: Mon, 11 May 2026 22:00:49 +0200 Subject: slab: improve KMALLOC_PARTITION_RANDOM randomness When using CONFIG_KMALLOC_PARTITION_RANDOM, _RET_IP_ was previously used to identify the allocation site. _RET_IP_, however, evaluates to the caller's parent's instruction pointer rather than the actual allocation site; this would lead to collisions where a function performs multiple allocations. With the generalization to kmalloc_token_t, we now generate the token at the outermost macro, and using _THIS_IP_ would fix this for all cases. Unfortunately, the generic implementation of _THIS_IP_ relies on taking the address of a local label, which is considered broken by both GCC [1] and Clang [2] because label addresses are only expected to be used with computed gotos. While the generic version more or less works today, it is known to be brittle. For example, Clang -O2 always returns 1 when this function is inlined: static inline unsigned long get_ip(void) { return ({ __label__ __here; __here: (unsigned long)&&__here; }); } To provide a reliable unique identifier without breaking architectures relying on the generic _THIS_IP_, introduce _CODE_LOCATION_: it resolves to _THIS_IP_ where architectures provide a safe implementation, and falls back to a zero-cost static marker where _THIS_IP_ is broken. Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120071 [1] Link: https://github.com/llvm/llvm-project/issues/138272 [2] Signed-off-by: Marco Elver Reviewed-by: Harry Yoo (Oracle) Link: https://patch.msgid.link/20260511200136.3201646-2-elver@google.com Signed-off-by: Vlastimil Babka (SUSE) --- include/linux/instruction_pointer.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'include/linux/instruction_pointer.h') diff --git a/include/linux/instruction_pointer.h b/include/linux/instruction_pointer.h index aa0b3ffea935..ea5bc756bd99 100644 --- a/include/linux/instruction_pointer.h +++ b/include/linux/instruction_pointer.h @@ -8,6 +8,30 @@ #ifndef _THIS_IP_ #define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; }) +/* + * The current generic definition of _THIS_IP_ is considered broken by GCC [1] + * and Clang [2]. In particular, the address of a label is only expected to be + * used with a computed goto. + * + * [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120071 + * [2] https://github.com/llvm/llvm-project/issues/138272 + * + * Mark it as broken, so that appropriate fallback options can be implemented + * for architectures that do not define their own _THIS_IP_. + */ +#define HAS_BROKEN_THIS_IP +#endif + +/* + * _CODE_LOCATION_ provides a unique identifier for the current code location. + * When _THIS_IP_ is broken (generic version), we fall back to a static marker + * which guarantees uniqueness and resolves to a constant address at link time, + * avoiding runtime overhead and compiler optimizations breaking it. + */ +#ifdef HAS_BROKEN_THIS_IP +#define _CODE_LOCATION_ ({ static const char __here; (unsigned long)&__here; }) +#else +#define _CODE_LOCATION_ _THIS_IP_ #endif #endif /* _LINUX_INSTRUCTION_POINTER_H */ -- cgit v1.2.3