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
+
+config CC_HAS_COUNTED_BY_PTR
+ def_bool y
+ depends on CC_HAS_COUNTED_BY_PTR_BARE || CC_HAS_COUNTED_BY_PTR_EXP
+
config 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://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
@@ -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
+ *
+ * gcc: https://gcc.gnu.org/pipermail/gcc-patches/2025-April/681727.html
+ * 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
On Mon, Oct 20, 2025 at 03:01:15PM -0700, Kees Cook 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.
So why do we need both __counted_by_ptr() and this __sized_by(), won't
one be good enough?
Also, given the existing __counted_by() is really only usable with
>=19.1.3 and we're now at 22-ish, do we really need two of these?
That is, I'm really hating the idea we need 3 different annotations for
what is effectively the same thing and feel we should try *really* hard
to make it 1.
On Tue, Oct 21, 2025 at 11:54:47AM +0200, Peter Zijlstra wrote:
> On Mon, Oct 20, 2025 at 03:01:15PM -0700, Kees Cook 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.
>
> So why do we need both __counted_by_ptr() and this __sized_by(), won't
> one be good enough?
I remain extraordinarily frustrated that counted_by can't be used with
"void *". I hit a brick wall on this, though, and don't know how to
convince either GCC or Clang devs to fix it. It's so obviously correct
to me: "void *" uses a 1 byte iterator for arithmetic... so asking how
big a given allocation is should be byte sized!
Let me take another stab at it...
> Also, given the existing __counted_by() is really only usable with
> >=19.1.3 and we're now at 22-ish, do we really need two of these?
>
> That is, I'm really hating the idea we need 3 different annotations for
> what is effectively the same thing and feel we should try *really* hard
> to make it 1.
As for avoiding __counted_by_ptr(), we could just raise the minimum
Clang and GCC versions to require this, but that means dropping existing
coverage (e.g GCC 15 supports only flexible array counted_by).
Maybe we could do a global __counted_by_ptr -> __counted_by replacement
once GCC 16 is released?
--
Kees Cook
On Tue, Oct 21, 2025 at 12:24:05PM -0700, Kees Cook wrote: > On Tue, Oct 21, 2025 at 11:54:47AM +0200, Peter Zijlstra wrote: > > > [...] > > > 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. > > > > So why do we need both __counted_by_ptr() and this __sized_by(), won't > > one be good enough? > [...] > Let me take another stab at it... It seems this will be acceptable as long as it is gated by GNU extensions. GCC patch in progress. Clang PR here: https://github.com/llvm/llvm-project/pull/163698 -- Kees Cook
On Wed, Oct 22, 2025 at 05:47:43PM -0700, Kees Cook wrote: > On Tue, Oct 21, 2025 at 12:24:05PM -0700, Kees Cook wrote: > > On Tue, Oct 21, 2025 at 11:54:47AM +0200, Peter Zijlstra wrote: > > > > [...] > > > > 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. > > > > > > So why do we need both __counted_by_ptr() and this __sized_by(), won't > > > one be good enough? > > [...] > > Let me take another stab at it... > > It seems this will be acceptable as long as it is gated by GNU > extensions. Excellent! > GCC patch in progress. Clang PR here: > https://github.com/llvm/llvm-project/pull/163698 I think you've got your link mixed up, this appears to be arm-kcfi (also good ofc). Either that, or I need copy/paste lessons. This one? https://github.com/llvm/llvm-project/pull/164737
On October 23, 2025 1:01:23 AM PDT, Peter Zijlstra <peterz@infradead.org> wrote: >On Wed, Oct 22, 2025 at 05:47:43PM -0700, Kees Cook wrote: >> On Tue, Oct 21, 2025 at 12:24:05PM -0700, Kees Cook wrote: >> > On Tue, Oct 21, 2025 at 11:54:47AM +0200, Peter Zijlstra wrote: >> > > > [...] >> > > > 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. >> > > >> > > So why do we need both __counted_by_ptr() and this __sized_by(), won't >> > > one be good enough? >> > [...] >> > Let me take another stab at it... >> >> It seems this will be acceptable as long as it is gated by GNU >> extensions. > >Excellent! > >> GCC patch in progress. Clang PR here: >> https://github.com/llvm/llvm-project/pull/163698 > >I think you've got your link mixed up, this appears to be arm-kcfi (also >good ofc). Either that, or I need copy/paste lessons. > >This one? > > https://github.com/llvm/llvm-project/pull/164737 Whoops, yes, that's the one! Seems I'm the one needing those lessons. ;) -- Kees Cook
On Tue, Oct 21, 2025 at 12:24:05PM -0700, Kees Cook wrote: > On Tue, Oct 21, 2025 at 11:54:47AM +0200, Peter Zijlstra wrote: > > So why do we need both __counted_by_ptr() and this __sized_by(), won't > > one be good enough? > > I remain extraordinarily frustrated that counted_by can't be used with > "void *". I hit a brick wall on this, though, and don't know how to > convince either GCC or Clang devs to fix it. It's so obviously correct > to me: "void *" uses a 1 byte iterator for arithmetic... so asking how > big a given allocation is should be byte sized! Right, at least for gnu11 language variants this really should work. I mean, disallow the usage for c11 if you're pedantic but for crying out loud, have the GNU extensions be consistent and all that. Feel free to use my feedback if it would help. > Let me take another stab at it... Thanks! > As for avoiding __counted_by_ptr(), we could just raise the minimum > Clang and GCC versions to require this, but that means dropping existing > coverage (e.g GCC 15 supports only flexible array counted_by). > > Maybe we could do a global __counted_by_ptr -> __counted_by replacement > once GCC 16 is released? That sounds like a plan! :-)
On Mon, Oct 20, 2025 at 3:01 PM 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.
>
I'm pretty sure that "sized_by" is available in Clang right now.
-bw
> 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
> +
> +config CC_HAS_COUNTED_BY_PTR
> + def_bool y
> + depends on CC_HAS_COUNTED_BY_PTR_BARE || CC_HAS_COUNTED_BY_PTR_EXP
> +
> config 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://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
> @@ -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
> + *
> + * gcc: https://gcc.gnu.org/pipermail/gcc-patches/2025-April/681727.html
> + * 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
>
On Mon, Oct 20, 2025 at 03:53:55PM -0700, Bill Wendling wrote:
> On Mon, Oct 20, 2025 at 3:01 PM 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.
> >
> I'm pretty sure that "sized_by" is available in Clang right now.
My clang-22 build seems to accept it no problem indeed -- although I've
not verified it actually does anything with it.
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_EXP
> +
> config 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://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
> @@ -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
> + *
> + * gcc: https://gcc.gnu.org/pipermail/gcc-patches/2025-April/681727.html
> + * 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
>
© 2016 - 2026 Red Hat, Inc.