Skip to contentSkip to conversation

Detect changed compiler dependencies for full rebuild

PATCH Superseded Kees Cook 3 participants 8 messages May 1, 2025 – May 2, 2025

Subsystems (4)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Kees Cook

author maintainer
#0 lore raw

cover Detect changed compiler dependencies for full rebuild

Hi,

This is my attempt to introduce dependencies that track the various compiler behaviors that may globally change the build that aren't represented by either compiler flags nor the compiler version (CC_VERSION_TEXT). Namely, this is to detect when the contents of a file the compiler uses changes. We have 3 such situations currently in the tree:

- If any of the GCC plugins change, we need to rebuild everything that was built with them, as they may have changed their behavior and those behaviors may need to be synchronized across all translation units. (The most obvious of these is the randstruct GCC plugin, but is true for most of them.)

- If the randstruct seed itself changes (whether for GCC plugins or Clang), the entire tree needs to be rebuilt since the randomization of structures may change between compilation units if not.

- If the integer-wrap-ignore.scl file for Clang's integer wrapping sanitizer changes, a full rebuild is needed as the coverage for wrapping types may have changed, once again cause behavior differences between compilation units.

The best way I found to deal with this is to use a -include argument for each of the above cases, which causes fixdep to pick up the file and naturally depend on it causing the build to notice any date stamp changes. Each case updates its .h file when its internal dependencies change.

-Kees

Kees Cook (3):
gcc-plugins: Force full rebuild when plugins change
randstruct: Force full rebuild when seed changes
integer-wrap: Force full rebuild when .scl file changes

 include/linux/vermagic.h     |  1 -
 scripts/Makefile.gcc-plugins |  2 +-
 scripts/Makefile.randstruct  |  3 ++-
 scripts/Makefile.ubsan       |  1 +
 scripts/basic/Makefile       | 20 +++++++++++++++-----
 scripts/gcc-plugins/Makefile |  8 ++++++++
 6 files changed, 27 insertions(+), 8 deletions(-)
Signature · 1 line
2.34.1
author maintainer
#1 lore raw

PATCH 1/3 gcc-plugins: Force full rebuild when plugins change

There was no dependency between the plugins changing and the rest of the kernel being built. Enforce this by including a synthetic header file when using plugins, that is regenerated any time the plugins are built.

---
Cc: Masahiro Yamada <[email protected]>
Cc: Nathan Chancellor <[email protected]>
Cc: Nicolas Schier <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>

---
 scripts/Makefile.gcc-plugins | 2 +-
 scripts/gcc-plugins/Makefile | 8 ++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)
scripts/Makefile.gcc-plugins +1 -1
index 5b8a8378ca8a..b0d2b9ccf42c 100644
@@ -38,7 +38,7 @@ export DISABLE_STACKLEAK_PLUGIN
 
 # All the plugin CFLAGS are collected here in case a build target needs to
 # filter them out of the KBUILD_CFLAGS.
-GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y))
+GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y)) -include $(objtree)/scripts/gcc-plugins/deps.h
 export GCC_PLUGINS_CFLAGS
 
 # Add the flags to the build!
scripts/gcc-plugins/Makefile +8 -0
index 320afd3cf8e8..38fd4c9f9b98 100644
@@ -66,3 +66,11 @@ quiet_cmd_plugin_cxx_o_c = HOSTCXX $@
 
 $(plugin-objs): $(obj)/%.o: $(src)/%.c FORCE
 	$(call if_changed_dep,plugin_cxx_o_c)
+
+quiet_cmd_gcc_plugins_updated = UPDATE  $@
+      cmd_gcc_plugins_updated = echo '/* $^ */' > $(obj)/deps.h
+
+$(obj)/deps.h: $(plugin-single) $(plugin-multi) FORCE
+	$(call if_changed,gcc_plugins_updated)
+
+always-y += deps.h
Signature · 1 line
2.34.1
#2 lore raw

Re: [PATCH 1/3] gcc-plugins: Force full rebuild when plugins change

kernel test robot noticed the following build errors:

Hi Kees,

kernel test robot noticed the following build errors:

[auto build test ERROR on kees/for-next/hardening]
[also build test ERROR on kees/for-next/pstore linus/master v6.15-rc4 next-20250501] [cannot apply to kees/for-next/kspp]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Kees-Cook/gcc-plugins-Force-full-rebuild-when-plugins-change/20250502-035038
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
patch link:    https://lore.kernel.org/r/20250501194826.2947101-1-kees%40kernel.org
patch subject: [PATCH 1/3] gcc-plugins: Force full rebuild when plugins change

:::::: branch date: 11 hours ago
:::::: commit date: 11 hours ago
config: arm64-randconfig-002-20250502 (https://download.01.org/0day-ci/archive/20250502/[email protected]/config)
compiler: aarch64-linux-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250502/[email protected]/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/r/[email protected]/

All errors (new ones prefixed by >>):

>> aarch64-linux-gcc: fatal error: cannot specify -o with -c, -S or -E with multiple files
   compilation terminated.
   make[3]: *** [scripts/Makefile.build:203: arch/arm64/kernel/vdso/vgettimeofday.o] Error 1 shuffle=1304459473
>> aarch64-linux-gcc: fatal error: cannot specify -o with -c, -S or -E with multiple files

compilation terminated.
make[3]: *** [scripts/Makefile.build:203: arch/arm64/kernel/vdso/vgetrandom.o] Error 1 shuffle=1304459473 make[3]: Target 'include/generated/vdso-offsets.h' not remade because of errors. make[3]: Target 'arch/arm64/kernel/vdso/vdso.so' not remade because of errors.
make[2]: *** [arch/arm64/Makefile:224: vdso_prepare] Error 2 shuffle=1304459473 make[2]: Target 'prepare' not remade because of errors.
make[1]: *** [Makefile:248: __sub-make] Error 2 shuffle=1304459473
make[1]: Target 'prepare' not remade because of errors.
make: *** [Makefile:248: __sub-make] Error 2 shuffle=1304459473
make: Target 'prepare' not remade because of errors.

Signature · 2 lines
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
author maintainer
#3 lore raw

Re: [PATCH 1/3] gcc-plugins: Force full rebuild when plugins change

In reply to Kees Cook
Quoted 21 lines · Kees Cook

There was no dependency between the plugins changing and the rest of the kernel being built. Enforce this by including a synthetic header file when using plugins, that is regenerated any time the plugins are built.

---
Cc: Masahiro Yamada <[email protected]>
Cc: Nathan Chancellor <[email protected]>
Cc: Nicolas Schier <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>

---
 scripts/Makefile.gcc-plugins | 2 +-
 scripts/gcc-plugins/Makefile | 8 ++++++++
 2 files changed, 9 insertions(+), 1 deletion(-)
scripts/Makefile.gcc-plugins +0 -0
index 5b8a8378ca8a..b0d2b9ccf42c 100644

scripts/Makefile.gcc-plugins export DISABLE_STACKLEAK_PLUGIN · line 41

Quoted 5 lines
scripts/Makefile.gcc-plugins +1 -1
@@ -38,7 +38,7 @@ export DISABLE_STACKLEAK_PLUGIN
 
 # All the plugin CFLAGS are collected here in case a build target needs to
 # filter them out of the KBUILD_CFLAGS.
-GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y))
+GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y)) -include $(objtree)/scripts/gcc-plugins/deps.h

This doesn't work[1] because CFLAGS_REMOVE and so many other places use filter-out (instead of subst) to remove flags, thinking flags are singular. But adding "-include path.h" means "-include" gets removed in a "$(filter-out $GCC_PLUGINS_CFLAGS, ...)" case. :(

Ugh.

-Kees

[1] https://lore.kernel.org/r/[email protected]/

Signature · 1 line
Kees Cook
author maintainer
#4 lore raw

PATCH 2/3 randstruct: Force full rebuild when seed changes

In reply to Kees Cook

While the randstruct GCC plugin was being rebuilt if the randstruct seed changed, Clangs build did not notice the change. Include the hash header directly so that it becomes a universal build dependency and full rebuilds will happen if it changes.

---
Cc: Masahiro Yamada <[email protected]>
Cc: Nathan Chancellor <[email protected]>
Cc: Nicolas Schier <[email protected]>
Cc: Petr Pavlu <[email protected]>
Cc: Sebastian Andrzej Siewior <[email protected]>
Cc: <[email protected]>

---
 include/linux/vermagic.h    |  1 -
 scripts/Makefile.randstruct |  3 ++-
 scripts/basic/Makefile      | 11 ++++++-----
 3 files changed, 8 insertions(+), 7 deletions(-)
include/linux/vermagic.h +0 -1
index 939ceabcaf06..335c360d4f9b 100644
@@ -33,7 +33,6 @@
 #define MODULE_VERMAGIC_MODVERSIONS ""
 #endif
 #ifdef RANDSTRUCT
-#include <generated/randstruct_hash.h>
 #define MODULE_RANDSTRUCT "RANDSTRUCT_" RANDSTRUCT_HASHED_SEED
 #else
 #define MODULE_RANDSTRUCT
scripts/Makefile.randstruct +2 -1
index 24e283e89893..ab87219c6149 100644
@@ -12,6 +12,7 @@ randstruct-cflags-y	\
 	+= -frandomize-layout-seed-file=$(objtree)/scripts/basic/randstruct.seed
 endif
 
-export RANDSTRUCT_CFLAGS := $(randstruct-cflags-y)
+export RANDSTRUCT_CFLAGS := $(randstruct-cflags-y) \
+			    -include $(objtree)/scripts/basic/randstruct_hash.h
 
 KBUILD_CFLAGS	+= $(RANDSTRUCT_CFLAGS)
scripts/basic/Makefile +6 -5
index dd289a6725ac..31637ce4dc5c 100644
@@ -8,9 +8,10 @@ hostprogs-always-y	+= fixdep
 # before running a Clang kernel build.
 gen-randstruct-seed	:= $(srctree)/scripts/gen-randstruct-seed.sh
 quiet_cmd_create_randstruct_seed = GENSEED $@
-cmd_create_randstruct_seed = \
-	$(CONFIG_SHELL) $(gen-randstruct-seed) \
-		$@ $(objtree)/include/generated/randstruct_hash.h
-$(obj)/randstruct.seed: $(gen-randstruct-seed) FORCE
+      cmd_create_randstruct_seed = $(CONFIG_SHELL) $(gen-randstruct-seed) \
+		$(obj)/randstruct.seed $(obj)/randstruct_hash.h
+
+$(obj)/randstruct_hash.h $(obj)/randstruct.seed: $(gen-randstruct-seed) FORCE
 	$(call if_changed,create_randstruct_seed)
-always-$(CONFIG_RANDSTRUCT) += randstruct.seed
+
+always-$(CONFIG_RANDSTRUCT) += randstruct.seed randstruct_hash.h
Signature · 1 line
2.34.1
#5 lore raw

Re: [PATCH 2/3] randstruct: Force full rebuild when seed changes

Hi Kees,

Quoted 36 lines · Kees Cook

While the randstruct GCC plugin was being rebuilt if the randstruct seed changed, Clangs build did not notice the change. Include the hash header directly so that it becomes a universal build dependency and full rebuilds will happen if it changes.

---
Cc: Masahiro Yamada <[email protected]>
Cc: Nathan Chancellor <[email protected]>
Cc: Nicolas Schier <[email protected]>
Cc: Petr Pavlu <[email protected]>
Cc: Sebastian Andrzej Siewior <[email protected]>
Cc: <[email protected]>

---
 include/linux/vermagic.h    |  1 -
 scripts/Makefile.randstruct |  3 ++-
 scripts/basic/Makefile      | 11 ++++++-----
 3 files changed, 8 insertions(+), 7 deletions(-)
include/linux/vermagic.h +0 -1
index 939ceabcaf06..335c360d4f9b 100644
@@ -33,7 +33,6 @@
 #define MODULE_VERMAGIC_MODVERSIONS ""
 #endif
 #ifdef RANDSTRUCT
