From f02003c860d921171be4a27e2893766eb3bc6871 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 14 Sep 2021 12:49:03 -0700 Subject: [PATCH 1/6] hardening: Avoid harmless Clang option under CONFIG_INIT_STACK_ALL_ZERO Currently under Clang, CC_HAS_AUTO_VAR_INIT_ZERO requires an extra -enable flag compared to CC_HAS_AUTO_VAR_INIT_PATTERN. GCC 12[1] will not, and will happily ignore the Clang-specific flag. However, its presence on the command-line is both cumbersome and confusing. Due to GCC's tolerant behavior, though, we can continue to use a single Kconfig cc-option test for the feature on both compilers, but then drop the Clang-specific option in the Makefile. In other words, this patch does not change anything other than making the compiler command line shorter once GCC supports -ftrivial-auto-var-init=zero. [1] https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=a25e0b5e6ac8a77a71c229e0a7b744603365b0e9 Cc: Greg Kroah-Hartman Cc: Masahiro Yamada Cc: llvm@lists.linux.dev Fixes: dcb7c0b9461c ("hardening: Clarify Kconfig text for auto-var-init") Suggested-by: Will Deacon Link: https://lore.kernel.org/lkml/20210914102837.6172-1-will@kernel.org/ Reviewed-by: Nick Desaulniers Reviewed-by: Nathan Chancellor Acked-by: Will Deacon Signed-off-by: Kees Cook --- Makefile | 6 +++--- security/Kconfig.hardening | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 5e7c1d854441..e20baaa838b1 100644 --- a/Makefile +++ b/Makefile @@ -831,12 +831,12 @@ endif # Initialize all stack variables with a zero value. ifdef CONFIG_INIT_STACK_ALL_ZERO -# Future support for zero initialization is still being debated, see -# https://bugs.llvm.org/show_bug.cgi?id=45497. These flags are subject to being -# renamed or dropped. KBUILD_CFLAGS += -ftrivial-auto-var-init=zero +ifdef CONFIG_CC_IS_CLANG +# https://bugs.llvm.org/show_bug.cgi?id=45497 KBUILD_CFLAGS += -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang endif +endif # While VLAs have been removed, GCC produces unreachable stack probes # for the randomize_kstack_offset feature. Disable it for all compilers. diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening index 90cbaff86e13..ded17b8abce2 100644 --- a/security/Kconfig.hardening +++ b/security/Kconfig.hardening @@ -23,13 +23,16 @@ config CC_HAS_AUTO_VAR_INIT_PATTERN def_bool $(cc-option,-ftrivial-auto-var-init=pattern) config CC_HAS_AUTO_VAR_INIT_ZERO + # GCC ignores the -enable flag, so we can test for the feature with + # a single invocation using the flag, but drop it as appropriate in + # the Makefile, depending on the presence of Clang. def_bool $(cc-option,-ftrivial-auto-var-init=zero -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang) choice prompt "Initialize kernel stack variables at function entry" default GCC_PLUGIN_STRUCTLEAK_BYREF_ALL if COMPILE_TEST && GCC_PLUGINS default INIT_STACK_ALL_PATTERN if COMPILE_TEST && CC_HAS_AUTO_VAR_INIT_PATTERN - default INIT_STACK_ALL_ZERO if CC_HAS_AUTO_VAR_INIT_PATTERN + default INIT_STACK_ALL_ZERO if CC_HAS_AUTO_VAR_INIT_ZERO default INIT_STACK_NONE help This option enables initialization of stack variables at From 4c78c7271f34befd96d2d221c8c356be1bbf132e Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 22 Sep 2021 20:26:32 +0200 Subject: [PATCH 2/6] gcc-plugins: remove support for GCC 4.9 and older The minimum GCC version has been bumped to 5.1, so we can get rid of all the compatibility code for anything older than that. Signed-off-by: Ard Biesheuvel Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20210922182632.633394-1-ardb@kernel.org --- scripts/gcc-plugins/gcc-common.h | 131 +----------------- .../gcc-plugins/gcc-generate-gimple-pass.h | 19 --- scripts/gcc-plugins/gcc-generate-ipa-pass.h | 19 --- scripts/gcc-plugins/gcc-generate-rtl-pass.h | 19 --- .../gcc-generate-simple_ipa-pass.h | 19 --- scripts/gcc-plugins/structleak_plugin.c | 2 - 6 files changed, 1 insertion(+), 208 deletions(-) diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h index 0c087614fc3e..62bf1c07b8bf 100644 --- a/scripts/gcc-plugins/gcc-common.h +++ b/scripts/gcc-plugins/gcc-common.h @@ -27,9 +27,7 @@ #include "except.h" #include "function.h" #include "toplev.h" -#if BUILDING_GCC_VERSION >= 5000 #include "expr.h" -#endif #include "basic-block.h" #include "intl.h" #include "ggc.h" @@ -39,11 +37,7 @@ #include "params.h" #endif -#if BUILDING_GCC_VERSION <= 4009 -#include "pointer-set.h" -#else #include "hash-map.h" -#endif #if BUILDING_GCC_VERSION >= 7000 #include "memmodel.h" @@ -99,9 +93,7 @@ #include "gimple-ssa.h" #include "ssa-iterators.h" -#if BUILDING_GCC_VERSION >= 5000 #include "builtins.h" -#endif /* missing from basic_block.h... */ void debug_dominance_info(enum cdi_direction dir); @@ -152,125 +144,6 @@ struct register_pass_info NAME##_pass_info = { \ #define TODO_dump_func 0 #define TODO_dump_cgraph 0 -#if BUILDING_GCC_VERSION <= 4009 -#define TODO_verify_il 0 -#define AVAIL_INTERPOSABLE AVAIL_OVERWRITABLE - -#define section_name_prefix LTO_SECTION_NAME_PREFIX -#define fatal_error(loc, gmsgid, ...) fatal_error((gmsgid), __VA_ARGS__) - -rtx emit_move_insn(rtx x, rtx y); - -typedef struct rtx_def rtx_insn; - -static inline const char *get_decl_section_name(const_tree decl) -{ - if (DECL_SECTION_NAME(decl) == NULL_TREE) - return NULL; - - return TREE_STRING_POINTER(DECL_SECTION_NAME(decl)); -} - -static inline void set_decl_section_name(tree node, const char *value) -{ - if (value) - DECL_SECTION_NAME(node) = build_string(strlen(value) + 1, value); - else - DECL_SECTION_NAME(node) = NULL; -} -#endif - -#if BUILDING_GCC_VERSION == 4009 -typedef struct gimple_statement_asm gasm; -typedef struct gimple_statement_base gassign; -typedef struct gimple_statement_call gcall; -typedef struct gimple_statement_base gcond; -typedef struct gimple_statement_base gdebug; -typedef struct gimple_statement_base ggoto; -typedef struct gimple_statement_phi gphi; -typedef struct gimple_statement_base greturn; - -static inline gasm *as_a_gasm(gimple stmt) -{ - return as_a(stmt); -} - -static inline const gasm *as_a_const_gasm(const_gimple stmt) -{ - return as_a(stmt); -} - -static inline gassign *as_a_gassign(gimple stmt) -{ - return stmt; -} - -static inline const gassign *as_a_const_gassign(const_gimple stmt) -{ - return stmt; -} - -static inline gcall *as_a_gcall(gimple stmt) -{ - return as_a(stmt); -} - -static inline const gcall *as_a_const_gcall(const_gimple stmt) -{ - return as_a(stmt); -} - -static inline gcond *as_a_gcond(gimple stmt) -{ - return stmt; -} - -static inline const gcond *as_a_const_gcond(const_gimple stmt) -{ - return stmt; -} - -static inline gdebug *as_a_gdebug(gimple stmt) -{ - return stmt; -} - -static inline const gdebug *as_a_const_gdebug(const_gimple stmt) -{ - return stmt; -} - -static inline ggoto *as_a_ggoto(gimple stmt) -{ - return stmt; -} - -static inline const ggoto *as_a_const_ggoto(const_gimple stmt) -{ - return stmt; -} - -static inline gphi *as_a_gphi(gimple stmt) -{ - return as_a(stmt); -} - -static inline const gphi *as_a_const_gphi(const_gimple stmt) -{ - return as_a(stmt); -} - -static inline greturn *as_a_greturn(gimple stmt) -{ - return stmt; -} - -static inline const greturn *as_a_const_greturn(const_gimple stmt) -{ - return stmt; -} -#endif - #define TODO_ggc_collect 0 #define NODE_SYMBOL(node) (node) #define NODE_DECL(node) (node)->decl @@ -282,7 +155,7 @@ static inline opt_pass *get_pass_for_id(int id) return g->get_passes()->get_pass_for_id(id); } -#if BUILDING_GCC_VERSION >= 5000 && BUILDING_GCC_VERSION < 6000 +#if BUILDING_GCC_VERSION < 6000 /* gimple related */ template <> template <> @@ -292,7 +165,6 @@ inline bool is_a_helper::test(const_gimple gs) } #endif -#if BUILDING_GCC_VERSION >= 5000 #define TODO_verify_ssa TODO_verify_il #define TODO_verify_flow TODO_verify_il #define TODO_verify_stmts TODO_verify_il @@ -533,7 +405,6 @@ static inline void ipa_remove_stmt_references(symtab_node *referring_node, gimpl { referring_node->remove_stmt_references(stmt); } -#endif #if BUILDING_GCC_VERSION < 6000 #define get_inner_reference(exp, pbitsize, pbitpos, poffset, pmode, punsignedp, preversep, pvolatilep, keep_aligning) \ diff --git a/scripts/gcc-plugins/gcc-generate-gimple-pass.h b/scripts/gcc-plugins/gcc-generate-gimple-pass.h index 51780828734e..503c07496396 100644 --- a/scripts/gcc-plugins/gcc-generate-gimple-pass.h +++ b/scripts/gcc-plugins/gcc-generate-gimple-pass.h @@ -78,17 +78,6 @@ static const pass_data _PASS_NAME_PASS_DATA = { .type = GIMPLE_PASS, .name = _PASS_NAME_NAME, .optinfo_flags = OPTGROUP_NONE, -#if BUILDING_GCC_VERSION >= 5000 -#elif BUILDING_GCC_VERSION == 4009 - .has_gate = _HAS_GATE, - .has_execute = _HAS_EXECUTE, -#else - .gate = _GATE, - .execute = _EXECUTE, - .sub = NULL, - .next = NULL, - .static_pass_number = 0, -#endif .tv_id = TV_NONE, .properties_required = PROPERTIES_REQUIRED, .properties_provided = PROPERTIES_PROVIDED, @@ -102,21 +91,13 @@ public: _PASS_NAME_PASS() : gimple_opt_pass(_PASS_NAME_PASS_DATA, g) {} #ifndef NO_GATE -#if BUILDING_GCC_VERSION >= 5000 virtual bool gate(function *) { return _GATE(); } -#else - virtual bool gate(void) { return _GATE(); } -#endif #endif virtual opt_pass * clone () { return new _PASS_NAME_PASS(); } #ifndef NO_EXECUTE -#if BUILDING_GCC_VERSION >= 5000 virtual unsigned int execute(function *) { return _EXECUTE(); } -#else - virtual unsigned int execute(void) { return _EXECUTE(); } -#endif }; } diff --git a/scripts/gcc-plugins/gcc-generate-ipa-pass.h b/scripts/gcc-plugins/gcc-generate-ipa-pass.h index c34ffec035bf..1e7f064e8f6e 100644 --- a/scripts/gcc-plugins/gcc-generate-ipa-pass.h +++ b/scripts/gcc-plugins/gcc-generate-ipa-pass.h @@ -146,17 +146,6 @@ static const pass_data _PASS_NAME_PASS_DATA = { .type = IPA_PASS, .name = _PASS_NAME_NAME, .optinfo_flags = OPTGROUP_NONE, -#if BUILDING_GCC_VERSION >= 5000 -#elif BUILDING_GCC_VERSION == 4009 - .has_gate = _HAS_GATE, - .has_execute = _HAS_EXECUTE, -#else - .gate = _GATE, - .execute = _EXECUTE, - .sub = NULL, - .next = NULL, - .static_pass_number = 0, -#endif .tv_id = TV_NONE, .properties_required = PROPERTIES_REQUIRED, .properties_provided = PROPERTIES_PROVIDED, @@ -180,20 +169,12 @@ public: _VARIABLE_TRANSFORM) {} #ifndef NO_GATE -#if BUILDING_GCC_VERSION >= 5000 virtual bool gate(function *) { return _GATE(); } -#else - virtual bool gate(void) { return _GATE(); } -#endif virtual opt_pass *clone() { return new _PASS_NAME_PASS(); } #ifndef NO_EXECUTE -#if BUILDING_GCC_VERSION >= 5000 virtual unsigned int execute(function *) { return _EXECUTE(); } -#else - virtual unsigned int execute(void) { return _EXECUTE(); } -#endif #endif }; } diff --git a/scripts/gcc-plugins/gcc-generate-rtl-pass.h b/scripts/gcc-plugins/gcc-generate-rtl-pass.h index d14614f4b139..7cd46e8d5049 100644 --- a/scripts/gcc-plugins/gcc-generate-rtl-pass.h +++ b/scripts/gcc-plugins/gcc-generate-rtl-pass.h @@ -78,17 +78,6 @@ static const pass_data _PASS_NAME_PASS_DATA = { .type = RTL_PASS, .name = _PASS_NAME_NAME, .optinfo_flags = OPTGROUP_NONE, -#if BUILDING_GCC_VERSION >= 5000 -#elif BUILDING_GCC_VERSION == 4009 - .has_gate = _HAS_GATE, - .has_execute = _HAS_EXECUTE, -#else - .gate = _GATE, - .execute = _EXECUTE, - .sub = NULL, - .next = NULL, - .static_pass_number = 0, -#endif .tv_id = TV_NONE, .properties_required = PROPERTIES_REQUIRED, .properties_provided = PROPERTIES_PROVIDED, @@ -102,21 +91,13 @@ public: _PASS_NAME_PASS() : rtl_opt_pass(_PASS_NAME_PASS_DATA, g) {} #ifndef NO_GATE -#if BUILDING_GCC_VERSION >= 5000 virtual bool gate(function *) { return _GATE(); } -#else - virtual bool gate(void) { return _GATE(); } -#endif #endif virtual opt_pass *clone() { return new _PASS_NAME_PASS(); } #ifndef NO_EXECUTE -#if BUILDING_GCC_VERSION >= 5000 virtual unsigned int execute(function *) { return _EXECUTE(); } -#else - virtual unsigned int execute(void) { return _EXECUTE(); } -#endif #endif }; } diff --git a/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h b/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h index ef6f4c2cb6fa..33093ccc947a 100644 --- a/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h +++ b/scripts/gcc-plugins/gcc-generate-simple_ipa-pass.h @@ -78,17 +78,6 @@ static const pass_data _PASS_NAME_PASS_DATA = { .type = SIMPLE_IPA_PASS, .name = _PASS_NAME_NAME, .optinfo_flags = OPTGROUP_NONE, -#if BUILDING_GCC_VERSION >= 5000 -#elif BUILDING_GCC_VERSION == 4009 - .has_gate = _HAS_GATE, - .has_execute = _HAS_EXECUTE, -#else - .gate = _GATE, - .execute = _EXECUTE, - .sub = NULL, - .next = NULL, - .static_pass_number = 0, -#endif .tv_id = TV_NONE, .properties_required = PROPERTIES_REQUIRED, .properties_provided = PROPERTIES_PROVIDED, @@ -102,21 +91,13 @@ public: _PASS_NAME_PASS() : simple_ipa_opt_pass(_PASS_NAME_PASS_DATA, g) {} #ifndef NO_GATE -#if BUILDING_GCC_VERSION >= 5000 virtual bool gate(function *) { return _GATE(); } -#else - virtual bool gate(void) { return _GATE(); } -#endif #endif virtual opt_pass *clone() { return new _PASS_NAME_PASS(); } #ifndef NO_EXECUTE -#if BUILDING_GCC_VERSION >= 5000 virtual unsigned int execute(function *) { return _EXECUTE(); } -#else - virtual unsigned int execute(void) { return _EXECUTE(); } -#endif #endif }; } diff --git a/scripts/gcc-plugins/structleak_plugin.c b/scripts/gcc-plugins/structleak_plugin.c index d7190e443a14..74e319288389 100644 --- a/scripts/gcc-plugins/structleak_plugin.c +++ b/scripts/gcc-plugins/structleak_plugin.c @@ -103,10 +103,8 @@ static void finish_type(void *event_data, void *data) if (type == NULL_TREE || type == error_mark_node) return; -#if BUILDING_GCC_VERSION >= 5000 if (TREE_CODE(type) == ENUMERAL_TYPE) return; -#endif if (TYPE_USERSPACE(type)) return; From 6eb4bd92c1cedcaadd65868b7ade396b422be4be Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Mon, 4 Oct 2021 09:29:33 -0700 Subject: [PATCH 3/6] kallsyms: strip LTO suffixes from static functions Similar to: commit 8b8e6b5d3b01 ("kallsyms: strip ThinLTO hashes from static functions") It's very common for compilers to modify the symbol name for static functions as part of optimizing transformations. That makes hooking static functions (that weren't inlined or DCE'd) with kprobes difficult. LLVM has yet another name mangling scheme used by thin LTO. Combine handling of the various schemes by truncating after the first '.'. Strip off these suffixes so that we can continue to hook such static functions. Clang releases prior to clang-13 would use '$' instead of '.' Link: https://reviews.llvm.org/rGc6e5c4654bd5045fe22a1a52779e48e2038a404c Reported-by: KE.LI(Lieke) Suggested-by: Nathan Chancellor Suggested-by: Padmanabha Srinivasaiah Suggested-by: Sami Tolvanen Reviewed-by: Nathan Chancellor Reviewed-by: Fangrui Song Reviewed-by: Sami Tolvanen Signed-off-by: Nick Desaulniers Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20211004162936.21961-1-ndesaulniers@google.com --- kernel/kallsyms.c | 50 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 0ba87982d017..3011bc33a5ba 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -164,26 +164,46 @@ static unsigned long kallsyms_sym_address(int idx) return kallsyms_relative_base - 1 - kallsyms_offsets[idx]; } -#if defined(CONFIG_CFI_CLANG) && defined(CONFIG_LTO_CLANG_THIN) -/* - * LLVM appends a hash to static function names when ThinLTO and CFI are - * both enabled, i.e. foo() becomes foo$707af9a22804d33c81801f27dcfe489b. - * This causes confusion and potentially breaks user space tools, so we - * strip the suffix from expanded symbol names. - */ -static inline bool cleanup_symbol_name(char *s) +static bool cleanup_symbol_name(char *s) { char *res; - res = strrchr(s, '$'); - if (res) - *res = '\0'; + if (!IS_ENABLED(CONFIG_LTO_CLANG)) + return false; - return res != NULL; + /* + * LLVM appends various suffixes for local functions and variables that + * must be promoted to global scope as part of LTO. This can break + * hooking of static functions with kprobes. '.' is not a valid + * character in an identifier in C. Suffixes observed: + * - foo.llvm.[0-9a-f]+ + * - foo.[0-9a-f]+ + * - foo.[0-9a-f]+.cfi_jt + */ + res = strchr(s, '.'); + if (res) { + *res = '\0'; + return true; + } + + if (!IS_ENABLED(CONFIG_CFI_CLANG) || + !IS_ENABLED(CONFIG_LTO_CLANG_THIN) || + CONFIG_CLANG_VERSION >= 130000) + return false; + + /* + * Prior to LLVM 13, the following suffixes were observed when thinLTO + * and CFI are both enabled: + * - foo$[0-9]+ + */ + res = strrchr(s, '$'); + if (res) { + *res = '\0'; + return true; + } + + return false; } -#else -static inline bool cleanup_symbol_name(char *s) { return false; } -#endif /* Lookup the address for this symbol. Returns 0 if not found. */ unsigned long kallsyms_lookup_name(const char *name) From 8bd51a2ba3c3bb81a693fff17e983d02d914c14c Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 20 Oct 2021 10:35:53 -0700 Subject: [PATCH 4/6] gcc-plugins: Explicitly document purpose and deprecation schedule GCC plugins should only exist when some compiler feature needs to be proven but does not exist in either GCC nor Clang. For example, if a desired feature is already in Clang, it should be added to GCC upstream. Document this explicitly. Additionally, mark the plugins with matching upstream GCC features as removable past their respective GCC versions. Cc: Masahiro Yamada Cc: Michal Marek Cc: Nick Desaulniers Cc: Jonathan Corbet Cc: James Morris Cc: "Serge E. Hallyn" Cc: Nathan Chancellor Cc: linux-hardening@vger.kernel.org Cc: linux-kbuild@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: linux-security-module@vger.kernel.org Cc: llvm@lists.linux.dev Signed-off-by: Kees Cook Reviewed-by: Nathan Chancellor Reviewed-by: Miguel Ojeda Acked-by: Nick Desaulniers Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20211020173554.38122-2-keescook@chromium.org --- Documentation/kbuild/gcc-plugins.rst | 26 ++++++++++++++++++++++++++ scripts/gcc-plugins/Kconfig | 4 ++-- security/Kconfig.hardening | 9 ++++++--- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/Documentation/kbuild/gcc-plugins.rst b/Documentation/kbuild/gcc-plugins.rst index 3349966f213d..4b28c7a4032f 100644 --- a/Documentation/kbuild/gcc-plugins.rst +++ b/Documentation/kbuild/gcc-plugins.rst @@ -32,6 +32,32 @@ This infrastructure was ported from grsecurity [6]_ and PaX [7]_. .. [7] https://pax.grsecurity.net/ +Purpose +======= + +GCC plugins are designed to provide a place to experiment with potential +compiler features that are neither in GCC nor Clang upstream. Once +their utility is proven, the goal is to upstream the feature into GCC +(and Clang), and then to finally remove them from the kernel once the +feature is available in all supported versions of GCC. + +Specifically, new plugins should implement only features that have no +upstream compiler support (in either GCC or Clang). + +When a feature exists in Clang but not GCC, effort should be made to +bring the feature to upstream GCC (rather than just as a kernel-specific +GCC plugin), so the entire ecosystem can benefit from it. + +Similarly, even if a feature provided by a GCC plugin does *not* exist +in Clang, but the feature is proven to be useful, effort should be spent +to upstream the feature to GCC (and Clang). + +After a feature is available in upstream GCC, the plugin will be made +unbuildable for the corresponding GCC version (and later). Once all +kernel-supported versions of GCC provide the feature, the plugin will +be removed from the kernel. + + Files ===== diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig index ab9eb4cbe33a..7c7ba3b0d3cd 100644 --- a/scripts/gcc-plugins/Kconfig +++ b/scripts/gcc-plugins/Kconfig @@ -37,6 +37,8 @@ config GCC_PLUGIN_CYC_COMPLEXITY config GCC_PLUGIN_SANCOV bool + # Plugin can be removed once the kernel only supports GCC 6+ + depends on !CC_HAS_SANCOV_TRACE_PC help This plugin inserts a __sanitizer_cov_trace_pc() call at the start of basic blocks. It supports all gcc versions with plugin support (from @@ -83,8 +85,6 @@ config GCC_PLUGIN_RANDSTRUCT the existing seed and will be removed by a make mrproper or make distclean. - Note that the implementation requires gcc 4.7 or newer. - This plugin was ported from grsecurity/PaX. More information at: * https://grsecurity.net/ * https://pax.grsecurity.net/ diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening index ded17b8abce2..d051f8ceefdd 100644 --- a/security/Kconfig.hardening +++ b/security/Kconfig.hardening @@ -56,7 +56,8 @@ choice config GCC_PLUGIN_STRUCTLEAK_USER bool "zero-init structs marked for userspace (weak)" - depends on GCC_PLUGINS + # Plugin can be removed once the kernel only supports GCC 12+ + depends on GCC_PLUGINS && !CC_HAS_AUTO_VAR_INIT_ZERO select GCC_PLUGIN_STRUCTLEAK help Zero-initialize any structures on the stack containing @@ -67,7 +68,8 @@ choice config GCC_PLUGIN_STRUCTLEAK_BYREF bool "zero-init structs passed by reference (strong)" - depends on GCC_PLUGINS + # Plugin can be removed once the kernel only supports GCC 12+ + depends on GCC_PLUGINS && !CC_HAS_AUTO_VAR_INIT_ZERO depends on !(KASAN && KASAN_STACK) select GCC_PLUGIN_STRUCTLEAK help @@ -85,7 +87,8 @@ choice config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL bool "zero-init everything passed by reference (very strong)" - depends on GCC_PLUGINS + # Plugin can be removed once the kernel only supports GCC 12+ + depends on GCC_PLUGINS && !CC_HAS_AUTO_VAR_INIT_ZERO depends on !(KASAN && KASAN_STACK) select GCC_PLUGIN_STRUCTLEAK help From b4d89579ccb1ad5ffcdb3430933ce1e31a009ec7 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 20 Oct 2021 10:35:54 -0700 Subject: [PATCH 5/6] gcc-plugins: Remove cyc_complexity This plugin has no impact on the resulting binary, is disabled under COMPILE_TEST, and is not enabled on any builds I'm aware of. Additionally, given the clarified purpose of GCC plugins in the kernel, remove cyc_complexity. Cc: Masahiro Yamada Cc: Michal Marek Cc: Nick Desaulniers Cc: Jonathan Corbet Cc: linux-hardening@vger.kernel.org Cc: linux-kbuild@vger.kernel.org Cc: linux-doc@vger.kernel.org Signed-off-by: Kees Cook Reviewed-by: Miguel Ojeda Reviewed-by: Nathan Chancellor Acked-by: Nick Desaulniers Acked-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20211020173554.38122-3-keescook@chromium.org --- Documentation/kbuild/gcc-plugins.rst | 2 - scripts/Makefile.gcc-plugins | 2 - scripts/gcc-plugins/Kconfig | 16 ----- scripts/gcc-plugins/cyc_complexity_plugin.c | 69 --------------------- 4 files changed, 89 deletions(-) delete mode 100644 scripts/gcc-plugins/cyc_complexity_plugin.c diff --git a/Documentation/kbuild/gcc-plugins.rst b/Documentation/kbuild/gcc-plugins.rst index 4b28c7a4032f..0ba76719f1b9 100644 --- a/Documentation/kbuild/gcc-plugins.rst +++ b/Documentation/kbuild/gcc-plugins.rst @@ -96,7 +96,6 @@ Enable the GCC plugin infrastructure and some plugin(s) you want to use in the kernel config:: CONFIG_GCC_PLUGINS=y - CONFIG_GCC_PLUGIN_CYC_COMPLEXITY=y CONFIG_GCC_PLUGIN_LATENT_ENTROPY=y ... @@ -115,4 +114,3 @@ The GCC plugins are in scripts/gcc-plugins/. You need to put plugin source files right under scripts/gcc-plugins/. Creating subdirectories is not supported. It must be added to scripts/gcc-plugins/Makefile, scripts/Makefile.gcc-plugins and a relevant Kconfig file. -See the cyc_complexity_plugin.c (CONFIG_GCC_PLUGIN_CYC_COMPLEXITY) GCC plugin. diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins index 952e46876329..6583ecf2e674 100644 --- a/scripts/Makefile.gcc-plugins +++ b/scripts/Makefile.gcc-plugins @@ -1,7 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -gcc-plugin-$(CONFIG_GCC_PLUGIN_CYC_COMPLEXITY) += cyc_complexity_plugin.so - gcc-plugin-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += latent_entropy_plugin.so gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) \ += -DLATENT_ENTROPY_PLUGIN diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig index 7c7ba3b0d3cd..51d81c3f03d6 100644 --- a/scripts/gcc-plugins/Kconfig +++ b/scripts/gcc-plugins/Kconfig @@ -19,22 +19,6 @@ menuconfig GCC_PLUGINS if GCC_PLUGINS -config GCC_PLUGIN_CYC_COMPLEXITY - bool "Compute the cyclomatic complexity of a function" if EXPERT - depends on !COMPILE_TEST # too noisy - help - The complexity M of a function's control flow graph is defined as: - M = E - N + 2P - where - - E = the number of edges - N = the number of nodes - P = the number of connected components (exit nodes). - - Enabling this plugin reports the complexity to stderr during the - build. It mainly serves as a simple example of how to create a - gcc plugin for the kernel. - config GCC_PLUGIN_SANCOV bool # Plugin can be removed once the kernel only supports GCC 6+ diff --git a/scripts/gcc-plugins/cyc_complexity_plugin.c b/scripts/gcc-plugins/cyc_complexity_plugin.c deleted file mode 100644 index 73124c2b3edd..000000000000 --- a/scripts/gcc-plugins/cyc_complexity_plugin.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2011-2016 by Emese Revfy - * Licensed under the GPL v2, or (at your option) v3 - * - * Homepage: - * https://github.com/ephox-gcc-plugins/cyclomatic_complexity - * - * https://en.wikipedia.org/wiki/Cyclomatic_complexity - * The complexity M is then defined as: - * M = E - N + 2P - * where - * - * E = the number of edges of the graph - * N = the number of nodes of the graph - * P = the number of connected components (exit nodes). - * - * Usage (4.5 - 5): - * $ make clean; make run - */ - -#include "gcc-common.h" - -__visible int plugin_is_GPL_compatible; - -static struct plugin_info cyc_complexity_plugin_info = { - .version = "20160225", - .help = "Cyclomatic Complexity\n", -}; - -static unsigned int cyc_complexity_execute(void) -{ - int complexity; - expanded_location xloc; - - /* M = E - N + 2P */ - complexity = n_edges_for_fn(cfun) - n_basic_blocks_for_fn(cfun) + 2; - - xloc = expand_location(DECL_SOURCE_LOCATION(current_function_decl)); - fprintf(stderr, "Cyclomatic Complexity %d %s:%s\n", complexity, - xloc.file, DECL_NAME_POINTER(current_function_decl)); - - return 0; -} - -#define PASS_NAME cyc_complexity - -#define NO_GATE -#define TODO_FLAGS_FINISH TODO_dump_func - -#include "gcc-generate-gimple-pass.h" - -__visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) -{ - const char * const plugin_name = plugin_info->base_name; - - PASS_INFO(cyc_complexity, "ssa", 1, PASS_POS_INSERT_AFTER); - - if (!plugin_default_version_check(version, &gcc_version)) { - error(G_("incompatible gcc/plugin versions")); - return 1; - } - - register_callback(plugin_name, PLUGIN_INFO, NULL, - &cyc_complexity_plugin_info); - register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, - &cyc_complexity_pass_info); - - return 0; -} From 6425392acf24b6d469932dd1b217dc7b20d6447f Mon Sep 17 00:00:00 2001 From: Ye Guojin Date: Tue, 19 Oct 2021 08:29:10 +0000 Subject: [PATCH 6/6] gcc-plugins: remove duplicate include in gcc-common.h 'tree-ssa-operands.h' included in 'gcc-common.h' is duplicated. it's also included at line 56. Reported-by: Zeal Robot Signed-off-by: Ye Guojin Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20211019082910.998257-1-ye.guojin@zte.com.cn --- scripts/gcc-plugins/gcc-common.h | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h index 62bf1c07b8bf..9a1895747b15 100644 --- a/scripts/gcc-plugins/gcc-common.h +++ b/scripts/gcc-plugins/gcc-common.h @@ -86,7 +86,6 @@ #include "stmt.h" #include "gimplify.h" #include "gimple.h" -#include "tree-ssa-operands.h" #include "tree-phinodes.h" #include "tree-cfg.h" #include "gimple-iterator.h"