1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/sched.h>
16#include <linux/mm.h>
17#include <linux/smp.h>
18#include <linux/kernel.h>
19#include <linux/signal.h>
20#include <linux/errno.h>
21#include <linux/wait.h>
22#include <linux/unistd.h>
23#include <linux/stddef.h>
24#include <linux/personality.h>
25#include <linux/suspend.h>
26#include <linux/ptrace.h>
27#include <linux/elf.h>
28#include <linux/compat.h>
29#include <linux/syscalls.h>
30#include <linux/uaccess.h>
31#include <asm/processor.h>
32#include <asm/ucontext.h>
33#include <asm/sigframe.h>
34#include <asm/syscalls.h>
35#include <asm/vdso.h>
36#include <arch/interrupts.h>
37
38struct compat_ucontext {
39 compat_ulong_t uc_flags;
40 compat_uptr_t uc_link;
41 struct compat_sigaltstack uc_stack;
42 struct sigcontext uc_mcontext;
43 sigset_t uc_sigmask;
44};
45
46struct compat_rt_sigframe {
47 unsigned char save_area[C_ABI_SAVE_AREA_SIZE];
48 struct compat_siginfo info;
49 struct compat_ucontext uc;
50};
51
52int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *from)
53{
54 int err;
55
56 if (!access_ok(VERIFY_WRITE, to, sizeof(struct compat_siginfo)))
57 return -EFAULT;
58
59
60
61
62
63
64 err = __put_user(from->si_signo, &to->si_signo);
65 err |= __put_user(from->si_errno, &to->si_errno);
66 err |= __put_user((short)from->si_code, &to->si_code);
67
68 if (from->si_code < 0) {
69 err |= __put_user(from->si_pid, &to->si_pid);
70 err |= __put_user(from->si_uid, &to->si_uid);
71 err |= __put_user(from->si_int, &to->si_int);
72 } else {
73
74
75
76
77 err |= __put_user(from->_sifields._pad[0],
78 &to->_sifields._pad[0]);
79 switch (from->si_code >> 16) {
80 case __SI_FAULT >> 16:
81 break;
82 case __SI_CHLD >> 16:
83 err |= __put_user(from->si_utime, &to->si_utime);
84 err |= __put_user(from->si_stime, &to->si_stime);
85 err |= __put_user(from->si_status, &to->si_status);
86
87 default:
88 case __SI_KILL >> 16:
89 err |= __put_user(from->si_uid, &to->si_uid);
90 break;
91 case __SI_POLL >> 16:
92 err |= __put_user(from->si_fd, &to->si_fd);
93 break;
94 case __SI_TIMER >> 16:
95 err |= __put_user(from->si_overrun, &to->si_overrun);
96 err |= __put_user(from->si_int, &to->si_int);
97 break;
98
99 case __SI_RT >> 16:
100 case __SI_MESGQ >> 16:
101 err |= __put_user(from->si_uid, &to->si_uid);
102 err |= __put_user(from->si_int, &to->si_int);
103 break;
104 }
105 }
106 return err;
107}
108
109int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
110{
111 int err;
112
113 if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo)))
114 return -EFAULT;
115
116 err = __get_user(to->si_signo, &from->si_signo);
117 err |= __get_user(to->si_errno, &from->si_errno);
118 err |= __get_user(to->si_code, &from->si_code);
119
120 err |= __get_user(to->si_pid, &from->si_pid);
121 err |= __get_user(to->si_uid, &from->si_uid);
122 err |= __get_user(to->si_int, &from->si_int);
123
124 return err;
125}
126
127
128long compat_sys_rt_sigreturn(void)
129{
130 struct pt_regs *regs = current_pt_regs();
131 struct compat_rt_sigframe __user *frame =
132 (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
133 sigset_t set;
134
135 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
136 goto badframe;
137 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
138 goto badframe;
139
140 set_current_blocked(&set);
141
142 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
143 goto badframe;
144
145 if (compat_restore_altstack(&frame->uc.uc_stack))
146 goto badframe;
147
148 return 0;
149
150badframe:
151 signal_fault("bad sigreturn frame", regs, frame, 0);
152 return 0;
153}
154
155
156
157
158static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
159 struct pt_regs *regs,
160 size_t frame_size)
161{
162 unsigned long sp;
163
164
165 sp = (unsigned long)compat_ptr(regs->sp);
166
167
168
169
170
171
172 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
173 return (void __user __force *)-1UL;
174
175
176 if (ka->sa.sa_flags & SA_ONSTACK) {
177 if (sas_ss_flags(sp) == 0)
178 sp = current->sas_ss_sp + current->sas_ss_size;
179 }
180
181 sp -= frame_size;
182
183
184
185
186 sp &= -16UL;
187 return (void __user *) sp;
188}
189
190int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
191 struct pt_regs *regs)
192{
193 unsigned long restorer;
194 struct compat_rt_sigframe __user *frame;
195 int err = 0, sig = ksig->sig;
196
197 frame = compat_get_sigframe(&ksig->ka, regs, sizeof(*frame));
198
199 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
200 goto err;
201
202
203 if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
204
205 err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
206 regs->flags |= PT_FLAGS_RESTORE_REGS;
207 } else {
208 err |= __put_user(ksig->info.si_signo, &frame->info.si_signo);
209 }
210
211
212 err |= __clear_user(&frame->save_area, sizeof(frame->save_area));
213 err |= __put_user(0, &frame->uc.uc_flags);
214 err |= __put_user(0, &frame->uc.uc_link);
215 err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp);
216 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
217 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
218 if (err)
219 goto err;
220
221 restorer = VDSO_SYM(&__vdso_rt_sigreturn);
222 if (ksig->ka.sa.sa_flags & SA_RESTORER)
223 restorer = ptr_to_compat_reg(ksig->ka.sa.sa_restorer);
224
225
226
227
228
229
230
231
232 regs->pc = ptr_to_compat_reg(ksig->ka.sa.sa_handler);
233 regs->ex1 = PL_ICS_EX1(USER_PL, 1);
234 regs->sp = ptr_to_compat_reg(frame);
235 regs->lr = restorer;
236 regs->regs[0] = (unsigned long) sig;
237 regs->regs[1] = ptr_to_compat_reg(&frame->info);
238 regs->regs[2] = ptr_to_compat_reg(&frame->uc);
239 regs->flags |= PT_FLAGS_CALLER_SAVES;
240 return 0;
241
242err:
243 trace_unhandled_signal("bad sigreturn frame", regs,
244 (unsigned long)frame, SIGSEGV);
245 return -EFAULT;
246}
247