xref: /openbmc/linux/arch/parisc/kernel/signal32.c (revision 23c2b932)
1 /*    Signal support for 32-bit kernel builds
2  *
3  *    Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
4  *    Copyright (C) 2006 Kyle McMartin <kyle at parisc-linux.org>
5  *
6  *    Code was mostly borrowed from kernel/signal.c.
7  *    See kernel/signal.c for additional Copyrights.
8  *
9  *
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.
14  *
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.
19  *
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
23  */
24 
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>
33 
34 #include <asm/uaccess.h>
35 
36 #include "signal32.h"
37 
38 #define DEBUG_COMPAT_SIG 0
39 #define DEBUG_COMPAT_SIG_LEVEL 2
40 
41 #if DEBUG_COMPAT_SIG
42 #define DBG(LEVEL, ...) \
43 	((DEBUG_COMPAT_SIG_LEVEL >= LEVEL) \
44 	? printk(__VA_ARGS__) : (void) 0)
45 #else
46 #define DBG(LEVEL, ...)
47 #endif
48 
49 inline void
50 sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
51 {
52 	s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
53 }
54 
55 inline void
56 sigset_64to32(compat_sigset_t *s32, sigset_t *s64)
57 {
58 	s32->sig[0] = s64->sig[0] & 0xffffffffUL;
59 	s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL;
60 }
61 
62 long
63 restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
64 		struct pt_regs *regs)
65 {
66 	long err = 0;
67 	compat_uint_t compat_reg;
68 	compat_uint_t compat_regt;
69 	int regn;
70 
71 	/* When loading 32-bit values into 64-bit registers make
72 	   sure to clear the upper 32-bits */
73 	DBG(2,"restore_sigcontext32: PER_LINUX32 process\n");
74 	DBG(2,"restore_sigcontext32: sc = 0x%p, rf = 0x%p, regs = 0x%p\n", sc, rf, regs);
75 	DBG(2,"restore_sigcontext32: compat_sigcontext is %#lx bytes\n", sizeof(*sc));
76 	for(regn=0; regn < 32; regn++){
77 		err |= __get_user(compat_reg,&sc->sc_gr[regn]);
78 		regs->gr[regn] = compat_reg;
79 		/* Load upper half */
80 		err |= __get_user(compat_regt,&rf->rf_gr[regn]);
81 		regs->gr[regn] = ((u64)compat_regt << 32) | (u64)compat_reg;
82 		DBG(3,"restore_sigcontext32: gr%02d = %#lx (%#x / %#x)\n",
83 				regn, regs->gr[regn], compat_regt, compat_reg);
84 	}
85 	DBG(2,"restore_sigcontext32: sc->sc_fr = 0x%p (%#lx)\n",sc->sc_fr, sizeof(sc->sc_fr));
86 	/* XXX: BE WARNED FR's are 64-BIT! */
87 	err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
88 
89 	/* Better safe than sorry, pass __get_user two things of
90 	   the same size and let gcc do the upward conversion to
91 	   64-bits */
92 	err |= __get_user(compat_reg, &sc->sc_iaoq[0]);
93 	/* Load upper half */
94 	err |= __get_user(compat_regt, &rf->rf_iaoq[0]);
95 	regs->iaoq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
96 	DBG(2,"restore_sigcontext32: upper half of iaoq[0] = %#lx\n", compat_regt);
97 	DBG(2,"restore_sigcontext32: sc->sc_iaoq[0] = %p => %#x\n",
98 			&sc->sc_iaoq[0], compat_reg);
99 
100 	err |= __get_user(compat_reg, &sc->sc_iaoq[1]);
101 	/* Load upper half */
102 	err |= __get_user(compat_regt, &rf->rf_iaoq[1]);
103 	regs->iaoq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
104 	DBG(2,"restore_sigcontext32: upper half of iaoq[1] = %#lx\n", compat_regt);
105 	DBG(2,"restore_sigcontext32: sc->sc_iaoq[1] = %p => %#x\n",
106 			&sc->sc_iaoq[1],compat_reg);
107 	DBG(2,"restore_sigcontext32: iaoq is %#lx / %#lx\n",
108 			regs->iaoq[0],regs->iaoq[1]);
109 
110 	err |= __get_user(compat_reg, &sc->sc_iasq[0]);
111 	/* Load the upper half for iasq */
112 	err |= __get_user(compat_regt, &rf->rf_iasq[0]);
113 	regs->iasq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
114 	DBG(2,"restore_sigcontext32: upper half of iasq[0] = %#lx\n", compat_regt);
115 
116 	err |= __get_user(compat_reg, &sc->sc_iasq[1]);
117 	/* Load the upper half for iasq */
118 	err |= __get_user(compat_regt, &rf->rf_iasq[1]);
119 	regs->iasq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
120 	DBG(2,"restore_sigcontext32: upper half of iasq[1] = %#lx\n", compat_regt);
121 	DBG(2,"restore_sigcontext32: iasq is %#lx / %#lx\n",
122 		regs->iasq[0],regs->iasq[1]);
123 
124 	err |= __get_user(compat_reg, &sc->sc_sar);
125 	/* Load the upper half for sar */
126 	err |= __get_user(compat_regt, &rf->rf_sar);
127 	regs->sar = ((u64)compat_regt << 32) | (u64)compat_reg;
128 	DBG(2,"restore_sigcontext32: upper_half & sar = %#lx\n", compat_regt);
129 	DBG(2,"restore_sigcontext32: sar is %#lx\n", regs->sar);
130 	DBG(2,"restore_sigcontext32: r28 is %ld\n", regs->gr[28]);
131 
132 	return err;
133 }
134 
135 /*
136  * Set up the sigcontext structure for this process.
137  * This is not an easy task if the kernel is 64-bit, it will require
138  * that we examine the process personality to determine if we need to
139  * truncate for a 32-bit userspace.
140  */
141 long
142 setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
143 		struct pt_regs *regs, int in_syscall)
144 {
145 	compat_int_t flags = 0;
146 	long err = 0;
147 	compat_uint_t compat_reg;
148 	compat_uint_t compat_regb;
149 	int regn;
150 
151 	if (on_sig_stack((unsigned long) sc))
152 		flags |= PARISC_SC_FLAG_ONSTACK;
153 
154 	if (in_syscall) {
155 
156 		DBG(1,"setup_sigcontext32: in_syscall\n");
157 
158 		flags |= PARISC_SC_FLAG_IN_SYSCALL;
159 		/* Truncate gr31 */
160 		compat_reg = (compat_uint_t)(regs->gr[31]);
161 		/* regs->iaoq is undefined in the syscall return path */
162 		err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
163 		DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
164 				&sc->sc_iaoq[0], compat_reg);
165 
166 		/* Store upper half */
167 		compat_reg = (compat_uint_t)(regs->gr[31] >> 32);
168 		err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
169 		DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
170 
171 
172 		compat_reg = (compat_uint_t)(regs->gr[31]+4);
173 		err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
174 		DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
175 				&sc->sc_iaoq[1], compat_reg);
176 		/* Store upper half */
177 		compat_reg = (compat_uint_t)((regs->gr[31]+4) >> 32);
178 		err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
179 		DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
180 
181 		/* Truncate sr3 */
182 		compat_reg = (compat_uint_t)(regs->sr[3]);
183 		err |= __put_user(compat_reg, &sc->sc_iasq[0]);
184 		err |= __put_user(compat_reg, &sc->sc_iasq[1]);
185 
186 		/* Store upper half */
187 		compat_reg = (compat_uint_t)(regs->sr[3] >> 32);
188 		err |= __put_user(compat_reg, &rf->rf_iasq[0]);
189 		err |= __put_user(compat_reg, &rf->rf_iasq[1]);
190 
191 		DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
192 		DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
193 		DBG(1,"setup_sigcontext32: iaoq %#lx / %#lx\n",
194 			regs->gr[31], regs->gr[31]+4);
195 
196 	} else {
197 
198 		compat_reg = (compat_uint_t)(regs->iaoq[0]);
199 		err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
200 		DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
201 				&sc->sc_iaoq[0], compat_reg);
202 		/* Store upper half */
203 		compat_reg = (compat_uint_t)(regs->iaoq[0] >> 32);
204 		err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
205 		DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
206 
207 		compat_reg = (compat_uint_t)(regs->iaoq[1]);
208 		err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
209 		DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
210 				&sc->sc_iaoq[1], compat_reg);
211 		/* Store upper half */
212 		compat_reg = (compat_uint_t)(regs->iaoq[1] >> 32);
213 		err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
214 		DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
215 
216 
217 		compat_reg = (compat_uint_t)(regs->iasq[0]);
218 		err |= __put_user(compat_reg, &sc->sc_iasq[0]);
219 		DBG(2,"setup_sigcontext32: sc->sc_iasq[0] = %p <= %#x\n",
220 				&sc->sc_iasq[0], compat_reg);
221 		/* Store upper half */
222 		compat_reg = (compat_uint_t)(regs->iasq[0] >> 32);
223 		err |= __put_user(compat_reg, &rf->rf_iasq[0]);
224 		DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
225 
226 
227 		compat_reg = (compat_uint_t)(regs->iasq[1]);
228 		err |= __put_user(compat_reg, &sc->sc_iasq[1]);
229 		DBG(2,"setup_sigcontext32: sc->sc_iasq[1] = %p <= %#x\n",
230 				&sc->sc_iasq[1], compat_reg);
231 		/* Store upper half */
232 		compat_reg = (compat_uint_t)(regs->iasq[1] >> 32);
233 		err |= __put_user(compat_reg, &rf->rf_iasq[1]);
234 		DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
235 
236 		/* Print out the IAOQ for debugging */
237 		DBG(1,"setup_sigcontext32: ia0q %#lx / %#lx\n",
238 			regs->iaoq[0], regs->iaoq[1]);
239 	}
240 
241 	err |= __put_user(flags, &sc->sc_flags);
242 
243 	DBG(1,"setup_sigcontext32: Truncating general registers.\n");
244 
245 	for(regn=0; regn < 32; regn++){
246 		/* Truncate a general register */
247 		compat_reg = (compat_uint_t)(regs->gr[regn]);
248 		err |= __put_user(compat_reg, &sc->sc_gr[regn]);
249 		/* Store upper half */
250 		compat_regb = (compat_uint_t)(regs->gr[regn] >> 32);
251 		err |= __put_user(compat_regb, &rf->rf_gr[regn]);
252 
253 		/* DEBUG: Write out the "upper / lower" register data */
254 		DBG(2,"setup_sigcontext32: gr%02d = %#x / %#x\n", regn,
255 				compat_regb, compat_reg);
256 	}
257 
258 	/* Copy the floating point registers (same size)
259 	   XXX: BE WARNED FR's are 64-BIT! */
260 	DBG(1,"setup_sigcontext32: Copying from regs to sc, "
261 	      "sc->sc_fr size = %#lx, regs->fr size = %#lx\n",
262 		sizeof(regs->fr), sizeof(sc->sc_fr));
263 	err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
264 
265 	compat_reg = (compat_uint_t)(regs->sar);
266 	err |= __put_user(compat_reg, &sc->sc_sar);
267 	DBG(2,"setup_sigcontext32: sar is %#x\n", compat_reg);
268 	/* Store upper half */
269 	compat_reg = (compat_uint_t)(regs->sar >> 32);
270 	err |= __put_user(compat_reg, &rf->rf_sar);
271 	DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg);
272 	DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]);
273 
274 	return err;
275 }
276 
277 int
278 copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
279 {
280 	compat_uptr_t addr;
281 	int err;
282 
283 	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
284 		return -EFAULT;
285 
286 	err = __get_user(to->si_signo, &from->si_signo);
287 	err |= __get_user(to->si_errno, &from->si_errno);
288 	err |= __get_user(to->si_code, &from->si_code);
289 
290 	if (to->si_code < 0)
291 		err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
292 	else {
293 		switch (to->si_code >> 16) {
294 		      case __SI_CHLD >> 16:
295 			err |= __get_user(to->si_utime, &from->si_utime);
296 			err |= __get_user(to->si_stime, &from->si_stime);
297 			err |= __get_user(to->si_status, &from->si_status);
298 		      default:
299 			err |= __get_user(to->si_pid, &from->si_pid);
300 			err |= __get_user(to->si_uid, &from->si_uid);
301 			break;
302 		      case __SI_FAULT >> 16:
303 			err |= __get_user(addr, &from->si_addr);
304 			to->si_addr = compat_ptr(addr);
305 			break;
306 		      case __SI_POLL >> 16:
307 			err |= __get_user(to->si_band, &from->si_band);
308 			err |= __get_user(to->si_fd, &from->si_fd);
309 			break;
310 		      case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
311 		      case __SI_MESGQ >> 16:
312 			err |= __get_user(to->si_pid, &from->si_pid);
313 			err |= __get_user(to->si_uid, &from->si_uid);
314 			err |= __get_user(to->si_int, &from->si_int);
315 			break;
316 		}
317 	}
318 	return err;
319 }
320 
321 int
322 copy_siginfo_to_user32 (compat_siginfo_t __user *to, const siginfo_t *from)
323 {
324 	compat_uptr_t addr;
325 	compat_int_t val;
326 	int err;
327 
328 	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
329 		return -EFAULT;
330 
331 	/* If you change siginfo_t structure, please be sure
332 	   this code is fixed accordingly.
333 	   It should never copy any pad contained in the structure
334 	   to avoid security leaks, but must copy the generic
335 	   3 ints plus the relevant union member.
336 	   This routine must convert siginfo from 64bit to 32bit as well
337 	   at the same time.  */
338 	err = __put_user(from->si_signo, &to->si_signo);
339 	err |= __put_user(from->si_errno, &to->si_errno);
340 	err |= __put_user((short)from->si_code, &to->si_code);
341 	if (from->si_code < 0)
342 		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
343 	else {
344 		switch (from->si_code >> 16) {
345 		case __SI_CHLD >> 16:
346 			err |= __put_user(from->si_utime, &to->si_utime);
347 			err |= __put_user(from->si_stime, &to->si_stime);
348 			err |= __put_user(from->si_status, &to->si_status);
349 		default:
350 			err |= __put_user(from->si_pid, &to->si_pid);
351 			err |= __put_user(from->si_uid, &to->si_uid);
352 			break;
353 		case __SI_FAULT >> 16:
354 			addr = ptr_to_compat(from->si_addr);
355 			err |= __put_user(addr, &to->si_addr);
356 			break;
357 		case __SI_POLL >> 16:
358 			err |= __put_user(from->si_band, &to->si_band);
359 			err |= __put_user(from->si_fd, &to->si_fd);
360 			break;
361 		case __SI_TIMER >> 16:
362 			err |= __put_user(from->si_tid, &to->si_tid);
363 			err |= __put_user(from->si_overrun, &to->si_overrun);
364 			val = (compat_int_t)from->si_int;
365 			err |= __put_user(val, &to->si_int);
366 			break;
367 		case __SI_RT >> 16:	/* Not generated by the kernel as of now.  */
368 		case __SI_MESGQ >> 16:
369 			err |= __put_user(from->si_uid, &to->si_uid);
370 			err |= __put_user(from->si_pid, &to->si_pid);
371 			val = (compat_int_t)from->si_int;
372 			err |= __put_user(val, &to->si_int);
373 			break;
374 		case __SI_SYS >> 16:
375 			err |= __put_user(ptr_to_compat(from->si_call_addr), &to->si_call_addr);
376 			err |= __put_user(from->si_syscall, &to->si_syscall);
377 			err |= __put_user(from->si_arch, &to->si_arch);
378 			break;
379 		}
380 	}
381 	return err;
382 }
383