1 /* Signal support for 32-bit kernel builds
3 * Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
4 * Copyright (C) 2006 Kyle McMartin <kyle at parisc-linux.org>
6 * Code was mostly borrowed from kernel/signal.c.
7 * See kernel/signal.c for additional Copyrights.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include <linux/compat.h>
26 #include <linux/module.h>
27 #include <linux/unistd.h>
28 #include <linux/init.h>
29 #include <linux/sched.h>
30 #include <linux/syscalls.h>
31 #include <linux/types.h>
32 #include <linux/errno.h>
34 #include <linux/uaccess.h>
38 #define DEBUG_COMPAT_SIG 0
39 #define DEBUG_COMPAT_SIG_LEVEL 2
42 #define DBG(LEVEL, ...) \
43 ((DEBUG_COMPAT_SIG_LEVEL >= LEVEL) \
44 ? printk(__VA_ARGS__) : (void) 0)
46 #define DBG(LEVEL, ...)
50 restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
54 compat_uint_t compat_reg;
55 compat_uint_t compat_regt;
58 /* When loading 32-bit values into 64-bit registers make
59 sure to clear the upper 32-bits */
60 DBG(2,"restore_sigcontext32: PER_LINUX32 process\n");
61 DBG(2,"restore_sigcontext32: sc = 0x%p, rf = 0x%p, regs = 0x%p\n", sc, rf, regs);
62 DBG(2,"restore_sigcontext32: compat_sigcontext is %#lx bytes\n", sizeof(*sc));
63 for(regn=0; regn < 32; regn++){
64 err |= __get_user(compat_reg,&sc->sc_gr[regn]);
65 regs->gr[regn] = compat_reg;
67 err |= __get_user(compat_regt,&rf->rf_gr[regn]);
68 regs->gr[regn] = ((u64)compat_regt << 32) | (u64)compat_reg;
69 DBG(3,"restore_sigcontext32: gr%02d = %#lx (%#x / %#x)\n",
70 regn, regs->gr[regn], compat_regt, compat_reg);
72 DBG(2,"restore_sigcontext32: sc->sc_fr = 0x%p (%#lx)\n",sc->sc_fr, sizeof(sc->sc_fr));
73 /* XXX: BE WARNED FR's are 64-BIT! */
74 err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
76 /* Better safe than sorry, pass __get_user two things of
77 the same size and let gcc do the upward conversion to
79 err |= __get_user(compat_reg, &sc->sc_iaoq[0]);
81 err |= __get_user(compat_regt, &rf->rf_iaoq[0]);
82 regs->iaoq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
83 DBG(2,"restore_sigcontext32: upper half of iaoq[0] = %#lx\n", compat_regt);
84 DBG(2,"restore_sigcontext32: sc->sc_iaoq[0] = %p => %#x\n",
85 &sc->sc_iaoq[0], compat_reg);
87 err |= __get_user(compat_reg, &sc->sc_iaoq[1]);
89 err |= __get_user(compat_regt, &rf->rf_iaoq[1]);
90 regs->iaoq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
91 DBG(2,"restore_sigcontext32: upper half of iaoq[1] = %#lx\n", compat_regt);
92 DBG(2,"restore_sigcontext32: sc->sc_iaoq[1] = %p => %#x\n",
93 &sc->sc_iaoq[1],compat_reg);
94 DBG(2,"restore_sigcontext32: iaoq is %#lx / %#lx\n",
95 regs->iaoq[0],regs->iaoq[1]);
97 err |= __get_user(compat_reg, &sc->sc_iasq[0]);
98 /* Load the upper half for iasq */
99 err |= __get_user(compat_regt, &rf->rf_iasq[0]);
100 regs->iasq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
101 DBG(2,"restore_sigcontext32: upper half of iasq[0] = %#lx\n", compat_regt);
103 err |= __get_user(compat_reg, &sc->sc_iasq[1]);
104 /* Load the upper half for iasq */
105 err |= __get_user(compat_regt, &rf->rf_iasq[1]);
106 regs->iasq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
107 DBG(2,"restore_sigcontext32: upper half of iasq[1] = %#lx\n", compat_regt);
108 DBG(2,"restore_sigcontext32: iasq is %#lx / %#lx\n",
109 regs->iasq[0],regs->iasq[1]);
111 err |= __get_user(compat_reg, &sc->sc_sar);
112 /* Load the upper half for sar */
113 err |= __get_user(compat_regt, &rf->rf_sar);
114 regs->sar = ((u64)compat_regt << 32) | (u64)compat_reg;
115 DBG(2,"restore_sigcontext32: upper_half & sar = %#lx\n", compat_regt);
116 DBG(2,"restore_sigcontext32: sar is %#lx\n", regs->sar);
117 DBG(2,"restore_sigcontext32: r28 is %ld\n", regs->gr[28]);
123 * Set up the sigcontext structure for this process.
124 * This is not an easy task if the kernel is 64-bit, it will require
125 * that we examine the process personality to determine if we need to
126 * truncate for a 32-bit userspace.
129 setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
130 struct pt_regs *regs, int in_syscall)
132 compat_int_t flags = 0;
134 compat_uint_t compat_reg;
135 compat_uint_t compat_regb;
138 if (on_sig_stack((unsigned long) sc))
139 flags |= PARISC_SC_FLAG_ONSTACK;
143 DBG(1,"setup_sigcontext32: in_syscall\n");
145 flags |= PARISC_SC_FLAG_IN_SYSCALL;
147 compat_reg = (compat_uint_t)(regs->gr[31]);
148 /* regs->iaoq is undefined in the syscall return path */
149 err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
150 DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
151 &sc->sc_iaoq[0], compat_reg);
153 /* Store upper half */
154 compat_reg = (compat_uint_t)(regs->gr[31] >> 32);
155 err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
156 DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
159 compat_reg = (compat_uint_t)(regs->gr[31]+4);
160 err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
161 DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
162 &sc->sc_iaoq[1], compat_reg);
163 /* Store upper half */
164 compat_reg = (compat_uint_t)((regs->gr[31]+4) >> 32);
165 err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
166 DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
169 compat_reg = (compat_uint_t)(regs->sr[3]);
170 err |= __put_user(compat_reg, &sc->sc_iasq[0]);
171 err |= __put_user(compat_reg, &sc->sc_iasq[1]);
173 /* Store upper half */
174 compat_reg = (compat_uint_t)(regs->sr[3] >> 32);
175 err |= __put_user(compat_reg, &rf->rf_iasq[0]);
176 err |= __put_user(compat_reg, &rf->rf_iasq[1]);
178 DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
179 DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
180 DBG(1,"setup_sigcontext32: iaoq %#lx / %#lx\n",
181 regs->gr[31], regs->gr[31]+4);
185 compat_reg = (compat_uint_t)(regs->iaoq[0]);
186 err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
187 DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
188 &sc->sc_iaoq[0], compat_reg);
189 /* Store upper half */
190 compat_reg = (compat_uint_t)(regs->iaoq[0] >> 32);
191 err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
192 DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
194 compat_reg = (compat_uint_t)(regs->iaoq[1]);
195 err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
196 DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
197 &sc->sc_iaoq[1], compat_reg);
198 /* Store upper half */
199 compat_reg = (compat_uint_t)(regs->iaoq[1] >> 32);
200 err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
201 DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
204 compat_reg = (compat_uint_t)(regs->iasq[0]);
205 err |= __put_user(compat_reg, &sc->sc_iasq[0]);
206 DBG(2,"setup_sigcontext32: sc->sc_iasq[0] = %p <= %#x\n",
207 &sc->sc_iasq[0], compat_reg);
208 /* Store upper half */
209 compat_reg = (compat_uint_t)(regs->iasq[0] >> 32);
210 err |= __put_user(compat_reg, &rf->rf_iasq[0]);
211 DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
214 compat_reg = (compat_uint_t)(regs->iasq[1]);
215 err |= __put_user(compat_reg, &sc->sc_iasq[1]);
216 DBG(2,"setup_sigcontext32: sc->sc_iasq[1] = %p <= %#x\n",
217 &sc->sc_iasq[1], compat_reg);
218 /* Store upper half */
219 compat_reg = (compat_uint_t)(regs->iasq[1] >> 32);
220 err |= __put_user(compat_reg, &rf->rf_iasq[1]);
221 DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
223 /* Print out the IAOQ for debugging */
224 DBG(1,"setup_sigcontext32: ia0q %#lx / %#lx\n",
225 regs->iaoq[0], regs->iaoq[1]);
228 err |= __put_user(flags, &sc->sc_flags);
230 DBG(1,"setup_sigcontext32: Truncating general registers.\n");
232 for(regn=0; regn < 32; regn++){
233 /* Truncate a general register */
234 compat_reg = (compat_uint_t)(regs->gr[regn]);
235 err |= __put_user(compat_reg, &sc->sc_gr[regn]);
236 /* Store upper half */
237 compat_regb = (compat_uint_t)(regs->gr[regn] >> 32);
238 err |= __put_user(compat_regb, &rf->rf_gr[regn]);
240 /* DEBUG: Write out the "upper / lower" register data */
241 DBG(2,"setup_sigcontext32: gr%02d = %#x / %#x\n", regn,
242 compat_regb, compat_reg);
245 /* Copy the floating point registers (same size)
246 XXX: BE WARNED FR's are 64-BIT! */
247 DBG(1,"setup_sigcontext32: Copying from regs to sc, "
248 "sc->sc_fr size = %#lx, regs->fr size = %#lx\n",
249 sizeof(regs->fr), sizeof(sc->sc_fr));
250 err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
252 compat_reg = (compat_uint_t)(regs->sar);
253 err |= __put_user(compat_reg, &sc->sc_sar);
254 DBG(2,"setup_sigcontext32: sar is %#x\n", compat_reg);
255 /* Store upper half */
256 compat_reg = (compat_uint_t)(regs->sar >> 32);
257 err |= __put_user(compat_reg, &rf->rf_sar);
258 DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg);
259 DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]);
265 copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
270 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
273 err = __get_user(to->si_signo, &from->si_signo);
274 err |= __get_user(to->si_errno, &from->si_errno);
275 err |= __get_user(to->si_code, &from->si_code);
278 err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
280 switch (siginfo_layout(to->si_signo, to->si_code)) {
282 err |= __get_user(to->si_utime, &from->si_utime);
283 err |= __get_user(to->si_stime, &from->si_stime);
284 err |= __get_user(to->si_status, &from->si_status);
287 err |= __get_user(to->si_pid, &from->si_pid);
288 err |= __get_user(to->si_uid, &from->si_uid);
291 err |= __get_user(addr, &from->si_addr);
292 to->si_addr = compat_ptr(addr);
295 err |= __get_user(to->si_band, &from->si_band);
296 err |= __get_user(to->si_fd, &from->si_fd);
299 err |= __get_user(to->si_pid, &from->si_pid);
300 err |= __get_user(to->si_uid, &from->si_uid);
301 err |= __get_user(to->si_int, &from->si_int);
309 copy_siginfo_to_user32 (compat_siginfo_t __user *to, const siginfo_t *from)
315 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
318 /* If you change siginfo_t structure, please be sure
319 this code is fixed accordingly.
320 It should never copy any pad contained in the structure
321 to avoid security leaks, but must copy the generic
322 3 ints plus the relevant union member.
323 This routine must convert siginfo from 64bit to 32bit as well
325 err = __put_user(from->si_signo, &to->si_signo);
326 err |= __put_user(from->si_errno, &to->si_errno);
327 err |= __put_user(from->si_code, &to->si_code);
328 if (from->si_code < 0)
329 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
331 switch (siginfo_layout(from->si_signo, from->si_code)) {
333 err |= __put_user(from->si_utime, &to->si_utime);
334 err |= __put_user(from->si_stime, &to->si_stime);
335 err |= __put_user(from->si_status, &to->si_status);
337 err |= __put_user(from->si_pid, &to->si_pid);
338 err |= __put_user(from->si_uid, &to->si_uid);
341 addr = ptr_to_compat(from->si_addr);
342 err |= __put_user(addr, &to->si_addr);
345 err |= __put_user(from->si_band, &to->si_band);
346 err |= __put_user(from->si_fd, &to->si_fd);
349 err |= __put_user(from->si_tid, &to->si_tid);
350 err |= __put_user(from->si_overrun, &to->si_overrun);
351 val = (compat_int_t)from->si_int;
352 err |= __put_user(val, &to->si_int);
355 err |= __put_user(from->si_uid, &to->si_uid);
356 err |= __put_user(from->si_pid, &to->si_pid);
357 val = (compat_int_t)from->si_int;
358 err |= __put_user(val, &to->si_int);
361 err |= __put_user(ptr_to_compat(from->si_call_addr), &to->si_call_addr);
362 err |= __put_user(from->si_syscall, &to->si_syscall);
363 err |= __put_user(from->si_arch, &to->si_arch);