-#include <generated/randstruct_hash.h>
 #define MODULE_RANDSTRUCT "RANDSTRUCT_" RANDSTRUCT_HASHED_SEED
 #else
 #define MODULE_RANDSTRUCT
scripts/Makefile.randstruct +0 -0
index 24e283e89893..ab87219c6149 100644

scripts/Makefile.randstruct randstruct-cflags-y \ · line 16

Quoted 6 lines
scripts/Makefile.randstruct +2 -1
@@ -12,6 +12,7 @@ randstruct-cflags-y	\
 	+= -frandomize-layout-seed-file=$(objtree)/scripts/basic/randstruct.seed
 endif
 
-export RANDSTRUCT_CFLAGS := $(randstruct-cflags-y)
+export RANDSTRUCT_CFLAGS := $(randstruct-cflags-y) \
+			    -include $(objtree)/scripts/basic/randstruct_hash.h

As the kernel test robot points out (on a report that you weren't included on for some reason...), this breaks the build in several places on next-20250502.

https://lore.kernel.org/[email protected]/

  $ make -skj"$(nproc)" ARCH=arm LLVM=1 clean allmodconfig arch/arm/vdso/vgettimeofday.o
  clang: error: cannot specify -o when generating multiple output files

There are places in the kernel that filter out RANDSTRUCT_CFLAGS and this appears to cause other '-include' flags to be filtered out as well, such as the one in the efistub that includes hidden.h.

Quoted 24 lines
scripts/Makefile.randstruct +0 -0
 KBUILD_CFLAGS	+= $(RANDSTRUCT_CFLAGS)
scripts/basic/Makefile +6 -5
index dd289a6725ac..31637ce4dc5c 100644
@@ -8,9 +8,10 @@ hostprogs-always-y	+= fixdep
 # before running a Clang kernel build.
 gen-randstruct-seed	:= $(srctree)/scripts/gen-randstruct-seed.sh
 quiet_cmd_create_randstruct_seed = GENSEED $@
-cmd_create_randstruct_seed = \
-	$(CONFIG_SHELL) $(gen-randstruct-seed) \
-		$@ $(objtree)/include/generated/randstruct_hash.h
-$(obj)/randstruct.seed: $(gen-randstruct-seed) FORCE
+      cmd_create_randstruct_seed = $(CONFIG_SHELL) $(gen-randstruct-seed) \
+		$(obj)/randstruct.seed $(obj)/randstruct_hash.h
+
+$(obj)/randstruct_hash.h $(obj)/randstruct.seed: $(gen-randstruct-seed) FORCE
 	$(call if_changed,create_randstruct_seed)
-always-$(CONFIG_RANDSTRUCT) += randstruct.seed
+
+always-$(CONFIG_RANDSTRUCT) += randstruct.seed randstruct_hash.h
Signature · 1 line
2.34.1
author maintainer
#6 lore raw

Re: [PATCH 2/3] randstruct: Force full rebuild when seed changes

Quoted 50 lines · Nathan Chancellor

Hi Kees,

Quoted 36 lines · Kees Cook

While the randstruct GCC plugin was being rebuilt if the randstruct seed changed, Clangs build did not notice the change. Include the hash header directly so that it becomes a universal build dependency and full rebuilds will happen if it changes.

---
Cc: Masahiro Yamada <[email protected]>
Cc: Nathan Chancellor <[email protected]>
Cc: Nicolas Schier <[email protected]>
Cc: Petr Pavlu <[email protected]>
Cc: Sebastian Andrzej Siewior <[email protected]>
Cc: <[email protected]>

---
 include/linux/vermagic.h    |  1 -
 scripts/Makefile.randstruct |  3 ++-
 scripts/basic/Makefile      | 11 ++++++-----
 3 files changed, 8 insertions(+), 7 deletions(-)
include/linux/vermagic.h +0 -1
index 939ceabcaf06..335c360d4f9b 100644
@@ -33,7 +33,6 @@
 #define MODULE_VERMAGIC_MODVERSIONS ""
 #endif
 #ifdef RANDSTRUCT
-#include <generated/randstruct_hash.h>
 #define MODULE_RANDSTRUCT "RANDSTRUCT_" RANDSTRUCT_HASHED_SEED
 #else
 #define MODULE_RANDSTRUCT
scripts/Makefile.randstruct +0 -0
index 24e283e89893..ab87219c6149 100644

scripts/Makefile.randstruct randstruct-cflags-y \ · line 16

Quoted 6 lines
scripts/Makefile.randstruct +2 -1
@@ -12,6 +12,7 @@ randstruct-cflags-y	\
 	+= -frandomize-layout-seed-file=$(objtree)/scripts/basic/randstruct.seed
 endif
 
-export RANDSTRUCT_CFLAGS := $(randstruct-cflags-y)
+export RANDSTRUCT_CFLAGS := $(randstruct-cflags-y) \
+			    -include $(objtree)/scripts/basic/randstruct_hash.h

As the kernel test robot points out (on a report that you weren't included on for some reason...), this breaks the build in several places on next-20250502.

Quoted 8 lines

https://lore.kernel.org/[email protected]/

  $ make -skj"$(nproc)" ARCH=arm LLVM=1 clean allmodconfig arch/arm/vdso/vgettimeofday.o
  clang: error: cannot specify -o when generating multiple output files

There are places in the kernel that filter out RANDSTRUCT_CFLAGS and this appears to cause other '-include' flags to be filtered out as well, such as the one in the efistub that includes hidden.h.

Thanks! Yeah, I have been poking at it for most of today. 😭

I think I have a viable solution, that I actually end up liking a bit better, which I just sent out:
https://lore.kernel.org/lkml/[email protected]/

Signature · 1 line
Kees Cook
author maintainer
#7 lore raw

PATCH 3/3 integer-wrap: Force full rebuild when .scl file changes

In reply to Kees Cook

Since the integer wrapping sanitizer's behavior depends on its associated .scl file, we must force a full rebuild if the file changes. Universally include a synthetic header file that is rebuilt when the .scl file changes.

---
Cc: Masahiro Yamada <[email protected]>
Cc: Justin Stitt <[email protected]>
Cc: Nathan Chancellor <[email protected]>
Cc: Nicolas Schier <[email protected]>
Cc: Marco Elver <[email protected]>
Cc: Andrey Konovalov <[email protected]>
Cc: Andrey Ryabinin <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>
Cc: <[email protected]>

---
 scripts/Makefile.ubsan | 1 +
 scripts/basic/Makefile | 9 +++++++++
 2 files changed, 10 insertions(+)
scripts/Makefile.ubsan +1 -0
index 9e35198edbf0..254d5a7ec994 100644
@@ -15,6 +15,7 @@ ubsan-cflags-$(CONFIG_UBSAN_TRAP)		+= $(call cc-option,-fsanitize-trap=undefined
 export CFLAGS_UBSAN := $(ubsan-cflags-y)
 
 ubsan-integer-wrap-cflags-$(CONFIG_UBSAN_INTEGER_WRAP)     +=	\
+	-include $(objtree)/scripts/basic/integer-wrap.h	\
 	-fsanitize-undefined-ignore-overflow-pattern=all	\
 	-fsanitize=signed-integer-overflow			\
 	-fsanitize=unsigned-integer-overflow			\
scripts/basic/Makefile +9 -0
index 31637ce4dc5c..04f5620a3f8b 100644
@@ -15,3 +15,12 @@ $(obj)/randstruct_hash.h $(obj)/randstruct.seed: $(gen-randstruct-seed) FORCE
 	$(call if_changed,create_randstruct_seed)
 
 always-$(CONFIG_RANDSTRUCT) += randstruct.seed randstruct_hash.h
+
+# integer-wrap: if the .scl file changes, we need to do a full rebuild.
+quiet_cmd_integer_wrap_updated = UPDATE  $@
+      cmd_integer_wrap_updated = echo '/* $^ */' > $(obj)/integer-wrap.h
+
+$(obj)/integer-wrap.h: $(srctree)/scripts/integer-wrap-ignore.scl FORCE
+	$(call if_changed,integer_wrap_updated)
+
+always-$(CONFIG_UBSAN_INTEGER_WRAP) += integer-wrap.h
Signature · 1 line
2.34.1