objtool: dynamically detect noreturns
Get series with b4
b4 am [email protected]Versions newest first · linked by author and title
- v3 Latest28 patches 5 repliesIn review
- v227 patches 1 replySuperseded
- v127 patches 3 repliesSuperseded
Patches in v3 No applies recorded yet
| # | Subject and files | Size | Replies | Applied |
|---|---|---|---|---|
| 1/28 | objtool: Remove obsolete noreturns.h entriestools/ | +0 | 0 replies | |
| 2/28 | kbuild: Add CONFIG_OBJTOOL_DEFERREDarch/ lib/ scripts/ +3 more | +19 | 1 reply | |
| 3/28 | kbuild: Add CONFIG_OBJTOOL_CONTROL_FLOWlib/ lib/ | +7 | 1 reply | |
| 4/28 | objtool: Fix dead end detection for sibling callstools/ | +19 | 0 replies | |
| 5/28 | objtool: Refactor the noreturn/dead-end detectiontools/ tools/ | +93 | 0 replies | |
| 6/28 | objtool: Ignore traps after noreturn calls in STT_CODEtools/ | +6 | 0 replies | |
| 7/28 | objtool: Make .discard.stack_frame_non_standard non-allocatableinclude/ | +8 | 0 replies | |
| 8/28 | efi/libstub: Drop .discard.addressable from the stub objectsdrivers/ | +6 | 0 replies | |
| 9/28 | efi/loongarch: Mark loongarch efi_boot_kernel() non-standard for objtooldrivers/ | +8 | 0 replies | |
| 10/28 | objtool: Add ANNOTATE_IGNORE_NORETURN()include/ include/ tools/ +2 more | +29 | 0 replies | |
| 11/28 | LoongArch: Annotate reboot and kexec paths as returnablearch/ arch/ | +6 | 0 replies | |
| 12/28 | kbuild: Defer running objtool to link time for all CFG featureslib/ scripts/ tools/ | +5 | 1 reply | |
| 13/28 | rust: Annotate the intrinsic stubs as returnablerust/ rust/ rust/ +1 more | +26 | 0 replies | |
| 14/28 | panic: Mark abort() __noreturnarch/ arch/ include/ +1 more | +6 | 0 replies | |
| 15/28 | x86/xen: Ignore noreturn status of weak mem_map_via_hcall()arch/ | +1 | 0 replies | |
| 16/28 | objtool: Detect noreturns in weak functionstools/ tools/ | +1 | 0 replies | |
| 17/28 | x86/entry: Make rewind_stack_and_make_dead() a real functionarch/ tools/ | +3 | 0 replies | |
| 18/28 | x86/xen: Make xen_cpu_bringup_again() a real functionarch/ tools/ | +3 | 0 replies | |
| 19/28 | x86/xen: Make xen_start_kernel() noreturnarch/ arch/ tools/ | +2 | 0 replies | |
| 20/28 | x86/boot: Rework how pi startup symbols get exposed to vmlinuxarch/ arch/ arch/ +2 more | +23 | 0 replies | |
| 21/28 | objtool: Fix noreturn detection for non-sibling jumps to SYM_CODEtools/ | +15 | 0 replies | |
| 22/28 | objtool: Add options to write/read exported noreturns to/from a filetools/ tools/ tools/ +1 more | +157 | 0 replies | |
| 23/28 | kbuild: Do the per-module objtool pass right before linkingscripts/ scripts/ scripts/ | +36 | 1 reply | |
| 24/28 | kbuild: Generate the noreturn list and validate modules against itMakefile scripts/ scripts/ +4 more | +29 | 1 reply | |
| 25/28 | objtool: Add ANNOTATE_EXPORTED_NORETURN()include/ tools/ tools/ | +76 | 0 replies | |
| 26/28 | objtool: Annotate all module-exported noreturns and remove noreturns.hdrivers/ include/ include/ +4 more | +9 | 0 replies | |
| 27/28 | objtool: Warn about missing/stale ANNOTATE_EXPORTED_NORETURN() usagetools/ tools/ tools/ | +71 | 0 replies | |
| 28/28 | fixup! objtool: Add options to write/read exported noreturns to/from a filetools/ | +3 | 0 replies |
Reviews trailers per patch
5 of 28 patches have a Reviewed-by or Acked-by.
| Patch | Nicolas Schier |
|---|---|
| 1/28 | |
| 2/28 | R-b |
| 3/28 | R-b |
| 4/28 | |
| 5/28 | |
| 6/28 | |
| 7/28 | |
| 8/28 | |
| 9/28 | |
| 10/28 | |
| 11/28 | |
| 12/28 | A-b |
| 13/28 | |
| 14/28 | |
| 15/28 | |
| 16/28 | |
| 17/28 | |
| 18/28 | |
| 19/28 | |
| 20/28 | |
| 21/28 | |
| 22/28 | |
| 23/28 | R-b |
| 24/28 | R-b |
| 25/28 | |
| 26/28 | |
| 27/28 | |
| 28/28 |
Trailers given in replies are filled; those carried in the patches from earlier versions are outlined with dashes.
Cover letter [PATCH v3 00/28] objtool: dynamically detect noreturns
changes since v2 (https://lore.kernel.org/[email protected]):
- move OBJTOOL_DEFERRED and OBJTOOL_CONTROL_FLOW to OBJTOOL submenu
- remove .discard.addressable from libstub temporary binary before absolute symbol reference check
- fix ppc32 build failures by gating rust annotations on CONFIG_OBJTOOL_DEFERRED
- do rust instrinsic noreturn annotations in source code rather than Makefile
- fix read_exports() for exported aliases
- fix klp .ko copying optimization regression
changes since v1 (https://lore.kernel.org/[email protected]):
- improve commit log for "kbuild: Defer running objtool to link time for all CFG features"
- rebase on v7.3-rc2 to get a proper Sashiko review
-----
The C and rust manual noreturn lists are a maintenance nightmare. Get rid of them by taking advantage of the fact that objtool can run on linked objects (vmlinux.o and modules) and can thus detect noreturns dynamically:
1) When features are enabled which require the noreturn knowledge (i.e., control flow analysis) always defer objtool to run on linked objects. That obsoletes most of noreturns.h. (patch 12)
2) For noreturn functions which are exported by vmlinux, dynamically write their names to a file which is then read by objtool running on modules. That obsoletes most of the remaining noreturns.h entries and the entirety of is_rust_noreturn(). (patch 24)
3) For the (four) noreturn functions which are exported by modules, manually annotate them at their declaration sites with a new ANNOTATE_EXPORTED_NORETURN(). That removes the last few stragglers in noreturns.h. (patch 26)
Josh Poimboeuf (28):
objtool: Remove obsolete noreturns.h entries
kbuild: Add CONFIG_OBJTOOL_DEFERRED
kbuild: Add CONFIG_OBJTOOL_CONTROL_FLOW
objtool: Fix dead end detection for sibling calls
objtool: Refactor the noreturn/dead-end detection
objtool: Ignore traps after noreturn calls in STT_CODE
objtool: Make .discard.stack_frame_non_standard non-allocatable efi/libstub: Drop .discard.addressable from the stub objects efi/loongarch: Mark loongarch efi_boot_kernel() non-standard for
objtool
objtool: Add ANNOTATE_IGNORE_NORETURN()
LoongArch: Annotate reboot and kexec paths as returnable
kbuild: Defer running objtool to link time for all CFG features
rust: Annotate the intrinsic stubs as returnable
panic: Mark abort() __noreturn
x86/xen: Ignore noreturn status of weak mem_map_via_hcall()
objtool: Detect noreturns in weak functions
x86/entry: Make rewind_stack_and_make_dead() a real function x86/xen: Make xen_cpu_bringup_again() a real function x86/xen: Make xen_start_kernel() noreturn
x86/boot: Rework how pi startup symbols get exposed to vmlinux
objtool: Fix noreturn detection for non-sibling jumps to SYM_CODE
objtool: Add options to write/read exported noreturns to/from a file
kbuild: Do the per-module objtool pass right before linking
kbuild: Generate the noreturn list and validate modules against it
objtool: Add ANNOTATE_EXPORTED_NORETURN()
objtool: Annotate all module-exported noreturns and remove noreturns.h
objtool: Warn about missing/stale ANNOTATE_EXPORTED_NORETURN() usage fixup! objtool: Add options to write/read exported noreturns to/from a
file
Makefile | 8 + arch/arc/kernel/traps.c | 4 +- arch/arm/kernel/traps.c | 2 +- arch/loongarch/kernel/machine_kexec.c | 2 + arch/loongarch/kernel/reset.c | 4 + arch/x86/boot/startup/Makefile | 16 +- arch/x86/boot/startup/exports.h | 14 - arch/x86/boot/startup/unprefix.syms | 13 + arch/x86/entry/entry_64.S | 7 +- arch/x86/kernel/vmlinux.lds.S | 2 - arch/x86/platform/pvh/enlighten.c | 1 + arch/x86/xen/enlighten_pv.c | 5 +- arch/x86/xen/xen-head.S | 5 +- arch/x86/xen/xen-ops.h | 2 +- drivers/firmware/efi/libstub/Makefile | 7 +- drivers/firmware/efi/libstub/loongarch.c | 8 + drivers/message/fusion/mptbase.h | 2 + include/kunit/test.h | 1 + include/kunit/try-catch.h | 2 + include/linux/annotate.h | 24 + include/linux/objtool.h | 13 +- include/linux/objtool_types.h | 1 + include/linux/panic.h | 2 +- include/linux/rtc/ds1685.h | 2 + kernel/exit.c | 2 +- lib/Kconfig.debug | 14 + lib/Kconfig.ubsan | 2 +- rust/Makefile | 6 + rust/compiler_builtins.rs | 12 + rust/kernel/.gitignore | 1 + .../kernel/generated_ignore_noreturn_asm.rs.S | 7 + scripts/.gitignore | 1 + scripts/Makefile.build | 31 +- scripts/Makefile.lib | 4 +- scripts/Makefile.modfinal | 35 +- scripts/Makefile.vmlinux_o | 13 +- scripts/link-vmlinux.sh | 3 +- scripts/livepatch/klp-build | 12 +- tools/include/linux/objtool_types.h | 1 + tools/objtool/Documentation/objtool.txt | 30 +- tools/objtool/builtin-check.c | 12 + tools/objtool/check.c | 435 +++++++++++++----- tools/objtool/include/objtool/builtin.h | 2 + tools/objtool/include/objtool/elf.h | 4 + tools/objtool/klp-diff.c | 32 ++ tools/objtool/noreturns.h | 56 --- 46 files changed, 596 insertions(+), 266 deletions(-) delete mode 100644 arch/x86/boot/startup/exports.h create mode 100644 arch/x86/boot/startup/unprefix.syms create mode 100644 rust/kernel/generated_ignore_noreturn_asm.rs.S delete mode 100644 tools/objtool/noreturns.h
Signature · 1 line
2.55.0
drivers/firmware/efi/libstub/Makefile +5 -4
@@ -155,9 +155,10 @@ STUBCOPY_FLAGS-$(CONFIG_LOONGARCH) += --prefix-alloc-sections=.init \ --prefix-symbols=__efistub_ STUBCOPY_RELOC-$(CONFIG_LOONGARCH) := R_LARCH_MARK_LA -# Drop the section created by __ADDRESSABLE() so it doesn't get prefixed. -# Its job is already done. -STUBCOPY_FLAGS-y += --remove-section=.discard.addressable +# Drop the section created by __ADDRESSABLE() from the absolute symbol check +# and the objcopy, otherwise it gets prefixed and doesn't get discared. +STUBCOPY_RM_SECTIONS := --remove-section=.discard.addressable +STUBCOPY_FLAGS-y += $(STUBCOPY_RM_SECTIONS) $(obj)/%.stub.o: $(obj)/%.o FORCE $(call if_changed,stubcopy)
@@ -170,7 +171,7 @@ $(obj)/%.stub.o: $(obj)/%.o FORCE # quiet_cmd_stubcopy = STUBCPY $@ cmd_stubcopy = \ - $(STRIP) --strip-debug -o $@ $<; \ + $(STRIP) --strip-debug $(STUBCOPY_RM_SECTIONS) -o $@ $<; \ if $(OBJDUMP) -r $@ | grep $(STUBCOPY_RELOC-y); then \ echo "$@: absolute symbol references not allowed in the EFI stub" >&2; \ /bin/false; \
lib/Kconfig.debug +14 -14
@@ -570,6 +570,20 @@ config OBJTOOL_WERROR If unsure, say Y. +# For when objtool defers its work to the linked image (vmlinux.o or module.o) +# rather than running on individual translation units. +config OBJTOOL_DEFERRED + def_bool y + depends on OBJTOOL + depends on OBJTOOL_CONTROL_FLOW || NOINSTR_VALIDATION || LTO_CLANG || \ + X86_KERNEL_IBT || KLP_BUILD + +# Objtool reverse-engineers the control flow graph +config OBJTOOL_CONTROL_FLOW + def_bool y + depends on OBJTOOL + depends on UNWINDER_ORC || STACK_VALIDATION || HAVE_UACCESS_VALIDATION + config STACK_VALIDATION bool "Compile-time stack metadata validation" depends on HAVE_STACK_VALIDATION && UNWINDER_FRAME_POINTER
@@ -588,20 +602,6 @@ config NOINSTR_VALIDATION select OBJTOOL default y -# Objtool reverse-engineers the control flow graph -config OBJTOOL_CONTROL_FLOW - def_bool y - depends on OBJTOOL - depends on UNWINDER_ORC || STACK_VALIDATION || HAVE_UACCESS_VALIDATION - -# Objtool defers its work to the linked image (vmlinux.o or module.o) rather -# than running on individual translation units. -config OBJTOOL_DEFERRED - def_bool y - depends on OBJTOOL - depends on OBJTOOL_CONTROL_FLOW || NOINSTR_VALIDATION || LTO_CLANG || \ - X86_KERNEL_IBT || KLP_BUILD - config VMLINUX_MAP bool "Generate vmlinux.map file when linking" depends on EXPERT
rust/.gitignore +0 -1
@@ -6,6 +6,5 @@ doctests_kernel_generated.rs doctests_kernel_generated_kunit.c uapi_generated.rs exports_*_generated.h -intrinsics_annotate_generated.c doc/ test/
rust/Makefile +6 -17
@@ -36,9 +36,6 @@ endif obj-$(CONFIG_RUST) += exports.o -always-$(CONFIG_RUST) += intrinsics_annotate_generated.c -obj-$(CONFIG_RUST) += intrinsics_annotate_generated.o - always-$(CONFIG_RUST) += host/libproc_macro2.rlib host/libquote.rlib host/libsyn.rlib always-$(CONFIG_RUST_KERNEL_DOCTESTS) += doctests_kernel_generated.rs
@@ -52,6 +49,8 @@ ifndef CONFIG_UML always-$(subst y,$(CONFIG_RUST),$(CONFIG_BUG)) += kernel/generated_arch_warn_asm.rs kernel/generated_arch_reachable_asm.rs endif +always-$(subst y,$(CONFIG_RUST),$(CONFIG_OBJTOOL_DEFERRED)) += kernel/generated_ignore_noreturn_asm.rs + # Avoids running `$(RUSTC)` when it may not be available. ifdef CONFIG_RUST
@@ -705,20 +704,6 @@ ifdef CONFIG_PPC32 __udivdi3 __umoddi3 endif -# For objtool, annotate the redirect-intrinsics as returnable. Their call -# sites were compiled against the returnable intrinsics, but the redirected -# versions are noreturn. -quiet_cmd_intrinsics_annotate = GEN $@ - cmd_intrinsics_annotate = { \ - echo '/* Generated by rust/Makefile - do not edit */'; \ - echo '\#include <linux/annotate.h>'; \ - for s in $(redirect-intrinsics); do \ - echo "ANNOTATE_IGNORE_NORETURN(__rust$$s);"; \ - done; } > $@ - -$(obj)/intrinsics_annotate_generated.c: $(srctree)/rust/Makefile FORCE - $(call if_changed,intrinsics_annotate) - ifdef CONFIG_MODVERSIONS cmd_gendwarfksyms = $(if $(skip_gendwarfksyms),, \ $(call rust_exports,$@,"%s\n") | \
@@ -766,6 +751,10 @@ $(obj)/compiler_builtins.o: private rustc_objcopy = -w -W '__*' $(obj)/compiler_builtins.o: $(src)/compiler_builtins.rs $(obj)/core.o FORCE +$(call if_changed_rule,rustc_library) +ifdef CONFIG_OBJTOOL_DEFERRED +$(obj)/compiler_builtins.o: $(obj)/kernel/generated_ignore_noreturn_asm.rs +endif + $(obj)/zerocopy.o: private skip_clippy = 1 $(obj)/zerocopy.o: private skip_gendwarfksyms = 1 $(obj)/zerocopy.o: private rustc_target_envs := $(zerocopy-envs)
rust/compiler_builtins.rs +12 -0
@@ -33,6 +33,18 @@ macro_rules! define_panicking_intrinsics(pub extern "C" fn $ident() {panic! ($reason); } + +// The redirected call sites were compiled against the real +// intrinsics, which return. Tell objtool to ignore the noreturn +// status of the panicking intrinsics. +#[cfg( CONFIG_OBJTOOL_DEFERRED )] + ::core::arch::global_asm!( +include! (concat! ( +env! ("OBJTREE" ), +"/rust/kernel/generated_ignore_noreturn_asm.rs" + )), + sym = sym $ident, + ); )* } );
rust/kernel/.gitignore +1 -0
@@ -3,3 +3,4 @@ /generated_arch_static_branch_asm.rs /generated_arch_warn_asm.rs /generated_arch_reachable_asm.rs +/generated_ignore_noreturn_asm.rs
rust/kernel/generated_ignore_noreturn_asm.rs.S new file +7 -0
@@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <linux/annotate.h> + +// Cut here. + +ASM_ANNOTATE_LABEL({sym}, ANNOTYPE_IGNORE_NORETURN)
scripts/livepatch/klp-build +4 -4
@@ -599,7 +599,7 @@ copy_orig_objects() { xtrace_save "copying original objects" for _file in "${files[@]}"; do - local rel_file="${_file/.ko/.o}" + local rel_file="${_file/%.ko/.o}" local file="$PWD/${_file/%.ko/.ko.o}" local orig_file="$ORIG_DIR/$rel_file" local orig_dir="$(dirname "$orig_file")"
@@ -607,7 +607,7 @@ copy_orig_objects() { [[ ! -f "$file" ]] && die "missing $(basename "$file") for $_file" mkdir -p "$orig_dir" - cp -f "$file" "$orig_dir" + cp -f "$file" "$orig_file" done xtrace_restore
@@ -635,7 +635,7 @@ copy_patched_objects() { xtrace_save "copying changed objects" for _file in "${files[@]}"; do - local rel_file="${_file/.ko/.o}" + local rel_file="${_file/%.ko/.o}" local file="$PWD/${_file/%.ko/.ko.o}" local orig_file="$ORIG_DIR/$rel_file" local patched_file="$PATCHED_DIR/$rel_file"
@@ -646,7 +646,7 @@ copy_patched_objects() { cmp -s "$orig_file" "$file" && continue mkdir -p "$patched_dir" - cp -f "$file" "$patched_dir" + cp -f "$file" "$patched_file" found=1 done xtrace_restore
tools/objtool/check.c +2 -7
@@ -2350,19 +2350,14 @@ static int add_jump_table_alts(struct objtool_file *file)static void read_exports (struct objtool_file *file) {struct section *sec; -struct symbol *func;struct reloc *reloc; sec =find_section_by_name (file->elf,".export_symbol" );if (!sec || !sec->rsec)return ; -for_each_reloc (sec->rsec, reloc) { - func =find_func_by_offset (reloc->sym->sec, - reloc->sym->offset +reloc_addend (reloc)); -if (func) - func->exported =1 ; - } +for_each_reloc (sec->rsec, reloc) + reloc->sym->exported =1 ; }static void set_func_state (struct cfi_state *state)