 
            On Tue, 21 Oct 2025 at 00:01, Kees Cook kees@kernel.org wrote:
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; };
Since "counted_by" can only be applied to pointer members in very recent compiler versions, its application ends up needing to be distinct from flexible array "counted_by" annotations, hence a separate macro.
Unfortunately, this annotation cannot be used for "void *" members (since such a member is considered a pointer to an incomplete type, and neither Clang nor GCC developers could be convinced otherwise[1], even in the face of the GNU extension that "void *" has size "1 byte" for pointer arithmetic). For "void *" members, we must use the coming "sized_by" attribute.
Link: https://gcc.gnu.org/pipermail/gcc-patches/2025-May/683136.html [1] Signed-off-by: Kees Cook kees@kernel.org
Cc: Miguel Ojeda ojeda@kernel.org Cc: Nathan Chancellor nathan@kernel.org Cc: Nick Desaulniers nick.desaulniers+lkml@gmail.com Cc: Bill Wendling morbo@google.com Cc: Justin Stitt justinstitt@google.com Cc: Peter Zijlstra peterz@infradead.org Cc: Marco Elver elver@google.com Cc: Przemek Kitszel przemyslaw.kitszel@intel.com Cc: Andrew Morton akpm@linux-foundation.org Cc: Masahiro Yamada masahiroy@kernel.org Cc: Christophe Leroy christophe.leroy@csgroup.eu Cc: Johannes Weiner hannes@cmpxchg.org Cc: llvm@lists.linux.dev
init/Kconfig | 11 +++++++++++ Makefile | 4 ++++ include/linux/compiler_types.h | 21 ++++++++++++++++++++- include/uapi/linux/stddef.h | 4 ++++ 4 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/init/Kconfig b/init/Kconfig index cab3ad28ca49..54691b086bc6 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -139,6 +139,17 @@ 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_BARE
def_bool $(success,echo 'struct foo { int *ptr __attribute__((__counted_by__(count))); int count; };' | $(CC) $(CLANG_FLAGS) -x c - -c -o /dev/null -Werror)+config CC_HAS_COUNTED_BY_PTR_EXP
def_bool $(success,echo 'struct foo { int *ptr __attribute__((__counted_by__(count))); int count; };' | $(CC) $(CLANG_FLAGS) -fexperimental-late-parse-attributes -x c - -c -o /dev/null -Werror)
depends on !CC_HAS_COUNTED_BY_PTR_BARE
Do these still require an unreleased Clang version? Otherwise a version check will be faster.
+config CC_HAS_COUNTED_BY_PTR
def_bool y
depends on CC_HAS_COUNTED_BY_PTR_BARE || CC_HAS_COUNTED_BY_PTR_EXPconfig CC_HAS_MULTIDIMENSIONAL_NONSTRING def_bool $(success,echo 'char tag[][4] __attribute__((__nonstring__)) = { };' | $(CC) $(CLANG_FLAGS) -x c - -c -o /dev/null -Werror)
diff --git a/Makefile b/Makefile index d14824792227..1b297dcbb0df 100644 --- a/Makefile +++ b/Makefile @@ -933,6 +933,10 @@ KBUILD_CFLAGS += $(CC_AUTO_VAR_INIT_ZERO_ENABLER) endif endif
+ifdef CONFIG_CC_HAS_COUNTED_BY_PTR_EXP +KBUILD_CFLAGS += -fexperimental-late-parse-attributes +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 59288a2c1ad2..f197ea03b593 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -353,11 +353,14 @@ struct ftrace_likely_data { #endif
/*
- Runtime track number of flexible array member elements for use by
- CONFIG_FORTIFY_SOURCE and CONFIG_UBSAN_BOUNDS.
- Optional: only supported since gcc >= 15
- Optional: only supported since clang >= 18
- gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896
- clang: https://clang.llvm.org/docs/AttributeReference.html#counted-by-counted-by-or...
- __bdos on clang < 19.1.2 can erroneously return 0:
- https://github.com/llvm/llvm-project/pull/110497
@@ -371,6 +374,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 >= 20
- clang: ...
- */
+#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 9a28f7d9a334..111b097ec00b 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
2.34.1