From 150a04d817d8f5be5a4f92799827cdc8d7e45989 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Fri, 16 Jan 2026 00:57:57 +0000 Subject: [PATCH] compiler_types.h: Attributes: Add __counted_by_ptr macro Introduce __counted_by_ptr(), which works like __counted_by(), but for pointer struct members. struct foo { int a, b, c; char *buffer __counted_by_ptr(bytes); short nr_bars; struct bar *bars __counted_by_ptr(nr_bars); size_t bytes; }; Because "counted_by" can only be applied to pointer members in very recent compiler versions, its application ends up needing to be distinct from flexibe array "counted_by" annotations, hence a separate macro. This is a reworking of Kees' previous patch [1]. Link: https://lore.kernel.org/all/20251020220118.1226740-1-kees@kernel.org/ [1] Co-developed-by: Kees Cook Signed-off-by: Bill Wendling Link: https://patch.msgid.link/20260116005838.2419118-1-morbo@google.com Signed-off-by: Kees Cook --- Makefile | 6 ++++++ include/linux/compiler_types.h | 18 +++++++++++++++++- include/uapi/linux/stddef.h | 4 ++++ init/Kconfig | 7 +++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3cd00b62cde99..c0751976cdee8 100644 --- a/Makefile +++ b/Makefile @@ -952,6 +952,12 @@ KBUILD_CFLAGS += $(CC_AUTO_VAR_INIT_ZERO_ENABLER) endif endif +ifdef CONFIG_CC_IS_CLANG +ifdef CONFIG_CC_HAS_COUNTED_BY_PTR +KBUILD_CFLAGS += -fexperimental-late-parse-attributes +endif +endif + # Explicitly clear padding bits during variable initialization KBUILD_CFLAGS += $(call cc-option,-fzero-init-padding-bits=all) diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h index d3318a3c25777..d095beb904ea3 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -369,7 +369,7 @@ struct ftrace_likely_data { * Optional: only supported since clang >= 18 * * gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896 - * clang: https://github.com/llvm/llvm-project/pull/76348 + * clang: https://clang.llvm.org/docs/AttributeReference.html#counted-by-counted-by-or-null-sized-by-sized-by-or-null * * __bdos on clang < 19.1.2 can erroneously return 0: * https://github.com/llvm/llvm-project/pull/110497 @@ -383,6 +383,22 @@ struct ftrace_likely_data { # define __counted_by(member) #endif +/* + * Runtime track number of objects pointed to by a pointer member for use by + * CONFIG_FORTIFY_SOURCE and CONFIG_UBSAN_BOUNDS. + * + * Optional: only supported since gcc >= 16 + * Optional: only supported since clang >= 22 + * + * gcc: https://gcc.gnu.org/pipermail/gcc-patches/2025-April/681727.html + * clang: https://clang.llvm.org/docs/AttributeReference.html#counted-by-counted-by-or-null-sized-by-sized-by-or-null + */ +#ifdef CONFIG_CC_HAS_COUNTED_BY_PTR +#define __counted_by_ptr(member) __attribute__((__counted_by__(member))) +#else +#define __counted_by_ptr(member) +#endif + /* * Optional: only supported since gcc >= 15 * Optional: not supported by Clang diff --git a/include/uapi/linux/stddef.h b/include/uapi/linux/stddef.h index 9a28f7d9a3342..111b097ec00b0 100644 --- a/include/uapi/linux/stddef.h +++ b/include/uapi/linux/stddef.h @@ -72,6 +72,10 @@ #define __counted_by_be(m) #endif +#ifndef __counted_by_ptr +#define __counted_by_ptr(m) +#endif + #ifdef __KERNEL__ #define __kernel_nonstring __nonstring #else diff --git a/init/Kconfig b/init/Kconfig index fa79feb8fe57b..96b7cd481eaaa 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -143,6 +143,13 @@ config CC_HAS_COUNTED_BY # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896 default y if CC_IS_GCC && GCC_VERSION >= 150100 +config CC_HAS_COUNTED_BY_PTR + bool + # supported since clang 22 + default y if CC_IS_CLANG && CLANG_VERSION >= 220000 + # supported since gcc 16.0.0 + default y if CC_IS_GCC && GCC_VERSION >= 160000 + config CC_HAS_MULTIDIMENSIONAL_NONSTRING def_bool $(success,echo 'char tag[][4] __attribute__((__nonstring__)) = { };' | $(CC) $(CLANG_FLAGS) -x c - -c -o /dev/null -Werror) -- 2.47.3