Skip to contentSkip to conversation

Compile-time stack metadata validation

PATCH In review Josh Poimboeuf 14 participants 133 messages Jan 21, 2016 – Feb 25, 2016 1 message not in the archive

Subsystems (22)
Networking Network drivers x86 KVM +18 more subsystems
lore
Share & tools
lore
#0 lore raw

cover Compile-time stack metadata validation

This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.

v15 can be found here:

https://lkml.kernel.org/r/cover.1450442274.git.jpoimboe-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org

For more information about the motivation behind this patch set, and more details about what it does, see the first patch changelog and tools/stacktool/Documentation/stack-validation.txt.

Patches 1-4 add stacktool and integrate it into the kernel build.

Patches 5-28 are some proposed fixes for several of the warnings reported by stacktool. They've been compile-tested and boot-tested in a VM, but I haven't attempted any meaningful testing for many of them.

Patches 29-33 add some directories, files, and functions to the stacktool whitelist in order to silence false positive warnings.

v16:
- fix all allyesconfig warnings, except for staging
- get rid of STACKTOOL_IGNORE_INSN which is no longer needed
- remove several whitelists in favor of automatically whitelisting any function with a special instruction like ljmp, lret, or vmrun
- split up stacktool patch into 3 parts as suggested by Ingo
- update the global noreturn function list
- detect noreturn function fallthroughs
- skip weak functions in noreturn call detection logic
- add empty function check to noreturn logic
- allow non-section rela symbols for __ex_table sections
- support rare switch table case with jmpq *[addr](%rip)
- don't warn on frame pointer restore without save
- rearrange patch order a bit

v15:
- restructure code for a new cmdline interface "stacktool check" using the new subcommand framework in tools/lib/subcmd
- fix 32 bit build fail (put __sp at end) in paravirt_types.h patch 10 which was reported by 0day

v14:
- make tools/include/linux/list.h self-sufficient
- create FRAME_OFFSET to allow 32-bit code to be able to access function arguments on the stack
- add FRAME_OFFSET usage in crypto patch 14/24: "Create stack frames in aesni-intel_asm.S"
- rename "index" -> "idx" to fix build with some compilers

v13:
- LDFLAGS order fix from Chris J Arges
- new warning fix patches from Chris J Arges
- "--frame-pointer" -> "--check-frame-pointer"

v12:
- rename "stackvalidate" -> "stacktool"
- move from scripts/ to tools/:
- makefile rework
- make a copy of the x86 insn code (and warn if the code diverges)
- use tools/include/linux/list.h
- move warning macros to a new warn.h file
- change wording: "stack validation" -> "stack metadata validation"

v11:
- attempt to answer the "why" question better in the documentation and commit message
- s/FP_SAVE/FRAME_BEGIN/ in documentation

v10:
- add scripts/mod to directory ignores
- remove circular dependencies for ignored objects which are built before stackvalidate
- fix CONFIG_MODVERSIONS incompatibility

v9:
- rename FRAME/ENDFRAME -> FRAME_BEGIN/FRAME_END
- fix jump table issue for when the original instruction is a jump
- drop paravirt thunk alignment patch
- add maintainers to CC for proposed warning fixes

v8:
- add proposed fixes for warnings
- fix all memory leaks
- process ignores earlier and add more ignore checks
- always assume POPCNT alternative is enabled
- drop hweight inline asm fix
- drop __schedule() ignore patch
- change .Ltemp_\@ to .Lstackvalidate_ignore_\@ in asm macro
- fix CONFIG_* checks in asm macros
- add C versions of ignore macros and frame macros
- change ";" to "\n" in C macros
- add ifdef CONFIG_STACK_VALIDATION checks in C ignore macros
- use numbered label in C ignore macro
- add missing break in switch case statement in arch-x86.c

v7:
- sibling call support
- document proposed solution for inline asm() frame pointer issues
- say "kernel entry/exit" instead of "context switch"
- clarify the checking of switch statement jump tables
- discard __stackvalidate_ignore_* sections in linker script
- use .Ltemp_\@ to get a unique label instead of static 3-digit number
- change STACKVALIDATE_IGNORE_FUNC variable to a static
- move STACKVALIDATE_IGNORE_INSN to arch-specific .h file

v6:
- rename asmvalidate -> stackvalidate (again)
- gcc-generated object file support
- recursive branch state analysis
- external jump support
- fixup/exception table support
- jump label support
- switch statement jump table support
- added documentation
- detection of "noreturn" dead end functions
- added a Kbuild mechanism for skipping files and dirs
- moved frame pointer macros to arch/x86/include/asm/frame.h
- moved ignore macros to include/linux/stackvalidate.h

v5:
- stackvalidate -> asmvalidate
- frame pointers only required for non-leaf functions
- check for the use of the FP_SAVE/RESTORE macros instead of manually analyzing code to detect frame pointer usage
- additional checks to ensure each function doesn't leave its boundaries
- make the macros simpler and more flexible
- support for analyzing ALTERNATIVE macros
- simplified the arch interfaces in scripts/asmvalidate/arch.h
- fixed some asmvalidate warnings
- rebased onto latest tip asm cleanups
- many more small changes

v4:
- Changed the default to CONFIG_STACK_VALIDATION=n, until all the asm code can get cleaned up.
- Fixed a stackvalidate error path exit code issue found by Michal Marek.

v3:
- Added a patch to make the push/pop CFI macros arch-independent, as suggested by H. Peter Anvin

v2:
- Fixed memory leaks reported by Petr Mladek

Cc Michal Marek <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Linus Torvalds <torvalds-de/[email protected]>
Cc Andi Kleen <andi-Vw/[email protected]>
Cc Pedro Alves <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Andrew Morton <akpm-de/[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>

Chris J Arges (1):
x86/uaccess: Add stack frame output operand in get_user inline asm

Josh Poimboeuf (32):
x86/stacktool: Compile-time stack metadata validation kbuild/stacktool: Add CONFIG_STACK_VALIDATION option x86/stacktool: Enable stacktool on x86_64
x86/stacktool: Add STACKTOOL_IGNORE_FUNC macro
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: Add stack frame dependency to test_cc() inline asm watchdog/hpwdt: Create stack frame in asminline_call() x86/locking: Create stack frame in PV unlock x86/stacktool: Add directory and file whitelists x86/xen: Add xen_cpuid() to stacktool whitelist
bpf: Add __bpf_prog_run() to stacktool whitelist
sched: Add __schedule() to stacktool whitelist x86/kprobes: Add kretprobe_trampoline() to stacktool whitelist

 MAINTAINERS                                        |   6 +
 Makefile                                           |   5 +-
 arch/Kconfig                                       |   6 +
 arch/x86/Kconfig                                   |   1 +
 arch/x86/boot/Makefile                             |   1 +
 arch/x86/boot/compressed/Makefile                  |   3 +-
 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/crc32c-pcl-intel-asm_64.S          |   8 +-
 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/thunk_64.S                          |   4 +
 arch/x86/entry/vdso/Makefile                       |   5 +-
 arch/x86/include/asm/paravirt.h                    |   9 +-
 arch/x86/include/asm/paravirt_types.h              |  18 +-
 arch/x86/include/asm/qspinlock_paravirt.h          |   4 +
 arch/x86/include/asm/uaccess.h                     |   5 +-
 arch/x86/include/asm/xen/hypercall.h               |   5 +-
 arch/x86/kernel/Makefile                           |   5 +
 arch/x86/kernel/acpi/wakeup_64.S                   |   3 +
 arch/x86/kernel/cpu/amd.c                          |   5 +-
 arch/x86/kernel/kprobes/core.c                     |  59 +-
 arch/x86/kernel/vmlinux.lds.S                      |   5 +-
 arch/x86/kvm/emulate.c                             |  33 +-
 arch/x86/lib/rwsem.S                               |  11 +-
 arch/x86/net/bpf_jit.S                             |  48 +-
 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/xen/enlighten.c                           |   3 +-
 arch/x86/xen/xen-asm.S                             |  10 +-
 arch/x86/xen/xen-asm_64.S                          |   1 +
 drivers/firmware/efi/libstub/Makefile              |   1 +
 drivers/watchdog/hpwdt.c                           |   8 +-
 include/linux/stacktool.h                          |  23 +
 kernel/bpf/core.c                                  |   2 +
 kernel/sched/core.c                                |   2 +
 lib/Kconfig.debug                                  |  12 +
 scripts/Makefile.build                             |  38 +-
 scripts/mod/Makefile                               |   2 +
 tools/Makefile                                     |  14 +-
 tools/stacktool/.gitignore                         |   2 +
 tools/stacktool/Build                              |  13 +
 tools/stacktool/Documentation/stack-validation.txt | 333 +++++++
 tools/stacktool/Makefile                           |  60 ++
 tools/stacktool/arch.h                             |  44 +
 tools/stacktool/arch/x86/Build                     |  12 +
 tools/stacktool/arch/x86/decode.c                  | 172 ++++
 .../stacktool/arch/x86/insn/gen-insn-attr-x86.awk  | 387 ++++++++
 tools/stacktool/arch/x86/insn/inat.c               |  97 ++
 tools/stacktool/arch/x86/insn/inat.h               | 221 +++++
 tools/stacktool/arch/x86/insn/inat_types.h         |  29 +
 tools/stacktool/arch/x86/insn/insn.c               | 594 ++++++++++++
 tools/stacktool/arch/x86/insn/insn.h               | 201 +++++
 tools/stacktool/arch/x86/insn/x86-opcode-map.txt   | 984 ++++++++++++++++++++
 tools/stacktool/builtin-check.c                    | 991 +++++++++++++++++++++
 tools/stacktool/builtin.h                          |  22 +
 tools/stacktool/elf.c                              | 403 +++++++++
 tools/stacktool/elf.h                              |  79 ++
 tools/stacktool/special.c                          | 193 ++++
 tools/stacktool/special.h                          |  42 +
 tools/stacktool/stacktool.c                        | 134 +++
 tools/stacktool/warn.h                             |  60 ++
 74 files changed, 5516 insertions(+), 189 deletions(-)
 create mode 100644 include/linux/stacktool.h
 create mode 100644 tools/stacktool/.gitignore
 create mode 100644 tools/stacktool/Build
 create mode 100644 tools/stacktool/Documentation/stack-validation.txt
 create mode 100644 tools/stacktool/Makefile
 create mode 100644 tools/stacktool/arch.h
 create mode 100644 tools/stacktool/arch/x86/Build
 create mode 100644 tools/stacktool/arch/x86/decode.c
 create mode 100644 tools/stacktool/arch/x86/insn/gen-insn-attr-x86.awk
 create mode 100644 tools/stacktool/arch/x86/insn/inat.c
 create mode 100644 tools/stacktool/arch/x86/insn/inat.h
 create mode 100644 tools/stacktool/arch/x86/insn/inat_types.h
 create mode 100644 tools/stacktool/arch/x86/insn/insn.c
 create mode 100644 tools/stacktool/arch/x86/insn/insn.h
 create mode 100644 tools/stacktool/arch/x86/insn/x86-opcode-map.txt
 create mode 100644 tools/stacktool/builtin-check.c
 create mode 100644 tools/stacktool/builtin.h
 create mode 100644 tools/stacktool/elf.c
 create mode 100644 tools/stacktool/elf.h
 create mode 100644 tools/stacktool/special.c
 create mode 100644 tools/stacktool/special.h
 create mode 100644 tools/stacktool/stacktool.c
 create mode 100644 tools/stacktool/warn.h
Signature · 6 lines
2.4.3

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#1 lore raw

PATCH 1/33 x86/stacktool: Compile-time stack metadata validation

This adds a host tool named stacktool which analyzes .o files to ensure the validity of stack metadata. It enforces a set of rules on asm code and C inline assembly code so that stack traces can be reliable.

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

Here are some of the benefits of validating stack metadata:

a) More reliable stack traces for frame pointer enabled kernels

Frame pointers are used for debugging purposes. They allow runtime code and debug tools to be able to walk the stack to determine the chain of function call sites that led to the currently executing code.

For some architectures, frame pointers are enabled by CONFIG_FRAME_POINTER. For some other architectures they may be required by the ABI (sometimes referred to as "backchain pointers").

For C code, gcc automatically generates instructions for setting up frame pointers when the -fno-omit-frame-pointer option is used.

But for asm code, the frame setup instructions have to be written by hand, which most people don't do. So the end result is that CONFIG_FRAME_POINTER is honored for C code but not for most asm code.

For stack traces based on frame pointers to be reliable, all functions which call other functions must first create a stack frame and update the frame pointer. If a first function doesn't properly create a stack frame before calling a second function, the *caller* of the first function will be skipped on the stack trace.

For example, consider the following example backtrace with frame pointers enabled:

     [<ffffffff81812584>] dump_stack+0x4b/0x63
     [<ffffffff812d6dc2>] cmdline_proc_show+0x12/0x30
     [<ffffffff8127f568>] seq_read+0x108/0x3e0
     [<ffffffff812cce62>] proc_reg_read+0x42/0x70
     [<ffffffff81256197>] __vfs_read+0x37/0x100
     [<ffffffff81256b16>] vfs_read+0x86/0x130
     [<ffffffff81257898>] SyS_read+0x58/0xd0
     [<ffffffff8181c1f2>] entry_SYSCALL_64_fastpath+0x12/0x76

It correctly shows that the caller of cmdline_proc_show() is seq_read().

If we remove the frame pointer logic from cmdline_proc_show() by replacing the frame pointer related instructions with nops, here's what it looks like instead:

     [<ffffffff81812584>] dump_stack+0x4b/0x63
     [<ffffffff812d6dc2>] cmdline_proc_show+0x12/0x30
     [<ffffffff812cce62>] proc_reg_read+0x42/0x70
     [<ffffffff81256197>] __vfs_read+0x37/0x100
     [<ffffffff81256b16>] vfs_read+0x86/0x130
     [<ffffffff81257898>] SyS_read+0x58/0xd0
     [<ffffffff8181c1f2>] entry_SYSCALL_64_fastpath+0x12/0x76

Notice that cmdline_proc_show()'s caller, seq_read(), has been skipped. Instead the stack trace seems to show that cmdline_proc_show() was called by proc_reg_read().

The benefit of stacktool here is that because it ensures that *all* functions honor CONFIG_FRAME_POINTER, no functions will ever[*] be skipped on a stack trace.

[*] unless an interrupt or exception has occurred at the very
beginning of a function before the stack frame has been created, or at the very end of the function after the stack frame has been destroyed. This is an inherent limitation of frame pointers.

b) 100% reliable stack traces for DWARF enabled kernels

This is not yet implemented. For more details about what is planned, see tools/stacktool/Documentation/stack-validation.txt.

c) Higher live patching compatibility rate

This is not yet implemented. For more details about what is planned, see tools/stacktool/Documentation/stack-validation.txt.

To achieve the validation, stacktool enforces the following rules:

1. Each callable function must be annotated as such with the ELF function type. In asm code, this is typically done using the ENTRY/ENDPROC macros. If stacktool finds a return instruction outside of a function, it flags an error since that usually indicates callable code which should be annotated accordingly.

This rule is needed so that stacktool can properly identify each callable function in order to analyze its stack metadata.

2. Conversely, each section of code which is *not* callable should *not* be annotated as an ELF function. The ENDPROC macro shouldn't be used in this case.

This rule is needed so that stacktool can ignore non-callable code. Such code doesn't have to follow any of the other rules.

3. Each callable function which calls another function must have the correct frame pointer logic, if required by CONFIG_FRAME_POINTER or the architecture's back chain rules. This can by done in asm code with the FRAME_BEGIN/FRAME_END macros.

This rule ensures that frame pointer based stack traces will work as designed. If function A doesn't create a stack frame before calling function B, the _caller_ of function A will be skipped on the stack trace.

4. Dynamic jumps and jumps to undefined symbols are only allowed if:

a) the jump is part of a switch statement; or

b) the jump matches sibling call semantics and the frame pointer has the same value it had on function entry.

This rule is needed so that stacktool can reliably analyze all of a function's code paths. If a function jumps to code in another file, and it's not a sibling call, stacktool has no way to follow the jump because it only analyzes a single file at a time.

5. A callable function may not execute kernel entry/exit instructions. The only code which needs such instructions is kernel entry code, which shouldn't be be in callable functions anyway.

This rule is just a sanity check to ensure that callable functions return normally.

It currently only supports x86_64. I tried to make the code generic so that support for other architectures can hopefully be plugged in relatively easily.

On my Lenovo laptop with a i7-4810MQ 4-core/8-thread CPU, building the kernel with stacktool checking every .o file adds about three seconds of total build time. It hasn't been optimized for performance yet, so there are probably some opportunities for better build performance.

---
 MAINTAINERS                                        |   5 +
 tools/Makefile                                     |  14 +-
 tools/stacktool/.gitignore                         |   2 +
 tools/stacktool/Build                              |  13 +
 tools/stacktool/Documentation/stack-validation.txt | 333 +++++++
 tools/stacktool/Makefile                           |  60 ++
 tools/stacktool/arch.h                             |  44 +
 tools/stacktool/arch/x86/Build                     |  12 +
 tools/stacktool/arch/x86/decode.c                  | 172 ++++
 .../stacktool/arch/x86/insn/gen-insn-attr-x86.awk  | 387 ++++++++
 tools/stacktool/arch/x86/insn/inat.c               |  97 ++
 tools/stacktool/arch/x86/insn/inat.h               | 221 +++++
 tools/stacktool/arch/x86/insn/inat_types.h         |  29 +
 tools/stacktool/arch/x86/insn/insn.c               | 594 ++++++++++++
 tools/stacktool/arch/x86/insn/insn.h               | 201 +++++
 tools/stacktool/arch/x86/insn/x86-opcode-map.txt   | 984 ++++++++++++++++++++
 tools/stacktool/builtin-check.c                    | 991 +++++++++++++++++++++
 tools/stacktool/builtin.h                          |  22 +
 tools/stacktool/elf.c                              | 403 +++++++++
 tools/stacktool/elf.h                              |  79 ++
 tools/stacktool/special.c                          | 193 ++++
 tools/stacktool/special.h                          |  42 +
 tools/stacktool/stacktool.c                        | 134 +++
 tools/stacktool/warn.h                             |  60 ++
 24 files changed, 5086 insertions(+), 6 deletions(-)
 create mode 100644 tools/stacktool/.gitignore
 create mode 100644 tools/stacktool/Build
 create mode 100644 tools/stacktool/Documentation/stack-validation.txt
 create mode 100644 tools/stacktool/Makefile
 create mode 100644 tools/stacktool/arch.h
 create mode 100644 tools/stacktool/arch/x86/Build
 create mode 100644 tools/stacktool/arch/x86/decode.c
 create mode 100644 tools/stacktool/arch/x86/insn/gen-insn-attr-x86.awk
 create mode 100644 tools/stacktool/arch/x86/insn/inat.c
 create mode 100644 tools/stacktool/arch/x86/insn/inat.h
 create mode 100644 tools/stacktool/arch/x86/insn/inat_types.h
 create mode 100644 tools/stacktool/arch/x86/insn/insn.c
 create mode 100644 tools/stacktool/arch/x86/insn/insn.h
 create mode 100644 tools/stacktool/arch/x86/insn/x86-opcode-map.txt
 create mode 100644 tools/stacktool/builtin-check.c
 create mode 100644 tools/stacktool/builtin.h
 create mode 100644 tools/stacktool/elf.c
 create mode 100644 tools/stacktool/elf.h
 create mode 100644 tools/stacktool/special.c
 create mode 100644 tools/stacktool/special.h
 create mode 100644 tools/stacktool/stacktool.c
 create mode 100644 tools/stacktool/warn.h
MAINTAINERS +5 -0
index ab68d05..7ecbea9 100644
@@ -10186,6 +10186,11 @@ L:	[email protected]
 S:	Supported
 F:	Documentation/stable_kernel_rules.txt
 
+STACK METADATA VALIDATION
+M:	Josh Poimboeuf <[email protected]>
+S:	Supported
+F:	tools/stacktool/
+
 STAGING SUBSYSTEM
 M:	Greg Kroah-Hartman <[email protected]>
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
tools/Makefile +8 -6
index 6339f6a..ac4f97a 100644
@@ -20,6 +20,7 @@ help:
 	@echo '  perf                   - Linux performance measurement and analysis tool'
 	@echo '  selftests              - various kernel selftests'
 	@echo '  spi                    - spi tools'
+	@echo '  stacktool              - a stack metadata validation tool'
 	@echo '  tmon                   - thermal monitoring and tuning tool'
 	@echo '  turbostat              - Intel CPU idle stats and freq reporting tool'
 	@echo '  usb                    - USB testing tools'
@@ -53,7 +54,7 @@ acpi: FORCE
 cpupower: FORCE
 	$(call descend,power/$@)
 
-cgroup firewire hv guest spi usb virtio vm net iio: FORCE
+cgroup firewire hv guest spi usb virtio vm net iio stacktool: FORCE
 	$(call descend,$@)
 
 liblockdep: FORCE
@@ -85,7 +86,7 @@ freefall: FORCE
 all: acpi cgroup cpupower hv firewire lguest \
 		perf selftests turbostat usb \
 		virtio vm net x86_energy_perf_policy \
-		tmon freefall
+		tmon freefall stacktool
 
 acpi_install:
 	$(call descend,power/$(@:_install=),install)
@@ -93,7 +94,7 @@ acpi_install:
 cpupower_install:
 	$(call descend,power/$(@:_install=),install)
 
-cgroup_install firewire_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install:
+cgroup_install firewire_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install stacktool_install:
 	$(call descend,$(@:_install=),install)
 
 selftests_install:
@@ -111,7 +112,7 @@ freefall_install:
 install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \
 		perf_install selftests_install turbostat_install usb_install \
 		virtio_install vm_install net_install x86_energy_perf_policy_install \
-		tmon_install freefall_install
+		tmon_install freefall_install stacktool_install
 
 acpi_clean:
 	$(call descend,power/acpi,clean)
@@ -119,7 +120,7 @@ acpi_clean:
 cpupower_clean:
 	$(call descend,power/cpupower,clean)
 
-cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean:
+cgroup_clean hv_clean firewire_clean lguest_clean spi_clean usb_clean virtio_clean vm_clean net_clean iio_clean stacktool_clean:
 	$(call descend,$(@:_clean=),clean)
 
 liblockdep_clean:
@@ -155,6 +156,7 @@ build_clean:
 clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean lguest_clean \
 		perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \
 		vm_clean net_clean iio_clean x86_energy_perf_policy_clean tmon_clean \
-		freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean
+		freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \
+		stacktool_clean
 
 .PHONY: FORCE
tools/stacktool/.gitignore new file +2 -0
new file mode 100644
index 0000000..6023f61
@@ -0,0 +1,2 @@
+arch/x86/insn/inat-tables.c
+stacktool
tools/stacktool/Build new file +13 -0
new file mode 100644
index 0000000..9f697e6
@@ -0,0 +1,13 @@
+stacktool-y += arch/$(ARCH)/
+stacktool-y += builtin-check.o
+stacktool-y += elf.o
+stacktool-y += special.o
+stacktool-y += stacktool.o
+
+stacktool-y += libstring.o
+
+CFLAGS += -I$(srctree)/tools/lib
+
+$(OUTPUT)libstring.o: ../lib/string.c FORCE
+	$(call rule_mkdir)
+	$(call if_changed_dep,cc_o_c)
tools/stacktool/Documentation/stack-validation.txt new file +333 -0

333 lines not on this page · raw message

tools/stacktool/Makefile new file +60 -0

60 lines not on this page · raw message

tools/stacktool/arch.h new file +44 -0

44 lines not on this page · raw message

tools/stacktool/arch/x86/Build new file +12 -0
new file mode 100644
index 0000000..9b9777d
@@ -0,0 +1,12 @@
+stacktool-y += decode.o
+
+inat_tables_script = arch/x86/insn/gen-insn-attr-x86.awk
+inat_tables_maps = arch/x86/insn/x86-opcode-map.txt
+
+$(OUTPUT)arch/x86/insn/inat-tables.c: $(inat_tables_script) $(inat_tables_maps)
+	$(call rule_mkdir)
+	$(Q)$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@
+
+$(OUTPUT)arch/x86/decode.o: $(OUTPUT)arch/x86/insn/inat-tables.c
+
+CFLAGS_decode.o += -I$(OUTPUT)arch/x86/insn
tools/stacktool/arch/x86/decode.c new file +172 -0

172 lines not on this page · raw message

tools/stacktool/arch/x86/insn/gen-insn-attr-x86.awk new file +387 -0

387 lines not on this page · raw message

tools/stacktool/arch/x86/insn/inat.c new file +97 -0

97 lines not on this page · raw message

tools/stacktool/arch/x86/insn/inat.h new file +221 -0

221 lines not on this page · raw message

tools/stacktool/arch/x86/insn/inat_types.h new file +29 -0
new file mode 100644
index 0000000..cb3c20c
@@ -0,0 +1,29 @@
+#ifndef _ASM_X86_INAT_TYPES_H
+#define _ASM_X86_INAT_TYPES_H
+/*
+ * x86 instruction attributes
+ *
+ * Written by Masami Hiramatsu <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+/* Instruction attributes */
+typedef unsigned int insn_attr_t;
+typedef unsigned char insn_byte_t;
+typedef signed int insn_value_t;
+
+#endif
tools/stacktool/arch/x86/insn/insn.c new file +594 -0

594 lines not on this page · raw message

tools/stacktool/arch/x86/insn/insn.h new file +201 -0

201 lines not on this page · raw message

tools/stacktool/arch/x86/insn/x86-opcode-map.txt new file +984 -0

769 lines not on this page · raw message

tools/stacktool/builtin-check.c new file +991 -0

991 lines not on this page · raw message

tools/stacktool/builtin.h new file +22 -0
new file mode 100644
index 0000000..34d2ba7

Lines of this file are not shown. View the raw message.

tools/stacktool/elf.c new file +403 -0

403 lines not on this page · raw message

tools/stacktool/elf.h new file +79 -0

79 lines not on this page · raw message

tools/stacktool/special.c new file +193 -0

193 lines not on this page · raw message

tools/stacktool/special.h new file +42 -0

42 lines not on this page · raw message

tools/stacktool/stacktool.c new file +134 -0

134 lines not on this page · raw message

tools/stacktool/warn.h new file +60 -0

60 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.4.3

Part of the diff is not shown here. View the raw message.

#2 lore raw

PATCH 2/33 kbuild/stacktool: Add CONFIG_STACK_VALIDATION option

In reply to Josh Poimboeuf

Add a CONFIG_STACK_VALIDATION option which will run "stacktool check" for each .o file to ensure the validity of its stack metadata.

---
 Makefile               |  5 ++++-
 arch/Kconfig           |  6 ++++++
 lib/Kconfig.debug      | 12 ++++++++++++
 scripts/Makefile.build | 38 ++++++++++++++++++++++++++++++++++----
 scripts/mod/Makefile   |  2 ++
 5 files changed, 58 insertions(+), 5 deletions(-)
Makefile +4 -1
index 70dea02..8e518fe 100644
@@ -986,7 +986,10 @@ prepare0: archprepare FORCE
 	$(Q)$(MAKE) $(build)=.
 
 # All the preparing..
-prepare: prepare0
+prepare: prepare0 prepare-stacktool
+
+PHONY += prepare-stacktool
+prepare-stacktool: $(if $(CONFIG_STACK_VALIDATION), tools/stacktool FORCE)
 
 # Generate some files
 # ---------------------------------------------------------------------------
arch/Kconfig +6 -0
index 671810c..b20f472 100644
@@ -527,6 +527,12 @@ config HAVE_COPY_THREAD_TLS
 	  normal C parameter passing, rather than extracting the syscall
 	  argument from pt_regs.
 
+config HAVE_STACK_VALIDATION
+	bool
+	help
+	  Architecture supports the stacktool host tool, which adds
+	  compile-time stack metadata validation.
+
 #
 # ABI hall of shame
 #
lib/Kconfig.debug +12 -0
index ee1ac1c..a984656 100644
@@ -342,6 +342,18 @@ config FRAME_POINTER
 	  larger and slower, but it gives very useful debugging information
 	  in case of kernel bugs. (precise oopses/stacktraces/warnings)
 
+config STACK_VALIDATION
+	bool "Enable compile-time stack metadata validation"
+	depends on HAVE_STACK_VALIDATION
+	default n
+	help
+	  Add compile-time checks to validate stack metadata, including frame
+	  pointers (if CONFIG_FRAME_POINTER is enabled).  This helps ensure
+	  that runtime stack traces are more reliable.
+
+	  For more information, see
+	  tools/stacktool/Documentation/stack-validation.txt.
+
 config DEBUG_FORCE_WEAK_PER_CPU
 	bool "Force weak per-cpu definitions"
 	depends on DEBUG_KERNEL
scripts/Makefile.build +34 -4
index 01df30a..5ec40fc 100644
@@ -241,10 +241,31 @@ cmd_record_mcount =						\
 	fi;
 endif
 
+ifdef CONFIG_STACK_VALIDATION
+
+__stacktool_obj := $(objtree)/tools/stacktool/stacktool
+
+stacktool_args = check
+ifndef CONFIG_FRAME_POINTER
+stacktool_args += --no-fp
+endif
+
+# Set STACKTOOL_foo.o=n to skip stack metadata validation for a file.
+# Set STACKTOOL=n to skip stack metadata validation for a directory.
+stacktool_obj = $(if $(patsubst n%,, \
+	$(STACKTOOL_$(basetarget).o)$(STACKTOOL)y), \
+	$(__stacktool_obj))
+cmd_stacktool = $(if $(patsubst n%,, \
+	$(STACKTOOL_$(basetarget).o)$(STACKTOOL)y), \
+	$(__stacktool_obj) $(stacktool_args) "$(@)";)
+
+endif # CONFIG_STACK_VALIDATION
+
 define rule_cc_o_c
 	$(call echo-cmd,checksrc) $(cmd_checksrc)			  \
 	$(call echo-cmd,cc_o_c) $(cmd_cc_o_c);				  \
 	$(cmd_modversions)						  \
+	$(cmd_stacktool)						  \
 	$(call echo-cmd,record_mcount)					  \
 	$(cmd_record_mcount)						  \
 	scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' >    \
@@ -253,14 +274,23 @@ define rule_cc_o_c
 	mv -f $(dot-target).tmp $(dot-target).cmd
 endef
 
+define rule_as_o_S
+	$(call echo-cmd,as_o_S) $(cmd_as_o_S);				  \
+	$(cmd_stacktool)						  \
+	scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,as_o_S)' >    \
+	                                              $(dot-target).tmp;  \
+	rm -f $(depfile);						  \
+	mv -f $(dot-target).tmp $(dot-target).cmd
+endef
+
 # Built-in and composite module parts
-$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
+$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(stacktool_obj) FORCE
 	$(call cmd,force_checksrc)
 	$(call if_changed_rule,cc_o_c)
 
 # Single-part modules are special since we need to mark them in $(MODVERDIR)
 
-$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
+$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) $(stacktool_obj) FORCE
 	$(call cmd,force_checksrc)
 	$(call if_changed_rule,cc_o_c)
 	@{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod)
@@ -290,8 +320,8 @@ $(obj)/%.s: $(src)/%.S FORCE
 quiet_cmd_as_o_S = AS $(quiet_modtag)  $@
 cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
 
-$(obj)/%.o: $(src)/%.S FORCE
-	$(call if_changed_dep,as_o_S)
+$(obj)/%.o: $(src)/%.S $(stacktool_obj) FORCE
+	$(call if_changed_rule,as_o_S)
 
 targets += $(real-objs-y) $(real-objs-m) $(lib-y)
 targets += $(extra-y) $(MAKECMDGOALS) $(always)
scripts/mod/Makefile +2 -0
index c11212f..496184d 100644
@@ -1,3 +1,5 @@
+STACKTOOL	:= n
+
 hostprogs-y	:= modpost mk_elfconfig
 always		:= $(hostprogs-y) empty.o
 
Signature · 1 line
2.4.3
#3 lore raw

PATCH 3/33 x86/stacktool: Enable stacktool on x86_64

In reply to Josh Poimboeuf

Set HAVE_STACK_VALIDATION to enable stack metadata validation for x86_64.

Also, disable stacktool checking for the kexec purgatory code, because:

1. It's built by the archprepare target, which can run before stacktool has been built yet.

2. It runs outside the scope of the kernel's normal mode of operation and doesn't need stack checking anyway.

---
 arch/x86/Kconfig            | 1 +
 arch/x86/purgatory/Makefile | 2 ++
 2 files changed, 3 insertions(+)
arch/x86/Kconfig +1 -0
index 41b74e2..a7e4959 100644
@@ -154,6 +154,7 @@ config X86
 	select VIRT_TO_BUS
 	select X86_DEV_DMA_OPS			if X86_64
 	select X86_FEATURE_NAMES		if PROC_FS
+	select HAVE_STACK_VALIDATION		if X86_64
 
 config INSTRUCTION_DECODER
 	def_bool y
arch/x86/purgatory/Makefile +2 -0
index 2c835e3..30d7d58 100644
@@ -1,3 +1,5 @@
+STACKTOOL := n
+
 purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string.o
 
 targets += $(purgatory-y)
Signature · 1 line
2.4.3
#4 lore raw

PATCH 4/33 x86/stacktool: Add STACKTOOL_IGNORE_FUNC macro

In reply to Josh Poimboeuf

Add a new stacktool ignore macro, STACKTOOL_IGNORE_FUNC, which can be used to tell stacktool to skip validation of a function.

---
 MAINTAINERS                   |  1 +
 arch/x86/kernel/vmlinux.lds.S |  5 ++++-
 include/linux/stacktool.h     | 23 +++++++++++++++++++++++
 3 files changed, 28 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/stacktool.h
MAINTAINERS +1 -0
index 7ecbea9..80b26ec 100644
@@ -10190,6 +10190,7 @@ STACK METADATA VALIDATION
 M:	Josh Poimboeuf <[email protected]>
 S:	Supported
 F:	tools/stacktool/
+F:	include/linux/stacktool.h
 
 STAGING SUBSYSTEM
 M:	Greg Kroah-Hartman <[email protected]>
arch/x86/kernel/vmlinux.lds.S +4 -1
index 4f19942..c08c283c 100644
@@ -333,7 +333,10 @@ SECTIONS
 
 	/* Sections to be discarded */
 	DISCARDS
-	/DISCARD/ : { *(.eh_frame) }
+	/DISCARD/ : {
+		*(.eh_frame)
+		*(__stacktool_ignore_*)
+	}
 }
 
 
include/linux/stacktool.h new file +23 -0
new file mode 100644
index 0000000..0d90db7
@@ -0,0 +1,23 @@
+#ifndef _LINUX_STACKTOOL_H
+#define _LINUX_STACKTOOL_H
+
+#ifdef CONFIG_STACK_VALIDATION
+/*
+ * This C macro tells stacktool to ignore the function when doing stack
+ * metadata validation.  It should only be used in special cases where you're
+ * 100% sure it won't affect the reliability of frame pointers and kernel stack
+ * traces.
+ *
+ * For more information, see tools/stacktool/Documentation/stack-validation.txt.
+ */
+#define STACKTOOL_IGNORE_FUNC(_func) \
+	static void __used __section(__stacktool_ignore_func) \
+		*__stacktool_ignore_func_##_func = _func
+
+#else /* !CONFIG_STACK_VALIDATION */
+
+#define STACKTOOL_IGNORE_FUNC(_func)
+
+#endif /* CONFIG_STACK_VALIDATION */
+
+#endif /* _LINUX_STACKTOOL_H */
Signature · 1 line
2.4.3
#5 lore raw

PATCH 5/33 x86/xen: Add stack frame dependency to hypercall inline asm calls

In reply to Josh Poimboeuf

If a hypercall is inlined at the beginning of a function, gcc can insert the call instruction before setting up a stack frame, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.

Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the hypercall inline asm statements.

---
 arch/x86/include/asm/xen/hypercall.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/include/asm/xen/hypercall.h +3 -2
index 3bcdcc8..a12a047 100644
@@ -110,9 +110,10 @@ extern struct { char _entry[32]; } hypercall_page[];
 	register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
 	register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
 	register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
-	register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5;
+	register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5; \
+	register void *__sp asm(_ASM_SP);
 
-#define __HYPERCALL_0PARAM	"=r" (__res)
+#define __HYPERCALL_0PARAM	"=r" (__res), "+r" (__sp)
 #define __HYPERCALL_1PARAM	__HYPERCALL_0PARAM, "+r" (__arg1)
 #define __HYPERCALL_2PARAM	__HYPERCALL_1PARAM, "+r" (__arg2)
 #define __HYPERCALL_3PARAM	__HYPERCALL_2PARAM, "+r" (__arg3)
Signature · 1 line
2.4.3
#7 lore raw

[tip:x86/debug] x86/xen: Add stack frame dependency to hypercall inline asm calls

In reply to Josh Poimboeuf
x86/xen: Add stack frame dependency to hypercall inline asm calls
Commit-ID:  0e8e2238b52e5301d1d1d4a298ec5b72ac54c702
Gitweb:     http://git.kernel.org/tip/0e8e2238b52e5301d1d1d4a298ec5b72ac54c702
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:09 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:41 +0100

x86/xen: Add stack frame dependency to hypercall inline asm calls

If a hypercall is inlined at the beginning of a function, gcc can insert the call instruction before setting up a stack frame, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.

Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the hypercall inline asm statements.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Boris Ostrovsky <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/include/asm/xen/hypercall.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/include/asm/xen/hypercall.h +3 -2
index 3bcdcc8..a12a047 100644
@@ -110,9 +110,10 @@ extern struct { char _entry[32]; } hypercall_page[];
 	register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
 	register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
 	register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
-	register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5;
+	register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5; \
+	register void *__sp asm(_ASM_SP);
 
-#define __HYPERCALL_0PARAM	"=r" (__res)
+#define __HYPERCALL_0PARAM	"=r" (__res), "+r" (__sp)
 #define __HYPERCALL_1PARAM	__HYPERCALL_0PARAM, "+r" (__arg1)
 #define __HYPERCALL_2PARAM	__HYPERCALL_1PARAM, "+r" (__arg2)
 #define __HYPERCALL_3PARAM	__HYPERCALL_2PARAM, "+r" (__arg3)
#8 lore raw

PATCH 6/33 x86/asm/xen: Set ELF function type for xen_adjust_exception_frame()

In reply to Josh Poimboeuf

xen_adjust_exception_frame() is a callable function, but is missing the ELF function type, which confuses tools like stacktool.

Properly annotate it to be a callable function. The generated code is unchanged.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Boris Ostrovsky <[email protected]>
Cc David Vrabel <[email protected]>
---
 arch/x86/xen/xen-asm_64.S | 1 +
 1 file changed, 1 insertion(+)
arch/x86/xen/xen-asm_64.S +1 -0
index cc8acc4..c3df431 100644
@@ -26,6 +26,7 @@ ENTRY(xen_adjust_exception_frame)
 	mov 8+0(%rsp), %rcx
 	mov 8+8(%rsp), %r11
 	ret $16
+ENDPROC(xen_adjust_exception_frame)
 
 hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
 /*
Signature · 1 line
2.4.3
#10 lore raw

[tip:x86/debug] x86/asm/xen: Set ELF function type for xen_adjust_exception_frame()

In reply to Josh Poimboeuf
x86/asm/xen: Set ELF function type for xen_adjust_exception_frame()
Commit-ID:  9fd216067d75b45eb18d84dc476059de47da07c2
Gitweb:     http://git.kernel.org/tip/9fd216067d75b45eb18d84dc476059de47da07c2
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:10 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:41 +0100

x86/asm/xen: Set ELF function type for xen_adjust_exception_frame()

xen_adjust_exception_frame() is a callable function, but is missing the ELF function type, which confuses tools like stacktool.

Properly annotate it to be a callable function. The generated code is unchanged.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Boris Ostrovsky <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc David Vrabel <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/xen/xen-asm_64.S | 1 +
 1 file changed, 1 insertion(+)
arch/x86/xen/xen-asm_64.S +1 -0
index cc8acc4..c3df431 100644
@@ -26,6 +26,7 @@ ENTRY(xen_adjust_exception_frame)
 	mov 8+0(%rsp), %rcx
 	mov 8+8(%rsp), %r11
 	ret $16
+ENDPROC(xen_adjust_exception_frame)
 
 hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
 /*
#11 lore raw

PATCH 7/33 x86/asm/xen: Create stack frames in xen-asm.S

In reply to Josh Poimboeuf

xen_irq_enable_direct(), xen_restore_fl_direct(), and check_events() are callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create stack frames for them when CONFIG_FRAME_POINTER is enabled.

Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Boris Ostrovsky <[email protected]>
Cc David Vrabel <[email protected]>
---
 arch/x86/xen/xen-asm.S | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
arch/x86/xen/xen-asm.S +9 -1
index 3e45aa0..eff224d 100644
@@ -14,6 +14,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/percpu.h>
 #include <asm/processor-flags.h>
+#include <asm/frame.h>
 
 #include "xen-asm.h"
 
@@ -23,6 +24,7 @@
  * then enter the hypervisor to get them handled.
  */
 ENTRY(xen_irq_enable_direct)
+	FRAME_BEGIN
 	/* Unmask events */
 	movb $0, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
 
@@ -39,6 +41,7 @@ ENTRY(xen_irq_enable_direct)
 2:	call check_events
 1:
 ENDPATCH(xen_irq_enable_direct)
+	FRAME_END
 	ret
 	ENDPROC(xen_irq_enable_direct)
 	RELOC(xen_irq_enable_direct, 2b+1)
@@ -82,6 +85,7 @@ ENDPATCH(xen_save_fl_direct)
  * enters the hypervisor to get them delivered if so.
  */
 ENTRY(xen_restore_fl_direct)
+	FRAME_BEGIN
 #ifdef CONFIG_X86_64
 	testw $X86_EFLAGS_IF, %di
 #else
@@ -100,6 +104,7 @@ ENTRY(xen_restore_fl_direct)
 2:	call check_events
 1:
 ENDPATCH(xen_restore_fl_direct)
+	FRAME_END
 	ret
 	ENDPROC(xen_restore_fl_direct)
 	RELOC(xen_restore_fl_direct, 2b+1)
@@ -109,7 +114,8 @@ ENDPATCH(xen_restore_fl_direct)
  * Force an event check by making a hypercall, but preserve regs
  * before making the call.
  */
-check_events:
+ENTRY(check_events)
+	FRAME_BEGIN
 #ifdef CONFIG_X86_32
 	push %eax
 	push %ecx
@@ -139,4 +145,6 @@ check_events:
 	pop %rcx
 	pop %rax
 #endif
+	FRAME_END
 	ret
+ENDPROC(check_events)
Signature · 1 line
2.4.3
#13 lore raw

[tip:x86/debug] x86/asm/xen: Create stack frames in xen-asm.S

In reply to Josh Poimboeuf
x86/asm/xen: Create stack frames in xen-asm.S
Commit-ID:  8be0eb7e0d53bc2dbe6e9ad6e96a2d5b89d148a8
Gitweb:     http://git.kernel.org/tip/8be0eb7e0d53bc2dbe6e9ad6e96a2d5b89d148a8
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:11 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:42 +0100

x86/asm/xen: Create stack frames in xen-asm.S

xen_irq_enable_direct(), xen_restore_fl_direct(), and check_events() are callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create stack frames for them when CONFIG_FRAME_POINTER is enabled.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Boris Ostrovsky <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc David Vrabel <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/xen/xen-asm.S | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
arch/x86/xen/xen-asm.S +9 -1
index 3e45aa0..eff224d 100644
@@ -14,6 +14,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/percpu.h>
 #include <asm/processor-flags.h>
+#include <asm/frame.h>
 
 #include "xen-asm.h"
 
@@ -23,6 +24,7 @@
  * then enter the hypervisor to get them handled.
  */
 ENTRY(xen_irq_enable_direct)
+	FRAME_BEGIN
 	/* Unmask events */
 	movb $0, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_mask
 
@@ -39,6 +41,7 @@ ENTRY(xen_irq_enable_direct)
 2:	call check_events
 1:
 ENDPATCH(xen_irq_enable_direct)
+	FRAME_END
 	ret
 	ENDPROC(xen_irq_enable_direct)
 	RELOC(xen_irq_enable_direct, 2b+1)
@@ -82,6 +85,7 @@ ENDPATCH(xen_save_fl_direct)
  * enters the hypervisor to get them delivered if so.
  */
 ENTRY(xen_restore_fl_direct)
+	FRAME_BEGIN
 #ifdef CONFIG_X86_64
 	testw $X86_EFLAGS_IF, %di
 #else
@@ -100,6 +104,7 @@ ENTRY(xen_restore_fl_direct)
 2:	call check_events
 1:
 ENDPATCH(xen_restore_fl_direct)
+	FRAME_END
 	ret
 	ENDPROC(xen_restore_fl_direct)
 	RELOC(xen_restore_fl_direct, 2b+1)
@@ -109,7 +114,8 @@ ENDPATCH(xen_restore_fl_direct)
  * Force an event check by making a hypercall, but preserve regs
  * before making the call.
  */
-check_events:
+ENTRY(check_events)
+	FRAME_BEGIN
 #ifdef CONFIG_X86_32
 	push %eax
 	push %ecx
@@ -139,4 +145,6 @@ check_events:
 	pop %rcx
 	pop %rax
 #endif
+	FRAME_END
 	ret
+ENDPROC(check_events)
#14 lore raw

PATCH 8/33 x86/paravirt: Add stack frame dependency to PVOP inline asm calls

In reply to Josh Poimboeuf

If a PVOP call macro is inlined at the beginning of a function, gcc can insert the call instruction before setting up a stack frame, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.

Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the PVOP inline asm statements.

Cc Jeremy Fitzhardinge <[email protected]>
Cc Chris Wright <[email protected]>
Cc Alok Kataria <[email protected]>
Cc Rusty Russell <[email protected]>
---
 arch/x86/include/asm/paravirt_types.h | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)
arch/x86/include/asm/paravirt_types.h +10 -8
index 77db561..e8c2326 100644
@@ -466,8 +466,9 @@ int paravirt_disable_iospace(void);
  * makes sure the incoming and outgoing types are always correct.
  */
 #ifdef CONFIG_X86_32
-#define PVOP_VCALL_ARGS				\
-	unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx
+#define PVOP_VCALL_ARGS							\
+	unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx;	\
+	register void *__sp asm("esp")
 #define PVOP_CALL_ARGS			PVOP_VCALL_ARGS
 
 #define PVOP_CALL_ARG1(x)		"a" ((unsigned long)(x))
@@ -485,9 +486,10 @@ int paravirt_disable_iospace(void);
 #define VEXTRA_CLOBBERS
 #else  /* CONFIG_X86_64 */
 /* [re]ax isn't an arg, but the return val */
-#define PVOP_VCALL_ARGS					\
-	unsigned long __edi = __edi, __esi = __esi,	\
-		__edx = __edx, __ecx = __ecx, __eax = __eax
+#define PVOP_VCALL_ARGS						\
+	unsigned long __edi = __edi, __esi = __esi,		\
+		__edx = __edx, __ecx = __ecx, __eax = __eax;	\
+	register void *__sp asm("rsp")
 #define PVOP_CALL_ARGS		PVOP_VCALL_ARGS
 
 #define PVOP_CALL_ARG1(x)		"D" ((unsigned long)(x))
@@ -526,7 +528,7 @@ int paravirt_disable_iospace(void);
 			asm volatile(pre				\
 				     paravirt_alt(PARAVIRT_CALL)	\
 				     post				\
-				     : call_clbr			\
+				     : call_clbr, "+r" (__sp)		\
 				     : paravirt_type(op),		\
 				       paravirt_clobber(clbr),		\
 				       ##__VA_ARGS__			\
@@ -536,7 +538,7 @@ int paravirt_disable_iospace(void);
 			asm volatile(pre				\
 				     paravirt_alt(PARAVIRT_CALL)	\
 				     post				\
-				     : call_clbr			\
+				     : call_clbr, "+r" (__sp)		\
 				     : paravirt_type(op),		\
 				       paravirt_clobber(clbr),		\
 				       ##__VA_ARGS__			\
@@ -563,7 +565,7 @@ int paravirt_disable_iospace(void);
 		asm volatile(pre					\
 			     paravirt_alt(PARAVIRT_CALL)		\
 			     post					\
-			     : call_clbr				\
+			     : call_clbr, "+r" (__sp)			\
 			     : paravirt_type(op),			\
 			       paravirt_clobber(clbr),			\
 			       ##__VA_ARGS__				\
Signature · 1 line
2.4.3
#16 lore raw

[tip:x86/debug] x86/paravirt: Add stack frame dependency to PVOP inline asm calls

In reply to Josh Poimboeuf
x86/paravirt: Add stack frame dependency to PVOP inline asm calls
Commit-ID:  bb93eb4cd606888f879897e8289d9c1143571feb
Gitweb:     http://git.kernel.org/tip/bb93eb4cd606888f879897e8289d9c1143571feb
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:12 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:42 +0100

x86/paravirt: Add stack frame dependency to PVOP inline asm calls

If a PVOP call macro is inlined at the beginning of a function, gcc can insert the call instruction before setting up a stack frame, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.

Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the PVOP inline asm statements.

Cc Alok Kataria <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Chris Wright <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jeremy Fitzhardinge <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Rusty Russell <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/include/asm/paravirt_types.h | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)
arch/x86/include/asm/paravirt_types.h +10 -8
index 77db561..e8c2326 100644
@@ -466,8 +466,9 @@ int paravirt_disable_iospace(void);
  * makes sure the incoming and outgoing types are always correct.
  */
 #ifdef CONFIG_X86_32
-#define PVOP_VCALL_ARGS				\
-	unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx
+#define PVOP_VCALL_ARGS							\
+	unsigned long __eax = __eax, __edx = __edx, __ecx = __ecx;	\
+	register void *__sp asm("esp")
 #define PVOP_CALL_ARGS			PVOP_VCALL_ARGS
 
 #define PVOP_CALL_ARG1(x)		"a" ((unsigned long)(x))
@@ -485,9 +486,10 @@ int paravirt_disable_iospace(void);
 #define VEXTRA_CLOBBERS
 #else  /* CONFIG_X86_64 */
 /* [re]ax isn't an arg, but the return val */
-#define PVOP_VCALL_ARGS					\
-	unsigned long __edi = __edi, __esi = __esi,	\
-		__edx = __edx, __ecx = __ecx, __eax = __eax
+#define PVOP_VCALL_ARGS						\
+	unsigned long __edi = __edi, __esi = __esi,		\
+		__edx = __edx, __ecx = __ecx, __eax = __eax;	\
+	register void *__sp asm("rsp")
 #define PVOP_CALL_ARGS		PVOP_VCALL_ARGS
 
 #define PVOP_CALL_ARG1(x)		"D" ((unsigned long)(x))
@@ -526,7 +528,7 @@ int paravirt_disable_iospace(void);
 			asm volatile(pre				\
 				     paravirt_alt(PARAVIRT_CALL)	\
 				     post				\
-				     : call_clbr			\
+				     : call_clbr, "+r" (__sp)		\
 				     : paravirt_type(op),		\
 				       paravirt_clobber(clbr),		\
 				       ##__VA_ARGS__			\
@@ -536,7 +538,7 @@ int paravirt_disable_iospace(void);
 			asm volatile(pre				\
 				     paravirt_alt(PARAVIRT_CALL)	\
 				     post				\
-				     : call_clbr			\
+				     : call_clbr, "+r" (__sp)		\
 				     : paravirt_type(op),		\
 				       paravirt_clobber(clbr),		\
 				       ##__VA_ARGS__			\
@@ -563,7 +565,7 @@ int paravirt_disable_iospace(void);
 		asm volatile(pre					\
 			     paravirt_alt(PARAVIRT_CALL)		\
 			     post					\
-			     : call_clbr				\
+			     : call_clbr, "+r" (__sp)			\
 			     : paravirt_type(op),			\
 			       paravirt_clobber(clbr),			\
 			       ##__VA_ARGS__				\
#17 lore raw

PATCH 9/33 x86/paravirt: Create a stack frame in PV_CALLEE_SAVE_REGS_THUNK

In reply to Josh Poimboeuf

A function created with the PV_CALLEE_SAVE_REGS_THUNK macro doesn't set up a new stack frame before the call instruction, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace. Also, the thunk functions aren't annotated as ELF callable functions.

Create a stack frame when CONFIG_FRAME_POINTER is enabled and add the ELF function type.

Cc Jeremy Fitzhardinge <[email protected]>
Cc Chris Wright <[email protected]>
Cc Alok Kataria <[email protected]>
Cc Rusty Russell <[email protected]>
---
 arch/x86/include/asm/paravirt.h | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/include/asm/paravirt.h +7 -2
index f619250..601f1b8 100644
@@ -13,6 +13,7 @@
 #include <linux/bug.h>
 #include <linux/types.h>
 #include <linux/cpumask.h>
+#include <asm/frame.h>
 
 static inline int paravirt_enabled(void)
 {
@@ -756,15 +757,19 @@ static __always_inline void __ticket_unlock_kick(struct arch_spinlock *lock,
  * call. The return value in rax/eax will not be saved, even for void
  * functions.
  */
+#define PV_THUNK_NAME(func) "__raw_callee_save_" #func
 #define PV_CALLEE_SAVE_REGS_THUNK(func)					\
 	extern typeof(func) __raw_callee_save_##func;			\
 									\
 	asm(".pushsection .text;"					\
-	    ".globl __raw_callee_save_" #func " ; "			\
-	    "__raw_callee_save_" #func ": "				\
+	    ".globl " PV_THUNK_NAME(func) ";"				\
+	    ".type " PV_THUNK_NAME(func) ", @function;"			\
+	    PV_THUNK_NAME(func) ":"					\
+	    FRAME_BEGIN							\
 	    PV_SAVE_ALL_CALLER_REGS					\
 	    "call " #func ";"						\
 	    PV_RESTORE_ALL_CALLER_REGS					\
+	    FRAME_END							\
 	    "ret;"							\
 	    ".popsection")
 
Signature · 1 line
2.4.3
#19 lore raw

[tip:x86/debug] x86/paravirt: Create a stack frame in PV_CALLEE_SAVE_REGS_THUNK

In reply to Josh Poimboeuf
x86/paravirt: Create a stack frame in PV_CALLEE_SAVE_REGS_THUNK
Commit-ID:  87b240cbe3e51bf070fe2839fecb6450323aaef4
Gitweb:     http://git.kernel.org/tip/87b240cbe3e51bf070fe2839fecb6450323aaef4
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:13 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:42 +0100

x86/paravirt: Create a stack frame in PV_CALLEE_SAVE_REGS_THUNK

A function created with the PV_CALLEE_SAVE_REGS_THUNK macro doesn't set up a new stack frame before the call instruction, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace. Also, the thunk functions aren't annotated as ELF callable functions.

Create a stack frame when CONFIG_FRAME_POINTER is enabled and add the ELF function type.

Cc Alok Kataria <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Chris Wright <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jeremy Fitzhardinge <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Rusty Russell <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/include/asm/paravirt.h | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/include/asm/paravirt.h +7 -2
index f619250..601f1b8 100644
@@ -13,6 +13,7 @@
 #include <linux/bug.h>
 #include <linux/types.h>
 #include <linux/cpumask.h>
+#include <asm/frame.h>
 
 static inline int paravirt_enabled(void)
 {
@@ -756,15 +757,19 @@ static __always_inline void __ticket_unlock_kick(struct arch_spinlock *lock,
  * call. The return value in rax/eax will not be saved, even for void
  * functions.
  */
+#define PV_THUNK_NAME(func) "__raw_callee_save_" #func
 #define PV_CALLEE_SAVE_REGS_THUNK(func)					\
 	extern typeof(func) __raw_callee_save_##func;			\
 									\
 	asm(".pushsection .text;"					\
-	    ".globl __raw_callee_save_" #func " ; "			\
-	    "__raw_callee_save_" #func ": "				\
+	    ".globl " PV_THUNK_NAME(func) ";"				\
+	    ".type " PV_THUNK_NAME(func) ", @function;"			\
+	    PV_THUNK_NAME(func) ":"					\
+	    FRAME_BEGIN							\
 	    PV_SAVE_ALL_CALLER_REGS					\
 	    "call " #func ";"						\
 	    PV_RESTORE_ALL_CALLER_REGS					\
+	    FRAME_END							\
 	    "ret;"							\
 	    ".popsection")
 
#20 lore raw

PATCH 10/33 x86/amd: Set ELF function type for vide()

In reply to Josh Poimboeuf

vide() is a callable function, but is missing the ELF function type, which confuses tools like stacktool.

Properly annotate it to be a callable function. The generated code is unchanged.

---
 arch/x86/kernel/cpu/amd.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
arch/x86/kernel/cpu/amd.c +4 -1
index a07956a..fe2f089 100644
@@ -75,7 +75,10 @@ static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
  */
 
 extern __visible void vide(void);
-__asm__(".globl vide\n\t.align 4\nvide: ret");
+__asm__(".globl vide\n"
+	".type vide, @function\n"
+	".align 4\n"
+	"vide: ret\n");
 
 static void init_amd_k5(struct cpuinfo_x86 *c)
 {
Signature · 1 line
2.4.3
#22 lore raw

[tip:x86/debug] x86/amd: Set ELF function type for vide()

In reply to Josh Poimboeuf
x86/amd: Set ELF function type for vide()
Commit-ID:  de642faf48670c3c8eae5899177f786c624f4894
Gitweb:     http://git.kernel.org/tip/de642faf48670c3c8eae5899177f786c624f4894
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:14 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:42 +0100

x86/amd: Set ELF function type for vide()

vide() is a callable function, but is missing the ELF function type, which confuses tools like stacktool.

Properly annotate it to be a callable function. The generated code is unchanged.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/kernel/cpu/amd.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
arch/x86/kernel/cpu/amd.c +4 -1
index a07956a..fe2f089 100644
@@ -75,7 +75,10 @@ static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
  */
 
 extern __visible void vide(void);
-__asm__(".globl vide\n\t.align 4\nvide: ret");
+__asm__(".globl vide\n"
+	".type vide, @function\n"
+	".align 4\n"
+	"vide: ret\n");
 
 static void init_amd_k5(struct cpuinfo_x86 *c)
 {
#23 lore raw

PATCH 11/33 x86/asm/crypto: Move .Lbswap_mask data to .rodata section

In reply to Josh Poimboeuf

stacktool reports the following warning:

stacktool: arch/x86/crypto/aesni-intel_asm.o: _aesni_inc_init(): can't find starting instruction

stacktool gets confused when it tries to disassemble the following data in the .text section:

.Lbswap_mask:

          .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0

Move it to .rodata which is a more appropriate section for read-only data.

---
 arch/x86/crypto/aesni-intel_asm.S | 2 ++
 1 file changed, 2 insertions(+)
arch/x86/crypto/aesni-intel_asm.S +2 -0
index 6bd2c6c..c44cfed 100644
@@ -2538,9 +2538,11 @@ ENTRY(aesni_cbc_dec)
 ENDPROC(aesni_cbc_dec)
 
 #ifdef __x86_64__
+.pushsection .rodata
 .align 16
 .Lbswap_mask:
 	.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+.popsection
 
 /*
  * _aesni_inc_init:	internal ABI
Signature · 1 line
2.4.3
#25 lore raw

[tip:x86/debug] x86/asm/crypto: Move .Lbswap_mask data to .rodata section

In reply to Josh Poimboeuf
x86/asm/crypto: Move .Lbswap_mask data to .rodata section
Commit-ID:  1253cab8a35278c0493a48aa5ab74992f7a849ea
Gitweb:     http://git.kernel.org/tip/1253cab8a35278c0493a48aa5ab74992f7a849ea
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:15 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:42 +0100

x86/asm/crypto: Move .Lbswap_mask data to .rodata section

stacktool reports the following warning:

stacktool: arch/x86/crypto/aesni-intel_asm.o: _aesni_inc_init(): can't find starting instruction

stacktool gets confused when it tries to disassemble the following data in the .text section:

.Lbswap_mask:

          .byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0

Move it to .rodata which is a more appropriate section for read-only data.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc David S. Miller <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Herbert Xu <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/crypto/aesni-intel_asm.S | 2 ++
 1 file changed, 2 insertions(+)
arch/x86/crypto/aesni-intel_asm.S +2 -0
index 6bd2c6c..c44cfed 100644
@@ -2538,9 +2538,11 @@ ENTRY(aesni_cbc_dec)
 ENDPROC(aesni_cbc_dec)
 
 #ifdef __x86_64__
+.pushsection .rodata
 .align 16
 .Lbswap_mask:
 	.byte 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+.popsection
 
 /*
  * _aesni_inc_init:	internal ABI
#26 lore raw

PATCH 12/33 x86/asm/crypto: Move jump_table to .rodata section

In reply to Josh Poimboeuf

stacktool reports the following warning:

stacktool: arch/x86/crypto/crc32c-pcl-intel-asm_64.o: crc_pcl()+0x11dd: can't decode instruction

It gets confused when trying to decode jump_table data. Move jump_table to the .rodata section which is a more appropriate home for read-only data.

---
 arch/x86/crypto/crc32c-pcl-intel-asm_64.S | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
arch/x86/crypto/crc32c-pcl-intel-asm_64.S +4 -4
index 4fe27e0..dc05f01 100644
@@ -170,8 +170,8 @@ continue_block:
 	## branch into array
 	lea	jump_table(%rip), bufp
 	movzxw  (bufp, %rax, 2), len
-	offset=crc_array-jump_table
-	lea     offset(bufp, len, 1), bufp
+	lea	crc_array(%rip), bufp
+	lea     (bufp, len, 1), bufp
 	jmp     *bufp
 
 	################################################################
@@ -310,7 +310,9 @@ do_return:
 	popq    %rdi
 	popq    %rbx
         ret
+ENDPROC(crc_pcl)
 
+.section	.rodata, "a", %progbits
         ################################################################
         ## jump table        Table is 129 entries x 2 bytes each
         ################################################################
@@ -324,13 +326,11 @@ JMPTBL_ENTRY %i
 	i=i+1
 .endr
 
-ENDPROC(crc_pcl)
 
 	################################################################
 	## PCLMULQDQ tables
 	## Table is 128 entries x 2 words (8 bytes) each
 	################################################################
-.section	.rodata, "a", %progbits
 .align 8
 K_table:
 	.long 0x493c7d27, 0x00000001
Signature · 1 line
2.4.3
#28 lore raw

[tip:x86/debug] x86/asm/crypto: Move jump_table to .rodata section

In reply to Josh Poimboeuf
x86/asm/crypto: Move jump_table to .rodata section
Commit-ID:  f66f61919eb38c5f20e8a978cae7ecdede4c23b9
Gitweb:     http://git.kernel.org/tip/f66f61919eb38c5f20e8a978cae7ecdede4c23b9
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:16 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:42 +0100

x86/asm/crypto: Move jump_table to .rodata section

stacktool reports the following warning:

stacktool: arch/x86/crypto/crc32c-pcl-intel-asm_64.o: crc_pcl()+0x11dd: can't decode instruction

It gets confused when trying to decode jump_table data. Move jump_table to the .rodata section which is a more appropriate home for read-only data.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc David S. Miller <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Herbert Xu <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/crypto/crc32c-pcl-intel-asm_64.S | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
arch/x86/crypto/crc32c-pcl-intel-asm_64.S +4 -4
index 4fe27e0..dc05f01 100644
@@ -170,8 +170,8 @@ continue_block:
 	## branch into array
 	lea	jump_table(%rip), bufp
 	movzxw  (bufp, %rax, 2), len
-	offset=crc_array-jump_table
-	lea     offset(bufp, len, 1), bufp
+	lea	crc_array(%rip), bufp
+	lea     (bufp, len, 1), bufp
 	jmp     *bufp
 
 	################################################################
@@ -310,7 +310,9 @@ do_return:
 	popq    %rdi
 	popq    %rbx
         ret
+ENDPROC(crc_pcl)
 
+.section	.rodata, "a", %progbits
         ################################################################
         ## jump table        Table is 129 entries x 2 bytes each
         ################################################################
@@ -324,13 +326,11 @@ JMPTBL_ENTRY %i
 	i=i+1
 .endr
 
-ENDPROC(crc_pcl)
 
 	################################################################
 	## PCLMULQDQ tables
 	## Table is 128 entries x 2 words (8 bytes) each
 	################################################################
-.section	.rodata, "a", %progbits
 .align 8
 K_table:
 	.long 0x493c7d27, 0x00000001
#29 lore raw

PATCH 13/33 x86/asm/crypto: Simplify stack usage in sha-mb functions

In reply to Josh Poimboeuf

sha1_mb_mgr_flush_avx2() and sha1_mb_mgr_submit_avx2() both allocate a lot of stack space which is never used. Also, many of the registers being saved aren't being clobbered so there's no need to save them.

---
 arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S  | 32 ++----------------------
 arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 29 +++------------------
 2 files changed, 6 insertions(+), 55 deletions(-)
arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S +2 -30
index 85c4e1c..672eaeb 100644
@@ -86,16 +86,6 @@
 #define extra_blocks    %arg2
 #define p               %arg2
 
-
-# STACK_SPACE needs to be an odd multiple of 8
-_XMM_SAVE_SIZE  = 10*16
-_GPR_SAVE_SIZE  = 8*8
-_ALIGN_SIZE     = 8
-
-_XMM_SAVE       = 0
-_GPR_SAVE       = _XMM_SAVE + _XMM_SAVE_SIZE
-STACK_SPACE     = _GPR_SAVE + _GPR_SAVE_SIZE + _ALIGN_SIZE
-
 .macro LABEL prefix n
 \prefix\n\():
 .endm
@@ -113,16 +103,7 @@ offset = \_offset
 # JOB* sha1_mb_mgr_flush_avx2(MB_MGR *state)
 # arg 1 : rcx : state
 ENTRY(sha1_mb_mgr_flush_avx2)
-	mov	%rsp, %r10
-	sub     $STACK_SPACE, %rsp
-	and     $~31, %rsp
-	mov     %rbx, _GPR_SAVE(%rsp)
-	mov     %r10, _GPR_SAVE+8*1(%rsp) #save rsp
-	mov	%rbp, _GPR_SAVE+8*3(%rsp)
-	mov	%r12, _GPR_SAVE+8*4(%rsp)
-	mov	%r13, _GPR_SAVE+8*5(%rsp)
-	mov	%r14, _GPR_SAVE+8*6(%rsp)
-	mov	%r15, _GPR_SAVE+8*7(%rsp)
+	push	%rbx
 
 	# If bit (32+3) is set, then all lanes are empty
 	mov     _unused_lanes(state), unused_lanes
@@ -230,16 +211,7 @@ len_is_0:
 	mov     tmp2_w, offset(job_rax)
 
 return:
-
-	mov     _GPR_SAVE(%rsp), %rbx
-	mov     _GPR_SAVE+8*1(%rsp), %r10 #saved rsp
-	mov	_GPR_SAVE+8*3(%rsp), %rbp
-	mov	_GPR_SAVE+8*4(%rsp), %r12
-	mov	_GPR_SAVE+8*5(%rsp), %r13
-	mov	_GPR_SAVE+8*6(%rsp), %r14
-	mov	_GPR_SAVE+8*7(%rsp), %r15
-	mov     %r10, %rsp
-
+	pop	%rbx
 	ret
 
 return_null:
arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S +4 -25
index 2ab9560..a5a14c62 100644
@@ -94,25 +94,12 @@ DWORD_tmp	= %r9d
 
 lane_data       = %r10
 
-# STACK_SPACE needs to be an odd multiple of 8
-STACK_SPACE     = 8*8 + 16*10 + 8
-
 # JOB* submit_mb_mgr_submit_avx2(MB_MGR *state, job_sha1 *job)
 # arg 1 : rcx : state
 # arg 2 : rdx : job
 ENTRY(sha1_mb_mgr_submit_avx2)
-
-	mov	%rsp, %r10
-	sub     $STACK_SPACE, %rsp
-	and	$~31, %rsp
-
-	mov     %rbx, (%rsp)
-	mov	%r10, 8*2(%rsp)	#save old rsp
-	mov     %rbp, 8*3(%rsp)
-	mov	%r12, 8*4(%rsp)
-	mov	%r13, 8*5(%rsp)
-	mov	%r14, 8*6(%rsp)
-	mov	%r15, 8*7(%rsp)
+	push	%rbx
+	push	%rbp
 
 	mov     _unused_lanes(state), unused_lanes
 	mov	unused_lanes, lane
@@ -203,16 +190,8 @@ len_is_0:
 	movl    DWORD_tmp, _result_digest+1*16(job_rax)
 
 return:
-
-	mov     (%rsp), %rbx
-	mov	8*2(%rsp), %r10	#save old rsp
-	mov     8*3(%rsp), %rbp
-	mov	8*4(%rsp), %r12
-	mov	8*5(%rsp), %r13
-	mov	8*6(%rsp), %r14
-	mov	8*7(%rsp), %r15
-	mov     %r10, %rsp
-
+	pop	%rbp
+	pop	%rbx
 	ret
 
 return_null:
Signature · 1 line
2.4.3
#31 lore raw

[tip:x86/debug] x86/asm/crypto: Simplify stack usage in sha-mb functions

In reply to Josh Poimboeuf
x86/asm/crypto: Simplify stack usage in sha-mb functions
Commit-ID:  aec4d0e301f17bb143341c82cc44685b8af0b945
Gitweb:     http://git.kernel.org/tip/aec4d0e301f17bb143341c82cc44685b8af0b945
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:17 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:42 +0100

x86/asm/crypto: Simplify stack usage in sha-mb functions

sha1_mb_mgr_flush_avx2() and sha1_mb_mgr_submit_avx2() both allocate a lot of stack space which is never used. Also, many of the registers being saved aren't being clobbered so there's no need to save them.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S  | 32 ++----------------------
 arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 29 +++------------------
 2 files changed, 6 insertions(+), 55 deletions(-)
arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S +2 -30
index 85c4e1c..672eaeb 100644
@@ -86,16 +86,6 @@
 #define extra_blocks    %arg2
 #define p               %arg2
 
-
-# STACK_SPACE needs to be an odd multiple of 8
-_XMM_SAVE_SIZE  = 10*16
-_GPR_SAVE_SIZE  = 8*8
-_ALIGN_SIZE     = 8
-
-_XMM_SAVE       = 0
-_GPR_SAVE       = _XMM_SAVE + _XMM_SAVE_SIZE
-STACK_SPACE     = _GPR_SAVE + _GPR_SAVE_SIZE + _ALIGN_SIZE
-
 .macro LABEL prefix n
 \prefix\n\():
 .endm
@@ -113,16 +103,7 @@ offset = \_offset
 # JOB* sha1_mb_mgr_flush_avx2(MB_MGR *state)
 # arg 1 : rcx : state
 ENTRY(sha1_mb_mgr_flush_avx2)
-	mov	%rsp, %r10
-	sub     $STACK_SPACE, %rsp
-	and     $~31, %rsp
-	mov     %rbx, _GPR_SAVE(%rsp)
-	mov     %r10, _GPR_SAVE+8*1(%rsp) #save rsp
-	mov	%rbp, _GPR_SAVE+8*3(%rsp)
-	mov	%r12, _GPR_SAVE+8*4(%rsp)
-	mov	%r13, _GPR_SAVE+8*5(%rsp)
-	mov	%r14, _GPR_SAVE+8*6(%rsp)
-	mov	%r15, _GPR_SAVE+8*7(%rsp)
+	push	%rbx
 
 	# If bit (32+3) is set, then all lanes are empty
 	mov     _unused_lanes(state), unused_lanes
@@ -230,16 +211,7 @@ len_is_0:
 	mov     tmp2_w, offset(job_rax)
 
 return:
-
-	mov     _GPR_SAVE(%rsp), %rbx
-	mov     _GPR_SAVE+8*1(%rsp), %r10 #saved rsp
-	mov	_GPR_SAVE+8*3(%rsp), %rbp
-	mov	_GPR_SAVE+8*4(%rsp), %r12
-	mov	_GPR_SAVE+8*5(%rsp), %r13
-	mov	_GPR_SAVE+8*6(%rsp), %r14
-	mov	_GPR_SAVE+8*7(%rsp), %r15
-	mov     %r10, %rsp
-
+	pop	%rbx
 	ret
 
 return_null:
arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S +4 -25
index 2ab9560..a5a14c6 100644
@@ -94,25 +94,12 @@ DWORD_tmp	= %r9d
 
 lane_data       = %r10
 
-# STACK_SPACE needs to be an odd multiple of 8
-STACK_SPACE     = 8*8 + 16*10 + 8
-
 # JOB* submit_mb_mgr_submit_avx2(MB_MGR *state, job_sha1 *job)
 # arg 1 : rcx : state
 # arg 2 : rdx : job
 ENTRY(sha1_mb_mgr_submit_avx2)
-
-	mov	%rsp, %r10
-	sub     $STACK_SPACE, %rsp
-	and	$~31, %rsp
-
-	mov     %rbx, (%rsp)
-	mov	%r10, 8*2(%rsp)	#save old rsp
-	mov     %rbp, 8*3(%rsp)
-	mov	%r12, 8*4(%rsp)
-	mov	%r13, 8*5(%rsp)
-	mov	%r14, 8*6(%rsp)
-	mov	%r15, 8*7(%rsp)
+	push	%rbx
+	push	%rbp
 
 	mov     _unused_lanes(state), unused_lanes
 	mov	unused_lanes, lane
@@ -203,16 +190,8 @@ len_is_0:
 	movl    DWORD_tmp, _result_digest+1*16(job_rax)
 
 return:
-
-	mov     (%rsp), %rbx
-	mov	8*2(%rsp), %r10	#save old rsp
-	mov     8*3(%rsp), %rbp
-	mov	8*4(%rsp), %r12
-	mov	8*5(%rsp), %r13
-	mov	8*6(%rsp), %r14
-	mov	8*7(%rsp), %r15
-	mov     %r10, %rsp
-
+	pop	%rbp
+	pop	%rbx
 	ret
 
 return_null:
#32 lore raw

PATCH 14/33 x86/asm/crypto: Don't use rbp as a scratch register

In reply to Josh Poimboeuf

The frame pointer (rbp) is getting clobbered in sha1_mb_mgr_submit_avx2() before a function call, which can mess up stack traces. Use r12 instead.

---
 arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S +4 -4
index a5a14c62..c3b9447 100644
@@ -86,8 +86,8 @@ job_rax         = %rax
 len             = %rax
 DWORD_len	= %eax
 
-lane            = %rbp
-tmp3            = %rbp
+lane            = %r12
+tmp3            = %r12
 
 tmp             = %r9
 DWORD_tmp	= %r9d
@@ -99,7 +99,7 @@ lane_data       = %r10
 # arg 2 : rdx : job
 ENTRY(sha1_mb_mgr_submit_avx2)
 	push	%rbx
-	push	%rbp
+	push	%r12
 
 	mov     _unused_lanes(state), unused_lanes
 	mov	unused_lanes, lane
@@ -190,7 +190,7 @@ len_is_0:
 	movl    DWORD_tmp, _result_digest+1*16(job_rax)
 
 return:
-	pop	%rbp
+	pop	%r12
 	pop	%rbx
 	ret
 
Signature · 1 line
2.4.3
#34 lore raw

[tip:x86/debug] x86/asm/crypto: Don't use RBP as a scratch register

In reply to Josh Poimboeuf
x86/asm/crypto: Don't use RBP as a scratch register
Commit-ID:  68874ac3304ade7ed5ebb12af00d6b9bbbca0a16
Gitweb:     http://git.kernel.org/tip/68874ac3304ade7ed5ebb12af00d6b9bbbca0a16
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:18 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:42 +0100

x86/asm/crypto: Don't use RBP as a scratch register

The frame pointer (RBP) is getting clobbered in sha1_mb_mgr_submit_avx2() before a function call, which can mess up stack traces. Use R12 instead.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S +4 -4
index a5a14c6..c3b9447 100644
@@ -86,8 +86,8 @@ job_rax         = %rax
 len             = %rax
 DWORD_len	= %eax
 
-lane            = %rbp
-tmp3            = %rbp
+lane            = %r12
+tmp3            = %r12
 
 tmp             = %r9
 DWORD_tmp	= %r9d
@@ -99,7 +99,7 @@ lane_data       = %r10
 # arg 2 : rdx : job
 ENTRY(sha1_mb_mgr_submit_avx2)
 	push	%rbx
-	push	%rbp
+	push	%r12
 
 	mov     _unused_lanes(state), unused_lanes
 	mov	unused_lanes, lane
@@ -190,7 +190,7 @@ len_is_0:
 	movl    DWORD_tmp, _result_digest+1*16(job_rax)
 
 return:
-	pop	%rbp
+	pop	%r12
 	pop	%rbx
 	ret
 
#35 lore raw

PATCH 15/33 x86/asm/crypto: Create stack frames in crypto functions

In reply to Josh Poimboeuf

The crypto code has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create stack frames for them when CONFIG_FRAME_POINTER is enabled.

Cc Herbert Xu <[email protected]>
Cc David S. Miller <[email protected]>
---
 arch/x86/crypto/aesni-intel_asm.S                | 73 +++++++++++++++---------
 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/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  |  3 +
 arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S |  3 +
 arch/x86/crypto/twofish-avx-x86_64-asm_64.S      | 13 +++++
 11 files changed, 148 insertions(+), 27 deletions(-)
arch/x86/crypto/aesni-intel_asm.S +46 -27
index c44cfed..383a6f8 100644
@@ -31,6 +31,7 @@
 
 #include <linux/linkage.h>
 #include <asm/inst.h>
+#include <asm/frame.h>
 
 /*
  * The following macros are used to move an (un)aligned 16 byte value to/from
@@ -1800,11 +1801,12 @@ ENDPROC(_key_expansion_256b)
  *                   unsigned int key_len)
  */
 ENTRY(aesni_set_key)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl KEYP
-	movl 8(%esp), KEYP		# ctx
-	movl 12(%esp), UKEYP		# in_key
-	movl 16(%esp), %edx		# key_len
+	movl (FRAME_OFFSET+8)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+12)(%esp), UKEYP	# in_key
+	movl (FRAME_OFFSET+16)(%esp), %edx	# key_len
 #endif
 	movups (UKEYP), %xmm0		# user key (first 16 bytes)
 	movaps %xmm0, (KEYP)
@@ -1905,6 +1907,7 @@ ENTRY(aesni_set_key)
 #ifndef __x86_64__
 	popl KEYP
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_set_key)
 
@@ -1912,12 +1915,13 @@ ENDPROC(aesni_set_key)
  * void aesni_enc(struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
  */
 ENTRY(aesni_enc)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl KEYP
 	pushl KLEN
-	movl 12(%esp), KEYP
-	movl 16(%esp), OUTP
-	movl 20(%esp), INP
+	movl (FRAME_OFFSET+12)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+16)(%esp), OUTP	# dst
+	movl (FRAME_OFFSET+20)(%esp), INP	# src
 #endif
 	movl 480(KEYP), KLEN		# key length
 	movups (INP), STATE		# input
@@ -1927,6 +1931,7 @@ ENTRY(aesni_enc)
 	popl KLEN
 	popl KEYP
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_enc)
 
@@ -2101,12 +2106,13 @@ ENDPROC(_aesni_enc4)
  * void aesni_dec (struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
  */
 ENTRY(aesni_dec)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl KEYP
 	pushl KLEN
-	movl 12(%esp), KEYP
-	movl 16(%esp), OUTP
-	movl 20(%esp), INP
+	movl (FRAME_OFFSET+12)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+16)(%esp), OUTP	# dst
+	movl (FRAME_OFFSET+20)(%esp), INP	# src
 #endif
 	mov 480(KEYP), KLEN		# key length
 	add $240, KEYP
@@ -2117,6 +2123,7 @@ ENTRY(aesni_dec)
 	popl KLEN
 	popl KEYP
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_dec)
 
@@ -2292,14 +2299,15 @@ ENDPROC(_aesni_dec4)
  *		      size_t len)
  */
 ENTRY(aesni_ecb_enc)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl LEN
 	pushl KEYP
 	pushl KLEN
-	movl 16(%esp), KEYP
-	movl 20(%esp), OUTP
-	movl 24(%esp), INP
-	movl 28(%esp), LEN
+	movl (FRAME_OFFSET+16)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+20)(%esp), OUTP	# dst
+	movl (FRAME_OFFSET+24)(%esp), INP	# src
+	movl (FRAME_OFFSET+28)(%esp), LEN	# len
 #endif
 	test LEN, LEN		# check length
 	jz .Lecb_enc_ret
@@ -2342,6 +2350,7 @@ ENTRY(aesni_ecb_enc)
 	popl KEYP
 	popl LEN
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_ecb_enc)
 
@@ -2350,14 +2359,15 @@ ENDPROC(aesni_ecb_enc)
  *		      size_t len);
  */
 ENTRY(aesni_ecb_dec)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl LEN
 	pushl KEYP
 	pushl KLEN
-	movl 16(%esp), KEYP
-	movl 20(%esp), OUTP
-	movl 24(%esp), INP
-	movl 28(%esp), LEN
+	movl (FRAME_OFFSET+16)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+20)(%esp), OUTP	# dst
+	movl (FRAME_OFFSET+24)(%esp), INP	# src
+	movl (FRAME_OFFSET+28)(%esp), LEN	# len
 #endif
 	test LEN, LEN
 	jz .Lecb_dec_ret
@@ -2401,6 +2411,7 @@ ENTRY(aesni_ecb_dec)
 	popl KEYP
 	popl LEN
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_ecb_dec)
 
@@ -2409,16 +2420,17 @@ ENDPROC(aesni_ecb_dec)
  *		      size_t len, u8 *iv)
  */
 ENTRY(aesni_cbc_enc)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl IVP
 	pushl LEN
 	pushl KEYP
 	pushl KLEN
-	movl 20(%esp), KEYP
-	movl 24(%esp), OUTP
-	movl 28(%esp), INP
-	movl 32(%esp), LEN
-	movl 36(%esp), IVP
+	movl (FRAME_OFFSET+20)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+24)(%esp), OUTP	# dst
+	movl (FRAME_OFFSET+28)(%esp), INP	# src
+	movl (FRAME_OFFSET+32)(%esp), LEN	# len
+	movl (FRAME_OFFSET+36)(%esp), IVP	# iv
 #endif
 	cmp $16, LEN
 	jb .Lcbc_enc_ret
@@ -2443,6 +2455,7 @@ ENTRY(aesni_cbc_enc)
 	popl LEN
 	popl IVP
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_cbc_enc)
 
@@ -2451,16 +2464,17 @@ ENDPROC(aesni_cbc_enc)
  *		      size_t len, u8 *iv)
  */
 ENTRY(aesni_cbc_dec)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl IVP
 	pushl LEN
 	pushl KEYP
 	pushl KLEN
-	movl 20(%esp), KEYP
-	movl 24(%esp), OUTP
-	movl 28(%esp), INP
-	movl 32(%esp), LEN
-	movl 36(%esp), IVP
+	movl (FRAME_OFFSET+20)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+24)(%esp), OUTP	# dst
+	movl (FRAME_OFFSET+28)(%esp), INP	# src
+	movl (FRAME_OFFSET+32)(%esp), LEN	# len
+	movl (FRAME_OFFSET+36)(%esp), IVP	# iv
 #endif
 	cmp $16, LEN
 	jb .Lcbc_dec_just_ret
@@ -2534,6 +2548,7 @@ ENTRY(aesni_cbc_dec)
 	popl LEN
 	popl IVP
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_cbc_dec)
 
@@ -2600,6 +2615,7 @@ ENDPROC(_aesni_inc)
  *		      size_t len, u8 *iv)
  */
 ENTRY(aesni_ctr_enc)
+	FRAME_BEGIN
 	cmp $16, LEN
 	jb .Lctr_enc_just_ret
 	mov 480(KEYP), KLEN
@@ -2653,6 +2669,7 @@ ENTRY(aesni_ctr_enc)
 .Lctr_enc_ret:
 	movups IV, (IVP)
 .Lctr_enc_just_ret:
+	FRAME_END
 	ret
 ENDPROC(aesni_ctr_enc)
 
@@ -2679,6 +2696,7 @@ ENDPROC(aesni_ctr_enc)
  *			 bool enc, u8 *iv)
  */
 ENTRY(aesni_xts_crypt8)
+	FRAME_BEGIN
 	cmpb $0, %cl
 	movl $0, %ecx
 	movl $240, %r10d
@@ -2779,6 +2797,7 @@ ENTRY(aesni_xts_crypt8)
 	pxor INC, STATE4
 	movdqu STATE4, 0x70(OUTP)
 
+	FRAME_END
 	ret
 ENDPROC(aesni_xts_crypt8)
 
arch/x86/crypto/camellia-aesni-avx-asm_64.S +15 -0
index ce71f92..aa9e8bd 100644
@@ -16,6 +16,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 
 #define CAMELLIA_TABLE_BYTE_LEN 272
 
@@ -726,6 +727,7 @@ __camellia_enc_blk16:
 	 *	%xmm0..%xmm15: 16 encrypted blocks, order swapped:
 	 *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
 	 */
+	FRAME_BEGIN
 
 	leaq 8 * 16(%rax), %rcx;
 
@@ -780,6 +782,7 @@ __camellia_enc_blk16:
 		    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
 		    %xmm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 16(%rax));
 
+	FRAME_END
 	ret;
 
 .align 8
@@ -812,6 +815,7 @@ __camellia_dec_blk16:
 	 *	%xmm0..%xmm15: 16 plaintext blocks, order swapped:
 	 *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
 	 */
+	FRAME_BEGIN
 
 	leaq 8 * 16(%rax), %rcx;
 
@@ -865,6 +869,7 @@ __camellia_dec_blk16:
 		    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
 		    %xmm15, (key_table)(CTX), (%rax), 1 * 16(%rax));
 
+	FRAME_END
 	ret;
 
 .align 8
@@ -890,6 +895,7 @@ ENTRY(camellia_ecb_enc_16way)
 	 *	%rsi: dst (16 blocks)
 	 *	%rdx: src (16 blocks)
 	 */
+	 FRAME_BEGIN
 
 	inpack16_pre(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
 		     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
@@ -904,6 +910,7 @@ ENTRY(camellia_ecb_enc_16way)
 		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
 		     %xmm8, %rsi);
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_ecb_enc_16way)
 
@@ -913,6 +920,7 @@ ENTRY(camellia_ecb_dec_16way)
 	 *	%rsi: dst (16 blocks)
 	 *	%rdx: src (16 blocks)
 	 */
+	 FRAME_BEGIN
 
 	cmpl $16, key_length(CTX);
 	movl $32, %r8d;
@@ -932,6 +940,7 @@ ENTRY(camellia_ecb_dec_16way)
 		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
 		     %xmm8, %rsi);
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_ecb_dec_16way)
 
@@ -941,6 +950,7 @@ ENTRY(camellia_cbc_dec_16way)
 	 *	%rsi: dst (16 blocks)
 	 *	%rdx: src (16 blocks)
 	 */
+	FRAME_BEGIN
 
 	cmpl $16, key_length(CTX);
 	movl $32, %r8d;
@@ -981,6 +991,7 @@ ENTRY(camellia_cbc_dec_16way)
 		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
 		     %xmm8, %rsi);
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_cbc_dec_16way)
 
@@ -997,6 +1008,7 @@ ENTRY(camellia_ctr_16way)
 	 *	%rdx: src (16 blocks)
 	 *	%rcx: iv (little endian, 128bit)
 	 */
+	FRAME_BEGIN
 
 	subq $(16 * 16), %rsp;
 	movq %rsp, %rax;
@@ -1092,6 +1104,7 @@ ENTRY(camellia_ctr_16way)
 		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
 		     %xmm8, %rsi);
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_ctr_16way)
 
@@ -1112,6 +1125,7 @@ camellia_xts_crypt_16way:
 	 *	%r8: index for input whitening key
 	 *	%r9: pointer to  __camellia_enc_blk16 or __camellia_dec_blk16
 	 */
+	FRAME_BEGIN
 
 	subq $(16 * 16), %rsp;
 	movq %rsp, %rax;
@@ -1234,6 +1248,7 @@ camellia_xts_crypt_16way:
 		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
 		     %xmm8, %rsi);
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_xts_crypt_16way)
 
arch/x86/crypto/camellia-aesni-avx2-asm_64.S +15 -0
index 0e0b886..16186c1 100644
@@ -11,6 +11,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 
 #define CAMELLIA_TABLE_BYTE_LEN 272
 
@@ -766,6 +767,7 @@ __camellia_enc_blk32:
 	 *	%ymm0..%ymm15: 32 encrypted blocks, order swapped:
 	 *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
 	 */
+	FRAME_BEGIN
 
 	leaq 8 * 32(%rax), %rcx;
 
@@ -820,6 +822,7 @@ __camellia_enc_blk32:
 		    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
 		    %ymm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 32(%rax));
 
+	FRAME_END
 	ret;
 
 .align 8
@@ -852,6 +855,7 @@ __camellia_dec_blk32:
 	 *	%ymm0..%ymm15: 16 plaintext blocks, order swapped:
 	 *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
 	 */
+	FRAME_BEGIN
 
 	leaq 8 * 32(%rax), %rcx;
 
@@ -905,6 +909,7 @@ __camellia_dec_blk32:
 		    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
 		    %ymm15, (key_table)(CTX), (%rax), 1 * 32(%rax));
 
+	FRAME_END
 	ret;
 
 .align 8
@@ -930,6 +935,7 @@ ENTRY(camellia_ecb_enc_32way)
 	 *	%rsi: dst (32 blocks)
 	 *	%rdx: src (32 blocks)
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -948,6 +954,7 @@ ENTRY(camellia_ecb_enc_32way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_ecb_enc_32way)
 
@@ -957,6 +964,7 @@ ENTRY(camellia_ecb_dec_32way)
 	 *	%rsi: dst (32 blocks)
 	 *	%rdx: src (32 blocks)
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -980,6 +988,7 @@ ENTRY(camellia_ecb_dec_32way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_ecb_dec_32way)
 
@@ -989,6 +998,7 @@ ENTRY(camellia_cbc_dec_32way)
 	 *	%rsi: dst (32 blocks)
 	 *	%rdx: src (32 blocks)
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -1046,6 +1056,7 @@ ENTRY(camellia_cbc_dec_32way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_cbc_dec_32way)
 
@@ -1070,6 +1081,7 @@ ENTRY(camellia_ctr_32way)
 	 *	%rdx: src (32 blocks)
 	 *	%rcx: iv (little endian, 128bit)
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -1184,6 +1196,7 @@ ENTRY(camellia_ctr_32way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_ctr_32way)
 
@@ -1216,6 +1229,7 @@ camellia_xts_crypt_32way:
 	 *	%r8: index for input whitening key
 	 *	%r9: pointer to  __camellia_enc_blk32 or __camellia_dec_blk32
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -1349,6 +1363,7 @@ camellia_xts_crypt_32way:
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_xts_crypt_32way)
 
arch/x86/crypto/cast5-avx-x86_64-asm_64.S +9 -0
index c35fd5d..14fa196 100644
@@ -24,6 +24,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 
 .file "cast5-avx-x86_64-asm_64.S"
 
@@ -365,6 +366,7 @@ ENTRY(cast5_ecb_enc_16way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -388,6 +390,7 @@ ENTRY(cast5_ecb_enc_16way)
 	vmovdqu RR4, (6*4*4)(%r11);
 	vmovdqu RL4, (7*4*4)(%r11);
 
+	FRAME_END
 	ret;
 ENDPROC(cast5_ecb_enc_16way)
 
@@ -398,6 +401,7 @@ ENTRY(cast5_ecb_dec_16way)
 	 *	%rdx: src
 	 */
 
+	FRAME_BEGIN
 	movq %rsi, %r11;
 
 	vmovdqu (0*4*4)(%rdx), RL1;
@@ -420,6 +424,7 @@ ENTRY(cast5_ecb_dec_16way)
 	vmovdqu RR4, (6*4*4)(%r11);
 	vmovdqu RL4, (7*4*4)(%r11);
 
+	FRAME_END
 	ret;
 ENDPROC(cast5_ecb_dec_16way)
 
@@ -429,6 +434,7 @@ ENTRY(cast5_cbc_dec_16way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	pushq %r12;
 
@@ -469,6 +475,7 @@ ENTRY(cast5_cbc_dec_16way)
 
 	popq %r12;
 
+	FRAME_END
 	ret;
 ENDPROC(cast5_cbc_dec_16way)
 
@@ -479,6 +486,7 @@ ENTRY(cast5_ctr_16way)
 	 *	%rdx: src
 	 *	%rcx: iv (big endian, 64bit)
 	 */
+	FRAME_BEGIN
 
 	pushq %r12;
 
@@ -542,5 +550,6 @@ ENTRY(cast5_ctr_16way)
 
 	popq %r12;
 
+	FRAME_END
 	ret;
 ENDPROC(cast5_ctr_16way)
arch/x86/crypto/cast6-avx-x86_64-asm_64.S +13 -0
index e3531f8..c419389 100644
@@ -24,6 +24,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 #include "glue_helper-asm-avx.S"
 
 .file "cast6-avx-x86_64-asm_64.S"
@@ -349,6 +350,7 @@ ENTRY(cast6_ecb_enc_8way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -358,6 +360,7 @@ ENTRY(cast6_ecb_enc_8way)
 
 	store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(cast6_ecb_enc_8way)
 
@@ -367,6 +370,7 @@ ENTRY(cast6_ecb_dec_8way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -376,6 +380,7 @@ ENTRY(cast6_ecb_dec_8way)
 
 	store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(cast6_ecb_dec_8way)
 
@@ -385,6 +390,7 @@ ENTRY(cast6_cbc_dec_8way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	pushq %r12;
 
@@ -399,6 +405,7 @@ ENTRY(cast6_cbc_dec_8way)
 
 	popq %r12;
 
+	FRAME_END
 	ret;
 ENDPROC(cast6_cbc_dec_8way)
 
@@ -409,6 +416,7 @@ ENTRY(cast6_ctr_8way)
 	 *	%rdx: src
 	 *	%rcx: iv (little endian, 128bit)
 	 */
+	FRAME_BEGIN
 
 	pushq %r12;
 
@@ -424,6 +432,7 @@ ENTRY(cast6_ctr_8way)
 
 	popq %r12;
 
+	FRAME_END
 	ret;
 ENDPROC(cast6_ctr_8way)
 
@@ -434,6 +443,7 @@ ENTRY(cast6_xts_enc_8way)
 	 *	%rdx: src
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -446,6 +456,7 @@ ENTRY(cast6_xts_enc_8way)
 	/* dst <= regs xor IVs(in dst) */
 	store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(cast6_xts_enc_8way)
 
@@ -456,6 +467,7 @@ ENTRY(cast6_xts_dec_8way)
 	 *	%rdx: src
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -468,5 +480,6 @@ ENTRY(cast6_xts_dec_8way)
 	/* dst <= regs xor IVs(in dst) */
 	store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(cast6_xts_dec_8way)
arch/x86/crypto/ghash-clmulni-intel_asm.S +5 -0
index 5d1e007..eed55c8 100644
@@ -18,6 +18,7 @@
 
 #include <linux/linkage.h>
 #include <asm/inst.h>
+#include <asm/frame.h>
 
 .data
 
@@ -94,6 +95,7 @@ ENDPROC(__clmul_gf128mul_ble)
 
 /* void clmul_ghash_mul(char *dst, const u128 *shash) */
 ENTRY(clmul_ghash_mul)
+	FRAME_BEGIN
 	movups (%rdi), DATA
 	movups (%rsi), SHASH
 	movaps .Lbswap_mask, BSWAP
@@ -101,6 +103,7 @@ ENTRY(clmul_ghash_mul)
 	call __clmul_gf128mul_ble
 	PSHUFB_XMM BSWAP DATA
 	movups DATA, (%rdi)
+	FRAME_END
 	ret
 ENDPROC(clmul_ghash_mul)
 
@@ -109,6 +112,7 @@ ENDPROC(clmul_ghash_mul)
  *			   const u128 *shash);
  */
 ENTRY(clmul_ghash_update)
+	FRAME_BEGIN
 	cmp $16, %rdx
 	jb .Lupdate_just_ret	# check length
 	movaps .Lbswap_mask, BSWAP
@@ -128,5 +132,6 @@ ENTRY(clmul_ghash_update)
 	PSHUFB_XMM BSWAP DATA
 	movups DATA, (%rdi)
 .Lupdate_just_ret:
+	FRAME_END
 	ret
 ENDPROC(clmul_ghash_update)
arch/x86/crypto/serpent-avx-x86_64-asm_64.S +13 -0
index 2f202f4..8be5718 100644
@@ -24,6 +24,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 #include "glue_helper-asm-avx.S"
 
 .file "serpent-avx-x86_64-asm_64.S"
@@ -681,6 +682,7 @@ ENTRY(serpent_ecb_enc_8way_avx)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
@@ -688,6 +690,7 @@ ENTRY(serpent_ecb_enc_8way_avx)
 
 	store_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_ecb_enc_8way_avx)
 
@@ -697,6 +700,7 @@ ENTRY(serpent_ecb_dec_8way_avx)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
@@ -704,6 +708,7 @@ ENTRY(serpent_ecb_dec_8way_avx)
 
 	store_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_ecb_dec_8way_avx)
 
@@ -713,6 +718,7 @@ ENTRY(serpent_cbc_dec_8way_avx)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
@@ -720,6 +726,7 @@ ENTRY(serpent_cbc_dec_8way_avx)
 
 	store_cbc_8way(%rdx, %rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_cbc_dec_8way_avx)
 
@@ -730,6 +737,7 @@ ENTRY(serpent_ctr_8way_avx)
 	 *	%rdx: src
 	 *	%rcx: iv (little endian, 128bit)
 	 */
+	FRAME_BEGIN
 
 	load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2,
 		      RD2, RK0, RK1, RK2);
@@ -738,6 +746,7 @@ ENTRY(serpent_ctr_8way_avx)
 
 	store_ctr_8way(%rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_ctr_8way_avx)
 
@@ -748,6 +757,7 @@ ENTRY(serpent_xts_enc_8way_avx)
 	 *	%rdx: src
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	/* regs <= src, dst <= IVs, regs <= regs xor IVs */
 	load_xts_8way(%rcx, %rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2,
@@ -758,6 +768,7 @@ ENTRY(serpent_xts_enc_8way_avx)
 	/* dst <= regs xor IVs(in dst) */
 	store_xts_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_xts_enc_8way_avx)
 
@@ -768,6 +779,7 @@ ENTRY(serpent_xts_dec_8way_avx)
 	 *	%rdx: src
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	/* regs <= src, dst <= IVs, regs <= regs xor IVs */
 	load_xts_8way(%rcx, %rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2,
@@ -778,5 +790,6 @@ ENTRY(serpent_xts_dec_8way_avx)
 	/* dst <= regs xor IVs(in dst) */
 	store_xts_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_xts_dec_8way_avx)
arch/x86/crypto/serpent-avx2-asm_64.S +13 -0
index b222085..97c48ad 100644
@@ -15,6 +15,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 #include "glue_helper-asm-avx2.S"
 
 .file "serpent-avx2-asm_64.S"
@@ -673,6 +674,7 @@ ENTRY(serpent_ecb_enc_16way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -684,6 +686,7 @@ ENTRY(serpent_ecb_enc_16way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_ecb_enc_16way)
 
@@ -693,6 +696,7 @@ ENTRY(serpent_ecb_dec_16way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -704,6 +708,7 @@ ENTRY(serpent_ecb_dec_16way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_ecb_dec_16way)
 
@@ -713,6 +718,7 @@ ENTRY(serpent_cbc_dec_16way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -725,6 +731,7 @@ ENTRY(serpent_cbc_dec_16way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_cbc_dec_16way)
 
@@ -735,6 +742,7 @@ ENTRY(serpent_ctr_16way)
 	 *	%rdx: src (16 blocks)
 	 *	%rcx: iv (little endian, 128bit)
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -748,6 +756,7 @@ ENTRY(serpent_ctr_16way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_ctr_16way)
 
@@ -758,6 +767,7 @@ ENTRY(serpent_xts_enc_16way)
 	 *	%rdx: src (16 blocks)
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -772,6 +782,7 @@ ENTRY(serpent_xts_enc_16way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_xts_enc_16way)
 
@@ -782,6 +793,7 @@ ENTRY(serpent_xts_dec_16way)
 	 *	%rdx: src (16 blocks)
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -796,5 +808,6 @@ ENTRY(serpent_xts_dec_16way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_xts_dec_16way)
arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S +3 -0
index 672eaeb..96df6a3 100644
@@ -52,6 +52,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include <linux/linkage.h>
+#include <asm/frame.h>
 #include "sha1_mb_mgr_datastruct.S"
 
 
@@ -103,6 +104,7 @@ offset = \_offset
 # JOB* sha1_mb_mgr_flush_avx2(MB_MGR *state)
 # arg 1 : rcx : state
 ENTRY(sha1_mb_mgr_flush_avx2)
+	FRAME_BEGIN
 	push	%rbx
 
 	# If bit (32+3) is set, then all lanes are empty
@@ -212,6 +214,7 @@ len_is_0:
 
 return:
 	pop	%rbx
+	FRAME_END
 	ret
 
 return_null:
arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S +3 -0
index c3b9447..1435acf 100644
@@ -53,6 +53,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 #include "sha1_mb_mgr_datastruct.S"
 
 
@@ -98,6 +99,7 @@ lane_data       = %r10
 # arg 1 : rcx : state
 # arg 2 : rdx : job
 ENTRY(sha1_mb_mgr_submit_avx2)
+	FRAME_BEGIN
 	push	%rbx
 	push	%r12
 
@@ -192,6 +194,7 @@ len_is_0:
 return:
 	pop	%r12
 	pop	%rbx
+	FRAME_END
 	ret
 
 return_null:
arch/x86/crypto/twofish-avx-x86_64-asm_64.S +13 -0
index 0505813..dc66273 100644
@@ -24,6 +24,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 #include "glue_helper-asm-avx.S"
 
 .file "twofish-avx-x86_64-asm_64.S"
@@ -333,6 +334,7 @@ ENTRY(twofish_ecb_enc_8way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -342,6 +344,7 @@ ENTRY(twofish_ecb_enc_8way)
 
 	store_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
 
+	FRAME_END
 	ret;
 ENDPROC(twofish_ecb_enc_8way)
 
@@ -351,6 +354,7 @@ ENTRY(twofish_ecb_dec_8way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -360,6 +364,7 @@ ENTRY(twofish_ecb_dec_8way)
 
 	store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(twofish_ecb_dec_8way)
 
@@ -369,6 +374,7 @@ ENTRY(twofish_cbc_dec_8way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	pushq %r12;
 
@@ -383,6 +389,7 @@ ENTRY(twofish_cbc_dec_8way)
 
 	popq %r12;
 
+	FRAME_END
 	ret;
 ENDPROC(twofish_cbc_dec_8way)
 
@@ -393,6 +400,7 @@ ENTRY(twofish_ctr_8way)
 	 *	%rdx: src
 	 *	%rcx: iv (little endian, 128bit)
 	 */
+	FRAME_BEGIN
 
 	pushq %r12;
 
@@ -408,6 +416,7 @@ ENTRY(twofish_ctr_8way)
 
 	popq %r12;
 
+	FRAME_END
 	ret;
 ENDPROC(twofish_ctr_8way)
 
@@ -418,6 +427,7 @@ ENTRY(twofish_xts_enc_8way)
 	 *	%rdx: src
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -430,6 +440,7 @@ ENTRY(twofish_xts_enc_8way)
 	/* dst <= regs xor IVs(in dst) */
 	store_xts_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
 
+	FRAME_END
 	ret;
 ENDPROC(twofish_xts_enc_8way)
 
@@ -440,6 +451,7 @@ ENTRY(twofish_xts_dec_8way)
 	 *	%rdx: src
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -452,5 +464,6 @@ ENTRY(twofish_xts_dec_8way)
 	/* dst <= regs xor IVs(in dst) */
 	store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(twofish_xts_dec_8way)
Signature · 1 line
2.4.3
#37 lore raw

[tip:x86/debug] x86/asm/crypto: Create stack frames in crypto functions

In reply to Josh Poimboeuf
x86/asm/crypto: Create stack frames in crypto functions
Commit-ID:  8691ccd764f9ecc69a6812dfe76214c86ac9ba06
Gitweb:     http://git.kernel.org/tip/8691ccd764f9ecc69a6812dfe76214c86ac9ba06
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:19 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:43 +0100

x86/asm/crypto: Create stack frames in crypto functions

The crypto code has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create stack frames for them when CONFIG_FRAME_POINTER is enabled.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc David S. Miller <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Herbert Xu <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/crypto/aesni-intel_asm.S                | 73 +++++++++++++++---------
 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/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  |  3 +
 arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S |  3 +
 arch/x86/crypto/twofish-avx-x86_64-asm_64.S      | 13 +++++
 11 files changed, 148 insertions(+), 27 deletions(-)
arch/x86/crypto/aesni-intel_asm.S +46 -27
index c44cfed..383a6f8 100644
@@ -31,6 +31,7 @@
 
 #include <linux/linkage.h>
 #include <asm/inst.h>
+#include <asm/frame.h>
 
 /*
  * The following macros are used to move an (un)aligned 16 byte value to/from
@@ -1800,11 +1801,12 @@ ENDPROC(_key_expansion_256b)
  *                   unsigned int key_len)
  */
 ENTRY(aesni_set_key)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl KEYP
-	movl 8(%esp), KEYP		# ctx
-	movl 12(%esp), UKEYP		# in_key
-	movl 16(%esp), %edx		# key_len
+	movl (FRAME_OFFSET+8)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+12)(%esp), UKEYP	# in_key
+	movl (FRAME_OFFSET+16)(%esp), %edx	# key_len
 #endif
 	movups (UKEYP), %xmm0		# user key (first 16 bytes)
 	movaps %xmm0, (KEYP)
@@ -1905,6 +1907,7 @@ ENTRY(aesni_set_key)
 #ifndef __x86_64__
 	popl KEYP
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_set_key)
 
@@ -1912,12 +1915,13 @@ ENDPROC(aesni_set_key)
  * void aesni_enc(struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
  */
 ENTRY(aesni_enc)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl KEYP
 	pushl KLEN
-	movl 12(%esp), KEYP
-	movl 16(%esp), OUTP
-	movl 20(%esp), INP
+	movl (FRAME_OFFSET+12)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+16)(%esp), OUTP	# dst
+	movl (FRAME_OFFSET+20)(%esp), INP	# src
 #endif
 	movl 480(KEYP), KLEN		# key length
 	movups (INP), STATE		# input
@@ -1927,6 +1931,7 @@ ENTRY(aesni_enc)
 	popl KLEN
 	popl KEYP
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_enc)
 
@@ -2101,12 +2106,13 @@ ENDPROC(_aesni_enc4)
  * void aesni_dec (struct crypto_aes_ctx *ctx, u8 *dst, const u8 *src)
  */
 ENTRY(aesni_dec)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl KEYP
 	pushl KLEN
-	movl 12(%esp), KEYP
-	movl 16(%esp), OUTP
-	movl 20(%esp), INP
+	movl (FRAME_OFFSET+12)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+16)(%esp), OUTP	# dst
+	movl (FRAME_OFFSET+20)(%esp), INP	# src
 #endif
 	mov 480(KEYP), KLEN		# key length
 	add $240, KEYP
@@ -2117,6 +2123,7 @@ ENTRY(aesni_dec)
 	popl KLEN
 	popl KEYP
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_dec)
 
@@ -2292,14 +2299,15 @@ ENDPROC(_aesni_dec4)
  *		      size_t len)
  */
 ENTRY(aesni_ecb_enc)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl LEN
 	pushl KEYP
 	pushl KLEN
-	movl 16(%esp), KEYP
-	movl 20(%esp), OUTP
-	movl 24(%esp), INP
-	movl 28(%esp), LEN
+	movl (FRAME_OFFSET+16)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+20)(%esp), OUTP	# dst
+	movl (FRAME_OFFSET+24)(%esp), INP	# src
+	movl (FRAME_OFFSET+28)(%esp), LEN	# len
 #endif
 	test LEN, LEN		# check length
 	jz .Lecb_enc_ret
@@ -2342,6 +2350,7 @@ ENTRY(aesni_ecb_enc)
 	popl KEYP
 	popl LEN
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_ecb_enc)
 
@@ -2350,14 +2359,15 @@ ENDPROC(aesni_ecb_enc)
  *		      size_t len);
  */
 ENTRY(aesni_ecb_dec)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl LEN
 	pushl KEYP
 	pushl KLEN
-	movl 16(%esp), KEYP
-	movl 20(%esp), OUTP
-	movl 24(%esp), INP
-	movl 28(%esp), LEN
+	movl (FRAME_OFFSET+16)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+20)(%esp), OUTP	# dst
+	movl (FRAME_OFFSET+24)(%esp), INP	# src
+	movl (FRAME_OFFSET+28)(%esp), LEN	# len
 #endif
 	test LEN, LEN
 	jz .Lecb_dec_ret
@@ -2401,6 +2411,7 @@ ENTRY(aesni_ecb_dec)
 	popl KEYP
 	popl LEN
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_ecb_dec)
 
@@ -2409,16 +2420,17 @@ ENDPROC(aesni_ecb_dec)
  *		      size_t len, u8 *iv)
  */
 ENTRY(aesni_cbc_enc)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl IVP
 	pushl LEN
 	pushl KEYP
 	pushl KLEN
-	movl 20(%esp), KEYP
-	movl 24(%esp), OUTP
-	movl 28(%esp), INP
-	movl 32(%esp), LEN
-	movl 36(%esp), IVP
+	movl (FRAME_OFFSET+20)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+24)(%esp), OUTP	# dst
+	movl (FRAME_OFFSET+28)(%esp), INP	# src
+	movl (FRAME_OFFSET+32)(%esp), LEN	# len
+	movl (FRAME_OFFSET+36)(%esp), IVP	# iv
 #endif
 	cmp $16, LEN
 	jb .Lcbc_enc_ret
@@ -2443,6 +2455,7 @@ ENTRY(aesni_cbc_enc)
 	popl LEN
 	popl IVP
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_cbc_enc)
 
@@ -2451,16 +2464,17 @@ ENDPROC(aesni_cbc_enc)
  *		      size_t len, u8 *iv)
  */
 ENTRY(aesni_cbc_dec)
+	FRAME_BEGIN
 #ifndef __x86_64__
 	pushl IVP
 	pushl LEN
 	pushl KEYP
 	pushl KLEN
-	movl 20(%esp), KEYP
-	movl 24(%esp), OUTP
-	movl 28(%esp), INP
-	movl 32(%esp), LEN
-	movl 36(%esp), IVP
+	movl (FRAME_OFFSET+20)(%esp), KEYP	# ctx
+	movl (FRAME_OFFSET+24)(%esp), OUTP	# dst
+	movl (FRAME_OFFSET+28)(%esp), INP	# src
+	movl (FRAME_OFFSET+32)(%esp), LEN	# len
+	movl (FRAME_OFFSET+36)(%esp), IVP	# iv
 #endif
 	cmp $16, LEN
 	jb .Lcbc_dec_just_ret
@@ -2534,6 +2548,7 @@ ENTRY(aesni_cbc_dec)
 	popl LEN
 	popl IVP
 #endif
+	FRAME_END
 	ret
 ENDPROC(aesni_cbc_dec)
 
@@ -2600,6 +2615,7 @@ ENDPROC(_aesni_inc)
  *		      size_t len, u8 *iv)
  */
 ENTRY(aesni_ctr_enc)
+	FRAME_BEGIN
 	cmp $16, LEN
 	jb .Lctr_enc_just_ret
 	mov 480(KEYP), KLEN
@@ -2653,6 +2669,7 @@ ENTRY(aesni_ctr_enc)
 .Lctr_enc_ret:
 	movups IV, (IVP)
 .Lctr_enc_just_ret:
+	FRAME_END
 	ret
 ENDPROC(aesni_ctr_enc)
 
@@ -2679,6 +2696,7 @@ ENDPROC(aesni_ctr_enc)
  *			 bool enc, u8 *iv)
  */
 ENTRY(aesni_xts_crypt8)
+	FRAME_BEGIN
 	cmpb $0, %cl
 	movl $0, %ecx
 	movl $240, %r10d
@@ -2779,6 +2797,7 @@ ENTRY(aesni_xts_crypt8)
 	pxor INC, STATE4
 	movdqu STATE4, 0x70(OUTP)
 
+	FRAME_END
 	ret
 ENDPROC(aesni_xts_crypt8)
 
arch/x86/crypto/camellia-aesni-avx-asm_64.S +15 -0
index ce71f92..aa9e8bd 100644
@@ -16,6 +16,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 
 #define CAMELLIA_TABLE_BYTE_LEN 272
 
@@ -726,6 +727,7 @@ __camellia_enc_blk16:
 	 *	%xmm0..%xmm15: 16 encrypted blocks, order swapped:
 	 *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
 	 */
+	FRAME_BEGIN
 
 	leaq 8 * 16(%rax), %rcx;
 
@@ -780,6 +782,7 @@ __camellia_enc_blk16:
 		    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
 		    %xmm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 16(%rax));
 
+	FRAME_END
 	ret;
 
 .align 8
@@ -812,6 +815,7 @@ __camellia_dec_blk16:
 	 *	%xmm0..%xmm15: 16 plaintext blocks, order swapped:
 	 *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
 	 */
+	FRAME_BEGIN
 
 	leaq 8 * 16(%rax), %rcx;
 
@@ -865,6 +869,7 @@ __camellia_dec_blk16:
 		    %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
 		    %xmm15, (key_table)(CTX), (%rax), 1 * 16(%rax));
 
+	FRAME_END
 	ret;
 
 .align 8
@@ -890,6 +895,7 @@ ENTRY(camellia_ecb_enc_16way)
 	 *	%rsi: dst (16 blocks)
 	 *	%rdx: src (16 blocks)
 	 */
+	 FRAME_BEGIN
 
 	inpack16_pre(%xmm0, %xmm1, %xmm2, %xmm3, %xmm4, %xmm5, %xmm6, %xmm7,
 		     %xmm8, %xmm9, %xmm10, %xmm11, %xmm12, %xmm13, %xmm14,
@@ -904,6 +910,7 @@ ENTRY(camellia_ecb_enc_16way)
 		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
 		     %xmm8, %rsi);
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_ecb_enc_16way)
 
@@ -913,6 +920,7 @@ ENTRY(camellia_ecb_dec_16way)
 	 *	%rsi: dst (16 blocks)
 	 *	%rdx: src (16 blocks)
 	 */
+	 FRAME_BEGIN
 
 	cmpl $16, key_length(CTX);
 	movl $32, %r8d;
@@ -932,6 +940,7 @@ ENTRY(camellia_ecb_dec_16way)
 		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
 		     %xmm8, %rsi);
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_ecb_dec_16way)
 
@@ -941,6 +950,7 @@ ENTRY(camellia_cbc_dec_16way)
 	 *	%rsi: dst (16 blocks)
 	 *	%rdx: src (16 blocks)
 	 */
+	FRAME_BEGIN
 
 	cmpl $16, key_length(CTX);
 	movl $32, %r8d;
@@ -981,6 +991,7 @@ ENTRY(camellia_cbc_dec_16way)
 		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
 		     %xmm8, %rsi);
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_cbc_dec_16way)
 
@@ -997,6 +1008,7 @@ ENTRY(camellia_ctr_16way)
 	 *	%rdx: src (16 blocks)
 	 *	%rcx: iv (little endian, 128bit)
 	 */
+	FRAME_BEGIN
 
 	subq $(16 * 16), %rsp;
 	movq %rsp, %rax;
@@ -1092,6 +1104,7 @@ ENTRY(camellia_ctr_16way)
 		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
 		     %xmm8, %rsi);
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_ctr_16way)
 
@@ -1112,6 +1125,7 @@ camellia_xts_crypt_16way:
 	 *	%r8: index for input whitening key
 	 *	%r9: pointer to  __camellia_enc_blk16 or __camellia_dec_blk16
 	 */
+	FRAME_BEGIN
 
 	subq $(16 * 16), %rsp;
 	movq %rsp, %rax;
@@ -1234,6 +1248,7 @@ camellia_xts_crypt_16way:
 		     %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9,
 		     %xmm8, %rsi);
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_xts_crypt_16way)
 
arch/x86/crypto/camellia-aesni-avx2-asm_64.S +15 -0
index 0e0b886..16186c1 100644
@@ -11,6 +11,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 
 #define CAMELLIA_TABLE_BYTE_LEN 272
 
@@ -766,6 +767,7 @@ __camellia_enc_blk32:
 	 *	%ymm0..%ymm15: 32 encrypted blocks, order swapped:
 	 *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
 	 */
+	FRAME_BEGIN
 
 	leaq 8 * 32(%rax), %rcx;
 
@@ -820,6 +822,7 @@ __camellia_enc_blk32:
 		    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
 		    %ymm15, (key_table)(CTX, %r8, 8), (%rax), 1 * 32(%rax));
 
+	FRAME_END
 	ret;
 
 .align 8
@@ -852,6 +855,7 @@ __camellia_dec_blk32:
 	 *	%ymm0..%ymm15: 16 plaintext blocks, order swapped:
 	 *       7, 8, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8
 	 */
+	FRAME_BEGIN
 
 	leaq 8 * 32(%rax), %rcx;
 
@@ -905,6 +909,7 @@ __camellia_dec_blk32:
 		    %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14,
 		    %ymm15, (key_table)(CTX), (%rax), 1 * 32(%rax));
 
+	FRAME_END
 	ret;
 
 .align 8
@@ -930,6 +935,7 @@ ENTRY(camellia_ecb_enc_32way)
 	 *	%rsi: dst (32 blocks)
 	 *	%rdx: src (32 blocks)
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -948,6 +954,7 @@ ENTRY(camellia_ecb_enc_32way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_ecb_enc_32way)
 
@@ -957,6 +964,7 @@ ENTRY(camellia_ecb_dec_32way)
 	 *	%rsi: dst (32 blocks)
 	 *	%rdx: src (32 blocks)
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -980,6 +988,7 @@ ENTRY(camellia_ecb_dec_32way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_ecb_dec_32way)
 
@@ -989,6 +998,7 @@ ENTRY(camellia_cbc_dec_32way)
 	 *	%rsi: dst (32 blocks)
 	 *	%rdx: src (32 blocks)
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -1046,6 +1056,7 @@ ENTRY(camellia_cbc_dec_32way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_cbc_dec_32way)
 
@@ -1070,6 +1081,7 @@ ENTRY(camellia_ctr_32way)
 	 *	%rdx: src (32 blocks)
 	 *	%rcx: iv (little endian, 128bit)
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -1184,6 +1196,7 @@ ENTRY(camellia_ctr_32way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_ctr_32way)
 
@@ -1216,6 +1229,7 @@ camellia_xts_crypt_32way:
 	 *	%r8: index for input whitening key
 	 *	%r9: pointer to  __camellia_enc_blk32 or __camellia_dec_blk32
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -1349,6 +1363,7 @@ camellia_xts_crypt_32way:
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(camellia_xts_crypt_32way)
 
arch/x86/crypto/cast5-avx-x86_64-asm_64.S +9 -0
index c35fd5d..14fa196 100644
@@ -24,6 +24,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 
 .file "cast5-avx-x86_64-asm_64.S"
 
@@ -365,6 +366,7 @@ ENTRY(cast5_ecb_enc_16way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -388,6 +390,7 @@ ENTRY(cast5_ecb_enc_16way)
 	vmovdqu RR4, (6*4*4)(%r11);
 	vmovdqu RL4, (7*4*4)(%r11);
 
+	FRAME_END
 	ret;
 ENDPROC(cast5_ecb_enc_16way)
 
@@ -398,6 +401,7 @@ ENTRY(cast5_ecb_dec_16way)
 	 *	%rdx: src
 	 */
 
+	FRAME_BEGIN
 	movq %rsi, %r11;
 
 	vmovdqu (0*4*4)(%rdx), RL1;
@@ -420,6 +424,7 @@ ENTRY(cast5_ecb_dec_16way)
 	vmovdqu RR4, (6*4*4)(%r11);
 	vmovdqu RL4, (7*4*4)(%r11);
 
+	FRAME_END
 	ret;
 ENDPROC(cast5_ecb_dec_16way)
 
@@ -429,6 +434,7 @@ ENTRY(cast5_cbc_dec_16way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	pushq %r12;
 
@@ -469,6 +475,7 @@ ENTRY(cast5_cbc_dec_16way)
 
 	popq %r12;
 
+	FRAME_END
 	ret;
 ENDPROC(cast5_cbc_dec_16way)
 
@@ -479,6 +486,7 @@ ENTRY(cast5_ctr_16way)
 	 *	%rdx: src
 	 *	%rcx: iv (big endian, 64bit)
 	 */
+	FRAME_BEGIN
 
 	pushq %r12;
 
@@ -542,5 +550,6 @@ ENTRY(cast5_ctr_16way)
 
 	popq %r12;
 
+	FRAME_END
 	ret;
 ENDPROC(cast5_ctr_16way)
arch/x86/crypto/cast6-avx-x86_64-asm_64.S +13 -0
index e3531f8..c419389 100644
@@ -24,6 +24,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 #include "glue_helper-asm-avx.S"
 
 .file "cast6-avx-x86_64-asm_64.S"
@@ -349,6 +350,7 @@ ENTRY(cast6_ecb_enc_8way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -358,6 +360,7 @@ ENTRY(cast6_ecb_enc_8way)
 
 	store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(cast6_ecb_enc_8way)
 
@@ -367,6 +370,7 @@ ENTRY(cast6_ecb_dec_8way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -376,6 +380,7 @@ ENTRY(cast6_ecb_dec_8way)
 
 	store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(cast6_ecb_dec_8way)
 
@@ -385,6 +390,7 @@ ENTRY(cast6_cbc_dec_8way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	pushq %r12;
 
@@ -399,6 +405,7 @@ ENTRY(cast6_cbc_dec_8way)
 
 	popq %r12;
 
+	FRAME_END
 	ret;
 ENDPROC(cast6_cbc_dec_8way)
 
@@ -409,6 +416,7 @@ ENTRY(cast6_ctr_8way)
 	 *	%rdx: src
 	 *	%rcx: iv (little endian, 128bit)
 	 */
+	FRAME_BEGIN
 
 	pushq %r12;
 
@@ -424,6 +432,7 @@ ENTRY(cast6_ctr_8way)
 
 	popq %r12;
 
+	FRAME_END
 	ret;
 ENDPROC(cast6_ctr_8way)
 
@@ -434,6 +443,7 @@ ENTRY(cast6_xts_enc_8way)
 	 *	%rdx: src
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -446,6 +456,7 @@ ENTRY(cast6_xts_enc_8way)
 	/* dst <= regs xor IVs(in dst) */
 	store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(cast6_xts_enc_8way)
 
@@ -456,6 +467,7 @@ ENTRY(cast6_xts_dec_8way)
 	 *	%rdx: src
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -468,5 +480,6 @@ ENTRY(cast6_xts_dec_8way)
 	/* dst <= regs xor IVs(in dst) */
 	store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(cast6_xts_dec_8way)
arch/x86/crypto/ghash-clmulni-intel_asm.S +5 -0
index 5d1e007..eed55c8 100644
@@ -18,6 +18,7 @@
 
 #include <linux/linkage.h>
 #include <asm/inst.h>
+#include <asm/frame.h>
 
 .data
 
@@ -94,6 +95,7 @@ ENDPROC(__clmul_gf128mul_ble)
 
 /* void clmul_ghash_mul(char *dst, const u128 *shash) */
 ENTRY(clmul_ghash_mul)
+	FRAME_BEGIN
 	movups (%rdi), DATA
 	movups (%rsi), SHASH
 	movaps .Lbswap_mask, BSWAP
@@ -101,6 +103,7 @@ ENTRY(clmul_ghash_mul)
 	call __clmul_gf128mul_ble
 	PSHUFB_XMM BSWAP DATA
 	movups DATA, (%rdi)
+	FRAME_END
 	ret
 ENDPROC(clmul_ghash_mul)
 
@@ -109,6 +112,7 @@ ENDPROC(clmul_ghash_mul)
  *			   const u128 *shash);
  */
 ENTRY(clmul_ghash_update)
+	FRAME_BEGIN
 	cmp $16, %rdx
 	jb .Lupdate_just_ret	# check length
 	movaps .Lbswap_mask, BSWAP
@@ -128,5 +132,6 @@ ENTRY(clmul_ghash_update)
 	PSHUFB_XMM BSWAP DATA
 	movups DATA, (%rdi)
 .Lupdate_just_ret:
+	FRAME_END
 	ret
 ENDPROC(clmul_ghash_update)
arch/x86/crypto/serpent-avx-x86_64-asm_64.S +13 -0
index 2f202f4..8be5718 100644
@@ -24,6 +24,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 #include "glue_helper-asm-avx.S"
 
 .file "serpent-avx-x86_64-asm_64.S"
@@ -681,6 +682,7 @@ ENTRY(serpent_ecb_enc_8way_avx)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
@@ -688,6 +690,7 @@ ENTRY(serpent_ecb_enc_8way_avx)
 
 	store_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_ecb_enc_8way_avx)
 
@@ -697,6 +700,7 @@ ENTRY(serpent_ecb_dec_8way_avx)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
@@ -704,6 +708,7 @@ ENTRY(serpent_ecb_dec_8way_avx)
 
 	store_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_ecb_dec_8way_avx)
 
@@ -713,6 +718,7 @@ ENTRY(serpent_cbc_dec_8way_avx)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	load_8way(%rdx, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
@@ -720,6 +726,7 @@ ENTRY(serpent_cbc_dec_8way_avx)
 
 	store_cbc_8way(%rdx, %rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_cbc_dec_8way_avx)
 
@@ -730,6 +737,7 @@ ENTRY(serpent_ctr_8way_avx)
 	 *	%rdx: src
 	 *	%rcx: iv (little endian, 128bit)
 	 */
+	FRAME_BEGIN
 
 	load_ctr_8way(%rcx, .Lbswap128_mask, RA1, RB1, RC1, RD1, RA2, RB2, RC2,
 		      RD2, RK0, RK1, RK2);
@@ -738,6 +746,7 @@ ENTRY(serpent_ctr_8way_avx)
 
 	store_ctr_8way(%rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_ctr_8way_avx)
 
@@ -748,6 +757,7 @@ ENTRY(serpent_xts_enc_8way_avx)
 	 *	%rdx: src
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	/* regs <= src, dst <= IVs, regs <= regs xor IVs */
 	load_xts_8way(%rcx, %rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2,
@@ -758,6 +768,7 @@ ENTRY(serpent_xts_enc_8way_avx)
 	/* dst <= regs xor IVs(in dst) */
 	store_xts_8way(%rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_xts_enc_8way_avx)
 
@@ -768,6 +779,7 @@ ENTRY(serpent_xts_dec_8way_avx)
 	 *	%rdx: src
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	/* regs <= src, dst <= IVs, regs <= regs xor IVs */
 	load_xts_8way(%rcx, %rdx, %rsi, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2,
@@ -778,5 +790,6 @@ ENTRY(serpent_xts_dec_8way_avx)
 	/* dst <= regs xor IVs(in dst) */
 	store_xts_8way(%rsi, RC1, RD1, RB1, RE1, RC2, RD2, RB2, RE2);
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_xts_dec_8way_avx)
arch/x86/crypto/serpent-avx2-asm_64.S +13 -0
index b222085..97c48ad 100644
@@ -15,6 +15,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 #include "glue_helper-asm-avx2.S"
 
 .file "serpent-avx2-asm_64.S"
@@ -673,6 +674,7 @@ ENTRY(serpent_ecb_enc_16way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -684,6 +686,7 @@ ENTRY(serpent_ecb_enc_16way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_ecb_enc_16way)
 
@@ -693,6 +696,7 @@ ENTRY(serpent_ecb_dec_16way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -704,6 +708,7 @@ ENTRY(serpent_ecb_dec_16way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_ecb_dec_16way)
 
@@ -713,6 +718,7 @@ ENTRY(serpent_cbc_dec_16way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -725,6 +731,7 @@ ENTRY(serpent_cbc_dec_16way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_cbc_dec_16way)
 
@@ -735,6 +742,7 @@ ENTRY(serpent_ctr_16way)
 	 *	%rdx: src (16 blocks)
 	 *	%rcx: iv (little endian, 128bit)
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -748,6 +756,7 @@ ENTRY(serpent_ctr_16way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_ctr_16way)
 
@@ -758,6 +767,7 @@ ENTRY(serpent_xts_enc_16way)
 	 *	%rdx: src (16 blocks)
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -772,6 +782,7 @@ ENTRY(serpent_xts_enc_16way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_xts_enc_16way)
 
@@ -782,6 +793,7 @@ ENTRY(serpent_xts_dec_16way)
 	 *	%rdx: src (16 blocks)
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	vzeroupper;
 
@@ -796,5 +808,6 @@ ENTRY(serpent_xts_dec_16way)
 
 	vzeroupper;
 
+	FRAME_END
 	ret;
 ENDPROC(serpent_xts_dec_16way)
arch/x86/crypto/sha-mb/sha1_mb_mgr_flush_avx2.S +3 -0
index 672eaeb..96df6a3 100644
@@ -52,6 +52,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include <linux/linkage.h>
+#include <asm/frame.h>
 #include "sha1_mb_mgr_datastruct.S"
 
 
@@ -103,6 +104,7 @@ offset = \_offset
 # JOB* sha1_mb_mgr_flush_avx2(MB_MGR *state)
 # arg 1 : rcx : state
 ENTRY(sha1_mb_mgr_flush_avx2)
+	FRAME_BEGIN
 	push	%rbx
 
 	# If bit (32+3) is set, then all lanes are empty
@@ -212,6 +214,7 @@ len_is_0:
 
 return:
 	pop	%rbx
+	FRAME_END
 	ret
 
 return_null:
arch/x86/crypto/sha-mb/sha1_mb_mgr_submit_avx2.S +3 -0
index c3b9447..1435acf 100644
@@ -53,6 +53,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 #include "sha1_mb_mgr_datastruct.S"
 
 
@@ -98,6 +99,7 @@ lane_data       = %r10
 # arg 1 : rcx : state
 # arg 2 : rdx : job
 ENTRY(sha1_mb_mgr_submit_avx2)
+	FRAME_BEGIN
 	push	%rbx
 	push	%r12
 
@@ -192,6 +194,7 @@ len_is_0:
 return:
 	pop	%r12
 	pop	%rbx
+	FRAME_END
 	ret
 
 return_null:
arch/x86/crypto/twofish-avx-x86_64-asm_64.S +13 -0
index 0505813..dc66273 100644
@@ -24,6 +24,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/frame.h>
 #include "glue_helper-asm-avx.S"
 
 .file "twofish-avx-x86_64-asm_64.S"
@@ -333,6 +334,7 @@ ENTRY(twofish_ecb_enc_8way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -342,6 +344,7 @@ ENTRY(twofish_ecb_enc_8way)
 
 	store_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
 
+	FRAME_END
 	ret;
 ENDPROC(twofish_ecb_enc_8way)
 
@@ -351,6 +354,7 @@ ENTRY(twofish_ecb_dec_8way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -360,6 +364,7 @@ ENTRY(twofish_ecb_dec_8way)
 
 	store_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(twofish_ecb_dec_8way)
 
@@ -369,6 +374,7 @@ ENTRY(twofish_cbc_dec_8way)
 	 *	%rsi: dst
 	 *	%rdx: src
 	 */
+	FRAME_BEGIN
 
 	pushq %r12;
 
@@ -383,6 +389,7 @@ ENTRY(twofish_cbc_dec_8way)
 
 	popq %r12;
 
+	FRAME_END
 	ret;
 ENDPROC(twofish_cbc_dec_8way)
 
@@ -393,6 +400,7 @@ ENTRY(twofish_ctr_8way)
 	 *	%rdx: src
 	 *	%rcx: iv (little endian, 128bit)
 	 */
+	FRAME_BEGIN
 
 	pushq %r12;
 
@@ -408,6 +416,7 @@ ENTRY(twofish_ctr_8way)
 
 	popq %r12;
 
+	FRAME_END
 	ret;
 ENDPROC(twofish_ctr_8way)
 
@@ -418,6 +427,7 @@ ENTRY(twofish_xts_enc_8way)
 	 *	%rdx: src
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -430,6 +440,7 @@ ENTRY(twofish_xts_enc_8way)
 	/* dst <= regs xor IVs(in dst) */
 	store_xts_8way(%r11, RC1, RD1, RA1, RB1, RC2, RD2, RA2, RB2);
 
+	FRAME_END
 	ret;
 ENDPROC(twofish_xts_enc_8way)
 
@@ -440,6 +451,7 @@ ENTRY(twofish_xts_dec_8way)
 	 *	%rdx: src
 	 *	%rcx: iv (t ⊕ αⁿ ∈ GF(2¹²⁸))
 	 */
+	FRAME_BEGIN
 
 	movq %rsi, %r11;
 
@@ -452,5 +464,6 @@ ENTRY(twofish_xts_dec_8way)
 	/* dst <= regs xor IVs(in dst) */
 	store_xts_8way(%r11, RA1, RB1, RC1, RD1, RA2, RB2, RC2, RD2);
 
+	FRAME_END
 	ret;
 ENDPROC(twofish_xts_dec_8way)
#38 lore raw

PATCH 16/33 x86/asm/entry: Create stack frames in thunk functions

In reply to Josh Poimboeuf

Thunk functions are callable non-leaf functions that don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces. Also they aren't annotated as ELF callable functions which can confuse tooling.

Create stack frames for them when CONFIG_FRAME_POINTER is enabled and add the ELF function type.

---
 arch/x86/entry/thunk_64.S | 4 ++++
 1 file changed, 4 insertions(+)
arch/x86/entry/thunk_64.S +4 -0
index efb2b93..98df1fa 100644
@@ -8,11 +8,14 @@
 #include <linux/linkage.h>
 #include "calling.h"
 #include <asm/asm.h>
+#include <asm/frame.h>
 
 	/* rdi:	arg1 ... normal C conventions. rax is saved/restored. */
 	.macro THUNK name, func, put_ret_addr_in_rdi=0
 	.globl \name
+	.type \name, @function
 \name:
+	FRAME_BEGIN
 
 	/* this one pushes 9 elems, the next one would be %rIP */
 	pushq %rdi
@@ -62,6 +65,7 @@ restore:
 	popq %rdx
 	popq %rsi
 	popq %rdi
+	FRAME_END
 	ret
 	_ASM_NOKPROBE(restore)
 #endif
Signature · 1 line
2.4.3
#40 lore raw

[tip:x86/debug] x86/asm/entry: Create stack frames in thunk functions

In reply to Josh Poimboeuf
x86/asm/entry: Create stack frames in thunk functions
Commit-ID:  058fb73274f9e7eb72acc9836cbb2c4a9f9659a0
Gitweb:     http://git.kernel.org/tip/058fb73274f9e7eb72acc9836cbb2c4a9f9659a0
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:20 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:43 +0100

x86/asm/entry: Create stack frames in thunk functions

Thunk functions are callable non-leaf functions that don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces. Also they aren't annotated as ELF callable functions which can confuse tooling.

Create stack frames for them when CONFIG_FRAME_POINTER is enabled and add the ELF function type.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/entry/thunk_64.S | 4 ++++
 1 file changed, 4 insertions(+)
arch/x86/entry/thunk_64.S +4 -0
index efb2b93..98df1fa 100644
@@ -8,11 +8,14 @@
 #include <linux/linkage.h>
 #include "calling.h"
 #include <asm/asm.h>
+#include <asm/frame.h>
 
 	/* rdi:	arg1 ... normal C conventions. rax is saved/restored. */
 	.macro THUNK name, func, put_ret_addr_in_rdi=0
 	.globl \name
+	.type \name, @function
 \name:
+	FRAME_BEGIN
 
 	/* this one pushes 9 elems, the next one would be %rIP */
 	pushq %rdi
@@ -62,6 +65,7 @@ restore:
 	popq %rdx
 	popq %rsi
 	popq %rdi
+	FRAME_END
 	ret
 	_ASM_NOKPROBE(restore)
 #endif
#41 lore raw

PATCH 17/33 x86/asm/acpi: Create a stack frame in do_suspend_lowlevel()

In reply to Josh Poimboeuf

do_suspend_lowlevel() is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame for it when CONFIG_FRAME_POINTER is enabled.

---
 arch/x86/kernel/acpi/wakeup_64.S | 3 +++
 1 file changed, 3 insertions(+)
arch/x86/kernel/acpi/wakeup_64.S +3 -0
index 8c35df4..169963f 100644
@@ -5,6 +5,7 @@
 #include <asm/page_types.h>
 #include <asm/msr.h>
 #include <asm/asm-offsets.h>
+#include <asm/frame.h>
 
 # Copyright 2003 Pavel Machek <[email protected]>, distribute under GPLv2
 
@@ -39,6 +40,7 @@ bogus_64_magic:
 	jmp	bogus_64_magic
 
 ENTRY(do_suspend_lowlevel)
+	FRAME_BEGIN
 	subq	$8, %rsp
 	xorl	%eax, %eax
 	call	save_processor_state
@@ -109,6 +111,7 @@ ENTRY(do_suspend_lowlevel)
 
 	xorl	%eax, %eax
 	addq	$8, %rsp
+	FRAME_END
 	jmp	restore_processor_state
 ENDPROC(do_suspend_lowlevel)
 
Signature · 1 line
2.4.3
#43 lore raw

Re: [tip:x86/debug] x86/asm/acpi: Create a stack frame in do_suspend_lowlevel()

On Tue 2016-02-23 01:00:37, =?UTF-8?B?dGlwLWJvdCBmb3IgSm9zaCBQb2ltYm9ldWYgPHRpcGJvdEB6eXRvci5jb20+?=@zytor.com wrote:

Hi!

I don't who sent those mails (hpa?) but From: is severely misformated, as is content-type.

Pavel

Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
#44 lore raw

[tip:x86/debug] x86/asm/acpi: Create a stack frame in do_suspend_lowlevel()

In reply to Josh Poimboeuf
x86/asm/acpi: Create a stack frame in do_suspend_lowlevel()
Commit-ID:  13523309495cdbd57a0d344c0d5d574987af007f
Gitweb:     http://git.kernel.org/tip/13523309495cdbd57a0d344c0d5d574987af007f
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:21 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:43 +0100

x86/asm/acpi: Create a stack frame in do_suspend_lowlevel()

do_suspend_lowlevel() is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame for it when CONFIG_FRAME_POINTER is enabled.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Len Brown <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/kernel/acpi/wakeup_64.S | 3 +++
 1 file changed, 3 insertions(+)
arch/x86/kernel/acpi/wakeup_64.S +3 -0
index 8c35df4..169963f 100644
@@ -5,6 +5,7 @@
 #include <asm/page_types.h>
 #include <asm/msr.h>
 #include <asm/asm-offsets.h>
+#include <asm/frame.h>
 
 # Copyright 2003 Pavel Machek <[email protected]>, distribute under GPLv2
 
@@ -39,6 +40,7 @@ bogus_64_magic:
 	jmp	bogus_64_magic
 
 ENTRY(do_suspend_lowlevel)
+	FRAME_BEGIN
 	subq	$8, %rsp
 	xorl	%eax, %eax
 	call	save_processor_state
@@ -109,6 +111,7 @@ ENTRY(do_suspend_lowlevel)
 
 	xorl	%eax, %eax
 	addq	$8, %rsp
+	FRAME_END
 	jmp	restore_processor_state
 ENDPROC(do_suspend_lowlevel)
 
#45 lore raw

PATCH 18/33 x86/asm: Create stack frames in rwsem functions

In reply to Josh Poimboeuf

rwsem.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create stack frames for them when CONFIG_FRAME_POINTER is enabled.

---
 arch/x86/lib/rwsem.S | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
arch/x86/lib/rwsem.S +10 -1
index 40027db..be110ef 100644
@@ -15,6 +15,7 @@
 
 #include <linux/linkage.h>
 #include <asm/alternative-asm.h>
+#include <asm/frame.h>
 
 #define __ASM_HALF_REG(reg)	__ASM_SEL(reg, e##reg)
 #define __ASM_HALF_SIZE(inst)	__ASM_SEL(inst##w, inst##l)
@@ -84,24 +85,29 @@
 
 /* Fix up special calling conventions */
 ENTRY(call_rwsem_down_read_failed)
+	FRAME_BEGIN
 	save_common_regs
 	__ASM_SIZE(push,) %__ASM_REG(dx)
 	movq %rax,%rdi
 	call rwsem_down_read_failed
 	__ASM_SIZE(pop,) %__ASM_REG(dx)
 	restore_common_regs
+	FRAME_END
 	ret
 ENDPROC(call_rwsem_down_read_failed)
 
 ENTRY(call_rwsem_down_write_failed)
+	FRAME_BEGIN
 	save_common_regs
 	movq %rax,%rdi
 	call rwsem_down_write_failed
 	restore_common_regs
+	FRAME_END
 	ret
 ENDPROC(call_rwsem_down_write_failed)
 
 ENTRY(call_rwsem_wake)
+	FRAME_BEGIN
 	/* do nothing if still outstanding active readers */
 	__ASM_HALF_SIZE(dec) %__ASM_HALF_REG(dx)
 	jnz 1f
@@ -109,15 +115,18 @@ ENTRY(call_rwsem_wake)
 	movq %rax,%rdi
 	call rwsem_wake
 	restore_common_regs
-1:	ret
+1:	FRAME_END
+	ret
 ENDPROC(call_rwsem_wake)
 
 ENTRY(call_rwsem_downgrade_wake)
+	FRAME_BEGIN
 	save_common_regs
 	__ASM_SIZE(push,) %__ASM_REG(dx)
 	movq %rax,%rdi
 	call rwsem_downgrade_wake
 	__ASM_SIZE(pop,) %__ASM_REG(dx)
 	restore_common_regs
+	FRAME_END
 	ret
 ENDPROC(call_rwsem_downgrade_wake)
Signature · 1 line
2.4.3
#47 lore raw

[tip:x86/debug] x86/asm: Create stack frames in rwsem functions

In reply to Josh Poimboeuf
x86/asm: Create stack frames in rwsem functions
Commit-ID:  3387a535ce629906d849864ef6a3c3437a645cb5
Gitweb:     http://git.kernel.org/tip/3387a535ce629906d849864ef6a3c3437a645cb5
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:22 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:43 +0100

x86/asm: Create stack frames in rwsem functions

rwsem.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create stack frames for them when CONFIG_FRAME_POINTER is enabled.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/lib/rwsem.S | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
arch/x86/lib/rwsem.S +10 -1
index 40027db..be110ef 100644
@@ -15,6 +15,7 @@
 
 #include <linux/linkage.h>
 #include <asm/alternative-asm.h>
+#include <asm/frame.h>
 
 #define __ASM_HALF_REG(reg)	__ASM_SEL(reg, e##reg)
 #define __ASM_HALF_SIZE(inst)	__ASM_SEL(inst##w, inst##l)
@@ -84,24 +85,29 @@
 
 /* Fix up special calling conventions */
 ENTRY(call_rwsem_down_read_failed)
+	FRAME_BEGIN
 	save_common_regs
 	__ASM_SIZE(push,) %__ASM_REG(dx)
 	movq %rax,%rdi
 	call rwsem_down_read_failed
 	__ASM_SIZE(pop,) %__ASM_REG(dx)
 	restore_common_regs
+	FRAME_END
 	ret
 ENDPROC(call_rwsem_down_read_failed)
 
 ENTRY(call_rwsem_down_write_failed)
+	FRAME_BEGIN
 	save_common_regs
 	movq %rax,%rdi
 	call rwsem_down_write_failed
 	restore_common_regs
+	FRAME_END
 	ret
 ENDPROC(call_rwsem_down_write_failed)
 
 ENTRY(call_rwsem_wake)
+	FRAME_BEGIN
 	/* do nothing if still outstanding active readers */
 	__ASM_HALF_SIZE(dec) %__ASM_HALF_REG(dx)
 	jnz 1f
@@ -109,15 +115,18 @@ ENTRY(call_rwsem_wake)
 	movq %rax,%rdi
 	call rwsem_wake
 	restore_common_regs
-1:	ret
+1:	FRAME_END
+	ret
 ENDPROC(call_rwsem_wake)
 
 ENTRY(call_rwsem_downgrade_wake)
+	FRAME_BEGIN
 	save_common_regs
 	__ASM_SIZE(push,) %__ASM_REG(dx)
 	movq %rax,%rdi
 	call rwsem_downgrade_wake
 	__ASM_SIZE(pop,) %__ASM_REG(dx)
 	restore_common_regs
+	FRAME_END
 	ret
 ENDPROC(call_rwsem_downgrade_wake)
#48 lore raw

PATCH 19/33 x86/asm/efi: Create a stack frame in efi_call()

In reply to Josh Poimboeuf

efi_call() is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame for it when CONFIG_FRAME_POINTER is enabled.

---
 arch/x86/platform/efi/efi_stub_64.S | 3 +++
 1 file changed, 3 insertions(+)
arch/x86/platform/efi/efi_stub_64.S +3 -0
index 32020cb..92723ae 100644
@@ -11,6 +11,7 @@
 #include <asm/msr.h>
 #include <asm/processor-flags.h>
 #include <asm/page_types.h>
+#include <asm/frame.h>
 
 #define SAVE_XMM			\
 	mov %rsp, %rax;			\
@@ -39,6 +40,7 @@
 	mov (%rsp), %rsp
 
 ENTRY(efi_call)
+	FRAME_BEGIN
 	SAVE_XMM
 	mov (%rsp), %rax
 	mov 8(%rax), %rax
@@ -51,5 +53,6 @@ ENTRY(efi_call)
 	call *%rdi
 	addq $48, %rsp
 	RESTORE_XMM
+	FRAME_END
 	ret
 ENDPROC(efi_call)
Signature · 1 line
2.4.3
#50 lore raw

[tip:x86/debug] x86/asm/efi: Create a stack frame in efi_call()

In reply to Josh Poimboeuf
x86/asm/efi: Create a stack frame in efi_call()
Commit-ID:  779c433b8ea5c9fdfb892265b2ca6213d1f12ff8
Gitweb:     http://git.kernel.org/tip/779c433b8ea5c9fdfb892265b2ca6213d1f12ff8
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:23 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:43 +0100

x86/asm/efi: Create a stack frame in efi_call()

efi_call() is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame for it when CONFIG_FRAME_POINTER is enabled.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/platform/efi/efi_stub_64.S | 3 +++
 1 file changed, 3 insertions(+)
arch/x86/platform/efi/efi_stub_64.S +3 -0
index 86d0f9e..0df2dcc 100644
@@ -11,6 +11,7 @@
 #include <asm/msr.h>
 #include <asm/processor-flags.h>
 #include <asm/page_types.h>
+#include <asm/frame.h>
 
 #define SAVE_XMM			\
 	mov %rsp, %rax;			\
@@ -74,6 +75,7 @@
 	.endm
 
 ENTRY(efi_call)
+	FRAME_BEGIN
 	SAVE_XMM
 	mov (%rsp), %rax
 	mov 8(%rax), %rax
@@ -88,6 +90,7 @@ ENTRY(efi_call)
 	RESTORE_PGT
 	addq $48, %rsp
 	RESTORE_XMM
+	FRAME_END
 	ret
 ENDPROC(efi_call)
 
#51 lore raw

PATCH 20/33 x86/asm/power: Create stack frames in hibernate_asm_64.S

In reply to Josh Poimboeuf

swsusp_arch_suspend() and restore_registers() are callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces. Also they aren't annotated as ELF callable functions which can confuse tooling.

Create a stack frame for them when CONFIG_FRAME_POINTER is enabled and give them proper ELF function annotations.

---
 arch/x86/power/hibernate_asm_64.S | 7 +++++++
 1 file changed, 7 insertions(+)
arch/x86/power/hibernate_asm_64.S +7 -0
index e2386cb..4400a43 100644
@@ -21,8 +21,10 @@
 #include <asm/page_types.h>
 #include <asm/asm-offsets.h>
 #include <asm/processor-flags.h>
+#include <asm/frame.h>
 
 ENTRY(swsusp_arch_suspend)
+	FRAME_BEGIN
 	movq	$saved_context, %rax
 	movq	%rsp, pt_regs_sp(%rax)
 	movq	%rbp, pt_regs_bp(%rax)
@@ -50,7 +52,9 @@ ENTRY(swsusp_arch_suspend)
 	movq	%rax, restore_cr3(%rip)
 
 	call swsusp_save
+	FRAME_END
 	ret
+ENDPROC(swsusp_arch_suspend)
 
 ENTRY(restore_image)
 	/* switch to temporary page tables */
@@ -107,6 +111,7 @@ ENTRY(core_restore_code)
 	 */
 
 ENTRY(restore_registers)
+	FRAME_BEGIN
 	/* go back to the original page tables */
 	movq    %rbx, %cr3
 
@@ -147,4 +152,6 @@ ENTRY(restore_registers)
 	/* tell the hibernation core that we've just restored the memory */
 	movq	%rax, in_suspend(%rip)
 
+	FRAME_END
 	ret
+ENDPROC(restore_registers)
Signature · 1 line
2.4.3
#53 lore raw

[tip:x86/debug] x86/asm/power: Create stack frames in hibernate_asm_64.S

In reply to Josh Poimboeuf
x86/asm/power: Create stack frames in hibernate_asm_64.S
Commit-ID:  ef0f3ed5a4acfb24740480bf2e50b178724f094d
Gitweb:     http://git.kernel.org/tip/ef0f3ed5a4acfb24740480bf2e50b178724f094d
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:24 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:43 +0100

x86/asm/power: Create stack frames in hibernate_asm_64.S

swsusp_arch_suspend() and restore_registers() are callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces. Also they aren't annotated as ELF callable functions which can confuse tooling.

Create a stack frame for them when CONFIG_FRAME_POINTER is enabled and give them proper ELF function annotations.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/power/hibernate_asm_64.S | 7 +++++++
 1 file changed, 7 insertions(+)
arch/x86/power/hibernate_asm_64.S +7 -0
index e2386cb..4400a43 100644
@@ -21,8 +21,10 @@
 #include <asm/page_types.h>
 #include <asm/asm-offsets.h>
 #include <asm/processor-flags.h>
+#include <asm/frame.h>
 
 ENTRY(swsusp_arch_suspend)
+	FRAME_BEGIN
 	movq	$saved_context, %rax
 	movq	%rsp, pt_regs_sp(%rax)
 	movq	%rbp, pt_regs_bp(%rax)
@@ -50,7 +52,9 @@ ENTRY(swsusp_arch_suspend)
 	movq	%rax, restore_cr3(%rip)
 
 	call swsusp_save
+	FRAME_END
 	ret
+ENDPROC(swsusp_arch_suspend)
 
 ENTRY(restore_image)
 	/* switch to temporary page tables */
@@ -107,6 +111,7 @@ ENTRY(core_restore_code)
 	 */
 
 ENTRY(restore_registers)
+	FRAME_BEGIN
 	/* go back to the original page tables */
 	movq    %rbx, %cr3
 
@@ -147,4 +152,6 @@ ENTRY(restore_registers)
 	/* tell the hibernation core that we've just restored the memory */
 	movq	%rax, in_suspend(%rip)
 
+	FRAME_END
 	ret
+ENDPROC(restore_registers)
#54 lore raw

PATCH 21/33 x86/uaccess: Add stack frame output operand in get_user inline asm

In reply to Josh Poimboeuf

From: Chris J Arges <[email protected]>

Numerous 'call without frame pointer save/setup' warnings are introduced by stacktool because of functions using the get_user macro. Bad stack traces could occur due to lack of or misplacement of stack frame setup code.

This patch forces a stack frame to be created before the inline asm code if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the get_user inline assembly statement.

---
 arch/x86/include/asm/uaccess.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/include/asm/uaccess.h +3 -2
index 660458a..2584134 100644
@@ -176,10 +176,11 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
 ({									\
 	int __ret_gu;							\
 	register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX);		\
+	register void *__sp asm(_ASM_SP);				\
 	__chk_user_ptr(ptr);						\
 	might_fault();							\
-	asm volatile("call __get_user_%P3"				\
-		     : "=a" (__ret_gu), "=r" (__val_gu)			\
+	asm volatile("call __get_user_%P4"				\
+		     : "=a" (__ret_gu), "=r" (__val_gu), "+r" (__sp)	\
 		     : "0" (ptr), "i" (sizeof(*(ptr))));		\
 	(x) = (__force __typeof__(*(ptr))) __val_gu;			\
 	__builtin_expect(__ret_gu, 0);					\
Signature · 1 line
2.4.3
#56 lore raw

[tip:x86/debug] x86/uaccess: Add stack frame output operand in get_user() inline asm

In reply to Josh Poimboeuf
x86/uaccess: Add stack frame output operand in get_user() inline asm
Commit-ID:  f05058c4d652b619adfda6c78d8f5b341169c264
Gitweb:     http://git.kernel.org/tip/f05058c4d652b619adfda6c78d8f5b341169c264
Author:     Chris J Arges <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:25 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:43 +0100

x86/uaccess: Add stack frame output operand in get_user() inline asm

Numerous 'call without frame pointer save/setup' warnings are introduced by stacktool because of functions using the get_user() macro. Bad stack traces could occur due to lack of or misplacement of stack frame setup code.

This patch forces a stack frame to be created before the inline asm code if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the get_user() inline assembly statement.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/include/asm/uaccess.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/include/asm/uaccess.h +3 -2
index a4a30e4..9bbb3b2 100644
@@ -179,10 +179,11 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
 ({									\
 	int __ret_gu;							\
 	register __inttype(*(ptr)) __val_gu asm("%"_ASM_DX);		\
+	register void *__sp asm(_ASM_SP);				\
 	__chk_user_ptr(ptr);						\
 	might_fault();							\
-	asm volatile("call __get_user_%P3"				\
-		     : "=a" (__ret_gu), "=r" (__val_gu)			\
+	asm volatile("call __get_user_%P4"				\
+		     : "=a" (__ret_gu), "=r" (__val_gu), "+r" (__sp)	\
 		     : "0" (ptr), "i" (sizeof(*(ptr))));		\
 	(x) = (__force __typeof__(*(ptr))) __val_gu;			\
 	__builtin_expect(__ret_gu, 0);					\
#57 lore raw

PATCH 22/33 x86/asm/bpf: Annotate callable functions

In reply to Josh Poimboeuf

bpf_jit.S has several functions which can be called from C code. Give them proper ELF annotations.

---
 arch/x86/net/bpf_jit.S | 39 ++++++++++++++++-----------------------
 1 file changed, 16 insertions(+), 23 deletions(-)
arch/x86/net/bpf_jit.S +16 -23
index 4093216..eb4a3bd 100644
@@ -22,15 +22,16 @@
 	32 /* space for rbx,r13,r14,r15 */ + \
 	8 /* space for skb_copy_bits */)
 
-sk_load_word:
-	.globl	sk_load_word
+#define FUNC(name) \
+	.globl name; \
+	.type name, @function; \
+	name:
 
+FUNC(sk_load_word)
 	test	%esi,%esi
 	js	bpf_slow_path_word_neg
 
-sk_load_word_positive_offset:
-	.globl	sk_load_word_positive_offset
-
+FUNC(sk_load_word_positive_offset)
 	mov	%r9d,%eax		# hlen
 	sub	%esi,%eax		# hlen - offset
 	cmp	$3,%eax
@@ -39,15 +40,11 @@ sk_load_word_positive_offset:
 	bswap   %eax  			/* ntohl() */
 	ret
 
-sk_load_half:
-	.globl	sk_load_half
-
+FUNC(sk_load_half)
 	test	%esi,%esi
 	js	bpf_slow_path_half_neg
 
-sk_load_half_positive_offset:
-	.globl	sk_load_half_positive_offset
-
+FUNC(sk_load_half_positive_offset)
 	mov	%r9d,%eax
 	sub	%esi,%eax		#	hlen - offset
 	cmp	$1,%eax
@@ -56,15 +53,11 @@ sk_load_half_positive_offset:
 	rol	$8,%ax			# ntohs()
 	ret
 
-sk_load_byte:
-	.globl	sk_load_byte
-
+FUNC(sk_load_byte)
 	test	%esi,%esi
 	js	bpf_slow_path_byte_neg
 
-sk_load_byte_positive_offset:
-	.globl	sk_load_byte_positive_offset
-
+FUNC(sk_load_byte_positive_offset)
 	cmp	%esi,%r9d   /* if (offset >= hlen) goto bpf_slow_path_byte */
 	jle	bpf_slow_path_byte
 	movzbl	(SKBDATA,%rsi),%eax
@@ -120,8 +113,8 @@ bpf_slow_path_byte:
 bpf_slow_path_word_neg:
 	cmp	SKF_MAX_NEG_OFF, %esi	/* test range */
 	jl	bpf_error	/* offset lower -> error  */
-sk_load_word_negative_offset:
-	.globl	sk_load_word_negative_offset
+
+FUNC(sk_load_word_negative_offset)
 	sk_negative_common(4)
 	mov	(%rax), %eax
 	bswap	%eax
@@ -130,8 +123,8 @@ sk_load_word_negative_offset:
 bpf_slow_path_half_neg:
 	cmp	SKF_MAX_NEG_OFF, %esi
 	jl	bpf_error
-sk_load_half_negative_offset:
-	.globl	sk_load_half_negative_offset
+
+FUNC(sk_load_half_negative_offset)
 	sk_negative_common(2)
 	mov	(%rax),%ax
 	rol	$8,%ax
@@ -141,8 +134,8 @@ sk_load_half_negative_offset:
 bpf_slow_path_byte_neg:
 	cmp	SKF_MAX_NEG_OFF, %esi
 	jl	bpf_error
-sk_load_byte_negative_offset:
-	.globl	sk_load_byte_negative_offset
+
+FUNC(sk_load_byte_negative_offset)
 	sk_negative_common(1)
 	movzbl	(%rax), %eax
 	ret
Signature · 1 line
2.4.3
#59 lore raw

[tip:x86/debug] x86/asm/bpf: Annotate callable functions

In reply to Josh Poimboeuf
x86/asm/bpf: Annotate callable functions
Commit-ID:  2d8fe90a1b96d52c2a3f719c385b846b02f0bcd8
Gitweb:     http://git.kernel.org/tip/2d8fe90a1b96d52c2a3f719c385b846b02f0bcd8
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:26 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:43 +0100

x86/asm/bpf: Annotate callable functions

bpf_jit.S has several functions which can be called from C code. Give them proper ELF annotations.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/net/bpf_jit.S | 39 ++++++++++++++++-----------------------
 1 file changed, 16 insertions(+), 23 deletions(-)
arch/x86/net/bpf_jit.S +16 -23
index 4093216..eb4a3bd 100644
@@ -22,15 +22,16 @@
 	32 /* space for rbx,r13,r14,r15 */ + \
 	8 /* space for skb_copy_bits */)
 
-sk_load_word:
-	.globl	sk_load_word
+#define FUNC(name) \
+	.globl name; \
+	.type name, @function; \
+	name:
 
+FUNC(sk_load_word)
 	test	%esi,%esi
 	js	bpf_slow_path_word_neg
 
-sk_load_word_positive_offset:
-	.globl	sk_load_word_positive_offset
-
+FUNC(sk_load_word_positive_offset)
 	mov	%r9d,%eax		# hlen
 	sub	%esi,%eax		# hlen - offset
 	cmp	$3,%eax
@@ -39,15 +40,11 @@ sk_load_word_positive_offset:
 	bswap   %eax  			/* ntohl() */
 	ret
 
-sk_load_half:
-	.globl	sk_load_half
-
+FUNC(sk_load_half)
 	test	%esi,%esi
 	js	bpf_slow_path_half_neg
 
-sk_load_half_positive_offset:
-	.globl	sk_load_half_positive_offset
-
+FUNC(sk_load_half_positive_offset)
 	mov	%r9d,%eax
 	sub	%esi,%eax		#	hlen - offset
 	cmp	$1,%eax
@@ -56,15 +53,11 @@ sk_load_half_positive_offset:
 	rol	$8,%ax			# ntohs()
 	ret
 
-sk_load_byte:
-	.globl	sk_load_byte
-
+FUNC(sk_load_byte)
 	test	%esi,%esi
 	js	bpf_slow_path_byte_neg
 
-sk_load_byte_positive_offset:
-	.globl	sk_load_byte_positive_offset
-
+FUNC(sk_load_byte_positive_offset)
 	cmp	%esi,%r9d   /* if (offset >= hlen) goto bpf_slow_path_byte */
 	jle	bpf_slow_path_byte
 	movzbl	(SKBDATA,%rsi),%eax
@@ -120,8 +113,8 @@ bpf_slow_path_byte:
 bpf_slow_path_word_neg:
 	cmp	SKF_MAX_NEG_OFF, %esi	/* test range */
 	jl	bpf_error	/* offset lower -> error  */
-sk_load_word_negative_offset:
-	.globl	sk_load_word_negative_offset
+
+FUNC(sk_load_word_negative_offset)
 	sk_negative_common(4)
 	mov	(%rax), %eax
 	bswap	%eax
@@ -130,8 +123,8 @@ sk_load_word_negative_offset:
 bpf_slow_path_half_neg:
 	cmp	SKF_MAX_NEG_OFF, %esi
 	jl	bpf_error
-sk_load_half_negative_offset:
-	.globl	sk_load_half_negative_offset
+
+FUNC(sk_load_half_negative_offset)
 	sk_negative_common(2)
 	mov	(%rax),%ax
 	rol	$8,%ax
@@ -141,8 +134,8 @@ sk_load_half_negative_offset:
 bpf_slow_path_byte_neg:
 	cmp	SKF_MAX_NEG_OFF, %esi
 	jl	bpf_error
-sk_load_byte_negative_offset:
-	.globl	sk_load_byte_negative_offset
+
+FUNC(sk_load_byte_negative_offset)
 	sk_negative_common(1)
 	movzbl	(%rax), %eax
 	ret
#60 lore raw

PATCH 23/33 x86/asm/bpf: Create stack frames in bpf_jit.S

In reply to Josh Poimboeuf

bpf_jit.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame before the call instructions when CONFIG_FRAME_POINTER is enabled.

---
 arch/x86/net/bpf_jit.S | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/net/bpf_jit.S +7 -2
index eb4a3bd..f2a7faf 100644
@@ -8,6 +8,7 @@
  * of the License.
  */
 #include <linux/linkage.h>
+#include <asm/frame.h>
 
 /*
  * Calling convention :
@@ -65,16 +66,18 @@ FUNC(sk_load_byte_positive_offset)
 
 /* rsi contains offset and can be scratched */
 #define bpf_slow_path_common(LEN)		\
+	lea	-MAX_BPF_STACK + 32(%rbp), %rdx;\
+	FRAME_BEGIN;				\
 	mov	%rbx, %rdi; /* arg1 == skb */	\
 	push	%r9;				\
 	push	SKBDATA;			\
 /* rsi already has offset */			\
 	mov	$LEN,%ecx;	/* len */	\
-	lea	- MAX_BPF_STACK + 32(%rbp),%rdx;			\
 	call	skb_copy_bits;			\
 	test    %eax,%eax;			\
 	pop	SKBDATA;			\
-	pop	%r9;
+	pop	%r9;				\
+	FRAME_END
 
 
 bpf_slow_path_word:
@@ -99,6 +102,7 @@ bpf_slow_path_byte:
 	ret
 
 #define sk_negative_common(SIZE)				\
+	FRAME_BEGIN;						\
 	mov	%rbx, %rdi; /* arg1 == skb */			\
 	push	%r9;						\
 	push	SKBDATA;					\
@@ -108,6 +112,7 @@ bpf_slow_path_byte:
 	test	%rax,%rax;					\
 	pop	SKBDATA;					\
 	pop	%r9;						\
+	FRAME_END;						\
 	jz	bpf_error
 
 bpf_slow_path_word_neg:
Signature · 1 line
2.4.3
#61 lore raw

Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S

Quoted 33 lines · Josh Poimboeuf

bpf_jit.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame before the call instructions when CONFIG_FRAME_POINTER is enabled.

---
 arch/x86/net/bpf_jit.S | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/net/bpf_jit.S +3 -0
index eb4a3bd..f2a7faf 100644
@@ -8,6 +8,7 @@
  * of the License.
  */
 #include <linux/linkage.h>
+#include <asm/frame.h>
 
 /*
  * Calling convention :
@@ -65,16 +66,18 @@ FUNC(sk_load_byte_positive_offset)
 
 /* rsi contains offset and can be scratched */
 #define bpf_slow_path_common(LEN)		\
+	lea	-MAX_BPF_STACK + 32(%rbp), %rdx;\
+	FRAME_BEGIN;				\
 	mov	%rbx, %rdi; /* arg1 == skb */	\
 	push	%r9;				\

arch/x86/net/bpf_jit.S FUNC(sk_load_byte_positive_offset) · line 80

Quoted 10 lines
arch/x86/net/bpf_jit.S +2 -2
 	push	SKBDATA;			\
 /* rsi already has offset */			\
 	mov	$LEN,%ecx;	/* len */	\
-	lea	- MAX_BPF_STACK + 32(%rbp),%rdx;			\
 	call	skb_copy_bits;			\
 	test    %eax,%eax;			\
 	pop	SKBDATA;			\
-	pop	%r9;
+	pop	%r9;				\
+	FRAME_END

I'm not sure what above is doing.
There is already 'push rbp; mov rbp,rsp' at the beginning of generated code and with above the stack trace will show two function at the same ip? since there were no calls between them?
I think the stack walker will get even more confused?
Also the JIT of bpf_call insn will emit variable number of push/pop around the call and I definitely don't want to add extra push rbp there, since it's the critical path and callee will do its own push rbp.
Also there are push/pops emitted around div/mod
and there is indirect goto emitted as well for bpf_tail_call that jumps into different function body without touching current stack.
Also none of the JITed function are dwarf annotated.
I could be missing something. I think either this patch
is not need or you need to teach the tool to ignore
all JITed stuff. I don't think it's practical to annotate everything. Different JITs do their own magic.
s390 JIT is even more fancy.

#62 lore raw

Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S

Quoted 50 lines · Alexei Starovoitov
Quoted 33 lines · Josh Poimboeuf

bpf_jit.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame before the call instructions when CONFIG_FRAME_POINTER is enabled.

---
 arch/x86/net/bpf_jit.S | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/net/bpf_jit.S +3 -0
index eb4a3bd..f2a7faf 100644
@@ -8,6 +8,7 @@
  * of the License.
  */
 #include <linux/linkage.h>
+#include <asm/frame.h>
 
 /*
  * Calling convention :
@@ -65,16 +66,18 @@ FUNC(sk_load_byte_positive_offset)
 
 /* rsi contains offset and can be scratched */
 #define bpf_slow_path_common(LEN)		\
+	lea	-MAX_BPF_STACK + 32(%rbp), %rdx;\
+	FRAME_BEGIN;				\
 	mov	%rbx, %rdi; /* arg1 == skb */	\
 	push	%r9;				\

arch/x86/net/bpf_jit.S FUNC(sk_load_byte_positive_offset) · line 80

Quoted 10 lines
arch/x86/net/bpf_jit.S +2 -2
 	push	SKBDATA;			\
 /* rsi already has offset */			\
 	mov	$LEN,%ecx;	/* len */	\
-	lea	- MAX_BPF_STACK + 32(%rbp),%rdx;			\
 	call	skb_copy_bits;			\
 	test    %eax,%eax;			\
 	pop	SKBDATA;			\
-	pop	%r9;
+	pop	%r9;				\
+	FRAME_END

I'm not sure what above is doing.
There is already 'push rbp; mov rbp,rsp' at the beginning of generated code and with above the stack trace will show two function at the same ip? since there were no calls between them?
I think the stack walker will get even more confused?

Quoted 8 lines

Also the JIT of bpf_call insn will emit variable number of push/pop around the call and I definitely don't want to add extra push rbp there, since it's the critical path and callee will do its own push rbp.
Also there are push/pops emitted around div/mod
and there is indirect goto emitted as well for bpf_tail_call that jumps into different function body without touching current stack.

Hm, I'm not sure I follow. Let me try to explain my understanding.

As you mentioned, the generated code sets up the frame pointer. From emit_prologue():

        EMIT1(0x55); /* push rbp */
	EMIT3(0x48, 0x89, 0xE5); /* mov rbp,rsp */

And then later, do_jit() can generate a call into the functions in bpf_jit.S. For example:

	func = CHOOSE_LOAD_FUNC(imm32, sk_load_word);
	...
	EMIT1_off32(0xE8, jmp_offset); /* call */

So the functions in bpf_jit.S are being called by the generated code. They're not part of the generated code itself. So they're callees and need to create their own stack frame before they call out to somewhere else.

Or did I miss something?

Quoted 1 line

Also none of the JITed function are dwarf annotated.

But what does that have to do with frame pointers?

Quoted 5 lines

I could be missing something. I think either this patch is not need or you need to teach the tool to ignore all JITed stuff. I don't think it's practical to annotate everything. Different JITs do their own magic. s390 JIT is even more fancy.

Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor CONFIG_FRAME_POINTER just like any other code.

Signature · 1 line
Josh
#63 lore raw

Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S

Quoted 75 lines · Josh Poimboeuf
Quoted 50 lines · Alexei Starovoitov
Quoted 33 lines · Josh Poimboeuf

bpf_jit.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame before the call instructions when CONFIG_FRAME_POINTER is enabled.

---
 arch/x86/net/bpf_jit.S | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/net/bpf_jit.S +3 -0
index eb4a3bd..f2a7faf 100644
@@ -8,6 +8,7 @@
  * of the License.
  */
 #include <linux/linkage.h>
+#include <asm/frame.h>
 
 /*
  * Calling convention :
@@ -65,16 +66,18 @@ FUNC(sk_load_byte_positive_offset)
 
 /* rsi contains offset and can be scratched */
 #define bpf_slow_path_common(LEN)		\
+	lea	-MAX_BPF_STACK + 32(%rbp), %rdx;\
+	FRAME_BEGIN;				\
 	mov	%rbx, %rdi; /* arg1 == skb */	\
 	push	%r9;				\

arch/x86/net/bpf_jit.S FUNC(sk_load_byte_positive_offset) · line 80

Quoted 10 lines
arch/x86/net/bpf_jit.S +2 -2
 	push	SKBDATA;			\
 /* rsi already has offset */			\
 	mov	$LEN,%ecx;	/* len */	\
-	lea	- MAX_BPF_STACK + 32(%rbp),%rdx;			\
 	call	skb_copy_bits;			\
 	test    %eax,%eax;			\
 	pop	SKBDATA;			\
-	pop	%r9;
+	pop	%r9;				\
+	FRAME_END

I'm not sure what above is doing.
There is already 'push rbp; mov rbp,rsp' at the beginning of generated code and with above the stack trace will show two function at the same ip? since there were no calls between them?
I think the stack walker will get even more confused?

Quoted 8 lines

Also the JIT of bpf_call insn will emit variable number of push/pop around the call and I definitely don't want to add extra push rbp there, since it's the critical path and callee will do its own push rbp.
Also there are push/pops emitted around div/mod
and there is indirect goto emitted as well for bpf_tail_call that jumps into different function body without touching current stack.

Hm, I'm not sure I follow. Let me try to explain my understanding.

As you mentioned, the generated code sets up the frame pointer. From emit_prologue():

        EMIT1(0x55); /* push rbp */
	EMIT3(0x48, 0x89, 0xE5); /* mov rbp,rsp */

And then later, do_jit() can generate a call into the functions in bpf_jit.S. For example:

	func = CHOOSE_LOAD_FUNC(imm32, sk_load_word);
	...
	EMIT1_off32(0xE8, jmp_offset); /* call */
Quoted 6 lines

So the functions in bpf_jit.S are being called by the generated code. They're not part of the generated code itself. So they're callees and need to create their own stack frame before they call out to somewhere else.

Or did I miss something?

yes. all correct.
This particular patch is ok, since it adds to bpf_slow_path_common and as the name says it's slow and rare, but wanted to make sure the rest of it is understood.

Quoted 3 lines
Quoted 1 line

Also none of the JITed function are dwarf annotated.

But what does that have to do with frame pointers?

nothing, but then why do you need
.type name, @function
annotations in another patch?

Quoted 10 lines
Quoted 5 lines

I could be missing something. I think either this patch is not need or you need to teach the tool to ignore all JITed stuff. I don't think it's practical to annotate everything. Different JITs do their own magic. s390 JIT is even more fancy.

Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor CONFIG_FRAME_POINTER just like any other code.

It can if there is no performance cost added.
I can speak for x64 JIT, but the rest needs to be analyzed as well. My point was that may be it's easier to ignore all JITed code and just say that such call stacks may be unreliable? live-patching is not applicable to JITed code anyway
or you want to livepatch the callees of it?

#64 lore raw

Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S

Quoted 10 lines · Alexei Starovoitov
Quoted 9 lines
Quoted 4 lines

I could be missing something. I think either this patch is not need or you need to teach the tool to ignore all JITed stuff. I don't think it's practical to annotate everything. Different JITs do their own magic. s390 JIT is even more fancy.

Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor CONFIG_FRAME_POINTER just like any other code.

Quoted 5 lines

It can if there is no performance cost added. I can speak for x64 JIT, but the rest needs to be analyzed as well. My point was that may be it's easier to ignore all JITed code and just say that such call stacks may be unreliable? live-patching is not applicable to JITed code anyway or you want to livepatch the callees of it?

So the rule is that if frame pointers are enabled all kernel code should have correct stack frames - in case an IRQ (or NMI) hits it or it crashes.

Thanks,

Ingo

#65 lore raw

Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S

In reply to Alexei Starovoitov
Quoted 88 lines · Alexei Starovoitov
Quoted 75 lines · Josh Poimboeuf
Quoted 50 lines · Alexei Starovoitov
Quoted 33 lines · Josh Poimboeuf

bpf_jit.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame before the call instructions when CONFIG_FRAME_POINTER is enabled.

---
 arch/x86/net/bpf_jit.S | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/net/bpf_jit.S +3 -0
index eb4a3bd..f2a7faf 100644
@@ -8,6 +8,7 @@
  * of the License.
  */
 #include <linux/linkage.h>
+#include <asm/frame.h>
 
 /*
  * Calling convention :
@@ -65,16 +66,18 @@ FUNC(sk_load_byte_positive_offset)
 
 /* rsi contains offset and can be scratched */
 #define bpf_slow_path_common(LEN)		\
+	lea	-MAX_BPF_STACK + 32(%rbp), %rdx;\
+	FRAME_BEGIN;				\
 	mov	%rbx, %rdi; /* arg1 == skb */	\
 	push	%r9;				\

arch/x86/net/bpf_jit.S FUNC(sk_load_byte_positive_offset) · line 80

Quoted 10 lines
arch/x86/net/bpf_jit.S +2 -2
 	push	SKBDATA;			\
 /* rsi already has offset */			\
 	mov	$LEN,%ecx;	/* len */	\
-	lea	- MAX_BPF_STACK + 32(%rbp),%rdx;			\
 	call	skb_copy_bits;			\
 	test    %eax,%eax;			\
 	pop	SKBDATA;			\
-	pop	%r9;
+	pop	%r9;				\
+	FRAME_END

I'm not sure what above is doing.
There is already 'push rbp; mov rbp,rsp' at the beginning of generated code and with above the stack trace will show two function at the same ip? since there were no calls between them?
I think the stack walker will get even more confused?

Quoted 8 lines

Also the JIT of bpf_call insn will emit variable number of push/pop around the call and I definitely don't want to add extra push rbp there, since it's the critical path and callee will do its own push rbp.
Also there are push/pops emitted around div/mod
and there is indirect goto emitted as well for bpf_tail_call that jumps into different function body without touching current stack.

Hm, I'm not sure I follow. Let me try to explain my understanding.

As you mentioned, the generated code sets up the frame pointer. From emit_prologue():

        EMIT1(0x55); /* push rbp */
	EMIT3(0x48, 0x89, 0xE5); /* mov rbp,rsp */

And then later, do_jit() can generate a call into the functions in bpf_jit.S. For example:

	func = CHOOSE_LOAD_FUNC(imm32, sk_load_word);
	...
	EMIT1_off32(0xE8, jmp_offset); /* call */
Quoted 6 lines

So the functions in bpf_jit.S are being called by the generated code. They're not part of the generated code itself. So they're callees and need to create their own stack frame before they call out to somewhere else.

Or did I miss something?

yes. all correct.
This particular patch is ok, since it adds to bpf_slow_path_common and as the name says it's slow and rare, but wanted to make sure the rest of it is understood.

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

Also none of the JITed function are dwarf annotated.

But what does that have to do with frame pointers?

nothing, but then why do you need
.type name, @function
annotations in another patch?

Those are ELF function annotations which are needed so that stacktool can find and analyze all callable functions (and they're a good idea anyway for the sake of other tooling).

Obviously we can't annotate the JIT functions which have no name, but that's ok. As long as they're doing the right thing with respect to frame pointers, the stack dump code will still be able to see their frames (and that they're associated with generated code).

Quoted 6 lines
Quoted 6 lines
Quoted 5 lines

I could be missing something. I think either this patch is not need or you need to teach the tool to ignore all JITed stuff. I don't think it's practical to annotate everything. Different JITs do their own magic. s390 JIT is even more fancy.

Quoted 6 lines
Quoted 4 lines

Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor CONFIG_FRAME_POINTER just like any other code.

It can if there is no performance cost added.

CONFIG_FRAME_POINTER always adds a small performance cost but as you mentioned it only affects the slow path here. And hopefully we'll soon have an in-kernel DWARF unwinder on x86 so we can get rid of the need for frame pointers.

Quoted 5 lines

I can speak for x64 JIT, but the rest needs to be analyzed as well. My point was that may be it's easier to ignore all JITed code and just say that such call stacks may be unreliable? live-patching is not applicable to JITed code anyway
or you want to livepatch the callees of it?

Right. We can't patch JIT code, but we might need to patch other functions on the call stack (including callees and callers).

Signature · 1 line
Josh
#66 lore raw

Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S

Quoted 15 lines · Josh Poimboeuf
Quoted 14 lines · Alexei Starovoitov
Quoted 13 lines · Josh Poimboeuf
Quoted 12 lines · Alexei Starovoitov
Quoted 11 lines · Josh Poimboeuf

bpf_jit.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame before the call instructions when CONFIG_FRAME_POINTER is enabled.

---
 arch/x86/net/bpf_jit.S | 9 +++++++--

...

Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines

/* rsi contains offset and can be scratched */
#define bpf_slow_path_common(LEN) \

arch/x86/net/bpf_jit.S +4 -2
+	lea	-MAX_BPF_STACK + 32(%rbp), %rdx;\
+	FRAME_BEGIN;				\
 	mov	%rbx, %rdi; /* arg1 == skb */	\
 	push	%r9;				\
 	push	SKBDATA;			\
 /* rsi already has offset */			\
 	mov	$LEN,%ecx;	/* len */	\
-	lea	- MAX_BPF_STACK + 32(%rbp),%rdx;			\
 	call	skb_copy_bits;			\
 	test    %eax,%eax;			\
 	pop	SKBDATA;			\
-	pop	%r9;
+	pop	%r9;				\
+	FRAME_END

...

Quoted 11 lines
Quoted 6 lines
Quoted 4 lines

Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor CONFIG_FRAME_POINTER just like any other code.

It can if there is no performance cost added.

CONFIG_FRAME_POINTER always adds a small performance cost but as you mentioned it only affects the slow path here. And hopefully we'll soon have an in-kernel DWARF unwinder on x86 so we can get rid of the need for frame pointers.

ok. fair enough.

#67 lore raw

Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S

Quoted 41 lines · Alexei Starovoitov
Quoted 15 lines · Josh Poimboeuf
Quoted 14 lines · Alexei Starovoitov
Quoted 13 lines · Josh Poimboeuf
Quoted 12 lines · Alexei Starovoitov
Quoted 11 lines · Josh Poimboeuf

bpf_jit.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame before the call instructions when CONFIG_FRAME_POINTER is enabled.

---
 arch/x86/net/bpf_jit.S | 9 +++++++--

...

Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines

/* rsi contains offset and can be scratched */
#define bpf_slow_path_common(LEN) \

arch/x86/net/bpf_jit.S +4 -2
+	lea	-MAX_BPF_STACK + 32(%rbp), %rdx;\
+	FRAME_BEGIN;				\
 	mov	%rbx, %rdi; /* arg1 == skb */	\
 	push	%r9;				\
 	push	SKBDATA;			\
 /* rsi already has offset */			\
 	mov	$LEN,%ecx;	/* len */	\
-	lea	- MAX_BPF_STACK + 32(%rbp),%rdx;			\
 	call	skb_copy_bits;			\
 	test    %eax,%eax;			\
 	pop	SKBDATA;			\
-	pop	%r9;
+	pop	%r9;				\
+	FRAME_END

...

Quoted 7 lines
Quoted 6 lines
Quoted 4 lines

Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor CONFIG_FRAME_POINTER just like any other code.

It can if there is no performance cost added.

Quoted 7 lines
Quoted 4 lines

CONFIG_FRAME_POINTER always adds a small performance cost but as you mentioned it only affects the slow path here. And hopefully we'll soon have an in-kernel DWARF unwinder on x86 so we can get rid of the need for frame pointers.

ok. fair enough.

Thanks!

Can I assume your ack also applies to the previous patch which adds the ELF annotations ("x86/asm/bpf: Annotate callable functions")?

Signature · 1 line
Josh
#68 lore raw

Re: [PATCH 23/33] x86/asm/bpf: Create stack frames in bpf_jit.S

Quoted 47 lines · Josh Poimboeuf
Quoted 46 lines · Alexei Starovoitov
Quoted 15 lines · Josh Poimboeuf
Quoted 14 lines · Alexei Starovoitov
Quoted 13 lines · Josh Poimboeuf
Quoted 12 lines · Alexei Starovoitov
Quoted 11 lines · Josh Poimboeuf

bpf_jit.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame before the call instructions when CONFIG_FRAME_POINTER is enabled.

---
 arch/x86/net/bpf_jit.S | 9 +++++++--

...

Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines
Quoted 16 lines

/* rsi contains offset and can be scratched */
#define bpf_slow_path_common(LEN) \

(quoted diff) +4 -2
+	lea	-MAX_BPF_STACK + 32(%rbp), %rdx;\
+	FRAME_BEGIN;				\
 	mov	%rbx, %rdi; /* arg1 == skb */	\
 	push	%r9;				\
 	push	SKBDATA;			\
 /* rsi already has offset */			\
 	mov	$LEN,%ecx;	/* len */	\
-	lea	- MAX_BPF_STACK + 32(%rbp),%rdx;			\
 	call	skb_copy_bits;			\
 	test    %eax,%eax;			\
 	pop	SKBDATA;			\
-	pop	%r9;
+	pop	%r9;				\
+	FRAME_END

...

Quoted 11 lines
Quoted 6 lines
Quoted 4 lines

Well, but the point of these patches isn't to make the tool happy. It's really to make sure that runtime stack traces can be made reliable. Maybe I'm missing something but I don't see why JIT code can't honor CONFIG_FRAME_POINTER just like any other code.

It can if there is no performance cost added.

CONFIG_FRAME_POINTER always adds a small performance cost but as you mentioned it only affects the slow path here. And hopefully we'll soon have an in-kernel DWARF unwinder on x86 so we can get rid of the need for frame pointers.

Quoted 7 lines
Quoted 2 lines

ok. fair enough.

Thanks!

Can I assume your ack also applies to the previous patch which adds the ELF annotations ("x86/asm/bpf: Annotate callable functions")?

Yes. Thanks.

#70 lore raw

[tip:x86/debug] x86/asm/bpf: Create stack frames in bpf_jit.S

In reply to Josh Poimboeuf
x86/asm/bpf: Create stack frames in bpf_jit.S
Commit-ID:  d21001cc15ba9f63b0334d60942278587471a451
Gitweb:     http://git.kernel.org/tip/d21001cc15ba9f63b0334d60942278587471a451
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:27 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:44 +0100

x86/asm/bpf: Create stack frames in bpf_jit.S

bpf_jit.S has several callable non-leaf functions which don't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame before the call instructions when CONFIG_FRAME_POINTER is enabled.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/net/bpf_jit.S | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
arch/x86/net/bpf_jit.S +7 -2
index eb4a3bd..f2a7faf 100644
@@ -8,6 +8,7 @@
  * of the License.
  */
 #include <linux/linkage.h>
+#include <asm/frame.h>
 
 /*
  * Calling convention :
@@ -65,16 +66,18 @@ FUNC(sk_load_byte_positive_offset)
 
 /* rsi contains offset and can be scratched */
 #define bpf_slow_path_common(LEN)		\
+	lea	-MAX_BPF_STACK + 32(%rbp), %rdx;\
+	FRAME_BEGIN;				\
 	mov	%rbx, %rdi; /* arg1 == skb */	\
 	push	%r9;				\
 	push	SKBDATA;			\
 /* rsi already has offset */			\
 	mov	$LEN,%ecx;	/* len */	\
-	lea	- MAX_BPF_STACK + 32(%rbp),%rdx;			\
 	call	skb_copy_bits;			\
 	test    %eax,%eax;			\
 	pop	SKBDATA;			\
-	pop	%r9;
+	pop	%r9;				\
+	FRAME_END
 
 
 bpf_slow_path_word:
@@ -99,6 +102,7 @@ bpf_slow_path_byte:
 	ret
 
 #define sk_negative_common(SIZE)				\
+	FRAME_BEGIN;						\
 	mov	%rbx, %rdi; /* arg1 == skb */			\
 	push	%r9;						\
 	push	SKBDATA;					\
@@ -108,6 +112,7 @@ bpf_slow_path_byte:
 	test	%rax,%rax;					\
 	pop	SKBDATA;					\
 	pop	%r9;						\
+	FRAME_END;						\
 	jz	bpf_error
 
 bpf_slow_path_word_neg:
#71 lore raw

PATCH 24/33 x86/kprobes: Get rid of kretprobe_trampoline_holder()

In reply to Josh Poimboeuf

The kretprobe_trampoline_holder() wrapper around kretprobe_trampoline() isn't used anywhere and adds some unnecessary frame pointer instructions which never execute. Instead, just make kretprobe_trampoline() a proper ELF function.

Cc Ananth N Mavinakayanahalli <[email protected]>
Cc Anil S Keshavamurthy <[email protected]>
Cc "David S. Miller" <[email protected]>
Cc Masami Hiramatsu <[email protected]>
---
 arch/x86/kernel/kprobes/core.c | 57 +++++++++++++++++++++---------------------
 1 file changed, 28 insertions(+), 29 deletions(-)
arch/x86/kernel/kprobes/core.c +28 -29
index 1deffe6..5b187df 100644
@@ -671,38 +671,37 @@ NOKPROBE_SYMBOL(kprobe_int3_handler);
  * When a retprobed function returns, this code saves registers and
  * calls trampoline_handler() runs, which calls the kretprobe's handler.
  */
-static void __used kretprobe_trampoline_holder(void)
-{
-	asm volatile (
-			".global kretprobe_trampoline\n"
-			"kretprobe_trampoline: \n"
+asm(
+	".global kretprobe_trampoline\n"
+	".type kretprobe_trampoline, @function\n"
+	"kretprobe_trampoline:\n"
 #ifdef CONFIG_X86_64
-			/* We don't bother saving the ss register */
-			"	pushq %rsp\n"
-			"	pushfq\n"
-			SAVE_REGS_STRING
-			"	movq %rsp, %rdi\n"
-			"	call trampoline_handler\n"
-			/* Replace saved sp with true return address. */
-			"	movq %rax, 152(%rsp)\n"
-			RESTORE_REGS_STRING
-			"	popfq\n"
+	/* We don't bother saving the ss register */
+	"	pushq %rsp\n"
+	"	pushfq\n"
+	SAVE_REGS_STRING
+	"	movq %rsp, %rdi\n"
+	"	call trampoline_handler\n"
+	/* Replace saved sp with true return address. */
+	"	movq %rax, 152(%rsp)\n"
+	RESTORE_REGS_STRING
+	"	popfq\n"
 #else
-			"	pushf\n"
-			SAVE_REGS_STRING
-			"	movl %esp, %eax\n"
-			"	call trampoline_handler\n"
-			/* Move flags to cs */
-			"	movl 56(%esp), %edx\n"
-			"	movl %edx, 52(%esp)\n"
-			/* Replace saved flags with true return address. */
-			"	movl %eax, 56(%esp)\n"
-			RESTORE_REGS_STRING
-			"	popf\n"
+	"	pushf\n"
+	SAVE_REGS_STRING
+	"	movl %esp, %eax\n"
+	"	call trampoline_handler\n"
+	/* Move flags to cs */
+	"	movl 56(%esp), %edx\n"
+	"	movl %edx, 52(%esp)\n"
+	/* Replace saved flags with true return address. */
+	"	movl %eax, 56(%esp)\n"
+	RESTORE_REGS_STRING
+	"	popf\n"
 #endif
-			"	ret\n");
-}
-NOKPROBE_SYMBOL(kretprobe_trampoline_holder);
+	"	ret\n"
+	".size kretprobe_trampoline, .-kretprobe_trampoline\n"
+);
 NOKPROBE_SYMBOL(kretprobe_trampoline);
 
 /*
Signature · 1 line
2.4.3
#72 lore raw

RE: [PATCH 24/33] x86/kprobes: Get rid of kretprobe_trampoline_holder()

Quoted 7 lines

From: Josh Poimboeuf [mailto:[email protected]]

The kretprobe_trampoline_holder() wrapper around kretprobe_trampoline() isn't used anywhere and adds some unnecessary frame pointer instructions which never execute. Instead, just make kretprobe_trampoline() a proper ELF function.

Looks good to me :)

Thanks!

Quoted 82 lines
Cc Ananth N Mavinakayanahalli <[email protected]>
Cc Anil S Keshavamurthy <[email protected]>
Cc "David S. Miller" <[email protected]>
Cc Masami Hiramatsu <[email protected]>

---
arch/x86/kernel/kprobes/core.c | 57 +++++++++++++++++++++---------------------

1 file changed, 28 insertions(+), 29 deletions(-)
arch/x86/kernel/kprobes/core.c +28 -30
index 1deffe6..5b187df 100644
@@ -671,38 +671,37 @@ NOKPROBE_SYMBOL(kprobe_int3_handler);
 * When a retprobed function returns, this code saves registers and
 * calls trampoline_handler() runs, which calls the kretprobe's handler.
 */
-static void __used kretprobe_trampoline_holder(void)
-{
-	asm volatile (
-			".global kretprobe_trampoline\n"
-			"kretprobe_trampoline: \n"
+asm(
+	".global kretprobe_trampoline\n"
+	".type kretprobe_trampoline, @function\n"
+	"kretprobe_trampoline:\n"
 #ifdef CONFIG_X86_64
-			/* We don't bother saving the ss register */
-			"	pushq %rsp\n"
-			"	pushfq\n"
-			SAVE_REGS_STRING
-			"	movq %rsp, %rdi\n"
-			"	call trampoline_handler\n"
-			/* Replace saved sp with true return address. */
-			"	movq %rax, 152(%rsp)\n"
-			RESTORE_REGS_STRING
-			"	popfq\n"
+	/* We don't bother saving the ss register */
+	"	pushq %rsp\n"
+	"	pushfq\n"
+	SAVE_REGS_STRING
+	"	movq %rsp, %rdi\n"
+	"	call trampoline_handler\n"
+	/* Replace saved sp with true return address. */
+	"	movq %rax, 152(%rsp)\n"
+	RESTORE_REGS_STRING
+	"	popfq\n"
 #else
-			"	pushf\n"
-			SAVE_REGS_STRING
-			"	movl %esp, %eax\n"
-			"	call trampoline_handler\n"
-			/* Move flags to cs */
-			"	movl 56(%esp), %edx\n"
-			"	movl %edx, 52(%esp)\n"
-			/* Replace saved flags with true return address. */
-			"	movl %eax, 56(%esp)\n"
-			RESTORE_REGS_STRING
-			"	popf\n"
+	"	pushf\n"
+	SAVE_REGS_STRING
+	"	movl %esp, %eax\n"
+	"	call trampoline_handler\n"
+	/* Move flags to cs */
+	"	movl 56(%esp), %edx\n"
+	"	movl %edx, 52(%esp)\n"
+	/* Replace saved flags with true return address. */
+	"	movl %eax, 56(%esp)\n"
+	RESTORE_REGS_STRING
+	"	popf\n"
 #endif
-			"	ret\n");
-}
-NOKPROBE_SYMBOL(kretprobe_trampoline_holder);
+	"	ret\n"
+	".size kretprobe_trampoline, .-kretprobe_trampoline\n"
+);
 NOKPROBE_SYMBOL(kretprobe_trampoline);
 
 /*
--

2.4.3

#74 lore raw

[tip:x86/debug] x86/kprobes: Get rid of kretprobe_trampoline_holder()

In reply to Josh Poimboeuf
x86/kprobes: Get rid of kretprobe_trampoline_holder()
Commit-ID:  c1c355ce14c037666fbcb9453d9067c86bbdda5c
Gitweb:     http://git.kernel.org/tip/c1c355ce14c037666fbcb9453d9067c86bbdda5c
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:28 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:44 +0100

x86/kprobes: Get rid of kretprobe_trampoline_holder()

The kretprobe_trampoline_holder() wrapper around kretprobe_trampoline() isn't used anywhere and adds some unnecessary frame pointer instructions which never execute. Instead, just make kretprobe_trampoline() a proper ELF function.

Cc Ananth N Mavinakayanahalli <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Anil S Keshavamurthy <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc David S. Miller <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/kernel/kprobes/core.c | 57 +++++++++++++++++++++---------------------
 1 file changed, 28 insertions(+), 29 deletions(-)
arch/x86/kernel/kprobes/core.c +28 -29
index 1deffe6..5b187df 100644
@@ -671,38 +671,37 @@ NOKPROBE_SYMBOL(kprobe_int3_handler);
  * When a retprobed function returns, this code saves registers and
  * calls trampoline_handler() runs, which calls the kretprobe's handler.
  */
-static void __used kretprobe_trampoline_holder(void)
-{
-	asm volatile (
-			".global kretprobe_trampoline\n"
-			"kretprobe_trampoline: \n"
+asm(
+	".global kretprobe_trampoline\n"
+	".type kretprobe_trampoline, @function\n"
+	"kretprobe_trampoline:\n"
 #ifdef CONFIG_X86_64
-			/* We don't bother saving the ss register */
-			"	pushq %rsp\n"
-			"	pushfq\n"
-			SAVE_REGS_STRING
-			"	movq %rsp, %rdi\n"
-			"	call trampoline_handler\n"
-			/* Replace saved sp with true return address. */
-			"	movq %rax, 152(%rsp)\n"
-			RESTORE_REGS_STRING
-			"	popfq\n"
+	/* We don't bother saving the ss register */
+	"	pushq %rsp\n"
+	"	pushfq\n"
+	SAVE_REGS_STRING
+	"	movq %rsp, %rdi\n"
+	"	call trampoline_handler\n"
+	/* Replace saved sp with true return address. */
+	"	movq %rax, 152(%rsp)\n"
+	RESTORE_REGS_STRING
+	"	popfq\n"
 #else
-			"	pushf\n"
-			SAVE_REGS_STRING
-			"	movl %esp, %eax\n"
-			"	call trampoline_handler\n"
-			/* Move flags to cs */
-			"	movl 56(%esp), %edx\n"
-			"	movl %edx, 52(%esp)\n"
-			/* Replace saved flags with true return address. */
-			"	movl %eax, 56(%esp)\n"
-			RESTORE_REGS_STRING
-			"	popf\n"
+	"	pushf\n"
+	SAVE_REGS_STRING
+	"	movl %esp, %eax\n"
+	"	call trampoline_handler\n"
+	/* Move flags to cs */
+	"	movl 56(%esp), %edx\n"
+	"	movl %edx, 52(%esp)\n"
+	/* Replace saved flags with true return address. */
+	"	movl %eax, 56(%esp)\n"
+	RESTORE_REGS_STRING
+	"	popf\n"
 #endif
-			"	ret\n");
-}
-NOKPROBE_SYMBOL(kretprobe_trampoline_holder);
+	"	ret\n"
+	".size kretprobe_trampoline, .-kretprobe_trampoline\n"
+);
 NOKPROBE_SYMBOL(kretprobe_trampoline);
 
 /*
#75 lore raw

PATCH 25/33 x86/kvm: Set ELF function type for fastop functions

In reply to Josh Poimboeuf

The callable functions created with the FOP* and FASTOP* macros are missing ELF function annotations, which confuses tools like stacktool. Properly annotate them.

This adds some additional labels to the assembly, but the generated binary code is unchanged (with the exception of instructions which have embedded references to __LINE__).

---
 arch/x86/kvm/emulate.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)
arch/x86/kvm/emulate.c +21 -8
index 1505587..aa4d726 100644
@@ -309,23 +309,29 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)
 
 static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
 
-#define FOP_ALIGN ".align " __stringify(FASTOP_SIZE) " \n\t"
+#define FOP_FUNC(name) \
+	".align " __stringify(FASTOP_SIZE) " \n\t" \
+	".type " name ", @function \n\t" \
+	name ":\n\t"
+
 #define FOP_RET   "ret \n\t"
 
 #define FOP_START(op) \
 	extern void em_##op(struct fastop *fake); \
 	asm(".pushsection .text, \"ax\" \n\t" \
 	    ".global em_" #op " \n\t" \
-            FOP_ALIGN \
-	    "em_" #op ": \n\t"
+	    FOP_FUNC("em_" #op)
 
 #define FOP_END \
 	    ".popsection")
 
-#define FOPNOP() FOP_ALIGN FOP_RET
+#define FOPNOP() \
+	FOP_FUNC(__stringify(__UNIQUE_ID(nop))) \
+	FOP_RET
 
 #define FOP1E(op,  dst) \
-	FOP_ALIGN "10: " #op " %" #dst " \n\t" FOP_RET
+	FOP_FUNC(#op "_" #dst) \
+	"10: " #op " %" #dst " \n\t" FOP_RET
 
 #define FOP1EEX(op,  dst) \
 	FOP1E(op, dst) _ASM_EXTABLE(10b, kvm_fastop_exception)
@@ -357,7 +363,8 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
 	FOP_END
 
 #define FOP2E(op,  dst, src)	   \
-	FOP_ALIGN #op " %" #src ", %" #dst " \n\t" FOP_RET
+	FOP_FUNC(#op "_" #dst "_" #src) \
+	#op " %" #src ", %" #dst " \n\t" FOP_RET
 
 #define FASTOP2(op) \
 	FOP_START(op) \
@@ -395,7 +402,8 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
 	FOP_END
 
 #define FOP3E(op,  dst, src, src2) \
-	FOP_ALIGN #op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET
+	FOP_FUNC(#op "_" #dst "_" #src "_" #src2) \
+	#op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET
 
 /* 3-operand, word-only, src2=cl */
 #define FASTOP3WCL(op) \
@@ -407,7 +415,12 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
 	FOP_END
 
 /* Special case for SETcc - 1 instruction per cc */
-#define FOP_SETCC(op) ".align 4; " #op " %al; ret \n\t"
+#define FOP_SETCC(op) \
+	".align 4 \n\t" \
+	".type " #op ", @function \n\t" \
+	#op ": \n\t" \
+	#op " %al \n\t" \
+	FOP_RET
 
 asm(".global kvm_fastop_exception \n"
     "kvm_fastop_exception: xor %esi, %esi; ret");
Signature · 1 line
2.4.3
maintainer Acked-by on v1 25/33
#76 lore raw

Re: [PATCH 25/33] x86/kvm: Set ELF function type for fastop functions

Quoted 80 lines · Josh Poimboeuf

The callable functions created with the FOP* and FASTOP* macros are missing ELF function annotations, which confuses tools like stacktool. Properly annotate them.

This adds some additional labels to the assembly, but the generated binary code is unchanged (with the exception of instructions which have embedded references to __LINE__).

---
 arch/x86/kvm/emulate.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)
arch/x86/kvm/emulate.c +15 -7
index 1505587..aa4d726 100644
@@ -309,23 +309,29 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)
 
 static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
 
-#define FOP_ALIGN ".align " __stringify(FASTOP_SIZE) " \n\t"
+#define FOP_FUNC(name) \
+	".align " __stringify(FASTOP_SIZE) " \n\t" \
+	".type " name ", @function \n\t" \
+	name ":\n\t"
+
 #define FOP_RET   "ret \n\t"
 
 #define FOP_START(op) \
 	extern void em_##op(struct fastop *fake); \
 	asm(".pushsection .text, \"ax\" \n\t" \
 	    ".global em_" #op " \n\t" \
-            FOP_ALIGN \
-	    "em_" #op ": \n\t"
+	    FOP_FUNC("em_" #op)
 
 #define FOP_END \
 	    ".popsection")
 
-#define FOPNOP() FOP_ALIGN FOP_RET
+#define FOPNOP() \
+	FOP_FUNC(__stringify(__UNIQUE_ID(nop))) \
+	FOP_RET
 
 #define FOP1E(op,  dst) \
-	FOP_ALIGN "10: " #op " %" #dst " \n\t" FOP_RET
+	FOP_FUNC(#op "_" #dst) \
+	"10: " #op " %" #dst " \n\t" FOP_RET
 
 #define FOP1EEX(op,  dst) \
 	FOP1E(op, dst) _ASM_EXTABLE(10b, kvm_fastop_exception)
@@ -357,7 +363,8 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
 	FOP_END
 
 #define FOP2E(op,  dst, src)	   \
-	FOP_ALIGN #op " %" #src ", %" #dst " \n\t" FOP_RET
+	FOP_FUNC(#op "_" #dst "_" #src) \
+	#op " %" #src ", %" #dst " \n\t" FOP_RET
 
 #define FASTOP2(op) \
 	FOP_START(op) \
@@ -395,7 +402,8 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
 	FOP_END
 
 #define FOP3E(op,  dst, src, src2) \
-	FOP_ALIGN #op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET
+	FOP_FUNC(#op "_" #dst "_" #src "_" #src2) \
+	#op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET
 
 /* 3-operand, word-only, src2=cl */
 #define FASTOP3WCL(op) \
@@ -407,7 +415,12 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
 	FOP_END
 
 /* Special case for SETcc - 1 instruction per cc */

arch/x86/kvm/emulate.c static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *)); · line 426

Quoted 10 lines
arch/x86/kvm/emulate.c +6 -1
-#define FOP_SETCC(op) ".align 4; " #op " %al; ret \n\t"
+#define FOP_SETCC(op) \
+	".align 4 \n\t" \
+	".type " #op ", @function \n\t" \
+	#op ": \n\t" \
+	#op " %al \n\t" \
+	FOP_RET
 
 asm(".global kvm_fastop_exception \n"
     "kvm_fastop_exception: xor %esi, %esi; ret");
#78 lore raw

[tip:x86/debug] x86/kvm: Set ELF function type for fastop functions

In reply to Josh Poimboeuf
x86/kvm: Set ELF function type for fastop functions
Commit-ID:  1482a0825bdf82dab4074bd3c824f4c87cbdf848
Gitweb:     http://git.kernel.org/tip/1482a0825bdf82dab4074bd3c824f4c87cbdf848
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:29 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:44 +0100

x86/kvm: Set ELF function type for fastop functions

The callable functions created with the FOP* and FASTOP* macros are missing ELF function annotations, which confuses tools like stacktool. Properly annotate them.

This adds some additional labels to the assembly, but the generated binary code is unchanged (with the exception of instructions which have embedded references to __LINE__).

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc Gleb Natapov <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/kvm/emulate.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)
arch/x86/kvm/emulate.c +21 -8
index 1505587..aa4d726 100644
@@ -309,23 +309,29 @@ static void invalidate_registers(struct x86_emulate_ctxt *ctxt)
 
 static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
 
-#define FOP_ALIGN ".align " __stringify(FASTOP_SIZE) " \n\t"
+#define FOP_FUNC(name) \
+	".align " __stringify(FASTOP_SIZE) " \n\t" \
+	".type " name ", @function \n\t" \
+	name ":\n\t"
+
 #define FOP_RET   "ret \n\t"
 
 #define FOP_START(op) \
 	extern void em_##op(struct fastop *fake); \
 	asm(".pushsection .text, \"ax\" \n\t" \
 	    ".global em_" #op " \n\t" \
-            FOP_ALIGN \
-	    "em_" #op ": \n\t"
+	    FOP_FUNC("em_" #op)
 
 #define FOP_END \
 	    ".popsection")
 
-#define FOPNOP() FOP_ALIGN FOP_RET
+#define FOPNOP() \
+	FOP_FUNC(__stringify(__UNIQUE_ID(nop))) \
+	FOP_RET
 
 #define FOP1E(op,  dst) \
-	FOP_ALIGN "10: " #op " %" #dst " \n\t" FOP_RET
+	FOP_FUNC(#op "_" #dst) \
+	"10: " #op " %" #dst " \n\t" FOP_RET
 
 #define FOP1EEX(op,  dst) \
 	FOP1E(op, dst) _ASM_EXTABLE(10b, kvm_fastop_exception)
@@ -357,7 +363,8 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
 	FOP_END
 
 #define FOP2E(op,  dst, src)	   \
-	FOP_ALIGN #op " %" #src ", %" #dst " \n\t" FOP_RET
+	FOP_FUNC(#op "_" #dst "_" #src) \
+	#op " %" #src ", %" #dst " \n\t" FOP_RET
 
 #define FASTOP2(op) \
 	FOP_START(op) \
@@ -395,7 +402,8 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
 	FOP_END
 
 #define FOP3E(op,  dst, src, src2) \
-	FOP_ALIGN #op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET
+	FOP_FUNC(#op "_" #dst "_" #src "_" #src2) \
+	#op " %" #src2 ", %" #src ", %" #dst " \n\t" FOP_RET
 
 /* 3-operand, word-only, src2=cl */
 #define FASTOP3WCL(op) \
@@ -407,7 +415,12 @@ static int fastop(struct x86_emulate_ctxt *ctxt, void (*fop)(struct fastop *));
 	FOP_END
 
 /* Special case for SETcc - 1 instruction per cc */
-#define FOP_SETCC(op) ".align 4; " #op " %al; ret \n\t"
+#define FOP_SETCC(op) \
+	".align 4 \n\t" \
+	".type " #op ", @function \n\t" \
+	#op ": \n\t" \
+	#op " %al \n\t" \
+	FOP_RET
 
 asm(".global kvm_fastop_exception \n"
     "kvm_fastop_exception: xor %esi, %esi; ret");
#79 lore raw

PATCH 26/33 x86/kvm: Add stack frame dependency to test_cc() inline asm

In reply to Josh Poimboeuf

With some configs, gcc doesn't inline test_cc(). When that happens, it doesn't create a stack frame before inserting the call instruction. This breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.

Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the inline asm statement.

---
 arch/x86/kvm/emulate.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
arch/x86/kvm/emulate.c +3 -1
index aa4d726..7dba65a 100644
@@ -972,11 +972,13 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt)
 static u8 test_cc(unsigned int condition, unsigned long flags)
 {
 	u8 rc;
+	register void *__sp asm(_ASM_SP);
 	void (*fop)(void) = (void *)em_setcc + 4 * (condition & 0xf);
 
 	flags = (flags & EFLAGS_MASK) | X86_EFLAGS_IF;
 	asm("push %[flags]; popf; call *%[fastop]"
-	    : "=a"(rc) : [fastop]"r"(fop), [flags]"r"(flags));
+	    : "=a"(rc), "+r"(__sp)
+	    : [fastop]"r"(fop), [flags]"r"(flags));
 	return rc;
 }
 
Signature · 1 line
2.4.3
maintainer
#80 lore raw

Re: [PATCH 26/33] x86/kvm: Add stack frame dependency to test_cc() inline asm

Quoted 8 lines · Josh Poimboeuf

With some configs, gcc doesn't inline test_cc(). When that happens, it doesn't create a stack frame before inserting the call instruction. This breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.

Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the inline asm statement.

If an __always_inline allocation works, that would be better.

Paolo

Quoted 28 lines
---
 arch/x86/kvm/emulate.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
arch/x86/kvm/emulate.c +3 -1
index aa4d726..7dba65a 100644
@@ -972,11 +972,13 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt)
 static u8 test_cc(unsigned int condition, unsigned long flags)
 {
 	u8 rc;
+	register void *__sp asm(_ASM_SP);
 	void (*fop)(void) = (void *)em_setcc + 4 * (condition & 0xf);
 
 	flags = (flags & EFLAGS_MASK) | X86_EFLAGS_IF;
 	asm("push %[flags]; popf; call *%[fastop]"
-	    : "=a"(rc) : [fastop]"r"(fop), [flags]"r"(flags));
+	    : "=a"(rc), "+r"(__sp)
+	    : [fastop]"r"(fop), [flags]"r"(flags));
 	return rc;
 }
 
#81 lore raw

Re: [PATCH 26/33] x86/kvm: Add stack frame dependency to test_cc() inline asm

Quoted 8 lines · Paolo Bonzini
Quoted 5 lines · Josh Poimboeuf

With some configs, gcc doesn't inline test_cc(). When that happens, it doesn't create a stack frame before inserting the call instruction. This breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.

Quoted 5 lines
Quoted 3 lines

Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the inline asm statement.

If an __always_inline allocation works, that would be better.

Yeah, that seems to work. I'll update the patch.

Signature · 1 line
Josh
#82 lore raw

PATCH 26/33 x86/kvm: Make test_cc() always inline

With some configs (including allyesconfig), gcc doesn't inline test_cc(). When that happens, test_cc() doesn't create a stack frame before inserting the inline asm call instruction. This breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.

Force it to always be inlined so that its containing function's stack frame can be used.

---
 arch/x86/kvm/emulate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/emulate.c +1 -1
index aa4d726..80363eb 100644
@@ -969,7 +969,7 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt)
 	return fastop(ctxt, em_bsr);
 }
 
-static u8 test_cc(unsigned int condition, unsigned long flags)
+static __always_inline u8 test_cc(unsigned int condition, unsigned long flags)
 {
 	u8 rc;
 	void (*fop)(void) = (void *)em_setcc + 4 * (condition & 0xf);
Signature · 1 line
2.4.3
#84 lore raw

[tip:x86/debug] x86/kvm: Make test_cc() always inline

In reply to Josh Poimboeuf
x86/kvm: Make test_cc() always inline
Commit-ID:  cb7390fed4c04e609a420ac0b1c07a7a781b43bf
Gitweb:     http://git.kernel.org/tip/cb7390fed4c04e609a420ac0b1c07a7a781b43bf
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Fri, 22 Jan 2016 10:16:12 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:44 +0100

x86/kvm: Make test_cc() always inline

With some configs (including allyesconfig), gcc doesn't inline test_cc(). When that happens, test_cc() doesn't create a stack frame before inserting the inline asm call instruction. This breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in a bad stack trace.

Force it to always be inlined so that its containing function's stack frame can be used.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc Gleb Natapov <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
---
 arch/x86/kvm/emulate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kvm/emulate.c +1 -1
index aa4d726..80363eb 100644
@@ -969,7 +969,7 @@ static int em_bsr_c(struct x86_emulate_ctxt *ctxt)
 	return fastop(ctxt, em_bsr);
 }
 
-static u8 test_cc(unsigned int condition, unsigned long flags)
+static __always_inline u8 test_cc(unsigned int condition, unsigned long flags)
 {
 	u8 rc;
 	void (*fop)(void) = (void *)em_setcc + 4 * (condition & 0xf);
#85 lore raw

PATCH 27/33 watchdog/hpwdt: Create stack frame in asminline_call()

In reply to Josh Poimboeuf

asminline_call() is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame when CONFIG_FRAME_POINTER is enabled.

---
 drivers/watchdog/hpwdt.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/watchdog/hpwdt.c +4 -4
index 286369d..f368383 100644
@@ -353,10 +353,10 @@ static int detect_cru_service(void)
 
 asm(".text                      \n\t"
     ".align 4                   \n\t"
-    ".globl asminline_call	\n"
+    ".globl asminline_call	\n\t"
+    ".type asminline_call, @function \n\t"
     "asminline_call:            \n\t"
-    "pushq      %rbp            \n\t"
-    "movq       %rsp, %rbp      \n\t"
+    FRAME_BEGIN
     "pushq      %rax            \n\t"
     "pushq      %rbx            \n\t"
     "pushq      %rdx            \n\t"
@@ -386,7 +386,7 @@ asm(".text                      \n\t"
     "popq       %rdx            \n\t"
     "popq       %rbx            \n\t"
     "popq       %rax            \n\t"
-    "leave                      \n\t"
+    FRAME_END
     "ret                        \n\t"
     ".previous");
 
Signature · 1 line
2.4.3
#87 lore raw

[tip:x86/debug] watchdog/hpwdt: Create stack frame in asminline_call()

In reply to Josh Poimboeuf
watchdog/hpwdt: Create stack frame in asminline_call()
Commit-ID:  5c1d5f283a855a5fe6b4f122054d85072b97ae4a
Gitweb:     http://git.kernel.org/tip/5c1d5f283a855a5fe6b4f122054d85072b97ae4a
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:31 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:44 +0100

watchdog/hpwdt: Create stack frame in asminline_call()

asminline_call() is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame when CONFIG_FRAME_POINTER is enabled.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc Guenter Roeck <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Wim Van Sebroeck <[email protected]>
---
 drivers/watchdog/hpwdt.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/watchdog/hpwdt.c +4 -4
index 92443c3..90016db 100644
@@ -353,10 +353,10 @@ static int detect_cru_service(void)
 
 asm(".text                      \n\t"
     ".align 4                   \n\t"
-    ".globl asminline_call	\n"
+    ".globl asminline_call	\n\t"
+    ".type asminline_call, @function \n\t"
     "asminline_call:            \n\t"
-    "pushq      %rbp            \n\t"
-    "movq       %rsp, %rbp      \n\t"
+    FRAME_BEGIN
     "pushq      %rax            \n\t"
     "pushq      %rbx            \n\t"
     "pushq      %rdx            \n\t"
@@ -386,7 +386,7 @@ asm(".text                      \n\t"
     "popq       %rdx            \n\t"
     "popq       %rbx            \n\t"
     "popq       %rax            \n\t"
-    "leave                      \n\t"
+    FRAME_END
     "ret                        \n\t"
     ".previous");
 
#88 lore raw

PATCH 28/33 x86/locking: Create stack frame in PV unlock

In reply to Josh Poimboeuf

The assembly PV_UNLOCK function is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame when CONFIG_FRAME_POINTER is enabled.

---
 arch/x86/include/asm/qspinlock_paravirt.h | 4 ++++
 1 file changed, 4 insertions(+)
arch/x86/include/asm/qspinlock_paravirt.h +4 -0
index 9f92c18..9d55f9b 100644
@@ -36,8 +36,10 @@ PV_CALLEE_SAVE_REGS_THUNK(__pv_queued_spin_unlock_slowpath);
  */
 asm    (".pushsection .text;"
 	".globl " PV_UNLOCK ";"
+	".type " PV_UNLOCK ", @function;"
 	".align 4,0x90;"
 	PV_UNLOCK ": "
+	FRAME_BEGIN
 	"push  %rdx;"
 	"mov   $0x1,%eax;"
 	"xor   %edx,%edx;"
@@ -45,6 +47,7 @@ asm    (".pushsection .text;"
 	"cmp   $0x1,%al;"
 	"jne   .slowpath;"
 	"pop   %rdx;"
+	FRAME_END
 	"ret;"
 	".slowpath: "
 	"push   %rsi;"
@@ -52,6 +55,7 @@ asm    (".pushsection .text;"
 	"call " PV_UNLOCK_SLOWPATH ";"
 	"pop    %rsi;"
 	"pop    %rdx;"
+	FRAME_END
 	"ret;"
 	".size " PV_UNLOCK ", .-" PV_UNLOCK ";"
 	".popsection");
Signature · 1 line
2.4.3
#90 lore raw

[tip:x86/debug] x86/locking: Create stack frame in PV unlock

In reply to Josh Poimboeuf
x86/locking: Create stack frame in PV unlock
Commit-ID:  16df4ff8604881db0130f93f4b6ade759fa48e87
Gitweb:     http://git.kernel.org/tip/16df4ff8604881db0130f93f4b6ade759fa48e87
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 21 Jan 2016 16:49:32 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:44 +0100

x86/locking: Create stack frame in PV unlock

The assembly PV_UNLOCK function is a callable non-leaf function which doesn't honor CONFIG_FRAME_POINTER, which can result in bad stack traces.

Create a stack frame when CONFIG_FRAME_POINTER is enabled.

Cc Andrew Morton <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Brian Gerst <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Denys Vlasenko <[email protected]>
Cc H. Peter Anvin <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Michal Marek <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Thomas Gleixner <[email protected]>
Cc Waiman Long <[email protected]>
---
 arch/x86/include/asm/qspinlock_paravirt.h | 4 ++++
 1 file changed, 4 insertions(+)
arch/x86/include/asm/qspinlock_paravirt.h +4 -0
index 9f92c18..9d55f9b 100644
@@ -36,8 +36,10 @@ PV_CALLEE_SAVE_REGS_THUNK(__pv_queued_spin_unlock_slowpath);
  */
 asm    (".pushsection .text;"
 	".globl " PV_UNLOCK ";"
+	".type " PV_UNLOCK ", @function;"
 	".align 4,0x90;"
 	PV_UNLOCK ": "
+	FRAME_BEGIN
 	"push  %rdx;"
 	"mov   $0x1,%eax;"
 	"xor   %edx,%edx;"
@@ -45,6 +47,7 @@ asm    (".pushsection .text;"
 	"cmp   $0x1,%al;"
 	"jne   .slowpath;"
 	"pop   %rdx;"
+	FRAME_END
 	"ret;"
 	".slowpath: "
 	"push   %rsi;"
@@ -52,6 +55,7 @@ asm    (".pushsection .text;"
 	"call " PV_UNLOCK_SLOWPATH ";"
 	"pop    %rsi;"
 	"pop    %rdx;"
+	FRAME_END
 	"ret;"
 	".size " PV_UNLOCK ", .-" PV_UNLOCK ";"
 	".popsection");
#91 lore raw

PATCH 29/33 x86/stacktool: Add directory and file whitelists

In reply to Josh Poimboeuf

Tell stacktool to skip validation of the following code which runs outside the kernel's normal mode of operation:

- boot image
- vdso image
- relocation
- realmode
- efi
- head

Also, skip the following code which does the right thing with respect to frame pointers, but is too "special" to be validated by a tool:

- entry
- mcount

Also skip the test_nx module because it modifies its exception handling table at runtime, which stacktool can't understand. Fortunately it's just a test module so it doesn't matter much.

---
 arch/x86/boot/Makefile                | 1 +
 arch/x86/boot/compressed/Makefile     | 3 ++-
 arch/x86/entry/Makefile               | 4 ++++
 arch/x86/entry/vdso/Makefile          | 5 ++++-
 arch/x86/kernel/Makefile              | 5 +++++
 arch/x86/platform/efi/Makefile        | 2 ++
 arch/x86/realmode/Makefile            | 4 +++-
 arch/x86/realmode/rm/Makefile         | 3 ++-
 drivers/firmware/efi/libstub/Makefile | 1 +
 9 files changed, 24 insertions(+), 4 deletions(-)
arch/x86/boot/Makefile +1 -0
index 2ee62db..df43778 100644
@@ -10,6 +10,7 @@
 #
 
 KASAN_SANITIZE := n
+STACKTOOL	:= n
 
 # If you want to preset the SVGA mode, uncomment the next line and
 # set SVGA_MODE to whatever number you want.
arch/x86/boot/compressed/Makefile +2 -1
index 0a291cd..8cea814 100644
@@ -16,7 +16,8 @@
 #	(see scripts/Makefile.lib size_append)
 #	compressed vmlinux.bin.all + u32 size of vmlinux.bin.all
 
-KASAN_SANITIZE := n
+KASAN_SANITIZE	:= n
+STACKTOOL	:= n
 
 targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma \
 	vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4
arch/x86/entry/Makefile +4 -0
index bd55ded..14a5b41 100644
@@ -1,6 +1,10 @@
 #
 # Makefile for the x86 low level entry code
 #
+
+STACKTOOL_entry_$(BITS).o   := n
+STACKTOOL_entry_64_compat.o := n
+
 obj-y				:= entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o
 obj-y				+= common.o
 
arch/x86/entry/vdso/Makefile +4 -1
index 265c0ed..510985f 100644
@@ -3,7 +3,9 @@
 #
 
 KBUILD_CFLAGS += $(DISABLE_LTO)
-KASAN_SANITIZE := n
+
+KASAN_SANITIZE	:= n
+STACKTOOL	:= n
 
 VDSO64-$(CONFIG_X86_64)		:= y
 VDSOX32-$(CONFIG_X86_X32_ABI)	:= y
@@ -15,6 +17,7 @@ vobjs-y := vdso-note.o vclock_gettime.o vgetcpu.o
 
 # files to link into kernel
 obj-y				+= vma.o
+STACKTOOL_vma.o			:= y
 
 # vDSO images to build
 vdso_img-$(VDSO64-y)		+= 64
arch/x86/kernel/Makefile +5 -0
index b1b78ff..fe410c4 100644
@@ -20,6 +20,11 @@ KASAN_SANITIZE_head$(BITS).o := n
 KASAN_SANITIZE_dumpstack.o := n
 KASAN_SANITIZE_dumpstack_$(BITS).o := n
 
+STACKTOOL_head_$(BITS).o		:= n
+STACKTOOL_relocate_kernel_$(BITS).o	:= n
+STACKTOOL_mcount_$(BITS).o		:= n
+STACKTOOL_test_nx.o			:= n
+
 CFLAGS_irq.o := -I$(src)/../include/asm/trace
 
 obj-y			:= process_$(BITS).o signal.o
arch/x86/platform/efi/Makefile +2 -0
index 2846aaa..8a347b2 100644
@@ -1,3 +1,5 @@
+STACKTOOL_efi_thunk_$(BITS).o := n
+
 obj-$(CONFIG_EFI) 		+= quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o
 obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
 obj-$(CONFIG_EARLY_PRINTK_EFI)	+= early_printk.o
arch/x86/realmode/Makefile +3 -1
index e02c2c6..0c24689 100644
@@ -6,7 +6,9 @@
 # for more details.
 #
 #
-KASAN_SANITIZE := n
+KASAN_SANITIZE	:= n
+STACKTOOL	:= n
+
 subdir- := rm
 
 obj-y += init.o
arch/x86/realmode/rm/Makefile +2 -1
index 2730d77..1da2e5b 100644
@@ -6,7 +6,8 @@
 # for more details.
 #
 #
-KASAN_SANITIZE := n
+KASAN_SANITIZE	:= n
+STACKTOOL	:= n
 
 always := realmode.bin realmode.relocs
 
drivers/firmware/efi/libstub/Makefile +1 -0
index 9c12e18..a73d2d74 100644
@@ -22,6 +22,7 @@ KBUILD_CFLAGS			:= $(cflags-y) -DDISABLE_BRANCH_PROFILING \
 
 GCOV_PROFILE			:= n
 KASAN_SANITIZE			:= n
+STACKTOOL			:= n
 
 lib-y				:= efi-stub-helper.o
 
Signature · 1 line
2.4.3
#92 lore raw

PATCH 30/33 x86/xen: Add xen_cpuid() to stacktool whitelist

In reply to Josh Poimboeuf

stacktool reports the following false positive warning:

stacktool: arch/x86/xen/enlighten.o: xen_cpuid()+0x41: can't find jump dest instruction at .text+0x108

The warning is due to xen_cpuid()'s use of XEN_EMULATE_PREFIX to insert some fake instructions which stacktool doesn't know how to decode.

Cc David Vrabel <[email protected]>
Cc Konrad Rzeszutek Wilk <[email protected]>
Cc Boris Ostrovsky <[email protected]>
---
 arch/x86/xen/enlighten.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
arch/x86/xen/enlighten.c +2 -1
index d09e4c9..7ba9520 100644
@@ -32,6 +32,7 @@
 #include <linux/gfp.h>
 #include <linux/memblock.h>
 #include <linux/edd.h>
+#include <linux/stacktool.h>
 
 #ifdef CONFIG_KEXEC_CORE
 #include <linux/kexec.h>
@@ -351,8 +352,8 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
 	*cx &= maskecx;
 	*cx |= setecx;
 	*dx &= maskedx;
-
 }
+STACKTOOL_IGNORE_FUNC(xen_cpuid);
 
 static bool __init xen_check_mwait(void)
 {
Signature · 1 line
2.4.3
#93 lore raw

PATCH 31/33 bpf: Add __bpf_prog_run() to stacktool whitelist

In reply to Josh Poimboeuf

stacktool reports the following false positive warnings:

stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x5c: sibling call from callable instruction with changed frame pointer
stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x60: function has unreachable instruction
stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x64: function has unreachable instruction
[...]

It's confused by the following dynamic jump instruction in __bpf_prog_run()::

jmp *(%r12,%rax,8)

which corresponds to the following line in the C code:

  goto *jumptable[insn->code];

There's no way for stacktool to deterministically find all possible branch targets for a dynamic jump, so it can't verify this code.

In this case the jumps all stay within the function, and there's nothing unusual going on related to the stack, so we can whitelist the function.

---
 kernel/bpf/core.c | 2 ++
 1 file changed, 2 insertions(+)
kernel/bpf/core.c +2 -0
index 972d9a8..7108a96 100644
@@ -27,6 +27,7 @@
 #include <linux/random.h>
 #include <linux/moduleloader.h>
 #include <linux/bpf.h>
+#include <linux/stacktool.h>
 
 #include <asm/unaligned.h>
 
@@ -649,6 +650,7 @@ load_byte:
 		WARN_RATELIMIT(1, "unknown opcode %02x\n", insn->code);
 		return 0;
 }
+STACKTOOL_IGNORE_FUNC(__bpf_prog_run);
 
 bool bpf_prog_array_compatible(struct bpf_array *array,
 			       const struct bpf_prog *fp)
Signature · 1 line
2.4.3
maintainer Acked-by on v1 31/33
#94 lore raw

Re: [PATCH 31/33] bpf: Add __bpf_prog_run() to stacktool whitelist

Quoted 19 lines · Josh Poimboeuf

stacktool reports the following false positive warnings:

stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x5c: sibling call from callable instruction with changed frame pointer
stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x60: function has unreachable instruction
stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x64: function has unreachable instruction
[...]

It's confused by the following dynamic jump instruction in __bpf_prog_run()::

   jmp     *(%r12,%rax,8)

which corresponds to the following line in the C code:

   goto *jumptable[insn->code];

There's no way for stacktool to deterministically find all possible branch targets for a dynamic jump, so it can't verify this code.

Quoted 6 lines

In this case the jumps all stay within the function, and there's nothing unusual going on related to the stack, so we can whitelist the function.

Fine by me:

#95 lore raw

Re: [PATCH 31/33] bpf: Add __bpf_prog_run() to stacktool whitelist

In reply to Josh Poimboeuf
Quoted 14 lines · Josh Poimboeuf

stacktool reports the following false positive warnings:

stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x5c: sibling call from callable instruction with changed frame pointer
stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x60: function has unreachable instruction
stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x64: function has unreachable instruction
[...]

It's confused by the following dynamic jump instruction in __bpf_prog_run()::

jmp *(%r12,%rax,8)

which corresponds to the following line in the C code:

Quoted 7 lines
  goto *jumptable[insn->code];

There's no way for stacktool to deterministically find all possible branch targets for a dynamic jump, so it can't verify this code.

In this case the jumps all stay within the function, and there's nothing unusual going on related to the stack, so we can whitelist the function.

well, few things are very unusual in this function.
did you see what JMP_CALL does? it's a call into a different function, but not like typical indirect call. Will it be ok as well?

In general it's not possible for any tool to identify all possible branch targets. bpf programs can be loaded on the fly and jumping sequence will change.
So if this marking says 'don't bother analyzing this function because it does sane stuff' that's probably not the case.
If this marking says 'don't bother analyzing, the stack may be crazy from here on' then it's ok.

#96 lore raw

Re: [PATCH 31/33] bpf: Add __bpf_prog_run() to stacktool whitelist

Quoted 27 lines · Alexei Starovoitov
Quoted 14 lines · Josh Poimboeuf

stacktool reports the following false positive warnings:

stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x5c: sibling call from callable instruction with changed frame pointer
stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x60: function has unreachable instruction
stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x64: function has unreachable instruction
[...]

It's confused by the following dynamic jump instruction in __bpf_prog_run()::

jmp *(%r12,%rax,8)

which corresponds to the following line in the C code:

Quoted 7 lines
  goto *jumptable[insn->code];

There's no way for stacktool to deterministically find all possible branch targets for a dynamic jump, so it can't verify this code.

In this case the jumps all stay within the function, and there's nothing unusual going on related to the stack, so we can whitelist the function.

well, few things are very unusual in this function.
did you see what JMP_CALL does? it's a call into a different function, but not like typical indirect call. Will it be ok as well?

Quoted 7 lines

In general it's not possible for any tool to identify all possible branch targets. bpf programs can be loaded on the fly and jumping sequence will change.
So if this marking says 'don't bother analyzing this function because it does sane stuff' that's probably not the case.
If this marking says 'don't bother analyzing, the stack may be crazy from here on' then it's ok.

So the tool doesn't need to follow all possible call targets. Instead it just verifies that all functions follow the frame pointer convention. That way it doesn't matter *which* function is being called because they all do the right thing.

But it *does* need to follow all jump targets, so that it can analyze all possible code paths within the function itself. With a dynamic jump, it can't do that.

So the JMP_CALL is fine, but the goto *jumptable[insn->code] isn't. (And BTW that's the only occurrence of such a dynamic jump table in the entire kernel.)

Signature · 1 line
Josh
#97 lore raw

Re: [PATCH 31/33] bpf: Add __bpf_prog_run() to stacktool whitelist

Quoted 41 lines · Josh Poimboeuf
Quoted 27 lines · Alexei Starovoitov
Quoted 14 lines · Josh Poimboeuf

stacktool reports the following false positive warnings:

stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x5c: sibling call from callable instruction with changed frame pointer
stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x60: function has unreachable instruction
stacktool: kernel/bpf/core.o: __bpf_prog_run()+0x64: function has unreachable instruction
[...]

It's confused by the following dynamic jump instruction in __bpf_prog_run()::

jmp *(%r12,%rax,8)

which corresponds to the following line in the C code:

Quoted 7 lines
  goto *jumptable[insn->code];

There's no way for stacktool to deterministically find all possible branch targets for a dynamic jump, so it can't verify this code.

In this case the jumps all stay within the function, and there's nothing unusual going on related to the stack, so we can whitelist the function.

well, few things are very unusual in this function.
did you see what JMP_CALL does? it's a call into a different function, but not like typical indirect call. Will it be ok as well?

Quoted 7 lines

In general it's not possible for any tool to identify all possible branch targets. bpf programs can be loaded on the fly and jumping sequence will change.
So if this marking says 'don't bother analyzing this function because it does sane stuff' that's probably not the case.
If this marking says 'don't bother analyzing, the stack may be crazy from here on' then it's ok.

So the tool doesn't need to follow all possible call targets. Instead it just verifies that all functions follow the frame pointer convention. That way it doesn't matter *which* function is being called because they all do the right thing.

Quoted 7 lines

But it *does* need to follow all jump targets, so that it can analyze all possible code paths within the function itself. With a dynamic jump, it can't do that.

So the JMP_CALL is fine, but the goto *jumptable[insn->code] isn't. (And BTW that's the only occurrence of such a dynamic jump table in the entire kernel.)

#98 lore raw

PATCH 32/33 sched: Add __schedule() to stacktool whitelist

In reply to Josh Poimboeuf

stacktool reports the following warnings for __schedule():

stacktool: kernel/sched/core.o: __schedule()+0x3c0: duplicate frame pointer save
stacktool: kernel/sched/core.o: __schedule()+0x3fd: sibling call from callable instruction with changed frame pointer
stacktool: kernel/sched/core.o: __schedule()+0x40a: call without frame pointer save/setup
stacktool: kernel/sched/core.o: __schedule()+0x7fd: frame pointer state mismatch
stacktool: kernel/sched/core.o: __schedule()+0x421: frame pointer state mismatch

Basically it's confused by two unusual attributes of the switch_to() macro:

1. It saves prev's frame pointer to the old stack and restores next's frame pointer from the new stack.

2. For new tasks it jumps directly to ret_from_fork.

Eventually it would probably be a good idea to clean up the ret_from_fork hack so that new tasks are created with a valid initial stack, as suggested by Andy:

https://lkml.kernel.org/r/CALCETrWsqCw4L1qKO9j9L5F+4ED4viuLQTFc=n1pKBZfFPQUFg@mail.gmail.com

Then __schedule() could return normally into the new code and stacktool hopefully wouldn't have a problem anymore.

In the meantime, add it to the stacktool whitelist so we can have a baseline with no stacktool warnings. The marker also serves as a reminder that this code could be improved a bit.

---
 kernel/sched/core.c | 2 ++
 1 file changed, 2 insertions(+)
kernel/sched/core.c +2 -0
index 474658b..cc7e8e70 100644
@@ -74,6 +74,7 @@
 #include <linux/binfmts.h>
 #include <linux/context_tracking.h>
 #include <linux/compiler.h>
+#include <linux/stacktool.h>
 
 #include <asm/switch_to.h>
 #include <asm/tlb.h>
@@ -3288,6 +3289,7 @@ static void __sched notrace __schedule(bool preempt)
 
 	balance_callback(rq);
 }
+STACKTOOL_IGNORE_FUNC(__schedule);
 
 static inline void sched_submit_work(struct task_struct *tsk)
 {
Signature · 1 line
2.4.3
#99 lore raw

PATCH 33/33 x86/kprobes: Add kretprobe_trampoline() to stacktool whitelist

In reply to Josh Poimboeuf

stacktool reports the following warning for kretprobe_trampoline():

stacktool: arch/x86/kernel/kprobes/core.o: kretprobe_trampoline()+0x20: call without frame pointer save/setup

kretprobes are a special case where the stack is intentionally wrong. The return address isn't known at the beginning of the trampoline, so the stack frame can't be set up properly before it calls trampoline_handler().

Because kretprobe handlers don't sleep, the frame pointer doesn't *have* to be accurate in the trampoline. So it's ok to add the trampoline to the stacktool whitelist. This results in no actual changes to the generated code.

Cc Ananth N Mavinakayanahalli <[email protected]>
Cc Anil S Keshavamurthy <[email protected]>
Cc "David S. Miller" <[email protected]>
Cc Masami Hiramatsu <[email protected]>
---
 arch/x86/kernel/kprobes/core.c | 2 ++
 1 file changed, 2 insertions(+)
arch/x86/kernel/kprobes/core.c +2 -0
index 5b187df..2b29272 100644
@@ -49,6 +49,7 @@
 #include <linux/kdebug.h>
 #include <linux/kallsyms.h>
 #include <linux/ftrace.h>
+#include <linux/stacktool.h>
 
 #include <asm/cacheflush.h>
 #include <asm/desc.h>
@@ -703,6 +704,7 @@ asm(
 	".size kretprobe_trampoline, .-kretprobe_trampoline\n"
 );
 NOKPROBE_SYMBOL(kretprobe_trampoline);
+STACKTOOL_IGNORE_FUNC(kretprobe_trampoline);
 
 /*
  * Called from kretprobe_trampoline
Signature · 1 line
2.4.3
#100 lore raw
In reply to Josh Poimboeuf
Quoted 4 lines · Josh Poimboeuf

This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.

Josh,

Looks good, with my config [1] I do still get a few warnings building linux/linux-next.

Here are the warnings:

$ grep ^stacktool build.log | grep -v staging
stacktool: arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setup
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: return without frame pointer restore
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x89: duplicate frame pointer save
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x8a: duplicate frame pointer setup
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: frame pointer state mismatch
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x0: frame pointer state mismatch
stacktool: fs/reiserfs/ibalance.o: .text: unexpected end of section
stacktool: fs/reiserfs/tail_conversion.o: .text: unexpected end of section

For vmx_handle_external_intr, I'm wondering if ignoring this function is the best option.

--

arch/x86/kvm/vmx.c +2 -0
index e2951b6..d19dfb2 100644
@@ -33,6 +33,7 @@
 #include <linux/slab.h>
 #include <linux/tboot.h>
 #include <linux/hrtimer.h>
+#include <linux/stacktool.h>
 #include "kvm_cache_regs.h"
 #include "x86.h"
 
@@ -8398,6 +8399,7 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
        } else
                local_irq_enable();
 }
+STACKTOOL_IGNORE_FUNC(vmx_handle_external_intr);
 
 static bool vmx_has_high_real_mode_segbase(void)
 {

--chris

[1] http://paste.ubuntu.com/14599083/

Quoted 297 lines

v15 can be found here:

https://lkml.kernel.org/r/[email protected]

For more information about the motivation behind this patch set, and more details about what it does, see the first patch changelog and tools/stacktool/Documentation/stack-validation.txt.

Patches 1-4 add stacktool and integrate it into the kernel build.

Patches 5-28 are some proposed fixes for several of the warnings reported by stacktool. They've been compile-tested and boot-tested in a VM, but I haven't attempted any meaningful testing for many of them.

Patches 29-33 add some directories, files, and functions to the stacktool whitelist in order to silence false positive warnings.

v16:
- fix all allyesconfig warnings, except for staging
- get rid of STACKTOOL_IGNORE_INSN which is no longer needed
- remove several whitelists in favor of automatically whitelisting any function with a special instruction like ljmp, lret, or vmrun
- split up stacktool patch into 3 parts as suggested by Ingo
- update the global noreturn function list
- detect noreturn function fallthroughs
- skip weak functions in noreturn call detection logic
- add empty function check to noreturn logic
- allow non-section rela symbols for __ex_table sections
- support rare switch table case with jmpq *[addr](%rip)
- don't warn on frame pointer restore without save
- rearrange patch order a bit

v15:
- restructure code for a new cmdline interface "stacktool check" using the new subcommand framework in tools/lib/subcmd
- fix 32 bit build fail (put __sp at end) in paravirt_types.h patch 10 which was reported by 0day

v14:
- make tools/include/linux/list.h self-sufficient
- create FRAME_OFFSET to allow 32-bit code to be able to access function arguments on the stack
- add FRAME_OFFSET usage in crypto patch 14/24: "Create stack frames in aesni-intel_asm.S"
- rename "index" -> "idx" to fix build with some compilers

v13:
- LDFLAGS order fix from Chris J Arges
- new warning fix patches from Chris J Arges
- "--frame-pointer" -> "--check-frame-pointer"

v12:
- rename "stackvalidate" -> "stacktool"
- move from scripts/ to tools/:
- makefile rework
- make a copy of the x86 insn code (and warn if the code diverges)
- use tools/include/linux/list.h
- move warning macros to a new warn.h file
- change wording: "stack validation" -> "stack metadata validation"

v11:
- attempt to answer the "why" question better in the documentation and commit message
- s/FP_SAVE/FRAME_BEGIN/ in documentation

v10:
- add scripts/mod to directory ignores
- remove circular dependencies for ignored objects which are built before stackvalidate
- fix CONFIG_MODVERSIONS incompatibility

v9:
- rename FRAME/ENDFRAME -> FRAME_BEGIN/FRAME_END
- fix jump table issue for when the original instruction is a jump
- drop paravirt thunk alignment patch
- add maintainers to CC for proposed warning fixes

v8:
- add proposed fixes for warnings
- fix all memory leaks
- process ignores earlier and add more ignore checks
- always assume POPCNT alternative is enabled
- drop hweight inline asm fix
- drop __schedule() ignore patch
- change .Ltemp_\@ to .Lstackvalidate_ignore_\@ in asm macro
- fix CONFIG_* checks in asm macros
- add C versions of ignore macros and frame macros
- change ";" to "\n" in C macros
- add ifdef CONFIG_STACK_VALIDATION checks in C ignore macros
- use numbered label in C ignore macro
- add missing break in switch case statement in arch-x86.c

v7:
- sibling call support
- document proposed solution for inline asm() frame pointer issues
- say "kernel entry/exit" instead of "context switch"
- clarify the checking of switch statement jump tables
- discard __stackvalidate_ignore_* sections in linker script
- use .Ltemp_\@ to get a unique label instead of static 3-digit number
- change STACKVALIDATE_IGNORE_FUNC variable to a static
- move STACKVALIDATE_IGNORE_INSN to arch-specific .h file

v6:
- rename asmvalidate -> stackvalidate (again)
- gcc-generated object file support
- recursive branch state analysis
- external jump support
- fixup/exception table support
- jump label support
- switch statement jump table support
- added documentation
- detection of "noreturn" dead end functions
- added a Kbuild mechanism for skipping files and dirs
- moved frame pointer macros to arch/x86/include/asm/frame.h
- moved ignore macros to include/linux/stackvalidate.h

v5:
- stackvalidate -> asmvalidate
- frame pointers only required for non-leaf functions
- check for the use of the FP_SAVE/RESTORE macros instead of manually analyzing code to detect frame pointer usage
- additional checks to ensure each function doesn't leave its boundaries
- make the macros simpler and more flexible
- support for analyzing ALTERNATIVE macros
- simplified the arch interfaces in scripts/asmvalidate/arch.h
- fixed some asmvalidate warnings
- rebased onto latest tip asm cleanups
- many more small changes

v4:
- Changed the default to CONFIG_STACK_VALIDATION=n, until all the asm code can get cleaned up.
- Fixed a stackvalidate error path exit code issue found by Michal Marek.

v3:
- Added a patch to make the push/pop CFI macros arch-independent, as suggested by H. Peter Anvin

v2:
- Fixed memory leaks reported by Petr Mladek

Cc Michal Marek <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Andy Lutomirski <[email protected]>
Cc Borislav Petkov <[email protected]>
Cc Linus Torvalds <[email protected]>
Cc Andi Kleen <[email protected]>
Cc Pedro Alves <[email protected]>
Cc Namhyung Kim <[email protected]>
Cc Bernd Petrovitsch <[email protected]>
Cc Chris J Arges <[email protected]>
Cc Andrew Morton <[email protected]>
Cc Jiri Slaby <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>

Chris J Arges (1):
x86/uaccess: Add stack frame output operand in get_user inline asm

Josh Poimboeuf (32):
x86/stacktool: Compile-time stack metadata validation kbuild/stacktool: Add CONFIG_STACK_VALIDATION option x86/stacktool: Enable stacktool on x86_64
x86/stacktool: Add STACKTOOL_IGNORE_FUNC macro
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: Add stack frame dependency to test_cc() inline asm watchdog/hpwdt: Create stack frame in asminline_call() x86/locking: Create stack frame in PV unlock x86/stacktool: Add directory and file whitelists x86/xen: Add xen_cpuid() to stacktool whitelist
bpf: Add __bpf_prog_run() to stacktool whitelist
sched: Add __schedule() to stacktool whitelist x86/kprobes: Add kretprobe_trampoline() to stacktool whitelist

 MAINTAINERS                                        |   6 +
 Makefile                                           |   5 +-
 arch/Kconfig                                       |   6 +
 arch/x86/Kconfig                                   |   1 +
 arch/x86/boot/Makefile                             |   1 +
 arch/x86/boot/compressed/Makefile                  |   3 +-
 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/crc32c-pcl-intel-asm_64.S          |   8 +-
 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/thunk_64.S                          |   4 +
 arch/x86/entry/vdso/Makefile                       |   5 +-
 arch/x86/include/asm/paravirt.h                    |   9 +-
 arch/x86/include/asm/paravirt_types.h              |  18 +-
 arch/x86/include/asm/qspinlock_paravirt.h          |   4 +
 arch/x86/include/asm/uaccess.h                     |   5 +-
 arch/x86/include/asm/xen/hypercall.h               |   5 +-
 arch/x86/kernel/Makefile                           |   5 +
 arch/x86/kernel/acpi/wakeup_64.S                   |   3 +
 arch/x86/kernel/cpu/amd.c                          |   5 +-
 arch/x86/kernel/kprobes/core.c                     |  59 +-
 arch/x86/kernel/vmlinux.lds.S                      |   5 +-
 arch/x86/kvm/emulate.c                             |  33 +-
 arch/x86/lib/rwsem.S                               |  11 +-
 arch/x86/net/bpf_jit.S                             |  48 +-
 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/xen/enlighten.c                           |   3 +-
 arch/x86/xen/xen-asm.S                             |  10 +-
 arch/x86/xen/xen-asm_64.S                          |   1 +
 drivers/firmware/efi/libstub/Makefile              |   1 +
 drivers/watchdog/hpwdt.c                           |   8 +-
 include/linux/stacktool.h                          |  23 +
 kernel/bpf/core.c                                  |   2 +
 kernel/sched/core.c                                |   2 +
 lib/Kconfig.debug                                  |  12 +
 scripts/Makefile.build                             |  38 +-
 scripts/mod/Makefile                               |   2 +
 tools/Makefile                                     |  14 +-
 tools/stacktool/.gitignore                         |   2 +
 tools/stacktool/Build                              |  13 +
 tools/stacktool/Documentation/stack-validation.txt | 333 +++++++
 tools/stacktool/Makefile                           |  60 ++
 tools/stacktool/arch.h                             |  44 +
 tools/stacktool/arch/x86/Build                     |  12 +
 tools/stacktool/arch/x86/decode.c                  | 172 ++++
 .../stacktool/arch/x86/insn/gen-insn-attr-x86.awk  | 387 ++++++++
 tools/stacktool/arch/x86/insn/inat.c               |  97 ++
 tools/stacktool/arch/x86/insn/inat.h               | 221 +++++
 tools/stacktool/arch/x86/insn/inat_types.h         |  29 +
 tools/stacktool/arch/x86/insn/insn.c               | 594 ++++++++++++
 tools/stacktool/arch/x86/insn/insn.h               | 201 +++++
 tools/stacktool/arch/x86/insn/x86-opcode-map.txt   | 984 ++++++++++++++++++++
 tools/stacktool/builtin-check.c                    | 991 +++++++++++++++++++++
 tools/stacktool/builtin.h                          |  22 +
 tools/stacktool/elf.c                              | 403 +++++++++
 tools/stacktool/elf.h                              |  79 ++
 tools/stacktool/special.c                          | 193 ++++
 tools/stacktool/special.h                          |  42 +
 tools/stacktool/stacktool.c                        | 134 +++
 tools/stacktool/warn.h                             |  60 ++
 74 files changed, 5516 insertions(+), 189 deletions(-)
 create mode 100644 include/linux/stacktool.h
 create mode 100644 tools/stacktool/.gitignore
 create mode 100644 tools/stacktool/Build
 create mode 100644 tools/stacktool/Documentation/stack-validation.txt
 create mode 100644 tools/stacktool/Makefile
 create mode 100644 tools/stacktool/arch.h
 create mode 100644 tools/stacktool/arch/x86/Build
 create mode 100644 tools/stacktool/arch/x86/decode.c
 create mode 100644 tools/stacktool/arch/x86/insn/gen-insn-attr-x86.awk
 create mode 100644 tools/stacktool/arch/x86/insn/inat.c
 create mode 100644 tools/stacktool/arch/x86/insn/inat.h
 create mode 100644 tools/stacktool/arch/x86/insn/inat_types.h
 create mode 100644 tools/stacktool/arch/x86/insn/insn.c
 create mode 100644 tools/stacktool/arch/x86/insn/insn.h
 create mode 100644 tools/stacktool/arch/x86/insn/x86-opcode-map.txt
 create mode 100644 tools/stacktool/builtin-check.c
 create mode 100644 tools/stacktool/builtin.h
 create mode 100644 tools/stacktool/elf.c
 create mode 100644 tools/stacktool/elf.h
 create mode 100644 tools/stacktool/special.c
 create mode 100644 tools/stacktool/special.h
 create mode 100644 tools/stacktool/stacktool.c
 create mode 100644 tools/stacktool/warn.h
Signature · 1 line
2.4.3
#101 lore raw
Quoted 5 lines · Chris J Arges
Quoted 4 lines · Josh Poimboeuf

This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.

Quoted 7 lines

Josh,

Looks good, with my config [1] I do still get a few warnings building linux/linux-next.

Here are the warnings:

$ grep ^stacktool build.log | grep -v staging

Thanks for reporting these!

Quoted 1 line

stacktool: arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setup

This can be fixed by setting the stack pointer as an output operand for the inline asm call in vmx_handle_external_intr().

Feel free to submit a patch, or I'll get around to it eventually.

Quoted 5 lines

stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: return without frame pointer restore
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x89: duplicate frame pointer save
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x8a: duplicate frame pointer setup
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: frame pointer state mismatch
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x0: frame pointer state mismatch

These are false positives. Stacktool is confused by the use of a "noreturn" function which it doesn't know about (__reiserfs_panic).

Unfortunately the only solution I currently have for dealing with global noreturn functions is to just hard-code a list of them. So the short term fix would be to add "__reiserfs_panic" to the global_noreturns list in tools/stacktool/builtin-check.c.

I'm still trying to figure out a better way to deal with this type of issue, as it's a pain to have to keep a hard-coded list of noreturn functions. Unfortunately that info isn't available in the ELF.

Quoted 2 lines

stacktool: fs/reiserfs/ibalance.o: .text: unexpected end of section
stacktool: fs/reiserfs/tail_conversion.o: .text: unexpected end of section

For some reason I'm not able to recreate these warnings... Can you share one of the .o files?

Signature · 5 lines
Josh
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#102 lore raw
Quoted 32 lines · Josh Poimboeuf
Quoted 5 lines · Chris J Arges
Quoted 4 lines · Josh Poimboeuf

This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.

Quoted 7 lines

Josh,

Looks good, with my config [1] I do still get a few warnings building linux/linux-next.

Here are the warnings:

$ grep ^stacktool build.log | grep -v staging

Thanks for reporting these!

Quoted 1 line

stacktool: arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setup

This can be fixed by setting the stack pointer as an output operand for the inline asm call in vmx_handle_external_intr().

Feel free to submit a patch, or I'll get around to it eventually.

Quoted 5 lines

stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: return without frame pointer restore
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x89: duplicate frame pointer save
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x8a: duplicate frame pointer setup
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: frame pointer state mismatch
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x0: frame pointer state mismatch

These are false positives. Stacktool is confused by the use of a "noreturn" function which it doesn't know about (__reiserfs_panic).

Quoted 9 lines

Unfortunately the only solution I currently have for dealing with global noreturn functions is to just hard-code a list of them. So the short term fix would be to add "__reiserfs_panic" to the global_noreturns list in tools/stacktool/builtin-check.c.

I'm still trying to figure out a better way to deal with this type of issue, as it's a pain to have to keep a hard-coded list of noreturn functions. Unfortunately that info isn't available in the ELF.

Josh,
Ok I'll hack on the patches above.

Quoted 9 lines
Quoted 2 lines

stacktool: fs/reiserfs/ibalance.o: .text: unexpected end of section
stacktool: fs/reiserfs/tail_conversion.o: .text: unexpected end of section

For some reason I'm not able to recreate these warnings... Can you share one of the .o files?

Signature · 1 line
Josh

Binaries are here:
http://people.canonical.com/~arges/stacktool/

--chris
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#103 lore raw
Quoted 46 lines · Chris J Arges
Quoted 32 lines · Josh Poimboeuf
Quoted 5 lines · Chris J Arges
Quoted 4 lines · Josh Poimboeuf

This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.

Quoted 7 lines

Josh,

Looks good, with my config [1] I do still get a few warnings building linux/linux-next.

Here are the warnings:

$ grep ^stacktool build.log | grep -v staging

Thanks for reporting these!

Quoted 1 line

stacktool: arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setup

This can be fixed by setting the stack pointer as an output operand for the inline asm call in vmx_handle_external_intr().

Feel free to submit a patch, or I'll get around to it eventually.

Quoted 5 lines

stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: return without frame pointer restore
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x89: duplicate frame pointer save
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x8a: duplicate frame pointer setup
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: frame pointer state mismatch
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x0: frame pointer state mismatch

These are false positives. Stacktool is confused by the use of a "noreturn" function which it doesn't know about (__reiserfs_panic).

Quoted 9 lines

Unfortunately the only solution I currently have for dealing with global noreturn functions is to just hard-code a list of them. So the short term fix would be to add "__reiserfs_panic" to the global_noreturns list in tools/stacktool/builtin-check.c.

I'm still trying to figure out a better way to deal with this type of issue, as it's a pain to have to keep a hard-coded list of noreturn functions. Unfortunately that info isn't available in the ELF.

Josh,
Ok I'll hack on the patches above.

Quoted 8 lines
Quoted 5 lines
Quoted 2 lines

stacktool: fs/reiserfs/ibalance.o: .text: unexpected end of section
stacktool: fs/reiserfs/tail_conversion.o: .text: unexpected end of section

For some reason I'm not able to recreate these warnings... Can you share one of the .o files?

Binaries are here:
http://people.canonical.com/~arges/stacktool/

Thanks, looks like the same __reiserfs_panic() noreturn fix for those.

Signature · 5 lines
Josh
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#104 lore raw

cover A few stacktool warning fixes.

These patches fix a few warnings I saw testing stacktool v16. I've done light testing on these by booting it on a machine and running kvm-unit-tests on it.

Chris J Arges (2):
tools/stacktool: Add __reiserfs_panic to global_noreturns list x86/kvm: Add output operand in vmx_handle_external_intr inline asm

 arch/x86/kvm/vmx.c              | 4 +++-
 tools/stacktool/builtin-check.c | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)
Signature · 1 line
2.5.0
#105 lore raw

PATCH 1/2 tools/stacktool: Add __reiserfs_panic to global_noreturns list

The following false positives were noticed with stacktool:
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: return without frame pointer restore
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x89: duplicate frame pointer save
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x8a: duplicate frame pointer setup
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: frame pointer state mismatch
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x0: frame pointer state mismatch

These all call into '__reiserfs_panic' which has a noreturn attribute. Add this to the global list because this particular attribute cannot be determined from reading the ELF object.

---
 tools/stacktool/builtin-check.c | 1 +
 1 file changed, 1 insertion(+)
tools/stacktool/builtin-check.c +1 -0
index 5b0e91f..23fa93d2 100644
@@ -139,6 +139,7 @@ static bool dead_end_function(struct stacktool_file *file, struct symbol *func)
 		"__module_put_and_exit",
 		"complete_and_exit",
 		"kvm_spurious_fault",
+		"__reiserfs_panic",
 	};
 
 	if (func->bind == STB_WEAK)
Signature · 1 line
2.5.0
author Acked-by on v1 1/2
#106 lore raw

Re: [PATCH 1/2] tools/stacktool: Add __reiserfs_panic to global_noreturns list

Quoted 7 lines · Chris J Arges

The following false positives were noticed with stacktool:
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: return without frame pointer restore
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x89: duplicate frame pointer save
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x8a: duplicate frame pointer setup
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x9e: frame pointer state mismatch
stacktool: fs/reiserfs/namei.o: set_de_name_and_namelen()+0x0: frame pointer state mismatch

Quoted 5 lines

These all call into '__reiserfs_panic' which has a noreturn attribute. Add this to the global list because this particular attribute cannot be determined from reading the ELF object.

Quoted 19 lines
---
 tools/stacktool/builtin-check.c | 1 +
 1 file changed, 1 insertion(+)
tools/stacktool/builtin-check.c +1 -0
index 5b0e91f..23fa93d2 100644
@@ -139,6 +139,7 @@ static bool dead_end_function(struct stacktool_file *file, struct symbol *func)
 		"__module_put_and_exit",
 		"complete_and_exit",
 		"kvm_spurious_fault",
+		"__reiserfs_panic",
 	};
 
 	if (func->bind == STB_WEAK)
Signature · 1 line
2.5.0
Signature · 1 line
Josh
#107 lore raw

PATCH 2/2 x86/kvm: Add output operand in vmx_handle_external_intr inline asm

In reply to Chris J Arges

Stacktool generates the following warning:
stacktool: arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setup

By adding the stackpointer as an output operand, this patch ensures that a stack frame is created when CONFIG_FRAME_POINTER is enabled for the inline assmebly statement.

---
 arch/x86/kvm/vmx.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
arch/x86/kvm/vmx.c +3 -1
index e2951b6..e153522 100644
@@ -8356,6 +8356,7 @@ static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)
 static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
 {
 	u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+	register void *__sp asm(_ASM_SP);
 
 	/*
 	 * If external interrupt exists, IF bit is set in rflags/eflags on the
@@ -8388,8 +8389,9 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
 			"call *%[entry]\n\t"
 			:
 #ifdef CONFIG_X86_64
-			[sp]"=&r"(tmp)
+			[sp]"=&r"(tmp),
 #endif
+			"+r"(__sp)
 			:
 			[entry]"r"(entry),
 			[ss]"i"(__KERNEL_DS),
Signature · 1 line
2.5.0
author Reviewed-by on v1 2/2
#108 lore raw

Re: [PATCH 2/2] x86/kvm: Add output operand in vmx_handle_external_intr inline asm

Quoted 8 lines · Chris J Arges

Stacktool generates the following warning:
stacktool: arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setup

By adding the stackpointer as an output operand, this patch ensures that a stack frame is created when CONFIG_FRAME_POINTER is enabled for the inline assmebly statement.

Quoted 30 lines
---
 arch/x86/kvm/vmx.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
arch/x86/kvm/vmx.c +3 -1
index e2951b6..e153522 100644
@@ -8356,6 +8356,7 @@ static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)
 static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
 {
 	u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+	register void *__sp asm(_ASM_SP);
 
 	/*
 	 * If external interrupt exists, IF bit is set in rflags/eflags on the
@@ -8388,8 +8389,9 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
 			"call *%[entry]\n\t"
 			:
 #ifdef CONFIG_X86_64
-			[sp]"=&r"(tmp)
+			[sp]"=&r"(tmp),
 #endif
+			"+r"(__sp)
 			:
 			[entry]"r"(entry),
 			[ss]"i"(__KERNEL_DS),
Signature · 1 line
2.5.0
#110 lore raw

[tip:x86/debug] x86/kvm: Add output operand in vmx_handle_external_intr inline asm

In reply to Chris J Arges
x86/kvm: Add output operand in vmx_handle_external_intr inline asm
Commit-ID:  3f62de5f6f369b67b7ac709e3c942c9130d2c51a
Gitweb:     http://git.kernel.org/tip/3f62de5f6f369b67b7ac709e3c942c9130d2c51a
Author:     Chris J Arges <[email protected]>
AuthorDate: Fri, 22 Jan 2016 15:44:38 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:44 +0100

x86/kvm: Add output operand in vmx_handle_external_intr inline asm

Stacktool generates the following warning:
stacktool: arch/x86/kvm/vmx.o: vmx_handle_external_intr()+0x67: call without frame pointer save/setup

By adding the stackpointer as an output operand, this patch ensures that a stack frame is created when CONFIG_FRAME_POINTER is enabled for the inline assmebly statement.

---
 arch/x86/kvm/vmx.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
arch/x86/kvm/vmx.c +3 -1
index e2951b6..e153522 100644
@@ -8356,6 +8356,7 @@ static void vmx_complete_atomic_exit(struct vcpu_vmx *vmx)
 static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
 {
 	u32 exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+	register void *__sp asm(_ASM_SP);
 
 	/*
 	 * If external interrupt exists, IF bit is set in rflags/eflags on the
@@ -8388,8 +8389,9 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu)
 			"call *%[entry]\n\t"
 			:
 #ifdef CONFIG_X86_64
-			[sp]"=&r"(tmp)
+			[sp]"=&r"(tmp),
 #endif
+			"+r"(__sp)
 			:
 			[entry]"r"(entry),
 			[ss]"i"(__KERNEL_DS),
#111 lore raw
In reply to Josh Poimboeuf
Quoted 3 lines · Josh Poimboeuf

This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.

Hi,

with this config:
https://github.com/openSUSE/kernel-source/blob/master/config/x86_64/vanilla

I am seeing a lot of functions in C which do not have frame pointer setup/cleanup:
stacktool: drivers/scsi/hpsa.o: hpsa_scsi_do_simple_cmd.constprop.106()+0x79: call without frame pointer save/setup
stacktool: drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.o: cfs_cdebug_show.part.5.constprop.35()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.o: cfs_cdebug_show.part.5.constprop.35()+0x8: duplicate frame pointer save
stacktool: drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.o: cfs_cdebug_show.part.5.constprop.35()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: ksocknal_connsock_decref()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: ksocknal_connsock_decref()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: ksocknal_connsock_decref()+0x1: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lnet/lnet/lib-move.o: cfs_cdebug_show.part.1.constprop.16()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/lnet/lib-move.o: cfs_cdebug_show.part.1.constprop.16()+0x8: duplicate frame pointer save
stacktool: drivers/staging/lustre/lnet/lnet/lib-move.o: cfs_cdebug_show.part.1.constprop.16()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lnet/lnet/lib-move.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lnet/lnet/lo.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lnet/lnet/nidstrings.o: cfs_print_nidlist()+0x220: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/lnet/peer.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lnet/lnet/router.o: cfs_cdebug_show.part.0.constprop.16()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/lnet/router.o: cfs_cdebug_show.part.0.constprop.16()+0x8: duplicate frame pointer save
stacktool: drivers/staging/lustre/lnet/lnet/router.o: cfs_cdebug_show.part.0.constprop.16()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lnet/lnet/router.o: lnet_find_net_locked()+0x8a: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/lnet/router.o: lnet_find_net_locked()+0x8a: return without frame pointer restore
stacktool: drivers/staging/lustre/lustre/fid/fid_request.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/fld/lproc_fld.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/libcfs/libcfs_lock.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/libcfs/libcfs_mem.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/dir.o: obd_unpackmd()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/dir.o: obd_unpackmd()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/dir.o: obd_unpackmd()+0x4: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/file.o: md_intent_lock.part.28()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/file.o: md_intent_lock.part.28()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/file.o: md_intent_lock.part.28()+0x24: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x1a: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x1b: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x19: return without frame pointer restore
stacktool: drivers/staging/lustre/lustre/llite/../lclient/lcommon_misc.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/llite_mmap.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/lproc_llite.o: checksum_pages_store()+0x19e: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/namei.o: ll_test_inode()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/namei.o: ll_test_inode()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/namei.o: ll_test_inode()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/rw.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: md_revalidate_lock.part.26()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: md_revalidate_lock.part.26()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: md_revalidate_lock.part.26()+0x24: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: sa_args_fini()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: sa_args_fini()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: sa_args_fini()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/vvp_page.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/xattr_cache.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/xattr.o: get_xattr_type()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/xattr.o: get_xattr_type()+0x1f: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/xattr.o: get_xattr_type()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/lmv/lmv_intent.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/lmv/lmv_obd.o: __lmv_fid_alloc()+0x185: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/lov/lov_io.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/lov/lovsub_dev.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/mdc/mdc_lib.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/mdc/mdc_locks.o: .text.unlikely: unexpected end of section
stacktool: drivers/staging/lustre/lustre/obdclass/debug.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/obdclass/genops.o: class_name2dev()+0xc7: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/obdclass/lustre_handles.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/obdclass/obd_config.o: lustre_cfg_string()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/obdclass/obd_config.o: lustre_cfg_string()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/obdclass/obd_config.o: lustre_cfg_string()+0x4: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: __client_obd_list_lock()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: __client_obd_list_lock()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: __client_obd_list_lock()+0x1: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: osc_extent_search()+0x78: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: osc_extent_search()+0x78: return without frame pointer restore
stacktool: drivers/staging/lustre/lustre/osc/osc_dev.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/osc/osc_page.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/connection.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/import.o: deuuidify.constprop.8()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/import.o: deuuidify.constprop.8()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/ptlrpc/import.o: deuuidify.constprop.8()+0x6: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/ptlrpc/llog_net.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/../../lustre/ldlm/ldlm_extent.o: ldlm_extent_shift_kms()+0x93: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/../../lustre/ldlm/ldlm_lock.o: ldlm_work_bl_ast_lock()+0x156: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/../../lustre/ldlm/ldlm_lock.o: ldlm_work_cp_ast_lock()+0xda: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/nrs.o: nrs_policy_register()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/nrs.o: nrs_policy_register()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/ptlrpc/nrs.o: nrs_policy_register()+0x6: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/ptlrpc/nrs.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/pack_generic.o: lustre_swab_mgs_nidtbl_entry()+0x89: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/pack_generic.o: lustre_swab_mgs_nidtbl_entry()+0x89: return without frame pointer restore
stacktool: drivers/staging/lustre/lustre/ptlrpc/sec_bulk.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/sec_config.o: .text: unexpected end of section
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x70: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x92: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xff: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xf5: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0x11a: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_get()+0x225: call without frame pointer save/setup
stacktool: kernel/locking/percpu-rwsem.o: percpu_up_read()+0x27: call without frame pointer save/setup
stacktool: kernel/profile.o: do_profile_hits.isra.5()+0x139: call without frame pointer save/setup
stacktool: lib/nmi_backtrace.o: nmi_trigger_all_cpu_backtrace()+0x2b6: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_recv()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_send()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_recv.o: rds_ib_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_recv_cq_comp_handler()+0x55: call without frame pointer save/setup

For example do_profile_hits.isra.5:
0000000000003360 <hpsa_scsi_do_simple_cmd.constprop.106>:

    3360:       e8 00 00 00 00          callq  3365 <hpsa_scsi_do_simple_cmd.constprop.106+0x5>
                        3361: R_X86_64_PC32     __fentry__-0x4
    3365:       65 ff 05 00 00 00 00    incl   %gs:0x0(%rip)        # 336c <hpsa_scsi_do_simple_cmd.constprop.106+0xc>
                        3368: R_X86_64_PC32     __preempt_count-0x4
    336c:       65 8b 0d 00 00 00 00    mov    %gs:0x0(%rip),%ecx        # 3373 <hpsa_scsi_do_simple_cmd.constprop.106+0x13>
                        336f: R_X86_64_PC32     cpu_number-0x4
    3373:       48 63 c9                movslq %ecx,%rcx
    3376:       48 8b 87 b8 4b 00 00    mov    0x4bb8(%rdi),%rax
    337d:       48 8b 0c cd 00 00 00    mov    0x0(,%rcx,8),%rcx
    3384:       00 
                        3381: R_X86_64_32S      __per_cpu_offset
    3385:       8b 04 01                mov    (%rcx,%rax,1),%eax
    3388:       65 ff 0d 00 00 00 00    decl   %gs:0x0(%rip)        # 338f <hpsa_scsi_do_simple_cmd.constprop.106+0x2f>
                        338b: R_X86_64_PC32     __preempt_count-0x4
    338f:       74 48                   je     33d9 <hpsa_scsi_do_simple_cmd.constprop.106+0x79>
    3391:       85 c0                   test   %eax,%eax
    3393:       75 4d                   jne    33e2 <hpsa_scsi_do_simple_cmd.constprop.106+0x82>
    3395:       55                      push   %rbp
    3396:       48 89 e5                mov    %rsp,%rbp
    3399:       53                      push   %rbx
    339a:       48 8d 5d d8             lea    -0x28(%rbp),%rbx
    339e:       48 83 ec 20             sub    $0x20,%rsp
    33a2:       c7 45 d8 00 00 00 00    movl   $0x0,-0x28(%rbp)
    33a9:       c7 45 e0 00 00 00 00    movl   $0x0,-0x20(%rbp)
    33b0:       48 8d 43 10             lea    0x10(%rbx),%rax
    33b4:       48 89 9e 54 02 00 00    mov    %rbx,0x254(%rsi)
    33bb:       48 89 45 e8             mov    %rax,-0x18(%rbp)
    33bf:       48 89 45 f0             mov    %rax,-0x10(%rbp)
    33c3:       e8 f8 ce ff ff          callq  2c0 <__enqueue_cmd_and_start_io>
    33c8:       48 89 df                mov    %rbx,%rdi
    33cb:       e8 00 00 00 00          callq  33d0 <hpsa_scsi_do_simple_cmd.constprop.106+0x70>
                        33cc: R_X86_64_PC32     wait_for_completion_io-0x4
    33d0:       48 83 c4 20             add    $0x20,%rsp
    33d4:       31 c0                   xor    %eax,%eax
    33d6:       5b                      pop    %rbx
    33d7:       5d                      pop    %rbp
    33d8:       c3                      retq   
    33d9:       e8 00 00 00 00          callq  33de <hpsa_scsi_do_simple_cmd.constprop.106+0x7e>
                        33da: R_X86_64_PC32     ___preempt_schedule-0x4
    33de:       85 c0                   test   %eax,%eax
    33e0:       74 b3                   je     3395 <hpsa_scsi_do_simple_cmd.constprop.106+0x35>
    33e2:       48 8b 86 38 02 00 00    mov    0x238(%rsi),%rax
    33e9:       ba ff ff ff ff          mov    $0xffffffff,%edx
    33ee:       66 89 50 02             mov    %dx,0x2(%rax)
    33f2:       31 c0                   xor    %eax,%eax
    33f4:       c3                      retq   
    33f5:       90                      nop
    33f6:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
    33fd:       00 00 00 

It there some compilation flag missing? -f flags when compiling that file are:
-falign-jumps=1
-falign-loops=1
-fconserve-stack
-fno-asynchronous-unwind-tables
-fno-common
-fno-delete-null-pointer-checks
-fno-inline-functions-called-once
-fno-omit-frame-pointer
-fno-optimize-sibling-calls
-fno-strict-aliasing
-fno-strict-overflow
-fno-var-tracking-assignments
-fstack-protector
-funit-at-a-time

thanks,

Signature · 2 lines
js
suse labs
#112 lore raw
Quoted 5 lines · Jiri Slaby

It there some compilation flag missing? -f flags when compiling that file are:

(quoted diff) +0 -4
-falign-jumps=1
-falign-loops=1
-fconserve-stack
-fno-asynchronous-unwind-tables

Review

Quoted 10 lines
(quoted diff) +0 -10
-fno-common
-fno-delete-null-pointer-checks
-fno-inline-functions-called-once
-fno-omit-frame-pointer
-fno-optimize-sibling-calls
-fno-strict-aliasing
-fno-strict-overflow
-fno-var-tracking-assignments
-fstack-protector
-funit-at-a-time

Happens with:
gcc (SUSE Linux) 5.3.1 20151207 [gcc-5-branch revision 231355] gcc-6 (SUSE Linux) 6.0.0 20160202 (experimental) [trunk revision 233076]

Quoted 1 line

thanks,

Signature · 2 lines
js
suse labs
#113 lore raw
In reply to Jiri Slaby
Quoted 11 lines · Jiri Slaby
Quoted 3 lines · Josh Poimboeuf

This is v16 of the compile-time stack metadata validation patch set, along with proposed fixes for most of the warnings it found. It's based on the tip/master branch.

Hi,

with this config:
https://github.com/openSUSE/kernel-source/blob/master/config/x86_64/vanilla

I am seeing a lot of functions in C which do not have frame pointer setup/cleanup:

Hi Jiri,

Thanks for testing.

Quoted 1 line

stacktool: drivers/scsi/hpsa.o: hpsa_scsi_do_simple_cmd.constprop.106()+0x79: call without frame pointer save/setup

This seems like a real frame pointer bug caused by the following line in arch/x86/include/asm/preempt.h:

  # define __preempt_schedule() asm ("call ___preempt_schedule")

The asm statement doesn't have the stack pointer as an output operand, so gcc doesn't skips the frame pointer setup before calling.

However, I suspect the "bug" is intentional for optimization purposes.

Quoted 79 lines

stacktool: drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.o: cfs_cdebug_show.part.5.constprop.35()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.o: cfs_cdebug_show.part.5.constprop.35()+0x8: duplicate frame pointer save
stacktool: drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.o: cfs_cdebug_show.part.5.constprop.35()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: ksocknal_connsock_decref()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: ksocknal_connsock_decref()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: ksocknal_connsock_decref()+0x1: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lnet/klnds/socklnd/socklnd.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lnet/lnet/lib-move.o: cfs_cdebug_show.part.1.constprop.16()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/lnet/lib-move.o: cfs_cdebug_show.part.1.constprop.16()+0x8: duplicate frame pointer save
stacktool: drivers/staging/lustre/lnet/lnet/lib-move.o: cfs_cdebug_show.part.1.constprop.16()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lnet/lnet/lib-move.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lnet/lnet/lo.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lnet/lnet/nidstrings.o: cfs_print_nidlist()+0x220: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/lnet/peer.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lnet/lnet/router.o: cfs_cdebug_show.part.0.constprop.16()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/lnet/router.o: cfs_cdebug_show.part.0.constprop.16()+0x8: duplicate frame pointer save
stacktool: drivers/staging/lustre/lnet/lnet/router.o: cfs_cdebug_show.part.0.constprop.16()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lnet/lnet/router.o: lnet_find_net_locked()+0x8a: frame pointer state mismatch
stacktool: drivers/staging/lustre/lnet/lnet/router.o: lnet_find_net_locked()+0x8a: return without frame pointer restore
stacktool: drivers/staging/lustre/lustre/fid/fid_request.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/fld/lproc_fld.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/libcfs/libcfs_lock.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/libcfs/libcfs_mem.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/dir.o: obd_unpackmd()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/dir.o: obd_unpackmd()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/dir.o: obd_unpackmd()+0x4: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/file.o: md_intent_lock.part.28()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/file.o: md_intent_lock.part.28()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/file.o: md_intent_lock.part.28()+0x24: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x1a: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x1b: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/../lclient/glimpse.o: cl_io_get()+0x19: return without frame pointer restore
stacktool: drivers/staging/lustre/lustre/llite/../lclient/lcommon_misc.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/llite_mmap.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/lproc_llite.o: checksum_pages_store()+0x19e: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/namei.o: ll_test_inode()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/namei.o: ll_test_inode()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/namei.o: ll_test_inode()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/rw.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: md_revalidate_lock.part.26()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: md_revalidate_lock.part.26()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: md_revalidate_lock.part.26()+0x24: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: sa_args_fini()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: sa_args_fini()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: sa_args_fini()+0x9: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/statahead.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/vvp_page.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/xattr_cache.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/llite/xattr.o: get_xattr_type()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/llite/xattr.o: get_xattr_type()+0x1f: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/llite/xattr.o: get_xattr_type()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/lmv/lmv_intent.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/lmv/lmv_obd.o: __lmv_fid_alloc()+0x185: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/lov/lov_io.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/lov/lovsub_dev.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/mdc/mdc_lib.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/mdc/mdc_locks.o: .text.unlikely: unexpected end of section
stacktool: drivers/staging/lustre/lustre/obdclass/debug.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/obdclass/genops.o: class_name2dev()+0xc7: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/obdclass/lustre_handles.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/obdclass/obd_config.o: lustre_cfg_string()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/obdclass/obd_config.o: lustre_cfg_string()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/obdclass/obd_config.o: lustre_cfg_string()+0x4: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: __client_obd_list_lock()+0x0: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: __client_obd_list_lock()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: __client_obd_list_lock()+0x1: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: osc_extent_search()+0x78: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/osc/osc_cache.o: osc_extent_search()+0x78: return without frame pointer restore
stacktool: drivers/staging/lustre/lustre/osc/osc_dev.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/osc/osc_page.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/connection.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/import.o: deuuidify.constprop.8()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/import.o: deuuidify.constprop.8()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/ptlrpc/import.o: deuuidify.constprop.8()+0x6: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/ptlrpc/llog_net.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/../../lustre/ldlm/ldlm_extent.o: ldlm_extent_shift_kms()+0x93: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/../../lustre/ldlm/ldlm_lock.o: ldlm_work_bl_ast_lock()+0x156: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/../../lustre/ldlm/ldlm_lock.o: ldlm_work_cp_ast_lock()+0xda: frame pointer state mismatch

Quoted 8 lines

stacktool: drivers/staging/lustre/lustre/ptlrpc/nrs.o: nrs_policy_register()+0x0: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/nrs.o: nrs_policy_register()+0x5: duplicate frame pointer save
stacktool: drivers/staging/lustre/lustre/ptlrpc/nrs.o: nrs_policy_register()+0x6: duplicate frame pointer setup
stacktool: drivers/staging/lustre/lustre/ptlrpc/nrs.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/pack_generic.o: lustre_swab_mgs_nidtbl_entry()+0x89: frame pointer state mismatch
stacktool: drivers/staging/lustre/lustre/ptlrpc/pack_generic.o: lustre_swab_mgs_nidtbl_entry()+0x89: return without frame pointer restore
stacktool: drivers/staging/lustre/lustre/ptlrpc/sec_bulk.o: .text: unexpected end of section
stacktool: drivers/staging/lustre/lustre/ptlrpc/sec_config.o: .text: unexpected end of section

These staging driver issues are caused by stacktool getting confused by gcc optimizations related to noreturn functions. I have it on the TODO list to make the noreturn function detection more intelligent.

Quoted 6 lines

stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x70: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x92: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xff: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xf5: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0x11a: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_get()+0x225: call without frame pointer save/setup

Quoted 8 lines

stacktool: kernel/locking/percpu-rwsem.o: percpu_up_read()+0x27: call without frame pointer save/setup
stacktool: kernel/profile.o: do_profile_hits.isra.5()+0x139: call without frame pointer save/setup
stacktool: lib/nmi_backtrace.o: nmi_trigger_all_cpu_backtrace()+0x2b6: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_recv()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_send()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_recv.o: rds_ib_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_recv_cq_comp_handler()+0x55: call without frame pointer save/setup

These are all the same "call ___preempt_schedule" issue from above. I'll need to look into it to figure out if it's a real bug or if it's a "feature" we should ignore.

Signature · 1 line
Josh
maintainer
#114 lore raw
Quoted 6 lines · Josh Poimboeuf

On Fri, Feb 12, 2016 at 11:36:24AM +0100, Jiri Slaby wrote:

This seems like a real frame pointer bug caused by the following line in arch/x86/include/asm/preempt.h:

  # define __preempt_schedule() asm ("call ___preempt_schedule")

The purpose there is that:

	preempt_enable();

turns into:

	decl	__percpu_prefix:__preempt_count
	jnz	1f:
	call	___preempt_schedule

1:

See arch/x86/include/asm/preempt.h:__preempt_count_dec_and_test()

#115 lore raw
Quoted 12 lines · Peter Zijlstra
Quoted 6 lines · Josh Poimboeuf

On Fri, Feb 12, 2016 at 11:36:24AM +0100, Jiri Slaby wrote:

This seems like a real frame pointer bug caused by the following line in arch/x86/include/asm/preempt.h:

  # define __preempt_schedule() asm ("call ___preempt_schedule")

The purpose there is that:

	preempt_enable();
Quoted 8 lines

turns into:

	decl	__percpu_prefix:__preempt_count
	jnz	1f:
	call	___preempt_schedule

1:

See arch/x86/include/asm/preempt.h:__preempt_count_dec_and_test()

Sorry, I'm kind of confused. Do you mean that's what preempt_enable() would turn into *without* the above define?

What I actually see in the listing is:

decl __percpu_prefix:__preempt_count
je 1f:

	....

1:
call ___preempt_schedule

So it puts the "call ___preempt_schedule" in the slow path.

I also don't see how that would be related to the use of the asm statement in the __preempt_schedule() macro. Doesn't the use of unlikely() in preempt_enable() put the call in the slow path?

#define preempt_enable() \

  do { \
	  barrier(); \
	  if (unlikely(preempt_count_dec_and_test())) \
		  preempt_schedule(); \

} while (0)

Also, why is the thunk needed? Any reason why preempt_enable() can't be called directly from C?

Signature · 1 line
Josh
#116 lore raw
Quoted 40 lines · Josh Poimboeuf
Quoted 12 lines · Peter Zijlstra
Quoted 6 lines · Josh Poimboeuf

On Fri, Feb 12, 2016 at 11:36:24AM +0100, Jiri Slaby wrote:

This seems like a real frame pointer bug caused by the following line in arch/x86/include/asm/preempt.h:

  # define __preempt_schedule() asm ("call ___preempt_schedule")

The purpose there is that:

	preempt_enable();
Quoted 8 lines

turns into:

	decl	__percpu_prefix:__preempt_count
	jnz	1f:
	call	___preempt_schedule

1:

See arch/x86/include/asm/preempt.h:__preempt_count_dec_and_test()

Sorry, I'm kind of confused. Do you mean that's what preempt_enable() would turn into *without* the above define?

What I actually see in the listing is:

(quoted diff) +0 -0
 	decl	__percpu_prefix:__preempt_count
 	je	1f:
....
 1:
 	call	___preempt_schedule

So it puts the "call ___preempt_schedule" in the slow path.

I also don't see how that would be related to the use of the asm statement in the __preempt_schedule() macro. Doesn't the use of unlikely() in preempt_enable() put the call in the slow path?

#define preempt_enable() \

Quoted 8 lines
  do { \
	  barrier(); \
	  if (unlikely(preempt_count_dec_and_test())) \
		  preempt_schedule(); \

} while (0)

Also, why is the thunk needed? Any reason why preempt_enable() can't be called directly from C?

Sorry, s/preempt_enable/preempt_schedule/ on that last sentence.

Signature · 5 lines
Josh
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
maintainer
#117 lore raw
In reply to Josh Poimboeuf
Quoted 9 lines · Josh Poimboeuf

What I actually see in the listing is:

(quoted diff) +0 -0
 	decl	__percpu_prefix:__preempt_count
 	je	1f:
....
 1:
 	call	___preempt_schedule

So it puts the "call ___preempt_schedule" in the slow path.

Ah yes indeed. Same difference though.

Quoted 3 lines

I also don't see how that would be related to the use of the asm statement in the __preempt_schedule() macro. Doesn't the use of unlikely() in preempt_enable() put the call in the slow path?

Sadly no, unlikely() and asm_goto don't work well together. But the slow path or not isn't the reason we do the asm call thing.

Quoted 9 lines

#define preempt_enable() \

  do { \
	  barrier(); \
	  if (unlikely(preempt_count_dec_and_test())) \
		  preempt_schedule(); \

} while (0)

Also, why is the thunk needed? Any reason why preempt_enable() can't be called directly from C?

That would make the call-site save registers and increase the size of every preempt_enable(). By using the thunk we can do callee saved registers and avoid blowing up the call site.
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#118 lore raw
Quoted 27 lines · Peter Zijlstra
Quoted 9 lines · Josh Poimboeuf

What I actually see in the listing is:

(quoted diff) +0 -0
 	decl	__percpu_prefix:__preempt_count
 	je	1f:
....
 1:
 	call	___preempt_schedule

So it puts the "call ___preempt_schedule" in the slow path.

Ah yes indeed. Same difference though.

Quoted 3 lines

I also don't see how that would be related to the use of the asm statement in the __preempt_schedule() macro. Doesn't the use of unlikely() in preempt_enable() put the call in the slow path?

Sadly no, unlikely() and asm_goto don't work well together. But the slow path or not isn't the reason we do the asm call thing.

Quoted 7 lines

#define preempt_enable() \

  do { \
	  barrier(); \
	  if (unlikely(preempt_count_dec_and_test())) \
		  preempt_schedule(); \

} while (0)

Quoted 6 lines
Quoted 2 lines

Also, why is the thunk needed? Any reason why preempt_enable() can't be called directly from C?

That would make the call-site save registers and increase the size of every preempt_enable(). By using the thunk we can do callee saved registers and avoid blowing up the call site.

So is the goal to optimize for size? If I replace the calls to __preempt_schedule[_notrace]() with real C calls and remove the thunks, it only adds about 2k to vmlinux.

There are two ways to fix the warnings:

1. get rid of the thunks and call the C functions directly; or

2. add the stack pointer to the asm() statement output operand list to ensure a stack frame gets created in the caller function before the call. (Note this still allows the thunks to do callee saved registers.)

I like #1 better, but maybe I'm still missing the point of the thunks.

Signature · 1 line
Josh
maintainer
#119 lore raw
Quoted 28 lines · Josh Poimboeuf
Quoted 27 lines · Peter Zijlstra
Quoted 9 lines · Josh Poimboeuf

What I actually see in the listing is:

(quoted diff) +0 -0
 	decl	__percpu_prefix:__preempt_count
 	je	1f:
....
 1:
 	call	___preempt_schedule

So it puts the "call ___preempt_schedule" in the slow path.

Ah yes indeed. Same difference though.

Quoted 3 lines

I also don't see how that would be related to the use of the asm statement in the __preempt_schedule() macro. Doesn't the use of unlikely() in preempt_enable() put the call in the slow path?

Sadly no, unlikely() and asm_goto don't work well together. But the slow path or not isn't the reason we do the asm call thing.

Quoted 7 lines

#define preempt_enable() \

  do { \
	  barrier(); \
	  if (unlikely(preempt_count_dec_and_test())) \
		  preempt_schedule(); \

} while (0)

Quoted 8 lines
Quoted 6 lines
Quoted 2 lines

Also, why is the thunk needed? Any reason why preempt_enable() can't be called directly from C?

That would make the call-site save registers and increase the size of every preempt_enable(). By using the thunk we can do callee saved registers and avoid blowing up the call site.

So is the goal to optimize for size?

General performance impact of preempt_enable().

Quoted 3 lines

If I replace the calls to
__preempt_schedule[_notrace]() with real C calls and remove the thunks, it only adds about 2k to vmlinux.

That's less than I had expected, but probably still worth it.

And is that added text purely in the slow path? We really want to avoid putting any more register pressure on the preempt_enable() call sites. The single memop and Jcc is about as fast we can get and we spend quite a bit of effort getting there.

Quoted 9 lines

There are two ways to fix the warnings:

1. get rid of the thunks and call the C functions directly; or

2. add the stack pointer to the asm() statement output operand list to ensure a stack frame gets created in the caller function before the call. (Note this still allows the thunks to do callee saved registers.)

I like #1 better, but maybe I'm still missing the point of the thunks.

Ingo, Linus?
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

A message that is not in the archive (sent off-list or not yet received): CA+55aFzoPCd_LcSx1FUuEhSBYk2KrfzXGj-Vcn39W5bz=KuZhA@mail.gmail.com

#121 lore raw
Quoted 21 lines · Linus Torvalds
Quoted 4 lines · Josh Poimboeuf

So is the goal to optimize for size? If I replace the calls to __preempt_schedule[_notrace]() with real C calls and remove the thunks, it only adds about 2k to vmlinux.

It adds nasty register pressure in some of the most critical parts of the kernel, and makes the asm code harder to read.

And yes, I still read the asm. For performance reasons, and when decoding oopses.

I realize that few other people care about generated code. That's sad.

Quoted 3 lines

There are two ways to fix the warnings:

1. get rid of the thunks and call the C functions directly; or

No. Not until gcc learns about per-function callibg conventions (so that it can be marked as not clobbering registers).

Quoted 7 lines
Quoted 3 lines

2. add the stack pointer to the asm() statement output operand list to ensure a stack frame gets created in the caller function before the call.

That probably doesn't make things much worse. It probably makes least functions have a stack frame if they do preempt disable, but it might still be acceptable. Hard to say before I end up hurting this case again.

Oddly, this change (see patch below) actually seems to make things faster in a lot of cases. For many smaller functions it causes the stack frame creation to get moved out of the common path and into the unlikely path.

For example, here's the original cyc2ns_read_end():

ffffffff8101f8c0 <cyc2ns_read_end>:

  ffffffff8101f8c0:	55                   	push   %rbp
  ffffffff8101f8c1:	48 89 e5             	mov    %rsp,%rbp
  ffffffff8101f8c4:	83 6f 10 01          	subl   $0x1,0x10(%rdi)
  ffffffff8101f8c8:	75 08                	jne    ffffffff8101f8d2 <cyc2ns_read_end+0x12>
  ffffffff8101f8ca:	65 48 89 3d e6 5a ff 	mov    %rdi,%gs:0x7eff5ae6(%rip)        # 153b8 <cyc2ns+0x38>
  ffffffff8101f8d1:	7e 
  ffffffff8101f8d2:	65 ff 0d 77 c4 fe 7e 	decl   %gs:0x7efec477(%rip)        # bd50 <__preempt_count>
  ffffffff8101f8d9:	74 02                	je     ffffffff8101f8dd <cyc2ns_read_end+0x1d>
  ffffffff8101f8db:	5d                   	pop    %rbp
  ffffffff8101f8dc:	c3                   	retq   
  ffffffff8101f8dd:	e8 1e 37 fe ff       	callq  ffffffff81003000 <___preempt_schedule>
  ffffffff8101f8e2:	5d                   	pop    %rbp
  ffffffff8101f8e3:	c3                   	retq   

ffffffff8101f8e4: 66 66 66 2e 0f 1f 84 data16 data16 nopw %cs:0x0(%rax,%rax,1)
ffffffff8101f8eb: 00 00 00 00 00

And here's the same function with the patch:

ffffffff8101f8c0 <cyc2ns_read_end>:

  ffffffff8101f8c0:	83 6f 10 01          	subl   $0x1,0x10(%rdi)
  ffffffff8101f8c4:	75 08                	jne    ffffffff8101f8ce <cyc2ns_read_end+0xe>
  ffffffff8101f8c6:	65 48 89 3d ea 5a ff 	mov    %rdi,%gs:0x7eff5aea(%rip)        # 153b8 <cyc2ns+0x38>
  ffffffff8101f8cd:	7e 
  ffffffff8101f8ce:	65 ff 0d 7b c4 fe 7e 	decl   %gs:0x7efec47b(%rip)        # bd50 <__preempt_count>
  ffffffff8101f8d5:	74 01                	je     ffffffff8101f8d8 <cyc2ns_read_end+0x18>
  ffffffff8101f8d7:	c3                   	retq   
  ffffffff8101f8d8:	55                   	push   %rbp
  ffffffff8101f8d9:	48 89 e5             	mov    %rsp,%rbp
  ffffffff8101f8dc:	e8 1f 37 fe ff       	callq  ffffffff81003000 <___preempt_schedule>
  ffffffff8101f8e1:	5d                   	pop    %rbp
  ffffffff8101f8e2:	c3                   	retq   

ffffffff8101f8e3: 66 66 66 66 2e 0f 1f data16 data16 data16 nopw %cs:0x0(%rax,%rax,1)
ffffffff8101f8ea: 84 00 00 00 00 00

Notice that it moved the frame pointer setup code to the unlikely ___preempt_schedule() call path. Going through a sampling of the differences in the asm, that's the most common change I see.

Otherwise it has no real effect on callers which already have stack frames (though it does change the ordering of some 'mov's).

And it has the intended effect of fixing the following warnings by ensuring these call sites have stack frames:

stacktool: drivers/scsi/hpsa.o: hpsa_scsi_do_simple_cmd.constprop.106()+0x79: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x70: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x92: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xff: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xf5: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0x11a: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_get()+0x225: call without frame pointer save/setup
stacktool: kernel/locking/percpu-rwsem.o: percpu_up_read()+0x27: call without frame pointer save/setup
stacktool: kernel/profile.o: do_profile_hits.isra.5()+0x139: call without frame pointer save/setup
stacktool: lib/nmi_backtrace.o: nmi_trigger_all_cpu_backtrace()+0x2b6: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_recv()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_send()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_recv.o: rds_ib_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_recv_cq_comp_handler()+0x55: call without frame pointer save/setup

So that only adds a stack frame to 15 call sites out of ~5000 calls to ___preempt_schedule[_notrace]. All the others already had stack frames.

Any idea for a good benchmark to run with the patch?

Quoted 2 lines

The alternative is to just teach the tools about the magic issue of a few things like this.

I think that would be problematic for our goal of making stack traces of sleeping tasks reliable. If preempt_enable()'s caller doesn't first create a stack frame, the caller of the caller will get skipped in the stack trace.

---8<---

arch/x86/include/asm/preempt.h +11 -2
index 01bcde8..2989aa6 100644
@@ -94,10 +94,19 @@ static __always_inline bool should_resched(int preempt_offset)
 
 #ifdef CONFIG_PREEMPT
   extern asmlinkage void ___preempt_schedule(void);
-# define __preempt_schedule() asm ("call ___preempt_schedule")
+# define __preempt_schedule() \
+({ \
+	register void *__sp asm(_ASM_SP); \
+	asm volatile ("call ___preempt_schedule" : "+r"(__sp)); \
+})
+
   extern asmlinkage void preempt_schedule(void);
   extern asmlinkage void ___preempt_schedule_notrace(void);
-# define __preempt_schedule_notrace() asm ("call ___preempt_schedule_notrace")
+# define __preempt_schedule_notrace() \
+({ \
+	register void *__sp asm(_ASM_SP); \
+	asm volatile ("call ___preempt_schedule_notrace" : "+r"(__sp)); \
+})
   extern asmlinkage void preempt_schedule_notrace(void);
 #endif
 
Signature · 1 line
Josh
#122 lore raw

PATCH 1/1 sched/x86: Add stack frame dependency to __preempt_schedule[_notrace]

If __preempt_schedule() or __preempt_schedule_notrace() is referenced at the beginning of a function, gcc can insert the asm inline "call ___preempt_schedule[_notrace]" instruction before setting up a stack frame, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in bad stack traces.

Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the inline asm statements.

Specifically this fixes the following stacktool warnings:

stacktool: drivers/scsi/hpsa.o: hpsa_scsi_do_simple_cmd.constprop.106()+0x79: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x70: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x92: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xff: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xf5: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0x11a: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_get()+0x225: call without frame pointer save/setup
stacktool: kernel/locking/percpu-rwsem.o: percpu_up_read()+0x27: call without frame pointer save/setup
stacktool: kernel/profile.o: do_profile_hits.isra.5()+0x139: call without frame pointer save/setup
stacktool: lib/nmi_backtrace.o: nmi_trigger_all_cpu_backtrace()+0x2b6: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_recv()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_send()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_recv.o: rds_ib_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_recv_cq_comp_handler()+0x55: call without frame pointer save/setup

So it only adds a stack frame to 15 call sites out of ~5000 calls to ___preempt_schedule[_notrace]. All the others already had stack frames.

Oddly, this change actually seems to make things faster in a lot of cases. For many smaller functions it causes the stack frame creation to get moved out of the common path and into the unlikely path.

For example, here's the original cyc2ns_read_end():

ffffffff8101f8c0 <cyc2ns_read_end>:

  ffffffff8101f8c0:	55                   	push   %rbp
  ffffffff8101f8c1:	48 89 e5             	mov    %rsp,%rbp
  ffffffff8101f8c4:	83 6f 10 01          	subl   $0x1,0x10(%rdi)
  ffffffff8101f8c8:	75 08                	jne    ffffffff8101f8d2 <cyc2ns_read_end+0x12>
  ffffffff8101f8ca:	65 48 89 3d e6 5a ff 	mov    %rdi,%gs:0x7eff5ae6(%rip)        # 153b8 <cyc2ns+0x38>
  ffffffff8101f8d1:	7e
  ffffffff8101f8d2:	65 ff 0d 77 c4 fe 7e 	decl   %gs:0x7efec477(%rip)        # bd50 <__preempt_count>
  ffffffff8101f8d9:	74 02                	je     ffffffff8101f8dd <cyc2ns_read_end+0x1d>
  ffffffff8101f8db:	5d                   	pop    %rbp
  ffffffff8101f8dc:	c3                   	retq
  ffffffff8101f8dd:	e8 1e 37 fe ff       	callq  ffffffff81003000 <___preempt_schedule>
  ffffffff8101f8e2:	5d                   	pop    %rbp
  ffffffff8101f8e3:	c3                   	retq

ffffffff8101f8e4: 66 66 66 2e 0f 1f 84 data16 data16 nopw %cs:0x0(%rax,%rax,1)
ffffffff8101f8eb: 00 00 00 00 00

And here's the same function with the patch:

ffffffff8101f8c0 <cyc2ns_read_end>:

  ffffffff8101f8c0:	83 6f 10 01          	subl   $0x1,0x10(%rdi)
  ffffffff8101f8c4:	75 08                	jne    ffffffff8101f8ce <cyc2ns_read_end+0xe>
  ffffffff8101f8c6:	65 48 89 3d ea 5a ff 	mov    %rdi,%gs:0x7eff5aea(%rip)        # 153b8 <cyc2ns+0x38>
  ffffffff8101f8cd:	7e
  ffffffff8101f8ce:	65 ff 0d 7b c4 fe 7e 	decl   %gs:0x7efec47b(%rip)        # bd50 <__preempt_count>
  ffffffff8101f8d5:	74 01                	je     ffffffff8101f8d8 <cyc2ns_read_end+0x18>
  ffffffff8101f8d7:	c3                   	retq
  ffffffff8101f8d8:	55                   	push   %rbp
  ffffffff8101f8d9:	48 89 e5             	mov    %rsp,%rbp
  ffffffff8101f8dc:	e8 1f 37 fe ff       	callq  ffffffff81003000 <___preempt_schedule>
  ffffffff8101f8e1:	5d                   	pop    %rbp
  ffffffff8101f8e2:	c3                   	retq

ffffffff8101f8e3: 66 66 66 66 2e 0f 1f data16 data16 data16 nopw %cs:0x0(%rax,%rax,1)
ffffffff8101f8ea: 84 00 00 00 00 00

Notice that it moved the frame pointer setup code to the unlikely ___preempt_schedule() call path. Going through a sampling of the differences in the asm, that's the most common change I see.

Otherwise it has no real effect on callers which already have stack frames (though it does result in the reordering of some 'mov's).

---
 arch/x86/include/asm/preempt.h | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
arch/x86/include/asm/preempt.h +11 -2
index 01bcde8..d397deb 100644
@@ -94,10 +94,19 @@ static __always_inline bool should_resched(int preempt_offset)
 
 #ifdef CONFIG_PREEMPT
   extern asmlinkage void ___preempt_schedule(void);
-# define __preempt_schedule() asm ("call ___preempt_schedule")
+# define __preempt_schedule()					\
+({								\
+	register void *__sp asm(_ASM_SP);			\
+	asm volatile ("call ___preempt_schedule" : "+r"(__sp));	\
+})
+
   extern asmlinkage void preempt_schedule(void);
   extern asmlinkage void ___preempt_schedule_notrace(void);
-# define __preempt_schedule_notrace() asm ("call ___preempt_schedule_notrace")
+# define __preempt_schedule_notrace()					\
+({									\
+	register void *__sp asm(_ASM_SP);				\
+	asm volatile ("call ___preempt_schedule_notrace" : "+r"(__sp));	\
+})
   extern asmlinkage void preempt_schedule_notrace(void);
 #endif
 
Signature · 1 line
2.4.3
#123 lore raw

Re: [PATCH] sched/x86: Add stack frame dependency to __preempt_schedule[_notrace]

Quoted 13 lines · Josh Poimboeuf

If __preempt_schedule() or __preempt_schedule_notrace() is referenced at the beginning of a function, gcc can insert the asm inline "call ___preempt_schedule[_notrace]" instruction before setting up a stack frame, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in bad stack traces.

Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the inline asm statements.

Specifically this fixes the following stacktool warnings:

stacktool: drivers/scsi/hpsa.o: hpsa_scsi_do_simple_cmd.constprop.106()+0x79: call without frame pointer save/setup

...

Quoted 1 line

This patch and adding lbug_with_loc to global_noreturns makes all stacktool warnings go away here.

Quoted 22 lines
---
 arch/x86/include/asm/preempt.h | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
arch/x86/include/asm/preempt.h +6 -1
index 01bcde8..d397deb 100644
@@ -94,10 +94,19 @@ static __always_inline bool should_resched(int preempt_offset)
 
 #ifdef CONFIG_PREEMPT
   extern asmlinkage void ___preempt_schedule(void);
-# define __preempt_schedule() asm ("call ___preempt_schedule")
+# define __preempt_schedule()					\
+({								\
+	register void *__sp asm(_ASM_SP);			\
+	asm volatile ("call ___preempt_schedule" : "+r"(__sp));	\
+})
+
   extern asmlinkage void preempt_schedule(void);

arch/x86/include/asm/preempt.h static __always_inline bool should_resched(int preempt_offset) · line 112

Quoted 10 lines
arch/x86/include/asm/preempt.h +5 -1
   extern asmlinkage void ___preempt_schedule_notrace(void);
-# define __preempt_schedule_notrace() asm ("call ___preempt_schedule_notrace")
+# define __preempt_schedule_notrace()					\
+({									\
+	register void *__sp asm(_ASM_SP);				\
+	asm volatile ("call ___preempt_schedule_notrace" : "+r"(__sp));	\
+})
   extern asmlinkage void preempt_schedule_notrace(void);
 #endif
 

thanks,

Signature · 2 lines
js
suse labs
#125 lore raw

[tip:x86/debug] sched/x86: Add stack frame dependency to __preempt_schedule[_notrace]()

In reply to Josh Poimboeuf
sched/x86: Add stack frame dependency to __preempt_schedule[_notrace]()
Commit-ID:  821eae7d14f0bbf69df1cc4656c54900b2672928
Gitweb:     http://git.kernel.org/tip/821eae7d14f0bbf69df1cc4656c54900b2672928
Author:     Josh Poimboeuf <[email protected]>
AuthorDate: Thu, 18 Feb 2016 11:41:58 -0600
Committer:  Ingo Molnar <[email protected]>
CommitDate: Wed, 24 Feb 2016 08:35:45 +0100

sched/x86: Add stack frame dependency to __preempt_schedule[_notrace]()

If __preempt_schedule() or __preempt_schedule_notrace() is referenced at the beginning of a function, gcc can insert the asm inline "call ___preempt_schedule[_notrace]" instruction before setting up a stack frame, which breaks frame pointer convention if CONFIG_FRAME_POINTER is enabled and can result in bad stack traces.

Force a stack frame to be created if CONFIG_FRAME_POINTER is enabled by listing the stack pointer as an output operand for the inline asm statements.

Specifically this fixes the following stacktool warnings:

stacktool: drivers/scsi/hpsa.o: hpsa_scsi_do_simple_cmd.constprop.106()+0x79: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x70: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_find_first()+0x92: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xff: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0xf5: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_free()+0x11a: call without frame pointer save/setup
stacktool: fs/mbcache.o: mb_cache_entry_get()+0x225: call without frame pointer save/setup
stacktool: kernel/locking/percpu-rwsem.o: percpu_up_read()+0x27: call without frame pointer save/setup
stacktool: kernel/profile.o: do_profile_hits.isra.5()+0x139: call without frame pointer save/setup
stacktool: lib/nmi_backtrace.o: nmi_trigger_all_cpu_backtrace()+0x2b6: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_recv()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_cm.o: rds_ib_cq_comp_handler_send()+0x58: call without frame pointer save/setup
stacktool: net/rds/ib_recv.o: rds_ib_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_attempt_ack()+0xc1: call without frame pointer save/setup
stacktool: net/rds/iw_recv.o: rds_iw_recv_cq_comp_handler()+0x55: call without frame pointer save/setup

So it only adds a stack frame to 15 call sites out of ~5000 calls to ___preempt_schedule[_notrace](). All the others already had stack frames.

Oddly, this change actually seems to make things faster in a lot of cases. For many smaller functions it causes the stack frame creation to get moved out of the common path and into the unlikely path.

For example, here's the original cyc2ns_read_end():

ffffffff8101f8c0 <cyc2ns_read_end>:

  ffffffff8101f8c0:	55                   	push   %rbp
  ffffffff8101f8c1:	48 89 e5             	mov    %rsp,%rbp
  ffffffff8101f8c4:	83 6f 10 01          	subl   $0x1,0x10(%rdi)
  ffffffff8101f8c8:	75 08                	jne    ffffffff8101f8d2 <cyc2ns_read_end+0x12>
  ffffffff8101f8ca:	65 48 89 3d e6 5a ff 	mov    %rdi,%gs:0x7eff5ae6(%rip)        # 153b8 <cyc2ns+0x38>
  ffffffff8101f8d1:	7e
  ffffffff8101f8d2:	65 ff 0d 77 c4 fe 7e 	decl   %gs:0x7efec477(%rip)        # bd50 <__preempt_count>
  ffffffff8101f8d9:	74 02                	je     ffffffff8101f8dd <cyc2ns_read_end+0x1d>
  ffffffff8101f8db:	5d                   	pop    %rbp
  ffffffff8101f8dc:	c3                   	retq
  ffffffff8101f8dd:	e8 1e 37 fe ff       	callq  ffffffff81003000 <___preempt_schedule>
  ffffffff8101f8e2:	5d                   	pop    %rbp
  ffffffff8101f8e3:	c3                   	retq

ffffffff8101f8e4: 66 66 66 2e 0f 1f 84 data16 data16 nopw %cs:0x0(%rax,%rax,1)
ffffffff8101f8eb: 00 00 00 00 00

And here's the same function with the patch:

ffffffff8101f8c0 <cyc2ns_read_end>:

  ffffffff8101f8c0:	83 6f 10 01          	subl   $0x1,0x10(%rdi)
  ffffffff8101f8c4:	75 08                	jne    ffffffff8101f8ce <cyc2ns_read_end+0xe>
  ffffffff8101f8c6:	65 48 89 3d ea 5a ff 	mov    %rdi,%gs:0x7eff5aea(%rip)        # 153b8 <cyc2ns+0x38>
  ffffffff8101f8cd:	7e
  ffffffff8101f8ce:	65 ff 0d 7b c4 fe 7e 	decl   %gs:0x7efec47b(%rip)        # bd50 <__preempt_count>
  ffffffff8101f8d5:	74 01                	je     ffffffff8101f8d8 <cyc2ns_read_end+0x18>
  ffffffff8101f8d7:	c3                   	retq
  ffffffff8101f8d8:	55                   	push   %rbp
  ffffffff8101f8d9:	48 89 e5             	mov    %rsp,%rbp
  ffffffff8101f8dc:	e8 1f 37 fe ff       	callq  ffffffff81003000 <___preempt_schedule>
  ffffffff8101f8e1:	5d                   	pop    %rbp
  ffffffff8101f8e2:	c3                   	retq

ffffffff8101f8e3: 66 66 66 66 2e 0f 1f data16 data16 data16 nopw %cs:0x0(%rax,%rax,1)
ffffffff8101f8ea: 84 00 00 00 00 00

Notice that it moved the frame pointer setup code to the unlikely ___preempt_schedule() call path. Going through a sampling of the differences in the asm, that's the most common change I see.

Otherwise it has no real effect on callers which already have stack frames (though it does result in the reordering of some 'mov's).

---
 arch/x86/include/asm/preempt.h | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
arch/x86/include/asm/preempt.h +11 -2
index 01bcde8..d397deb 100644
@@ -94,10 +94,19 @@ static __always_inline bool should_resched(int preempt_offset)
 
 #ifdef CONFIG_PREEMPT
   extern asmlinkage void ___preempt_schedule(void);
-# define __preempt_schedule() asm ("call ___preempt_schedule")
+# define __preempt_schedule()					\
+({								\
+	register void *__sp asm(_ASM_SP);			\
+	asm volatile ("call ___preempt_schedule" : "+r"(__sp));	\
+})
+
   extern asmlinkage void preempt_schedule(void);
   extern asmlinkage void ___preempt_schedule_notrace(void);
-# define __preempt_schedule_notrace() asm ("call ___preempt_schedule_notrace")
+# define __preempt_schedule_notrace()					\
+({									\
+	register void *__sp asm(_ASM_SP);				\
+	asm volatile ("call ___preempt_schedule_notrace" : "+r"(__sp));	\
+})
   extern asmlinkage void preempt_schedule_notrace(void);
 #endif
 
#126 lore raw
In reply to a message not in the archive
Quoted 6 lines
Quoted 3 lines

There are two ways to fix the warnings:

1. get rid of the thunks and call the C functions directly; or

No. Not until gcc learns about per-function callibg conventions (so that it can be marked as not clobbering registers).

It does already for static functions in 5.x (with -fipa-ra). And with LTO it can be used even somewhat globally.

Even older version supported it, for only for x86->SSE on 32bit, which is useless for the kernel. But the new IPA-RA propagates which registers are clobbered.

That said it will probably be a long time until we can drop support for older compilers. So for now the manual method is still needed.

-Andi

--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#127 lore raw
In reply to Josh Poimboeuf

So I tried out this latest stacktool series and it looks mostly good for an upstream merge.

To help this effort move forward I've applied the preparatory/fix patches that are part of this series to tip:x86/debug - that's 26 out of 31 patches. (I've propagated all the acks that the latest submission got into the changelogs.)

I have 5 (easy to address) observations that need to be addressed before we can move on with the rest of the merge:

1)

Due to recent changes to x86 exception handling, I get a lot of bogus warnings about exception table sizes:

stacktool: arch/x86/kernel/cpu/mcheck/mce.o: __ex_table size not a multiple of 24
stacktool: arch/x86/kernel/cpu/mtrr/generic.o: __ex_table size not a multiple of 24
stacktool: arch/x86/kernel/cpu/mtrr/cleanup.o: __ex_table size not a multiple of 24

this is due to:

548acf19234d x86/mm: Expand the exception table logic to allow new handling options

2)

The fact that 'stacktool' already checks about assembly details like __ex_table[] shows that my review feedback early iterations of this series, that the 'stacktool' name is too specific, was correct.

We really need to rename it before it gets upstream and the situation gets worse. __ex_table[] has obviously nothing to do with the 'stack layout' of binaries.

Another suitable name would be 'asmtool' or 'objtool'. For example the following would naturally express what it does:

objtool check kernel/built-in.o

the name expresses that the tool checks object files, independently of the existing toolchain. Its primary purpose right now is the checking of stack layout details, but the tool is not limited to that at all.

3)

There's quite a bit of overhead when running the tool on larger object files, most prominently in cmd_check():

    62.06%  stacktool        stacktool                              [.] cmd_check
     6.72%  stacktool        stacktool                              [.] find_rela_by_dest_range

I added -g to the CFLAGS, which made it visible to annotated output of perf top:

    0.00 :        40430d:       lea    0x4(%rdx,%rax,1),%r13
         :      find_instruction():
         :                                                  struct section *sec,
         :                                                  unsigned long offset)
         :      {
         :              struct instruction *insn;
         :
         :              list_for_each_entry(insn, &file->insns, list)
    0.03 :        404312:       mov    0x38(%rsp),%rax
    0.00 :        404317:       cmp    %rbp,%rax
    0.00 :        40431a:       jne    404334 <cmd_check+0x5b4>
    0.00 :        40431c:       jmpq   4045ba <cmd_check+0x83a>
    0.00 :        404321:       nopl   0x0(%rax)
    6.14 :        404328:       mov    (%rax),%rax
    0.00 :        40432b:       cmp    %rbp,%rax
    2.02 :        40432e:       je     4045ba <cmd_check+0x83a>
         :                      if (insn->sec == sec && insn->offset == offset)
    0.55 :        404334:       cmp    %r12,0x10(%rax)
   87.91 :        404338:       jne    404328 <cmd_check+0x5a8>
    0.00 :        40433a:       cmp    %r13,0x18(%rax)
    3.36 :        40433e:       jne    404328 <cmd_check+0x5a8>
         :      get_jump_destinations():
         :                               * later in validate_functions().
         :                               */
         :                              continue;
         :                      }
         :
         :                      insn->jump_dest = find_instruction(file, dest_sec, dest_off);
    0.00 :        404340:       mov    %rax,0x48(%rbx)
    0.00 :        404344:       jmpq   4042b0 <cmd_check+0x530>
    0.00 :        404349:       nopl   0x0(%rax)
         :      fprintf():
         :
         :      # ifdef __va_arg_pack
         :      __fortify_function int
         :      fprintf (FILE *__restrict __stream, const char *__restrict __fmt, ...)
         :      {
         :        return __fprintf_chk (__stream, __USE_FORTIFY_LEVEL - 1, __fmt,

that looks like a linear list search? That would suck with thousands of entries.

(If this is non-trivial to improve then we can delay this optimization to a later patch.)

4)

I think the various 'STACKTOOL' flags in the kernel source are a bit of a misnomer
- it's not the tool we want to name but the actual property of the code.

So instead of:

  STACKTOOL_IGNORE_FUNC(__bpf_prog_run);

we should do something like:

  STACK_FRAME_NON_STANDARD(__bpf_prog_run);

see how much more expressive it is? It becomes a function attribute independent of the tooling that makes use of it.

Similarly, for the highest level 'don't check these directories' makefile flags, I'd suggest, instead of using this rather opaque, tool dependent naming:

STACKTOOL := n

something more specific, like:

OBJECT_FILES_NON_STANDARD := y

which makes it clearer what's going on: these are special object files that are not the typical kernel object files.

Stacktool (or objtool) would be one consumer of this annotation.

I think Boris made similar observations in past reviews.

5)

Likewise, I think the CONFIG_STACK_VALIDATION=y Kconfig flag does not express that we do exception table checks as well - and it does not express all the other things we may check in object files in the future.

Something like CONFIG_CHECK_OBJECT_FILES=y would express it, and the help text would list all the things the tool is able to checks for at the moment.

-------------------

Please send followup iterations of the series against the tip:x86/debug tree (or tip:master), to keep the size of the series down.

Thanks,

Ingo

#128 lore raw

Em Tue, Feb 23, 2016 at 09:14:06AM +0100, Ingo Molnar escreveu:

Quoted 7 lines

The fact that 'stacktool' already checks about assembly details like __ex_table[] shows that my review feedback early iterations of this series, that the 'stacktool' name is too specific, was correct.

We really need to rename it before it gets upstream and the situation gets worse. __ex_table[] has obviously nothing to do with the 'stack layout' of binaries.

Quoted 8 lines

Another suitable name would be 'asmtool' or 'objtool'. For example the following would naturally express what it does:

objtool check kernel/built-in.o

the name expresses that the tool checks object files, independently of the existing toolchain. Its primary purpose right now is the checking of stack layout details, but the tool is not limited to that at all.

Removing 'tool' from the tool name would be nice too :-) Making it easily googlable would be good too, lotsa people complain about 'perf' being too vague, see for a quick laugher:

http://www.brendangregg.com/perf.html

``Searching for just "perf" finds sites on the police, petroleum, weed control, and a T-shirt. This is not an official perf page, for either perf_events or the T-shirt.''

The T-shirt: http://www.brendangregg.com/perf_events/omg-so-perf.jpg

Maybe we should ask Linus to come with some other nice, short, searchable, funny name like 'git'?

'chob' as in 'check object'?

- Arnaldo
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#129 lore raw
Quoted 21 lines · Arnaldo Carvalho de Melo

Em Tue, Feb 23, 2016 at 09:14:06AM +0100, Ingo Molnar escreveu:

Quoted 7 lines

The fact that 'stacktool' already checks about assembly details like __ex_table[] shows that my review feedback early iterations of this series, that the 'stacktool' name is too specific, was correct.

We really need to rename it before it gets upstream and the situation gets worse. __ex_table[] has obviously nothing to do with the 'stack layout' of binaries.

Quoted 8 lines

Another suitable name would be 'asmtool' or 'objtool'. For example the following would naturally express what it does:

objtool check kernel/built-in.o

the name expresses that the tool checks object files, independently of the existing toolchain. Its primary purpose right now is the checking of stack layout details, but the tool is not limited to that at all.

Removing 'tool' from the tool name would be nice too :-) Making it easily googlable would be good too, lotsa people complain about 'perf' being too vague, see for a quick laugher:

Quoted 7 lines

http://www.brendangregg.com/perf.html

``Searching for just "perf" finds sites on the police, petroleum, weed control, and a T-shirt. This is not an official perf page, for either perf_events or the T-shirt.''

The T-shirt: http://www.brendangregg.com/perf_events/omg-so-perf.jpg

Yeah, 'tool' in the name is kind of silly, but the above type of situation is why I prefer 'objtool' over 'obj'.

Though I have to admit I like the idea of making a t-shirt for it ;-)

Quoted 4 lines

Maybe we should ask Linus to come with some other nice, short, searchable, funny name like 'git'?

'chob' as in 'check object'?

I think 'objtool' is searchable enough. And I also like the fact that its name at least gives you an idea of what it does (and eventually it will do more than just "checking").

Signature · 1 line
Josh
#130 lore raw

Em Tue, Feb 23, 2016 at 09:07:55AM -0600, Josh Poimboeuf escreveu:

Quoted 1 line

I think 'objtool' is searchable enough. And I also like the fact that

Yeah, agreed, there is even documentation available for it already:

http://docs.bvstools.com/home/objtool

Quoted 2 lines

its name at least gives you an idea of what it does (and eventually it will do more than just "checking").

:-)

- ARnaldo

#131 lore raw
In reply to Ingo Molnar

Hi Ingo,

Quoted 6 lines · Ingo Molnar

So I tried out this latest stacktool series and it looks mostly good for an upstream merge.

To help this effort move forward I've applied the preparatory/fix patches that are part of this series to tip:x86/debug - that's 26 out of 31 patches. (I've propagated all the acks that the latest submission got into the changelogs.)

Thanks very much for your review and for applying the fixes!

A few issues relating to the merge:

- The tip:x86/debug branch fails to build because it depends on ec5186557abb ("x86/asm: Add C versions of frame pointer macros") which is in tip:x86/asm.

- As Pavel mentioned, the tip-bot seems to be spitting out garbage emails from:
=?UTF-8?B?dGlwLWJvdCBmb3IgSm9zaCBQb2ltYm9ldWYgPHRpcGJvdEB6eXRvci5jb20+?=@zytor.com.

Quoted 8 lines

I have 5 (easy to address) observations that need to be addressed before we can move on with the rest of the merge:

1)

Due to recent changes to x86 exception handling, I get a lot of bogus warnings about exception table sizes:

Quoted 7 lines

stacktool: arch/x86/kernel/cpu/mcheck/mce.o: __ex_table size not a multiple of 24
stacktool: arch/x86/kernel/cpu/mtrr/generic.o: __ex_table size not a multiple of 24
stacktool: arch/x86/kernel/cpu/mtrr/cleanup.o: __ex_table size not a multiple of 24

this is due to:

548acf19234d x86/mm: Expand the exception table logic to allow new handling options

Ok, I'll fix it up.

Quoted 9 lines

2)

The fact that 'stacktool' already checks about assembly details like __ex_table[] shows that my review feedback early iterations of this series, that the 'stacktool' name is too specific, was correct.

We really need to rename it before it gets upstream and the situation gets worse. __ex_table[] has obviously nothing to do with the 'stack layout' of binaries.

Quoted 8 lines

Another suitable name would be 'asmtool' or 'objtool'. For example the following would naturally express what it does:

objtool check kernel/built-in.o

the name expresses that the tool checks object files, independently of the existing toolchain. Its primary purpose right now is the checking of stack layout details, but the tool is not limited to that at all.

Fair enough. I'll rename it to objtool if there are no objections.

Quoted 49 lines

3)

There's quite a bit of overhead when running the tool on larger object files, most prominently in cmd_check():

    62.06%  stacktool        stacktool                              [.] cmd_check
     6.72%  stacktool        stacktool                              [.] find_rela_by_dest_range

I added -g to the CFLAGS, which made it visible to annotated output of perf top:

    0.00 :        40430d:       lea    0x4(%rdx,%rax,1),%r13
         :      find_instruction():
         :                                                  struct section *sec,
         :                                                  unsigned long offset)
         :      {
         :              struct instruction *insn;
         :
         :              list_for_each_entry(insn, &file->insns, list)
    0.03 :        404312:       mov    0x38(%rsp),%rax
    0.00 :        404317:       cmp    %rbp,%rax
    0.00 :        40431a:       jne    404334 <cmd_check+0x5b4>
    0.00 :        40431c:       jmpq   4045ba <cmd_check+0x83a>
    0.00 :        404321:       nopl   0x0(%rax)
    6.14 :        404328:       mov    (%rax),%rax
    0.00 :        40432b:       cmp    %rbp,%rax
    2.02 :        40432e:       je     4045ba <cmd_check+0x83a>
         :                      if (insn->sec == sec && insn->offset == offset)
    0.55 :        404334:       cmp    %r12,0x10(%rax)
   87.91 :        404338:       jne    404328 <cmd_check+0x5a8>
    0.00 :        40433a:       cmp    %r13,0x18(%rax)
    3.36 :        40433e:       jne    404328 <cmd_check+0x5a8>
         :      get_jump_destinations():
         :                               * later in validate_functions().
         :                               */
         :                              continue;
         :                      }
         :
         :                      insn->jump_dest = find_instruction(file, dest_sec, dest_off);
    0.00 :        404340:       mov    %rax,0x48(%rbx)
    0.00 :        404344:       jmpq   4042b0 <cmd_check+0x530>
    0.00 :        404349:       nopl   0x0(%rax)
         :      fprintf():
         :
         :      # ifdef __va_arg_pack
         :      __fortify_function int
         :      fprintf (FILE *__restrict __stream, const char *__restrict __fmt, ...)
         :      {
         :        return __fprintf_chk (__stream, __USE_FORTIFY_LEVEL - 1, __fmt,
Quoted 4 lines

that looks like a linear list search? That would suck with thousands of entries.

(If this is non-trivial to improve then we can delay this optimization to a later patch.)

Yeah, I agree that the linear list search isn't good. I still need to think about the data structures a bit, so if it's ok with you, I'll fix it with a later patch.

Quoted 7 lines

4)

I think the various 'STACKTOOL' flags in the kernel source are a bit of a misnomer
- it's not the tool we want to name but the actual property of the code.

So instead of:

Quoted 8 lines
  STACKTOOL_IGNORE_FUNC(__bpf_prog_run);

we should do something like:

  STACK_FRAME_NON_STANDARD(__bpf_prog_run);

see how much more expressive it is? It becomes a function attribute independent of the tooling that makes use of it.

Ok, STACK_FRAME_NON_STANDARD sounds fine to me.

Quoted 7 lines

Similarly, for the highest level 'don't check these directories' makefile flags, I'd suggest, instead of using this rather opaque, tool dependent naming:

STACKTOOL := n

something more specific, like:

Quoted 8 lines

OBJECT_FILES_NON_STANDARD := y

which makes it clearer what's going on: these are special object files that are not the typical kernel object files.

Stacktool (or objtool) would be one consumer of this annotation.

I think Boris made similar observations in past reviews.

Sounds reasonable. With this approach we could probably eventually get rid of KASAN_SANITIZE.

I'll change it to "OBJECT_FILES_NON_STANDARD := y" if there are no objections.

Note there are also per-object ignores like:

  STACKTOOL_head_$(BITS).o := n

I can similarly change that to something like:

  OBJECT_FILES_NON_STANDARD_head_$(BITS).o := n
Quoted 8 lines

5)

Likewise, I think the CONFIG_STACK_VALIDATION=y Kconfig flag does not express that we do exception table checks as well - and it does not express all the other things we may check in object files in the future.

Something like CONFIG_CHECK_OBJECT_FILES=y would express it, and the help text would list all the things the tool is able to checks for at the moment.

Hm, I'm not really sure about this. Yes, the tool could potentially do other types of checks, but is it necessary to lump them all together into a single config option? It does have subcommands after all ;-)

The exception table check reported above is very basic and doesn't serve any useful purpose other than supporting the goal of validating the stack.

However, I don't feel strong enough about it to hold up the merge any longer, so I'll plan to make the change unless I hear back from you.

Quoted 2 lines

Please send followup iterations of the series against the tip:x86/debug tree (or tip:master), to keep the size of the series down.

Will do, thanks!

Signature · 1 line
Josh
#132 lore raw
Quoted 10 lines · Josh Poimboeuf

Hi Ingo,

Quoted 6 lines · Ingo Molnar

So I tried out this latest stacktool series and it looks mostly good for an upstream merge.

To help this effort move forward I've applied the preparatory/fix patches that are part of this series to tip:x86/debug - that's 26 out of 31 patches. (I've propagated all the acks that the latest submission got into the changelogs.)

Quoted 7 lines

Thanks very much for your review and for applying the fixes!

A few issues relating to the merge:

- The tip:x86/debug branch fails to build because it depends on ec5186557abb ("x86/asm: Add C versions of frame pointer macros") which is in tip:x86/asm.

Indeed...

Quoted 3 lines

- As Pavel mentioned, the tip-bot seems to be spitting out garbage emails from:
=?UTF-8?B?dGlwLWJvdCBmb3IgSm9zaCBQb2ltYm9ldWYgPHRpcGJvdEB6eXRvci5jb20+?=@zytor.com.

Yeah, hpa fixed that meanwhile.

Due to the above bad base I rebased the tree (to a x86/asm base), so there will be a new round of (hopefully readable) tip-bot notifications. I'll push it out after a bit of testing.

Quoted 6 lines
Quoted 6 lines

5)

Likewise, I think the CONFIG_STACK_VALIDATION=y Kconfig flag does not express that we do exception table checks as well - and it does not express all the other things we may check in object files in the future.

Quoted 6 lines
Quoted 2 lines

Something like CONFIG_CHECK_OBJECT_FILES=y would express it, and the help text would list all the things the tool is able to checks for at the moment.

Hm, I'm not really sure about this. Yes, the tool could potentially do other types of checks, but is it necessary to lump them all together into a single config option? It does have subcommands after all ;-)

lol ;-)

Ok, I'm fine with CONFIG_STACK_VALIDATION=y as well.

Thanks,

Ingo

#133 lore raw
Quoted 15 lines · Ingo Molnar
Quoted 12 lines · Josh Poimboeuf

Hi Ingo,

Quoted 6 lines · Ingo Molnar

So I tried out this latest stacktool series and it looks mostly good for an upstream merge.

To help this effort move forward I've applied the preparatory/fix patches that are part of this series to tip:x86/debug - that's 26 out of 31 patches. (I've propagated all the acks that the latest submission got into the changelogs.)

Thanks very much for your review and for applying the fixes!

Quoted 7 lines
Quoted 5 lines

A few issues relating to the merge:

- The tip:x86/debug branch fails to build because it depends on ec5186557abb ("x86/asm: Add C versions of frame pointer macros") which is in tip:x86/asm.

Indeed...

FYI, v17 will be based on tip:x86/debug. But note that, when run against that branch, it'll spit out a lot of these warnings:

objtool: arch/x86/ia32/sys_ia32.o: __ex_table size not a multiple of 12
objtool: arch/x86/ia32/ia32_signal.o: __ex_table size not a multiple of 12
objtool: arch/x86/entry/common.o: __ex_table size not a multiple of 12

Those warnings mean it's expecting the new exception table format which was added in:

548acf19234d ("x86/mm: Expand the exception table logic to allow new handling options")

So that commit is needed to avoid the warnings.

Thanks!

Signature · 5 lines
Josh
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html