diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/Makefile.compiler | 2 | ||||
-rw-r--r-- | scripts/Makefile.gcc-plugins | 16 | ||||
-rw-r--r-- | scripts/Makefile.kcov | 3 | ||||
-rwxr-xr-x | scripts/checkpatch.pl | 35 | ||||
-rw-r--r-- | scripts/gcc-plugins/Kconfig | 10 | ||||
-rw-r--r-- | scripts/gcc-plugins/gcc-common.h | 77 | ||||
-rw-r--r-- | scripts/gcc-plugins/randomize_layout_plugin.c | 22 | ||||
-rw-r--r-- | scripts/gcc-plugins/sancov_plugin.c | 134 | ||||
-rw-r--r-- | scripts/gcc-plugins/structleak_plugin.c | 257 | ||||
-rw-r--r-- | scripts/gdb/linux/cpus.py | 4 | ||||
-rw-r--r-- | scripts/gdb/linux/symbols.py | 38 | ||||
-rw-r--r-- | scripts/gdb/linux/utils.py | 22 | ||||
-rwxr-xr-x | scripts/min-tool-version.sh | 6 | ||||
-rw-r--r-- | scripts/spelling.txt | 2 |
14 files changed, 120 insertions, 508 deletions
diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler index 65cfa72e376b..ef91910de265 100644 --- a/scripts/Makefile.compiler +++ b/scripts/Makefile.compiler @@ -60,7 +60,7 @@ cc-option-yn = $(if $(call cc-option,$1),y,n) cc-disable-warning = $(call cc-option,-Wno-$(strip $1)) # gcc-min-version -# Usage: cflags-$(call gcc-min-version, 70100) += -foo +# Usage: cflags-$(call gcc-min-version, 110100) += -foo gcc-min-version = $(call test-ge, $(CONFIG_GCC_VERSION), $1) # clang-min-version diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins index e50dc931be49..435ab3f0ec44 100644 --- a/scripts/Makefile.gcc-plugins +++ b/scripts/Makefile.gcc-plugins @@ -8,20 +8,6 @@ ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY endif export DISABLE_LATENT_ENTROPY_PLUGIN -gcc-plugin-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += structleak_plugin.so -gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_VERBOSE) \ - += -fplugin-arg-structleak_plugin-verbose -gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF) \ - += -fplugin-arg-structleak_plugin-byref -gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL) \ - += -fplugin-arg-structleak_plugin-byref-all -ifdef CONFIG_GCC_PLUGIN_STRUCTLEAK - DISABLE_STRUCTLEAK_PLUGIN += -fplugin-arg-structleak_plugin-disable -endif -export DISABLE_STRUCTLEAK_PLUGIN -gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) \ - += -DSTRUCTLEAK_PLUGIN - gcc-plugin-$(CONFIG_GCC_PLUGIN_STACKLEAK) += stackleak_plugin.so gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STACKLEAK) \ += -DSTACKLEAK_PLUGIN @@ -46,8 +32,6 @@ KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) # Some plugins are enabled outside of this Makefile, but they still need to # be included in GCC_PLUGIN so they can get built. -gcc-plugin-external-$(CONFIG_GCC_PLUGIN_SANCOV) \ - += sancov_plugin.so gcc-plugin-external-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) \ += randomize_layout_plugin.so diff --git a/scripts/Makefile.kcov b/scripts/Makefile.kcov index 67e8cfe3474b..01616472f43e 100644 --- a/scripts/Makefile.kcov +++ b/scripts/Makefile.kcov @@ -1,6 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -kcov-flags-$(CONFIG_CC_HAS_SANCOV_TRACE_PC) += -fsanitize-coverage=trace-pc +kcov-flags-y += -fsanitize-coverage=trace-pc kcov-flags-$(CONFIG_KCOV_ENABLE_COMPARISONS) += -fsanitize-coverage=trace-cmp -kcov-flags-$(CONFIG_GCC_PLUGIN_SANCOV) += -fplugin=$(objtree)/scripts/gcc-plugins/sancov_plugin.so export CFLAGS_KCOV := $(kcov-flags-y) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 966813c2573c..664f7b7a622c 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -151,6 +151,24 @@ EOM exit($exitcode); } +my $DO_WHILE_0_ADVICE = q{ + do {} while (0) advice is over-stated in a few situations: + + The more obvious case is macros, like MODULE_PARM_DESC, invoked at + file-scope, where C disallows code (it must be in functions). See + $exceptions if you have one to add by name. + + More troublesome is declarative macros used at top of new scope, + like DECLARE_PER_CPU. These might just compile with a do-while-0 + wrapper, but would be incorrect. Most of these are handled by + detecting struct,union,etc declaration primitives in $exceptions. + + Theres also macros called inside an if (block), which "return" an + expression. These cannot do-while, and need a ({}) wrapper. + + Enjoy this qualification while we work to improve our heuristics. +}; + sub uniq { my %seen; return grep { !$seen{$_}++ } @_; @@ -5885,9 +5903,9 @@ sub process { } } -# multi-statement macros should be enclosed in a do while loop, grab the -# first statement and ensure its the whole macro if its not enclosed -# in a known good container +# Usually multi-statement macros should be enclosed in a do {} while +# (0) loop. Grab the first statement and ensure its the whole macro +# if its not enclosed in a known good container if ($realfile !~ m@/vmlinux.lds.h$@ && $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) { my $ln = $linenr; @@ -5940,10 +5958,13 @@ sub process { my $exceptions = qr{ $Declare| + # named exceptions module_param_named| MODULE_PARM_DESC| DECLARE_PER_CPU| DEFINE_PER_CPU| + static_assert| + # declaration primitives __typeof__\(| union| struct| @@ -5978,11 +5999,11 @@ sub process { ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", "Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx"); } elsif ($dstat =~ /;/) { - ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", - "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx"); + WARN("MULTISTATEMENT_MACRO_USE_DO_WHILE", + "Non-declarative macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx\nBUT SEE:\n$DO_WHILE_0_ADVICE"); } else { ERROR("COMPLEX_MACRO", - "Macros with complex values should be enclosed in parentheses\n" . "$herectx"); + "Macros with complex values should be enclosed in parentheses\n" . "$herectx\nBUT SEE:\n$DO_WHILE_0_ADVICE"); } } @@ -6026,7 +6047,7 @@ sub process { } # check if this is an unused argument - if ($define_stmt !~ /\b$arg\b/) { + if ($define_stmt !~ /\b$arg\b/ && $define_stmt) { WARN("MACRO_ARG_UNUSED", "Argument '$arg' is not used in function-like macro\n" . "$herectx"); } diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig index 231f4a20d617..6b34ba19358d 100644 --- a/scripts/gcc-plugins/Kconfig +++ b/scripts/gcc-plugins/Kconfig @@ -19,16 +19,6 @@ menuconfig GCC_PLUGINS if GCC_PLUGINS -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 - gcc-4.5 on). It is based on the commit "Add fuzzing coverage support" - by Dmitry Vyukov <dvyukov@google.com>. - config GCC_PLUGIN_LATENT_ENTROPY bool "Generate some entropy during boot and runtime" help diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h index 3222c1070444..6cb6d1051815 100644 --- a/scripts/gcc-plugins/gcc-common.h +++ b/scripts/gcc-plugins/gcc-common.h @@ -3,11 +3,7 @@ #define GCC_COMMON_H_INCLUDED #include "bversion.h" -#if BUILDING_GCC_VERSION >= 6000 #include "gcc-plugin.h" -#else -#include "plugin.h" -#endif #include "plugin-version.h" #include "config.h" #include "system.h" @@ -39,9 +35,7 @@ #include "hash-map.h" -#if BUILDING_GCC_VERSION >= 7000 #include "memmodel.h" -#endif #include "emit-rtl.h" #include "debug.h" #include "target.h" @@ -74,9 +68,7 @@ #include "context.h" #include "tree-ssa-alias.h" #include "tree-ssa.h" -#if BUILDING_GCC_VERSION >= 7000 #include "tree-vrp.h" -#endif #include "tree-ssanames.h" #include "print-tree.h" #include "tree-eh.h" @@ -123,6 +115,38 @@ static inline tree build_const_char_string(int len, const char *str) return cstr; } +static inline void __add_type_attr(tree type, const char *attr, tree args) +{ + tree oldattr; + + if (type == NULL_TREE) + return; + oldattr = lookup_attribute(attr, TYPE_ATTRIBUTES(type)); + if (oldattr != NULL_TREE) { + gcc_assert(TREE_VALUE(oldattr) == args || TREE_VALUE(TREE_VALUE(oldattr)) == TREE_VALUE(args)); + return; + } + + TYPE_ATTRIBUTES(type) = copy_list(TYPE_ATTRIBUTES(type)); + TYPE_ATTRIBUTES(type) = tree_cons(get_identifier(attr), args, TYPE_ATTRIBUTES(type)); +} + +static inline void add_type_attr(tree type, const char *attr, tree args) +{ + tree main_variant = TYPE_MAIN_VARIANT(type); + + __add_type_attr(TYPE_CANONICAL(type), attr, args); + __add_type_attr(TYPE_CANONICAL(main_variant), attr, args); + __add_type_attr(main_variant, attr, args); + + for (type = TYPE_NEXT_VARIANT(main_variant); type; type = TYPE_NEXT_VARIANT(type)) { + if (!lookup_attribute(attr, TYPE_ATTRIBUTES(type))) + TYPE_ATTRIBUTES(type) = TYPE_ATTRIBUTES(main_variant); + + __add_type_attr(TYPE_CANONICAL(type), attr, args); + } +} + #define PASS_INFO(NAME, REF, ID, POS) \ struct register_pass_info NAME##_pass_info = { \ .pass = make_##NAME##_pass(), \ @@ -149,16 +173,6 @@ static inline opt_pass *get_pass_for_id(int id) return g->get_passes()->get_pass_for_id(id); } -#if BUILDING_GCC_VERSION < 6000 -/* gimple related */ -template <> -template <> -inline bool is_a_helper<const gassign *>::test(const_gimple gs) -{ - return gs->code == GIMPLE_ASSIGN; -} -#endif - #define TODO_verify_ssa TODO_verify_il #define TODO_verify_flow TODO_verify_il #define TODO_verify_stmts TODO_verify_il @@ -181,7 +195,6 @@ static inline const char *get_decl_section_name(const_tree decl) #define varpool_get_node(decl) varpool_node::get(decl) #define dump_varpool_node(file, node) (node)->dump(file) -#if BUILDING_GCC_VERSION >= 8000 #define cgraph_create_edge(caller, callee, call_stmt, count, freq) \ (caller)->create_edge((callee), (call_stmt), (count)) @@ -189,15 +202,6 @@ static inline const char *get_decl_section_name(const_tree decl) old_call_stmt, call_stmt, count, freq, reason) \ (caller)->create_edge_including_clones((callee), \ (old_call_stmt), (call_stmt), (count), (reason)) -#else -#define cgraph_create_edge(caller, callee, call_stmt, count, freq) \ - (caller)->create_edge((callee), (call_stmt), (count), (freq)) - -#define cgraph_create_edge_including_clones(caller, callee, \ - old_call_stmt, call_stmt, count, freq, reason) \ - (caller)->create_edge_including_clones((callee), \ - (old_call_stmt), (call_stmt), (count), (freq), (reason)) -#endif typedef struct cgraph_node *cgraph_node_ptr; typedef struct cgraph_edge *cgraph_edge_p; @@ -293,14 +297,12 @@ static inline void cgraph_call_edge_duplication_hooks(cgraph_edge *cs1, cgraph_e symtab->call_edge_duplication_hooks(cs1, cs2); } -#if BUILDING_GCC_VERSION >= 6000 typedef gimple *gimple_ptr; typedef const gimple *const_gimple_ptr; #define gimple gimple_ptr #define const_gimple const_gimple_ptr #undef CONST_CAST_GIMPLE #define CONST_CAST_GIMPLE(X) CONST_CAST(gimple, (X)) -#endif /* gimple related */ static inline gimple gimple_build_assign_with_ops(enum tree_code subcode, tree lhs, tree op1, tree op2 MEM_STAT_DECL) @@ -400,15 +402,7 @@ static inline void ipa_remove_stmt_references(symtab_node *referring_node, gimpl referring_node->remove_stmt_references(stmt); } -#if BUILDING_GCC_VERSION < 6000 -#define get_inner_reference(exp, pbitsize, pbitpos, poffset, pmode, punsignedp, preversep, pvolatilep, keep_aligning) \ - get_inner_reference(exp, pbitsize, pbitpos, poffset, pmode, punsignedp, pvolatilep, keep_aligning) -#define gen_rtx_set(ARG0, ARG1) gen_rtx_SET(VOIDmode, (ARG0), (ARG1)) -#endif - -#if BUILDING_GCC_VERSION >= 6000 #define gen_rtx_set(ARG0, ARG1) gen_rtx_SET((ARG0), (ARG1)) -#endif #ifdef __cplusplus static inline void debug_tree(const_tree t) @@ -425,15 +419,8 @@ static inline void debug_gimple_stmt(const_gimple s) #define debug_gimple_stmt(s) debug_gimple_stmt(CONST_CAST_GIMPLE(s)) #endif -#if BUILDING_GCC_VERSION >= 7000 #define get_inner_reference(exp, pbitsize, pbitpos, poffset, pmode, punsignedp, preversep, pvolatilep, keep_aligning) \ get_inner_reference(exp, pbitsize, pbitpos, poffset, pmode, punsignedp, preversep, pvolatilep) -#endif - -#if BUILDING_GCC_VERSION < 7000 -#define SET_DECL_ALIGN(decl, align) DECL_ALIGN(decl) = (align) -#define SET_DECL_MODE(decl, mode) DECL_MODE(decl) = (mode) -#endif #if BUILDING_GCC_VERSION >= 14000 #define last_stmt(x) last_nondebug_stmt(x) diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c index 971a1908a8cc..ff65a4f87f24 100644 --- a/scripts/gcc-plugins/randomize_layout_plugin.c +++ b/scripts/gcc-plugins/randomize_layout_plugin.c @@ -73,6 +73,9 @@ static tree handle_randomize_layout_attr(tree *node, tree name, tree args, int f if (TYPE_P(*node)) { type = *node; + } else if (TREE_CODE(*node) == FIELD_DECL) { + *no_add_attrs = false; + return NULL_TREE; } else { gcc_assert(TREE_CODE(*node) == TYPE_DECL); type = TREE_TYPE(*node); @@ -348,15 +351,14 @@ static int relayout_struct(tree type) TREE_CHAIN(newtree[i]) = newtree[i+1]; TREE_CHAIN(newtree[num_fields - 1]) = NULL_TREE; + add_type_attr(type, "randomize_performed", NULL_TREE); + add_type_attr(type, "designated_init", NULL_TREE); + if (has_flexarray) + add_type_attr(type, "has_flexarray", NULL_TREE); + main_variant = TYPE_MAIN_VARIANT(type); - for (variant = main_variant; variant; variant = TYPE_NEXT_VARIANT(variant)) { + for (variant = main_variant; variant; variant = TYPE_NEXT_VARIANT(variant)) TYPE_FIELDS(variant) = newtree[0]; - TYPE_ATTRIBUTES(variant) = copy_list(TYPE_ATTRIBUTES(variant)); - TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("randomize_performed"), NULL_TREE, TYPE_ATTRIBUTES(variant)); - TYPE_ATTRIBUTES(variant) = tree_cons(get_identifier("designated_init"), NULL_TREE, TYPE_ATTRIBUTES(variant)); - if (has_flexarray) - TYPE_ATTRIBUTES(type) = tree_cons(get_identifier("has_flexarray"), NULL_TREE, TYPE_ATTRIBUTES(type)); - } /* * force a re-layout of the main variant @@ -424,10 +426,8 @@ static void randomize_type(tree type) if (lookup_attribute("randomize_layout", TYPE_ATTRIBUTES(TYPE_MAIN_VARIANT(type))) || is_pure_ops_struct(type)) relayout_struct(type); - for (variant = TYPE_MAIN_VARIANT(type); variant; variant = TYPE_NEXT_VARIANT(variant)) { - TYPE_ATTRIBUTES(type) = copy_list(TYPE_ATTRIBUTES(type)); - TYPE_ATTRIBUTES(type) = tree_cons(get_identifier("randomize_considered"), NULL_TREE, TYPE_ATTRIBUTES(type)); - } + add_type_attr(type, "randomize_considered", NULL_TREE); + #ifdef __DEBUG_PLUGIN fprintf(stderr, "Marking randomize_considered on struct %s\n", ORIG_TYPE_NAME(type)); #ifdef __DEBUG_VERBOSE diff --git a/scripts/gcc-plugins/sancov_plugin.c b/scripts/gcc-plugins/sancov_plugin.c deleted file mode 100644 index b76cb9c42cec..000000000000 --- a/scripts/gcc-plugins/sancov_plugin.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2011-2016 by Emese Revfy <re.emese@gmail.com> - * Licensed under the GPL v2, or (at your option) v3 - * - * Homepage: - * https://github.com/ephox-gcc-plugins/sancov - * - * This plugin inserts a __sanitizer_cov_trace_pc() call at the start of basic blocks. - * It supports all gcc versions with plugin support (from gcc-4.5 on). - * It is based on the commit "Add fuzzing coverage support" by Dmitry Vyukov <dvyukov@google.com>. - * - * You can read about it more here: - * https://gcc.gnu.org/viewcvs/gcc?limit_changes=0&view=revision&revision=231296 - * https://lwn.net/Articles/674854/ - * https://github.com/google/syzkaller - * https://lwn.net/Articles/677764/ - * - * Usage: - * make run - */ - -#include "gcc-common.h" - -__visible int plugin_is_GPL_compatible; - -tree sancov_fndecl; - -static struct plugin_info sancov_plugin_info = { - .version = PLUGIN_VERSION, - .help = "sancov plugin\n", -}; - -static unsigned int sancov_execute(void) -{ - basic_block bb; - - /* Remove this line when this plugin and kcov will be in the kernel. - if (!strcmp(DECL_NAME_POINTER(current_function_decl), DECL_NAME_POINTER(sancov_fndecl))) - return 0; - */ - - FOR_EACH_BB_FN(bb, cfun) { - const_gimple stmt; - gcall *gcall; - gimple_stmt_iterator gsi = gsi_after_labels(bb); - - if (gsi_end_p(gsi)) - continue; - - stmt = gsi_stmt(gsi); - gcall = as_a_gcall(gimple_build_call(sancov_fndecl, 0)); - gimple_set_location(gcall, gimple_location(stmt)); - gsi_insert_before(&gsi, gcall, GSI_SAME_STMT); - } - return 0; -} - -#define PASS_NAME sancov - -#define NO_GATE -#define TODO_FLAGS_FINISH TODO_dump_func | TODO_verify_stmts | TODO_update_ssa_no_phi | TODO_verify_flow - -#include "gcc-generate-gimple-pass.h" - -static void sancov_start_unit(void __unused *gcc_data, void __unused *user_data) -{ - tree leaf_attr, nothrow_attr; - tree BT_FN_VOID = build_function_type_list(void_type_node, NULL_TREE); - - sancov_fndecl = build_fn_decl("__sanitizer_cov_trace_pc", BT_FN_VOID); - - DECL_ASSEMBLER_NAME(sancov_fndecl); - TREE_PUBLIC(sancov_fndecl) = 1; - DECL_EXTERNAL(sancov_fndecl) = 1; - DECL_ARTIFICIAL(sancov_fndecl) = 1; - DECL_PRESERVE_P(sancov_fndecl) = 1; - DECL_UNINLINABLE(sancov_fndecl) = 1; - TREE_USED(sancov_fndecl) = 1; - - nothrow_attr = tree_cons(get_identifier("nothrow"), NULL, NULL); - decl_attributes(&sancov_fndecl, nothrow_attr, 0); - gcc_assert(TREE_NOTHROW(sancov_fndecl)); - leaf_attr = tree_cons(get_identifier("leaf"), NULL, NULL); - decl_attributes(&sancov_fndecl, leaf_attr, 0); -} - -__visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) -{ - int i; - const char * const plugin_name = plugin_info->base_name; - const int argc = plugin_info->argc; - const struct plugin_argument * const argv = plugin_info->argv; - bool enable = true; - - static const struct ggc_root_tab gt_ggc_r_gt_sancov[] = { - { - .base = &sancov_fndecl, - .nelt = 1, - .stride = sizeof(sancov_fndecl), - .cb = >_ggc_mx_tree_node, - .pchw = >_pch_nx_tree_node - }, - LAST_GGC_ROOT_TAB - }; - - /* BBs can be split afterwards?? */ - PASS_INFO(sancov, "asan", 0, PASS_POS_INSERT_BEFORE); - - if (!plugin_default_version_check(version, &gcc_version)) { - error(G_("incompatible gcc/plugin versions")); - return 1; - } - - for (i = 0; i < argc; ++i) { - if (!strcmp(argv[i].key, "no-sancov")) { - enable = false; - continue; - } - error(G_("unknown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key); - } - - register_callback(plugin_name, PLUGIN_INFO, NULL, &sancov_plugin_info); - - if (!enable) - return 0; - -#if BUILDING_GCC_VERSION < 6000 - register_callback(plugin_name, PLUGIN_START_UNIT, &sancov_start_unit, NULL); - register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, NULL, (void *)>_ggc_r_gt_sancov); - register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &sancov_pass_info); -#endif - - return 0; -} diff --git a/scripts/gcc-plugins/structleak_plugin.c b/scripts/gcc-plugins/structleak_plugin.c deleted file mode 100644 index d8c744233832..000000000000 --- a/scripts/gcc-plugins/structleak_plugin.c +++ /dev/null @@ -1,257 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright 2013-2017 by PaX Team <pageexec@freemail.hu> - * - * Note: the choice of the license means that the compilation process is - * NOT 'eligible' as defined by gcc's library exception to the GPL v3, - * but for the kernel it doesn't matter since it doesn't link against - * any of the gcc libraries - * - * gcc plugin to forcibly initialize certain local variables that could - * otherwise leak kernel stack to userland if they aren't properly initialized - * by later code - * - * Homepage: https://pax.grsecurity.net/ - * - * Options: - * -fplugin-arg-structleak_plugin-disable - * -fplugin-arg-structleak_plugin-verbose - * -fplugin-arg-structleak_plugin-byref - * -fplugin-arg-structleak_plugin-byref-all - * - * Usage: - * $ # for 4.5/4.6/C based 4.7 - * $ gcc -I`gcc -print-file-name=plugin`/include -I`gcc -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o structleak_plugin.so structleak_plugin.c - * $ # for C++ based 4.7/4.8+ - * $ g++ -I`g++ -print-file-name=plugin`/include -I`g++ -print-file-name=plugin`/include/c-family -fPIC -shared -O2 -o structleak_plugin.so structleak_plugin.c - * $ gcc -fplugin=./structleak_plugin.so test.c -O2 - * - * TODO: eliminate redundant initializers - */ - -#include "gcc-common.h" - -/* unused C type flag in all versions 4.5-6 */ -#define TYPE_USERSPACE(TYPE) TYPE_LANG_FLAG_5(TYPE) - -__visible int plugin_is_GPL_compatible; - -static struct plugin_info structleak_plugin_info = { - .version = PLUGIN_VERSION, - .help = "disable\tdo not activate plugin\n" - "byref\tinit structs passed by reference\n" - "byref-all\tinit anything passed by reference\n" - "verbose\tprint all initialized variables\n", -}; - -#define BYREF_STRUCT 1 -#define BYREF_ALL 2 - -static bool verbose; -static int byref; - -static tree handle_user_attribute(tree *node, tree name, tree args, int flags, bool *no_add_attrs) -{ - *no_add_attrs = true; - - /* check for types? for now accept everything linux has to offer */ - if (TREE_CODE(*node) != FIELD_DECL) - return NULL_TREE; - - *no_add_attrs = false; - return NULL_TREE; -} - -static struct attribute_spec user_attr = { }; - -static void register_attributes(void *event_data, void *data) -{ - user_attr.name = "user"; - user_attr.handler = handle_user_attribute; - user_attr.affects_type_identity = true; - - register_attribute(&user_attr); -} - -static tree get_field_type(tree field) -{ - return strip_array_types(TREE_TYPE(field)); -} - -static bool is_userspace_type(tree type) -{ - tree field; - - for (field = TYPE_FIELDS(type); field; field = TREE_CHAIN(field)) { - tree fieldtype = get_field_type(field); - enum tree_code code = TREE_CODE(fieldtype); - - if (code == RECORD_TYPE || code == UNION_TYPE) - if (is_userspace_type(fieldtype)) - return true; - - if (lookup_attribute("user", DECL_ATTRIBUTES(field))) - return true; - } - return false; -} - -static void finish_type(void *event_data, void *data) -{ - tree type = (tree)event_data; - - if (type == NULL_TREE || type == error_mark_node) - return; - - if (TREE_CODE(type) == ENUMERAL_TYPE) - return; - - if (TYPE_USERSPACE(type)) - return; - - if (is_userspace_type(type)) - TYPE_USERSPACE(type) = 1; -} - -static void initialize(tree var) -{ - basic_block bb; - gimple_stmt_iterator gsi; - tree initializer; - gimple init_stmt; - tree type; - - /* this is the original entry bb before the forced split */ - bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun)); - - /* first check if variable is already initialized, warn otherwise */ - for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) { - gimple stmt = gsi_stmt(gsi); - tree rhs1; - - /* we're looking for an assignment of a single rhs... */ - if (!gimple_assign_single_p(stmt)) - continue; - rhs1 = gimple_assign_rhs1(stmt); - /* ... of a non-clobbering expression... */ - if (TREE_CLOBBER_P(rhs1)) - continue; - /* ... to our variable... */ - if (gimple_get_lhs(stmt) != var) - continue; - /* if it's an initializer then we're good */ - if (TREE_CODE(rhs1) == CONSTRUCTOR) - return; - } - - /* these aren't the 0days you're looking for */ - if (verbose) - inform(DECL_SOURCE_LOCATION(var), - "%s variable will be forcibly initialized", - (byref && TREE_ADDRESSABLE(var)) ? "byref" - : "userspace"); - - /* build the initializer expression */ - type = TREE_TYPE(var); - if (AGGREGATE_TYPE_P(type)) - initializer = build_constructor(type, NULL); - else - initializer = fold_convert(type, integer_zero_node); - - /* build the initializer stmt */ - init_stmt = gimple_build_assign(var, initializer); - gsi = gsi_after_labels(single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun))); - gsi_insert_before(&gsi, init_stmt, GSI_NEW_STMT); - update_stmt(init_stmt); -} - -static unsigned int structleak_execute(void) -{ - basic_block bb; - tree var; - unsigned int i; - - /* split the first bb where we can put the forced initializers */ - gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun))); - bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun)); - if (!single_pred_p(bb)) { - split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun))); - gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun))); - } - - /* enumerate all local variables and forcibly initialize our targets */ - FOR_EACH_LOCAL_DECL(cfun, i, var) { - tree type = TREE_TYPE(var); - - gcc_assert(DECL_P(var)); - if (!auto_var_in_fn_p(var, current_function_decl)) - continue; - - /* only care about structure types unless byref-all */ - if (byref != BYREF_ALL && TREE_CODE(type) != RECORD_TYPE && TREE_CODE(type) != UNION_TYPE) - continue; - - /* if the type is of interest, examine the variable */ - if (TYPE_USERSPACE(type) || - (byref && TREE_ADDRESSABLE(var))) - initialize(var); - } - - return 0; -} - -#define PASS_NAME structleak -#define NO_GATE -#define PROPERTIES_REQUIRED PROP_cfg -#define TODO_FLAGS_FINISH TODO_verify_il | TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func | TODO_remove_unused_locals | TODO_update_ssa | TODO_ggc_collect | TODO_verify_flow -#include "gcc-generate-gimple-pass.h" - -__visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) -{ - int i; - const char * const plugin_name = plugin_info->base_name; - const int argc = plugin_info->argc; - const struct plugin_argument * const argv = plugin_info->argv; - bool enable = true; - - PASS_INFO(structleak, "early_optimizations", 1, PASS_POS_INSERT_BEFORE); - - if (!plugin_default_version_check(version, &gcc_version)) { - error(G_("incompatible gcc/plugin versions")); - return 1; - } - - if (strncmp(lang_hooks.name, "GNU C", 5) && !strncmp(lang_hooks.name, "GNU C+", 6)) { - inform(UNKNOWN_LOCATION, G_("%s supports C only, not %s"), plugin_name, lang_hooks.name); - enable = false; - } - - for (i = 0; i < argc; ++i) { - if (!strcmp(argv[i].key, "disable")) { - enable = false; - continue; - } - if (!strcmp(argv[i].key, "verbose")) { - verbose = true; - continue; - } - if (!strcmp(argv[i].key, "byref")) { - byref = BYREF_STRUCT; - continue; - } - if (!strcmp(argv[i].key, "byref-all")) { - byref = BYREF_ALL; - continue; - } - error(G_("unknown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key); - } - - register_callback(plugin_name, PLUGIN_INFO, NULL, &structleak_plugin_info); - if (enable) { - register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &structleak_pass_info); - register_callback(plugin_name, PLUGIN_FINISH_TYPE, finish_type, NULL); - } - register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, NULL); - - return 0; -} diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py index f506965ea759..6edf4ef61636 100644 --- a/scripts/gdb/linux/cpus.py +++ b/scripts/gdb/linux/cpus.py @@ -141,7 +141,7 @@ LxCpus() class PerCpu(gdb.Function): """Return per-cpu variable. -$lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the +$lx_per_cpu(VAR[, CPU]): Return the per-cpu variable called VAR for the given CPU number. If CPU is omitted, the CPU of the current context is used. Note that VAR has to be quoted as string.""" @@ -158,7 +158,7 @@ PerCpu() class PerCpuPtr(gdb.Function): """Return per-cpu pointer. -$lx_per_cpu_ptr("VAR"[, CPU]): Return the per-cpu pointer called VAR for the +$lx_per_cpu_ptr(VAR[, CPU]): Return the per-cpu pointer called VAR for the given CPU number. If CPU is omitted, the CPU of the current context is used. Note that VAR has to be quoted as string.""" diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py index b255177301e9..2332bd8eddf1 100644 --- a/scripts/gdb/linux/symbols.py +++ b/scripts/gdb/linux/symbols.py @@ -38,19 +38,13 @@ if hasattr(gdb, 'Breakpoint'): # Disable pagination while reporting symbol (re-)loading. # The console input is blocked in this context so that we would # get stuck waiting for the user to acknowledge paged output. - show_pagination = gdb.execute("show pagination", to_string=True) - pagination = show_pagination.endswith("on.\n") - gdb.execute("set pagination off") - - if module_name in cmd.loaded_modules: - gdb.write("refreshing all symbols to reload module " - "'{0}'\n".format(module_name)) - cmd.load_all_symbols() - else: - cmd.load_module_symbols(module) - - # restore pagination state - gdb.execute("set pagination %s" % ("on" if pagination else "off")) + with utils.pagination_off(): + if module_name in cmd.loaded_modules: + gdb.write("refreshing all symbols to reload module " + "'{0}'\n".format(module_name)) + cmd.load_all_symbols() + else: + cmd.load_module_symbols(module) return False @@ -60,6 +54,18 @@ def get_vmcore_s390(): vmcore_info = 0x0e0c paddr_vmcoreinfo_note = gdb.parse_and_eval("*(unsigned long long *)" + hex(vmcore_info)) + if paddr_vmcoreinfo_note == 0 or paddr_vmcoreinfo_note & 1: + # In the early boot case, extract vm_layout.kaslr_offset from the + # vmlinux image in physical memory. + if paddr_vmcoreinfo_note == 0: + kaslr_offset_phys = 0 + else: + kaslr_offset_phys = paddr_vmcoreinfo_note - 1 + with utils.pagination_off(): + gdb.execute("symbol-file {0} -o {1}".format( + utils.get_vmlinux(), hex(kaslr_offset_phys))) + kaslr_offset = gdb.parse_and_eval("vm_layout.kaslr_offset") + return "KERNELOFFSET=" + hex(kaslr_offset)[2:] inferior = gdb.selected_inferior() elf_note = inferior.read_memory(paddr_vmcoreinfo_note, 12) n_namesz, n_descsz, n_type = struct.unpack(">III", elf_note) @@ -178,11 +184,7 @@ lx-symbols command.""" saved_states.append({'breakpoint': bp, 'enabled': bp.enabled}) # drop all current symbols and reload vmlinux - orig_vmlinux = 'vmlinux' - for obj in gdb.objfiles(): - if (obj.filename.endswith('vmlinux') or - obj.filename.endswith('vmlinux.debug')): - orig_vmlinux = obj.filename + orig_vmlinux = utils.get_vmlinux() gdb.execute("symbol-file", to_string=True) kerneloffset = get_kerneloffset() if kerneloffset is None: diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py index 03ebdccf5f69..e11f6f67961a 100644 --- a/scripts/gdb/linux/utils.py +++ b/scripts/gdb/linux/utils.py @@ -200,7 +200,7 @@ def get_gdbserver_type(): def probe_kgdb(): try: - thread_info = gdb.execute("info thread 2", to_string=True) + thread_info = gdb.execute("info thread 1", to_string=True) return "shadowCPU" in thread_info except gdb.error: return False @@ -251,3 +251,23 @@ def parse_vmcore(s): else: kerneloffset = int(match.group(1), 16) return VmCore(kerneloffset=kerneloffset) + + +def get_vmlinux(): + vmlinux = 'vmlinux' + for obj in gdb.objfiles(): + if (obj.filename.endswith('vmlinux') or + obj.filename.endswith('vmlinux.debug')): + vmlinux = obj.filename + return vmlinux + + +@contextlib.contextmanager +def pagination_off(): + show_pagination = gdb.execute("show pagination", to_string=True) + pagination = show_pagination.endswith("on.\n") + gdb.execute("set pagination off") + try: + yield + finally: + gdb.execute("set pagination %s" % ("on" if pagination else "off")) diff --git a/scripts/min-tool-version.sh b/scripts/min-tool-version.sh index 787868183b84..0d223b4a9445 100755 --- a/scripts/min-tool-version.sh +++ b/scripts/min-tool-version.sh @@ -14,15 +14,13 @@ fi case "$1" in binutils) - echo 2.25.0 + echo 2.30.0 ;; gcc) if [ "$ARCH" = parisc64 ]; then echo 12.0.0 - elif [ "$SRCARCH" = x86 ]; then - echo 8.1.0 else - echo 5.1.0 + echo 8.1.0 fi ;; llvm) diff --git a/scripts/spelling.txt b/scripts/spelling.txt index a290db720b0f..ac94fa1c2415 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -1240,6 +1240,8 @@ prefered||preferred prefferably||preferably prefitler||prefilter preform||perform +previleged||privileged +previlege||privilege premption||preemption prepaired||prepared prepate||prepare |