All of lore.kernel.org
 help / color / mirror / Atom feed
From: Borislav Petkov <bp@alien8.de>
To: Alexander Popov <alex.popov@linux.com>
Cc: kernel-hardening@lists.openwall.com,
	Kees Cook <keescook@chromium.org>,
	PaX Team <pageexec@freemail.hu>,
	Brad Spengler <spender@grsecurity.net>,
	Ingo Molnar <mingo@kernel.org>, Andy Lutomirski <luto@kernel.org>,
	Tycho Andersen <tycho@tycho.ws>,
	Laura Abbott <labbott@redhat.com>,
	Mark Rutland <mark.rutland@arm.com>,
	Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	"H . Peter Anvin" <hpa@zytor.com>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	"Dmitry V . Levin" <ldv@altlinux.org>,
	x86@kernel.org
Subject: Re: [PATCH RFC v8 1/6] x86/entry: Add STACKLEAK erasing the kernel stack at the end of syscalls
Date: Wed, 21 Feb 2018 14:24:43 +0100	[thread overview]
Message-ID: <20180221132443.GA9989@pd.tnic> (raw)
In-Reply-To: <1518804657-24905-2-git-send-email-alex.popov@linux.com>

On Fri, Feb 16, 2018 at 09:10:52PM +0300, Alexander Popov wrote:
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 63bf349..62748bd 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -119,6 +119,7 @@ config X86
>  	select HAVE_ARCH_COMPAT_MMAP_BASES	if MMU && COMPAT
>  	select HAVE_ARCH_SECCOMP_FILTER
>  	select HAVE_ARCH_THREAD_STRUCT_WHITELIST
> +	select HAVE_ARCH_STACKLEAK
>  	select HAVE_ARCH_TRACEHOOK
>  	select HAVE_ARCH_TRANSPARENT_HUGEPAGE
>  	select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if X86_64
> diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
> index 16c2c02..4a7365a 100644
> --- a/arch/x86/entry/entry_32.S
> +++ b/arch/x86/entry/entry_32.S
> @@ -77,6 +77,90 @@
>  #endif
>  .endm
>  
> +.macro erase_kstack
> +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
> +	call erase_kstack

Hmm, why do we need a macro *and* a function of the same name? Why not do

	call erase_kstack

everywhere we need to?

And then do

ENTRY(erase_kstack)
#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
	...

to tone down the ifdeffery.

> +#endif
> +.endm
> +
> +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
> +ENTRY(erase_kstack)
> +	pushl	%edi
> +	pushl	%ecx
> +	pushl	%eax
> +	pushl	%ebp
> +
> +	movl	PER_CPU_VAR(current_task), %ebp
> +	mov	TASK_lowest_stack(%ebp), %edi

So instead of TASK_lowest_stack and adding all the ifdeffery around, why
not do this computation:

	(unsigned long)task_stack_page(p) + 2 * sizeof(unsigned long);

in asm?

You only need task->stack as an offset variable. And other code might
need it too, anyway so you could just as well use it instead of adding
another var to thread_struct.

/me reads further.

Ah. So this lowest_stack thing changes at the end:

	"Set the lowest_stack value to the top_of_stack - 256"

Why?

So that magic needs more explanation for slow people like me.

> +	mov	$STACKLEAK_POISON, %eax
> +	std
> +
> +	/*
> +	 * Let's search for the poison value in the stack.
> +	 * Start from the lowest_stack and go to the bottom (see std above).

Let's write insns capitalized: "see STD above".

...

> +	/*
> +	 * Check that some further qwords contain poison. If so, the part
> +	 * of the stack below the address in %rdi is likely to be poisoned.
> +	 * Otherwise we need to search deeper.
> +	 */
> +	mov	$STACKLEAK_POISON_CHECK_DEPTH / 8, %ecx
> +	repe	scasq
> +	jecxz	2f	/* Poison the upper part of the stack */
> +	jne	1b	/* Search deeper */
> +
> +2:

You could name that label

.Lpoison

and make the code more readable:

	jb	.Lpoison

and so on.

