Clang and GCC are expanding the '__counted_by' attribute to support
pointers in structs. Clang has support for it since version 21. This
requires defining a separate macro, '__counted_by_ptr', because, while
the attribute has the same name for both a pointer and a flexible array
member, minimal compiler versions need to catch up.
The effect of this feature is the same as for __counted_by on flexible
array members. It provides hardening the ability to perform run-time
bounds checking on otherwise unknown-size pointers.
Cc: Kees Cook <kees@kernel.org>
Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nick Desaulniers <nick.desaulniers+lkml@gmail.com>
Cc: Justin Stitt <justinstitt@google.com>
Cc: Miguel Ojeda <ojeda@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Marc Herbert <Marc.Herbert@linux.intel.com>
Cc: Uros Bizjak <ubizjak@gmail.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Jeff Xu <jeffxu@chromium.org>
Cc: "Michal Koutný" <mkoutny@suse.com>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: "Thomas Weißschuh" <thomas.weissschuh@linutronix.de>
Cc: John Stultz <jstultz@google.com>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: linux-kernel@vger.kernel.org
Cc: linux-hardening@vger.kernel.org
Cc: llvm@lists.linux.dev
Signed-off-by: Bill Wendling <morbo@google.com>
---
include/linux/compiler_types.h | 11 +++++++++++
init/Kconfig | 5 +++++
2 files changed, 16 insertions(+)
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index 0a1b9598940d..2b0251bb951c 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -351,6 +351,17 @@ struct ftrace_likely_data {
# define __assume(expr)
#endif
+/*
+ * Optional: only supported since clang >= 21
+ *
+ * clang: https://github.com/llvm/llvm-project/pull/137250
+ */
+#ifdef CONFIG_CC_HAS_COUNTED_BY_FOR_POINTER
+#define __counted_by_ptr(member) __attribute__((__counted_by__(member)))
+#else
+#define __counted_by_ptr(member)
+#endif
+
/*
* Optional: only supported since gcc >= 15
* Optional: only supported since clang >= 18
diff --git a/init/Kconfig b/init/Kconfig
index cab3ad28ca49..298c94c4c1b1 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -139,6 +139,11 @@ 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_ON_POINTERS
+ bool
+ # Needs clang 21.1.0 or higher.
+ default y if CC_IS_CLANG && CLANG_VERSION >= 210100
+
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.52.0.rc2.455.g230fcf2819-goog
On Fri, Nov 21, 2025 at 11:40 AM Bill Wendling <morbo@google.com> wrote:
>
> Clang and GCC are expanding the '__counted_by' attribute to support
> pointers in structs. Clang has support for it since version 21. This
> requires defining a separate macro, '__counted_by_ptr', because, while
> the attribute has the same name for both a pointer and a flexible array
> member, minimal compiler versions need to catch up.
>
> The effect of this feature is the same as for __counted_by on flexible
> array members. It provides hardening the ability to perform run-time
> bounds checking on otherwise unknown-size pointers.
>
> Cc: Kees Cook <kees@kernel.org>
> Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
> Cc: Nathan Chancellor <nathan@kernel.org>
> Cc: Nick Desaulniers <nick.desaulniers+lkml@gmail.com>
> Cc: Justin Stitt <justinstitt@google.com>
> Cc: Miguel Ojeda <ojeda@kernel.org>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Heiko Carstens <hca@linux.ibm.com>
> Cc: Marc Herbert <Marc.Herbert@linux.intel.com>
> Cc: Uros Bizjak <ubizjak@gmail.com>
> Cc: Tejun Heo <tj@kernel.org>
> Cc: Jeff Xu <jeffxu@chromium.org>
> Cc: "Michal Koutný" <mkoutny@suse.com>
> Cc: Shakeel Butt <shakeel.butt@linux.dev>
> Cc: "Thomas Weißschuh" <thomas.weissschuh@linutronix.de>
> Cc: John Stultz <jstultz@google.com>
> Cc: Christian Brauner <brauner@kernel.org>
> Cc: Randy Dunlap <rdunlap@infradead.org>
> Cc: Brian Gerst <brgerst@gmail.com>
> Cc: Masahiro Yamada <masahiroy@kernel.org>
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-hardening@vger.kernel.org
> Cc: llvm@lists.linux.dev
> Signed-off-by: Bill Wendling <morbo@google.com>
> ---
> include/linux/compiler_types.h | 11 +++++++++++
> init/Kconfig | 5 +++++
> 2 files changed, 16 insertions(+)
>
> diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
> index 0a1b9598940d..2b0251bb951c 100644
> --- a/include/linux/compiler_types.h
> +++ b/include/linux/compiler_types.h
> @@ -351,6 +351,17 @@ struct ftrace_likely_data {
> # define __assume(expr)
> #endif
>
> +/*
> + * Optional: only supported since clang >= 21
> + *
> + * clang: https://github.com/llvm/llvm-project/pull/137250
> + */
> +#ifdef CONFIG_CC_HAS_COUNTED_BY_FOR_POINTER
> +#define __counted_by_ptr(member) __attribute__((__counted_by__(member)))
> +#else
> +#define __counted_by_ptr(member)
> +#endif
> +
> /*
> * Optional: only supported since gcc >= 15
> * Optional: only supported since clang >= 18
> diff --git a/init/Kconfig b/init/Kconfig
> index cab3ad28ca49..298c94c4c1b1 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -139,6 +139,11 @@ 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_ON_POINTERS
> + bool
> + # Needs clang 21.1.0 or higher.
> + default y if CC_IS_CLANG && CLANG_VERSION >= 210100
> +
I mistakenly left out GCC from here. I'll roll that in with v2.
-bw
> 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.52.0.rc2.455.g230fcf2819-goog
>
Clang and GCC are expanding the '__counted_by' attribute to support
pointers in structs. Clang has support for it since version 21. This
requires defining a separate macro, '__counted_by_ptr', because, while
the attribute has the same name for both a pointer and a flexible array
member, minimal compiler versions need to catch up.
The effect of this feature is the same as for __counted_by on flexible
array members. It provides hardening the ability to perform run-time
bounds checking on otherwise unknown-size pointers.
Cc: Kees Cook <kees@kernel.org>
Cc: Qing Zhao <qing.zhao@oracle.com>
Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nick Desaulniers <nick.desaulniers+lkml@gmail.com>
Cc: Justin Stitt <justinstitt@google.com>
Cc: Miguel Ojeda <ojeda@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Marc Herbert <Marc.Herbert@linux.intel.com>
Cc: Uros Bizjak <ubizjak@gmail.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Jeff Xu <jeffxu@chromium.org>
Cc: "Michal Koutný" <mkoutny@suse.com>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: "Thomas Weißschuh" <thomas.weissschuh@linutronix.de>
Cc: John Stultz <jstultz@google.com>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: linux-kernel@vger.kernel.org
Cc: linux-hardening@vger.kernel.org
Cc: llvm@lists.linux.dev
Signed-off-by: Bill Wendling <morbo@google.com>
---
v2 - Add support for GCC.
---
include/linux/compiler_types.h | 11 +++++++++++
init/Kconfig | 7 +++++++
2 files changed, 18 insertions(+)
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
index 0a1b9598940d..2b0251bb951c 100644
--- a/include/linux/compiler_types.h
+++ b/include/linux/compiler_types.h
@@ -351,6 +351,17 @@ struct ftrace_likely_data {
# define __assume(expr)
#endif
+/*
+ * Optional: only supported since clang >= 21
+ *
+ * clang: https://github.com/llvm/llvm-project/pull/137250
+ */
+#ifdef CONFIG_CC_HAS_COUNTED_BY_FOR_POINTER
+#define __counted_by_ptr(member) __attribute__((__counted_by__(member)))
+#else
+#define __counted_by_ptr(member)
+#endif
+
/*
* Optional: only supported since gcc >= 15
* Optional: only supported since clang >= 18
diff --git a/init/Kconfig b/init/Kconfig
index cab3ad28ca49..f947f242bca8 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -139,6 +139,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_ON_POINTERS
+ bool
+ # supported since clang 21.1.0
+ default y if CC_IS_CLANG && CLANG_VERSION >= 210100
+ # 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.52.0.rc2.455.g230fcf2819-goog
On Fri, Nov 21, 2025 at 8:55 PM Bill Wendling <morbo@google.com> wrote: > > +/* > + * Optional: only supported since clang >= 21 > + * > + * clang: https://github.com/llvm/llvm-project/pull/137250 > + */ > +#ifdef CONFIG_CC_HAS_COUNTED_BY_FOR_POINTER > +#define __counted_by_ptr(member) __attribute__((__counted_by__(member))) > +#else > +#define __counted_by_ptr(member) > +#endif I guess there is a reason for this name, but it sounds to me a bit like the thing between parenthesis is a pointer, i.e. that perhaps it is the pointee that one that counts. Hmm... what about `__ptr_counted_by`? In addition, could we please provide a bit of context in the documentation? i.e. links to the attribute docs in both Clang and GCC. And perhaps explaining why this cannot use `__has_attribute`, i.e. what the commit log mentions. Thanks! Cheers, Miguel
On Fri, Nov 21, 2025 at 1:48 PM Miguel Ojeda <miguel.ojeda.sandonis@gmail.com> wrote: > On Fri, Nov 21, 2025 at 8:55 PM Bill Wendling <morbo@google.com> wrote: > > > > +/* > > + * Optional: only supported since clang >= 21 > > + * > > + * clang: https://github.com/llvm/llvm-project/pull/137250 > > + */ > > +#ifdef CONFIG_CC_HAS_COUNTED_BY_FOR_POINTER > > +#define __counted_by_ptr(member) __attribute__((__counted_by__(member))) > > +#else > > +#define __counted_by_ptr(member) > > +#endif > > I guess there is a reason for this name, but it sounds to me a bit > like the thing between parenthesis is a pointer, i.e. that perhaps it > is the pointee that one that counts. > > Hmm... what about `__ptr_counted_by`? > > In addition, could we please provide a bit of context in the > documentation? i.e. links to the attribute docs in both Clang and GCC. > > And perhaps explaining why this cannot use `__has_attribute`, i.e. > what the commit log mentions. > The attribute used to be hidden behind "__has_attribute" (git show c8248faf3ca2), but was converted to a 'CONFIG_' variable due to (I assume) bug fixes that occurred at different compiler versions (git show f06e108a3dc53). Also "__has_attribute" won't work in this situation, because the attribute name, "__counted_by__", is used for both a pointer field (unsupported) and the flexible array member (supported). The naming of the macro is flexible of course. I have a preference for adding a suffix, because there are other expansions of this and other bounds safety attributes where, during discussions about the attributes' syntaxes, we've been using suffixes. I.e., Clang supports a limited form of context-free expressions as the argument to the attribute. We want to add support for that in the future, but there are issues with adding that support to GCC that haven't been ironed out yet. We've been calling that macro "__counted_by_expr", because again the attribute name is the same. This is not to say that it's the *best* name for the macro, but it does seem natural. I'll add these explanations to the commit message in a new version after I collect all feedback. :-) Thanks! -bw
© 2016 - 2025 Red Hat, Inc.