~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/parisc/kernel/signal32.c

Version: ~ [ linux-5.4-rc3 ] ~ [ linux-5.3.6 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.79 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.149 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.196 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.196 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.75 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp