linux-stable/arch
Mark Rutland e7308391df arm64: stackleak: fix current_top_of_stack()
[ Upstream commit e85094c31d ]

Due to some historical confusion, arm64's current_top_of_stack() isn't
what the stackleak code expects. This could in theory result in a number
of problems, and practically results in an unnecessary performance hit.
We can avoid this by aligning the arm64 implementation with the x86
implementation.

The arm64 implementation of current_top_of_stack() was added
specifically for stackleak in commit:

  0b3e336601 ("arm64: Add support for STACKLEAK gcc plugin")

This was intended to be equivalent to the x86 implementation, but the
implementation, semantics, and performance characteristics differ
wildly:

* On x86, current_top_of_stack() returns the top of the current task's
  task stack, regardless of which stack is in active use.

  The implementation accesses a percpu variable which the x86 entry code
  maintains, and returns the location immediately above the pt_regs on
  the task stack (above which x86 has some padding).

* On arm64 current_top_of_stack() returns the top of the stack in active
  use (i.e. the one which is currently being used).

  The implementation checks the SP against a number of
  potentially-accessible stacks, and will BUG() if no stack is found.

The core stackleak_erase() code determines the upper bound of stack to
erase with:

| if (on_thread_stack())
|         boundary = current_stack_pointer;
| else
|         boundary = current_top_of_stack();

On arm64 stackleak_erase() is always called on a task stack, and
on_thread_stack() should always be true. On x86, stackleak_erase() is
mostly called on a trampoline stack, and is sometimes called on a task
stack.

Currently, this results in a lot of unnecessary code being generated for
arm64 for the impossible !on_thread_stack() case. Some of this is
inlined, bloating stackleak_erase(), while portions of this are left
out-of-line and permitted to be instrumented (which would be a
functional problem if that code were reachable).

As a first step towards improving this, this patch aligns arm64's
implementation of current_top_of_stack() with x86's, always returning
the top of the current task's stack. With GCC 11.1.0 this results in the
bulk of the unnecessary code being removed, including all of the
out-of-line instrumentable code.

While I don't believe there's a functional problem in practice I've
marked this as a fix since the semantic was clearly wrong, the fix
itself is simple, and other code might rely upon this in future.

Fixes: 0b3e336601 ("arm64: Add support for STACKLEAK gcc plugin")
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Alexander Popov <alex.popov@linux.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Will Deacon <will@kernel.org>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20220427173128.2603085-2-mark.rutland@arm.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
2022-06-09 10:22:55 +02:00
..
alpha alpha: fix alloc_zeroed_user_highpage_movable() 2022-06-09 10:22:43 +02:00
arc ARC: entry: fix syscall_trace_exit argument 2022-04-27 14:39:00 +02:00
arm signal: Deliver SIGTRAP on perf event asynchronously if blocked 2022-06-09 10:22:48 +02:00
arm64 arm64: stackleak: fix current_top_of_stack() 2022-06-09 10:22:55 +02:00
csky uaccess: fix type mismatch warnings from access_ok() 2022-04-08 14:24:01 +02:00
h8300
hexagon uaccess: fix integer overflow on access_ok() 2022-03-28 09:58:45 +02:00
ia64 ia64: define get_cycles macro for arch-override 2022-05-30 09:29:12 +02:00
m68k signal: Deliver SIGTRAP on perf event asynchronously if blocked 2022-06-09 10:22:48 +02:00
microblaze uaccess: fix nios2 and microblaze get_user_8() 2022-04-08 14:23:18 +02:00
mips mips: use fallback for random_get_entropy() instead of just c0 random 2022-05-30 09:29:13 +02:00
nds32 nds32: fix access_ok() checks in get/put_user 2022-03-28 09:58:46 +02:00
nios2 nios2: use fallback for random_get_entropy() instead of zero 2022-05-30 09:29:14 +02:00
openrisc openrisc: start CPU timer early in boot 2022-06-09 10:22:38 +02:00
parisc parisc/stifb: Implement fb_is_primary_device() 2022-06-09 10:22:26 +02:00
powerpc powerpc/iommu: Add missing of_node_put in iommu_init_early_dart 2022-06-09 10:22:43 +02:00
riscv riscv: Move alternative length validation into subsection 2022-06-09 10:22:27 +02:00
s390 s390/preempt: disable __preempt_count_add() optimization for PROFILE_ALL_BRANCHES 2022-06-09 10:22:36 +02:00
sh
sparc signal: Deliver SIGTRAP on perf event asynchronously if blocked 2022-06-09 10:22:48 +02:00
um ptrace/um: Replace PT_DTRACE with TIF_SINGLESTEP 2022-06-09 10:22:29 +02:00
x86 x86/mm: Cleanup the control_va_addr_alignment() __setup handler 2022-06-09 10:22:54 +02:00
xtensa ptrace/xtensa: Replace PT_SINGLESTEP with TIF_SINGLESTEP 2022-06-09 10:22:29 +02:00
.gitignore
Kconfig stack: Constrain and fix stack offset randomization with Clang builds 2022-04-08 14:23:06 +02:00