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 /include/linux/signal.h | |
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 'include/linux/signal.h')
-rw-r--r-- | include/linux/signal.h | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/include/linux/signal.h b/include/linux/signal.h index d897484730c0..2ac423bdb676 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h | |||
@@ -434,6 +434,14 @@ void signals_init(void); | |||
434 | int restore_altstack(const stack_t __user *); | 434 | int restore_altstack(const stack_t __user *); |
435 | int __save_altstack(stack_t __user *, unsigned long); | 435 | int __save_altstack(stack_t __user *, unsigned long); |
436 | 436 | ||
437 | #define save_altstack_ex(uss, sp) do { \ | ||
438 | stack_t __user *__uss = uss; \ | ||
439 | struct task_struct *t = current; \ | ||
440 | put_user_ex((void __user *)t->sas_ss_sp, &__uss->ss_sp); \ | ||
441 | put_user_ex(sas_ss_flags(sp), &__uss->ss_flags); \ | ||
442 | put_user_ex(t->sas_ss_size, &__uss->ss_size); \ | ||
443 | } while (0); | ||
444 | |||
437 | #ifdef CONFIG_PROC_FS | 445 | #ifdef CONFIG_PROC_FS |
438 | struct seq_file; | 446 | struct seq_file; |
439 | extern void render_sigset_t(struct seq_file *, const char *, sigset_t *); | 447 | extern void render_sigset_t(struct seq_file *, const char *, sigset_t *); |