Skip to contentSkip to conversation

disable __counted_by for clang < 19.1.3

PATCH Applied Jan Hendrik Farr 6 participants 8 messages Oct 29, 2024 – Jun 11, 2025

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover disable __counted_by for clang < 19.1.3

Hi Kees,

Bill's PR to disable __counted_by for "whole struct" __bdos cases has now been merged into 19.1.3 [1], so here's the patch to disable __counted_by for clang versions < 19.1.3 in the kernel.

Hopefully in the near future __counted_by for whole struct __bdos can be enabled once again in coordination between the kernel, gcc, and clang. There has been recent progress on this in [2] thanks to Tavian.

Also see previous discussion on the mailing list [3]

Thanks to everyone for moving this issue along. In particular, Bill for his PR to clang/llvm, Kees and Thorsten for reproducers of the two issues, Nathan for Kconfig-ifying this patch, and Miguel for reviewing.

Info for the stable team:

This patch should be backported to kernels >= 6.6 to make sure that those build correctly with the effected clang versions. This patch cherry-picks cleanly onto linux-6.11.y. For linux-6.6.y three prerequiste commits are neded:

16c31dd7fdf6: Compiler Attributes: counted_by: bump min gcc version 2993eb7a8d34: Compiler Attributes: counted_by: fixup clang URL 231dc3f0c936: lkdtm/bugs: Improve warning message for compilers without counted_by support

There are still two merge conflicts even with those prerequistes. Here's the correct resolution:

1. include/linux/compiler_types.h:
use the incoming change until before (but not including) the "Apply __counted_by() when the Endianness matches to increase test coverage." comment

2. lib/overflow_kunit.c:
HEAD is correct

[1] https://github.com/llvm/llvm-project/pull/112786
[2] https://github.com/llvm/llvm-project/pull/112636
[3] https://lore.kernel.org/lkml/[email protected]/T/#m204c09f63c076586a02d194b87dffc7e81b8de7b

Best Regards
Jan

Jan Hendrik Farr (1):
Compiler Attributes: disable __counted_by for clang < 19.1.3

 drivers/misc/lkdtm/bugs.c           |  2 +-
 include/linux/compiler_attributes.h | 13 -------------
 include/linux/compiler_types.h      | 19 +++++++++++++++++++
 init/Kconfig                        |  9 +++++++++
 lib/overflow_kunit.c                |  2 +-
 5 files changed, 30 insertions(+), 15 deletions(-)
Signature · 1 line
2.47.0
#1 lore raw

PATCH 1/1 Compiler Attributes: disable __counted_by for clang < 19.1.3

This patch disables __counted_by for clang versions < 19.1.3 because of the two issues listed below. It does this by introducing CONFIG_CC_HAS_COUNTED_BY.

1. clang < 19.1.2 has a bug that can lead to __bdos returning 0:
https://github.com/llvm/llvm-project/pull/110497

2. clang < 19.1.3 has a bug that can lead to __bdos being off by 4:
https://github.com/llvm/llvm-project/pull/112636

Fixes c8248faf3ca2 ("Compiler Attributes: counted_by: Adjust name and identifier expansion")
Cc [email protected] # 6.6.x: 16c31dd7fdf6: Compiler Attributes: counted_by: bump min gcc version
Cc [email protected] # 6.6.x: 2993eb7a8d34: Compiler Attributes: counted_by: fixup clang URL
Cc [email protected] # 6.6.x: 231dc3f0c936: lkdtm/bugs: Improve warning message for compilers without counted_by support
---
 drivers/misc/lkdtm/bugs.c           |  2 +-
 include/linux/compiler_attributes.h | 13 -------------
 include/linux/compiler_types.h      | 19 +++++++++++++++++++
 init/Kconfig                        |  9 +++++++++
 lib/overflow_kunit.c                |  2 +-
 5 files changed, 30 insertions(+), 15 deletions(-)
drivers/misc/lkdtm/bugs.c +1 -1
index 62ba01525479..376047beea3d 100644
@@ -445,7 +445,7 @@ static void lkdtm_FAM_BOUNDS(void)
 
 	pr_err("FAIL: survived access of invalid flexible array member index!\n");
 
-	if (!__has_attribute(__counted_by__))
+	if (!IS_ENABLED(CONFIG_CC_HAS_COUNTED_BY))
 		pr_warn("This is expected since this %s was built with a compiler that does not support __counted_by\n",
 			lkdtm_kernel_info);
 	else if (IS_ENABLED(CONFIG_UBSAN_BOUNDS))
include/linux/compiler_attributes.h +0 -13
index 32284cd26d52..c16d4199bf92 100644
@@ -94,19 +94,6 @@
 # define __copy(symbol)
 #endif
 
-/*
- * 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
- */
-#if __has_attribute(__counted_by__)
-# define __counted_by(member)		__attribute__((__counted_by__(member)))
-#else
-# define __counted_by(member)
-#endif
-
 /*
  * Optional: not supported by gcc
  * Optional: only supported since clang >= 14.0
include/linux/compiler_types.h +19 -0
index 1a957ea2f4fe..639be0f30b45 100644
@@ -323,6 +323,25 @@ struct ftrace_likely_data {
 #define __no_sanitize_or_inline __always_inline
 #endif
 
+/*
+ * 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
+ *
+ * __bdos on clang < 19.1.2 can erroneously return 0:
+ * https://github.com/llvm/llvm-project/pull/110497
+ *
+ * __bdos on clang < 19.1.3 can be off by 4:
+ * https://github.com/llvm/llvm-project/pull/112636
+ */
+#ifdef CONFIG_CC_HAS_COUNTED_BY
+# define __counted_by(member)		__attribute__((__counted_by__(member)))
+#else
+# define __counted_by(member)
+#endif
+
 /*
  * Apply __counted_by() when the Endianness matches to increase test coverage.
  */
init/Kconfig +9 -0
index 530a382ee0fe..92f106cf5572 100644
@@ -116,6 +116,15 @@ config CC_HAS_ASM_INLINE
 config CC_HAS_NO_PROFILE_FN_ATTR
 	def_bool $(success,echo '__attribute__((no_profile_instrument_function)) int x();' | $(CC) -x c - -c -o /dev/null -Werror)
 
+config CC_HAS_COUNTED_BY
+	# TODO: when gcc 15 is released remove the build test and add
+	# a gcc version check
+	def_bool $(success,echo 'struct flex { int count; int array[] __attribute__((__counted_by__(count))); };' | $(CC) $(CLANG_FLAGS) -x c - -c -o /dev/null -Werror)
+	# clang needs to be at least 19.1.3 to avoid __bdos miscalculations
+	# https://github.com/llvm/llvm-project/pull/110497
+	# https://github.com/llvm/llvm-project/pull/112636
+	depends on !(CC_IS_CLANG && CLANG_VERSION < 190103)
+
 config PAHOLE_VERSION
 	int
 	default $(shell,$(srctree)/scripts/pahole-version.sh $(PAHOLE))
