All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] x86/mm/fault: Allow stack access below %rsp
@ 2018-11-06 20:12 Waiman Long
  2018-11-06 20:14 ` Waiman Long
  2018-11-12 10:33 ` [tip:x86/mm] " tip-bot for Waiman Long
  0 siblings, 2 replies; 3+ messages in thread
From: Waiman Long @ 2018-11-06 20:12 UTC (permalink / raw)
  To: Dave Hansen, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov
  Cc: H. Peter Anvin, x86, linux-kernel, Waiman Long

The current x86 page fault handler allows stack access below the stack
pointer if it is no more than 64k+256 bytes. Any access beyond the 64k+
limit will cause a segmentation fault.

The gcc -fstack-check option generates code to probe the stack for
large stack allocation to see if the stack is accessible. The newer gcc
does that while updating the %rsp simultaneously. Older gcc's like gcc4
doesn't do that. As a result, an application compiled with an old gcc
and the -fstack-check option may fail to start at all.

% cat test.c
int main() {
	char tmp[1024*128];
	printf("### ok\n");
	return 0;
}
% gcc -fstack-check -g -o test test.c
% ./test
Segmentation fault

The old binary was working in older kernels where expand_stack() was
somehow called before the check. But it is not working in newer kernels.
Besides, the 64k+ limit check is kind of crude and will not catch a
lot of mistakes that userspace applications may be misbehaving anyway.
I think the kernel isn't the right place for this kind of tests. We
should leave it to userspace instrumentation tools to perform them.

The 64k+ limit check is now removed to just let expand_stack() decide
if a segmentation fault should happen, when the RLIMIT_STACK limit is
exceeded, for example.

Signed-off-by: Waiman Long <longman@redhat.com>
---
 arch/x86/mm/fault.c | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 71d4b9d..29525cf 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1380,18 +1380,6 @@ void do_user_addr_fault(struct pt_regs *regs,
 		bad_area(regs, sw_error_code, address);
 		return;
 	}
-	if (sw_error_code & X86_PF_USER) {
-		/*
-		 * Accessing the stack below %sp is always a bug.
-		 * The large cushion allows instructions like enter
-		 * and pusha to work. ("enter $65535, $31" pushes
-		 * 32 pointers and then decrements %sp by 65535.)
-		 */
-		if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < regs->sp)) {
-			bad_area(regs, sw_error_code, address);
-			return;
-		}
-	}
 	if (unlikely(expand_stack(vma, address))) {
 		bad_area(regs, sw_error_code, address);
 		return;
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] x86/mm/fault: Allow stack access below %rsp
  2018-11-06 20:12 [PATCH v2] x86/mm/fault: Allow stack access below %rsp Waiman Long
@ 2018-11-06 20:14 ` Waiman Long
  2018-11-12 10:33 ` [tip:x86/mm] " tip-bot for Waiman Long
  1 sibling, 0 replies; 3+ messages in thread
From: Waiman Long @ 2018-11-06 20:14 UTC (permalink / raw)
  To: Dave Hansen, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov
  Cc: H. Peter Anvin, x86, linux-kernel

