aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/ia32/ia32_signal.c50
-rw-r--r--arch/x86/ia32/ia32entry.S1
-rw-r--r--arch/x86/include/asm/ia32.h10
-rw-r--r--arch/x86/include/asm/sys_ia32.h2
-rw-r--r--arch/x86/kernel/entry_64.S2
-rw-r--r--arch/x86/kernel/signal.c4
-rw-r--r--arch/x86/syscalls/syscall_32.tbl2
-rw-r--r--arch/x86/syscalls/syscall_64.tbl2
-rw-r--r--include/linux/compat.h16
-rw-r--r--kernel/signal.c45
10 files changed, 67 insertions, 67 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index efc6a958b71d..a866411a2fcc 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -136,52 +136,6 @@ asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
136 return sigsuspend(&blocked); 136 return sigsuspend(&blocked);
137} 137}
138 138
139asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
140 stack_ia32_t __user *uoss_ptr,
141 struct pt_regs *regs)
142{
143 stack_t uss, uoss;
144 int ret, err = 0;
145 mm_segment_t seg;
146
147 if (uss_ptr) {
148 u32 ptr;
149
150 memset(&uss, 0, sizeof(stack_t));
151 if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)))
152 return -EFAULT;
153
154 get_user_try {
155 get_user_ex(ptr, &uss_ptr->ss_sp);
156 get_user_ex(uss.ss_flags, &uss_ptr->ss_flags);
157 get_user_ex(uss.ss_size, &uss_ptr->ss_size);
158 } get_user_catch(err);
159
160 if (err)
161 return -EFAULT;
162 uss.ss_sp = compat_ptr(ptr);
163 }
164 seg = get_fs();
165 set_fs(KERNEL_DS);
166 ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL),
167 (stack_t __force __user *) &uoss, regs->sp);
168 set_fs(seg);
169 if (ret >= 0 && uoss_ptr) {
170 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
171 return -EFAULT;
172
173 put_user_try {
174 put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp);
175 put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags);
176 put_user_ex(uoss.ss_size, &uoss_ptr->ss_size);
177 } put_user_catch(err);
178
179 if (err)
180 ret = -EFAULT;
181 }
182 return ret;
183}
184
185/* 139/*
186 * Do a signal return; undo the signal stack. 140 * Do a signal return; undo the signal stack.
187 */ 141 */
@@ -292,7 +246,6 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
292 struct rt_sigframe_ia32 __user *frame; 246 struct rt_sigframe_ia32 __user *frame;
293 sigset_t set; 247 sigset_t set;
294 unsigned int ax; 248 unsigned int ax;
295 struct pt_regs tregs;
296 249
297 frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4); 250 frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
298 251
@@ -306,8 +259,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
306 if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) 259 if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
307 goto badframe; 260 goto badframe;
308 261
309 tregs = *regs; 262 if (compat_restore_altstack(&frame->uc.uc_stack))
310 if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
311 goto badframe; 263 goto badframe;
312 264
313 return ax; 265 return ax;
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 32e6f05ddaaa..102ff7cb3e41 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -464,7 +464,6 @@ GLOBAL(\label)
464 464
465 PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi 465 PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
466 PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi 466 PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
467 PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
468 PTREGSCALL stub32_execve, compat_sys_execve, %rcx 467 PTREGSCALL stub32_execve, compat_sys_execve, %rcx
469 PTREGSCALL stub32_fork, sys_fork, %rdi 468 PTREGSCALL stub32_fork, sys_fork, %rdi
470 PTREGSCALL stub32_vfork, sys_vfork, %rdi 469 PTREGSCALL stub32_vfork, sys_vfork, %rdi
diff --git a/arch/x86/include/asm/ia32.h b/arch/x86/include/asm/ia32.h
index e6232773ce49..4c6da2e4bb1d 100644
--- a/arch/x86/include/asm/ia32.h
+++ b/arch/x86/include/asm/ia32.h
@@ -29,16 +29,10 @@ struct old_sigaction32 {
29 unsigned int sa_restorer; /* Another 32 bit pointer */ 29 unsigned int sa_restorer; /* Another 32 bit pointer */
30}; 30};
31 31
32typedef struct sigaltstack_ia32 {
33 unsigned int ss_sp;
34 int ss_flags;
35 unsigned int ss_size;
36} stack_ia32_t;
37
38struct ucontext_ia32 { 32struct ucontext_ia32 {
39 unsigned int uc_flags; 33 unsigned int uc_flags;
40 unsigned int uc_link; 34 unsigned int uc_link;
41 stack_ia32_t uc_stack; 35 compat_stack_t uc_stack;
42 struct sigcontext_ia32 uc_mcontext; 36 struct sigcontext_ia32 uc_mcontext;
43 compat_sigset_t uc_sigmask; /* mask last for extensibility */ 37 compat_sigset_t uc_sigmask; /* mask last for extensibility */
44}; 38};
@@ -46,7 +40,7 @@ struct ucontext_ia32 {
46struct ucontext_x32 { 40struct ucontext_x32 {
47 unsigned int uc_flags; 41 unsigned int uc_flags;
48 unsigned int uc_link; 42 unsigned int uc_link;
49 stack_ia32_t uc_stack; 43 compat_stack_t uc_stack;
50 unsigned int uc__pad0; /* needed for alignment */ 44 unsigned int uc__pad0; /* needed for alignment */
51 struct sigcontext uc_mcontext; /* the 64-bit sigcontext type */ 45 struct sigcontext uc_mcontext; /* the 64-bit sigcontext type */
52 compat_sigset_t uc_sigmask; /* mask last for extensibility */ 46 compat_sigset_t uc_sigmask; /* mask last for extensibility */
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
index c76fae4d90be..31f61f96e0fb 100644
--- a/arch/x86/include/asm/sys_ia32.h
+++ b/arch/x86/include/asm/sys_ia32.h
@@ -69,8 +69,6 @@ asmlinkage long sys32_fallocate(int, int, unsigned,
69 69
70/* ia32/ia32_signal.c */ 70/* ia32/ia32_signal.c */
71asmlinkage long sys32_sigsuspend(int, int, old_sigset_t); 71asmlinkage long sys32_sigsuspend(int, int, old_sigset_t);
72asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *,
73 stack_ia32_t __user *, struct pt_regs *);
74asmlinkage long sys32_sigreturn(struct pt_regs *); 72asmlinkage long sys32_sigreturn(struct pt_regs *);
75asmlinkage long sys32_rt_sigreturn(struct pt_regs *); 73asmlinkage long sys32_rt_sigreturn(struct pt_regs *);
76 74
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 6e462019f195..86d81199bbde 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -912,8 +912,6 @@ ENTRY(stub_rt_sigreturn)
912END(stub_rt_sigreturn) 912END(stub_rt_sigreturn)
913 913
914#ifdef CONFIG_X86_X32_ABI 914#ifdef CONFIG_X86_X32_ABI
915 PTREGSCALL stub_x32_sigaltstack, sys32_sigaltstack, %rdx
916
917ENTRY(stub_x32_rt_sigreturn) 915ENTRY(stub_x32_rt_sigreturn)
918 CFI_STARTPROC 916 CFI_STARTPROC
919 addq $8, %rsp 917 addq $8, %rsp
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 16d065c23baf..b17ed37c61a2 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -857,7 +857,6 @@ asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
857 struct rt_sigframe_x32 __user *frame; 857 struct rt_sigframe_x32 __user *frame;
858 sigset_t set; 858 sigset_t set;
859 unsigned long ax; 859 unsigned long ax;
860 struct pt_regs tregs;
861 860
862 frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8); 861 frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8);
863 862
@@ -871,8 +870,7 @@ asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
871 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) 870 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
872 goto badframe; 871 goto badframe;
873 872
874 tregs = *regs; 873 if (compat_restore_altstack(&frame->uc.uc_stack))
875 if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
876 goto badframe; 874 goto badframe;
877 875
878 return ax; 876 return ax;
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index 62c7b222e45c..235226efaa7f 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -192,7 +192,7 @@
192183 i386 getcwd sys_getcwd 192183 i386 getcwd sys_getcwd
193184 i386 capget sys_capget 193184 i386 capget sys_capget
194185 i386 capset sys_capset 194185 i386 capset sys_capset
195186 i386 sigaltstack sys_sigaltstack stub32_sigaltstack 195186 i386 sigaltstack sys_sigaltstack compat_sys_sigaltstack
196187 i386 sendfile sys_sendfile sys32_sendfile 196187 i386 sendfile sys_sendfile sys32_sendfile
197188 i386 getpmsg 197188 i386 getpmsg
198189 i386 putpmsg 198189 i386 putpmsg
diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl
index 6ffa7f9d005e..c68cbe7174e7 100644
--- a/arch/x86/syscalls/syscall_64.tbl
+++ b/arch/x86/syscalls/syscall_64.tbl
@@ -337,7 +337,7 @@
337522 x32 rt_sigpending sys32_rt_sigpending 337522 x32 rt_sigpending sys32_rt_sigpending
338523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait 338523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait
339524 x32 rt_sigqueueinfo sys32_rt_sigqueueinfo 339524 x32 rt_sigqueueinfo sys32_rt_sigqueueinfo
340525 x32 sigaltstack stub_x32_sigaltstack 340525 x32 sigaltstack compat_sys_sigaltstack
341526 x32 timer_create compat_sys_timer_create 341526 x32 timer_create compat_sys_timer_create
342527 x32 mq_notify compat_sys_mq_notify 342527 x32 mq_notify compat_sys_mq_notify
343528 x32 kexec_load compat_sys_kexec_load 343528 x32 kexec_load compat_sys_kexec_load
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 62bb76f91baf..cb5637e2ee2c 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -68,6 +68,16 @@
68#ifndef compat_user_stack_pointer 68#ifndef compat_user_stack_pointer
69#define compat_user_stack_pointer() current_user_stack_pointer() 69#define compat_user_stack_pointer() current_user_stack_pointer()
70#endif 70#endif
71#ifdef CONFIG_GENERIC_SIGALTSTACK
72#ifndef compat_sigaltstack /* we'll need that for MIPS */
73typedef struct compat_sigaltstack {
74 compat_uptr_t ss_sp;
75 int ss_flags;
76 compat_size_t ss_size;
77} compat_stack_t;
78#endif
79#endif
80
71#define compat_jiffies_to_clock_t(x) \ 81#define compat_jiffies_to_clock_t(x) \
72 (((unsigned long)(x) * COMPAT_USER_HZ) / HZ) 82 (((unsigned long)(x) * COMPAT_USER_HZ) / HZ)
73 83
@@ -632,6 +642,12 @@ asmlinkage ssize_t compat_sys_process_vm_writev(compat_pid_t pid,
632 642
633asmlinkage long compat_sys_sendfile(int out_fd, int in_fd, 643asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
634 compat_off_t __user *offset, compat_size_t count); 644 compat_off_t __user *offset, compat_size_t count);
645#ifdef CONFIG_GENERIC_SIGALTSTACK
646asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr,
647 compat_stack_t __user *uoss_ptr);
648
649int compat_restore_altstack(const compat_stack_t __user *uss);
650#endif
635 651
636#else 652#else
637 653
diff --git a/kernel/signal.c b/kernel/signal.c
index f05f4c4150d9..aee85bd76b8a 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -31,6 +31,7 @@
31#include <linux/nsproxy.h> 31#include <linux/nsproxy.h>
32#include <linux/user_namespace.h> 32#include <linux/user_namespace.h>
33#include <linux/uprobes.h> 33#include <linux/uprobes.h>
34#include <linux/compat.h>
34#define CREATE_TRACE_POINTS 35#define CREATE_TRACE_POINTS
35#include <trace/events/signal.h> 36#include <trace/events/signal.h>
36 37
@@ -3116,6 +3117,50 @@ int restore_altstack(const stack_t __user *uss)
3116 return err == -EFAULT ? err : 0; 3117 return err == -EFAULT ? err : 0;
3117} 3118}
3118 3119
3120#ifdef CONFIG_COMPAT
3121#ifdef CONFIG_GENERIC_SIGALTSTACK
3122asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr,
3123 compat_stack_t __user *uoss_ptr)
3124{
3125 stack_t uss, uoss;
3126 int ret;
3127 mm_segment_t seg;
3128
3129 if (uss_ptr) {
3130 compat_stack_t uss32;
3131
3132 memset(&uss, 0, sizeof(stack_t));
3133 if (copy_from_user(&uss32, uss_ptr, sizeof(compat_stack_t)))
3134 return -EFAULT;
3135 uss.ss_sp = compat_ptr(uss32.ss_sp);
3136 uss.ss_flags = uss32.ss_flags;
3137 uss.ss_size = uss32.ss_size;
3138 }
3139 seg = get_fs();
3140 set_fs(KERNEL_DS);
3141 ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL),
3142 (stack_t __force __user *) &uoss,
3143 compat_user_stack_pointer());
3144 set_fs(seg);
3145 if (ret >= 0 && uoss_ptr) {
3146 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(compat_stack_t)) ||
3147 __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
3148 __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
3149 __put_user(uoss.ss_size, &uoss_ptr->ss_size))
3150 ret = -EFAULT;
3151 }
3152 return ret;
3153}
3154
3155int compat_restore_altstack(const compat_stack_t __user *uss)
3156{
3157 int err = compat_sys_sigaltstack(uss, NULL);
3158 /* squash all but -EFAULT for now */
3159 return err == -EFAULT ? err : 0;
3160}
3161#endif
3162#endif
3163
3119#ifdef __ARCH_WANT_SYS_SIGPENDING 3164#ifdef __ARCH_WANT_SYS_SIGPENDING
3120 3165
3121/** 3166/**