lib/overflow_kunit.c +1 -1
index 2abc78367dd1..5222c6393f11 100644
@@ -1187,7 +1187,7 @@ static void DEFINE_FLEX_test(struct kunit *test)
 {
 	/* Using _RAW_ on a __counted_by struct will initialize "counter" to zero */
 	DEFINE_RAW_FLEX(struct foo, two_but_zero, array, 2);
-#if __has_attribute(__counted_by__)
+#ifdef CONFIG_CC_HAS_COUNTED_BY
 	int expected_raw_size = sizeof(struct foo);
 #else
 	int expected_raw_size = sizeof(struct foo) + 2 * sizeof(s16);
Signature · 1 line
2.47.0
Reviewed-by on v1 1/1
#2 lore raw

Re: [PATCH 1/1] Compiler Attributes: disable __counted_by for clang < 19.1.3

Quoted 11 lines · Jan Hendrik Farr

This patch disables __counted_by for clang versions < 19.1.3 because of the two issues listed below. It does this by introducing CONFIG_CC_HAS_COUNTED_BY.

1. clang < 19.1.2 has a bug that can lead to __bdos returning 0:
https://github.com/llvm/llvm-project/pull/110497

2. clang < 19.1.3 has a bug that can lead to __bdos being off by 4:
https://github.com/llvm/llvm-project/pull/112636

Quoted 15 lines
Fixes c8248faf3ca2 ("Compiler Attributes: counted_by: Adjust name and identifier expansion")
Cc [email protected] # 6.6.x: 16c31dd7fdf6: Compiler Attributes: counted_by: bump min gcc version
Cc [email protected] # 6.6.x: 2993eb7a8d34: Compiler Attributes: counted_by: fixup clang URL
Cc [email protected] # 6.6.x: 231dc3f0c936: lkdtm/bugs: Improve warning message for compilers without counted_by support

Thanks for fixing this and your work on the Clang issues. Feel free to add:

maintainer Applied
#3 lore raw

Re: [PATCH 1/1] Compiler Attributes: disable __counted_by for clang < 19.1.3

In reply to Jan Hendrik Farr
Quoted 8 lines · Jan Hendrik Farr

This patch disables __counted_by for clang versions < 19.1.3 because of the two issues listed below. It does this by introducing CONFIG_CC_HAS_COUNTED_BY.

1. clang < 19.1.2 has a bug that can lead to __bdos returning 0:
https://github.com/llvm/llvm-project/pull/110497

[...]

Applied to for-next/hardening, thanks!

[1/1] Compiler Attributes: disable __counted_by for clang < 19.1.3

      https://git.kernel.org/kees/c/f06e108a3dc5

Take care,

Signature · 1 line
Kees Cook
#4 lore raw

Re: [PATCH 1/1] Compiler Attributes: disable __counted_by for clang < 19.1.3

In reply to Jan Hendrik Farr
Quoted 57 lines · Jan Hendrik Farr

This patch disables __counted_by for clang versions < 19.1.3 because of the two issues listed below. It does this by introducing CONFIG_CC_HAS_COUNTED_BY.

1. clang < 19.1.2 has a bug that can lead to __bdos returning 0:
https://github.com/llvm/llvm-project/pull/110497

2. clang < 19.1.3 has a bug that can lead to __bdos being off by 4:
https://github.com/llvm/llvm-project/pull/112636

Fixes c8248faf3ca2 ("Compiler Attributes: counted_by: Adjust name and identifier expansion")
Cc [email protected] # 6.6.x: 16c31dd7fdf6: Compiler Attributes: counted_by: bump min gcc version
Cc [email protected] # 6.6.x: 2993eb7a8d34: Compiler Attributes: counted_by: fixup clang URL
Cc [email protected] # 6.6.x: 231dc3f0c936: lkdtm/bugs: Improve warning message for compilers without counted_by support

---

drivers/misc/lkdtm/bugs.c           |  2 +-
include/linux/compiler_attributes.h | 13 -------------
include/linux/compiler_types.h      | 19 +++++++++++++++++++
init/Kconfig                        |  9 +++++++++
lib/overflow_kunit.c                |  2 +-
5 files changed, 30 insertions(+), 15 deletions(-)
drivers/misc/lkdtm/bugs.c +1 -1
index 62ba01525479..376047beea3d 100644
@@ -445,7 +445,7 @@ static void lkdtm_FAM_BOUNDS(void)
 
 	pr_err("FAIL: survived access of invalid flexible array member index!\n");
 
-	if (!__has_attribute(__counted_by__))
+	if (!IS_ENABLED(CONFIG_CC_HAS_COUNTED_BY))
 		pr_warn("This is expected since this %s was built with a compiler that does not support __counted_by\n",
 			lkdtm_kernel_info);
 	else if (IS_ENABLED(CONFIG_UBSAN_BOUNDS))
include/linux/compiler_attributes.h +0 -3
index 32284cd26d52..c16d4199bf92 100644
@@ -94,19 +94,6 @@
 # define __copy(symbol)
 #endif
 
-/*
- * Optional: only supported since gcc >= 15
- * Optional: only supported since clang >= 18

include/linux/compiler_attributes.h line 109

Quoted 10 lines
include/linux/compiler_attributes.h +0 -10
- *
- *   gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896
- * clang: https://github.com/llvm/llvm-project/pull/76348
- */
-#if __has_attribute(__counted_by__)
-# define __counted_by(member)		__attribute__((__counted_by__(member)))
-#else
-# define __counted_by(member)
-#endif
-

Why is the define of __counted_by moved from here (compiler_attributes.h) to a different location (compiler_types.h) ?
I am asking this because I try to compile an out of tree kernel module with ofed headers. in the ofed header of compiler_types.h there is an added include of types.h:

#include_next <linux/compiler_attributes.h>
#include <linux/types.h>

so what happen is that __counted_by is defined in types.h, and then I get a compilation error:

././include/linux/compiler_types.h:323: error: "__counted_by" redefined [-Werror]

I am not sure yet how this should be fixed.
Thank you,
Dafna

Quoted 69 lines
include/linux/compiler_attributes.h +0 -0
 /*
 * Optional: not supported by gcc
 * Optional: only supported since clang >= 14.0
include/linux/compiler_types.h +19 -0
index 1a957ea2f4fe..639be0f30b45 100644
@@ -323,6 +323,25 @@ struct ftrace_likely_data {
 #define __no_sanitize_or_inline __always_inline
 #endif
 
+/*
+ * 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
+ *
+ * __bdos on clang < 19.1.2 can erroneously return 0:
+ * https://github.com/llvm/llvm-project/pull/110497
+ *
+ * __bdos on clang < 19.1.3 can be off by 4:
+ * https://github.com/llvm/llvm-project/pull/112636
+ */
+#ifdef CONFIG_CC_HAS_COUNTED_BY
+# define __counted_by(member)		__attribute__((__counted_by__(member)))
+#else
+# define __counted_by(member)
+#endif
+
 /*
 * Apply __counted_by() when the Endianness matches to increase test coverage.
 */
init/Kconfig +0 -0
index 530a382ee0fe..92f106cf5572 100644
@@ -116,6 +116,15 @@ config CC_HAS_ASM_INLINE

config CC_HAS_NO_PROFILE_FN_ATTR

	def_bool $(success,echo '__attribute__((no_profile_instrument_function)) int x();' | $(CC) -x c - -c -o /dev/null -Werror)
init/Kconfig +9 -0
+config CC_HAS_COUNTED_BY
+	# TODO: when gcc 15 is released remove the build test and add
+	# a gcc version check
+	def_bool $(success,echo 'struct flex { int count; int array[] __attribute__((__counted_by__(count))); };' | $(CC) $(CLANG_FLAGS) -x c - -c -o /dev/null -Werror)
+	# clang needs to be at least 19.1.3 to avoid __bdos miscalculations
+	# https://github.com/llvm/llvm-project/pull/110497
+	# https://github.com/llvm/llvm-project/pull/112636
+	depends on !(CC_IS_CLANG && CLANG_VERSION < 190103)
+

config PAHOLE_VERSION

	int
	default $(shell,$(srctree)/scripts/pahole-version.sh $(PAHOLE))
lib/overflow_kunit.c +1 -1
index 2abc78367dd1..5222c6393f11 100644
@@ -1187,7 +1187,7 @@ static void DEFINE_FLEX_test(struct kunit *test)
 {
 	/* Using _RAW_ on a __counted_by struct will initialize "counter" to zero */
 	DEFINE_RAW_FLEX(struct foo, two_but_zero, array, 2);
-#if __has_attribute(__counted_by__)
+#ifdef CONFIG_CC_HAS_COUNTED_BY
 	int expected_raw_size = sizeof(struct foo);
 #else
 	int expected_raw_size = sizeof(struct foo) + 2 * sizeof(s16);
Signature · 1 line
2.47.0
#5 lore raw

Re: [PATCH 1/1] Compiler Attributes: disable __counted_by for clang < 19.1.3

Quoted 3 lines · Dafna Hirschfeld

Why is the define of __counted_by moved from here (compiler_attributes.h) to a different location (compiler_types.h) ?

compiler_attributes.h is supposed to have only things that do not depend on the kernel configuration and so on.

It sounds like those out-of-tree headers should be fixed.

I hope that helps.

Cheers,
Miguel

maintainer
#6 lore raw

Re: [PATCH 1/1] Compiler Attributes: disable __counted_by for clang < 19.1.3

In reply to Jan Hendrik Farr

[ Sasha's backport helper bot ]

Hi,

Summary of potential issues:
⚠️ Found matching upstream commit but patch is missing proper reference to it

Found matching upstream commit: f06e108a3dc53c0f5234d18de0bd224753db5019

Note: The patch differs from the upstream commit:
---

1:  f06e108a3dc53 < -:  ------------- Compiler Attributes: disable __counted_by for clang < 19.1.3
-:  ------------- > 1:  fc85704c3dae5 Linux 6.15.2

---

Results of testing on various branches:

| Branch                    | Patch Apply | Build Test |
|---------------------------|-------------|------------|
| stable/linux-5.4.y        |  Success    |  Success   |
#7 lore raw

Re: [PATCH 1/1] Compiler Attributes: disable __counted_by for clang < 19.1.3

Quoted 13 lines · Sasha Levin

[ Sasha's backport helper bot ]

Hi,

Summary of potential issues:
⚠️ Found matching upstream commit but patch is missing proper reference to it

Found matching upstream commit: f06e108a3dc53c0f5234d18de0bd224753db5019

Note: The patch differs from the upstream commit:
---

1:  f06e108a3dc53 < -:  ------------- Compiler Attributes: disable __counted_by for clang < 19.1.3
-:  ------------- > 1:  fc85704c3dae5 Linux 6.15.2
Quoted 7 lines

---

Results of testing on various branches:

| Branch                    | Patch Apply | Build Test |
|---------------------------|-------------|------------|
| stable/linux-5.4.y        |  Success    |  Success   |

I guess this patch has been erroneously picked up by the backport helper. This was the patch for upstream that already got into 6.13 and has already been applied to 6.12, 6.11 and backported to 6.6 back in December.

Best Regards
Jan