1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/sched.h>
19#include <linux/mm.h>
20#include <linux/smp.h>
21#include <linux/kernel.h>
22#include <linux/signal.h>
23#include <linux/errno.h>
24#include <linux/wait.h>
25#include <linux/ptrace.h>
26#include <linux/unistd.h>
27#include <linux/stddef.h>
28#include <linux/tracehook.h>
29
30#include <asm/processor.h>
31#include <asm/ucontext.h>
32#include <asm/uaccess.h>
33
34#define DEBUG_SIG 0
35
36asmlinkage long
37_sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
38{
39 return do_sigaltstack(uss, uoss, regs->sp);
40}
41
42struct rt_sigframe {
43 struct siginfo *pinfo;
44 void *puc;
45 struct siginfo info;
46 struct ucontext uc;
47 unsigned char retcode[16];
48};
49
50static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
51{
52 unsigned int err = 0;
53
54
55 current_thread_info()->restart_block.fn = do_no_restart_syscall;
56
57
58
59
60
61
62 if (__copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long)))
63 goto badframe;
64 if (__copy_from_user(®s->pc, &sc->regs.pc, sizeof(unsigned long)))
65 goto badframe;
66 if (__copy_from_user(®s->sr, &sc->regs.sr, sizeof(unsigned long)))
67 goto badframe;
68
69
70 regs->sr &= ~SPR_SR_SM;
71
72
73
74
75
76
77 return err;
78
79badframe:
80 return 1;
81}
82
83asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
84{
85 struct rt_sigframe *frame = (struct rt_sigframe __user *)regs->sp;
86 sigset_t set;
87 stack_t st;
88
89
90
91
92
93
94 if (((long)frame) & 3)
95 goto badframe;
96
97 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
98 goto badframe;
99 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
100 goto badframe;
101
102 set_current_blocked(&set);
103
104 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
105 goto badframe;
106
107 if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
108 goto badframe;
109
110
111 do_sigaltstack(&st, NULL, regs->sp);
112
113 return regs->gpr[11];
114
115badframe:
116 force_sig(SIGSEGV, current);
117 return 0;
118}
119
120
121
122
123
124static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
125 unsigned long mask)
126{
127 int err = 0;
128
129
130
131 err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long));
132 err |= __copy_to_user(&sc->regs.pc, ®s->pc, sizeof(unsigned long));
133 err |= __copy_to_user(&sc->regs.sr, ®s->sr, sizeof(unsigned long));
134
135
136
137 err |= __put_user(mask, &sc->oldmask);
138
139 return err;
140}
141
142static inline unsigned long align_sigframe(unsigned long sp)
143{
144 return sp & ~3UL;
145}
146
147
148
149
150
151
152static inline void __user *get_sigframe(struct k_sigaction *ka,
153 struct pt_regs *regs, size_t frame_size)
154{
155 unsigned long sp = regs->sp;
156 int onsigstack = on_sig_stack(sp);
157
158
159 sp -= STACK_FRAME_OVERHEAD;
160
161
162 if ((ka->sa.sa_flags & SA_ONSTACK) && !onsigstack) {
163 if (current->sas_ss_size)
164 sp = current->sas_ss_sp + current->sas_ss_size;
165 }
166
167 sp = align_sigframe(sp - frame_size);
168
169
170
171
172
173 if (onsigstack && !likely(on_sig_stack(sp)))
174 return (void __user *)-1L;
175
176 return (void __user *)sp;
177}
178
179
180
181
182
183
184
185
186static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
187 sigset_t *set, struct pt_regs *regs)
188{
189 struct rt_sigframe *frame;
190 unsigned long return_ip;
191 int err = 0;
192
193 frame = get_sigframe(ka, regs, sizeof(*frame));
194
195 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
196 goto give_sigsegv;
197
198 err |= __put_user(&frame->info, &frame->pinfo);
199 err |= __put_user(&frame->uc, &frame->puc);
200
201 if (ka->sa.sa_flags & SA_SIGINFO)
202 err |= copy_siginfo_to_user(&frame->info, info);
203 if (err)
204 goto give_sigsegv;
205
206
207 err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
208 err |= __put_user(0, &frame->uc.uc_flags);
209 err |= __put_user(NULL, &frame->uc.uc_link);
210 err |= __put_user((void *)current->sas_ss_sp,
211 &frame->uc.uc_stack.ss_sp);
212 err |= __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags);
213 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
214 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
215
216 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
217
218 if (err)
219 goto give_sigsegv;
220
221
222 return_ip = (unsigned long)&frame->retcode;
223
224 err |= __put_user(0xa960, (short *)(frame->retcode + 0));
225 err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode + 2));
226 err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
227 err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
228
229 if (err)
230 goto give_sigsegv;
231
232
233
234
235 regs->pc = (unsigned long)ka->sa.sa_handler;
236 regs->gpr[9] = (unsigned long)return_ip;
237 regs->gpr[3] = (unsigned long)sig;
238 regs->gpr[4] = (unsigned long)&frame->info;
239 regs->gpr[5] = (unsigned long)&frame->uc;
240
241
242 regs->sp = (unsigned long)frame;
243
244 return 0;
245
246give_sigsegv:
247 force_sigsegv(sig, current);
248 return -EFAULT;
249}
250
251static inline void
252handle_signal(unsigned long sig,
253 siginfo_t *info, struct k_sigaction *ka,
254 struct pt_regs *regs)
255{
256 int ret;
257
258 ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs);
259 if (ret)
260 return;
261
262 signal_delivered(sig, info, ka, regs,
263 test_thread_flag(TIF_SINGLESTEP));
264}
265
266
267
268
269
270
271
272
273
274
275
276
277
278void do_signal(struct pt_regs *regs)
279{
280 siginfo_t info;
281 int signr;
282 struct k_sigaction ka;
283
284
285
286
287
288
289
290 if (!user_mode(regs))
291 return;
292
293 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
294
295
296
297
298
299
300
301
302
303
304 if (regs->orig_gpr11) {
305 int restart = 0;
306
307 switch (regs->gpr[11]) {
308 case -ERESTART_RESTARTBLOCK:
309 case -ERESTARTNOHAND:
310
311 restart = (signr <= 0);
312 break;
313 case -ERESTARTSYS:
314
315
316 restart = (signr <= 0 || (ka.sa.sa_flags & SA_RESTART));
317 break;
318 case -ERESTARTNOINTR:
319
320 restart = 1;
321 break;
322 }
323
324 if (restart) {
325 if (regs->gpr[11] == -ERESTART_RESTARTBLOCK)
326 regs->gpr[11] = __NR_restart_syscall;
327 else
328 regs->gpr[11] = regs->orig_gpr11;
329 regs->pc -= 4;
330 } else {
331 regs->gpr[11] = -EINTR;
332 }
333 }
334
335 if (signr <= 0) {
336
337
338 restore_saved_sigmask();
339 } else {
340
341 handle_signal(signr, &info, &ka, regs);
342 }
343
344 return;
345}
346
347asmlinkage void do_notify_resume(struct pt_regs *regs)
348{
349 if (current_thread_info()->flags & _TIF_SIGPENDING)
350 do_signal(regs);
351
352 if (current_thread_info()->flags & _TIF_NOTIFY_RESUME) {
353 clear_thread_flag(TIF_NOTIFY_RESUME);
354 tracehook_notify_resume(regs);
355 }
356}
357