Messages in this thread | | | Date | Thu, 17 Mar 2016 09:08:20 +0100 | From | Ingo Molnar <> | Subject | [GIT PULL] Add build-time kernel stack frame validation support via 'objtool' |
| |
Linus,
Please pull the latest core-objtool-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core-objtool-for-linus
# HEAD: 1bcb58a099938c33acda78b212ed67b06b3359ef objtool: Only print one warning per function
This tree adds a new kernel build-time object file validation feature (ONFIG_STACK_VALIDATION=y): kernel stack frame correctness validation. It was written by and is maintained by Josh Poimboeuf.
The motivation: there's a category of hard to find kernel bugs, most of them in assembly code (but also occasionally in C code), that degrades the quality of kernel stack dumps/backtraces. These bugs are hard to detect at the source code level. Such bugs result in incorrect/incomplete backtraces most of time - but can also in some rare cases result in crashes or other undefined behavior.
The build time correctness checking is done via the new 'objtool' user-space utility that was written for this purpose and which is hosted in the kernel repository in tools/objtool/. The tool's (very simple) UI and source code design is shaped after Git and perf and shares quite a bit of infrastructure with tools/perf (which tooling infrastructure sharing effort got merged via perf and is already upstream). Objtool follows the well-known kernel coding style.
Objtool does not try to check .c or .S files, it instead analyzes the resulting .o generated machine code from first principles: it decodes the instruction stream and interprets it. (Right now objtool supports the x86-64 architecture.)
From tools/objtool/Documentation/stack-validation.txt:
"The kernel CONFIG_STACK_VALIDATION option enables a host tool named objtool which runs at compile time. It has a "check" subcommand which analyzes every .o file and ensures the validity of its stack metadata. It enforces a set of rules on asm code and C inline assembly code so that stack traces can be reliable.
Currently it only checks frame pointer usage, but there are plans to add CFI validation for C files and CFI generation for asm files.
For each function, it recursively follows all possible code paths and validates the correct frame pointer state at each instruction.
It also follows code paths involving special sections, like .altinstructions, __jump_table, and __ex_table, which can add alternative execution paths to a given instruction (or set of instructions). Similarly, it knows how to follow switch statements, for which gcc sometimes uses jump tables."
When this new kernel option is enabled (it's disabled by default), the tool, if it finds any suspicious assembly code pattern, outputs warnings in compiler warning format:
warning: objtool: rtlwifi_rate_mapping()+0x2e7: frame pointer state mismatch warning: objtool: cik_tiling_mode_table_init()+0x6ce: call without frame pointer save/setup warning: objtool:__schedule()+0x3c0: duplicate frame pointer save warning: objtool:__schedule()+0x3fd: sibling call from callable instruction with changed frame pointer
... so that scripts that pick up compiler warnings will notice them. All known warnings triggered by the tool are fixed by the tree, most of the commits in fact prepare the kernel to be warning-free. Most of them are bugfixes or cleanups that stand on their own, but there are also some annotations of 'special' stack frames for justified cases such entries to JIT-ed code (BPF) or really special boot time code.
There are two other long-term motivations behind this tool as well:
- To improve the quality and reliability of kernel stack frames, so that they can be used for optimized live patching.
- To create independent infrastructure to check the correctness of CFI stack frames at build time. CFI debuginfo is notoriously unreliable and we cannot use it in the kernel as-is without extra checking done both on the kernel side and on the build side.
The quality of kernel stack frames matters to debuggability as well, so IMO we can merge this without having to consider the live patching or CFI debuginfo angle.
Thanks,
Ingo
------------------> Alexander Kuleshov (3): x86/asm/entry: Remove unused SAVE_ALL/RESTORE_ALL macros for !CONFIG_x86_64 x86/asm: Remove unused L3_PAGE_OFFSET x86/entry/traps: Refactor preemption and interrupt flag handling
Andy Lutomirski (26): mm: Add a vm_special_mapping.fault() method mm: Add vm_insert_pfn_prot() x86/vdso: Track each mm's loaded vDSO image as well as its base x86/vdso: Use .fault for the vDSO text mapping x86/vdso: Use ->fault() instead of remap_pfn_range() for the vvar mapping x86/vdso: Disallow vvar access to vclock IO for never-used vclocks selftests/x86: Extend Makefile to allow 64-bit-only tests selftests/x86: Add check_initial_reg_state() x86/syscalls: Refactor syscalltbl.sh x86/syscalls: Remove __SYSCALL_COMMON and __SYSCALL_X32 x86/syscalls: Move compat syscall entry handling into syscalltbl.sh x86/syscalls: Add syscall entry qualifiers x86/entry/64: Always run ptregs-using syscalls on the slow path x86/entry/64: Call all native slow-path syscalls with full pt-regs x86/entry/64: Stop using int_ret_from_sys_call in ret_from_fork x86/entry/64: Migrate the 64-bit syscall slow path to C x86/entry/64: Fix an IRQ state error on ptregs-using syscalls x86/entry/64: Fix fast-path syscall return register state x86/syscalls/64: Mark sys_iopl() as using ptregs x86/signal/64: Add a comment about sigcontext->fs and gs x86/signal/64: Fix SS if needed when delivering a 64-bit signal x86/signal/64: Re-add support for SS in the 64-bit signal context selftests/x86: Add tests for UC_SIGCONTEXT_SS and UC_STRICT_RESTORE_SS selftests/x86: Fix some error messages in ptrace_syscall selftests/x86: Add a test for syscall restart under ptrace x86/entry/compat: Keep TS_COMPAT set during signal delivery
Aravind Gopalakrishnan (5): x86/mce: Fix order of AMD MCE init function call x86/mce/AMD: Do not perform shared bank check for future processors x86/mce/AMD: Reduce number of blocks scanned per bank x86/mce/AMD: Fix LVT offset configuration for thresholding x86/mce/AMD: Set MCAX Enable bit
Borislav Petkov (10): x86/cpufeature: Add AMD AVIC bit x86/cpufeature: Carve out X86_FEATURE_* x86/cpufeature: Replace the old static_cpu_has() with safe variant x86/cpufeature: Get rid of the non-asm goto variant x86/alternatives: Add an auxilary section x86/vdso: Use static_cpu_has() x86/mce/AMD: Carve out threshold block preparation x86/cpufeature: Speed up cpu_feature_enabled() x86/ftrace, x86/asm: Kill ftrace_caller_end label x86/msr: Document msr-index.h rule for addition
Brian Gerst (1): x86/alternatives: Discard dynamic check after init
Chris J Arges (2): x86/uaccess: Add stack frame output operand in get_user() inline asm x86/kvm: Add output operand in vmx_handle_external_intr inline asm
Denys Vlasenko (1): x86/asm/bitops: Force inlining of test_and_set_bit and friends
Dmitry V. Levin (1): x86/signal: Cleanup get_nr_restart_syscall()
Ingo Molnar (1): watchdog/hpwdt: Fix build on certain configs
Josh Poimboeuf (51): x86/asm: Clean up frame pointer macros x86/asm: Add C versions of frame pointer macros x86/xen: Add stack frame dependency to hypercall inline asm calls x86/asm/xen: Set ELF function type for xen_adjust_exception_frame() x86/asm/xen: Create stack frames in xen-asm.S x86/paravirt: Add stack frame dependency to PVOP inline asm calls x86/paravirt: Create a stack frame in PV_CALLEE_SAVE_REGS_THUNK x86/amd: Set ELF function type for vide() x86/asm/crypto: Move .Lbswap_mask data to .rodata section x86/asm/crypto: Move jump_table to .rodata section x86/asm/crypto: Simplify stack usage in sha-mb functions x86/asm/crypto: Don't use RBP as a scratch register x86/asm/crypto: Create stack frames in crypto functions x86/asm/entry: Create stack frames in thunk functions x86/asm/acpi: Create a stack frame in do_suspend_lowlevel() x86/asm: Create stack frames in rwsem functions x86/asm/efi: Create a stack frame in efi_call() x86/asm/power: Create stack frames in hibernate_asm_64.S x86/asm/bpf: Annotate callable functions x86/asm/bpf: Create stack frames in bpf_jit.S x86/kprobes: Get rid of kretprobe_trampoline_holder() x86/kvm: Set ELF function type for fastop functions x86/kvm: Make test_cc() always inline watchdog/hpwdt: Create stack frame in asminline_call() x86/locking: Create stack frame in PV unlock sched/x86: Add stack frame dependency to __preempt_schedule[_notrace]() objtool: Mark non-standard object files and directories objtool: Add STACK_FRAME_NON_STANDARD() macro x86/xen: Mark xen_cpuid() stack frame as non-standard bpf: Mark __bpf_prog_run() stack frame as non-standard sched: Mark __schedule() stack frame as non-standard sched: Always inline context_switch() x86/kprobes: Mark kretprobe_trampoline() stack frame as non-standard objtool: Add tool to perform compile-time stack metadata validation objtool: Add CONFIG_STACK_VALIDATION option objtool: Enable stack metadata validation on 64-bit x86 x86/asm/decoder: Use explicitly signed chars objtool: Support CROSS_COMPILE tools: Support relative directory path for 'O=' objtool: Detect and warn if libelf is missing and don't break the build objtool: Prevent infinite recursion in noreturn detection objtool: Detect infinite recursion objtool: Compile with debugging symbols objtool: Fix false positive warnings related to sibling calls objtool: Add helper macros for traversing instructions objtool: Remove superflous INIT_LIST_HEAD objtool: Rename some variables and functions objtool: Fix false positive warnings for functions with multiple switch statements tools: Copy hashtable.h into tools directory objtool: Add several performance improvements objtool: Only print one warning per function
Matthew Wilcox (1): x86/mm: Honour passed pgprot in track_pfn_insert() and track_pfn_remap()
Tony Luck (3): x86/mm: Expand the exception table logic to allow new handling options x86/mce: Check for faults tagged in EXTABLE_CLASS_FAULT exception table entries x86/cpufeature: Create a new synthetic cpu capability for machine check recovery
Documentation/kernel-parameters.txt | 2 +- Documentation/x86/exception-tables.txt | 35 + Documentation/x86/x86_64/boot-options.txt | 2 + MAINTAINERS | 5 + Makefile | 20 +- arch/Kconfig | 6 + arch/x86/Kconfig | 1 + arch/x86/Kconfig.debug | 10 - arch/x86/boot/Makefile | 3 +- arch/x86/boot/compressed/Makefile | 3 +- arch/x86/boot/cpuflags.h | 2 +- arch/x86/boot/mkcpustr.c | 2 +- arch/x86/crypto/aesni-intel_asm.S | 75 +- arch/x86/crypto/camellia-aesni-avx-asm_64.S | 15 + arch/x86/crypto/camellia-aesni-avx2-asm_64.S | 15 + arch/x86/crypto/cast5-avx-x86_64-asm_64.S | 9 + arch/x86/crypto/cast6-avx-x86_64-asm_64.S | 13 + arch/x86/crypto/crc32-pclmul_glue.c | 2 +- arch/x86/crypto/crc32c-intel_glue.c | 2 +- arch/x86/crypto/crc32c-pcl-intel-asm_64.S | 8 +- arch/x86/crypto/crct10dif-pclmul_glue.c | 2 +- arch/x86/crypto/ghash-clmulni-intel_asm.S | 5 + arch/x86/crypto/serpent-avx-x86_64-asm_64.S | 13 + arch/x86/crypto/serpent-avx2-asm_64.S | 13 + arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S | 35 +- arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 36 +- arch/x86/crypto/twofish-avx-x86_64-asm_64.S | 13 + arch/x86/entry/Makefile | 4 + arch/x86/entry/calling.h | 31 - arch/x86/entry/common.c | 48 +- arch/x86/entry/entry_32.S | 2 +- arch/x86/entry/entry_64.S | 276 ++--- arch/x86/entry/syscall_32.c | 10 +- arch/x86/entry/syscall_64.c | 13 +- arch/x86/entry/syscalls/syscall_64.tbl | 20 +- arch/x86/entry/syscalls/syscalltbl.sh | 58 +- arch/x86/entry/thunk_64.S | 4 + arch/x86/entry/vdso/Makefile | 6 +- arch/x86/entry/vdso/vdso2c.h | 7 - arch/x86/entry/vdso/vdso32-setup.c | 1 - arch/x86/entry/vdso/vdso32/system_call.S | 2 +- arch/x86/entry/vdso/vma.c | 127 ++- arch/x86/entry/vsyscall/vsyscall_gtod.c | 9 +- arch/x86/include/asm/alternative.h | 6 - arch/x86/include/asm/apic.h | 1 - arch/x86/include/asm/arch_hweight.h | 2 + arch/x86/include/asm/asm.h | 40 +- arch/x86/include/asm/bitops.h | 36 +- arch/x86/include/asm/clocksource.h | 9 +- arch/x86/include/asm/cmpxchg.h | 1 + arch/x86/include/asm/cpufeature.h | 448 +------- arch/x86/include/asm/cpufeatures.h | 289 +++++ arch/x86/include/asm/desc_defs.h | 23 + arch/x86/include/asm/fpu/internal.h | 15 +- arch/x86/include/asm/frame.h | 59 +- arch/x86/include/asm/irq_work.h | 2 +- arch/x86/include/asm/mce.h | 1 + arch/x86/include/asm/mmu.h | 3 +- arch/x86/include/asm/msr-index.h | 11 +- arch/x86/include/asm/mwait.h | 2 + arch/x86/include/asm/paravirt.h | 9 +- arch/x86/include/asm/paravirt_types.h | 18 +- arch/x86/include/asm/preempt.h | 13 +- arch/x86/include/asm/processor.h | 3 +- arch/x86/include/asm/qspinlock_paravirt.h | 4 + arch/x86/include/asm/sighandling.h | 1 - arch/x86/include/asm/smap.h | 2 +- arch/x86/include/asm/smp.h | 1 - arch/x86/include/asm/thread_info.h | 2 +- arch/x86/include/asm/tlbflush.h | 1 + arch/x86/include/asm/uaccess.h | 21 +- arch/x86/include/asm/uaccess_64.h | 2 +- arch/x86/include/asm/vdso.h | 3 - arch/x86/include/asm/vgtod.h | 6 + arch/x86/include/asm/xen/hypercall.h | 5 +- arch/x86/include/uapi/asm/sigcontext.h | 32 +- arch/x86/include/uapi/asm/ucontext.h | 53 +- arch/x86/kernel/Makefile | 11 +- arch/x86/kernel/acpi/wakeup_64.S | 3 + arch/x86/kernel/apic/apic_numachip.c | 4 +- arch/x86/kernel/asm-offsets_32.c | 2 +- arch/x86/kernel/asm-offsets_64.c | 10 +- arch/x86/kernel/cpu/Makefile | 2 +- arch/x86/kernel/cpu/amd.c | 5 +- arch/x86/kernel/cpu/centaur.c | 2 +- arch/x86/kernel/cpu/common.c | 14 - arch/x86/kernel/cpu/cyrix.c | 1 + arch/x86/kernel/cpu/intel.c | 2 +- arch/x86/kernel/cpu/intel_cacheinfo.c | 2 +- arch/x86/kernel/cpu/match.c | 2 +- arch/x86/kernel/cpu/mcheck/mce-severity.c | 22 +- arch/x86/kernel/cpu/mcheck/mce.c | 85 +- arch/x86/kernel/cpu/mcheck/mce_amd.c | 111 +- arch/x86/kernel/cpu/mkcapflags.sh | 6 +- arch/x86/kernel/cpu/mtrr/main.c | 2 +- arch/x86/kernel/cpu/transmeta.c | 2 +- arch/x86/kernel/e820.c | 1 + arch/x86/kernel/ftrace.c | 11 +- arch/x86/kernel/head_32.S | 2 +- arch/x86/kernel/head_64.S | 1 - arch/x86/kernel/hpet.c | 1 + arch/x86/kernel/kprobes/core.c | 61 +- arch/x86/kernel/mcount_64.S | 14 +- arch/x86/kernel/msr.c | 2 +- arch/x86/kernel/signal.c | 127 ++- arch/x86/kernel/traps.c | 53 +- arch/x86/kernel/verify_cpu.S | 2 +- arch/x86/kernel/vm86_32.c | 2 +- arch/x86/kernel/vmlinux.lds.S | 16 +- arch/x86/kvm/emulate.c | 31 +- arch/x86/kvm/vmx.c | 4 +- arch/x86/lib/clear_page_64.S | 2 +- arch/x86/lib/copy_page_64.S | 2 +- arch/x86/lib/copy_user_64.S | 2 +- arch/x86/lib/insn.c | 6 +- arch/x86/lib/memcpy_64.S | 2 +- arch/x86/lib/memmove_64.S | 2 +- arch/x86/lib/memset_64.S | 2 +- arch/x86/lib/rwsem.S | 11 +- arch/x86/mm/extable.c | 100 +- arch/x86/mm/fault.c | 2 +- arch/x86/mm/pat.c | 4 +- arch/x86/mm/setup_nx.c | 1 + arch/x86/net/bpf_jit.S | 48 +- arch/x86/oprofile/op_model_amd.c | 1 - arch/x86/platform/efi/Makefile | 2 + arch/x86/platform/efi/efi_stub_64.S | 3 + arch/x86/power/hibernate_asm_64.S | 7 + arch/x86/purgatory/Makefile | 2 + arch/x86/realmode/Makefile | 4 +- arch/x86/realmode/rm/Makefile | 3 +- arch/x86/um/asm/barrier.h | 2 +- arch/x86/um/sys_call_table_32.c | 4 +- arch/x86/um/sys_call_table_64.c | 7 +- arch/x86/um/user-offsets.c | 6 +- arch/x86/xen/enlighten.c | 3 +- arch/x86/xen/xen-asm.S | 10 +- arch/x86/xen/xen-asm_64.S | 1 + drivers/cpufreq/intel_pstate.c | 2 +- drivers/firmware/efi/libstub/Makefile | 1 + drivers/watchdog/hpwdt.c | 9 +- fs/btrfs/disk-io.c | 2 +- include/linux/frame.h | 23 + include/linux/mm.h | 2 + include/linux/mm_types.h | 22 +- kernel/bpf/core.c | 2 + kernel/sched/core.c | 4 +- lib/Kconfig.debug | 12 + lib/atomic64_test.c | 2 +- mm/memory.c | 25 +- mm/mmap.c | 13 +- scripts/Makefile.build | 41 +- scripts/mod/Makefile | 2 + scripts/sortextable.c | 32 + tools/Makefile | 14 +- tools/include/asm-generic/bitops/__fls.h | 2 +- tools/include/asm-generic/bitops/fls.h | 2 +- tools/include/asm-generic/bitops/fls64.h | 2 +- tools/include/linux/hashtable.h | 152 +++ tools/lib/subcmd/Makefile | 6 +- tools/objtool/.gitignore | 2 + tools/objtool/Build | 13 + tools/objtool/Documentation/stack-validation.txt | 342 ++++++ tools/objtool/Makefile | 63 ++ tools/objtool/arch.h | 44 + tools/objtool/arch/x86/Build | 12 + tools/objtool/arch/x86/decode.c | 172 +++ tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk | 387 +++++++ tools/objtool/arch/x86/insn/inat.c | 97 ++ tools/objtool/arch/x86/insn/inat.h | 221 ++++ tools/objtool/arch/x86/insn/inat_types.h | 29 + tools/objtool/arch/x86/insn/insn.c | 594 ++++++++++ tools/objtool/arch/x86/insn/insn.h | 201 ++++ tools/objtool/arch/x86/insn/x86-opcode-map.txt | 984 +++++++++++++++++ tools/objtool/builtin-check.c | 1159 ++++++++++++++++++++ tools/objtool/builtin.h | 22 + tools/objtool/elf.c | 412 +++++++ tools/objtool/elf.h | 85 ++ tools/objtool/objtool.c | 136 +++ tools/objtool/special.c | 193 ++++ tools/objtool/special.h | 42 + tools/objtool/warn.h | 60 + tools/perf/util/intel-pt-decoder/insn.c | 6 +- tools/testing/selftests/x86/Makefile | 17 +- .../selftests/x86/check_initial_reg_state.c | 109 ++ tools/testing/selftests/x86/ptrace_syscall.c | 132 ++- tools/testing/selftests/x86/sigreturn.c | 230 +++- 187 files changed, 7751 insertions(+), 1329 deletions(-) create mode 100644 arch/x86/include/asm/cpufeatures.h create mode 100644 include/linux/frame.h create mode 100644 tools/include/linux/hashtable.h create mode 100644 tools/objtool/.gitignore create mode 100644 tools/objtool/Build create mode 100644 tools/objtool/Documentation/stack-validation.txt create mode 100644 tools/objtool/Makefile create mode 100644 tools/objtool/arch.h create mode 100644 tools/objtool/arch/x86/Build create mode 100644 tools/objtool/arch/x86/decode.c create mode 100644 tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk create mode 100644 tools/objtool/arch/x86/insn/inat.c create mode 100644 tools/objtool/arch/x86/insn/inat.h create mode 100644 tools/objtool/arch/x86/insn/inat_types.h create mode 100644 tools/objtool/arch/x86/insn/insn.c create mode 100644 tools/objtool/arch/x86/insn/insn.h create mode 100644 tools/objtool/arch/x86/insn/x86-opcode-map.txt create mode 100644 tools/objtool/builtin-check.c create mode 100644 tools/objtool/builtin.h create mode 100644 tools/objtool/elf.c create mode 100644 tools/objtool/elf.h create mode 100644 tools/objtool/objtool.c create mode 100644 tools/objtool/special.c create mode 100644 tools/objtool/special.h create mode 100644 tools/objtool/warn.h create mode 100644 tools/testing/selftests/x86/check_initial_reg_state.c
[ ... diff omitted for size reasons ... ]
| |