diff options
Diffstat (limited to 'scripts')
38 files changed, 898 insertions, 432 deletions
diff --git a/scripts/Makefile.build b/scripts/Makefile.build index a4b89b757287..f89d3fcff39f 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -40,8 +40,7 @@ include $(srctree)/scripts/Makefile.compiler # The filename Kbuild has precedence over Makefile kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) -kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) -include $(kbuild-file) +include $(or $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Makefile) include $(srctree)/scripts/Makefile.lib @@ -88,8 +87,8 @@ endif targets-for-modules := $(patsubst %.o, %.mod, $(filter %.o, $(obj-m))) -ifdef CONFIG_LTO_CLANG -targets-for-modules += $(patsubst %.o, %.lto.o, $(filter %.o, $(obj-m))) +ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) +targets-for-modules += $(patsubst %.o, %.prelink.o, $(filter %.o, $(obj-m))) endif ifdef need-modorder @@ -223,26 +222,31 @@ cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), $(sub_cmd_record_mcount)) endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT -ifdef CONFIG_STACK_VALIDATION +ifdef CONFIG_OBJTOOL objtool := $(objtree)/tools/objtool/objtool objtool_args = \ - $(if $(CONFIG_UNWINDER_ORC),orc generate,check) \ - $(if $(part-of-module), --module) \ - $(if $(CONFIG_FRAME_POINTER),, --no-fp) \ - $(if $(CONFIG_GCOV_KERNEL)$(CONFIG_LTO_CLANG), --no-unreachable)\ - $(if $(CONFIG_RETPOLINE), --retpoline) \ - $(if $(CONFIG_X86_SMAP), --uaccess) \ + $(if $(CONFIG_HAVE_JUMP_LABEL_HACK), --hacks=jump_label) \ + $(if $(CONFIG_HAVE_NOINSTR_HACK), --hacks=noinstr) \ + $(if $(CONFIG_X86_KERNEL_IBT), --ibt) \ $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount) \ - $(if $(CONFIG_SLS), --sls) + $(if $(CONFIG_UNWINDER_ORC), --orc) \ + $(if $(CONFIG_RETPOLINE), --retpoline) \ + $(if $(CONFIG_SLS), --sls) \ + $(if $(CONFIG_STACK_VALIDATION), --stackval) \ + $(if $(CONFIG_HAVE_STATIC_CALL_INLINE), --static-call) \ + --uaccess \ + $(if $(linked-object), --link) \ + $(if $(part-of-module), --module) \ + $(if $(CONFIG_GCOV_KERNEL), --no-unreachable) cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool_args) $@) cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd) -endif # CONFIG_STACK_VALIDATION +endif # CONFIG_OBJTOOL -ifdef CONFIG_LTO_CLANG +ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) # Skip objtool for LLVM bitcode $(obj)/%.o: objtool-enabled := @@ -288,24 +292,25 @@ $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE $(call if_changed_rule,cc_o_c) $(call cmd,force_checksrc) -ifdef CONFIG_LTO_CLANG +ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) # Module .o files may contain LLVM bitcode, compile them into native code # before ELF processing -quiet_cmd_cc_lto_link_modules = LTO [M] $@ -cmd_cc_lto_link_modules = \ +quiet_cmd_cc_prelink_modules = LD [M] $@ + cmd_cc_prelink_modules = \ $(LD) $(ld_flags) -r -o $@ \ - $(shell [ -s $(@:.lto.o=.o.symversions) ] && \ - echo -T $(@:.lto.o=.o.symversions)) \ + $(shell [ -s $(@:.prelink.o=.o.symversions) ] && \ + echo -T $(@:.prelink.o=.o.symversions)) \ --whole-archive $(filter-out FORCE,$^) \ $(cmd_objtool) # objtool was skipped for LLVM bitcode, run it now that we have compiled # modules into native code -$(obj)/%.lto.o: objtool-enabled = y -$(obj)/%.lto.o: part-of-module := y +$(obj)/%.prelink.o: objtool-enabled = y +$(obj)/%.prelink.o: part-of-module := y +$(obj)/%.prelink.o: linked-object := y -$(obj)/%.lto.o: $(obj)/%.o FORCE - $(call if_changed,cc_lto_link_modules) +$(obj)/%.prelink.o: $(obj)/%.o FORCE + $(call if_changed,cc_prelink_modules) endif cmd_mod = { \ @@ -469,7 +474,7 @@ $(obj)/lib.a: $(lib-y) FORCE # Do not replace $(filter %.o,^) with $(real-prereqs). When a single object # module is turned into a multi object module, $^ will contain header file # dependencies recorded in the .*.cmd file. -ifdef CONFIG_LTO_CLANG +ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) quiet_cmd_link_multi-m = AR [M] $@ cmd_link_multi-m = \ $(cmd_update_lto_symversions); \ diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean index fd6175322470..74cb1c5c3658 100644 --- a/scripts/Makefile.clean +++ b/scripts/Makefile.clean @@ -12,7 +12,7 @@ include $(srctree)/scripts/Kbuild.include # The filename Kbuild has precedence over Makefile kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) -include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) +include $(or $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Makefile) # Figure out what we need to build from the various variables # ========================================================================== diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins index f67153b260c0..692d64a70542 100644 --- a/scripts/Makefile.gcc-plugins +++ b/scripts/Makefile.gcc-plugins @@ -8,8 +8,6 @@ ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY endif export DISABLE_LATENT_ENTROPY_PLUGIN -gcc-plugin-$(CONFIG_GCC_PLUGIN_SANCOV) += sancov_plugin.so - gcc-plugin-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += structleak_plugin.so gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_VERBOSE) \ += -fplugin-arg-structleak_plugin-verbose @@ -24,12 +22,6 @@ export DISABLE_STRUCTLEAK_PLUGIN gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) \ += -DSTRUCTLEAK_PLUGIN -gcc-plugin-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) += randomize_layout_plugin.so -gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) \ - += -DRANDSTRUCT_PLUGIN -gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT_PERFORMANCE) \ - += -fplugin-arg-randomize_layout_plugin-performance-mode - gcc-plugin-$(CONFIG_GCC_PLUGIN_STACKLEAK) += stackleak_plugin.so gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STACKLEAK) \ += -DSTACKLEAK_PLUGIN @@ -53,13 +45,19 @@ export DISABLE_ARM_SSP_PER_TASK_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)) -# The sancov_plugin.so is included via CFLAGS_KCOV, so it is removed here. -GCC_PLUGINS_CFLAGS := $(filter-out %/sancov_plugin.so, $(GCC_PLUGINS_CFLAGS)) export GCC_PLUGINS_CFLAGS # Add the flags to the build! KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) -# All enabled GCC plugins are collected here for building below. -GCC_PLUGIN := $(gcc-plugin-y) +# 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 + +# All enabled GCC plugins are collected here for building in +# scripts/gcc-scripts/Makefile. +GCC_PLUGIN := $(gcc-plugin-y) $(gcc-plugin-external-y) export GCC_PLUGIN diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 79be57fdd32a..9f69ecdd7977 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -87,11 +87,6 @@ base-dtb-y := $(foreach m, $(multi-dtb-y), $(firstword $(call suffix-search, $m, always-y += $(dtb-y) -ifneq ($(CHECK_DTBS),) -always-y += $(patsubst %.dtb,%.dt.yaml, $(real-dtb-y)) -always-y += $(patsubst %.dtbo,%.dt.yaml, $(real-dtb-y)) -endif - # Add subdir path extra-y := $(addprefix $(obj)/,$(extra-y)) @@ -111,7 +106,7 @@ subdir-ym := $(addprefix $(obj)/,$(subdir-ym)) modname-multi = $(sort $(foreach m,$(multi-obj-ym),\ $(if $(filter $*.o, $(call suffix-search, $m, .o, -objs -y -m)),$(m:.o=)))) -__modname = $(if $(modname-multi),$(modname-multi),$(basetarget)) +__modname = $(or $(modname-multi),$(basetarget)) modname = $(subst $(space),:,$(__modname)) modfile = $(addprefix $(obj)/,$(__modname)) @@ -230,11 +225,11 @@ dtc_cpp_flags = -Wp,-MMD,$(depfile).pre.tmp -nostdinc \ $(addprefix -I,$(DTC_INCLUDE)) \ -undef -D__DTS__ -ifeq ($(CONFIG_LTO_CLANG),y) +ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) # With CONFIG_LTO_CLANG, .o files in modules might be LLVM bitcode, so we # need to run LTO to compile them into native code (.lto.o) before further # processing. -mod-prelink-ext := .lto +mod-prelink-ext := .prelink endif # Useful for describing the dependency of composite objects @@ -246,20 +241,16 @@ $(foreach m, $(notdir $1), \ $(addprefix $(obj)/, $(foreach s, $3, $($(m:%$(strip $2)=%$(s))))))) endef -quiet_cmd_copy = COPY $@ - cmd_copy = cp $< $@ - -# Shipped files +# Copy a file # =========================================================================== # 'cp' preserves permissions. If you use it to copy a file in read-only srctree, # the copy would be read-only as well, leading to an error when executing the # rule next time. Use 'cat' instead in order to generate a writable file. - -quiet_cmd_shipped = SHIPPED $@ -cmd_shipped = cat $< > $@ +quiet_cmd_copy = COPY $@ + cmd_copy = cat $< > $@ $(obj)/%: $(src)/%_shipped - $(call cmd,shipped) + $(call cmd,copy) # Commands useful for building a boot image # =========================================================================== @@ -347,12 +338,6 @@ cmd_dtc = $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; -d $(depfile).dtc.tmp $(dtc-tmp) ; \ cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) -$(obj)/%.dtb: $(src)/%.dts $(DTC) FORCE - $(call if_changed_dep,dtc) - -$(obj)/%.dtbo: $(src)/%.dts $(DTC) FORCE - $(call if_changed_dep,dtc) - quiet_cmd_fdtoverlay = DTOVL $@ cmd_fdtoverlay = $(objtree)/scripts/dtc/fdtoverlay -o $@ -i $(real-prereqs) @@ -360,23 +345,27 @@ $(multi-dtb-y): FORCE $(call if_changed,fdtoverlay) $(call multi_depend, $(multi-dtb-y), .dtb, -dtbs) +ifneq ($(CHECK_DTBS)$(CHECK_DT_BINDING),) DT_CHECKER ?= dt-validate -DT_CHECKER_FLAGS ?= $(if $(DT_SCHEMA_FILES),,-m) +DT_CHECKER_FLAGS ?= $(if $(DT_SCHEMA_FILES),-l $(DT_SCHEMA_FILES),-m) DT_BINDING_DIR := Documentation/devicetree/bindings -# DT_TMP_SCHEMA may be overridden from Documentation/devicetree/bindings/Makefile -DT_TMP_SCHEMA ?= $(objtree)/$(DT_BINDING_DIR)/processed-schema.json +DT_TMP_SCHEMA := $(objtree)/$(DT_BINDING_DIR)/processed-schema.json quiet_cmd_dtb_check = CHECK $@ - cmd_dtb_check = $(DT_CHECKER) $(DT_CHECKER_FLAGS) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@ + cmd_dtb_check = $(DT_CHECKER) $(DT_CHECKER_FLAGS) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@ || true +endif define rule_dtc $(call cmd_and_fixdep,dtc) $(call cmd,dtb_check) endef -$(obj)/%.dt.yaml: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE +$(obj)/%.dtb: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE $(call if_changed_rule,dtc) +$(obj)/%.dtbo: $(src)/%.dts $(DTC) FORCE + $(call if_changed_dep,dtc) + dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) # Bzip2 @@ -438,7 +427,7 @@ MKIMAGE := $(srctree)/scripts/mkuboot.sh # SRCARCH just happens to match slightly more than ARCH (on sparc), so reduces # the number of overrides in arch makefiles UIMAGE_ARCH ?= $(SRCARCH) -UIMAGE_COMPRESSION ?= $(if $(2),$(2),none) +UIMAGE_COMPRESSION ?= $(or $(2),none) UIMAGE_OPTS-y ?= UIMAGE_TYPE ?= kernel UIMAGE_LOADADDR ?= arch_must_set_this diff --git a/scripts/Makefile.randstruct b/scripts/Makefile.randstruct new file mode 100644 index 000000000000..24e283e89893 --- /dev/null +++ b/scripts/Makefile.randstruct @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 + +randstruct-cflags-y += -DRANDSTRUCT + +ifdef CONFIG_GCC_PLUGIN_RANDSTRUCT +randstruct-cflags-y \ + += -fplugin=$(objtree)/scripts/gcc-plugins/randomize_layout_plugin.so +randstruct-cflags-$(CONFIG_RANDSTRUCT_PERFORMANCE) \ + += -fplugin-arg-randomize_layout_plugin-performance-mode +else +randstruct-cflags-y \ + += -frandomize-layout-seed-file=$(objtree)/scripts/basic/randstruct.seed +endif + +export RANDSTRUCT_CFLAGS := $(randstruct-cflags-y) + +KBUILD_CFLAGS += $(RANDSTRUCT_CFLAGS) diff --git a/scripts/atomic/gen-atomic-fallback.sh b/scripts/atomic/gen-atomic-fallback.sh index 8e2da71f1d5f..3a07695e3c89 100755 --- a/scripts/atomic/gen-atomic-fallback.sh +++ b/scripts/atomic/gen-atomic-fallback.sh @@ -164,41 +164,44 @@ gen_xchg_fallbacks() gen_try_cmpxchg_fallback() { + local cmpxchg="$1"; shift; local order="$1"; shift; cat <<EOF -#ifndef arch_try_cmpxchg${order} -#define arch_try_cmpxchg${order}(_ptr, _oldp, _new) \\ +#ifndef arch_try_${cmpxchg}${order} +#define arch_try_${cmpxchg}${order}(_ptr, _oldp, _new) \\ ({ \\ typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \\ - ___r = arch_cmpxchg${order}((_ptr), ___o, (_new)); \\ + ___r = arch_${cmpxchg}${order}((_ptr), ___o, (_new)); \\ if (unlikely(___r != ___o)) \\ *___op = ___r; \\ likely(___r == ___o); \\ }) -#endif /* arch_try_cmpxchg${order} */ +#endif /* arch_try_${cmpxchg}${order} */ EOF } gen_try_cmpxchg_fallbacks() { - printf "#ifndef arch_try_cmpxchg_relaxed\n" - printf "#ifdef arch_try_cmpxchg\n" + local cmpxchg="$1"; shift; - gen_basic_fallbacks "arch_try_cmpxchg" + printf "#ifndef arch_try_${cmpxchg}_relaxed\n" + printf "#ifdef arch_try_${cmpxchg}\n" - printf "#endif /* arch_try_cmpxchg */\n\n" + gen_basic_fallbacks "arch_try_${cmpxchg}" + + printf "#endif /* arch_try_${cmpxchg} */\n\n" for order in "" "_acquire" "_release" "_relaxed"; do - gen_try_cmpxchg_fallback "${order}" + gen_try_cmpxchg_fallback "${cmpxchg}" "${order}" done - printf "#else /* arch_try_cmpxchg_relaxed */\n" + printf "#else /* arch_try_${cmpxchg}_relaxed */\n" - gen_order_fallbacks "arch_try_cmpxchg" + gen_order_fallbacks "arch_try_${cmpxchg}" - printf "#endif /* arch_try_cmpxchg_relaxed */\n\n" + printf "#endif /* arch_try_${cmpxchg}_relaxed */\n\n" } cat << EOF @@ -218,7 +221,9 @@ for xchg in "arch_xchg" "arch_cmpxchg" "arch_cmpxchg64"; do gen_xchg_fallbacks "${xchg}" done -gen_try_cmpxchg_fallbacks +for cmpxchg in "cmpxchg" "cmpxchg64"; do + gen_try_cmpxchg_fallbacks "${cmpxchg}" +done grep '^[a-z]' "$1" | while read name meta args; do gen_proto "${meta}" "${name}" "atomic" "int" ${args} diff --git a/scripts/atomic/gen-atomic-instrumented.sh b/scripts/atomic/gen-atomic-instrumented.sh index 68f902731d01..77c06526a574 100755 --- a/scripts/atomic/gen-atomic-instrumented.sh +++ b/scripts/atomic/gen-atomic-instrumented.sh @@ -166,7 +166,7 @@ grep '^[a-z]' "$1" | while read name meta args; do done -for xchg in "xchg" "cmpxchg" "cmpxchg64" "try_cmpxchg"; do +for xchg in "xchg" "cmpxchg" "cmpxchg64" "try_cmpxchg" "try_cmpxchg64"; do for order in "" "_acquire" "_release" "_relaxed"; do gen_xchg "${xchg}" "${order}" "" printf "\n" diff --git a/scripts/basic/.gitignore b/scripts/basic/.gitignore index 961c91c8a884..07c195f605a1 100644 --- a/scripts/basic/.gitignore +++ b/scripts/basic/.gitignore @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only /fixdep +/randstruct.seed diff --git a/scripts/basic/Makefile b/scripts/basic/Makefile index eeb6a38c5551..dd289a6725ac 100644 --- a/scripts/basic/Makefile +++ b/scripts/basic/Makefile @@ -3,3 +3,14 @@ # fixdep: used to generate dependency information during build process hostprogs-always-y += fixdep + +# randstruct: the seed is needed before building the gcc-plugin or +# 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 + $(call if_changed,create_randstruct_seed) +always-$(CONFIG_RANDSTRUCT) += randstruct.seed diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index 44e887cff49b..2328f9a641da 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -105,25 +105,6 @@ static void usage(void) exit(1); } -/* - * In the intended usage of this program, the stdout is redirected to .*.cmd - * files. The return value of printf() must be checked to catch any error, - * e.g. "No space left on device". - */ -static void xprintf(const char *format, ...) -{ - va_list ap; - int ret; - - va_start(ap, format); - ret = vprintf(format, ap); - if (ret < 0) { - perror("fixdep"); - exit(1); - } - va_end(ap); -} - struct item { struct item *next; unsigned int len; @@ -189,7 +170,7 @@ static void use_config(const char *m, int slen) define_config(m, slen, hash); /* Print out a dependency path from a symbol name. */ - xprintf(" $(wildcard include/config/%.*s) \\\n", slen, m); + printf(" $(wildcard include/config/%.*s) \\\n", slen, m); } /* test if s ends in sub */ @@ -318,13 +299,13 @@ static void parse_dep_file(char *m, const char *target) */ if (!saw_any_target) { saw_any_target = 1; - xprintf("source_%s := %s\n\n", - target, m); - xprintf("deps_%s := \\\n", target); + printf("source_%s := %s\n\n", + target, m); + printf("deps_%s := \\\n", target); } is_first_dep = 0; } else { - xprintf(" %s \\\n", m); + printf(" %s \\\n", m); } buf = read_file(m); @@ -347,8 +328,8 @@ static void parse_dep_file(char *m, const char *target) exit(1); } - xprintf("\n%s: $(deps_%s)\n\n", target, target); - xprintf("$(deps_%s):\n", target); + printf("\n%s: $(deps_%s)\n\n", target, target); + printf("$(deps_%s):\n", target); } int main(int argc, char *argv[]) @@ -363,11 +344,22 @@ int main(int argc, char *argv[]) target = argv[2]; cmdline = argv[3]; - xprintf("cmd_%s := %s\n\n", target, cmdline); + printf("cmd_%s := %s\n\n", target, cmdline); buf = read_file(depfile); parse_dep_file(buf, target); free(buf); + fflush(stdout); + + /* + * In the intended usage, the stdout is redirected to .*.cmd files. + * Call ferror() to catch errors such as "No space left on device". + */ + if (ferror(stdout)) { + fprintf(stderr, "fixdep: not all data was written to the output\n"); + exit(1); + } + return 0; } diff --git a/scripts/check-blacklist-hashes.awk b/scripts/check-blacklist-hashes.awk new file mode 100755 index 000000000000..107c1d3204d4 --- /dev/null +++ b/scripts/check-blacklist-hashes.awk @@ -0,0 +1,37 @@ +#!/usr/bin/awk -f +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright © 2020, Microsoft Corporation. All rights reserved. +# +# Author: Mickaël Salaün <mic@linux.microsoft.com> +# +# Check that a CONFIG_SYSTEM_BLACKLIST_HASH_LIST file contains a valid array of +# hash strings. Such string must start with a prefix ("tbs" or "bin"), then a +# colon (":"), and finally an even number of hexadecimal lowercase characters +# (up to 128). + +BEGIN { + RS = "," +} +{ + if (!match($0, "^[ \t\n\r]*\"([^\"]*)\"[ \t\n\r]*$", part1)) { + print "Not a string (item " NR "):", $0; + exit 1; + } + if (!match(part1[1], "^(tbs|bin):(.*)$", part2)) { + print "Unknown prefix (item " NR "):", part1[1]; + exit 1; + } + if (!match(part2[2], "^([0-9a-f]+)$", part3)) { + print "Not a lowercase hexadecimal string (item " NR "):", part2[2]; + exit 1; + } + if (length(part3[1]) > 128) { + print "Hash string too long (item " NR "):", part3[1]; + exit 1; + } + if (length(part3[1]) % 2 == 1) { + print "Not an even number of hexadecimal characters (item " NR "):", part3[1]; + exit 1; + } +} diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile index 95aaf7431bff..4d32b9497da9 100644 --- a/scripts/dtc/Makefile +++ b/scripts/dtc/Makefile @@ -17,20 +17,7 @@ fdtoverlay-objs := $(libfdt) fdtoverlay.o util.o # Source files need to get at the userspace version of libfdt_env.h to compile HOST_EXTRACFLAGS += -I $(srctree)/$(src)/libfdt - -ifeq ($(shell pkg-config --exists yaml-0.1 2>/dev/null && echo yes),) -ifneq ($(CHECK_DT_BINDING)$(CHECK_DTBS),) -$(error dtc needs libyaml for DT schema validation support. \ - Install the necessary libyaml development package.) -endif HOST_EXTRACFLAGS += -DNO_YAML -else -dtc-objs += yamltree.o -# To include <yaml.h> installed in a non-default path -HOSTCFLAGS_yamltree.o := $(shell pkg-config --cflags yaml-0.1) -# To link libyaml installed in a non-default path -HOSTLDLIBS_dtc := $(shell pkg-config yaml-0.1 --libs) -endif # Generated files need one more search path to include headers in source tree HOSTCFLAGS_dtc-lexer.lex.o := -I $(srctree)/$(src) diff --git a/scripts/dtc/of_unittest_expect b/scripts/dtc/of_unittest_expect new file mode 100755 index 000000000000..96b12d9ea606 --- /dev/null +++ b/scripts/dtc/of_unittest_expect @@ -0,0 +1,408 @@ +#!/usr/bin/perl +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright 2020, 2022 Sony Corporation +# +# Author: Frank Rowand + +# This program is meant to be an aid to reading the verbose output of +# on the console log that results from executing the Linux kernel +# devicetree unittest (drivers/of/unitest.c). + +$VUFX = "220201a"; + +use strict 'refs'; +use strict subs; + +use Getopt::Long; +use Text::Wrap; + +# strip off everything before final "/" +(undef, $script_name) = split(/^.*\//, $0); + +# following /usr/include/sysexits.h +$EX_OK=0; +$EX_USAGE=64; + + +#______________________________________________________________________________ +sub compare { + my ($expect, $got) = @_; + my $expect_next; + my $expect_next_lit; + my $got_next; + my $type; + + while ($expect) { + + ($expect_next, $type) = split(/<</, $expect); + ($type) = split(/>>/, $type); + $expect =~ s/^.*?>>//; # '?' is non-greedy, minimal match + + # literal, ignore all metacharacters when used in a regex + $expect_next_lit = quotemeta($expect_next); + + $got_next = $got; + $got_next =~ s/^($expect_next_lit).*/\1/; + $got =~ s/^$expect_next_lit//; + + if ($expect_next ne $got_next) { + return 0; + } + + if ($type eq "int") { + if ($got =~ /^[+-]*[0-9]+/) { + $got =~ s/^[+-]*[0-9]+//; + } else { + return 0; + } + } elsif ($type eq "hex") { + if ($got =~ /^(0x)*[0-9a-f]+/) { + $got =~ s/^(0x)*[0-9a-f]+//; + } else { + return 0; + } + } elsif ($type eq "") { + if ($expect_next ne $got_next) { + return 0; + } else { + return 1; + } + } else { + $internal_err++; + print "** ERROR: special pattern not recognized: <<$type>>, CONSOLE_LOG line: $.\n"; + return 0; + } + + } + + # should not get here + $internal_err++; + print "** ERROR: $script_name internal error, at end of compare(), CONSOLE_LOG line: $.\n"; + + return 0; +} + + +#______________________________________________________________________________ +sub usage { + +# ***** when editing, be careful to not put tabs in the string printed: + + print STDERR +" +usage: + + $script_name CONSOLE_LOG + + -h print program usage + --help print program usage + --hide-expect suppress output of EXPECTed lines + --line-num report line number of CONSOLE_LOG + --no-expect-stats do not report EXPECT statistics + --no-strip-ts do not strip leading console timestamps + --verbose do not suppress EXPECT begin and end lines + --version print program version and exit + + + Process a console log for EXPECTed test related messages to either + highlight expected devicetree unittest related messages or suppress + the messages. Leading console timestamps will be stripped. + + Various unittests may trigger kernel messages from outside the + unittest code. The unittest annotates that it expects the message + to occur with an 'EXPECT \\ : text' (begin) before triggering the + message, and an 'EXPECT / : text' (end) after triggering the message. + + If an expected message does not occur, that will be reported. + + For each expected message, the 'EXPECT \\ : text' (begin) and + 'EXPECT / : text' (end), 'text' will contain the message text. + + If 'EXPECT \\' (begin) and 'EXPECT /' (end) lines do not contain + matching 'text', that will be reported. + + If EXPECT lines are nested, 'EXPECT /' (end) lines must be in the + reverse order of the corresponding 'EXPECT \\' (begin) lines. + + 'EXPECT \\ : text' (begin) and 'EXPECT / : text' (end) lines can + contain special patterns in 'text': + + <<int>> matches: [+-]*[0-9]+ + <<hex>> matches: (0x)*[0-9a-f]+ + + 'EXPECT \\' (begin) and 'EXPECT /' (end) lines are suppressed. + + A prefix is added to every line of output: + + 'ok ' Line matches an enclosing EXPECT begin/end pair + + '** ' Line reports $script_name warning or error + + '-> ' Line reports start or end of the unittests + + '>> ' Line reports a unittest test FAIL + + ' ' Lines that are not otherwise prefixed + + Issues detected in CONSOLE_LOG are reported to STDOUT, not to STDERR. + + Known Issues: + + --line-num causes the CONSOLE_LOG line number to be printed in 4 columns. + If CONSOLE_LOG contains more than 9999 lines then more columns will be + used to report the line number for lines greater than 9999 (eg for + lines 10000 - 99999, 5 columns will be used). +"; + + return {}; +} + +#______________________________________________________________________________ +#______________________________________________________________________________ + +if (!GetOptions( + "h" => \$help, + "help" => \$help, + "hide-expect" => \$hide_expect, + "line-num" => \$print_line_num, + "no-expect-stats" => \$no_expect_stats, + "no-strip-ts" => \$no_strip_ts, + "verbose" => \$verbose, + "version" => \$version, + )) { + print STDERR "\n"; + print STDERR "ERROR processing command line options\n"; + print STDERR "\n"; + print STDERR "For help, type '$script_name --help'\n"; + print STDERR "\n"; + + exit $EX_OK; +} + + +if ($no_strip_ts) { + $strip_ts = 1; + $no_strip_ts = 0; +} else { + $strip_ts = 0; + $no_strip_ts = 1; +} + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +if ($help){ + + &usage; + + exit $EX_OK; +} + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +if ($version) { + print STDERR "\n$script_name $VUFX\n\n"; + print STDERR "\n"; + + exit $EX_OK; +} + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +if ($#ARGV != 0) { + + # Limit input files to exactly one. + # + # 'while ($line = <ARGV>) {' in the code below supports multiple file + # names on the command line, but the EXPECT statistics are reported + # once for all input - it is not an expected use case to generate one + # set of statistics for multiple input files. + + print STDERR "\n"; + print STDERR "Required arguments: CONSOLE_LOG\n"; + print STDERR "\n"; + + exit $EX_USAGE; +} + + +#______________________________________________________________________________ + +# Patterns to match 'EXPECT \ : ' (begin) and 'EXPECT / : ' (end) +# +# $exp_* are used as regex match patterns, +# so '\\\\' in $exp_begin matches a single '\' +# quotemeta() does not do the right thing in this case +# +# $pr_fmt is the prefix that unittest prints for every message + +$pr_fmt = "### dt-test ### "; +$exp_begin = "${pr_fmt}EXPECT \\\\ : "; +$exp_end = "${pr_fmt}EXPECT / : "; + + +$line_num = ""; +$timestamp = ""; + +LINE: +while ($line = <ARGV>) { + + chomp $line; + + $prefix = " "; ## 2 characters + + + if ($strip_ts) { + + $timestamp = $line; + + if ($timestamp =~ /^\[\s*[0-9]+\.[0-9]*\] /) { + ($timestamp, $null) = split(/]/, $line); + $timestamp = $timestamp . "] "; + + } else { + $timestamp = ""; + } + } + + $line =~ s/^\[\s*[0-9]+\.[0-9]*\] //; + + + # ----- find EXPECT begin + + if ($line =~ /^\s*$exp_begin/) { + $data = $line; + $data =~ s/^\s*$exp_begin//; + push @begin, $data; + + if ($verbose) { + if ($print_line_num) { + $line_num = sprintf("%4s ", $.); + } + printf "%s %s%s%s\n", $prefix, $line_num, $timestamp, $line; + } + + next LINE; + } + + + # ----- find EXPECT end + + if ($line =~ /^\s*$exp_end/) { + $data = $line; + $data =~ s/^\s*$exp_end//; + + if ($verbose) { + if ($print_line_num) { + $line_num = sprintf("%4s ", $.); + } + printf "%s %s%s%s\n", $prefix, $line_num, $timestamp, $line; + } + + $found = 0; + $no_begin = 0; + if (@found_or_begin > 0) { + $begin = pop @found_or_begin; + if (compare($data, $begin)) { + $found = 1; + } + } elsif (@begin > 0) { + $begin = pop @begin; + } else { + $no_begin = 1; + } + + if ($no_begin) { + + $expect_missing_begin++; + print "** ERROR: EXPECT end without any EXPECT begin:\n"; + print " end ---> $line\n"; + + } elsif (! $found) { + + if ($print_line_num) { + $line_num = sprintf("%4s ", $.); + } + + $expect_not_found++; + printf "** %s%s$script_name WARNING - not found ---> %s\n", + $line_num, $timestamp, $data; + + } elsif (! compare($data, $begin)) { + + $expect_missing_end++; + print "** ERROR: EXPECT end does not match EXPECT begin:\n"; + print " begin -> $begin\n"; + print " end ---> $line\n"; + + } else { + + $expect_found++; + + } + + next LINE; + } + + + # ----- not an EXPECT line + + if (($line =~ /^${pr_fmt}start of unittest - you will see error messages$/) || + ($line =~ /^${pr_fmt}end of unittest - [0-9]+ passed, [0-9]+ failed$/ ) ) { + $prefix = "->"; # 2 characters + } elsif ($line =~ /^${pr_fmt}FAIL /) { + $unittest_fail++; + $prefix = ">>"; # 2 characters + } + + $found = 0; + foreach $begin (@begin) { + if (compare($begin, $line)) { + $found = 1; + last; + } + } + + if ($found) { + $begin = shift @begin; + while (! compare($begin, $line)) { + push @found_or_begin, $begin; + $begin = shift @begin; + } + push @found_or_begin, $line; + + if ($hide_expect) { + $suppress_line = 1; + next LINE; + } + $prefix = "ok"; # 2 characters + } + + + if ($print_line_num) { + $line_num = sprintf("%4s ", $.); + } + + printf "%s %s%s%s\n", $prefix, $line_num, $timestamp, $line; +} + +if (! $no_expect_stats) { + print "\n"; + print "** EXPECT statistics:\n"; + print "**\n"; + printf "** EXPECT found : %4i\n", $expect_found; + printf "** EXPECT not found : %4i\n", $expect_not_found; + printf "** missing EXPECT begin : %4i\n", $expect_missing_begin; + printf "** missing EXPECT end : %4i\n", $expect_missing_end; + printf "** unittest FAIL : %4i\n", $unittest_fail; + printf "** internal error : %4i\n", $internal_err; +} + +if (@begin) { + print "** ERROR: EXPECT begin without any EXPECT end:\n"; + print " This list may be misleading.\n"; + foreach $begin (@begin) { + print " begin ---> $begin\n"; + } +} diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh index 32ff17ffd089..94627541533e 100755 --- a/scripts/dtc/update-dtc-source.sh +++ b/scripts/dtc/update-dtc-source.sh @@ -32,7 +32,7 @@ DTC_UPSTREAM_PATH=`pwd`/../dtc DTC_LINUX_PATH=`pwd`/scripts/dtc DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c \ - srcpos.h treesource.c util.c util.h version_gen.h yamltree.c \ + srcpos.h treesource.c util.c util.h version_gen.h \ dtc-lexer.l dtc-parser.y" LIBFDT_SOURCE="fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \ fdt_overlay.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c \ diff --git a/scripts/faddr2line b/scripts/faddr2line index 6c6439f69a72..0e6268d59883 100755 --- a/scripts/faddr2line +++ b/scripts/faddr2line @@ -44,17 +44,6 @@ set -o errexit set -o nounset -READELF="${CROSS_COMPILE:-}readelf" -ADDR2LINE="${CROSS_COMPILE:-}addr2line" -SIZE="${CROSS_COMPILE:-}size" -NM="${CROSS_COMPILE:-}nm" - -command -v awk >/dev/null 2>&1 || die "awk isn't installed" -command -v ${READELF} >/dev/null 2>&1 || die "readelf isn't installed" -command -v ${ADDR2LINE} >/dev/null 2>&1 || die "addr2line isn't installed" -command -v ${SIZE} >/dev/null 2>&1 || die "size isn't installed" -command -v ${NM} >/dev/null 2>&1 || die "nm isn't installed" - usage() { echo "usage: faddr2line [--list] <object file> <func+offset> <func+offset>..." >&2 exit 1 @@ -69,6 +58,14 @@ die() { exit 1 } +READELF="${CROSS_COMPILE:-}readelf" +ADDR2LINE="${CROSS_COMPILE:-}addr2line" +AWK="awk" + +command -v ${AWK} >/dev/null 2>&1 || die "${AWK} isn't installed" +command -v ${READELF} >/dev/null 2>&1 || die "${READELF} isn't installed" +command -v ${ADDR2LINE} >/dev/null 2>&1 || die "${ADDR2LINE} isn't installed" + # Try to figure out the source directory prefix so we can remove it from the # addr2line output. HACK ALERT: This assumes that start_kernel() is in # init/main.c! This only works for vmlinux. Otherwise it falls back to @@ -76,7 +73,7 @@ die() { find_dir_prefix() { local objfile=$1 - local start_kernel_addr=$(${READELF} -sW $objfile | awk '$8 == "start_kernel" {printf "0x%s", $2}') + local start_kernel_addr=$(${READELF} --symbols --wide $objfile | ${AWK} '$8 == "start_kernel" {printf "0x%s", $2}') [[ -z $start_kernel_addr ]] && return local file_line=$(${ADDR2LINE} -e $objfile $start_kernel_addr) @@ -97,86 +94,133 @@ __faddr2line() { local dir_prefix=$3 local print_warnings=$4 - local func=${func_addr%+*} + local sym_name=${func_addr%+*} local offset=${func_addr#*+} offset=${offset%/*} - local size= - [[ $func_addr =~ "/" ]] && size=${func_addr#*/} + local user_size= + [[ $func_addr =~ "/" ]] && user_size=${func_addr#*/} - if [[ -z $func ]] || [[ -z $offset ]] || [[ $func = $func_addr ]]; then + if [[ -z $sym_name ]] || [[ -z $offset ]] || [[ $sym_name = $func_addr ]]; then warn "bad func+offset $func_addr" DONE=1 return fi # Go through each of the object's symbols which match the func name. - # In rare cases there might be duplicates. - file_end=$(${SIZE} -Ax $objfile | awk '$1 == ".text" {print $2}') - while read symbol; do - local fields=($symbol) - local sym_base=0x${fields[0]} - local sym_type=${fields[1]} - local sym_end=${fields[3]} - - # calculate the size - local sym_size=$(($sym_end - $sym_base)) + # In rare cases there might be duplicates, in which case we print all + # matches. + while read line; do + local fields=($line) + local sym_addr=0x${fields[1]} + local sym_elf_size=${fields[2]} + local sym_sec=${fields[6]} + + # Get the section size: + local sec_size=$(${READELF} --section-headers --wide $objfile | + sed 's/\[ /\[/' | + ${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print "0x" $6; exit }') + + if [[ -z $sec_size ]]; then + warn "bad section size: section: $sym_sec" + DONE=1 + return + fi + + # Calculate the symbol size. + # + # Unfortunately we can't use the ELF size, because kallsyms + # also includes the padding bytes in its size calculation. For + # kallsyms, the size calculation is the distance between the + # symbol and the next symbol in a sorted list. + local sym_size + local cur_sym_addr + local found=0 + while read line; do + local fields=($line) + cur_sym_addr=0x${fields[1]} + local cur_sym_elf_size=${fields[2]} + local cur_sym_name=${fields[7]:-} + + if [[ $cur_sym_addr = $sym_addr ]] && + [[ $cur_sym_elf_size = $sym_elf_size ]] && + [[ $cur_sym_name = $sym_name ]]; then + found=1 + continue + fi + + if [[ $found = 1 ]]; then + sym_size=$(($cur_sym_addr - $sym_addr)) + [[ $sym_size -lt $sym_elf_size ]] && continue; + found=2 + break + fi + done < <(${READELF} --symbols --wide $objfile | ${AWK} -v sec=$sym_sec '$7 == sec' | sort --key=2) + + if [[ $found = 0 ]]; then + warn "can't find symbol: sym_name: $sym_name sym_sec: $sym_sec sym_addr: $sym_addr sym_elf_size: $sym_elf_size" + DONE=1 + return + fi + + # If nothing was found after the symbol, assume it's the last + # symbol in the section. + [[ $found = 1 ]] && sym_size=$(($sec_size - $sym_addr)) + if [[ -z $sym_size ]] || [[ $sym_size -le 0 ]]; then - warn "bad symbol size: base: $sym_base end: $sym_end" + warn "bad symbol size: sym_addr: $sym_addr cur_sym_addr: $cur_sym_addr" DONE=1 return fi + sym_size=0x$(printf %x $sym_size) - # calculate the address - local addr=$(($sym_base + $offset)) + # Calculate the section address from user-supplied offset: + local addr=$(($sym_addr + $offset)) if [[ -z $addr ]] || [[ $addr = 0 ]]; then - warn "bad address: $sym_base + $offset" + warn "bad address: $sym_addr + $offset" DONE=1 return fi addr=0x$(printf %x $addr) - # weed out non-function symbols - if [[ $sym_type != t ]] && [[ $sym_type != T ]]; then - [[ $print_warnings = 1 ]] && - echo "skipping $func address at $addr due to non-function symbol of type '$sym_type'" - continue - fi - - # if the user provided a size, make sure it matches the symbol's size - if [[ -n $size ]] && [[ $size -ne $sym_size ]]; then + # If the user provided a size, make sure it matches the symbol's size: + if [[ -n $user_size ]] && [[ $user_size -ne $sym_size ]]; then [[ $print_warnings = 1 ]] && - echo "skipping $func address at $addr due to size mismatch ($size != $sym_size)" + echo "skipping $sym_name address at $addr due to size mismatch ($user_size != $sym_size)" continue; fi - # make sure the provided offset is within the symbol's range + # Make sure the provided offset is within the symbol's range: if [[ $offset -gt $sym_size ]]; then [[ $print_warnings = 1 ]] && - echo "skipping $func address at $addr due to size mismatch ($offset > $sym_size)" + echo "skipping $sym_name address at $addr due to size mismatch ($offset > $sym_size)" continue fi - # separate multiple entries with a blank line + # In case of duplicates or multiple addresses specified on the + # cmdline, separate multiple entries with a blank line: [[ $FIRST = 0 ]] && echo FIRST=0 - # pass real address to addr2line - echo "$func+$offset/$sym_size:" - local file_lines=$(${ADDR2LINE} -fpie $objfile $addr | sed "s; $dir_prefix\(\./\)*; ;") - [[ -z $file_lines ]] && return + echo "$sym_name+$offset/$sym_size:" + # Pass section address to addr2line and strip absolute paths + # from the output: + local output=$(${ADDR2LINE} -fpie $objfile $addr | sed "s; $dir_prefix\(\./\)*; ;") + [[ -z $output ]] && continue + + # Default output (non --list): if [[ $LIST = 0 ]]; then - echo "$file_lines" | while read -r line + echo "$output" | while read -r line do echo $line done DONE=1; - return + continue fi - # show each line with context - echo "$file_lines" | while read -r line + # For --list, show each line with its corresponding source code: + echo "$output" | while read -r line do echo echo $line @@ -184,12 +228,12 @@ __faddr2line() { n1=$[$n-5] n2=$[$n+5] f=$(echo $line | sed 's/.*at \(.\+\):.*/\1/g') - awk 'NR>=strtonum("'$n1'") && NR<=strtonum("'$n2'") { if (NR=='$n') printf(">%d<", NR); else printf(" %d ", NR); printf("\t%s\n", $0)}' $f + ${AWK} 'NR>=strtonum("'$n1'") && NR<=strtonum("'$n2'") { if (NR=='$n') printf(">%d<", NR); else printf(" %d ", NR); printf("\t%s\n", $0)}' $f done DONE=1 - done < <(${NM} -n $objfile | awk -v fn=$func -v end=$file_end '$3 == fn { found=1; line=$0; start=$1; next } found == 1 { found=0; print line, "0x"$1 } END {if (found == 1) print line, end; }') + done < <(${READELF} --symbols --wide $objfile | ${AWK} -v fn=$sym_name '$4 == "FUNC" && $8 == fn') } [[ $# -lt 2 ]] && usage diff --git a/scripts/gcc-plugins/Kconfig b/scripts/gcc-plugins/Kconfig index 51d81c3f03d6..e383cda05367 100644 --- a/scripts/gcc-plugins/Kconfig +++ b/scripts/gcc-plugins/Kconfig @@ -46,44 +46,6 @@ config GCC_PLUGIN_LATENT_ENTROPY * https://grsecurity.net/ * https://pax.grsecurity.net/ -config GCC_PLUGIN_RANDSTRUCT - bool "Randomize layout of sensitive kernel structures" - select MODVERSIONS if MODULES - help - If you say Y here, the layouts of structures that are entirely - function pointers (and have not been manually annotated with - __no_randomize_layout), or structures that have been explicitly - marked with __randomize_layout, will be randomized at compile-time. - This can introduce the requirement of an additional information - exposure vulnerability for exploits targeting these structure - types. - - Enabling this feature will introduce some performance impact, - slightly increase memory usage, and prevent the use of forensic - tools like Volatility against the system (unless the kernel - source tree isn't cleaned after kernel installation). - - The seed used for compilation is located at - scripts/gcc-plugins/randomize_layout_seed.h. It remains after - a make clean to allow for external modules to be compiled with - the existing seed and will be removed by a make mrproper or - make distclean. - - This plugin was ported from grsecurity/PaX. More information at: - * https://grsecurity.net/ - * https://pax.grsecurity.net/ - -config GCC_PLUGIN_RANDSTRUCT_PERFORMANCE - bool "Use cacheline-aware structure randomization" - depends on GCC_PLUGIN_RANDSTRUCT - depends on !COMPILE_TEST # do not reduce test coverage - help - If you say Y here, the RANDSTRUCT randomization will make a - best effort at restricting randomization to cacheline-sized - groups of elements. It will further not randomize bitfields - in structures. This reduces the performance hit of RANDSTRUCT - at the cost of weakened randomization. - config GCC_PLUGIN_ARM_SSP_PER_TASK bool depends on GCC_PLUGINS && ARM diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile index 1952d3bb80c6..6f0aecad5d67 100644 --- a/scripts/gcc-plugins/Makefile +++ b/scripts/gcc-plugins/Makefile @@ -1,12 +1,17 @@ # SPDX-License-Identifier: GPL-2.0 -$(obj)/randomize_layout_plugin.so: $(objtree)/$(obj)/randomize_layout_seed.h -quiet_cmd_create_randomize_layout_seed = GENSEED $@ +$(obj)/randomize_layout_plugin.so: $(obj)/randomize_layout_seed.h +quiet_cmd_create_randomize_layout_seed = SEEDHDR $@ cmd_create_randomize_layout_seed = \ - $(CONFIG_SHELL) $(srctree)/$(src)/gen-random-seed.sh $@ $(objtree)/include/generated/randomize_layout_hash.h -$(objtree)/$(obj)/randomize_layout_seed.h: FORCE + SEED=$$(cat $(filter-out FORCE,$^) </dev/null); \ + echo '/*' > $@; \ + echo ' * This file is automatically generated. Keep it private.' >> $@; \ + echo ' * Exposing this value will expose the layout of randomized structures.' >> $@; \ + echo ' */' >> $@; \ + echo "const char *randstruct_seed = \"$$SEED\";" >> $@ +$(obj)/randomize_layout_seed.h: $(objtree)/scripts/basic/randstruct.seed FORCE $(call if_changed,create_randomize_layout_seed) -targets += randomize_layout_seed.h randomize_layout_hash.h +targets += randomize_layout_seed.h # Build rules for plugins # @@ -23,10 +28,11 @@ GCC_PLUGINS_DIR = $(shell $(CC) -print-file-name=plugin) plugin_cxxflags = -Wp,-MMD,$(depfile) $(KBUILD_HOSTCXXFLAGS) -fPIC \ -include $(srctree)/include/linux/compiler-version.h \ - -I $(GCC_PLUGINS_DIR)/include -I $(obj) -std=gnu++11 \ - -fno-rtti -fno-exceptions -fasynchronous-unwind-tables \ - -ggdb -Wno-narrowing -Wno-unused-variable \ - -Wno-format-diag + -include $(objtree)/include/generated/utsrelease.h \ + -I $(GCC_PLUGINS_DIR)/include -I $(obj) -std=gnu++11 \ + -fno-rtti -fno-exceptions -fasynchronous-unwind-tables \ + -ggdb -Wno-narrowing -Wno-unused-variable \ + -Wno-format-diag plugin_ldflags = -shared diff --git a/scripts/gcc-plugins/gen-random-seed.sh b/scripts/gcc-plugins/gen-random-seed.sh deleted file mode 100755 index 68af5cc20a64..000000000000 --- a/scripts/gcc-plugins/gen-random-seed.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 - -if [ ! -f "$1" ]; then - SEED=`od -A n -t x8 -N 32 /dev/urandom | tr -d ' \n'` - echo "const char *randstruct_seed = \"$SEED\";" > "$1" - HASH=`echo -n "$SEED" | sha256sum | cut -d" " -f1 | tr -d ' \n'` - echo "#define RANDSTRUCT_HASHED_SEED \"$HASH\"" > "$2" -fi diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c b/scripts/gcc-plugins/latent_entropy_plugin.c index 589454bce930..5d415b2572a8 100644 --- a/scripts/gcc-plugins/latent_entropy_plugin.c +++ b/scripts/gcc-plugins/latent_entropy_plugin.c @@ -82,29 +82,35 @@ __visible int plugin_is_GPL_compatible; static GTY(()) tree latent_entropy_decl; static struct plugin_info latent_entropy_plugin_info = { - .version = "201606141920vanilla", + .version = UTS_RELEASE, .help = "disable\tturn off latent entropy instrumentation\n", }; -static unsigned HOST_WIDE_INT seed; -/* - * get_random_seed() (this is a GCC function) generates the seed. - * This is a simple random generator without any cryptographic security because - * the entropy doesn't come from here. - */ +static unsigned HOST_WIDE_INT deterministic_seed; +static unsigned HOST_WIDE_INT rnd_buf[32]; +static size_t rnd_idx = ARRAY_SIZE(rnd_buf); +static int urandom_fd = -1; + static unsigned HOST_WIDE_INT get_random_const(void) { - unsigned int i; - unsigned HOST_WIDE_INT ret = 0; - - for (i = 0; i < 8 * sizeof(ret); i++) { - ret = (ret << 1) | (seed & 1); - seed >>= 1; - if (ret & 1) - seed ^= 0xD800000000000000ULL; + if (deterministic_seed) { + unsigned HOST_WIDE_INT w = deterministic_seed; + w ^= w << 13; + w ^= w >> 7; + w ^= w << 17; + deterministic_seed = w; + return deterministic_seed; } - return ret; + if (urandom_fd < 0) { + urandom_fd = open("/dev/urandom", O_RDONLY); + gcc_assert(urandom_fd >= 0); + } + if (rnd_idx >= ARRAY_SIZE(rnd_buf)) { + gcc_assert(read(urandom_fd, rnd_buf, sizeof(rnd_buf)) == sizeof(rnd_buf)); + rnd_idx = 0; + } + return rnd_buf[rnd_idx++]; } static tree tree_get_random_const(tree type) @@ -537,8 +543,6 @@ static void latent_entropy_start_unit(void *gcc_data __unused, tree type, id; int quals; - seed = get_random_seed(false); - if (in_lto_p) return; @@ -573,6 +577,12 @@ __visible int plugin_init(struct plugin_name_args *plugin_info, const struct plugin_argument * const argv = plugin_info->argv; int i; + /* + * Call get_random_seed() with noinit=true, so that this returns + * 0 in the case where no seed has been passed via -frandom-seed. + */ + deterministic_seed = get_random_seed(true); + static const struct ggc_root_tab gt_ggc_r_gt_latent_entropy[] = { { .base = &latent_entropy_decl, diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c index 334741a31d0a..ea2aea570404 100644 --- a/scripts/gcc-plugins/randomize_layout_plugin.c +++ b/scripts/gcc-plugins/randomize_layout_plugin.c @@ -34,29 +34,11 @@ __visible int plugin_is_GPL_compatible; static int performance_mode; static struct plugin_info randomize_layout_plugin_info = { - .version = "201402201816vanilla", + .version = UTS_RELEASE, .help = "disable\t\t\tdo not activate plugin\n" "performance-mode\tenable cacheline-aware layout randomization\n" }; -struct whitelist_entry { - const char *pathname; - const char *lhs; - const char *rhs; -}; - -static const struct whitelist_entry whitelist[] = { - /* NIU overloads mapping with page struct */ - { "drivers/net/ethernet/sun/niu.c", "page", "address_space" }, - /* unix_skb_parms via UNIXCB() buffer */ - { "net/unix/af_unix.c", "unix_skb_parms", "char" }, - /* big_key payload.data struct splashing */ - { "security/keys/big_key.c", "path", "void *" }, - /* walk struct security_hook_heads as an array of struct hlist_head */ - { "security/security.c", "hlist_head", "security_hook_heads" }, - { } -}; - /* from old Linux dcache.h */ static inline unsigned long partial_name_hash(unsigned long c, unsigned long prevhash) @@ -742,60 +724,6 @@ static void handle_local_var_initializers(void) } } -static bool type_name_eq(gimple stmt, const_tree type_tree, const char *wanted_name) -{ - const char *type_name; - - if (type_tree == NULL_TREE) - return false; - - switch (TREE_CODE(type_tree)) { - case RECORD_TYPE: - type_name = TYPE_NAME_POINTER(type_tree); - break; - case INTEGER_TYPE: - if (TYPE_PRECISION(type_tree) == CHAR_TYPE_SIZE) - type_name = "char"; - else { - INFORM(gimple_location(stmt), "found non-char INTEGER_TYPE cast comparison: %qT\n", type_tree); - debug_tree(type_tree); - return false; - } - break; - case POINTER_TYPE: - if (TREE_CODE(TREE_TYPE(type_tree)) == VOID_TYPE) { - type_name = "void *"; - break; - } else { - INFORM(gimple_location(stmt), "found non-void POINTER_TYPE cast comparison %qT\n", type_tree); - debug_tree(type_tree); - return false; - } - default: - INFORM(gimple_location(stmt), "unhandled cast comparison: %qT\n", type_tree); - debug_tree(type_tree); - return false; - } - - return strcmp(type_name, wanted_name) == 0; -} - -static bool whitelisted_cast(gimple stmt, const_tree lhs_tree, const_tree rhs_tree) -{ - const struct whitelist_entry *entry; - expanded_location xloc = expand_location(gimple_location(stmt)); - - for (entry = whitelist; entry->pathname; entry++) { - if (!strstr(xloc.file, entry->pathname)) - continue; - - if (type_name_eq(stmt, lhs_tree, entry->lhs) && type_name_eq(stmt, rhs_tree, entry->rhs)) - return true; - } - - return false; -} - /* * iterate over all statements to find "bad" casts: * those where the address of the start of a structure is cast @@ -872,10 +800,7 @@ static unsigned int find_bad_casts_execute(void) #ifndef __DEBUG_PLUGIN if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(ptr_lhs_type))) #endif - { - if (!whitelisted_cast(stmt, ptr_lhs_type, ptr_rhs_type)) - MISMATCH(gimple_location(stmt), "rhs", ptr_lhs_type, ptr_rhs_type); - } + MISMATCH(gimple_location(stmt), "rhs", ptr_lhs_type, ptr_rhs_type); continue; } @@ -898,10 +823,7 @@ static unsigned int find_bad_casts_execute(void) #ifndef __DEBUG_PLUGIN if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(op0_type))) #endif - { - if (!whitelisted_cast(stmt, ptr_lhs_type, op0_type)) - MISMATCH(gimple_location(stmt), "op0", ptr_lhs_type, op0_type); - } + MISMATCH(gimple_location(stmt), "op0", ptr_lhs_type, op0_type); } else { const_tree ssa_name_var = SSA_NAME_VAR(rhs1); /* skip bogus type casts introduced by container_of */ @@ -911,10 +833,7 @@ static unsigned int find_bad_casts_execute(void) #ifndef __DEBUG_PLUGIN if (lookup_attribute("randomize_performed", TYPE_ATTRIBUTES(ptr_rhs_type))) #endif - { - if (!whitelisted_cast(stmt, ptr_lhs_type, ptr_rhs_type)) - MISMATCH(gimple_location(stmt), "ssa", ptr_lhs_type, ptr_rhs_type); - } + MISMATCH(gimple_location(stmt), "ssa", ptr_lhs_type, ptr_rhs_type); } } diff --git a/scripts/gcc-plugins/sancov_plugin.c b/scripts/gcc-plugins/sancov_plugin.c index 23bd023a283b..f3d629555b84 100644 --- a/scripts/gcc-plugins/sancov_plugin.c +++ b/scripts/gcc-plugins/sancov_plugin.c @@ -26,7 +26,7 @@ __visible int plugin_is_GPL_compatible; tree sancov_fndecl; static struct plugin_info sancov_plugin_info = { - .version = "20160402", + .version = UTS_RELEASE, .help = "sancov plugin\n", }; diff --git a/scripts/gcc-plugins/stackleak_plugin.c b/scripts/gcc-plugins/stackleak_plugin.c index 42f0252ee2a4..de817d54b8af 100644 --- a/scripts/gcc-plugins/stackleak_plugin.c +++ b/scripts/gcc-plugins/stackleak_plugin.c @@ -44,7 +44,7 @@ static bool verbose = false; static GTY(()) tree track_function_decl; static struct plugin_info stackleak_plugin_info = { - .version = "201707101337", + .version = UTS_RELEASE, .help = "track-min-size=nn\ttrack stack for functions with a stack frame size >= nn bytes\n" "arch=target_arch\tspecify target build arch\n" "disable\t\tdo not activate the plugin\n" diff --git a/scripts/gcc-plugins/structleak_plugin.c b/scripts/gcc-plugins/structleak_plugin.c index 74e319288389..86b608a24ec0 100644 --- a/scripts/gcc-plugins/structleak_plugin.c +++ b/scripts/gcc-plugins/structleak_plugin.c @@ -37,7 +37,7 @@ __visible int plugin_is_GPL_compatible; static struct plugin_info structleak_plugin_info = { - .version = "20190125vanilla", + .version = UTS_RELEASE, .help = "disable\tdo not activate plugin\n" "byref\tinit structs passed by reference\n" "byref-all\tinit anything passed by reference\n" diff --git a/scripts/gen-randstruct-seed.sh b/scripts/gen-randstruct-seed.sh new file mode 100755 index 000000000000..61017b36c464 --- /dev/null +++ b/scripts/gen-randstruct-seed.sh @@ -0,0 +1,7 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 + +SEED=$(od -A n -t x8 -N 32 /dev/urandom | tr -d ' \n') +echo "$SEED" > "$1" +HASH=$(echo -n "$SEED" | sha256sum | cut -d" " -f1) +echo "#define RANDSTRUCT_HASHED_SEED \"$HASH\"" > "$2" diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index 6212f58b69c6..1389db76cff3 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -92,6 +92,7 @@ sub parse_abi { my $mode = (stat($file))[2]; return if ($mode & S_IFDIR); return if ($file =~ m,/README,); + return if ($file =~ m,/\.,); my $name = $file; $name =~ s,.*/,,; @@ -326,7 +327,7 @@ sub output_rest { my @filepath = split / /, $data{$what}->{filepath}; if ($enable_lineno) { - printf "#define LINENO %s%s#%s\n\n", + printf ".. LINENO %s%s#%s\n\n", $prefix, $file[0], $data{$what}->{line_no}; } @@ -987,7 +988,7 @@ abi_book.pl - parse the Linux ABI files and produce a ReST book. B<abi_book.pl> [--debug <level>] [--enable-lineno] [--man] [--help] [--(no-)rst-source] [--dir=<dir>] [--show-hints] [--search-string <regex>] - <COMAND> [<ARGUMENT>] + <COMMAND> [<ARGUMENT>] Where B<COMMAND> can be: @@ -1022,7 +1023,7 @@ logic (B<--no-rst-source>). =item B<--enable-lineno> -Enable output of #define LINENO lines. +Enable output of .. LINENO lines. =item B<--debug> I<debug level> diff --git a/scripts/get_feat.pl b/scripts/get_feat.pl index 457712355676..76cfb96b59b6 100755 --- a/scripts/get_feat.pl +++ b/scripts/get_feat.pl @@ -13,6 +13,7 @@ my $man; my $debug; my $arch; my $feat; +my $enable_fname; my $basename = abs_path($0); $basename =~ s,/[^/]+$,/,; @@ -31,6 +32,7 @@ GetOptions( 'arch=s' => \$arch, 'feat=s' => \$feat, 'feature=s' => \$feat, + "enable-fname" => \$enable_fname, man => \$man ) or pod2usage(2); @@ -95,6 +97,10 @@ sub parse_feat { return if ($file =~ m,($prefix)/arch-support.txt,); return if (!($file =~ m,arch-support.txt$,)); + if ($enable_fname) { + printf ".. FILE %s\n", abs_path($file); + } + my $subsys = ""; $subsys = $2 if ( m,.*($prefix)/([^/]+).*,); @@ -580,6 +586,11 @@ Output features for a single specific feature. Changes the location of the Feature files. By default, it uses the Documentation/features directory. +=item B<--enable-fname> + +Prints the file name of the feature files. This can be used in order to +track dependencies during documentation build. + =item B<--debug> Put the script in verbose mode, useful for debugging. Can be called multiple diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 54ad86d13784..8caabddf817c 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -108,7 +108,7 @@ static bool is_ignored_symbol(const char *name, char type) /* Symbol names that begin with the following are ignored.*/ static const char * const ignored_prefixes[] = { "$", /* local symbols for ARM, MIPS, etc. */ - ".LASANPC", /* s390 kasan local symbols */ + ".L", /* local labels, .LBB,.Ltmpxxx,.L__unnamed_xx,.LASANPC, etc. */ "__crc_", /* modversions */ "__efistub_", /* arm64 EFI stub namespace */ "__kvm_nvhe_", /* arm64 non-VHE KVM namespace */ diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c index d3c3a61308ad..c4340c90e172 100644 --- a/scripts/kconfig/confdata.c +++ b/scripts/kconfig/confdata.c @@ -658,13 +658,6 @@ static char *escape_string_value(const char *in) return out; } -/* - * Kconfig configuration printer - * - * This printer is used when generating the resulting configuration after - * kconfig invocation and `defconfig' files. Unset symbol might be omitted by - * passing a non-NULL argument to the printer. - */ enum output_n { OUTPUT_N, OUTPUT_N_AS_UNSET, OUTPUT_N_NONE }; static void __print_symbol(FILE *fp, struct symbol *sym, enum output_n output_n, @@ -903,19 +896,20 @@ next: menu = menu->list; continue; } - if (menu->next) + +end_check: + if (!menu->sym && menu_is_visible(menu) && menu != &rootmenu && + menu->prompt->type == P_MENU) { + fprintf(out, "# end of %s\n", menu_get_prompt(menu)); + need_newline = true; + } + + if (menu->next) { menu = menu->next; - else while ((menu = menu->parent)) { - if (!menu->sym && menu_is_visible(menu) && - menu != &rootmenu) { - str = menu_get_prompt(menu); - fprintf(out, "# end of %s\n", str); - need_newline = true; - } - if (menu->next) { - menu = menu->next; - break; - } + } else { + menu = menu->parent; + if (menu) + goto end_check; } } fclose(out); @@ -979,6 +973,7 @@ static int conf_write_autoconf_cmd(const char *autoconf_name) fprintf(out, "\n$(deps_config): ;\n"); + fflush(out); ret = ferror(out); /* error check for all fprintf() calls */ fclose(out); if (ret) @@ -1097,6 +1092,7 @@ static int __conf_write_autoconf(const char *filename, if ((sym->flags & SYMBOL_WRITE) && sym->name) print_symbol(file, sym); + fflush(file); /* check possible errors in conf_write_heading() and print_symbol() */ ret = ferror(file); fclose(file); diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 9c084a2ba3b0..7516949bb049 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -424,7 +424,7 @@ sub get_kernel_version() { sub print_lineno { my $lineno = shift; if ($enable_lineno && defined($lineno)) { - print "#define LINENO " . $lineno . "\n"; + print ".. LINENO " . $lineno . "\n"; } } ## @@ -2478,7 +2478,7 @@ May be specified multiple times. =item -enable-lineno -Enable output of #define LINENO lines. +Enable output of .. LINENO lines. =back diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 666f7bbc13eb..d7f26f02f142 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -50,7 +50,7 @@ gen_initcalls() { info GEN .tmp_initcalls.lds - ${PYTHON} ${srctree}/scripts/jobserver-exec \ + ${PYTHON3} ${srctree}/scripts/jobserver-exec \ ${PERL} ${srctree}/scripts/generate_initcall_order.pl \ ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS} \ > .tmp_initcalls.lds @@ -108,46 +108,68 @@ objtool_link() local objtoolcmd; local objtoolopt; - if is_enabled CONFIG_LTO_CLANG && is_enabled CONFIG_STACK_VALIDATION; then - # Don't perform vmlinux validation unless explicitly requested, - # but run objtool on vmlinux.o now that we have an object file. - if is_enabled CONFIG_UNWINDER_ORC; then - objtoolcmd="orc generate" - fi + if ! is_enabled CONFIG_OBJTOOL; then + return; + fi - objtoolopt="${objtoolopt} --duplicate" + if is_enabled CONFIG_LTO_CLANG || is_enabled CONFIG_X86_KERNEL_IBT; then - if is_enabled CONFIG_FTRACE_MCOUNT_USE_OBJTOOL; then - objtoolopt="${objtoolopt} --mcount" + # For LTO and IBT, objtool doesn't run on individual + # translation units. Run everything on vmlinux instead. + + if is_enabled CONFIG_HAVE_JUMP_LABEL_HACK; then + objtoolopt="${objtoolopt} --hacks=jump_label" fi - fi - if is_enabled CONFIG_VMLINUX_VALIDATION; then - objtoolopt="${objtoolopt} --noinstr" - fi + if is_enabled CONFIG_HAVE_NOINSTR_HACK; then + objtoolopt="${objtoolopt} --hacks=noinstr" + fi - if [ -n "${objtoolopt}" ]; then - if [ -z "${objtoolcmd}" ]; then - objtoolcmd="check" + if is_enabled CONFIG_X86_KERNEL_IBT; then + objtoolopt="${objtoolopt} --ibt" fi - objtoolopt="${objtoolopt} --vmlinux" - if ! is_enabled CONFIG_FRAME_POINTER; then - objtoolopt="${objtoolopt} --no-fp" + + if is_enabled CONFIG_FTRACE_MCOUNT_USE_OBJTOOL; then + objtoolopt="${objtoolopt} --mcount" fi - if is_enabled CONFIG_GCOV_KERNEL || is_enabled CONFIG_LTO_CLANG; then - objtoolopt="${objtoolopt} --no-unreachable" + + if is_enabled CONFIG_UNWINDER_ORC; then + objtoolopt="${objtoolopt} --orc" fi + if is_enabled CONFIG_RETPOLINE; then objtoolopt="${objtoolopt} --retpoline" fi - if is_enabled CONFIG_X86_SMAP; then - objtoolopt="${objtoolopt} --uaccess" - fi + if is_enabled CONFIG_SLS; then objtoolopt="${objtoolopt} --sls" fi + + if is_enabled CONFIG_STACK_VALIDATION; then + objtoolopt="${objtoolopt} --stackval" + fi + + if is_enabled CONFIG_HAVE_STATIC_CALL_INLINE; then + objtoolopt="${objtoolopt} --static-call" + fi + + objtoolopt="${objtoolopt} --uaccess" + fi + + if is_enabled CONFIG_NOINSTR_VALIDATION; then + objtoolopt="${objtoolopt} --noinstr" + fi + + if [ -n "${objtoolopt}" ]; then + + if is_enabled CONFIG_GCOV_KERNEL; then + objtoolopt="${objtoolopt} --no-unreachable" + fi + + objtoolopt="${objtoolopt} --link" + info OBJTOOL ${1} - tools/objtool/objtool ${objtoolcmd} ${objtoolopt} ${1} + tools/objtool/objtool ${objtoolopt} ${1} fi } @@ -168,7 +190,7 @@ vmlinux_link() # skip output file argument shift - if is_enabled CONFIG_LTO_CLANG; then + if is_enabled CONFIG_LTO_CLANG || is_enabled CONFIG_X86_KERNEL_IBT; then # Use vmlinux.o instead of performing the slow LTO link again. objs=vmlinux.o libs= diff --git a/scripts/min-tool-version.sh b/scripts/min-tool-version.sh index 7c20252a90c6..250925aab101 100755 --- a/scripts/min-tool-version.sh +++ b/scripts/min-tool-version.sh @@ -24,9 +24,8 @@ icc) echo 16.0.3 ;; llvm) - # https://lore.kernel.org/r/YMtib5hKVyNknZt3@osiris/ if [ "$SRCARCH" = s390 ]; then - echo 13.0.0 + echo 14.0.0 else echo 11.0.0 fi diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 8a7937452991..ed9d056d2108 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -674,7 +674,7 @@ static void handle_modversion(const struct module *mod, unsigned int crc; if (sym->st_shndx == SHN_UNDEF) { - warn("EXPORT symbol \"%s\" [%s%s] version ...\n" + warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n" "Is \"%s\" prototyped in <asm/asm-prototypes.h>?\n", symname, mod->name, mod->is_vmlinux ? "" : ".ko", symname); @@ -1996,9 +1996,9 @@ static char *remove_dot(char *s) if (m && (s[n + m] == '.' || s[n + m] == 0)) s[n] = 0; - /* strip trailing .lto */ - if (strends(s, ".lto")) - s[strlen(s) - 4] = '\0'; + /* strip trailing .prelink */ + if (strends(s, ".prelink")) + s[strlen(s) - 8] = '\0'; } return s; } @@ -2022,9 +2022,9 @@ static void read_symbols(const char *modname) /* strip trailing .o */ tmp = NOFAIL(strdup(modname)); tmp[strlen(tmp) - 2] = '\0'; - /* strip trailing .lto */ - if (strends(tmp, ".lto")) - tmp[strlen(tmp) - 4] = '\0'; + /* strip trailing .prelink */ + if (strends(tmp, ".prelink")) + tmp[strlen(tmp) - 8] = '\0'; mod = new_module(tmp); free(tmp); } diff --git a/scripts/objdump-func b/scripts/objdump-func new file mode 100755 index 000000000000..4eb463dd9f52 --- /dev/null +++ b/scripts/objdump-func @@ -0,0 +1,29 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Disassemble a single function. +# +# usage: objdump-func <file> <func> + +set -o errexit +set -o nounset + +OBJDUMP="${CROSS_COMPILE:-}objdump" + +command -v gawk >/dev/null 2>&1 || die "gawk isn't installed" + +usage() { + echo "usage: objdump-func <file> <func>" >&2 + exit 1 +} + +[[ $# -lt 2 ]] && usage + +OBJ=$1; shift +FUNC=$1; shift + +# Secret feature to allow adding extra objdump args at the end +EXTRA_ARGS=$@ + +# Note this also matches compiler-added suffixes like ".cold", etc +${OBJDUMP} -wdr $EXTRA_ARGS $OBJ | gawk -M -v f=$FUNC '/^$/ { P=0; } $0 ~ "<" f "(\\..*)?>:" { P=1; O=strtonum("0x" $1); } { if (P) { o=strtonum("0x" $1); printf("%04x ", o-O); print $0; } }' diff --git a/scripts/package/builddeb b/scripts/package/builddeb index 91a502bb97e8..67cd420dcf89 100755 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb @@ -67,7 +67,7 @@ deploy_kernel_headers () { ) > debian/hdrsrcfiles { - if is_enabled CONFIG_STACK_VALIDATION; then + if is_enabled CONFIG_OBJTOOL; then echo tools/objtool/objtool fi diff --git a/scripts/selinux/genheaders/genheaders.c b/scripts/selinux/genheaders/genheaders.c index f355b3e0e968..15520806889e 100644 --- a/scripts/selinux/genheaders/genheaders.c +++ b/scripts/selinux/genheaders/genheaders.c @@ -59,35 +59,27 @@ int main(int argc, char *argv[]) exit(2); } - for (i = 0; secclass_map[i].name; i++) { - struct security_class_mapping *map = &secclass_map[i]; - map->name = stoupperx(map->name); - for (j = 0; map->perms[j]; j++) - map->perms[j] = stoupperx(map->perms[j]); - } - - isids_len = sizeof(initial_sid_to_string) / sizeof (char *); - for (i = 1; i < isids_len; i++) { - const char *s = initial_sid_to_string[i]; - - if (s) - initial_sid_to_string[i] = stoupperx(s); - } - fprintf(fout, "/* This file is automatically generated. Do not edit. */\n"); fprintf(fout, "#ifndef _SELINUX_FLASK_H_\n#define _SELINUX_FLASK_H_\n\n"); for (i = 0; secclass_map[i].name; i++) { - struct security_class_mapping *map = &secclass_map[i]; - fprintf(fout, "#define SECCLASS_%-39s %2d\n", map->name, i+1); + char *name = stoupperx(secclass_map[i].name); + + fprintf(fout, "#define SECCLASS_%-39s %2d\n", name, i+1); + free(name); } fprintf(fout, "\n"); + isids_len = sizeof(initial_sid_to_string) / sizeof(char *); for (i = 1; i < isids_len; i++) { const char *s = initial_sid_to_string[i]; - if (s) - fprintf(fout, "#define SECINITSID_%-39s %2d\n", s, i); + if (s) { + char *sidname = stoupperx(s); + + fprintf(fout, "#define SECINITSID_%-39s %2d\n", sidname, i); + free(sidname); + } } fprintf(fout, "\n#define SECINITSID_NUM %d\n", i-1); fprintf(fout, "\nstatic inline bool security_is_socket_class(u16 kern_tclass)\n"); @@ -96,10 +88,14 @@ int main(int argc, char *argv[]) fprintf(fout, "\tswitch (kern_tclass) {\n"); for (i = 0; secclass_map[i].name; i++) { static char s[] = "SOCKET"; - struct security_class_mapping *map = &secclass_map[i]; - int len = strlen(map->name), l = sizeof(s) - 1; - if (len >= l && memcmp(map->name + len - l, s, l) == 0) - fprintf(fout, "\tcase SECCLASS_%s:\n", map->name); + int len, l; + char *name = stoupperx(secclass_map[i].name); + + len = strlen(name); + l = sizeof(s) - 1; + if (len >= l && memcmp(name + len - l, s, l) == 0) + fprintf(fout, "\tcase SECCLASS_%s:\n", name); + free(name); } fprintf(fout, "\t\tsock = true;\n"); fprintf(fout, "\t\tbreak;\n"); @@ -110,33 +106,52 @@ int main(int argc, char *argv[]) fprintf(fout, "}\n"); fprintf(fout, "\n#endif\n"); - fclose(fout); + + if (fclose(fout) != 0) { + fprintf(stderr, "Could not successfully close %s: %s\n", + argv[1], strerror(errno)); + exit(4); + } fout = fopen(argv[2], "w"); if (!fout) { fprintf(stderr, "Could not open %s for writing: %s\n", argv[2], strerror(errno)); - exit(4); + exit(5); } fprintf(fout, "/* This file is automatically generated. Do not edit. */\n"); fprintf(fout, "#ifndef _SELINUX_AV_PERMISSIONS_H_\n#define _SELINUX_AV_PERMISSIONS_H_\n\n"); for (i = 0; secclass_map[i].name; i++) { - struct security_class_mapping *map = &secclass_map[i]; - int len = strlen(map->name); + const struct security_class_mapping *map = &secclass_map[i]; + int len; + char *name = stoupperx(map->name); + + len = strlen(name); for (j = 0; map->perms[j]; j++) { + char *permname; + if (j >= 32) { fprintf(stderr, "Too many permissions to fit into an access vector at (%s, %s).\n", map->name, map->perms[j]); exit(5); } - fprintf(fout, "#define %s__%-*s 0x%08xU\n", map->name, - 39-len, map->perms[j], 1U<<j); + permname = stoupperx(map->perms[j]); + fprintf(fout, "#define %s__%-*s 0x%08xU\n", name, + 39-len, permname, 1U<<j); + free(permname); } + free(name); } fprintf(fout, "\n#endif\n"); - fclose(fout); + + if (fclose(fout) != 0) { + fprintf(stderr, "Could not successfully close %s: %s\n", + argv[2], strerror(errno)); + exit(6); + } + exit(0); } diff --git a/scripts/selinux/mdp/mdp.c b/scripts/selinux/mdp/mdp.c index 105c1c31a316..1415604c3d24 100644 --- a/scripts/selinux/mdp/mdp.c +++ b/scripts/selinux/mdp/mdp.c @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) /* print out the class permissions */ for (i = 0; secclass_map[i].name; i++) { - struct security_class_mapping *map = &secclass_map[i]; + const struct security_class_mapping *map = &secclass_map[i]; fprintf(fout, "class %s\n", map->name); fprintf(fout, "{\n"); for (j = 0; map->perms[j]; j++) @@ -103,7 +103,7 @@ int main(int argc, char *argv[]) #define SYSTEMLOW "s0" #define SYSTEMHIGH "s1:c0.c1" for (i = 0; secclass_map[i].name; i++) { - struct security_class_mapping *map = &secclass_map[i]; + const struct security_class_mapping *map = &secclass_map[i]; fprintf(fout, "mlsconstrain %s {\n", map->name); for (j = 0; map->perms[j]; j++) diff --git a/scripts/spdxcheck.py b/scripts/spdxcheck.py index ebd06ae642c9..f3be8ed54f6d 100755 --- a/scripts/spdxcheck.py +++ b/scripts/spdxcheck.py @@ -200,7 +200,7 @@ class id_parser(object): tok = pe.tok.value sys.stdout.write('%s: %d:%d %s: %s\n' %(fname, self.curline, col, pe.txt, tok)) else: - sys.stdout.write('%s: %d:0 %s\n' %(fname, self.curline, col, pe.txt)) + sys.stdout.write('%s: %d:0 %s\n' %(fname, self.curline, pe.txt)) self.spdx_errors += 1 def scan_git_tree(tree): diff --git a/scripts/test_fortify.sh b/scripts/test_fortify.sh index a4da365508f0..c2688ab8281d 100644 --- a/scripts/test_fortify.sh +++ b/scripts/test_fortify.sh @@ -46,8 +46,12 @@ if "$@" -Werror -c "$IN" -o "$OUT".o 2> "$TMP" ; then status="warning: unsafe ${FUNC}() usage lacked '$WANT' symbol in $IN" fi else - # If the build failed, check for the warning in the stderr (gcc). - if ! grep -q -m1 "error: call to .\b${WANT}\b." "$TMP" ; then + # If the build failed, check for the warning in the stderr. + # GCC: + # ./include/linux/fortify-string.h:316:25: error: call to '__write_overflow_field' declared with attribute warning: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror=attribute-warning] + # Clang 14: + # ./include/linux/fortify-string.h:316:4: error: call to __write_overflow_field declared with 'warning' attribute: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror,-Wattribute-warning] + if ! grep -Eq -m1 "error: call to .?\b${WANT}\b.?" "$TMP" ; then status="warning: unsafe ${FUNC}() usage lacked '$WANT' warning in $IN" fi fi |