[GIT PULL] Add build-time kernel stack frame validation support via 'objtool'

From: Ingo Molnar
Date: Thu Mar 17 2016 - 04:09:05 EST


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 ... ]