On 11/06/2018 03:12 PM, Waiman Long wrote:
> The current x86 page fault handler allows stack access below the stack
> pointer if it is no more than 64k+256 bytes. Any access beyond the 64k+
> limit will cause a segmentation fault.
>
> The gcc -fstack-check option generates code to probe the stack for
> large stack allocation to see if the stack is accessible. The newer gcc
> does that while updating the %rsp simultaneously. Older gcc's like gcc4
> doesn't do that. As a result, an application compiled with an old gcc
> and the -fstack-check option may fail to start at all.
>
> % cat test.c
> int main() {
> 	char tmp[1024*128];
> 	printf("### ok\n");
> 	return 0;
> }
> % gcc -fstack-check -g -o test test.c
> % ./test
> Segmentation fault
>
> The old binary was working in older kernels where expand_stack() was
> somehow called before the check. But it is not working in newer kernels.
> Besides, the 64k+ limit check is kind of crude and will not catch a
> lot of mistakes that userspace applications may be misbehaving anyway.
> I think the kernel isn't the right place for this kind of tests. We
> should leave it to userspace instrumentation tools to perform them.
>
> The 64k+ limit check is now removed to just let expand_stack() decide
> if a segmentation fault should happen, when the RLIMIT_STACK limit is
> exceeded, for example.
>
> Signed-off-by: Waiman Long <longman@redhat.com>
> ---
>  arch/x86/mm/fault.c | 12 ------------
>  1 file changed, 12 deletions(-)
>
> diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
> index 71d4b9d..29525cf 100644
> --- a/arch/x86/mm/fault.c
> +++ b/arch/x86/mm/fault.c
> @@ -1380,18 +1380,6 @@ void do_user_addr_fault(struct pt_regs *regs,
>  		bad_area(regs, sw_error_code, address);
>  		return;
>  	}
> -	if (sw_error_code & X86_PF_USER) {
> -		/*
> -		 * Accessing the stack below %sp is always a bug.
> -		 * The large cushion allows instructions like enter
> -		 * and pusha to work. ("enter $65535, $31" pushes
> -		 * 32 pointers and then decrements %sp by 65535.)
> -		 */
> -		if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < regs->sp)) {
> -			bad_area(regs, sw_error_code, address);
> -			return;
> -		}
> -	}
>  	if (unlikely(expand_stack(vma, address))) {
>  		bad_area(regs, sw_error_code, address);
>  		return;

This v2 patch has no code change. I just updated the commit log to
capture some of the conversion that I had with the reviewers.

Cheers,
Longman


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [tip:x86/mm] x86/mm/fault: Allow stack access below %rsp
  2018-11-06 20:12 [PATCH v2] x86/mm/fault: Allow stack access below %rsp Waiman Long
  2018-11-06 20:14 ` Waiman Long
@ 2018-11-12 10:33 ` tip-bot for Waiman Long
  1 sibling, 0 replies; 3+ messages in thread
From: tip-bot for Waiman Long @ 2018-11-12 10:33 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: riel, mingo, longman, luto, dave.hansen, linux-kernel, brgerst,
	torvalds, bp, hpa, dvlasenk, peterz, tglx

Commit-ID:  1d8ca3be86ebc6a38dad8236f45c7a9c61681e78
Gitweb:     https://git.kernel.org/tip/1d8ca3be86ebc6a38dad8236f45c7a9c61681e78
Author:     Waiman Long <longman@redhat.com>
AuthorDate: Tue, 6 Nov 2018 15:12:29 -0500
Committer:  Ingo Molnar <mingo@kernel.org>
CommitDate: Mon, 12 Nov 2018 11:06:19 +0100

x86/mm/fault: Allow stack access below %rsp

The current x86 page fault handler allows stack access below the stack
pointer if it is no more than 64k+256 bytes. Any access beyond the 64k+
limit will cause a segmentation fault.

The gcc -fstack-check option generates code to probe the stack for
large stack allocation to see if the stack is accessible. The newer gcc
does that while updating the %rsp simultaneously. Older gcc's like gcc4
doesn't do that. As a result, an application compiled with an old gcc
and the -fstack-check option may fail to start at all:

  $ cat test.c
  int main() {
	char tmp[1024*128];
	printf("### ok\n");
	return 0;
  }

  $ gcc -fstack-check -g -o test test.c

  $ ./test
  Segmentation fault

The old binary was working in older kernels where expand_stack() was
somehow called before the check. But it is not working in newer kernels.
Besides, the 64k+ limit check is kind of crude and will not catch a
lot of mistakes that userspace applications may be misbehaving anyway.
I think the kernel isn't the right place for this kind of tests. We
should leave it to userspace instrumentation tools to perform them.

The 64k+ limit check is now removed to just let expand_stack() decide
if a segmentation fault should happen, when the RLIMIT_STACK limit is
exceeded, for example.

Signed-off-by: Waiman Long <longman@redhat.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rik van Riel <riel@surriel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/1541535149-31963-1-git-send-email-longman@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
---
 arch/x86/mm/fault.c | 12 ------------
 1 file changed, 12 deletions(-)

diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 71d4b9d4d43f..29525cf21100 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1380,18 +1380,6 @@ retry:
 		bad_area(regs, sw_error_code, address);
 		return;
 	}
-	if (sw_error_code & X86_PF_USER) {
-		/*
-		 * Accessing the stack below %sp is always a bug.
-		 * The large cushion allows instructions like enter
-		 * and pusha to work. ("enter $65535, $31" pushes
-		 * 32 pointers and then decrements %sp by 65535.)
-		 */
-		if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < regs->sp)) {
-			bad_area(regs, sw_error_code, address);
-			return;
-		}
-	}
 	if (unlikely(expand_stack(vma, address))) {
 		bad_area(regs, sw_error_code, address);
 		return;

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-11-12 10:34 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-06 20:12 [PATCH v2] x86/mm/fault: Allow stack access below %rsp Waiman Long
2018-11-06 20:14 ` Waiman Long
2018-11-12 10:33 ` [tip:x86/mm] " tip-bot for Waiman Long

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.