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