x86/oprofile: Fix bogus GCC-8 warning in nmi_setup()
[cris-mirror.git] / arch / tile / kernel / compat_signal.c
bloba703bd0e04886c29c67e76d0214b11b9e01d98ee
1 /*
2 * Copyright 2010 Tilera Corporation. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
15 #include <linux/sched.h>
16 #include <linux/sched/task_stack.h>
17 #include <linux/mm.h>
18 #include <linux/smp.h>
19 #include <linux/kernel.h>
20 #include <linux/signal.h>
21 #include <linux/errno.h>
22 #include <linux/wait.h>
23 #include <linux/unistd.h>
24 #include <linux/stddef.h>
25 #include <linux/personality.h>
26 #include <linux/suspend.h>
27 #include <linux/ptrace.h>
28 #include <linux/elf.h>
29 #include <linux/compat.h>
30 #include <linux/syscalls.h>
31 #include <linux/uaccess.h>
32 #include <asm/processor.h>
33 #include <asm/ucontext.h>
34 #include <asm/sigframe.h>
35 #include <asm/syscalls.h>
36 #include <asm/vdso.h>
37 #include <arch/interrupts.h>
39 struct compat_ucontext {
40 compat_ulong_t uc_flags;
41 compat_uptr_t uc_link;
42 struct compat_sigaltstack uc_stack;
43 struct sigcontext uc_mcontext;
44 sigset_t uc_sigmask; /* mask last for extensibility */
47 struct compat_rt_sigframe {
48 unsigned char save_area[C_ABI_SAVE_AREA_SIZE]; /* caller save area */
49 struct compat_siginfo info;
50 struct compat_ucontext uc;
53 /* The assembly shim for this function arranges to ignore the return value. */
54 long compat_sys_rt_sigreturn(void)
56 struct pt_regs *regs = current_pt_regs();
57 struct compat_rt_sigframe __user *frame =
58 (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
59 sigset_t set;
61 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
62 goto badframe;
63 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
64 goto badframe;
66 set_current_blocked(&set);
68 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
69 goto badframe;
71 if (compat_restore_altstack(&frame->uc.uc_stack))
72 goto badframe;
74 return 0;
76 badframe:
77 signal_fault("bad sigreturn frame", regs, frame, 0);
78 return 0;
82 * Determine which stack to use..
84 static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
85 struct pt_regs *regs,
86 size_t frame_size)
88 unsigned long sp;
90 /* Default to using normal stack */
91 sp = (unsigned long)compat_ptr(regs->sp);
94 * If we are on the alternate signal stack and would overflow
95 * it, don't. Return an always-bogus address instead so we
96 * will die with SIGSEGV.
98 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
99 return (void __user __force *)-1UL;
101 /* This is the X/Open sanctioned signal stack switching. */
102 if (ka->sa.sa_flags & SA_ONSTACK) {
103 if (sas_ss_flags(sp) == 0)
104 sp = current->sas_ss_sp + current->sas_ss_size;
107 sp -= frame_size;
109 * Align the stack pointer according to the TILE ABI,
110 * i.e. so that on function entry (sp & 15) == 0.
112 sp &= -16UL;
113 return (void __user *) sp;
116 int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
117 struct pt_regs *regs)
119 unsigned long restorer;
120 struct compat_rt_sigframe __user *frame;
121 int err = 0, sig = ksig->sig;
123 frame = compat_get_sigframe(&ksig->ka, regs, sizeof(*frame));
125 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
126 goto err;
128 /* Always write at least the signal number for the stack backtracer. */
129 if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
130 /* At sigreturn time, restore the callee-save registers too. */
131 err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
132 regs->flags |= PT_FLAGS_RESTORE_REGS;
133 } else {
134 err |= __put_user(ksig->info.si_signo, &frame->info.si_signo);
137 /* Create the ucontext. */
138 err |= __clear_user(&frame->save_area, sizeof(frame->save_area));
139 err |= __put_user(0, &frame->uc.uc_flags);
140 err |= __put_user(0, &frame->uc.uc_link);
141 err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp);
142 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
143 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
144 if (err)
145 goto err;
147 restorer = VDSO_SYM(&__vdso_rt_sigreturn);
148 if (ksig->ka.sa.sa_flags & SA_RESTORER)
149 restorer = ptr_to_compat_reg(ksig->ka.sa.sa_restorer);
152 * Set up registers for signal handler.
153 * Registers that we don't modify keep the value they had from
154 * user-space at the time we took the signal.
155 * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
156 * since some things rely on this (e.g. glibc's debug/segfault.c).
158 regs->pc = ptr_to_compat_reg(ksig->ka.sa.sa_handler);
159 regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
160 regs->sp = ptr_to_compat_reg(frame);
161 regs->lr = restorer;
162 regs->regs[0] = (unsigned long) sig;
163 regs->regs[1] = ptr_to_compat_reg(&frame->info);
164 regs->regs[2] = ptr_to_compat_reg(&frame->uc);
165 regs->flags |= PT_FLAGS_CALLER_SAVES;
166 return 0;
168 err:
169 trace_unhandled_signal("bad sigreturn frame", regs,
170 (unsigned long)frame, SIGSEGV);
171 return -EFAULT;