Detect changed compiler dependencies for full rebuild
Subsystems (4)
Kees Cook
maintainercover 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
Kees Cook
maintainerPATCH 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
@@ -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
@@ -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
kernel test robot
build botRe: [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
Kees Cook
maintainerRe: [PATCH 1/3] gcc-plugins: Force full rebuild when plugins change
In reply to Kees CookQuoted 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.
Signed-off-by Kees Cook <[email protected]>---
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
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
Kees Cook
maintainerPATCH 2/3 randstruct: Force full rebuild when seed changes
In reply to Kees CookWhile 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
@@ -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
@@ -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
@@ -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
Nathan Chancellor
maintainerRe: [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.
Signed-off-by Kees Cook <[email protected]>---
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@@ -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
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
-0KBUILD_CFLAGS += $(RANDSTRUCT_CFLAGS)scripts/basic/Makefile +6
-5@@ -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.hSignature · 1 line
2.34.1
Kees Cook
maintainerRe: [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.
Signed-off-by Kees Cook <[email protected]>---
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@@ -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
-0scripts/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.hAs 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 filesThere are places in the kernel that filter out
RANDSTRUCT_CFLAGSand this appears to cause other '-include' flags to be filtered out as well, such as the one in the efistub that includeshidden.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
Kees Cook
maintainerPATCH 3/3 integer-wrap: Force full rebuild when .scl file changes
In reply to Kees CookSince 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
@@ -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
@@ -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