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#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
  50inline void
  51sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
  52{
  53        s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
  54}
  55
  56inline void
  57sigset_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
  63long
  64restore_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 */
 142long
 143setup_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
 278int
 279copy_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
 322int
 323copy_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}
 379