Add a CONFIG_STACK_VALIDATION option which will run "stacktool check"
for each .o file to ensure the validity of its stack metadata.

Signed-off-by: Josh Poimboeuf <jpoim...@redhat.com>
---
 Makefile               |  5 ++++-
 arch/Kconfig           |  6 ++++++
 lib/Kconfig.debug      | 12 ++++++++++++
 scripts/Makefile.build | 38 ++++++++++++++++++++++++++++++++++----
 scripts/mod/Makefile   |  2 ++
 5 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/Makefile b/Makefile
index 70dea02..8e518fe 100644
--- a/Makefile
+++ b/Makefile
@@ -986,7 +986,10 @@ prepare0: archprepare FORCE
        $(Q)$(MAKE) $(build)=.
 
 # All the preparing..
-prepare: prepare0
+prepare: prepare0 prepare-stacktool
+
+PHONY += prepare-stacktool
+prepare-stacktool: $(if $(CONFIG_STACK_VALIDATION), tools/stacktool FORCE)
 
 # Generate some files
 # ---------------------------------------------------------------------------
diff --git a/arch/Kconfig b/arch/Kconfig
index 671810c..b20f472 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -527,6 +527,12 @@ config HAVE_COPY_THREAD_TLS
          normal C parameter passing, rather than extracting the syscall
          argument from pt_regs.
 
+config HAVE_STACK_VALIDATION
+       bool
+       help
+         Architecture supports the stacktool host tool, which adds
+         compile-time stack metadata validation.
+
 #
 # ABI hall of shame
 #
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index ee1ac1c..a984656 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -342,6 +342,18 @@ config FRAME_POINTER
          larger and slower, but it gives very useful debugging information
          in case of kernel bugs. (precise oopses/stacktraces/warnings)
 
+config STACK_VALIDATION
+       bool "Enable compile-time stack metadata validation"
+       depends on HAVE_STACK_VALIDATION
+       default n
+       help
+         Add compile-time checks to validate stack metadata, including frame
+         pointers (if CONFIG_FRAME_POINTER is enabled).  This helps ensure
+         that runtime stack traces are more reliable.
+
+         For more information, see
+         tools/stacktool/Documentation/stack-validation.txt.
+
 config DEBUG_FORCE_WEAK_PER_CPU
        bool "Force weak per-cpu definitions"
        depends on DEBUG_KERNEL
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 01df30a..5ec40fc 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -241,10 +241,31 @@ cmd_record_mcount =                                       
        \
        fi;
 endif
 
+ifdef CONFIG_STACK_VALIDATION
+
+__stacktool_obj := $(objtree)/tools/stacktool/stacktool
+
+stacktool_args = check
+ifndef CONFIG_FRAME_POINTER
+stacktool_args += --no-fp
+endif
+
+# Set STACKTOOL_foo.o=n to skip stack metadata validation for a file.
+# Set STACKTOOL=n to skip stack metadata validation for a directory.
+stacktool_obj = $(if $(patsubst n%,, \
+       $(STACKTOOL_$(basetarget).o)$(STACKTOOL)y), \
+       $(__stacktool_obj))
+cmd_stacktool = $(if $(patsubst n%,, \
+       $(STACKTOOL_$(basetarget).o)$(STACKTOOL)y), \
+       $(__stacktool_obj) $(stacktool_args) "$(@)";)
+
+endif # CONFIG_STACK_VALIDATION
+
 define rule_cc_o_c
        $(call echo-cmd,checksrc) $(cmd_checksrc)                         \
        $(call echo-cmd,cc_o_c) $(cmd_cc_o_c);                            \
        $(cmd_modversions)                                                \
+       $(cmd_stacktool)                                                  \
        $(call echo-cmd,record_mcount)                                    \
        $(cmd_record_mcount)                                              \
        scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' >    \
@@ -253,14 +274,23 @@ define rule_cc_o_c
        mv -f $(dot-target).tmp $(dot-target).cmd
 endef
 
+define rule_as_o_S
+       $(call echo-cmd,as_o_S) $(cmd_as_o_S);                            \
+       $(cmd_stacktool)                                                  \
+       scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,as_o_S)' >    \
+                                                     $(dot-target).tmp;  \
+       rm -f $(depfile);                                                 \
+       mv -f $(dot-target).tmp $(dot-target).cmd
+endef
+
 # Built-in and composite module parts
-$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
+$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(stacktool_obj) FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
 
 # Single-part modules are special since we need to mark them in $(MODVERDIR)
 
-$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
+$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) 
$(stacktool_obj) FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
        @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
@@ -290,8 +320,8 @@ $(obj)/%.s: $(src)/%.S FORCE
 quiet_cmd_as_o_S = AS $(quiet_modtag)  $@
 cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 
-$(obj)/%.o: $(src)/%.S FORCE
-       $(call if_changed_dep,as_o_S)
+$(obj)/%.o: $(src)/%.S $(stacktool_obj) FORCE
+       $(call if_changed_rule,as_o_S)
 
 targets += $(real-objs-y) $(real-objs-m) $(lib-y)
 targets += $(extra-y) $(MAKECMDGOALS) $(always)
diff --git a/scripts/mod/Makefile b/scripts/mod/Makefile
index c11212f..496184d 100644
--- a/scripts/mod/Makefile
+++ b/scripts/mod/Makefile
@@ -1,3 +1,5 @@
+STACKTOOL      := n
+
 hostprogs-y    := modpost mk_elfconfig
 always         := $(hostprogs-y) empty.o
 
-- 
2.4.3

Reply via email to