aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/signal_64.c
diff options
context:
space:
mode:
authorHiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>2008-11-24 21:23:12 -0500
committerIngo Molnar <mingo@elte.hu>2008-11-25 23:11:53 -0500
commitbfeb91a9435889ef4fe7bfbb4b673f625e69e790 (patch)
tree904f16d0eba56b7812b1462de6bc28df6c70371f /arch/x86/kernel/signal_64.c
parent2601657d223d82053d4e1fe1063091401e6b860a (diff)
x86: signal: cosmetic unification of __setup_sigframe() and __setup_rt_sigframe()
Impact: cleanup Add #ifdef directive to unify __setup_sigframe() and __setup_rt_sigframe(). Move them after {setup|restore}_sigcontext() declaration. Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/signal_64.c')
-rw-r--r--arch/x86/kernel/signal_64.c309
1 files changed, 256 insertions, 53 deletions
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index 771c8fcc8b0d..2da7e6e60807 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -174,80 +174,212 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
174 return err; 174 return err;
175} 175}
176 176
177/*
178 * Set up a signal frame.
179 */
177#ifdef CONFIG_X86_32 180#ifdef CONFIG_X86_32
178asmlinkage int sys_sigaltstack(unsigned long bx) 181static const struct {
182 u16 poplmovl;
183 u32 val;
184 u16 int80;
185} __attribute__((packed)) retcode = {
186 0xb858, /* popl %eax; movl $..., %eax */
187 __NR_sigreturn,
188 0x80cd, /* int $0x80 */
189};
190
191static const struct {
192 u8 movl;
193 u32 val;
194 u16 int80;
195 u8 pad;
196} __attribute__((packed)) rt_retcode = {
197 0xb8, /* movl $..., %eax */
198 __NR_rt_sigreturn,
199 0x80cd, /* int $0x80 */
200 0
201};
202
203/*
204 * Determine which stack to use..
205 */
206static inline void __user *
207get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
208 void **fpstate)
179{ 209{
210 unsigned long sp;
211
212 /* Default to using normal stack */
213 sp = regs->sp;
214
180 /* 215 /*
181 * This is needed to make gcc realize it doesn't own the 216 * If we are on the alternate signal stack and would overflow it, don't.
182 * "struct pt_regs" 217 * Return an always-bogus address instead so we will die with SIGSEGV.
183 */ 218 */
184 struct pt_regs *regs = (struct pt_regs *)&bx; 219 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
185 const stack_t __user *uss = (const stack_t __user *)bx; 220 return (void __user *) -1L;
186 stack_t __user *uoss = (stack_t __user *)regs->cx;
187 221
188 return do_sigaltstack(uss, uoss, regs->sp); 222 /* This is the X/Open sanctioned signal stack switching. */
189} 223 if (ka->sa.sa_flags & SA_ONSTACK) {
190#else /* !CONFIG_X86_32 */ 224 if (sas_ss_flags(sp) == 0)
191asmlinkage long 225 sp = current->sas_ss_sp + current->sas_ss_size;
192sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, 226 } else {
193 struct pt_regs *regs) 227 /* This is the legacy signal stack switching. */
194{ 228 if ((regs->ss & 0xffff) != __USER_DS &&
195 return do_sigaltstack(uss, uoss, regs->sp); 229 !(ka->sa.sa_flags & SA_RESTORER) &&
230 ka->sa.sa_restorer)
231 sp = (unsigned long) ka->sa.sa_restorer;
232 }
233
234 if (used_math()) {
235 sp = sp - sig_xstate_size;
236 *fpstate = (struct _fpstate *) sp;
237 if (save_i387_xstate(*fpstate) < 0)
238 return (void __user *)-1L;
239 }
240
241 sp -= frame_size;
242 /*
243 * Align the stack pointer according to the i386 ABI,
244 * i.e. so that on function entry ((sp + 4) & 15) == 0.
245 */
246 sp = ((sp + 4) & -16ul) - 4;
247
248 return (void __user *) sp;
196} 249}
197#endif /* CONFIG_X86_32 */
198 250
199/* 251static int
200 * Do a signal return; undo the signal stack. 252__setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
201 */ 253 struct pt_regs *regs)
202static long do_rt_sigreturn(struct pt_regs *regs)
203{ 254{
204 struct rt_sigframe __user *frame; 255 struct sigframe __user *frame;
205 unsigned long ax; 256 void __user *restorer;
206 sigset_t set; 257 int err = 0;
258 void __user *fpstate = NULL;
207 259
208 frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long)); 260 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
209 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
210 goto badframe;
211 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
212 goto badframe;
213 261
214 sigdelsetmask(&set, ~_BLOCKABLE); 262 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
215 spin_lock_irq(&current->sighand->siglock); 263 return -EFAULT;
216 current->blocked = set;
217 recalc_sigpending();
218 spin_unlock_irq(&current->sighand->siglock);
219 264
220 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) 265 if (__put_user(sig, &frame->sig))
221 goto badframe; 266 return -EFAULT;
222 267
223 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT) 268 if (setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]))
224 goto badframe; 269 return -EFAULT;
225 270
226 return ax; 271 if (_NSIG_WORDS > 1) {
272 if (__copy_to_user(&frame->extramask, &set->sig[1],
273 sizeof(frame->extramask)))
274 return -EFAULT;
275 }
276
277 if (current->mm->context.vdso)
278 restorer = VDSO32_SYMBOL(current->mm->context.vdso, sigreturn);
279 else
280 restorer = &frame->retcode;
281 if (ka->sa.sa_flags & SA_RESTORER)
282 restorer = ka->sa.sa_restorer;
283
284 /* Set up to return from userspace. */
285 err |= __put_user(restorer, &frame->pretcode);
286
287 /*
288 * This is popl %eax ; movl $__NR_sigreturn, %eax ; int $0x80
289 *
290 * WE DO NOT USE IT ANY MORE! It's only left here for historical
291 * reasons and because gdb uses it as a signature to notice
292 * signal handler stack frames.
293 */
294 err |= __put_user(*((u64 *)&retcode), (u64 *)frame->retcode);
295
296 if (err)
297 return -EFAULT;
298
299 /* Set up registers for signal handler */
300 regs->sp = (unsigned long)frame;
301 regs->ip = (unsigned long)ka->sa.sa_handler;
302 regs->ax = (unsigned long)sig;
303 regs->dx = 0;
304 regs->cx = 0;
305
306 regs->ds = __USER_DS;
307 regs->es = __USER_DS;
308 regs->ss = __USER_DS;
309 regs->cs = __USER_CS;
227 310
228badframe:
229 signal_fault(regs, frame, "rt_sigreturn");
230 return 0; 311 return 0;
231} 312}
232 313
233#ifdef CONFIG_X86_32 314static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
234asmlinkage int sys_rt_sigreturn(unsigned long __unused) 315 sigset_t *set, struct pt_regs *regs)
235{ 316{
236 struct pt_regs *regs = (struct pt_regs *)&__unused; 317 struct rt_sigframe __user *frame;
318 void __user *restorer;
319 int err = 0;
320 void __user *fpstate = NULL;
237 321
238 return do_rt_sigreturn(regs); 322 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
239}
240#else /* !CONFIG_X86_32 */
241asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
242{
243 return do_rt_sigreturn(regs);
244}
245#endif /* CONFIG_X86_32 */
246 323
247/* 324 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
248 * Set up a signal frame. 325 return -EFAULT;
249 */ 326
327 err |= __put_user(sig, &frame->sig);
328 err |= __put_user(&frame->info, &frame->pinfo);
329 err |= __put_user(&frame->uc, &frame->puc);
330 err |= copy_siginfo_to_user(&frame->info, info);
331 if (err)
332 return -EFAULT;
333
334 /* Create the ucontext. */
335 if (cpu_has_xsave)
336 err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
337 else
338 err |= __put_user(0, &frame->uc.uc_flags);
339 err |= __put_user(0, &frame->uc.uc_link);
340 err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
341 err |= __put_user(sas_ss_flags(regs->sp),
342 &frame->uc.uc_stack.ss_flags);
343 err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
344 err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
345 regs, set->sig[0]);
346 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
347 if (err)
348 return -EFAULT;
349
350 /* Set up to return from userspace. */
351 restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn);
352 if (ka->sa.sa_flags & SA_RESTORER)
353 restorer = ka->sa.sa_restorer;
354 err |= __put_user(restorer, &frame->pretcode);
355
356 /*
357 * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
358 *
359 * WE DO NOT USE IT ANY MORE! It's only left here for historical
360 * reasons and because gdb uses it as a signature to notice
361 * signal handler stack frames.
362 */
363 err |= __put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
250 364
365 if (err)
366 return -EFAULT;
367
368 /* Set up registers for signal handler */
369 regs->sp = (unsigned long)frame;
370 regs->ip = (unsigned long)ka->sa.sa_handler;
371 regs->ax = (unsigned long)sig;
372 regs->dx = (unsigned long)&frame->info;
373 regs->cx = (unsigned long)&frame->uc;
374
375 regs->ds = __USER_DS;
376 regs->es = __USER_DS;
377 regs->ss = __USER_DS;
378 regs->cs = __USER_CS;
379
380 return 0;
381}
382#else /* !CONFIG_X86_32 */
251/* 383/*
252 * Determine which stack to use.. 384 * Determine which stack to use..
253 */ 385 */
@@ -337,6 +469,77 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
337 469
338 return 0; 470 return 0;
339} 471}
472#endif /* CONFIG_X86_32 */
473
474#ifdef CONFIG_X86_32
475asmlinkage int sys_sigaltstack(unsigned long bx)
476{
477 /*
478 * This is needed to make gcc realize it doesn't own the
479 * "struct pt_regs"
480 */
481 struct pt_regs *regs = (struct pt_regs *)&bx;
482 const stack_t __user *uss = (const stack_t __user *)bx;
483 stack_t __user *uoss = (stack_t __user *)regs->cx;
484
485 return do_sigaltstack(uss, uoss, regs->sp);
486}
487#else /* !CONFIG_X86_32 */
488asmlinkage long
489sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
490 struct pt_regs *regs)
491{
492 return do_sigaltstack(uss, uoss, regs->sp);
493}
494#endif /* CONFIG_X86_32 */
495
496/*
497 * Do a signal return; undo the signal stack.
498 */
499static long do_rt_sigreturn(struct pt_regs *regs)
500{
501 struct rt_sigframe __user *frame;
502 unsigned long ax;
503 sigset_t set;
504
505 frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
506 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
507 goto badframe;
508 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
509 goto badframe;
510
511 sigdelsetmask(&set, ~_BLOCKABLE);
512 spin_lock_irq(&current->sighand->siglock);
513 current->blocked = set;
514 recalc_sigpending();
515 spin_unlock_irq(&current->sighand->siglock);
516
517 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
518 goto badframe;
519
520 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
521 goto badframe;
522
523 return ax;
524
525badframe:
526 signal_fault(regs, frame, "rt_sigreturn");
527 return 0;
528}
529
530#ifdef CONFIG_X86_32
531asmlinkage int sys_rt_sigreturn(unsigned long __unused)
532{
533 struct pt_regs *regs = (struct pt_regs *)&__unused;
534
535 return do_rt_sigreturn(regs);
536}
537#else /* !CONFIG_X86_32 */
538asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
539{
540 return do_rt_sigreturn(regs);
541}
542#endif /* CONFIG_X86_32 */
340 543
341/* 544/*
342 * OK, we're invoking a handler 545 * OK, we're invoking a handler