diff options
author | Al Viro <viro@ZenIV.linux.org.uk> | 2013-09-01 15:35:01 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2013-09-01 17:16:33 -0400 |
commit | bd1c149aa9915b9abb6d83d0f01dfd2ace0680b5 (patch) | |
tree | 1ccdf876f778bd986a6238d379ee9e9981ed98dc /arch/x86 | |
parent | 7263dda41b5a28ae6566fd126d9b06ada73dd721 (diff) |
Introduce [compat_]save_altstack_ex() to unbreak x86 SMAP
For performance reasons, when SMAP is in use, SMAP is left open for an
entire put_user_try { ... } put_user_catch(); block, however, calling
__put_user() in the middle of that block will close SMAP as the
STAC..CLAC constructs intentionally do not nest.
Furthermore, using __put_user() rather than put_user_ex() here is bad
for performance.
Thus, introduce new [compat_]save_altstack_ex() helpers that replace
__[compat_]save_altstack() for x86, being currently the only
architecture which supports put_user_try { ... } put_user_catch().
Reported-by: H. Peter Anvin <hpa@linux.intel.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Cc: <stable@vger.kernel.org> # v3.8+
Link: http://lkml.kernel.org/n/tip-es5p6y64if71k8p5u08agv9n@git.kernel.org
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/ia32/ia32_signal.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/signal.c | 6 |
2 files changed, 4 insertions, 4 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index bccfca68430e..665a730307f2 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c | |||
@@ -457,7 +457,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig, | |||
457 | else | 457 | else |
458 | put_user_ex(0, &frame->uc.uc_flags); | 458 | put_user_ex(0, &frame->uc.uc_flags); |
459 | put_user_ex(0, &frame->uc.uc_link); | 459 | put_user_ex(0, &frame->uc.uc_link); |
460 | err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp); | 460 | compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp); |
461 | 461 | ||
462 | if (ksig->ka.sa.sa_flags & SA_RESTORER) | 462 | if (ksig->ka.sa.sa_flags & SA_RESTORER) |
463 | restorer = ksig->ka.sa.sa_restorer; | 463 | restorer = ksig->ka.sa.sa_restorer; |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index cf913587d4dd..d859eea07db7 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -358,7 +358,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, | |||
358 | else | 358 | else |
359 | put_user_ex(0, &frame->uc.uc_flags); | 359 | put_user_ex(0, &frame->uc.uc_flags); |
360 | put_user_ex(0, &frame->uc.uc_link); | 360 | put_user_ex(0, &frame->uc.uc_link); |
361 | err |= __save_altstack(&frame->uc.uc_stack, regs->sp); | 361 | save_altstack_ex(&frame->uc.uc_stack, regs->sp); |
362 | 362 | ||
363 | /* Set up to return from userspace. */ | 363 | /* Set up to return from userspace. */ |
364 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); | 364 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); |
@@ -423,7 +423,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, | |||
423 | else | 423 | else |
424 | put_user_ex(0, &frame->uc.uc_flags); | 424 | put_user_ex(0, &frame->uc.uc_flags); |
425 | put_user_ex(0, &frame->uc.uc_link); | 425 | put_user_ex(0, &frame->uc.uc_link); |
426 | err |= __save_altstack(&frame->uc.uc_stack, regs->sp); | 426 | save_altstack_ex(&frame->uc.uc_stack, regs->sp); |
427 | 427 | ||
428 | /* Set up to return from userspace. If provided, use a stub | 428 | /* Set up to return from userspace. If provided, use a stub |
429 | already in userspace. */ | 429 | already in userspace. */ |
@@ -490,7 +490,7 @@ static int x32_setup_rt_frame(struct ksignal *ksig, | |||
490 | else | 490 | else |
491 | put_user_ex(0, &frame->uc.uc_flags); | 491 | put_user_ex(0, &frame->uc.uc_flags); |
492 | put_user_ex(0, &frame->uc.uc_link); | 492 | put_user_ex(0, &frame->uc.uc_link); |
493 | err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp); | 493 | compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp); |
494 | put_user_ex(0, &frame->uc.uc__pad0); | 494 | put_user_ex(0, &frame->uc.uc__pad0); |
495 | 495 | ||
496 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { | 496 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |