20 Sep, 2020

1 commit

  • Commit 32927393dc1c ("sysctl: pass kernel pointers to ->proc_handler")
    changed ctl_table.proc_handler to take a kernel pointer. Adjust the
    signature of stack_erasing_sysctl to match ctl_table.proc_handler which
    fixes the following sparse warning:

    kernel/stackleak.c:31:50: warning: incorrect type in argument 3 (different address spaces)
    kernel/stackleak.c:31:50: expected void *
    kernel/stackleak.c:31:50: got void [noderef] __user *buffer

    Fixes: 32927393dc1c ("sysctl: pass kernel pointers to ->proc_handler")
    Signed-off-by: Tobias Klauser
    Signed-off-by: Andrew Morton
    Cc: Christoph Hellwig
    Cc: Al Viro
    Link: https://lkml.kernel.org/r/20200907093253.13656-1-tklauser@distanz.ch
    Signed-off-by: Linus Torvalds

    Tobias Klauser
     

24 Jun, 2020

1 commit

  • The kernel code instrumentation in stackleak gcc plugin works in two stages.
    At first, stack tracking is added to GIMPLE representation of every function
    (except some special cases). And later, when stack frame size info is
    available, stack tracking is removed from the RTL representation of the
    functions with small stack frame. There is an unwanted side-effect for these
    functions: some of them do useless work with caller-saved registers.

    As an example of such case, proc_sys_write without() instrumentation:
    55 push %rbp
    41 b8 01 00 00 00 mov $0x1,%r8d
    48 89 e5 mov %rsp,%rbp
    e8 11 ff ff ff callq ffffffff81284610
    5d pop %rbp
    c3 retq
    0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
    66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
    00 00 00

    proc_sys_write() with instrumentation:
    55 push %rbp
    48 89 e5 mov %rsp,%rbp
    41 56 push %r14
    41 55 push %r13
    41 54 push %r12
    53 push %rbx
    49 89 f4 mov %rsi,%r12
    48 89 fb mov %rdi,%rbx
    49 89 d5 mov %rdx,%r13
    49 89 ce mov %rcx,%r14
    4c 89 f1 mov %r14,%rcx
    4c 89 ea mov %r13,%rdx
    4c 89 e6 mov %r12,%rsi
    48 89 df mov %rbx,%rdi
    41 b8 01 00 00 00 mov $0x1,%r8d
    e8 f2 fe ff ff callq ffffffff81298e80
    5b pop %rbx
    41 5c pop %r12
    41 5d pop %r13
    41 5e pop %r14
    5d pop %rbp
    c3 retq
    66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
    00 00

    Let's improve the instrumentation to avoid this:

    1. Make stackleak_track_stack() save all register that it works with.
    Use no_caller_saved_registers attribute for that function. This attribute
    is available for x86_64 and i386 starting from gcc-7.

    2. Insert calling stackleak_track_stack() in asm:
    asm volatile("call stackleak_track_stack" :: "r" (current_stack_pointer))
    Here we use ASM_CALL_CONSTRAINT trick from arch/x86/include/asm/asm.h.
    The input constraint is taken into account during gcc shrink-wrapping
    optimization. It is needed to be sure that stackleak_track_stack() call is
    inserted after the prologue of the containing function, when the stack
    frame is prepared.

    This work is a deep reengineering of the idea described on grsecurity blog
    https://grsecurity.net/resolving_an_unfortunate_stackleak_interaction

    Signed-off-by: Alexander Popov
    Acked-by: Miguel Ojeda
    Link: https://lore.kernel.org/r/20200624123330.83226-5-alex.popov@linux.com
    Signed-off-by: Kees Cook

    Alexander Popov
     

06 Dec, 2018

1 commit

  • Function graph tracing recurses into itself when stackleak is enabled,
    causing the ftrace graph selftest to run for up to 90 seconds and
    trigger the softlockup watchdog.

    Breakpoint 2, ftrace_graph_caller () at ../arch/arm64/kernel/entry-ftrace.S:200
    200 mcount_get_lr_addr x0 // pointer to function's saved lr
    (gdb) bt
    \#0 ftrace_graph_caller () at ../arch/arm64/kernel/entry-ftrace.S:200
    \#1 0xffffff80081d5280 in ftrace_caller () at ../arch/arm64/kernel/entry-ftrace.S:153
    \#2 0xffffff8008555484 in stackleak_track_stack () at ../kernel/stackleak.c:106
    \#3 0xffffff8008421ff8 in ftrace_ops_test (ops=0xffffff8009eaa840 , ip=18446743524091297036, regs=) at ../kernel/trace/ftrace.c:1507
    \#4 0xffffff8008428770 in __ftrace_ops_list_func (regs=, ignored=, parent_ip=, ip=) at ../kernel/trace/ftrace.c:6286
    \#5 ftrace_ops_no_ops (ip=18446743524091297036, parent_ip=18446743524091242824) at ../kernel/trace/ftrace.c:6321
    \#6 0xffffff80081d5280 in ftrace_caller () at ../arch/arm64/kernel/entry-ftrace.S:153
    \#7 0xffffff800832fd10 in irq_find_mapping (domain=0xffffffc03fc4bc80, hwirq=27) at ../kernel/irq/irqdomain.c:876
    \#8 0xffffff800832294c in __handle_domain_irq (domain=0xffffffc03fc4bc80, hwirq=27, lookup=true, regs=0xffffff800814b840) at ../kernel/irq/irqdesc.c:650
    \#9 0xffffff80081d52b4 in ftrace_graph_caller () at ../arch/arm64/kernel/entry-ftrace.S:205

    Rework so we mark stackleak_track_stack as notrace

    Co-developed-by: Arnd Bergmann
    Signed-off-by: Arnd Bergmann
    Signed-off-by: Anders Roxell
    Acked-by: Steven Rostedt (VMware)
    Signed-off-by: Kees Cook

    Anders Roxell
     

01 Dec, 2018

1 commit

  • The stackleak_erase() function is called on the trampoline stack at the
    end of syscall. This stack is not big enough for ftrace and kprobes
    operations, e.g. it can be exhausted if we use kprobe_events for
    stackleak_erase().

    So let's disable function tracing and kprobes of stackleak_erase().

    Reported-by: kernel test robot
    Fixes: 10e9ae9fabaf ("gcc-plugins: Add STACKLEAK plugin for tracking the kernel stack")
    Signed-off-by: Alexander Popov
    Reviewed-by: Steven Rostedt (VMware)
    Reviewed-by: Masami Hiramatsu
    Signed-off-by: Kees Cook

    Alexander Popov
     

05 Sep, 2018

4 commits

  • Introduce CONFIG_STACKLEAK_RUNTIME_DISABLE option, which provides
    'stack_erasing' sysctl. It can be used in runtime to control kernel
    stack erasing for kernels built with CONFIG_GCC_PLUGIN_STACKLEAK.

    Suggested-by: Ingo Molnar
    Signed-off-by: Alexander Popov
    Tested-by: Laura Abbott
    Signed-off-by: Kees Cook

    Alexander Popov
     
  • Introduce CONFIG_STACKLEAK_METRICS providing STACKLEAK information about
    tasks via the /proc file system. In particular, /proc//stack_depth
    shows the maximum kernel stack consumption for the current and previous
    syscalls. Although this information is not precise, it can be useful for
    estimating the STACKLEAK performance impact for your workloads.

    Suggested-by: Ingo Molnar
    Signed-off-by: Alexander Popov
    Tested-by: Laura Abbott
    Signed-off-by: Kees Cook

    Alexander Popov
     
  • The STACKLEAK feature erases the kernel stack before returning from
    syscalls. That reduces the information which kernel stack leak bugs can
    reveal and blocks some uninitialized stack variable attacks.

    This commit introduces the STACKLEAK gcc plugin. It is needed for
    tracking the lowest border of the kernel stack, which is important
    for the code erasing the used part of the kernel stack at the end
    of syscalls (comes in a separate commit).

    The STACKLEAK feature is ported from grsecurity/PaX. More information at:
    https://grsecurity.net/
    https://pax.grsecurity.net/

    This code is modified from Brad Spengler/PaX Team's code in the last
    public patch of grsecurity/PaX based on our understanding of the code.
    Changes or omissions from the original code are ours and don't reflect
    the original grsecurity/PaX code.

    Signed-off-by: Alexander Popov
    Tested-by: Laura Abbott
    Signed-off-by: Kees Cook

    Alexander Popov
     
  • The STACKLEAK feature (initially developed by PaX Team) has the following
    benefits:

    1. Reduces the information that can be revealed through kernel stack leak
    bugs. The idea of erasing the thread stack at the end of syscalls is
    similar to CONFIG_PAGE_POISONING and memzero_explicit() in kernel
    crypto, which all comply with FDP_RIP.2 (Full Residual Information
    Protection) of the Common Criteria standard.

    2. Blocks some uninitialized stack variable attacks (e.g. CVE-2017-17712,
    CVE-2010-2963). That kind of bugs should be killed by improving C
    compilers in future, which might take a long time.

    This commit introduces the code filling the used part of the kernel
    stack with a poison value before returning to userspace. Full
    STACKLEAK feature also contains the gcc plugin which comes in a
    separate commit.

    The STACKLEAK feature is ported from grsecurity/PaX. More information at:
    https://grsecurity.net/
    https://pax.grsecurity.net/

    This code is modified from Brad Spengler/PaX Team's code in the last
    public patch of grsecurity/PaX based on our understanding of the code.
    Changes or omissions from the original code are ours and don't reflect
    the original grsecurity/PaX code.

    Performance impact:

    Hardware: Intel Core i7-4770, 16 GB RAM

    Test #1: building the Linux kernel on a single core
    0.91% slowdown

    Test #2: hackbench -s 4096 -l 2000 -g 15 -f 25 -P
    4.2% slowdown

    So the STACKLEAK description in Kconfig includes: "The tradeoff is the
    performance impact: on a single CPU system kernel compilation sees a 1%
    slowdown, other systems and workloads may vary and you are advised to
    test this feature on your expected workload before deploying it".

    Signed-off-by: Alexander Popov
    Acked-by: Thomas Gleixner
    Reviewed-by: Dave Hansen
    Acked-by: Ingo Molnar
    Signed-off-by: Kees Cook

    Alexander Popov