linux/arch/parisc/kernel/signal32.c
<<
>>
Prefs
   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
  49inline void
  50sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
  51{
  52        s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
  53}
  54
  55inline void
  56sigset_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
  62long
  63restore_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 */
 141long
 142setup_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
 277int
 278copy_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
 321int
 322copy_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