linux/arch/parisc/kernel/sys_parisc32.c
<<
>>
Prefs
   1/*
   2 * sys_parisc32.c: Conversion between 32bit and 64bit native syscalls.
   3 *
   4 * Copyright (C) 2000-2001 Hewlett Packard Company
   5 * Copyright (C) 2000 John Marvin
   6 * Copyright (C) 2001 Matthew Wilcox
   7 *
   8 * These routines maintain argument size conversion between 32bit and 64bit
   9 * environment. Based heavily on sys_ia32.c and sys_sparc32.c.
  10 */
  11
  12#include <linux/compat.h>
  13#include <linux/kernel.h>
  14#include <linux/sched.h>
  15#include <linux/fs.h> 
  16#include <linux/mm.h> 
  17#include <linux/file.h> 
  18#include <linux/signal.h>
  19#include <linux/resource.h>
  20#include <linux/times.h>
  21#include <linux/time.h>
  22#include <linux/smp.h>
  23#include <linux/smp_lock.h>
  24#include <linux/sem.h>
  25#include <linux/msg.h>
  26#include <linux/shm.h>
  27#include <linux/slab.h>
  28#include <linux/uio.h>
  29#include <linux/nfs_fs.h>
  30#include <linux/ncp_fs.h>
  31#include <linux/sunrpc/svc.h>
  32#include <linux/nfsd/nfsd.h>
  33#include <linux/nfsd/cache.h>
  34#include <linux/nfsd/xdr.h>
  35#include <linux/nfsd/syscall.h>
  36#include <linux/poll.h>
  37#include <linux/personality.h>
  38#include <linux/stat.h>
  39#include <linux/highmem.h>
  40#include <linux/highuid.h>
  41#include <linux/mman.h>
  42#include <linux/binfmts.h>
  43#include <linux/namei.h>
  44#include <linux/vfs.h>
  45#include <linux/ptrace.h>
  46#include <linux/swap.h>
  47#include <linux/syscalls.h>
  48
  49#include <asm/types.h>
  50#include <asm/uaccess.h>
  51#include <asm/mmu_context.h>
  52
  53#include "sys32.h"
  54
  55#undef DEBUG
  56
  57#ifdef DEBUG
  58#define DBG(x)  printk x
  59#else
  60#define DBG(x)
  61#endif
  62
  63/*
  64 * sys32_execve() executes a new program.
  65 */
  66
  67asmlinkage int sys32_execve(struct pt_regs *regs)
  68{
  69        int error;
  70        char *filename;
  71
  72        DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
  73        filename = getname((const char __user *) regs->gr[26]);
  74        error = PTR_ERR(filename);
  75        if (IS_ERR(filename))
  76                goto out;
  77        error = compat_do_execve(filename, compat_ptr(regs->gr[25]),
  78                                 compat_ptr(regs->gr[24]), regs);
  79        putname(filename);
  80out:
  81
  82        return error;
  83}
  84
  85asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,
  86        int r22, int r21, int r20)
  87{
  88    printk(KERN_ERR "%s(%d): Unimplemented 32 on 64 syscall #%d!\n", 
  89        current->comm, current->pid, r20);
  90    return -ENOSYS;
  91}
  92
  93#ifdef CONFIG_SYSCTL
  94
  95struct __sysctl_args32 {
  96        u32 name;
  97        int nlen;
  98        u32 oldval;
  99        u32 oldlenp;
 100        u32 newval;
 101        u32 newlen;
 102        u32 __unused[4];
 103};
 104
 105asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
 106{
 107#ifndef CONFIG_SYSCTL_SYSCALL
 108        return -ENOSYS;
 109#else
 110        struct __sysctl_args32 tmp;
 111        int error;
 112        unsigned int oldlen32;
 113        size_t oldlen, __user *oldlenp = NULL;
 114        unsigned long addr = (((long __force)&args->__unused[0]) + 7) & ~7;
 115
 116        DBG(("sysctl32(%p)\n", args));
 117
 118        if (copy_from_user(&tmp, args, sizeof(tmp)))
 119                return -EFAULT;
 120
 121        if (tmp.oldval && tmp.oldlenp) {
 122                /* Duh, this is ugly and might not work if sysctl_args
 123                   is in read-only memory, but do_sysctl does indirectly
 124                   a lot of uaccess in both directions and we'd have to
 125                   basically copy the whole sysctl.c here, and
 126                   glibc's __sysctl uses rw memory for the structure
 127                   anyway.  */
 128                /* a possibly better hack than this, which will avoid the
 129                 * problem if the struct is read only, is to push the
 130                 * 'oldlen' value out to the user's stack instead. -PB
 131                 */
 132                if (get_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
 133                        return -EFAULT;
 134                oldlen = oldlen32;
 135                if (put_user(oldlen, (size_t *)addr))
 136                        return -EFAULT;
 137                oldlenp = (size_t *)addr;
 138        }
 139
 140        lock_kernel();
 141        error = do_sysctl((int __user *)(u64)tmp.name, tmp.nlen,
 142                          (void __user *)(u64)tmp.oldval, oldlenp,
 143                          (void __user *)(u64)tmp.newval, tmp.newlen);
 144        unlock_kernel();
 145        if (oldlenp) {
 146                if (!error) {
 147                        if (get_user(oldlen, (size_t *)addr)) {
 148                                error = -EFAULT;
 149                        } else {
 150                                oldlen32 = oldlen;
 151                                if (put_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
 152                                        error = -EFAULT;
 153                        }
 154                }
 155                if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
 156                        error = -EFAULT;
 157        }
 158        return error;
 159#endif
 160}
 161
 162#endif /* CONFIG_SYSCTL */
 163
 164asmlinkage long sys32_sched_rr_get_interval(pid_t pid,
 165        struct compat_timespec __user *interval)
 166{
 167        struct timespec t;
 168        int ret;
 169
 170        KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, (struct timespec __user *)&t);
 171        if (put_compat_timespec(&t, interval))
 172                return -EFAULT;
 173        return ret;
 174}
 175
 176struct msgbuf32 {
 177    int mtype;
 178    char mtext[1];
 179};
 180
 181asmlinkage long sys32_msgsnd(int msqid,
 182                                struct msgbuf32 __user *umsgp32,
 183                                size_t msgsz, int msgflg)
 184{
 185        struct msgbuf *mb;
 186        struct msgbuf32 mb32;
 187        int err;
 188
 189        if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)
 190                return -ENOMEM;
 191
 192        err = get_user(mb32.mtype, &umsgp32->mtype);
 193        mb->mtype = mb32.mtype;
 194        err |= copy_from_user(mb->mtext, &umsgp32->mtext, msgsz);
 195
 196        if (err)
 197                err = -EFAULT;
 198        else
 199                KERNEL_SYSCALL(err, sys_msgsnd, msqid, (struct msgbuf __user *)mb, msgsz, msgflg);
 200
 201        kfree(mb);
 202        return err;
 203}
 204
 205asmlinkage long sys32_msgrcv(int msqid,
 206                                struct msgbuf32 __user *umsgp32,
 207                                size_t msgsz, long msgtyp, int msgflg)
 208{
 209        struct msgbuf *mb;
 210        struct msgbuf32 mb32;
 211        int err, len;
 212
 213        if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)
 214                return -ENOMEM;
 215
 216        KERNEL_SYSCALL(err, sys_msgrcv, msqid, (struct msgbuf __user *)mb, msgsz, msgtyp, msgflg);
 217
 218        if (err >= 0) {
 219                len = err;
 220                mb32.mtype = mb->mtype;
 221                err = put_user(mb32.mtype, &umsgp32->mtype);
 222                err |= copy_to_user(&umsgp32->mtext, mb->mtext, len);
 223                if (err)
 224                        err = -EFAULT;
 225                else
 226                        err = len;
 227        }
 228
 229        kfree(mb);
 230        return err;
 231}
 232
 233asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count)
 234{
 235        mm_segment_t old_fs = get_fs();
 236        int ret;
 237        off_t of;
 238
 239        if (offset && get_user(of, offset))
 240                return -EFAULT;
 241
 242        set_fs(KERNEL_DS);
 243        ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count);
 244        set_fs(old_fs);
 245
 246        if (offset && put_user(of, offset))
 247                return -EFAULT;
 248
 249        return ret;
 250}
 251
 252asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count)
 253{
 254        mm_segment_t old_fs = get_fs();
 255        int ret;
 256        loff_t lof;
 257        
 258        if (offset && get_user(lof, offset))
 259                return -EFAULT;
 260                
 261        set_fs(KERNEL_DS);
 262        ret = sys_sendfile64(out_fd, in_fd, offset ? (loff_t __user *)&lof : NULL, count);
 263        set_fs(old_fs);
 264        
 265        if (offset && put_user(lof, offset))
 266                return -EFAULT;
 267                
 268        return ret;
 269}
 270
 271
 272/* lseek() needs a wrapper because 'offset' can be negative, but the top
 273 * half of the argument has been zeroed by syscall.S.
 274 */
 275
 276asmlinkage int sys32_lseek(unsigned int fd, int offset, unsigned int origin)
 277{
 278        return sys_lseek(fd, offset, origin);
 279}
 280
 281asmlinkage long sys32_semctl(int semid, int semnum, int cmd, union semun arg)
 282{
 283        union semun u;
 284        
 285        if (cmd == SETVAL) {
 286                /* Ugh.  arg is a union of int,ptr,ptr,ptr, so is 8 bytes.
 287                 * The int should be in the first 4, but our argument
 288                 * frobbing has left it in the last 4.
 289                 */
 290                u.val = *((int *)&arg + 1);
 291                return sys_semctl (semid, semnum, cmd, u);
 292        }
 293        return sys_semctl (semid, semnum, cmd, arg);
 294}
 295
 296long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
 297                          size_t len)
 298{
 299        return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
 300                                  buf, len);
 301}
 302
 303asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo,
 304                                u32 lenhi, u32 lenlo)
 305{
 306        return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo,
 307                             ((loff_t)lenhi << 32) | lenlo);
 308}
 309
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.