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 <arch/interrupts.h>
36
37struct compat_ucontext {
38 compat_ulong_t uc_flags;
39 compat_uptr_t uc_link;
40 struct compat_sigaltstack uc_stack;
41 struct sigcontext uc_mcontext;
42 sigset_t uc_sigmask;
43};
44
45struct compat_rt_sigframe {
46 unsigned char save_area[C_ABI_SAVE_AREA_SIZE];
47 struct compat_siginfo info;
48 struct compat_ucontext uc;
49};
50
51int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from)
52{
53 int err;
54
55 if (!access_ok(VERIFY_WRITE, to, sizeof(struct compat_siginfo)))
56 return -EFAULT;
57
58
59
60
61
62
63 err = __put_user(from->si_signo, &to->si_signo);
64 err |= __put_user(from->si_errno, &to->si_errno);
65 err |= __put_user((short)from->si_code, &to->si_code);
66
67 if (from->si_code < 0) {
68 err |= __put_user(from->si_pid, &to->si_pid);
69 err |= __put_user(from->si_uid, &to->si_uid);
70 err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
71 } else {
72
73
74
75
76 err |= __put_user(from->_sifields._pad[0],
77 &to->_sifields._pad[0]);
78 switch (from->si_code >> 16) {
79 case __SI_FAULT >> 16:
80 break;
81 case __SI_CHLD >> 16:
82 err |= __put_user(from->si_utime, &to->si_utime);
83 err |= __put_user(from->si_stime, &to->si_stime);
84 err |= __put_user(from->si_status, &to->si_status);
85
86 default:
87 case __SI_KILL >> 16:
88 err |= __put_user(from->si_uid, &to->si_uid);
89 break;
90 case __SI_POLL >> 16:
91 err |= __put_user(from->si_fd, &to->si_fd);
92 break;
93 case __SI_TIMER >> 16:
94 err |= __put_user(from->si_overrun, &to->si_overrun);
95 err |= __put_user(ptr_to_compat(from->si_ptr),
96 &to->si_ptr);
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 u32 ptr32;
113
114 if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo)))
115 return -EFAULT;
116
117 err = __get_user(to->si_signo, &from->si_signo);
118 err |= __get_user(to->si_errno, &from->si_errno);
119 err |= __get_user(to->si_code, &from->si_code);
120
121 err |= __get_user(to->si_pid, &from->si_pid);
122 err |= __get_user(to->si_uid, &from->si_uid);
123 err |= __get_user(ptr32, &from->si_ptr);
124 to->si_ptr = compat_ptr(ptr32);
125
126 return err;
127}
128
129
130long compat_sys_rt_sigreturn(void)
131{
132 struct pt_regs *regs = current_pt_regs();
133 struct compat_rt_sigframe __user *frame =
134 (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
135 sigset_t set;
136
137 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
138 goto badframe;
139 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
140 goto badframe;
141
142 set_current_blocked(&set);
143
144 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
145 goto badframe;
146
147 if (compat_restore_altstack(&frame->uc.uc_stack))
148 goto badframe;
149
150 return 0;
151
152badframe:
153 signal_fault("bad sigreturn frame", regs, frame, 0);
154 return 0;
155}
156
157
158
159
160static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
161 struct pt_regs *regs,
162 size_t frame_size)
163{
164 unsigned long sp;
165
166
167 sp = (unsigned long)compat_ptr(regs->sp);
168
169
170
171
172
173
174 if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
175 return (void __user __force *)-1UL;
176
177
178 if (ka->sa.sa_flags & SA_ONSTACK) {
179 if (sas_ss_flags(sp) == 0)
180 sp = current->sas_ss_sp + current->sas_ss_size;
181 }
182
183 sp -= frame_size;
184
185
186
187
188 sp &= -16UL;
189 return (void __user *) sp;
190}
191
192int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
193 sigset_t *set, struct pt_regs *regs)
194{
195 unsigned long restorer;
196 struct compat_rt_sigframe __user *frame;
197 int err = 0;
198 int usig;
199
200 frame = compat_get_sigframe(ka, regs, sizeof(*frame));
201
202 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
203 goto give_sigsegv;
204
205 usig = current_thread_info()->exec_domain
206 && current_thread_info()->exec_domain->signal_invmap
207 && sig < 32
208 ? current_thread_info()->exec_domain->signal_invmap[sig]
209 : sig;
210
211
212 if (ka->sa.sa_flags & SA_SIGINFO) {
213
214 err |= copy_siginfo_to_user32(&frame->info, info);
215 regs->flags |= PT_FLAGS_RESTORE_REGS;
216 } else {
217 err |= __put_user(info->si_signo, &frame->info.si_signo);
218 }
219
220
221 err |= __clear_user(&frame->save_area, sizeof(frame->save_area));
222 err |= __put_user(0, &frame->uc.uc_flags);
223 err |= __put_user(0, &frame->uc.uc_link);
224 err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp);
225 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
226 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
227 if (err)
228 goto give_sigsegv;
229
230 restorer = VDSO_BASE;
231 if (ka->sa.sa_flags & SA_RESTORER)
232 restorer = ptr_to_compat_reg(ka->sa.sa_restorer);
233
234
235
236
237
238
239
240
241 regs->pc = ptr_to_compat_reg(ka->sa.sa_handler);
242 regs->ex1 = PL_ICS_EX1(USER_PL, 1);
243 regs->sp = ptr_to_compat_reg(frame);
244 regs->lr = restorer;
245 regs->regs[0] = (unsigned long) usig;
246 regs->regs[1] = ptr_to_compat_reg(&frame->info);
247 regs->regs[2] = ptr_to_compat_reg(&frame->uc);
248 regs->flags |= PT_FLAGS_CALLER_SAVES;
249 return 0;
250
251give_sigsegv:
252 signal_fault("bad setup frame", regs, frame, sig);
253 return -EFAULT;
254}
255