linux-old/arch/parisc/kernel/signal32.c
<<
>>
Prefs
   1/* mostly borrowed from kernel/signal.c */
   2#include <linux/config.h>
   3#include <linux/slab.h>
   4#include <linux/module.h>
   5#include <linux/unistd.h>
   6#include <linux/smp_lock.h>
   7#include <linux/init.h>
   8#include <linux/sched.h>
   9#include <linux/types.h>
  10
  11#include <asm/uaccess.h>
  12#include "sys32.h"
  13
  14struct k_sigaction32 {
  15        struct sigaction32 sa;
  16};
  17
  18typedef unsigned int old_sigset_t32;
  19
  20static int
  21put_old_sigset32(old_sigset_t32 *up, old_sigset_t *set)
  22{
  23        old_sigset_t32 set32 = *set;
  24        return put_user(set32, up);
  25}
  26
  27static int
  28get_old_segset32(old_sigset_t32 *up, old_sigset_t *set)
  29{
  30        old_sigset_t32 set32;
  31        int r;
  32
  33        if ((r = get_user(set32, up)) == 0)
  34                *set = set32;
  35
  36        return r;
  37}
  38
  39long
  40sys32_sigpending(old_sigset_t32 *set)
  41{
  42        extern long sys_sigpending(old_sigset_t *set);
  43        old_sigset_t pending;
  44        int ret;
  45
  46        KERNEL_SYSCALL(ret, sys_sigpending, &pending);
  47
  48        /* can't put_user an old_sigset_t -- it is too big */
  49        if (put_old_sigset32(set, &pending))
  50                return -EFAULT;
  51
  52        return ret;
  53}
  54
  55int sys32_sigprocmask(int how, old_sigset_t32 *set, 
  56                                 old_sigset_t32 *oset)
  57{
  58        extern int sys_sigprocmask(int how, old_sigset_t *set, 
  59                                 old_sigset_t *oset);
  60        old_sigset_t s;
  61        int ret;
  62
  63        if (set && get_old_segset32 (set, &s))
  64                return -EFAULT;
  65        KERNEL_SYSCALL(ret, sys_sigprocmask, how, set ? &s : NULL, oset ? &s : NULL);
  66        if (!ret && oset && put_old_sigset32(oset, &s))
  67                return -EFAULT;
  68        return ret;
  69}
  70
  71static inline void
  72sigset_32to64(sigset_t *s64, sigset_t32 *s32)
  73{
  74        s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
  75}
  76
  77static inline void
  78sigset_64to32(sigset_t32 *s32, sigset_t *s64)
  79{
  80        s32->sig[0] = s64->sig[0] & 0xffffffffUL;
  81        s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL;
  82}
  83
  84static int
  85put_sigset32(sigset_t32 *up, sigset_t *set, size_t sz)
  86{
  87        sigset_t32 s;
  88
  89        if (sz != sizeof *set) panic("put_sigset32()");
  90        sigset_64to32(&s, set);
  91
  92        return copy_to_user(up, &s, sizeof s);
  93}
  94
  95static int
  96get_sigset32(sigset_t32 *up, sigset_t *set, size_t sz)
  97{
  98        sigset_t32 s;
  99        int r;
 100
 101        if (sz != sizeof *set) panic("put_sigset32()");
 102
 103        if ((r = copy_from_user(&s, up, sz)) == 0) {
 104                sigset_32to64(set, &s);
 105        }
 106
 107        return r;
 108}
 109
 110int sys32_rt_sigprocmask(int how, sigset_t32 *set, sigset_t32 *oset,
 111                                    unsigned int sigsetsize)
 112{
 113        extern long sys_rt_sigprocmask(int how,
 114                                    sigset_t *set, sigset_t *oset,
 115                                   size_t sigsetsize);
 116        sigset_t old_set, new_set;
 117        int ret;
 118
 119        if (set && get_sigset32(set, &new_set, sigsetsize))
 120                return -EFAULT;
 121        
 122        KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? &new_set : NULL,
 123                                 oset ? &old_set : NULL, sigsetsize);
 124
 125        if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize))
 126                return -EFAULT;
 127
 128        return ret;
 129}
 130
 131
 132int sys32_rt_sigpending(sigset_t32 *uset, unsigned int sigsetsize)
 133{
 134        int ret;
 135        sigset_t set;
 136        extern long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
 137
 138        KERNEL_SYSCALL(ret, sys_rt_sigpending, &set, sigsetsize);
 139
 140        if (!ret && put_sigset32(uset, &set, sigsetsize))
 141                return -EFAULT;
 142
 143        return ret;
 144}
 145
 146long
 147sys32_rt_sigaction(int sig, const struct sigaction32 *act, struct sigaction32 *oact,
 148                 size_t sigsetsize)
 149{
 150        struct k_sigaction32 new_sa32, old_sa32;
 151        struct k_sigaction new_sa, old_sa;
 152        int ret = -EINVAL;
 153
 154        if (act) {
 155                if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa))
 156                        return -EFAULT;
 157                new_sa.sa.sa_handler = (__sighandler_t)(unsigned long)new_sa32.sa.sa_handler;
 158                new_sa.sa.sa_flags = new_sa32.sa.sa_flags;
 159                sigset_32to64(&new_sa.sa.sa_mask, &new_sa32.sa.sa_mask);
 160        }
 161
 162        ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
 163
 164        if (!ret && oact) {
 165                sigset_64to32(&old_sa32.sa.sa_mask, &old_sa.sa.sa_mask);
 166                old_sa32.sa.sa_flags = old_sa.sa.sa_flags;
 167                old_sa32.sa.sa_handler = (__sighandler_t32)(unsigned long)old_sa.sa.sa_handler;
 168                if (copy_to_user(oact, &old_sa32.sa, sizeof old_sa32.sa))
 169                        return -EFAULT;
 170        }
 171        return ret;
 172}
 173
 174typedef struct {
 175        unsigned int ss_sp;
 176        int ss_flags;
 177        __kernel_size_t32 ss_size;
 178} stack_t32;
 179
 180int 
 181do_sigaltstack32 (const stack_t32 *uss32, stack_t32 *uoss32, unsigned long sp)
 182{
 183        stack_t32 ss32, oss32;
 184        stack_t ss, oss;
 185        stack_t *ssp = NULL, *ossp = NULL;
 186        int ret;
 187
 188        if (uss32) {
 189                if (copy_from_user(&ss32, uss32, sizeof ss32))
 190                        return -EFAULT;
 191
 192                ss.ss_sp = (void *)ss32.ss_sp;
 193                ss.ss_flags = ss32.ss_flags;
 194                ss.ss_size = ss32.ss_size;
 195
 196                ssp = &ss;
 197        }
 198
 199        if (uoss32)
 200                ossp = &oss;
 201
 202        KERNEL_SYSCALL(ret, do_sigaltstack, ssp, ossp, sp);
 203
 204        if (!ret && uoss32) {
 205                oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp;
 206                oss32.ss_flags = oss.ss_flags;
 207                oss32.ss_size = oss.ss_size;
 208                if (copy_to_user(uoss32, &oss32, sizeof *uoss32))
 209                        return -EFAULT;
 210        }
 211
 212        return ret;
 213}
 214
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.