> +	/*
> +	 * Two qwords at the bottom of the thread stack are reserved and
> +	 * should not be poisoned (see CONFIG_SCHED_STACK_END_CHECK).
> +	 */
> +	or	$2 * 8, %rdi
> +
> +	/*
> +	 * Check whether we are on the thread stack to prepare the counter
> +	 * for stack poisoning.
> +	 */
> +	mov	PER_CPU_VAR(cpu_current_top_of_stack), %rcx
> +	sub	%rsp, %rcx
> +	cmp	$THREAD_SIZE_asm, %rcx
> +	jb	3f
> +
> +	/*
> +	 * We are not on the thread stack, so we can write poison between
> +	 * the address in %rdi and the stack top.
> +	 */
> +	mov	PER_CPU_VAR(cpu_current_top_of_stack), %rcx
> +	sub	%rdi, %rcx
> +	jmp	4f
> +
> +3:
> +	/*
> +	 * We are on the thread stack, so we can write poison between the
> +	 * address in %rdi and the address in %rsp (not included, used memory).
> +	 */
> +	mov	%rsp, %rcx
> +	sub	%rdi, %rcx
> +
> +4:
> +	/* Check that the counter value is sane */
> +	cmp	$THREAD_SIZE_asm, %rcx
> +	jb	5f
> +	ud2
> +
> +5:
> +	/*
> +	 * So let's write the poison value to the kernel stack. Start from the
> +	 * address in %rdi and move up (see cld).
> +	 */
> +	cld
> +	shr	$3, %ecx
> +	rep	stosq

Hohumm, that's >2K loops per syscall here and stack is

0xffffc90000008010:     0xffffffffffff4111      0xffffffffffff4111
0xffffc90000008020:     0xffffffffffff4111      0xffffffffffff4111
0xffffc90000008030:     0xffffffffffff4111      0xffffffffffff4111
0xffffc90000008040:     0xffffffffffff4111      0xffffffffffff4111
0xffffc90000008050:     0xffffffffffff4111      0xffffffffffff4111
0xffffc90000008060:     0xffffffffffff4111      0xffffffffffff4111
...

> diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
> index 9eb448c..6dc55f6 100644
> --- a/arch/x86/kernel/process_64.c
> +++ b/arch/x86/kernel/process_64.c
> @@ -281,6 +281,11 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
>  	p->thread.sp = (unsigned long) fork_frame;
>  	p->thread.io_bitmap_ptr = NULL;
>  
> +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
> +	p->thread.lowest_stack = (unsigned long)task_stack_page(p) +
> +						2 * sizeof(unsigned long);
> +#endif
> +
>  	savesegment(gs, p->thread.gsindex);
>  	p->thread.gsbase = p->thread.gsindex ? 0 : me->thread.gsbase;
>  	savesegment(fs, p->thread.fsindex);
> diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> index e835fc0..fe04f60 100644
> --- a/include/linux/compiler.h
> +++ b/include/linux/compiler.h
> @@ -337,4 +337,10 @@ unsigned long read_word_at_a_time(const void *addr)
>  	compiletime_assert(__native_word(t),				\
>  		"Need native word sized stores/loads for atomicity.")
>  
> +#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
> +/* Poison value points to the unused hole in the virtual memory map */

There are a bunch of those there now. Please document it in
Documentation/x86/x86_64/mm.txt

> +# define STACKLEAK_POISON -0xBEEF
> +# define STACKLEAK_POISON_CHECK_DEPTH 128
> +#endif
> +
>  #endif /* __LINUX_COMPILER_H */
> -- 
> 2.7.4
> 

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

  reply	other threads:[~2018-02-21 13:24 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-16 18:10 [PATCH RFC v8 0/6] Introduce the STACKLEAK feature and a test for it Alexander Popov
2018-02-16 18:10 ` [PATCH RFC v8 1/6] x86/entry: Add STACKLEAK erasing the kernel stack at the end of syscalls Alexander Popov
2018-02-21 13:24   ` Borislav Petkov [this message]
2018-02-21 21:49     ` Alexander Popov
2018-02-22 19:14       ` Borislav Petkov
2018-02-22 20:24         ` Alexander Popov
2018-02-16 18:10 ` [PATCH RFC v8 2/6] gcc-plugins: Add STACKLEAK plugin for tracking the kernel stack Alexander Popov
2018-02-16 18:10 ` [PATCH RFC v8 3/6] x86/entry: Erase kernel stack in syscall_trace_enter() Alexander Popov
2018-02-16 18:10 ` [PATCH RFC v8 4/6] lkdtm: Add a test for STACKLEAK Alexander Popov
2018-02-16 18:10 ` [PATCH RFC v8 5/6] fs/proc: Show STACKLEAK metrics in the /proc file system Alexander Popov
2018-02-16 18:10 ` [PATCH RFC v8 6/6] doc: self-protection: Add information about STACKLEAK feature Alexander Popov
2018-02-20 10:29 ` [PATCH RFC v8 0/6] Introduce the STACKLEAK feature and a test for it Alexander Popov
2018-02-20 23:17   ` Kees Cook
2018-02-20 23:33     ` Laura Abbott
2018-02-21  1:13       ` [PATCH 0/2] Stackleak for arm64 Laura Abbott
2018-02-21  1:13         ` Laura Abbott
2018-02-21  1:13         ` [PATCH 1/2] stackleak: Update " Laura Abbott
2018-02-21  1:13           ` Laura Abbott
2018-02-22 16:58           ` Will Deacon
2018-02-22 16:58             ` Will Deacon
2018-02-22 19:22             ` Alexander Popov
2018-02-22 19:22               ` Alexander Popov
2018-02-27 10:21               ` Richard Sandiford
2018-02-27 10:21                 ` Richard Sandiford
2018-02-27 10:21                 ` Richard Sandiford
2018-02-28 15:09                 ` Alexander Popov
2018-02-28 15:09                   ` Alexander Popov
2018-03-01 10:33                   ` Richard Sandiford
2018-03-01 10:33                     ` Richard Sandiford
2018-03-01 10:33                     ` Richard Sandiford
2018-03-02 11:14                     ` Alexander Popov
2018-03-02 11:14                       ` Alexander Popov
2018-02-22 19:38             ` Laura Abbott
2018-02-22 19:38               ` Laura Abbott
2018-02-21  1:13         ` [PATCH 2/2] arm64: Clear the stack Laura Abbott
2018-02-21  1:13           ` Laura Abbott
2018-02-21 15:38           ` Mark Rutland
2018-02-21 15:38             ` Mark Rutland
2018-02-21 23:53             ` Laura Abbott
2018-02-21 23:53               ` Laura Abbott
2018-02-22  1:35               ` Laura Abbott
2018-02-22  1:35                 ` Laura Abbott
2018-02-21 14:48         ` [PATCH 0/2] Stackleak for arm64 Alexander Popov
2018-02-21 14:48           ` Alexander Popov
2018-02-21 10:05     ` [PATCH RFC v8 0/6] Introduce the STACKLEAK feature and a test for it Borislav Petkov
2018-02-21 15:09       ` Alexander Popov
2018-02-21 14:43     ` Alexander Popov
2018-02-22  1:43 ` Laura Abbott
2018-02-22 23:14   ` [PATCH 0/2] Update stackleak for gcc-8 Laura Abbott
2018-02-22 23:14     ` [PATCH 1/2] gcc-plugins: Update cgraph_create_edge " Laura Abbott
2018-02-22 23:40       ` Kees Cook
2018-02-23 17:30         ` Laura Abbott
2018-02-24 12:36           ` Alexander Popov
2018-02-22 23:14     ` [PATCH 2/2] gcc-plugins: stackleak: Update " Laura Abbott
2018-02-24 14:04       ` Alexander Popov
2018-02-26 21:51         ` Laura Abbott
2018-02-27 10:30           ` Richard Sandiford
2018-02-28 10:27             ` Alexander Popov
2018-02-22 23:43     ` [PATCH 0/2] Update stackleak " Kees Cook

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180221132443.GA9989@pd.tnic \
    --to=bp@alien8.de \
    --cc=a.p.zijlstra@chello.nl \
    --cc=alex.popov@linux.com \
    --cc=ard.biesheuvel@linaro.org \
    --cc=hpa@zytor.com \
    --cc=keescook@chromium.org \
    --cc=kernel-hardening@lists.openwall.com \
    --cc=labbott@redhat.com \
    --cc=ldv@altlinux.org \
    --cc=luto@kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@kernel.org \
    --cc=pageexec@freemail.hu \
    --cc=spender@grsecurity.net \
    --cc=tglx@linutronix.de \
    --cc=tycho@tycho.ws \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.