linux-old/arch/sparc64/kernel/sys_sparc32.c
<<
>>
Prefs
   1/* $Id: sys_sparc32.c,v 1.182.2.1 2002/02/20 08:49:24 davem Exp $
   2 * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
   3 *
   4 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
   5 * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
   6 *
   7 * These routines maintain argument size conversion between 32bit and 64bit
   8 * environment.
   9 */
  10
  11#include <linux/config.h>
  12#include <linux/kernel.h>
  13#include <linux/sched.h>
  14#include <linux/fs.h> 
  15#include <linux/mm.h> 
  16#include <linux/file.h> 
  17#include <linux/signal.h>
  18#include <linux/utime.h>
  19#include <linux/resource.h>
  20#include <linux/times.h>
  21#include <linux/utsname.h>
  22#include <linux/timex.h>
  23#include <linux/smp.h>
  24#include <linux/smp_lock.h>
  25#include <linux/sem.h>
  26#include <linux/msg.h>
  27#include <linux/shm.h>
  28#include <linux/slab.h>
  29#include <linux/uio.h>
  30#include <linux/nfs_fs.h>
  31#include <linux/smb_fs.h>
  32#include <linux/smb_mount.h>
  33#include <linux/ncp_fs.h>
  34#include <linux/quota.h>
  35#include <linux/quotacompat.h>
  36#include <linux/module.h>
  37#include <linux/sunrpc/svc.h>
  38#include <linux/nfsd/nfsd.h>
  39#include <linux/nfsd/cache.h>
  40#include <linux/nfsd/xdr.h>
  41#include <linux/nfsd/syscall.h>
  42#include <linux/poll.h>
  43#include <linux/personality.h>
  44#include <linux/stat.h>
  45#include <linux/filter.h>
  46#include <linux/highmem.h>
  47#include <linux/highuid.h>
  48#include <linux/mman.h>
  49#include <linux/ipv6.h>
  50#include <linux/in.h>
  51#include <linux/icmpv6.h>
  52#include <linux/sysctl.h>
  53#include <linux/dnotify.h>
  54#include <linux/netfilter_ipv4/ip_tables.h>
  55
  56#include <asm/types.h>
  57#include <asm/ipc.h>
  58#include <asm/uaccess.h>
  59#include <asm/fpumacro.h>
  60#include <asm/semaphore.h>
  61
  62#include <net/scm.h>
  63
  64/* Use this to get at 32-bit user passed pointers. */
  65/* Things to consider: the low-level assembly stub does
  66   srl x, 0, x for first four arguments, so if you have
  67   pointer to something in the first four arguments, just
  68   declare it as a pointer, not u32. On the other side, 
  69   arguments from 5th onwards should be declared as u32
  70   for pointers, and need AA() around each usage.
  71   A() macro should be used for places where you e.g.
  72   have some internal variable u32 and just want to get
  73   rid of a compiler warning. AA() has to be used in
  74   places where you want to convert a function argument
  75   to 32bit pointer or when you e.g. access pt_regs
  76   structure and want to consider 32bit registers only.
  77   -jj
  78 */
  79#define A(__x) ((unsigned long)(__x))
  80#define AA(__x)                         \
  81({      unsigned long __ret;            \
  82        __asm__ ("srl   %0, 0, %0"      \
  83                 : "=r" (__ret)         \
  84                 : "0" (__x));          \
  85        __ret;                          \
  86})
  87
  88extern asmlinkage long sys_chown(const char *, uid_t,gid_t);
  89extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);
  90extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);
  91extern asmlinkage long sys_setregid(gid_t, gid_t);
  92extern asmlinkage long sys_setgid(gid_t);
  93extern asmlinkage long sys_setreuid(uid_t, uid_t);
  94extern asmlinkage long sys_setuid(uid_t);
  95extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t);
  96extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t);
  97extern asmlinkage long sys_setfsuid(uid_t);
  98extern asmlinkage long sys_setfsgid(gid_t);
  99 
 100/* For this source file, we want overflow handling. */
 101
 102#undef high2lowuid
 103#undef high2lowgid
 104#undef low2highuid
 105#undef low2highgid
 106#undef SET_UID16
 107#undef SET_GID16
 108#undef NEW_TO_OLD_UID
 109#undef NEW_TO_OLD_GID
 110#undef SET_OLDSTAT_UID
 111#undef SET_OLDSTAT_GID
 112#undef SET_STAT_UID
 113#undef SET_STAT_GID
 114
 115#define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
 116#define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
 117#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)
 118#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)
 119#define SET_UID16(var, uid)     var = high2lowuid(uid)
 120#define SET_GID16(var, gid)     var = high2lowgid(gid)
 121#define NEW_TO_OLD_UID(uid)     high2lowuid(uid)
 122#define NEW_TO_OLD_GID(gid)     high2lowgid(gid)
 123#define SET_OLDSTAT_UID(stat, uid)      (stat).st_uid = high2lowuid(uid)
 124#define SET_OLDSTAT_GID(stat, gid)      (stat).st_gid = high2lowgid(gid)
 125#define SET_STAT_UID(stat, uid)         (stat).st_uid = high2lowuid(uid)
 126#define SET_STAT_GID(stat, gid)         (stat).st_gid = high2lowgid(gid)
 127
 128asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
 129{
 130        return sys_chown(filename, low2highuid(user), low2highgid(group));
 131}
 132
 133asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group)
 134{
 135        return sys_lchown(filename, low2highuid(user), low2highgid(group));
 136}
 137
 138asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
 139{
 140        return sys_fchown(fd, low2highuid(user), low2highgid(group));
 141}
 142
 143asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
 144{
 145        return sys_setregid(low2highgid(rgid), low2highgid(egid));
 146}
 147
 148asmlinkage long sys32_setgid16(u16 gid)
 149{
 150        return sys_setgid((gid_t)gid);
 151}
 152
 153asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
 154{
 155        return sys_setreuid(low2highuid(ruid), low2highuid(euid));
 156}
 157
 158asmlinkage long sys32_setuid16(u16 uid)
 159{
 160        return sys_setuid((uid_t)uid);
 161}
 162
 163asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
 164{
 165        return sys_setresuid(low2highuid(ruid), low2highuid(euid),
 166                low2highuid(suid));
 167}
 168
 169asmlinkage long sys32_getresuid16(u16 *ruid, u16 *euid, u16 *suid)
 170{
 171        int retval;
 172
 173        if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
 174            !(retval = put_user(high2lowuid(current->euid), euid)))
 175                retval = put_user(high2lowuid(current->suid), suid);
 176
 177        return retval;
 178}
 179
 180asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
 181{
 182        return sys_setresgid(low2highgid(rgid), low2highgid(egid),
 183                low2highgid(sgid));
 184}
 185
 186asmlinkage long sys32_getresgid16(u16 *rgid, u16 *egid, u16 *sgid)
 187{
 188        int retval;
 189
 190        if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
 191            !(retval = put_user(high2lowgid(current->egid), egid)))
 192                retval = put_user(high2lowgid(current->sgid), sgid);
 193
 194        return retval;
 195}
 196
 197asmlinkage long sys32_setfsuid16(u16 uid)
 198{
 199        return sys_setfsuid((uid_t)uid);
 200}
 201
 202asmlinkage long sys32_setfsgid16(u16 gid)
 203{
 204        return sys_setfsgid((gid_t)gid);
 205}
 206
 207asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
 208{
 209        u16 groups[NGROUPS];
 210        int i,j;
 211
 212        if (gidsetsize < 0)
 213                return -EINVAL;
 214        i = current->ngroups;
 215        if (gidsetsize) {
 216                if (i > gidsetsize)
 217                        return -EINVAL;
 218                for(j=0;j<i;j++)
 219                        groups[j] = current->groups[j];
 220                if (copy_to_user(grouplist, groups, sizeof(u16)*i))
 221                        return -EFAULT;
 222        }
 223        return i;
 224}
 225
 226asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
 227{
 228        u16 groups[NGROUPS];
 229        int i;
 230
 231        if (!capable(CAP_SETGID))
 232                return -EPERM;
 233        if ((unsigned) gidsetsize > NGROUPS)
 234                return -EINVAL;
 235        if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))
 236                return -EFAULT;
 237        for (i = 0 ; i < gidsetsize ; i++)
 238                current->groups[i] = (gid_t)groups[i];
 239        current->ngroups = gidsetsize;
 240        return 0;
 241}
 242
 243asmlinkage long sys32_getuid16(void)
 244{
 245        return high2lowuid(current->uid);
 246}
 247
 248asmlinkage long sys32_geteuid16(void)
 249{
 250        return high2lowuid(current->euid);
 251}
 252
 253asmlinkage long sys32_getgid16(void)
 254{
 255        return high2lowgid(current->gid);
 256}
 257
 258asmlinkage long sys32_getegid16(void)
 259{
 260        return high2lowgid(current->egid);
 261}
 262
 263/* 32-bit timeval and related flotsam.  */
 264
 265struct timeval32
 266{
 267    int tv_sec, tv_usec;
 268};
 269
 270struct itimerval32
 271{
 272    struct timeval32 it_interval;
 273    struct timeval32 it_value;
 274};
 275
 276static inline long get_tv32(struct timeval *o, struct timeval32 *i)
 277{
 278        return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) ||
 279                (__get_user(o->tv_sec, &i->tv_sec) |
 280                 __get_user(o->tv_usec, &i->tv_usec)));
 281}
 282
 283static inline long put_tv32(struct timeval32 *o, struct timeval *i)
 284{
 285        return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
 286                (__put_user(i->tv_sec, &o->tv_sec) |
 287                 __put_user(i->tv_usec, &o->tv_usec)));
 288}
 289
 290static inline long get_it32(struct itimerval *o, struct itimerval32 *i)
 291{
 292        return (!access_ok(VERIFY_READ, i32, sizeof(*i32)) ||
 293                (__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
 294                 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
 295                 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
 296                 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
 297}
 298
 299static inline long put_it32(struct itimerval32 *o, struct itimerval *i)
 300{
 301        return (!access_ok(VERIFY_WRITE, i32, sizeof(*i32)) ||
 302                (__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
 303                 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
 304                 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
 305                 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
 306}
 307
 308extern asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
 309
 310asmlinkage int sys32_ioperm(u32 from, u32 num, int on)
 311{
 312        return sys_ioperm((unsigned long)from, (unsigned long)num, on);
 313}
 314
 315struct msgbuf32 { s32 mtype; char mtext[1]; };
 316
 317struct ipc_perm32
 318{
 319        key_t             key;
 320        __kernel_uid_t32  uid;
 321        __kernel_gid_t32  gid;
 322        __kernel_uid_t32  cuid;
 323        __kernel_gid_t32  cgid;
 324        __kernel_mode_t32 mode;
 325        unsigned short  seq;
 326};
 327
 328struct semid_ds32 {
 329        struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
 330        __kernel_time_t32 sem_otime;              /* last semop time */
 331        __kernel_time_t32 sem_ctime;              /* last change time */
 332        u32 sem_base;              /* ptr to first semaphore in array */
 333        u32 sem_pending;          /* pending operations to be processed */
 334        u32 sem_pending_last;    /* last pending operation */
 335        u32 undo;                  /* undo requests on this array */
 336        unsigned short  sem_nsems;              /* no. of semaphores in array */
 337};
 338
 339struct semid64_ds32 {
 340        struct ipc64_perm sem_perm;               /* this structure is the same on sparc32 and sparc64 */
 341        unsigned int      __pad1;
 342        __kernel_time_t32 sem_otime;
 343        unsigned int      __pad2;
 344        __kernel_time_t32 sem_ctime;
 345        u32 sem_nsems;
 346        u32 __unused1;
 347        u32 __unused2;
 348};
 349
 350struct msqid_ds32
 351{
 352        struct ipc_perm32 msg_perm;
 353        u32 msg_first;
 354        u32 msg_last;
 355        __kernel_time_t32 msg_stime;
 356        __kernel_time_t32 msg_rtime;
 357        __kernel_time_t32 msg_ctime;
 358        u32 wwait;
 359        u32 rwait;
 360        unsigned short msg_cbytes;
 361        unsigned short msg_qnum;  
 362        unsigned short msg_qbytes;
 363        __kernel_ipc_pid_t32 msg_lspid;
 364        __kernel_ipc_pid_t32 msg_lrpid;
 365};
 366
 367struct msqid64_ds32 {
 368        struct ipc64_perm msg_perm;
 369        unsigned int   __pad1;
 370        __kernel_time_t32 msg_stime;
 371        unsigned int   __pad2;
 372        __kernel_time_t32 msg_rtime;
 373        unsigned int   __pad3;
 374        __kernel_time_t32 msg_ctime;
 375        unsigned int  msg_cbytes;
 376        unsigned int  msg_qnum;
 377        unsigned int  msg_qbytes;
 378        __kernel_pid_t32 msg_lspid;
 379        __kernel_pid_t32 msg_lrpid;
 380        unsigned int  __unused1;
 381        unsigned int  __unused2;
 382};
 383
 384
 385struct shmid_ds32 {
 386        struct ipc_perm32       shm_perm;
 387        int                     shm_segsz;
 388        __kernel_time_t32       shm_atime;
 389        __kernel_time_t32       shm_dtime;
 390        __kernel_time_t32       shm_ctime;
 391        __kernel_ipc_pid_t32    shm_cpid; 
 392        __kernel_ipc_pid_t32    shm_lpid; 
 393        unsigned short          shm_nattch;
 394};
 395
 396struct shmid64_ds32 {
 397        struct ipc64_perm       shm_perm;
 398        unsigned int            __pad1;
 399        __kernel_time_t32       shm_atime;
 400        unsigned int            __pad2;
 401        __kernel_time_t32       shm_dtime;
 402        unsigned int            __pad3;
 403        __kernel_time_t32       shm_ctime;
 404        __kernel_size_t32       shm_segsz;
 405        __kernel_pid_t32        shm_cpid;
 406        __kernel_pid_t32        shm_lpid;
 407        unsigned int            shm_nattch;
 408        unsigned int            __unused1;
 409        unsigned int            __unused2;
 410};
 411
 412                                                        
 413/*
 414 * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
 415 *
 416 * This is really horribly ugly.
 417 */
 418#define IPCOP_MASK(__x) (1UL << ((__x)&~IPC_64))
 419static int do_sys32_semctl(int first, int second, int third, void *uptr)
 420{
 421        union semun fourth;
 422        u32 pad;
 423        int err = -EINVAL;
 424
 425        if (!uptr)
 426                goto out;
 427        err = -EFAULT;
 428        if (get_user (pad, (u32 *)uptr))
 429                goto out;
 430        if ((third & ~IPC_64) == SETVAL)
 431                fourth.val = (int)pad;
 432        else
 433                fourth.__pad = (void *)A(pad);
 434        if (IPCOP_MASK (third) &
 435            (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) |
 436             IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
 437             IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) {
 438                err = sys_semctl (first, second, third, fourth);
 439        } else if (third & IPC_64) {
 440                struct semid64_ds s;
 441                struct semid64_ds32 *usp = (struct semid64_ds32 *)A(pad);
 442                mm_segment_t old_fs;
 443                int need_back_translation;
 444
 445                if (third == (IPC_SET|IPC_64)) {
 446                        err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
 447                        err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
 448                        err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
 449                        if (err)
 450                                goto out;
 451                        fourth.__pad = &s;
 452                }
 453                need_back_translation =
 454                        (IPCOP_MASK (third) &
 455                         (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
 456                if (need_back_translation)
 457                        fourth.__pad = &s;
 458                old_fs = get_fs ();
 459                set_fs (KERNEL_DS);
 460                err = sys_semctl (first, second, third, fourth);
 461                set_fs (old_fs);
 462                if (need_back_translation) {
 463                        int err2 = copy_to_user (&usp->sem_perm, &s.sem_perm, sizeof(struct ipc64_perm) + 2*sizeof(time_t));
 464                        err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
 465                        if (err2) err = -EFAULT;
 466                }
 467        } else {
 468                struct semid_ds s;
 469                struct semid_ds32 *usp = (struct semid_ds32 *)A(pad);
 470                mm_segment_t old_fs;
 471                int need_back_translation;
 472
 473                if (third == IPC_SET) {
 474                        err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
 475                        err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
 476                        err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
 477                        if (err)
 478                                goto out;
 479                        fourth.__pad = &s;
 480                }
 481                need_back_translation =
 482                        (IPCOP_MASK (third) &
 483                         (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
 484                if (need_back_translation)
 485                        fourth.__pad = &s;
 486                old_fs = get_fs ();
 487                set_fs (KERNEL_DS);
 488                err = sys_semctl (first, second, third, fourth);
 489                set_fs (old_fs);
 490                if (need_back_translation) {
 491                        int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
 492                        err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);
 493                        err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);
 494                        err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);
 495                        err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);
 496                        err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
 497                        err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
 498                        err2 |= __put_user (s.sem_otime, &usp->sem_otime);
 499                        err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
 500                        err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
 501                        if (err2) err = -EFAULT;
 502                }
 503        }
 504out:
 505        return err;
 506}
 507
 508static int do_sys32_msgsnd (int first, int second, int third, void *uptr)
 509{
 510        struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf), GFP_USER);
 511        struct msgbuf32 *up = (struct msgbuf32 *)uptr;
 512        mm_segment_t old_fs;
 513        int err;
 514
 515        if (!p)
 516                return -ENOMEM;
 517        err = -EFAULT;
 518        if (get_user (p->mtype, &up->mtype) ||
 519            __copy_from_user (p->mtext, &up->mtext, second))
 520                goto out;
 521        old_fs = get_fs ();
 522        set_fs (KERNEL_DS);
 523        err = sys_msgsnd (first, p, second, third);
 524        set_fs (old_fs);
 525out:
 526        kfree (p);
 527        return err;
 528}
 529
 530static int do_sys32_msgrcv (int first, int second, int msgtyp, int third,
 531                            int version, void *uptr)
 532{
 533        struct msgbuf32 *up;
 534        struct msgbuf *p;
 535        mm_segment_t old_fs;
 536        int err;
 537
 538        if (!version) {
 539                struct ipc_kludge *uipck = (struct ipc_kludge *)uptr;
 540                struct ipc_kludge ipck;
 541
 542                err = -EINVAL;
 543                if (!uptr)
 544                        goto out;
 545                err = -EFAULT;
 546                if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge)))
 547                        goto out;
 548                uptr = (void *)A(ipck.msgp);
 549                msgtyp = ipck.msgtyp;
 550        }
 551        err = -ENOMEM;
 552        p = kmalloc (second + sizeof (struct msgbuf), GFP_USER);
 553        if (!p)
 554                goto out;
 555        old_fs = get_fs ();
 556        set_fs (KERNEL_DS);
 557        err = sys_msgrcv (first, p, second, msgtyp, third);
 558        set_fs (old_fs);
 559        if (err < 0)
 560                goto free_then_out;
 561        up = (struct msgbuf32 *)uptr;
 562        if (put_user (p->mtype, &up->mtype) ||
 563            __copy_to_user (&up->mtext, p->mtext, err))
 564                err = -EFAULT;
 565free_then_out:
 566        kfree (p);
 567out:
 568        return err;
 569}
 570
 571static int do_sys32_msgctl (int first, int second, void *uptr)
 572{
 573        int err;
 574
 575        if (IPCOP_MASK (second) &
 576            (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) |
 577             IPCOP_MASK (IPC_RMID))) {
 578                err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
 579        } else if (second & IPC_64) {
 580                struct msqid64_ds m;
 581                struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr;
 582                mm_segment_t old_fs;
 583
 584                if (second == (IPC_SET|IPC_64)) {
 585                        err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
 586                        err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
 587                        err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
 588                        err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
 589                        if (err)
 590                                goto out;
 591                }
 592                old_fs = get_fs ();
 593                set_fs (KERNEL_DS);
 594                err = sys_msgctl (first, second, (struct msqid_ds *)&m);
 595                set_fs (old_fs);
 596                if (IPCOP_MASK (second) &
 597                    (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
 598                        int err2 = copy_to_user(&up->msg_perm, &m.msg_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t));
 599                        err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
 600                        err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
 601                        err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
 602                        err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
 603                        err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
 604                        if (err2)
 605                                err = -EFAULT;
 606                }
 607        } else {
 608                struct msqid_ds m;
 609                struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
 610                mm_segment_t old_fs;
 611
 612                if (second == IPC_SET) {
 613                        err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
 614                        err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
 615                        err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
 616                        err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
 617                        if (err)
 618                                goto out;
 619                }
 620                old_fs = get_fs ();
 621                set_fs (KERNEL_DS);
 622                err = sys_msgctl (first, second, &m);
 623                set_fs (old_fs);
 624                if (IPCOP_MASK (second) &
 625                    (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
 626                        int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
 627                        err2 |= __put_user (high2lowuid(m.msg_perm.uid), &up->msg_perm.uid);
 628                        err2 |= __put_user (high2lowgid(m.msg_perm.gid), &up->msg_perm.gid);
 629                        err2 |= __put_user (high2lowuid(m.msg_perm.cuid), &up->msg_perm.cuid);
 630                        err2 |= __put_user (high2lowgid(m.msg_perm.cgid), &up->msg_perm.cgid);
 631                        err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode);
 632                        err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq);
 633                        err2 |= __put_user (m.msg_stime, &up->msg_stime);
 634                        err2 |= __put_user (m.msg_rtime, &up->msg_rtime);
 635                        err2 |= __put_user (m.msg_ctime, &up->msg_ctime);
 636                        err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
 637                        err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
 638                        err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
 639                        err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
 640                        err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
 641                        if (err2)
 642                                err = -EFAULT;
 643                }
 644        }
 645
 646out:
 647        return err;
 648}
 649
 650static int do_sys32_shmat (int first, int second, int third, int version, void *uptr)
 651{
 652        unsigned long raddr;
 653        u32 *uaddr = (u32 *)A((u32)third);
 654        int err = -EINVAL;
 655
 656        if (version == 1)
 657                goto out;
 658        err = sys_shmat (first, uptr, second, &raddr);
 659        if (err)
 660                goto out;
 661        err = put_user (raddr, uaddr);
 662out:
 663        return err;
 664}
 665
 666static int do_sys32_shmctl (int first, int second, void *uptr)
 667{
 668        int err;
 669
 670        if (IPCOP_MASK (second) &
 671            (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) | IPCOP_MASK (SHM_UNLOCK) |
 672             IPCOP_MASK (IPC_RMID))) {
 673                if (second == (IPC_INFO|IPC_64))
 674                        second = IPC_INFO; /* So that we don't have to translate it */
 675                err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
 676        } else if ((second & IPC_64) && second != (SHM_INFO|IPC_64)) {
 677                struct shmid64_ds s;
 678                struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr;
 679                mm_segment_t old_fs;
 680
 681                if (second == (IPC_SET|IPC_64)) {
 682                        err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
 683                        err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
 684                        err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
 685                        if (err)
 686                                goto out;
 687                }
 688                old_fs = get_fs ();
 689                set_fs (KERNEL_DS);
 690                err = sys_shmctl (first, second, (struct shmid_ds *)&s);
 691                set_fs (old_fs);
 692                if (err < 0)
 693                        goto out;
 694
 695                /* Mask it even in this case so it becomes a CSE. */
 696                if (IPCOP_MASK (second) &
 697                    (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
 698                        int err2 = copy_to_user (&up->shm_perm, &s.shm_perm, sizeof(struct ipc64_perm) + 3*sizeof(time_t));
 699                        err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
 700                        err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
 701                        err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
 702                        err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
 703                        if (err2)
 704                                err = -EFAULT;
 705                }
 706        } else {
 707                struct shmid_ds s;
 708                struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
 709                mm_segment_t old_fs;
 710
 711                second &= ~IPC_64;
 712                if (second == IPC_SET) {
 713                        err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
 714                        err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
 715                        err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
 716                        if (err)
 717                                goto out;
 718                }
 719                old_fs = get_fs ();
 720                set_fs (KERNEL_DS);
 721                err = sys_shmctl (first, second, &s);
 722                set_fs (old_fs);
 723                if (err < 0)
 724                        goto out;
 725
 726                /* Mask it even in this case so it becomes a CSE. */
 727                if (second == SHM_INFO) {
 728                        struct shm_info32 {
 729                                int used_ids;
 730                                u32 shm_tot, shm_rss, shm_swp;
 731                                u32 swap_attempts, swap_successes;
 732                        } *uip = (struct shm_info32 *)uptr;
 733                        struct shm_info *kp = (struct shm_info *)&s;
 734                        int err2 = put_user (kp->used_ids, &uip->used_ids);
 735                        err2 |= __put_user (kp->shm_tot, &uip->shm_tot);
 736                        err2 |= __put_user (kp->shm_rss, &uip->shm_rss);
 737                        err2 |= __put_user (kp->shm_swp, &uip->shm_swp);
 738                        err2 |= __put_user (kp->swap_attempts, &uip->swap_attempts);
 739                        err2 |= __put_user (kp->swap_successes, &uip->swap_successes);
 740                        if (err2)
 741                                err = -EFAULT;
 742                } else if (IPCOP_MASK (second) &
 743                           (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
 744                        int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
 745                        err2 |= __put_user (high2lowuid(s.shm_perm.uid), &up->shm_perm.uid);
 746                        err2 |= __put_user (high2lowuid(s.shm_perm.gid), &up->shm_perm.gid);
 747                        err2 |= __put_user (high2lowuid(s.shm_perm.cuid), &up->shm_perm.cuid);
 748                        err2 |= __put_user (high2lowuid(s.shm_perm.cgid), &up->shm_perm.cgid);
 749                        err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode);
 750                        err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
 751                        err2 |= __put_user (s.shm_atime, &up->shm_atime);
 752                        err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
 753                        err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
 754                        err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
 755                        err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
 756                        err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
 757                        err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
 758                        if (err2)
 759                                err = -EFAULT;
 760                }
 761        }
 762out:
 763        return err;
 764}
 765
 766static __inline__ void *alloc_user_space(long len)
 767{
 768        struct pt_regs *regs = current->thread.kregs;
 769        unsigned long usp = regs->u_regs[UREG_I6];
 770
 771        if (!(current->thread.flags & SPARC_FLAG_32BIT))
 772                usp += STACK_BIAS;
 773
 774        return (void *) (usp - len);
 775}
 776
 777struct timespec32 {
 778        s32    tv_sec;
 779        s32    tv_nsec;
 780};
 781                
 782static int sys32_semtimedop(int semid, struct sembuf *tsems, int nsems,
 783                            const struct timespec32 *timeout32)
 784{
 785        struct timespec32 t32;
 786        struct timespec *t64 = alloc_user_space(sizeof(*t64));
 787
 788        if (copy_from_user(&t32, timeout32, sizeof(t32)))
 789                return -EFAULT;
 790
 791        if (put_user(t32.tv_sec, &t64->tv_sec) ||
 792            put_user(t32.tv_nsec, &t64->tv_nsec))
 793                return -EFAULT;
 794
 795        return sys_semtimedop(semid, tsems, nsems, t64);
 796}
 797
 798asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
 799{
 800        int version, err;
 801
 802        version = call >> 16; /* hack for backward compatibility */
 803        call &= 0xffff;
 804
 805        if (call <= SEMCTL)
 806                switch (call) {
 807                case SEMOP:
 808                        /* struct sembuf is the same on 32 and 64bit :)) */
 809                        err = sys_semtimedop (first, (struct sembuf *)AA(ptr), second, NULL);
 810                        goto out;
 811                case SEMTIMEDOP:
 812                        err = sys32_semtimedop (first, (struct sembuf *)AA(ptr), second, (const struct timespec32 *) AA(fifth));
 813                case SEMGET:
 814                        err = sys_semget (first, second, third);
 815                        goto out;
 816                case SEMCTL:
 817                        err = do_sys32_semctl (first, second, third, (void *)AA(ptr));
 818                        goto out;
 819                default:
 820                        err = -ENOSYS;
 821                        goto out;
 822                };
 823        if (call <= MSGCTL) 
 824                switch (call) {
 825                case MSGSND:
 826                        err = do_sys32_msgsnd (first, second, third, (void *)AA(ptr));
 827                        goto out;
 828                case MSGRCV:
 829                        err = do_sys32_msgrcv (first, second, fifth, third,
 830                                               version, (void *)AA(ptr));
 831                        goto out;
 832                case MSGGET:
 833                        err = sys_msgget ((key_t) first, second);
 834                        goto out;
 835                case MSGCTL:
 836                        err = do_sys32_msgctl (first, second, (void *)AA(ptr));
 837                        goto out;
 838                default:
 839                        err = -ENOSYS;
 840                        goto out;
 841                }
 842        if (call <= SHMCTL) 
 843                switch (call) {
 844                case SHMAT:
 845                        err = do_sys32_shmat (first, second, third,
 846                                              version, (void *)AA(ptr));
 847                        goto out;
 848                case SHMDT: 
 849                        err = sys_shmdt ((char *)AA(ptr));
 850                        goto out;
 851                case SHMGET:
 852                        err = sys_shmget (first, second, third);
 853                        goto out;
 854                case SHMCTL:
 855                        err = do_sys32_shmctl (first, second, (void *)AA(ptr));
 856                        goto out;
 857                default:
 858                        err = -ENOSYS;
 859                        goto out;
 860                }
 861
 862        err = -ENOSYS;
 863
 864out:
 865        return err;
 866}
 867
 868static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
 869{
 870        int err;
 871        
 872        err = get_user(kfl->l_type, &ufl->l_type);
 873        err |= __get_user(kfl->l_whence, &ufl->l_whence);
 874        err |= __get_user(kfl->l_start, &ufl->l_start);
 875        err |= __get_user(kfl->l_len, &ufl->l_len);
 876        err |= __get_user(kfl->l_pid, &ufl->l_pid);
 877        return err;
 878}
 879
 880static inline int put_flock(struct flock *kfl, struct flock32 *ufl)
 881{
 882        int err;
 883        
 884        err = __put_user(kfl->l_type, &ufl->l_type);
 885        err |= __put_user(kfl->l_whence, &ufl->l_whence);
 886        err |= __put_user(kfl->l_start, &ufl->l_start);
 887        err |= __put_user(kfl->l_len, &ufl->l_len);
 888        err |= __put_user(kfl->l_pid, &ufl->l_pid);
 889        return err;
 890}
 891
 892extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
 893
 894asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
 895{
 896        switch (cmd) {
 897        case F_GETLK:
 898        case F_SETLK:
 899        case F_SETLKW:
 900                {
 901                        struct flock f;
 902                        mm_segment_t old_fs;
 903                        long ret;
 904                        
 905                        if (get_flock(&f, (struct flock32 *)arg))
 906                                return -EFAULT;
 907                        old_fs = get_fs(); set_fs (KERNEL_DS);
 908                        ret = sys_fcntl(fd, cmd, (unsigned long)&f);
 909                        set_fs (old_fs);
 910                        if (ret) return ret;
 911                        if (put_flock(&f, (struct flock32 *)arg))
 912                                return -EFAULT;
 913                        return 0;
 914                }
 915        default:
 916                return sys_fcntl(fd, cmd, (unsigned long)arg);
 917        }
 918}
 919
 920asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
 921{
 922        if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
 923                return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg);
 924        return sys32_fcntl(fd, cmd, arg);
 925}
 926
 927struct user_dqblk32 {
 928    __u32 dqb_bhardlimit;
 929    __u32 dqb_bsoftlimit;
 930    __u32 dqb_curblocks;
 931    __u32 dqb_ihardlimit;
 932    __u32 dqb_isoftlimit;
 933    __u32 dqb_curinodes;
 934    __kernel_time_t32 dqb_btime;
 935    __kernel_time_t32 dqb_itime;
 936};
 937                                
 938extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
 939
 940asmlinkage int sys32_quotactl(int cmd, const char *special, int id, caddr_t addr)
 941{
 942        int cmds = cmd >> SUBCMDSHIFT;
 943        int err;
 944        struct v1c_mem_dqblk d;
 945        mm_segment_t old_fs;
 946        char *spec;
 947        
 948        switch (cmds) {
 949        case Q_V1_GETQUOTA:
 950                break;
 951        case Q_V1_SETQUOTA:
 952        case Q_V1_SETUSE:
 953        case Q_V1_SETQLIM:
 954                if (copy_from_user(&d, addr, sizeof(struct user_dqblk32)))
 955                        return -EFAULT;
 956                d.dqb_itime = ((struct user_dqblk32 *)&d)->dqb_itime;
 957                d.dqb_btime = ((struct user_dqblk32 *)&d)->dqb_btime;
 958                break;
 959        default:
 960                return sys_quotactl(cmd, special, id, addr);
 961        }
 962        spec = getname(special);
 963        err = PTR_ERR(spec);
 964        if (IS_ERR(spec))
 965                return err;
 966        old_fs = get_fs();
 967        set_fs (KERNEL_DS);
 968        err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
 969        set_fs (old_fs);
 970        putname (spec);
 971        if (cmds == Q_V1_GETQUOTA) {
 972                __kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
 973                ((struct user_dqblk32 *)&d)->dqb_itime = i;
 974                ((struct user_dqblk32 *)&d)->dqb_btime = b;
 975                if (copy_to_user(addr, &d, sizeof(struct user_dqblk32)))
 976                        return -EFAULT;
 977        }
 978        return err;
 979}
 980
 981static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
 982{
 983        int err;
 984        
 985        err = put_user (kbuf->f_type, &ubuf->f_type);
 986        err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
 987        err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
 988        err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree);
 989        err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail);
 990        err |= __put_user (kbuf->f_files, &ubuf->f_files);
 991        err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree);
 992        err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen);
 993        err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
 994        err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
 995        return err;
 996}
 997
 998extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
 999
1000asmlinkage int sys32_statfs(const char * path, struct statfs32 *buf)
1001{
1002        int ret;
1003        struct statfs s;
1004        mm_segment_t old_fs = get_fs();
1005        char *pth;
1006        
1007        pth = getname (path);
1008        ret = PTR_ERR(pth);
1009        if (!IS_ERR(pth)) {
1010                set_fs (KERNEL_DS);
1011                ret = sys_statfs((const char *)pth, &s);
1012                set_fs (old_fs);
1013                putname (pth);
1014                if (put_statfs(buf, &s))
1015                        return -EFAULT;
1016        }
1017        return ret;
1018}
1019
1020extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf);
1021
1022asmlinkage int sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
1023{
1024        int ret;
1025        struct statfs s;
1026        mm_segment_t old_fs = get_fs();
1027        
1028        set_fs (KERNEL_DS);
1029        ret = sys_fstatfs(fd, &s);
1030        set_fs (old_fs);
1031        if (put_statfs(buf, &s))
1032                return -EFAULT;
1033        return ret;
1034}
1035
1036extern asmlinkage long sys_truncate(const char * path, unsigned long length);
1037extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
1038
1039asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low)
1040{
1041        if ((int)high < 0)
1042                return -EINVAL;
1043        else
1044                return sys_truncate(path, (high << 32) | low);
1045}
1046
1047asmlinkage int sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
1048{
1049        if ((int)high < 0)
1050                return -EINVAL;
1051        else
1052                return sys_ftruncate(fd, (high << 32) | low);
1053}
1054
1055extern asmlinkage int sys_utime(char * filename, struct utimbuf * times);
1056
1057struct utimbuf32 {
1058        __kernel_time_t32 actime, modtime;
1059};
1060
1061asmlinkage int sys32_utime(char * filename, struct utimbuf32 *times)
1062{
1063        struct utimbuf t;
1064        mm_segment_t old_fs;
1065        int ret;
1066        char *filenam;
1067        
1068        if (!times)
1069                return sys_utime(filename, NULL);
1070        if (get_user (t.actime, &times->actime) ||
1071            __get_user (t.modtime, &times->modtime))
1072                return -EFAULT;
1073        filenam = getname (filename);
1074        ret = PTR_ERR(filenam);
1075        if (!IS_ERR(filenam)) {
1076                old_fs = get_fs();
1077                set_fs (KERNEL_DS); 
1078                ret = sys_utime(filenam, &t);
1079                set_fs (old_fs);
1080                putname (filenam);
1081        }
1082        return ret;
1083}
1084
1085struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
1086
1087typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
1088typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
1089
1090static long do_readv_writev32(int type, struct file *file,
1091                              const struct iovec32 *vector, u32 count)
1092{
1093        __kernel_ssize_t32 tot_len;
1094        struct iovec iovstack[UIO_FASTIOV];
1095        struct iovec *iov=iovstack, *ivp;
1096        struct inode *inode;
1097        long retval, i;
1098        io_fn_t fn;
1099        iov_fn_t fnv;
1100
1101        /* First get the "struct iovec" from user memory and
1102         * verify all the pointers
1103         */
1104        retval = 0;
1105        if (!count)
1106                goto out_nofree;
1107        retval = -EFAULT;
1108        if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
1109                goto out_nofree;
1110        retval = -EINVAL;
1111        if (count > UIO_MAXIOV)
1112                goto out_nofree;
1113        if (count > UIO_FASTIOV) {
1114                retval = -ENOMEM;
1115                iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
1116                if (!iov)
1117                        goto out_nofree;
1118        }
1119
1120        tot_len = 0;
1121        i = count;
1122        ivp = iov;
1123        retval = -EINVAL;
1124        while(i > 0) {
1125                __kernel_ssize_t32 tmp = tot_len;
1126                __kernel_ssize_t32 len;
1127                u32 buf;
1128
1129                __get_user(len, &vector->iov_len);
1130                __get_user(buf, &vector->iov_base);
1131                if (len < 0)    /* size_t not fittina an ssize_t32 .. */
1132                        goto out;
1133                tot_len += len;
1134                if (tot_len < tmp) /* maths overflow on the ssize_t32 */
1135                        goto out;
1136                ivp->iov_base = (void *)A(buf);
1137                ivp->iov_len = (__kernel_size_t) len;
1138                vector++;
1139                ivp++;
1140                i--;
1141        }
1142
1143        inode = file->f_dentry->d_inode;
1144        /* VERIFY_WRITE actually means a read, as we write to user space */
1145        retval = locks_verify_area((type == VERIFY_WRITE
1146                                    ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
1147                                   inode, file, file->f_pos, tot_len);
1148        if (retval)
1149                goto out;
1150
1151        /* VERIFY_WRITE actually means a read, as we write to user space */
1152        fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev);
1153        if (fnv) {
1154                retval = fnv(file, iov, count, &file->f_pos);
1155                goto out;
1156        }
1157
1158        fn = (type == VERIFY_WRITE ? file->f_op->read :
1159              (io_fn_t) file->f_op->write);
1160
1161        ivp = iov;
1162        while (count > 0) {
1163                void * base;
1164                int len, nr;
1165
1166                base = ivp->iov_base;
1167                len = ivp->iov_len;
1168                ivp++;
1169                count--;
1170                nr = fn(file, base, len, &file->f_pos);
1171                if (nr < 0) {
1172                        if (!retval)
1173                                retval = nr;
1174                        break;
1175                }
1176                retval += nr;
1177                if (nr != len)
1178                        break;
1179        }
1180out:
1181        if (iov != iovstack)
1182                kfree(iov);
1183out_nofree:
1184        /* VERIFY_WRITE actually means a read, as we write to user space */
1185        if ((retval + (type == VERIFY_WRITE)) > 0)
1186                dnotify_parent(file->f_dentry,
1187                        (type == VERIFY_WRITE) ? DN_ACCESS : DN_MODIFY);
1188
1189        return retval;
1190}
1191
1192asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
1193{
1194        struct file *file;
1195        long ret = -EBADF;
1196
1197        file = fget(fd);
1198        if(!file)
1199                goto bad_file;
1200
1201        if (file->f_op && (file->f_mode & FMODE_READ) &&
1202            (file->f_op->readv || file->f_op->read))
1203                ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);
1204        fput(file);
1205
1206bad_file:
1207        return ret;
1208}
1209
1210asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
1211{
1212        struct file *file;
1213        int ret = -EBADF;
1214
1215        file = fget(fd);
1216        if(!file)
1217                goto bad_file;
1218        if (file->f_op && (file->f_mode & FMODE_WRITE) &&
1219            (file->f_op->writev || file->f_op->write))
1220                ret = do_readv_writev32(VERIFY_READ, file, vector, count);
1221        fput(file);
1222
1223bad_file:
1224        return ret;
1225}
1226
1227/* readdir & getdents */
1228
1229#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
1230#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
1231
1232struct old_linux_dirent32 {
1233        u32             d_ino;
1234        u32             d_offset;
1235        unsigned short  d_namlen;
1236        char            d_name[1];
1237};
1238
1239struct readdir_callback32 {
1240        struct old_linux_dirent32 * dirent;
1241        int count;
1242};
1243
1244static int fillonedir(void * __buf, const char * name, int namlen,
1245                      loff_t offset, ino_t ino, unsigned int d_type)
1246{
1247        struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
1248        struct old_linux_dirent32 * dirent;
1249
1250        if (buf->count)
1251                return -EINVAL;
1252        buf->count++;
1253        dirent = buf->dirent;
1254        put_user(ino, &dirent->d_ino);
1255        put_user(offset, &dirent->d_offset);
1256        put_user(namlen, &dirent->d_namlen);
1257        copy_to_user(dirent->d_name, name, namlen);
1258        put_user(0, dirent->d_name + namlen);
1259        return 0;
1260}
1261
1262asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count)
1263{
1264        int error = -EBADF;
1265        struct file * file;
1266        struct readdir_callback32 buf;
1267
1268        file = fget(fd);
1269        if (!file)
1270                goto out;
1271
1272        buf.count = 0;
1273        buf.dirent = dirent;
1274
1275        error = vfs_readdir(file, fillonedir, &buf);
1276        if (error < 0)
1277                goto out_putf;
1278        error = buf.count;
1279
1280out_putf:
1281        fput(file);
1282out:
1283        return error;
1284}
1285
1286struct linux_dirent32 {
1287        u32             d_ino;
1288        u32             d_off;
1289        unsigned short  d_reclen;
1290        char            d_name[1];
1291};
1292
1293struct getdents_callback32 {
1294        struct linux_dirent32 * current_dir;
1295        struct linux_dirent32 * previous;
1296        int count;
1297        int error;
1298};
1299
1300static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
1301                   unsigned int d_type)
1302{
1303        struct linux_dirent32 * dirent;
1304        struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
1305        int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
1306
1307        buf->error = -EINVAL;   /* only used if we fail.. */
1308        if (reclen > buf->count)
1309                return -EINVAL;
1310        dirent = buf->previous;
1311        if (dirent)
1312                put_user(offset, &dirent->d_off);
1313        dirent = buf->current_dir;
1314        buf->previous = dirent;
1315        put_user(ino, &dirent->d_ino);
1316        put_user(reclen, &dirent->d_reclen);
1317        copy_to_user(dirent->d_name, name, namlen);
1318        put_user(0, dirent->d_name + namlen);
1319        ((char *) dirent) += reclen;
1320        buf->current_dir = dirent;
1321        buf->count -= reclen;
1322        return 0;
1323}
1324
1325asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count)
1326{
1327        struct file * file;
1328        struct linux_dirent32 * lastdirent;
1329        struct getdents_callback32 buf;
1330        int error = -EBADF;
1331
1332        file = fget(fd);
1333        if (!file)
1334                goto out;
1335
1336        buf.current_dir = dirent;
1337        buf.previous = NULL;
1338        buf.count = count;
1339        buf.error = 0;
1340
1341        error = vfs_readdir(file, filldir, &buf);
1342        if (error < 0)
1343                goto out_putf;
1344        lastdirent = buf.previous;
1345        error = buf.error;
1346        if(lastdirent) {
1347                put_user(file->f_pos, &lastdirent->d_off);
1348                error = count - buf.count;
1349        }
1350out_putf:
1351        fput(file);
1352out:
1353        return error;
1354}
1355
1356/* end of readdir & getdents */
1357
1358/*
1359 * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
1360 * 64-bit unsigned longs.
1361 */
1362
1363static inline int
1364get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
1365{
1366        if (ufdset) {
1367                unsigned long odd;
1368
1369                if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
1370                        return -EFAULT;
1371
1372                odd = n & 1UL;
1373                n &= ~1UL;
1374                while (n) {
1375                        unsigned long h, l;
1376                        __get_user(l, ufdset);
1377                        __get_user(h, ufdset+1);
1378                        ufdset += 2;
1379                        *fdset++ = h << 32 | l;
1380                        n -= 2;
1381                }
1382                if (odd)
1383                        __get_user(*fdset, ufdset);
1384        } else {
1385                /* Tricky, must clear full unsigned long in the
1386                 * kernel fdset at the end, this makes sure that
1387                 * actually happens.
1388                 */
1389                memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
1390        }
1391        return 0;
1392}
1393
1394static inline void
1395set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
1396{
1397        unsigned long odd;
1398
1399        if (!ufdset)
1400                return;
1401
1402        odd = n & 1UL;
1403        n &= ~1UL;
1404        while (n) {
1405                unsigned long h, l;
1406                l = *fdset++;
1407                h = l >> 32;
1408                __put_user(l, ufdset);
1409                __put_user(h, ufdset+1);
1410                ufdset += 2;
1411                n -= 2;
1412        }
1413        if (odd)
1414                __put_user(*fdset, ufdset);
1415}
1416
1417#define MAX_SELECT_SECONDS \
1418        ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
1419
1420asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x)
1421{
1422        fd_set_bits fds;
1423        struct timeval32 *tvp = (struct timeval32 *)AA(tvp_x);
1424        char *bits;
1425        unsigned long nn;
1426        long timeout;
1427        int ret, size;
1428
1429        timeout = MAX_SCHEDULE_TIMEOUT;
1430        if (tvp) {
1431                time_t sec, usec;
1432
1433                if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
1434                    || (ret = __get_user(sec, &tvp->tv_sec))
1435                    || (ret = __get_user(usec, &tvp->tv_usec)))
1436                        goto out_nofds;
1437
1438                ret = -EINVAL;
1439                if(sec < 0 || usec < 0)
1440                        goto out_nofds;
1441
1442                if ((unsigned long) sec < MAX_SELECT_SECONDS) {
1443                        timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
1444                        timeout += sec * (unsigned long) HZ;
1445                }
1446        }
1447
1448        ret = -EINVAL;
1449        if (n < 0)
1450                goto out_nofds;
1451        if (n > current->files->max_fdset)
1452                n = current->files->max_fdset;
1453
1454        /*
1455         * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
1456         * since we used fdset we need to allocate memory in units of
1457         * long-words. 
1458         */
1459        ret = -ENOMEM;
1460        size = FDS_BYTES(n);
1461        bits = kmalloc(6 * size, GFP_KERNEL);
1462        if (!bits)
1463                goto out_nofds;
1464        fds.in      = (unsigned long *)  bits;
1465        fds.out     = (unsigned long *) (bits +   size);
1466        fds.ex      = (unsigned long *) (bits + 2*size);
1467        fds.res_in  = (unsigned long *) (bits + 3*size);
1468        fds.res_out = (unsigned long *) (bits + 4*size);
1469        fds.res_ex  = (unsigned long *) (bits + 5*size);
1470
1471        nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
1472        if ((ret = get_fd_set32(nn, fds.in, inp)) ||
1473            (ret = get_fd_set32(nn, fds.out, outp)) ||
1474            (ret = get_fd_set32(nn, fds.ex, exp)))
1475                goto out;
1476        zero_fd_set(n, fds.res_in);
1477        zero_fd_set(n, fds.res_out);
1478        zero_fd_set(n, fds.res_ex);
1479
1480        ret = do_select(n, &fds, &timeout);
1481
1482        if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
1483                time_t sec = 0, usec = 0;
1484                if (timeout) {
1485                        sec = timeout / HZ;
1486                        usec = timeout % HZ;
1487                        usec *= (1000000/HZ);
1488                }
1489                put_user(sec, &tvp->tv_sec);
1490                put_user(usec, &tvp->tv_usec);
1491        }
1492
1493        if (ret < 0)
1494                goto out;
1495        if (!ret) {
1496                ret = -ERESTARTNOHAND;
1497                if (signal_pending(current))
1498                        goto out;
1499                ret = 0;
1500        }
1501
1502        set_fd_set32(nn, inp, fds.res_in);
1503        set_fd_set32(nn, outp, fds.res_out);
1504        set_fd_set32(nn, exp, fds.res_ex);
1505
1506out:
1507        kfree(bits);
1508out_nofds:
1509        return ret;
1510}
1511
1512static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
1513{
1514        unsigned long ino, blksize, blocks;
1515        kdev_t dev, rdev;
1516        umode_t mode;
1517        nlink_t nlink;
1518        uid_t uid;
1519        gid_t gid;
1520        off_t size;
1521        time_t atime, mtime, ctime;
1522        int err;
1523
1524        /* Stream the loads of inode data into the load buffer,
1525         * then we push it all into the store buffer below.  This
1526         * should give optimal cache performance.
1527         */
1528        ino = inode->i_ino;
1529        dev = inode->i_dev;
1530        mode = inode->i_mode;
1531        nlink = inode->i_nlink;
1532        uid = inode->i_uid;
1533        gid = inode->i_gid;
1534        rdev = inode->i_rdev;
1535        size = inode->i_size;
1536        atime = inode->i_atime;
1537        mtime = inode->i_mtime;
1538        ctime = inode->i_ctime;
1539        blksize = inode->i_blksize;
1540        blocks = inode->i_blocks;
1541
1542        err  = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
1543        err |= put_user(ino, &statbuf->st_ino);
1544        err |= put_user(mode, &statbuf->st_mode);
1545        err |= put_user(nlink, &statbuf->st_nlink);
1546        err |= put_user(high2lowuid(uid), &statbuf->st_uid);
1547        err |= put_user(high2lowgid(gid), &statbuf->st_gid);
1548        err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
1549        err |= put_user(size, &statbuf->st_size);
1550        err |= put_user(atime, &statbuf->st_atime);
1551        err |= put_user(0, &statbuf->__unused1);
1552        err |= put_user(mtime, &statbuf->st_mtime);
1553        err |= put_user(0, &statbuf->__unused2);
1554        err |= put_user(ctime, &statbuf->st_ctime);
1555        err |= put_user(0, &statbuf->__unused3);
1556        if (blksize) {
1557                err |= put_user(blksize, &statbuf->st_blksize);
1558                err |= put_user(blocks, &statbuf->st_blocks);
1559        } else {
1560                unsigned int tmp_blocks;
1561
1562#define D_B   7
1563#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
1564                tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
1565                if (tmp_blocks > D_B) {
1566                        unsigned int indirect;
1567
1568                        indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
1569                        tmp_blocks += indirect;
1570                        if (indirect > 1) {
1571                                indirect = (indirect - 1 + I_B - 1) / I_B;
1572                                tmp_blocks += indirect;
1573                                if (indirect > 1)
1574                                        tmp_blocks++;
1575                        }
1576                }
1577                err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
1578                err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
1579#undef D_B
1580#undef I_B
1581        }
1582        err |= put_user(0, &statbuf->__unused4[0]);
1583        err |= put_user(0, &statbuf->__unused4[1]);
1584
1585        return err;
1586}
1587
1588/* Perhaps this belongs in fs.h or similar. -DaveM */
1589static __inline__ int
1590do_revalidate(struct dentry *dentry)
1591{
1592        struct inode * inode = dentry->d_inode;
1593        if (inode->i_op && inode->i_op->revalidate)
1594                return inode->i_op->revalidate(dentry);
1595        return 0;
1596}
1597
1598asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
1599{
1600        struct nameidata nd;
1601        int error;
1602
1603        error = user_path_walk(filename, &nd);
1604        if (!error) {
1605                error = do_revalidate(nd.dentry);
1606                if (!error)
1607                        error = cp_new_stat32(nd.dentry->d_inode, statbuf);
1608                path_release(&nd);
1609        }
1610        return error;
1611}
1612
1613asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
1614{
1615        struct nameidata nd;
1616        int error;
1617
1618        error = user_path_walk_link(filename, &nd);
1619        if (!error) {
1620                error = do_revalidate(nd.dentry);
1621                if (!error)
1622                        error = cp_new_stat32(nd.dentry->d_inode, statbuf);
1623
1624                path_release(&nd);
1625        }
1626        return error;
1627}
1628
1629asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
1630{
1631        struct file *f;
1632        int err = -EBADF;
1633
1634        f = fget(fd);
1635        if (f) {
1636                struct dentry * dentry = f->f_dentry;
1637
1638                err = do_revalidate(dentry);
1639                if (!err)
1640                        err = cp_new_stat32(dentry->d_inode, statbuf);
1641                fput(f);
1642        }
1643        return err;
1644}
1645
1646extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
1647
1648asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2)
1649{
1650        return sys_sysfs(option, arg1, arg2);
1651}
1652
1653struct ncp_mount_data32_v3 {
1654        int version;
1655        unsigned int ncp_fd;
1656        __kernel_uid_t32 mounted_uid;
1657        __kernel_pid_t32 wdog_pid;
1658        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
1659        unsigned int time_out;
1660        unsigned int retry_count;
1661        unsigned int flags;
1662        __kernel_uid_t32 uid;
1663        __kernel_gid_t32 gid;
1664        __kernel_mode_t32 file_mode;
1665        __kernel_mode_t32 dir_mode;
1666};
1667
1668struct ncp_mount_data32_v4 {
1669        int version;
1670        /* all members below are "long" in ABI ... i.e. 32bit on sparc32, while 64bits on sparc64 */
1671        unsigned int flags;
1672        unsigned int mounted_uid;
1673        int wdog_pid;
1674
1675        unsigned int ncp_fd;
1676        unsigned int time_out;
1677        unsigned int retry_count;
1678
1679        unsigned int uid;
1680        unsigned int gid;
1681        unsigned int file_mode;
1682        unsigned int dir_mode;
1683};
1684
1685static void *do_ncp_super_data_conv(void *raw_data)
1686{
1687        switch (*(int*)raw_data) {
1688                case NCP_MOUNT_VERSION:
1689                        {
1690                                struct ncp_mount_data news, *n = &news; 
1691                                struct ncp_mount_data32_v3 *n32 = (struct ncp_mount_data32_v3 *)raw_data;
1692
1693                                n->version = n32->version;
1694                                n->ncp_fd = n32->ncp_fd;
1695                                n->mounted_uid = low2highuid(n32->mounted_uid);
1696                                n->wdog_pid = n32->wdog_pid;
1697                                memmove (n->mounted_vol, n32->mounted_vol, sizeof (n32->mounted_vol));
1698                                n->time_out = n32->time_out;
1699                                n->retry_count = n32->retry_count;
1700                                n->flags = n32->flags;
1701                                n->uid = low2highuid(n32->uid);
1702                                n->gid = low2highgid(n32->gid);
1703                                n->file_mode = n32->file_mode;
1704                                n->dir_mode = n32->dir_mode;
1705                                memcpy(raw_data, n, sizeof(*n)); 
1706                        }
1707                        break;
1708                case NCP_MOUNT_VERSION_V4:
1709                        {
1710                                struct ncp_mount_data_v4 news, *n = &news; 
1711                                struct ncp_mount_data32_v4 *n32 = (struct ncp_mount_data32_v4 *)raw_data;
1712
1713                                n->version = n32->version;
1714                                n->flags = n32->flags;
1715                                n->mounted_uid = n32->mounted_uid;
1716                                n->wdog_pid = n32->wdog_pid;
1717                                n->ncp_fd = n32->ncp_fd;
1718                                n->time_out = n32->time_out;
1719                                n->retry_count = n32->retry_count;
1720                                n->uid = n32->uid;
1721                                n->gid = n32->gid;
1722                                n->file_mode = n32->file_mode;
1723                                n->dir_mode = n32->dir_mode;
1724                                memcpy(raw_data, n, sizeof(*n)); 
1725                        }
1726                        break;
1727                default:
1728                        /* do not touch unknown structures */
1729                        break;
1730        }
1731        return raw_data;
1732}
1733
1734struct smb_mount_data32 {
1735        int version;
1736        __kernel_uid_t32 mounted_uid;
1737        __kernel_uid_t32 uid;
1738        __kernel_gid_t32 gid;
1739        __kernel_mode_t32 file_mode;
1740        __kernel_mode_t32 dir_mode;
1741};
1742
1743static void *do_smb_super_data_conv(void *raw_data)
1744{
1745        struct smb_mount_data news, *s = &news;
1746        struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
1747
1748        s->version = s32->version;
1749        s->mounted_uid = low2highuid(s32->mounted_uid);
1750        s->uid = low2highuid(s32->uid);
1751        s->gid = low2highgid(s32->gid);
1752        s->file_mode = s32->file_mode;
1753        s->dir_mode = s32->dir_mode;
1754        memcpy(raw_data, s, sizeof(struct smb_mount_data)); 
1755        return raw_data;
1756}
1757
1758static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
1759{
1760        int i;
1761        unsigned long page;
1762        struct vm_area_struct *vma;
1763
1764        *kernel = 0;
1765        if(!user)
1766                return 0;
1767        vma = find_vma(current->mm, (unsigned long)user);
1768        if(!vma || (unsigned long)user < vma->vm_start)
1769                return -EFAULT;
1770        if(!(vma->vm_flags & VM_READ))
1771                return -EFAULT;
1772        i = vma->vm_end - (unsigned long) user;
1773        if(PAGE_SIZE <= (unsigned long) i)
1774                i = PAGE_SIZE - 1;
1775        if(!(page = __get_free_page(GFP_KERNEL)))
1776                return -ENOMEM;
1777        if(copy_from_user((void *) page, user, i)) {
1778                free_page(page);
1779                return -EFAULT;
1780        }
1781        *kernel = page;
1782        return 0;
1783}
1784
1785#define SMBFS_NAME      "smbfs"
1786#define NCPFS_NAME      "ncpfs"
1787
1788asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data)
1789{
1790        unsigned long type_page = 0;
1791        unsigned long data_page = 0;
1792        unsigned long dev_page = 0;
1793        unsigned long dir_page = 0;
1794        int err, is_smb, is_ncp;
1795
1796        is_smb = is_ncp = 0;
1797
1798        err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
1799        if (err)
1800                goto out;
1801
1802        if (type_page) {
1803                is_smb = !strcmp((char *)type_page, SMBFS_NAME);
1804                is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
1805        } else {
1806                is_smb = is_ncp = 0;
1807        }
1808
1809        err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page);
1810        if (err)
1811                goto type_out;
1812
1813        err = copy_mount_stuff_to_kernel(dev_name, &dev_page);
1814        if (err)
1815                goto data_out;
1816
1817        err = copy_mount_stuff_to_kernel(dir_name, &dir_page);
1818        if (err)
1819                goto dev_out;
1820
1821        if (!is_smb && !is_ncp) {
1822                lock_kernel();
1823                err = do_mount((char*)dev_page, (char*)dir_page,
1824                                (char*)type_page, new_flags, (char*)data_page);
1825                unlock_kernel();
1826        } else {
1827                if (is_ncp)
1828                        do_ncp_super_data_conv((void *)data_page);
1829                else
1830                        do_smb_super_data_conv((void *)data_page);
1831
1832                lock_kernel();
1833                err = do_mount((char*)dev_page, (char*)dir_page,
1834                                (char*)type_page, new_flags, (char*)data_page);
1835                unlock_kernel();
1836        }
1837        free_page(dir_page);
1838
1839dev_out:
1840        free_page(dev_page);
1841
1842data_out:
1843        free_page(data_page);
1844
1845type_out:
1846        free_page(type_page);
1847
1848out:
1849        return err;
1850}
1851
1852struct rusage32 {
1853        struct timeval32 ru_utime;
1854        struct timeval32 ru_stime;
1855        s32    ru_maxrss;
1856        s32    ru_ixrss;
1857        s32    ru_idrss;
1858        s32    ru_isrss;
1859        s32    ru_minflt;
1860        s32    ru_majflt;
1861        s32    ru_nswap;
1862        s32    ru_inblock;
1863        s32    ru_oublock;
1864        s32    ru_msgsnd; 
1865        s32    ru_msgrcv; 
1866        s32    ru_nsignals;
1867        s32    ru_nvcsw;
1868        s32    ru_nivcsw;
1869};
1870
1871static int put_rusage (struct rusage32 *ru, struct rusage *r)
1872{
1873        int err;
1874        
1875        err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
1876        err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
1877        err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
1878        err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
1879        err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
1880        err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
1881        err |= __put_user (r->ru_idrss, &ru->ru_idrss);
1882        err |= __put_user (r->ru_isrss, &ru->ru_isrss);
1883        err |= __put_user (r->ru_minflt, &ru->ru_minflt);
1884        err |= __put_user (r->ru_majflt, &ru->ru_majflt);
1885        err |= __put_user (r->ru_nswap, &ru->ru_nswap);
1886        err |= __put_user (r->ru_inblock, &ru->ru_inblock);
1887        err |= __put_user (r->ru_oublock, &ru->ru_oublock);
1888        err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
1889        err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
1890        err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
1891        err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
1892        err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
1893        return err;
1894}
1895
1896asmlinkage int sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
1897{
1898        if (!ru)
1899                return sys_wait4(pid, stat_addr, options, NULL);
1900        else {
1901                struct rusage r;
1902                int ret;
1903                unsigned int status;
1904                mm_segment_t old_fs = get_fs();
1905                
1906                set_fs (KERNEL_DS);
1907                ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
1908                set_fs (old_fs);
1909                if (put_rusage (ru, &r)) return -EFAULT;
1910                if (stat_addr && put_user (status, stat_addr))
1911                        return -EFAULT;
1912                return ret;
1913        }
1914}
1915
1916struct sysinfo32 {
1917        s32 uptime;
1918        u32 loads[3];
1919        u32 totalram;
1920        u32 freeram;
1921        u32 sharedram;
1922        u32 bufferram;
1923        u32 totalswap;
1924        u32 freeswap;
1925        unsigned short procs;
1926        unsigned short pad;
1927        u32 totalhigh;
1928        u32 freehigh;
1929        u32 mem_unit;
1930        char _f[20-2*sizeof(int)-sizeof(int)];
1931};
1932
1933extern asmlinkage int sys_sysinfo(struct sysinfo *info);
1934
1935asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
1936{
1937        struct sysinfo s;
1938        int ret, err;
1939        int bitcount = 0;
1940        mm_segment_t old_fs = get_fs ();
1941        
1942        set_fs(KERNEL_DS);
1943        ret = sys_sysinfo(&s);
1944        set_fs(old_fs);
1945        /* Check to see if any memory value is too large for 32-bit and
1946         * scale down if needed.
1947         */
1948        if ((s.totalram >> 32) || (s.totalswap >> 32)) {
1949                while (s.mem_unit < PAGE_SIZE) {
1950                        s.mem_unit <<= 1;
1951                        bitcount++;
1952                }
1953                s.totalram >>= bitcount;
1954                s.freeram >>= bitcount;
1955                s.sharedram >>= bitcount;
1956                s.bufferram >>= bitcount;
1957                s.totalswap >>= bitcount;
1958                s.freeswap >>= bitcount;
1959                s.totalhigh >>= bitcount;
1960                s.freehigh >>= bitcount;
1961        }
1962
1963        err = put_user (s.uptime, &info->uptime);
1964        err |= __put_user (s.loads[0], &info->loads[0]);
1965        err |= __put_user (s.loads[1], &info->loads[1]);
1966        err |= __put_user (s.loads[2], &info->loads[2]);
1967        err |= __put_user (s.totalram, &info->totalram);
1968        err |= __put_user (s.freeram, &info->freeram);
1969        err |= __put_user (s.sharedram, &info->sharedram);
1970        err |= __put_user (s.bufferram, &info->bufferram);
1971        err |= __put_user (s.totalswap, &info->totalswap);
1972        err |= __put_user (s.freeswap, &info->freeswap);
1973        err |= __put_user (s.procs, &info->procs);
1974        err |= __put_user (s.totalhigh, &info->totalhigh);
1975        err |= __put_user (s.freehigh, &info->freehigh);
1976        err |= __put_user (s.mem_unit, &info->mem_unit);
1977        if (err)
1978                return -EFAULT;
1979        return ret;
1980}
1981
1982extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
1983
1984asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval)
1985{
1986        struct timespec t;
1987        int ret;
1988        mm_segment_t old_fs = get_fs ();
1989        
1990        set_fs (KERNEL_DS);
1991        ret = sys_sched_rr_get_interval(pid, &t);
1992        set_fs (old_fs);
1993        if (put_user (t.tv_sec, &interval->tv_sec) ||
1994            __put_user (t.tv_nsec, &interval->tv_nsec))
1995                return -EFAULT;
1996        return ret;
1997}
1998
1999extern asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
2000
2001asmlinkage int sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
2002{
2003        struct timespec t;
2004        int ret;
2005        mm_segment_t old_fs = get_fs ();
2006        
2007        if (get_user (t.tv_sec, &rqtp->tv_sec) ||
2008            __get_user (t.tv_nsec, &rqtp->tv_nsec))
2009                return -EFAULT;
2010        set_fs (KERNEL_DS);
2011        ret = sys_nanosleep(&t, rmtp ? &t : NULL);
2012        set_fs (old_fs);
2013        if (rmtp && ret == -EINTR) {
2014                if (__put_user (t.tv_sec, &rmtp->tv_sec) ||
2015                    __put_user (t.tv_nsec, &rmtp->tv_nsec))
2016                        return -EFAULT;
2017        }
2018        return ret;
2019}
2020
2021extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset);
2022
2023asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set, old_sigset_t32 *oset)
2024{
2025        old_sigset_t s;
2026        int ret;
2027        mm_segment_t old_fs = get_fs();
2028        
2029        if (set && get_user (s, set)) return -EFAULT;
2030        set_fs (KERNEL_DS);
2031        ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
2032        set_fs (old_fs);
2033        if (ret) return ret;
2034        if (oset && put_user (s, oset)) return -EFAULT;
2035        return 0;
2036}
2037
2038extern asmlinkage int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize);
2039
2040asmlinkage int sys32_rt_sigprocmask(int how, sigset_t32 *set, sigset_t32 *oset, __kernel_size_t32 sigsetsize)
2041{
2042        sigset_t s;
2043        sigset_t32 s32;
2044        int ret;
2045        mm_segment_t old_fs = get_fs();
2046        
2047        if (set) {
2048                if (copy_from_user (&s32, set, sizeof(sigset_t32)))
2049                        return -EFAULT;
2050                switch (_NSIG_WORDS) {
2051                case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
2052                case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
2053                case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
2054                case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
2055                }
2056        }
2057        set_fs (KERNEL_DS);
2058        ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sigsetsize);
2059        set_fs (old_fs);
2060        if (ret) return ret;
2061        if (oset) {
2062                switch (_NSIG_WORDS) {
2063                case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
2064                case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
2065                case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
2066                case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
2067                }
2068                if (copy_to_user (oset, &s32, sizeof(sigset_t32)))
2069                        return -EFAULT;
2070        }
2071        return 0;
2072}
2073
2074extern asmlinkage int sys_sigpending(old_sigset_t *set);
2075
2076asmlinkage int sys32_sigpending(old_sigset_t32 *set)
2077{
2078        old_sigset_t s;
2079        int ret;
2080        mm_segment_t old_fs = get_fs();
2081                
2082        set_fs (KERNEL_DS);
2083        ret = sys_sigpending(&s);
2084        set_fs (old_fs);
2085        if (put_user (s, set)) return -EFAULT;
2086        return ret;
2087}
2088
2089extern asmlinkage int sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
2090
2091asmlinkage int sys32_rt_sigpending(sigset_t32 *set, __kernel_size_t32 sigsetsize)
2092{
2093        sigset_t s;
2094        sigset_t32 s32;
2095        int ret;
2096        mm_segment_t old_fs = get_fs();
2097                
2098        set_fs (KERNEL_DS);
2099        ret = sys_rt_sigpending(&s, sigsetsize);
2100        set_fs (old_fs);
2101        if (!ret) {
2102                switch (_NSIG_WORDS) {
2103                case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
2104                case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
2105                case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
2106                case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
2107                }
2108                if (copy_to_user (set, &s32, sizeof(sigset_t32)))
2109                        return -EFAULT;
2110        }
2111        return ret;
2112}
2113
2114asmlinkage int
2115sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
2116                      struct timespec32 *uts, __kernel_size_t32 sigsetsize)
2117{
2118        int ret, sig;
2119        sigset_t these;
2120        sigset_t32 these32;
2121        struct timespec ts;
2122        siginfo_t info;
2123        long timeout = 0;
2124
2125        /* XXX: Don't preclude handling different sized sigset_t's.  */
2126        if (sigsetsize != sizeof(sigset_t))
2127                return -EINVAL;
2128
2129        if (copy_from_user (&these32, uthese, sizeof(sigset_t32)))
2130                return -EFAULT;
2131
2132        switch (_NSIG_WORDS) {
2133        case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
2134        case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
2135        case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
2136        case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
2137        }
2138                
2139        /*
2140         * Invert the set of allowed signals to get those we
2141         * want to block.
2142         */
2143        sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
2144        signotset(&these);
2145
2146        if (uts) {
2147                if (get_user (ts.tv_sec, &uts->tv_sec) ||
2148                    get_user (ts.tv_nsec, &uts->tv_nsec))
2149                        return -EINVAL;
2150                if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
2151                    || ts.tv_sec < 0)
2152                        return -EINVAL;
2153        }
2154
2155        spin_lock_irq(&current->sigmask_lock);
2156        sig = dequeue_signal(&these, &info);
2157        if (!sig) {
2158                timeout = MAX_SCHEDULE_TIMEOUT;
2159                if (uts)
2160                        timeout = (timespec_to_jiffies(&ts)
2161                                   + (ts.tv_sec || ts.tv_nsec));
2162
2163                current->state = TASK_INTERRUPTIBLE;
2164                timeout = schedule_timeout(timeout);
2165
2166                if (timeout) {
2167                        /* None ready -- temporarily unblock those we're
2168                         * interested while we are sleeping in so that we'll
2169                         * be awakened when they arrive.  */
2170                        sigset_t oldblocked = current->blocked;
2171                        sigandsets(&current->blocked, &current->blocked, &these);
2172                        recalc_sigpending(current);
2173                        spin_unlock_irq(&current->sigmask_lock);
2174
2175                        current->state = TASK_INTERRUPTIBLE;
2176                        timeout = schedule_timeout(timeout);
2177
2178                        spin_lock_irq(&current->sigmask_lock);
2179                        sig = dequeue_signal(&these, &info);
2180                        current->blocked = oldblocked;
2181                        recalc_sigpending(current);
2182                }
2183        }
2184        spin_unlock_irq(&current->sigmask_lock);
2185
2186        if (sig) {
2187                ret = sig;
2188                if (uinfo) {
2189                        if (copy_siginfo_to_user32(uinfo, &info))
2190                                ret = -EFAULT;
2191                }
2192        } else {
2193                ret = -EAGAIN;
2194                if (timeout)
2195                        ret = -EINTR;
2196        }
2197
2198        return ret;
2199}
2200
2201extern asmlinkage int
2202sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
2203
2204asmlinkage int
2205sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
2206{
2207        siginfo_t info;
2208        int ret;
2209        mm_segment_t old_fs = get_fs();
2210        
2211        if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
2212            copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
2213                return -EFAULT;
2214        set_fs (KERNEL_DS);
2215        ret = sys_rt_sigqueueinfo(pid, sig, &info);
2216        set_fs (old_fs);
2217        return ret;
2218}
2219
2220struct tms32 {
2221        __kernel_clock_t32 tms_utime;
2222        __kernel_clock_t32 tms_stime;
2223        __kernel_clock_t32 tms_cutime;
2224        __kernel_clock_t32 tms_cstime;
2225};
2226                                
2227extern asmlinkage long sys_times(struct tms * tbuf);
2228
2229asmlinkage long sys32_times(struct tms32 *tbuf)
2230{
2231        struct tms t;
2232        long ret;
2233        mm_segment_t old_fs = get_fs ();
2234        int err;
2235        
2236        set_fs (KERNEL_DS);
2237        ret = sys_times(tbuf ? &t : NULL);
2238        set_fs (old_fs);
2239        if (tbuf) {
2240                err = put_user (t.tms_utime, &tbuf->tms_utime);
2241                err |= __put_user (t.tms_stime, &tbuf->tms_stime);
2242                err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);
2243                err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);
2244                if (err)
2245                        ret = -EFAULT;
2246        }
2247        return ret;
2248}
2249
2250#define RLIM_INFINITY32 0x7fffffff
2251#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
2252
2253struct rlimit32 {
2254        u32     rlim_cur;
2255        u32     rlim_max;
2256};
2257
2258extern asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim);
2259
2260asmlinkage int sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim)
2261{
2262        struct rlimit r;
2263        int ret;
2264        mm_segment_t old_fs = get_fs ();
2265        
2266        set_fs (KERNEL_DS);
2267        ret = sys_getrlimit(resource, &r);
2268        set_fs (old_fs);
2269        if (!ret) {
2270                ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
2271                ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);
2272        }
2273        return ret;
2274}
2275
2276extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim);
2277
2278asmlinkage int sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
2279{
2280        struct rlimit r;
2281        int ret;
2282        mm_segment_t old_fs = get_fs ();
2283
2284        if (resource >= RLIM_NLIMITS) return -EINVAL;   
2285        if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
2286            __get_user (r.rlim_max, &rlim->rlim_max))
2287                return -EFAULT;
2288        if (r.rlim_cur == RLIM_INFINITY32)
2289                r.rlim_cur = RLIM_INFINITY;
2290        if (r.rlim_max == RLIM_INFINITY32)
2291                r.rlim_max = RLIM_INFINITY;
2292        set_fs (KERNEL_DS);
2293        ret = sys_setrlimit(resource, &r);
2294        set_fs (old_fs);
2295        return ret;
2296}
2297
2298extern asmlinkage int sys_getrusage(int who, struct rusage *ru);
2299
2300asmlinkage int sys32_getrusage(int who, struct rusage32 *ru)
2301{
2302        struct rusage r;
2303        int ret;
2304        mm_segment_t old_fs = get_fs();
2305                
2306        set_fs (KERNEL_DS);
2307        ret = sys_getrusage(who, &r);
2308        set_fs (old_fs);
2309        if (put_rusage (ru, &r)) return -EFAULT;
2310        return ret;
2311}
2312
2313/* XXX This really belongs in some header file... -DaveM */
2314#define MAX_SOCK_ADDR   128             /* 108 for Unix domain - 
2315                                           16 for IP, 16 for IPX,
2316                                           24 for IPv6,
2317                                           about 80 for AX.25 */
2318
2319extern struct socket *sockfd_lookup(int fd, int *err);
2320
2321/* XXX This as well... */
2322extern __inline__ void sockfd_put(struct socket *sock)
2323{
2324        fput(sock->file);
2325}
2326
2327struct msghdr32 {
2328        u32               msg_name;
2329        int               msg_namelen;
2330        u32               msg_iov;
2331        __kernel_size_t32 msg_iovlen;
2332        u32               msg_control;
2333        __kernel_size_t32 msg_controllen;
2334        unsigned          msg_flags;
2335};
2336
2337struct cmsghdr32 {
2338        __kernel_size_t32 cmsg_len;
2339        int               cmsg_level;
2340        int               cmsg_type;
2341};
2342
2343/* Bleech... */
2344#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
2345#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
2346
2347#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
2348
2349#define CMSG32_DATA(cmsg)       ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
2350#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
2351#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
2352
2353#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
2354                                    (struct cmsghdr32 *)(ctl) : \
2355                                    (struct cmsghdr32 *)NULL)
2356#define CMSG32_FIRSTHDR(msg)    __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
2357
2358__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
2359                                              struct cmsghdr32 *__cmsg, int __cmsg_len)
2360{
2361        struct cmsghdr32 * __ptr;
2362
2363        __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
2364                                     CMSG32_ALIGN(__cmsg_len));
2365        if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
2366                return NULL;
2367
2368        return __ptr;
2369}
2370
2371__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
2372                                            struct cmsghdr32 *__cmsg,
2373                                            int __cmsg_len)
2374{
2375        return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
2376                               __cmsg, __cmsg_len);
2377}
2378
2379static inline int iov_from_user32_to_kern(struct iovec *kiov,
2380                                          struct iovec32 *uiov32,
2381                                          int niov)
2382{
2383        int tot_len = 0;
2384
2385        while(niov > 0) {
2386                u32 len, buf;
2387
2388                if(get_user(len, &uiov32->iov_len) ||
2389                   get_user(buf, &uiov32->iov_base)) {
2390                        tot_len = -EFAULT;
2391                        break;
2392                }
2393                tot_len += len;
2394                kiov->iov_base = (void *)A(buf);
2395                kiov->iov_len = (__kernel_size_t) len;
2396                uiov32++;
2397                kiov++;
2398                niov--;
2399        }
2400        return tot_len;
2401}
2402
2403static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
2404                                             struct msghdr32 *umsg)
2405{
2406        u32 tmp1, tmp2, tmp3;
2407        int err;
2408
2409        err = get_user(tmp1, &umsg->msg_name);
2410        err |= __get_user(tmp2, &umsg->msg_iov);
2411        err |= __get_user(tmp3, &umsg->msg_control);
2412        if (err)
2413                return -EFAULT;
2414
2415        kmsg->msg_name = (void *)A(tmp1);
2416        kmsg->msg_iov = (struct iovec *)A(tmp2);
2417        kmsg->msg_control = (void *)A(tmp3);
2418
2419        err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
2420        err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
2421        err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
2422        err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
2423        
2424        return err;
2425}
2426
2427/* I've named the args so it is easy to tell whose space the pointers are in. */
2428static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
2429                          char *kern_address, int mode)
2430{
2431        int tot_len;
2432
2433        if(kern_msg->msg_namelen) {
2434                if(mode==VERIFY_READ) {
2435                        int err = move_addr_to_kernel(kern_msg->msg_name,
2436                                                      kern_msg->msg_namelen,
2437                                                      kern_address);
2438                        if(err < 0)
2439                                return err;
2440                }
2441                kern_msg->msg_name = kern_address;
2442        } else
2443                kern_msg->msg_name = NULL;
2444
2445        if(kern_msg->msg_iovlen > UIO_FASTIOV) {
2446                kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
2447                                   GFP_KERNEL);
2448                if(!kern_iov)
2449                        return -ENOMEM;
2450        }
2451
2452        tot_len = iov_from_user32_to_kern(kern_iov,
2453                                          (struct iovec32 *)kern_msg->msg_iov,
2454                                          kern_msg->msg_iovlen);
2455        if(tot_len >= 0)
2456                kern_msg->msg_iov = kern_iov;
2457        else if(kern_msg->msg_iovlen > UIO_FASTIOV)
2458                kfree(kern_iov);
2459
2460        return tot_len;
2461}
2462
2463/* There is a lot of hair here because the alignment rules (and
2464 * thus placement) of cmsg headers and length are different for
2465 * 32-bit apps.  -DaveM
2466 */
2467static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
2468                                       unsigned char *stackbuf, int stackbuf_size)
2469{
2470        struct cmsghdr32 *ucmsg;
2471        struct cmsghdr *kcmsg, *kcmsg_base;
2472        __kernel_size_t32 ucmlen;
2473        __kernel_size_t kcmlen, tmp;
2474
2475        kcmlen = 0;
2476        kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
2477        ucmsg = CMSG32_FIRSTHDR(kmsg);
2478        while(ucmsg != NULL) {
2479                if(get_user(ucmlen, &ucmsg->cmsg_len))
2480                        return -EFAULT;
2481
2482                /* Catch bogons. */
2483                if(CMSG32_ALIGN(ucmlen) <
2484                   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
2485                        return -EINVAL;
2486                if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
2487                                   + ucmlen) > kmsg->msg_controllen)
2488                        return -EINVAL;
2489
2490                tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
2491                       CMSG_ALIGN(sizeof(struct cmsghdr)));
2492                kcmlen += tmp;
2493                ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
2494        }
2495        if(kcmlen == 0)
2496                return -EINVAL;
2497
2498        /* The kcmlen holds the 64-bit version of the control length.
2499         * It may not be modified as we do not stick it into the kmsg
2500         * until we have successfully copied over all of the data
2501         * from the user.
2502         */
2503        if(kcmlen > stackbuf_size)
2504                kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
2505        if(kcmsg == NULL)
2506                return -ENOBUFS;
2507
2508        /* Now copy them over neatly. */
2509        memset(kcmsg, 0, kcmlen);
2510        ucmsg = CMSG32_FIRSTHDR(kmsg);
2511        while(ucmsg != NULL) {
2512                __get_user(ucmlen, &ucmsg->cmsg_len);
2513                tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
2514                       CMSG_ALIGN(sizeof(struct cmsghdr)));
2515                kcmsg->cmsg_len = tmp;
2516                __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
2517                __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
2518
2519                /* Copy over the data. */
2520                if(copy_from_user(CMSG_DATA(kcmsg),
2521                                  CMSG32_DATA(ucmsg),
2522                                  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
2523                        goto out_free_efault;
2524
2525                /* Advance. */
2526                kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
2527                ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
2528        }
2529
2530        /* Ok, looks like we made it.  Hook it up and return success. */
2531        kmsg->msg_control = kcmsg_base;
2532        kmsg->msg_controllen = kcmlen;
2533        return 0;
2534
2535out_free_efault:
2536        if(kcmsg_base != (struct cmsghdr *)stackbuf)
2537                kfree(kcmsg_base);
2538        return -EFAULT;
2539}
2540
2541static void put_cmsg32(struct msghdr *kmsg, int level, int type,
2542                       int len, void *data)
2543{
2544        struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
2545        struct cmsghdr32 cmhdr;
2546        int cmlen = CMSG32_LEN(len);
2547
2548        if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
2549                kmsg->msg_flags |= MSG_CTRUNC;
2550                return;
2551        }
2552
2553        if(kmsg->msg_controllen < cmlen) {
2554                kmsg->msg_flags |= MSG_CTRUNC;
2555                cmlen = kmsg->msg_controllen;
2556        }
2557        cmhdr.cmsg_level = level;
2558        cmhdr.cmsg_type = type;
2559        cmhdr.cmsg_len = cmlen;
2560
2561        if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
2562                return;
2563        if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
2564                return;
2565        cmlen = CMSG32_SPACE(len);
2566        kmsg->msg_control += cmlen;
2567        kmsg->msg_controllen -= cmlen;
2568}
2569
2570static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
2571{
2572        struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
2573        int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
2574        int fdnum = scm->fp->count;
2575        struct file **fp = scm->fp->fp;
2576        int *cmfptr;
2577        int err = 0, i;
2578
2579        if (fdnum < fdmax)
2580                fdmax = fdnum;
2581
2582        for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
2583                int new_fd;
2584                err = get_unused_fd();
2585                if (err < 0)
2586                        break;
2587                new_fd = err;
2588                err = put_user(new_fd, cmfptr);
2589                if (err) {
2590                        put_unused_fd(new_fd);
2591                        break;
2592                }
2593                /* Bump the usage count and install the file. */
2594                get_file(fp[i]);
2595                fd_install(new_fd, fp[i]);
2596        }
2597
2598        if (i > 0) {
2599                int cmlen = CMSG32_LEN(i * sizeof(int));
2600                if (!err)
2601                        err = put_user(SOL_SOCKET, &cm->cmsg_level);
2602                if (!err)
2603                        err = put_user(SCM_RIGHTS, &cm->cmsg_type);
2604                if (!err)
2605                        err = put_user(cmlen, &cm->cmsg_len);
2606                if (!err) {
2607                        cmlen = CMSG32_SPACE(i * sizeof(int));
2608                        kmsg->msg_control += cmlen;
2609                        kmsg->msg_controllen -= cmlen;
2610                }
2611        }
2612        if (i < fdnum)
2613                kmsg->msg_flags |= MSG_CTRUNC;
2614
2615        /*
2616         * All of the files that fit in the message have had their
2617         * usage counts incremented, so we just free the list.
2618         */
2619        __scm_destroy(scm);
2620}
2621
2622/* In these cases we (currently) can just copy to data over verbatim
2623 * because all CMSGs created by the kernel have well defined types which
2624 * have the same layout in both the 32-bit and 64-bit API.  One must add
2625 * some special cased conversions here if we start sending control messages
2626 * with incompatible types.
2627 *
2628 * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
2629 * we do our work.  The remaining cases are:
2630 *
2631 * SOL_IP       IP_PKTINFO      struct in_pktinfo       32-bit clean
2632 *              IP_TTL          int                     32-bit clean
2633 *              IP_TOS          __u8                    32-bit clean
2634 *              IP_RECVOPTS     variable length         32-bit clean
2635 *              IP_RETOPTS      variable length         32-bit clean
2636 *              (these last two are clean because the types are defined
2637 *               by the IPv4 protocol)
2638 *              IP_RECVERR      struct sock_extended_err +
2639 *                              struct sockaddr_in      32-bit clean
2640 * SOL_IPV6     IPV6_RECVERR    struct sock_extended_err +
2641 *                              struct sockaddr_in6     32-bit clean
2642 *              IPV6_PKTINFO    struct in6_pktinfo      32-bit clean
2643 *              IPV6_HOPLIMIT   int                     32-bit clean
2644 *              IPV6_FLOWINFO   u32                     32-bit clean
2645 *              IPV6_HOPOPTS    ipv6 hop exthdr         32-bit clean
2646 *              IPV6_DSTOPTS    ipv6 dst exthdr(s)      32-bit clean
2647 *              IPV6_RTHDR      ipv6 routing exthdr     32-bit clean
2648 *              IPV6_AUTHHDR    ipv6 auth exthdr        32-bit clean
2649 */
2650static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
2651{
2652        unsigned char *workbuf, *wp;
2653        unsigned long bufsz, space_avail;
2654        struct cmsghdr *ucmsg;
2655
2656        bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
2657        space_avail = kmsg->msg_controllen + bufsz;
2658        wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
2659        if(workbuf == NULL)
2660                goto fail;
2661
2662        /* To make this more sane we assume the kernel sends back properly
2663         * formatted control messages.  Because of how the kernel will truncate
2664         * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
2665         */
2666        ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
2667        while(((unsigned long)ucmsg) <=
2668              (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
2669                struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
2670                int clen64, clen32;
2671
2672                /* UCMSG is the 64-bit format CMSG entry in user-space.
2673                 * KCMSG32 is within the kernel space temporary buffer
2674                 * we use to convert into a 32-bit style CMSG.
2675                 */
2676                __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
2677                __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
2678                __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
2679
2680                clen64 = kcmsg32->cmsg_len;
2681                if (kcmsg32->cmsg_level == SOL_SOCKET &&
2682                        kcmsg32->cmsg_type == SO_TIMESTAMP) {
2683                        struct timeval tv;
2684                        struct timeval32 *tv32;
2685
2686                        if (clen64 != CMSG_LEN(sizeof(struct timeval))) {
2687                                kfree(workbuf);
2688                                goto fail;
2689                        }
2690
2691                        copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv));
2692                        tv32 = (struct timeval32 *)CMSG32_DATA(kcmsg32);
2693                        tv32->tv_sec = tv.tv_sec;
2694                        tv32->tv_usec = tv.tv_usec;
2695                        clen32 = sizeof(*tv32) +
2696                                  CMSG32_ALIGN(sizeof(struct cmsghdr32));
2697                } else {
2698                        copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
2699                                       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
2700                        clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
2701                                  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
2702                }
2703                kcmsg32->cmsg_len = clen32;
2704
2705                ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
2706                wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
2707        }
2708
2709        /* Copy back fixed up data, and adjust pointers. */
2710        bufsz = (wp - workbuf);
2711        copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
2712
2713        kmsg->msg_control = (struct cmsghdr *)
2714                (((char *)orig_cmsg_uptr) + bufsz);
2715        kmsg->msg_controllen = space_avail - bufsz;
2716
2717        kfree(workbuf);
2718        return;
2719
2720fail:
2721        /* If we leave the 64-bit format CMSG chunks in there,
2722         * the application could get confused and crash.  So to
2723         * ensure greater recovery, we report no CMSGs.
2724         */
2725        kmsg->msg_controllen += bufsz;
2726        kmsg->msg_control = (void *) orig_cmsg_uptr;
2727}
2728
2729asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
2730{
2731        struct socket *sock;
2732        char address[MAX_SOCK_ADDR];
2733        struct iovec iov[UIO_FASTIOV];
2734        unsigned char ctl[sizeof(struct cmsghdr) + 20];
2735        unsigned char *ctl_buf = ctl;
2736        struct msghdr kern_msg;
2737        int err, total_len;
2738
2739        if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
2740                return -EFAULT;
2741        if(kern_msg.msg_iovlen > UIO_MAXIOV)
2742                return -EINVAL;
2743        err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
2744        if (err < 0)
2745                goto out;
2746        total_len = err;
2747
2748        if(kern_msg.msg_controllen) {
2749                err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
2750                if(err)
2751                        goto out_freeiov;
2752                ctl_buf = kern_msg.msg_control;
2753        }
2754        kern_msg.msg_flags = user_flags;
2755
2756        sock = sockfd_lookup(fd, &err);
2757        if (sock != NULL) {
2758                if (sock->file->f_flags & O_NONBLOCK)
2759                        kern_msg.msg_flags |= MSG_DONTWAIT;
2760                err = sock_sendmsg(sock, &kern_msg, total_len);
2761                sockfd_put(sock);
2762        }
2763
2764        /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
2765        if(ctl_buf != ctl)
2766                kfree(ctl_buf);
2767out_freeiov:
2768        if(kern_msg.msg_iov != iov)
2769                kfree(kern_msg.msg_iov);
2770out:
2771        return err;
2772}
2773
2774asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
2775{
2776        struct iovec iovstack[UIO_FASTIOV];
2777        struct msghdr kern_msg;
2778        char addr[MAX_SOCK_ADDR];
2779        struct socket *sock;
2780        struct iovec *iov = iovstack;
2781        struct sockaddr *uaddr;
2782        int *uaddr_len;
2783        unsigned long cmsg_ptr;
2784        int err, total_len, len = 0;
2785
2786        if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
2787                return -EFAULT;
2788        if(kern_msg.msg_iovlen > UIO_MAXIOV)
2789                return -EINVAL;
2790
2791        uaddr = kern_msg.msg_name;
2792        uaddr_len = &user_msg->msg_namelen;
2793        err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
2794        if (err < 0)
2795                goto out;
2796        total_len = err;
2797
2798        cmsg_ptr = (unsigned long) kern_msg.msg_control;
2799        kern_msg.msg_flags = 0;
2800
2801        sock = sockfd_lookup(fd, &err);
2802        if (sock != NULL) {
2803                struct scm_cookie scm;
2804
2805                if (sock->file->f_flags & O_NONBLOCK)
2806                        user_flags |= MSG_DONTWAIT;
2807                memset(&scm, 0, sizeof(scm));
2808                err = sock->ops->recvmsg(sock, &kern_msg, total_len,
2809                                         user_flags, &scm);
2810                if(err >= 0) {
2811                        len = err;
2812                        if(!kern_msg.msg_control) {
2813                                if(sock->passcred || scm.fp)
2814                                        kern_msg.msg_flags |= MSG_CTRUNC;
2815                                if(scm.fp)
2816                                        __scm_destroy(&scm);
2817                        } else {
2818                                /* If recvmsg processing itself placed some
2819                                 * control messages into user space, it's is
2820                                 * using 64-bit CMSG processing, so we need
2821                                 * to fix it up before we tack on more stuff.
2822                                 */
2823                                if((unsigned long) kern_msg.msg_control != cmsg_ptr)
2824                                        cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
2825
2826                                /* Wheee... */
2827                                if(sock->passcred)
2828                                        put_cmsg32(&kern_msg,
2829                                                   SOL_SOCKET, SCM_CREDENTIALS,
2830                                                   sizeof(scm.creds), &scm.creds);
2831                                if(scm.fp != NULL)
2832                                        scm_detach_fds32(&kern_msg, &scm);
2833                        }
2834                }
2835                sockfd_put(sock);
2836        }
2837
2838        if(uaddr != NULL && err >= 0)
2839                err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
2840        if(cmsg_ptr != 0 && err >= 0) {
2841                unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
2842                __kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr);
2843                err |= __put_user(uclen, &user_msg->msg_controllen);
2844        }
2845        if(err >= 0)
2846                err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
2847        if(kern_msg.msg_iov != iov)
2848                kfree(kern_msg.msg_iov);
2849out:
2850        if(err < 0)
2851                return err;
2852        return len;
2853}
2854
2855extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
2856                                     char *optval, int optlen);
2857
2858static int do_netfilter_replace(int fd, int level, int optname,
2859                                char *optval, int optlen)
2860{
2861        struct ipt_replace32 {
2862                char name[IPT_TABLE_MAXNAMELEN];
2863                __u32 valid_hooks;
2864                __u32 num_entries;
2865                __u32 size;
2866                __u32 hook_entry[NF_IP_NUMHOOKS];
2867                __u32 underflow[NF_IP_NUMHOOKS];
2868                __u32 num_counters;
2869                __u32 counters;
2870                struct ipt_entry entries[0];
2871        } *repl32 = (struct ipt_replace32 *)optval;
2872        struct ipt_replace *krepl;
2873        struct ipt_counters *counters32;
2874        __u32 origsize;
2875        unsigned int kreplsize, kcountersize;
2876        mm_segment_t old_fs;
2877        int ret;
2878
2879        if (optlen < sizeof(repl32))
2880                return -EINVAL;
2881
2882        if (copy_from_user(&origsize,
2883                        &repl32->size,
2884                        sizeof(origsize)))
2885                return -EFAULT;
2886
2887        kreplsize = sizeof(*krepl) + origsize;
2888        kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
2889
2890        /* Hack: Causes ipchains to give correct error msg --RR */
2891        if (optlen != kreplsize)
2892                return -ENOPROTOOPT;
2893
2894        krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL);
2895        if (krepl == NULL)
2896                return -ENOMEM;
2897
2898        if (copy_from_user(krepl, optval, kreplsize)) {
2899                kfree(krepl);
2900                return -EFAULT;
2901        }
2902
2903        counters32 = (struct ipt_counters *)AA(
2904                ((struct ipt_replace32 *)krepl)->counters);
2905
2906        kcountersize = krepl->num_counters * sizeof(struct ipt_counters);
2907        krepl->counters = (struct ipt_counters *)kmalloc(
2908                                        kcountersize, GFP_KERNEL);
2909        if (krepl->counters == NULL) {
2910                kfree(krepl);
2911                return -ENOMEM;
2912        }
2913
2914        old_fs = get_fs();
2915        set_fs(KERNEL_DS);
2916        ret = sys_setsockopt(fd, level, optname,
2917                             (char *)krepl, kreplsize);
2918        set_fs(old_fs);
2919
2920        if (ret == 0 &&
2921                copy_to_user(counters32, krepl->counters, kcountersize))
2922                        ret = -EFAULT;
2923
2924        kfree(krepl->counters);
2925        kfree(krepl);
2926
2927        return ret;
2928}
2929
2930static int do_set_attach_filter(int fd, int level, int optname,
2931                                char *optval, int optlen)
2932{
2933        struct sock_fprog32 {
2934                __u16 len;
2935                __u32 filter;
2936        } *fprog32 = (struct sock_fprog32 *)optval;
2937        struct sock_fprog kfprog;
2938        struct sock_filter *kfilter;
2939        unsigned int fsize;
2940        mm_segment_t old_fs;
2941        __u32 uptr;
2942        int ret;
2943
2944        if (get_user(kfprog.len, &fprog32->len) ||
2945            __get_user(uptr, &fprog32->filter))
2946                return -EFAULT;
2947
2948        kfprog.filter = (struct sock_filter *)A(uptr);
2949        fsize = kfprog.len * sizeof(struct sock_filter);
2950
2951        kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
2952        if (kfilter == NULL)
2953                return -ENOMEM;
2954
2955        if (copy_from_user(kfilter, kfprog.filter, fsize)) {
2956                kfree(kfilter);
2957                return -EFAULT;
2958        }
2959
2960        kfprog.filter = kfilter;
2961
2962        old_fs = get_fs();
2963        set_fs(KERNEL_DS);
2964        ret = sys_setsockopt(fd, level, optname,
2965                             (char *)&kfprog, sizeof(kfprog));
2966        set_fs(old_fs);
2967
2968        kfree(kfilter);
2969
2970        return ret;
2971}
2972
2973static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen)
2974{
2975        struct timeval32 *up = (struct timeval32 *) optval;
2976        struct timeval ktime;
2977        mm_segment_t old_fs;
2978        int err;
2979
2980        if (optlen < sizeof(*up))
2981                return -EINVAL;
2982        if (get_user(ktime.tv_sec, &up->tv_sec) ||
2983            __get_user(ktime.tv_usec, &up->tv_usec))
2984                return -EFAULT;
2985        old_fs = get_fs();
2986        set_fs(KERNEL_DS);
2987        err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime));
2988        set_fs(old_fs);
2989
2990        return err;
2991}
2992
2993asmlinkage int sys32_setsockopt(int fd, int level, int optname,
2994                                char *optval, int optlen)
2995{
2996        if (optname == IPT_SO_SET_REPLACE)
2997                return do_netfilter_replace(fd, level, optname,
2998                                            optval, optlen);
2999        if (optname == SO_ATTACH_FILTER)
3000                return do_set_attach_filter(fd, level, optname,
3001                                            optval, optlen);
3002        if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
3003                return do_set_sock_timeout(fd, level, optname, optval, optlen);
3004
3005        return sys_setsockopt(fd, level, optname, optval, optlen);
3006}
3007
3008extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
3009                                      char *optval, int *optlen);
3010
3011static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
3012{
3013        struct timeval32 *up = (struct timeval32 *) optval;
3014        struct timeval ktime;
3015        mm_segment_t old_fs;
3016        int len, err;
3017
3018        if (get_user(len, optlen))
3019                return -EFAULT;
3020        if (len < sizeof(*up))
3021                return -EINVAL;
3022        len = sizeof(ktime);
3023        old_fs = get_fs();
3024        set_fs(KERNEL_DS);
3025        err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
3026        set_fs(old_fs);
3027
3028        if (!err) {
3029                if (put_user(sizeof(*up), optlen) ||
3030                    put_user(ktime.tv_sec, &up->tv_sec) ||
3031                    __put_user(ktime.tv_usec, &up->tv_usec))
3032                        err = -EFAULT;
3033        }
3034        return err;
3035}
3036
3037asmlinkage int sys32_getsockopt(int fd, int level, int optname,
3038                                char *optval, int *optlen)
3039{
3040        if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
3041                return do_get_sock_timeout(fd, level, optname, optval, optlen);
3042        return sys_getsockopt(fd, level, optname, optval, optlen);
3043}
3044
3045extern void check_pending(int signum);
3046
3047asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
3048{
3049        struct k_sigaction new_ka, old_ka;
3050        int ret;
3051
3052        if(sig < 0) {
3053                current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
3054                sig = -sig;
3055        }
3056
3057        if (act) {
3058                old_sigset_t32 mask;
3059                
3060                ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
3061                ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer);
3062                ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
3063                ret |= __get_user(mask, &act->sa_mask);
3064                if (ret)
3065                        return ret;
3066                new_ka.ka_restorer = NULL;
3067                siginitset(&new_ka.sa.sa_mask, mask);
3068        }
3069
3070        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
3071
3072        if (!ret && oact) {
3073                ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
3074                ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
3075                ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
3076                ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
3077        }
3078
3079        return ret;
3080}
3081
3082asmlinkage int
3083sys32_rt_sigaction(int sig, struct sigaction32 *act, struct sigaction32 *oact,
3084                   void *restorer, __kernel_size_t32 sigsetsize)
3085{
3086        struct k_sigaction new_ka, old_ka;
3087        int ret;
3088        sigset_t32 set32;
3089
3090        /* XXX: Don't preclude handling different sized sigset_t's.  */
3091        if (sigsetsize != sizeof(sigset_t32))
3092                return -EINVAL;
3093
3094        /* All tasks which use RT signals (effectively) use
3095         * new style signals.
3096         */
3097        current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
3098
3099        if (act) {
3100                new_ka.ka_restorer = restorer;
3101                ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
3102                ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(sigset_t32));
3103                switch (_NSIG_WORDS) {
3104                case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
3105                case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
3106                case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
3107                case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
3108                }
3109                ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
3110                ret |= __get_user((long)new_ka.sa.sa_restorer, &act->sa_restorer);
3111                if (ret)
3112                        return -EFAULT;
3113        }
3114
3115        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
3116
3117        if (!ret && oact) {
3118                switch (_NSIG_WORDS) {
3119                case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
3120                case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
3121                case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
3122                case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
3123                }
3124                ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
3125                ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(sigset_t32));
3126                ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
3127                ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
3128                if (ret)
3129                        ret = -EFAULT;
3130        }
3131
3132        return ret;
3133}
3134
3135
3136/*
3137 * count32() counts the number of arguments/envelopes
3138 */
3139static int count32(u32 * argv, int max)
3140{
3141        int i = 0;
3142
3143        if (argv != NULL) {
3144                for (;;) {
3145                        u32 p; int error;
3146
3147                        error = get_user(p,argv);
3148                        if (error)
3149                                return error;
3150                        if (!p)
3151                                break;
3152                        argv++;
3153                        if (++i > max)
3154                                return -E2BIG;
3155                }
3156        }
3157        return i;
3158}
3159
3160/*
3161 * 'copy_string32()' copies argument/envelope strings from user
3162 * memory to free pages in kernel mem. These are in a format ready
3163 * to be put directly into the top of new user memory.
3164 */
3165static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
3166{
3167        while (argc-- > 0) {
3168                u32 str;
3169                int len;
3170                unsigned long pos;
3171
3172                if (get_user(str, argv + argc) ||
3173                    !str ||
3174                    !(len = strnlen_user((char *)A(str), bprm->p)))
3175                        return -EFAULT;
3176
3177                if (bprm->p < len)
3178                        return -E2BIG;
3179
3180                bprm->p -= len;
3181
3182                pos = bprm->p;
3183                while (len) {
3184                        char *kaddr;
3185                        struct page *page;
3186                        int offset, bytes_to_copy, new, err;
3187
3188                        offset = pos % PAGE_SIZE;
3189                        page = bprm->page[pos / PAGE_SIZE];
3190                        new = 0;
3191                        if (!page) {
3192                                page = alloc_page(GFP_USER);
3193                                bprm->page[pos / PAGE_SIZE] = page;
3194                                if (!page)
3195                                        return -ENOMEM;
3196                                new = 1;
3197                        }
3198                        kaddr = kmap(page);
3199
3200                        if (new && offset)
3201                                memset(kaddr, 0, offset);
3202                        bytes_to_copy = PAGE_SIZE - offset;
3203                        if (bytes_to_copy > len) {
3204                                bytes_to_copy = len;
3205                                if (new)
3206                                        memset(kaddr+offset+len, 0,
3207                                               PAGE_SIZE-offset-len);
3208                        }
3209
3210                        err = copy_from_user(kaddr + offset, (char *)A(str),
3211                                             bytes_to_copy);
3212                        kunmap(page);
3213
3214                        if (err)
3215                                return -EFAULT;
3216
3217                        pos += bytes_to_copy;
3218                        str += bytes_to_copy;
3219                        len -= bytes_to_copy;
3220                }
3221        }
3222        return 0;
3223}
3224
3225/*
3226 * sys32_execve() executes a new program.
3227 */
3228static inline int 
3229do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
3230{
3231        struct linux_binprm bprm;
3232        struct file * file;
3233        int retval;
3234        int i;
3235
3236        bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
3237        memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
3238
3239        file = open_exec(filename);
3240
3241        retval = PTR_ERR(file);
3242        if (IS_ERR(file))
3243                return retval;
3244
3245        bprm.file = file;
3246        bprm.filename = filename;
3247        bprm.sh_bang = 0;
3248        bprm.loader = 0;
3249        bprm.exec = 0;
3250        if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) {
3251                allow_write_access(file);
3252                fput(file);
3253                return bprm.argc;
3254        }
3255        if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) {
3256                allow_write_access(file);
3257                fput(file);
3258                return bprm.envc;
3259        }
3260
3261        retval = prepare_binprm(&bprm);
3262        if (retval < 0)
3263                goto out;
3264        
3265        retval = copy_strings_kernel(1, &bprm.filename, &bprm);
3266        if (retval < 0)
3267                goto out;
3268
3269        bprm.exec = bprm.p;
3270        retval = copy_strings32(bprm.envc, envp, &bprm);
3271        if (retval < 0)
3272                goto out;
3273
3274        retval = copy_strings32(bprm.argc, argv, &bprm);
3275        if (retval < 0)
3276                goto out;
3277
3278        retval = search_binary_handler(&bprm, regs);
3279        if (retval >= 0)
3280                /* execve success */
3281                return retval;
3282
3283out:
3284        /* Something went wrong, return the inode and free the argument pages*/
3285        allow_write_access(bprm.file);
3286        if (bprm.file)
3287                fput(bprm.file);
3288
3289        for (i=0 ; i<MAX_ARG_PAGES ; i++)
3290                if (bprm.page[i])
3291                        __free_page(bprm.page[i]);
3292
3293        return retval;
3294}
3295
3296/*
3297 * sparc32_execve() executes a new program after the asm stub has set
3298 * things up for us.  This should basically do what I want it to.
3299 */
3300asmlinkage int sparc32_execve(struct pt_regs *regs)
3301{
3302        int error, base = 0;
3303        char *filename;
3304
3305        /* User register window flush is done by entry.S */
3306
3307        /* Check for indirect call. */
3308        if((u32)regs->u_regs[UREG_G1] == 0)
3309                base = 1;
3310
3311        filename = getname((char *)AA(regs->u_regs[base + UREG_I0]));
3312        error = PTR_ERR(filename);
3313        if(IS_ERR(filename))
3314                goto out;
3315        error = do_execve32(filename,
3316                (u32 *)AA((u32)regs->u_regs[base + UREG_I1]),
3317                (u32 *)AA((u32)regs->u_regs[base + UREG_I2]), regs);
3318        putname(filename);
3319
3320        if(!error) {
3321                fprs_write(0);
3322                current->thread.xfsr[0] = 0;
3323                current->thread.fpsaved[0] = 0;
3324                regs->tstate &= ~TSTATE_PEF;
3325        }
3326out:
3327        return error;
3328}
3329
3330#ifdef CONFIG_MODULES
3331
3332extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size);
3333
3334asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size)
3335{
3336        return sys_create_module(name_user, (size_t)size);
3337}
3338
3339extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user);
3340
3341/* Hey, when you're trying to init module, take time and prepare us a nice 64bit
3342 * module structure, even if from 32bit modutils... Why to pollute kernel... :))
3343 */
3344asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user)
3345{
3346        return sys_init_module(name_user, mod_user);
3347}
3348
3349extern asmlinkage int sys_delete_module(const char *name_user);
3350
3351asmlinkage int sys32_delete_module(const char *name_user)
3352{
3353        return sys_delete_module(name_user);
3354}
3355
3356struct module_info32 {
3357        u32 addr;
3358        u32 size;
3359        u32 flags;
3360        s32 usecount;
3361};
3362
3363/* Query various bits about modules.  */
3364
3365static inline long
3366get_mod_name(const char *user_name, char **buf)
3367{
3368        unsigned long page;
3369        long retval;
3370
3371        if ((unsigned long)user_name >= TASK_SIZE
3372            && !segment_eq(get_fs (), KERNEL_DS))
3373                return -EFAULT;
3374
3375        page = __get_free_page(GFP_KERNEL);
3376        if (!page)
3377                return -ENOMEM;
3378
3379        retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
3380        if (retval > 0) {
3381                if (retval < PAGE_SIZE) {
3382                        *buf = (char *)page;
3383                        return retval;
3384                }
3385                retval = -ENAMETOOLONG;
3386        } else if (!retval)
3387                retval = -EINVAL;
3388
3389        free_page(page);
3390        return retval;
3391}
3392
3393static inline void
3394put_mod_name(char *buf)
3395{
3396        free_page((unsigned long)buf);
3397}
3398
3399static __inline__ struct module *find_module(const char *name)
3400{
3401        struct module *mod;
3402
3403        for (mod = module_list; mod ; mod = mod->next) {
3404                if (mod->flags & MOD_DELETED)
3405                        continue;
3406                if (!strcmp(mod->name, name))
3407                        break;
3408        }
3409
3410        return mod;
3411}
3412
3413static int
3414qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
3415{
3416        struct module *mod;
3417        size_t nmod, space, len;
3418
3419        nmod = space = 0;
3420
3421        for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
3422                len = strlen(mod->name)+1;
3423                if (len > bufsize)
3424                        goto calc_space_needed;
3425                if (copy_to_user(buf, mod->name, len))
3426                        return -EFAULT;
3427                buf += len;
3428                bufsize -= len;
3429                space += len;
3430        }
3431
3432        if (put_user(nmod, ret))
3433                return -EFAULT;
3434        else
3435                return 0;
3436
3437calc_space_needed:
3438        space += len;
3439        while ((mod = mod->next)->next != NULL)
3440                space += strlen(mod->name)+1;
3441
3442        if (put_user(space, ret))
3443                return -EFAULT;
3444        else
3445                return -ENOSPC;
3446}
3447
3448static int
3449qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3450{
3451        size_t i, space, len;
3452
3453        if (mod->next == NULL)
3454                return -EINVAL;
3455        if (!MOD_CAN_QUERY(mod))
3456                return put_user(0, ret);
3457
3458        space = 0;
3459        for (i = 0; i < mod->ndeps; ++i) {
3460                const char *dep_name = mod->deps[i].dep->name;
3461
3462                len = strlen(dep_name)+1;
3463                if (len > bufsize)
3464                        goto calc_space_needed;
3465                if (copy_to_user(buf, dep_name, len))
3466                        return -EFAULT;
3467                buf += len;
3468                bufsize -= len;
3469                space += len;
3470        }
3471
3472        return put_user(i, ret);
3473
3474calc_space_needed:
3475        space += len;
3476        while (++i < mod->ndeps)
3477                space += strlen(mod->deps[i].dep->name)+1;
3478
3479        if (put_user(space, ret))
3480                return -EFAULT;
3481        else
3482                return -ENOSPC;
3483}
3484
3485static int
3486qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3487{
3488        size_t nrefs, space, len;
3489        struct module_ref *ref;
3490
3491        if (mod->next == NULL)
3492                return -EINVAL;
3493        if (!MOD_CAN_QUERY(mod))
3494                if (put_user(0, ret))
3495                        return -EFAULT;
3496                else
3497                        return 0;
3498
3499        space = 0;
3500        for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
3501                const char *ref_name = ref->ref->name;
3502
3503                len = strlen(ref_name)+1;
3504                if (len > bufsize)
3505                        goto calc_space_needed;
3506                if (copy_to_user(buf, ref_name, len))
3507                        return -EFAULT;
3508                buf += len;
3509                bufsize -= len;
3510                space += len;
3511        }
3512
3513        if (put_user(nrefs, ret))
3514                return -EFAULT;
3515        else
3516                return 0;
3517
3518calc_space_needed:
3519        space += len;
3520        while ((ref = ref->next_ref) != NULL)
3521                space += strlen(ref->ref->name)+1;
3522
3523        if (put_user(space, ret))
3524                return -EFAULT;
3525        else
3526                return -ENOSPC;
3527}
3528
3529static inline int
3530qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3531{
3532        size_t i, space, len;
3533        struct module_symbol *s;
3534        char *strings;
3535        unsigned *vals;
3536
3537        if (!MOD_CAN_QUERY(mod))
3538                if (put_user(0, ret))
3539                        return -EFAULT;
3540                else
3541                        return 0;
3542
3543        space = mod->nsyms * 2*sizeof(u32);
3544
3545        i = len = 0;
3546        s = mod->syms;
3547
3548        if (space > bufsize)
3549                goto calc_space_needed;
3550
3551        if (!access_ok(VERIFY_WRITE, buf, space))
3552                return -EFAULT;
3553
3554        bufsize -= space;
3555        vals = (unsigned *)buf;
3556        strings = buf+space;
3557
3558        for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
3559                len = strlen(s->name)+1;
3560                if (len > bufsize)
3561                        goto calc_space_needed;
3562
3563                if (copy_to_user(strings, s->name, len)
3564                    || __put_user(s->value, vals+0)
3565                    || __put_user(space, vals+1))
3566                        return -EFAULT;
3567
3568                strings += len;
3569                bufsize -= len;
3570                space += len;
3571        }
3572
3573        if (put_user(i, ret))
3574                return -EFAULT;
3575        else
3576                return 0;
3577
3578calc_space_needed:
3579        for (; i < mod->nsyms; ++i, ++s)
3580                space += strlen(s->name)+1;
3581
3582        if (put_user(space, ret))
3583                return -EFAULT;
3584        else
3585                return -ENOSPC;
3586}
3587
3588static inline int
3589qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3590{
3591        int error = 0;
3592
3593        if (mod->next == NULL)
3594                return -EINVAL;
3595
3596        if (sizeof(struct module_info32) <= bufsize) {
3597                struct module_info32 info;
3598                info.addr = (unsigned long)mod;
3599                info.size = mod->size;
3600                info.flags = mod->flags;
3601                info.usecount =
3602                        ((mod_member_present(mod, can_unload)
3603                          && mod->can_unload)
3604                         ? -1 : atomic_read(&mod->uc.usecount));
3605
3606                if (copy_to_user(buf, &info, sizeof(struct module_info32)))
3607                        return -EFAULT;
3608        } else
3609                error = -ENOSPC;
3610
3611        if (put_user(sizeof(struct module_info32), ret))
3612                return -EFAULT;
3613
3614        return error;
3615}
3616
3617asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, u32 ret)
3618{
3619        struct module *mod;
3620        int err;
3621
3622        lock_kernel();
3623        if (name_user == 0) {
3624                /* This finds "kernel_module" which is not exported. */
3625                for(mod = module_list; mod->next != NULL; mod = mod->next)
3626                        ;
3627        } else {
3628                long namelen;
3629                char *name;
3630
3631                if ((namelen = get_mod_name(name_user, &name)) < 0) {
3632                        err = namelen;
3633                        goto out;
3634                }
3635                err = -ENOENT;
3636                if (namelen == 0) {
3637                        /* This finds "kernel_module" which is not exported. */
3638                        for(mod = module_list; mod->next != NULL; mod = mod->next)
3639                                ;
3640                } else if ((mod = find_module(name)) == NULL) {
3641                        put_mod_name(name);
3642                        goto out;
3643                }
3644                put_mod_name(name);
3645        }
3646
3647        switch (which)
3648        {
3649        case 0:
3650                err = 0;
3651                break;
3652        case QM_MODULES:
3653                err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret));
3654                break;
3655        case QM_DEPS:
3656                err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3657                break;
3658        case QM_REFS:
3659                err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3660                break;
3661        case QM_SYMBOLS:
3662                err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3663                break;
3664        case QM_INFO:
3665                err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3666                break;
3667        default:
3668                err = -EINVAL;
3669                break;
3670        }
3671out:
3672        unlock_kernel();
3673        return err;
3674}
3675
3676struct kernel_sym32 {
3677        u32 value;
3678        char name[60];
3679};
3680                 
3681extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);
3682
3683asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table)
3684{
3685        int len, i;
3686        struct kernel_sym *tbl;
3687        mm_segment_t old_fs;
3688        
3689        len = sys_get_kernel_syms(NULL);
3690        if (!table) return len;
3691        tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
3692        if (!tbl) return -ENOMEM;
3693        old_fs = get_fs();
3694        set_fs (KERNEL_DS);
3695        sys_get_kernel_syms(tbl);
3696        set_fs (old_fs);
3697        for (i = 0; i < len; i++, table++) {
3698                if (put_user (tbl[i].value, &table->value) ||
3699                    copy_to_user (table->name, tbl[i].name, 60))
3700                        break;
3701        }
3702        kfree (tbl);
3703        return i;
3704}
3705
3706#else /* CONFIG_MODULES */
3707
3708asmlinkage unsigned long
3709sys32_create_module(const char *name_user, size_t size)
3710{
3711        return -ENOSYS;
3712}
3713
3714asmlinkage int
3715sys32_init_module(const char *name_user, struct module *mod_user)
3716{
3717        return -ENOSYS;
3718}
3719
3720asmlinkage int
3721sys32_delete_module(const char *name_user)
3722{
3723        return -ENOSYS;
3724}
3725
3726asmlinkage int
3727sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize,
3728                 size_t *ret)
3729{
3730        /* Let the program know about the new interface.  Not that
3731           it'll do them much good.  */
3732        if (which == 0)
3733                return 0;
3734
3735        return -ENOSYS;
3736}
3737
3738asmlinkage int
3739sys32_get_kernel_syms(struct kernel_sym *table)
3740{
3741        return -ENOSYS;
3742}
3743
3744#endif  /* CONFIG_MODULES */
3745
3746#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
3747/* Stuff for NFS server syscalls... */
3748struct nfsctl_svc32 {
3749        u16                     svc32_port;
3750        s32                     svc32_nthreads;
3751};
3752
3753struct nfsctl_client32 {
3754        s8                      cl32_ident[NFSCLNT_IDMAX+1];
3755        s32                     cl32_naddr;
3756        struct in_addr          cl32_addrlist[NFSCLNT_ADDRMAX];
3757        s32                     cl32_fhkeytype;
3758        s32                     cl32_fhkeylen;
3759        u8                      cl32_fhkey[NFSCLNT_KEYMAX];
3760};
3761
3762struct nfsctl_export32 {
3763        s8                      ex32_client[NFSCLNT_IDMAX+1];
3764        s8                      ex32_path[NFS_MAXPATHLEN+1];
3765        __kernel_dev_t32        ex32_dev;
3766        __kernel_ino_t32        ex32_ino;
3767        s32                     ex32_flags;
3768        __kernel_uid_t32        ex32_anon_uid;
3769        __kernel_gid_t32        ex32_anon_gid;
3770};
3771
3772struct nfsctl_uidmap32 {
3773        u32                     ug32_ident;   /* char * */
3774        __kernel_uid_t32        ug32_uidbase;
3775        s32                     ug32_uidlen;
3776        u32                     ug32_udimap;  /* uid_t * */
3777        __kernel_uid_t32        ug32_gidbase;
3778        s32                     ug32_gidlen;
3779        u32                     ug32_gdimap;  /* gid_t * */
3780};
3781
3782struct nfsctl_fhparm32 {
3783        struct sockaddr         gf32_addr;
3784        __kernel_dev_t32        gf32_dev;
3785        __kernel_ino_t32        gf32_ino;
3786        s32                     gf32_version;
3787};
3788
3789struct nfsctl_fdparm32 {
3790        struct sockaddr         gd32_addr;
3791        s8                      gd32_path[NFS_MAXPATHLEN+1];
3792        s32                     gd32_version;
3793};
3794
3795struct nfsctl_fsparm32 {
3796        struct sockaddr         gd32_addr;
3797        s8                      gd32_path[NFS_MAXPATHLEN+1];
3798        s32                     gd32_maxlen;
3799};
3800
3801struct nfsctl_arg32 {
3802        s32                     ca32_version;   /* safeguard */
3803        union {
3804                struct nfsctl_svc32     u32_svc;
3805                struct nfsctl_client32  u32_client;
3806                struct nfsctl_export32  u32_export;
3807                struct nfsctl_uidmap32  u32_umap;
3808                struct nfsctl_fhparm32  u32_getfh;
3809                struct nfsctl_fdparm32  u32_getfd;
3810                struct nfsctl_fsparm32  u32_getfs;
3811        } u;
3812#define ca32_svc        u.u32_svc
3813#define ca32_client     u.u32_client
3814#define ca32_export     u.u32_export
3815#define ca32_umap       u.u32_umap
3816#define ca32_getfh      u.u32_getfh
3817#define ca32_getfd      u.u32_getfd
3818#define ca32_getfs      u.u32_getfs
3819#define ca32_authd      u.u32_authd
3820};
3821
3822union nfsctl_res32 {
3823        __u8                    cr32_getfh[NFS_FHSIZE];
3824        struct knfsd_fh         cr32_getfs;
3825};
3826
3827static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3828{
3829        int err;
3830        
3831        err = __get_user(karg->ca_version, &arg32->ca32_version);
3832        err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
3833        err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads);
3834        return err;
3835}
3836
3837static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3838{
3839        int err;
3840        
3841        err = __get_user(karg->ca_version, &arg32->ca32_version);
3842        err |= copy_from_user(&karg->ca_client.cl_ident[0],
3843                          &arg32->ca32_client.cl32_ident[0],
3844                          NFSCLNT_IDMAX);
3845        err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr);
3846        err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
3847                          &arg32->ca32_client.cl32_addrlist[0],
3848                          (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
3849        err |= __get_user(karg->ca_client.cl_fhkeytype,
3850                      &arg32->ca32_client.cl32_fhkeytype);
3851        err |= __get_user(karg->ca_client.cl_fhkeylen,
3852                      &arg32->ca32_client.cl32_fhkeylen);
3853        err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
3854                          &arg32->ca32_client.cl32_fhkey[0],
3855                          NFSCLNT_KEYMAX);
3856        return (err ? -EFAULT : 0);
3857}
3858
3859static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3860{
3861        int err;
3862        
3863        err = __get_user(karg->ca_version, &arg32->ca32_version);
3864        err |= copy_from_user(&karg->ca_export.ex_client[0],
3865                          &arg32->ca32_export.ex32_client[0],
3866                          NFSCLNT_IDMAX);
3867        err |= copy_from_user(&karg->ca_export.ex_path[0],
3868                          &arg32->ca32_export.ex32_path[0],
3869                          NFS_MAXPATHLEN);
3870        err |= __get_user(karg->ca_export.ex_dev,
3871                      &arg32->ca32_export.ex32_dev);
3872        err |= __get_user(karg->ca_export.ex_ino,
3873                      &arg32->ca32_export.ex32_ino);
3874        err |= __get_user(karg->ca_export.ex_flags,
3875                      &arg32->ca32_export.ex32_flags);
3876        err |= __get_user(karg->ca_export.ex_anon_uid,
3877                      &arg32->ca32_export.ex32_anon_uid);
3878        err |= __get_user(karg->ca_export.ex_anon_gid,
3879                      &arg32->ca32_export.ex32_anon_gid);
3880        karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid);
3881        karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid);
3882        return (err ? -EFAULT : 0);
3883}
3884
3885static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3886{
3887        u32 uaddr;
3888        int i;
3889        int err;
3890
3891        memset(karg, 0, sizeof(*karg));
3892        if(__get_user(karg->ca_version, &arg32->ca32_version))
3893                return -EFAULT;
3894        karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER);
3895        if(!karg->ca_umap.ug_ident)
3896                return -ENOMEM;
3897        err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
3898        if(strncpy_from_user(karg->ca_umap.ug_ident,
3899                             (char *)A(uaddr), PAGE_SIZE) <= 0)
3900                return -EFAULT;
3901        err |= __get_user(karg->ca_umap.ug_uidbase,
3902                      &arg32->ca32_umap.ug32_uidbase);
3903        err |= __get_user(karg->ca_umap.ug_uidlen,
3904                      &arg32->ca32_umap.ug32_uidlen);
3905        err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
3906        if (err)
3907                return -EFAULT;
3908        karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
3909                                          GFP_USER);
3910        if(!karg->ca_umap.ug_udimap)
3911                return -ENOMEM;
3912        for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
3913                err |= __get_user(karg->ca_umap.ug_udimap[i],
3914                              &(((__kernel_uid_t32 *)A(uaddr))[i]));
3915        err |= __get_user(karg->ca_umap.ug_gidbase,
3916                      &arg32->ca32_umap.ug32_gidbase);
3917        err |= __get_user(karg->ca_umap.ug_uidlen,
3918                      &arg32->ca32_umap.ug32_gidlen);
3919        err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
3920        if (err)
3921                return -EFAULT;
3922        karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
3923                                          GFP_USER);
3924        if(!karg->ca_umap.ug_gdimap)
3925                return -ENOMEM;
3926        for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
3927                err |= __get_user(karg->ca_umap.ug_gdimap[i],
3928                              &(((__kernel_gid_t32 *)A(uaddr))[i]));
3929
3930        return (err ? -EFAULT : 0);
3931}
3932
3933static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3934{
3935        int err;
3936        
3937        err = __get_user(karg->ca_version, &arg32->ca32_version);
3938        err |= copy_from_user(&karg->ca_getfh.gf_addr,
3939                          &arg32->ca32_getfh.gf32_addr,
3940                          (sizeof(struct sockaddr)));
3941        err |= __get_user(karg->ca_getfh.gf_dev,
3942                      &arg32->ca32_getfh.gf32_dev);
3943        err |= __get_user(karg->ca_getfh.gf_ino,
3944                      &arg32->ca32_getfh.gf32_ino);
3945        err |= __get_user(karg->ca_getfh.gf_version,
3946                      &arg32->ca32_getfh.gf32_version);
3947        return (err ? -EFAULT : 0);
3948}
3949
3950static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3951{
3952        int err;
3953        
3954        err = __get_user(karg->ca_version, &arg32->ca32_version);
3955        err |= copy_from_user(&karg->ca_getfd.gd_addr,
3956                          &arg32->ca32_getfd.gd32_addr,
3957                          (sizeof(struct sockaddr)));
3958        err |= copy_from_user(&karg->ca_getfd.gd_path,
3959                          &arg32->ca32_getfd.gd32_path,
3960                          (NFS_MAXPATHLEN+1));
3961        err |= __get_user(karg->ca_getfd.gd_version,
3962                      &arg32->ca32_getfd.gd32_version);
3963        return (err ? -EFAULT : 0);
3964}
3965
3966static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3967{
3968        int err;
3969        
3970        err = __get_user(karg->ca_version, &arg32->ca32_version);
3971        err |= copy_from_user(&karg->ca_getfs.gd_addr,
3972                          &arg32->ca32_getfs.gd32_addr,
3973                          (sizeof(struct sockaddr)));
3974        err |= copy_from_user(&karg->ca_getfs.gd_path,
3975                          &arg32->ca32_getfs.gd32_path,
3976                          (NFS_MAXPATHLEN+1));
3977        err |= __get_user(karg->ca_getfs.gd_maxlen,
3978                      &arg32->ca32_getfs.gd32_maxlen);
3979        return (err ? -EFAULT : 0);
3980}
3981
3982/* This really doesn't need translations, we are only passing
3983 * back a union which contains opaque nfs file handle data.
3984 */
3985static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
3986{
3987        return (copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0);
3988}
3989
3990int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
3991{
3992        struct nfsctl_arg *karg = NULL;
3993        union nfsctl_res *kres = NULL;
3994        mm_segment_t oldfs;
3995        int err;
3996
3997        karg = kmalloc(sizeof(*karg), GFP_USER);
3998        if(!karg)
3999                return -ENOMEM;
4000        if(res32) {
4001                kres = kmalloc(sizeof(*kres), GFP_USER);
4002                if(!kres) {
4003                        kfree(karg);
4004                        return -ENOMEM;
4005                }
4006        }
4007        switch(cmd) {
4008        case NFSCTL_SVC:
4009                err = nfs_svc32_trans(karg, arg32);
4010                break;
4011        case NFSCTL_ADDCLIENT:
4012                err = nfs_clnt32_trans(karg, arg32);
4013                break;
4014        case NFSCTL_DELCLIENT:
4015                err = nfs_clnt32_trans(karg, arg32);
4016                break;
4017        case NFSCTL_EXPORT:
4018        case NFSCTL_UNEXPORT:
4019                err = nfs_exp32_trans(karg, arg32);
4020                break;
4021        /* This one is unimplemented, be we're ready for it. */
4022        case NFSCTL_UGIDUPDATE:
4023                err = nfs_uud32_trans(karg, arg32);
4024                break;
4025        case NFSCTL_GETFH:
4026                err = nfs_getfh32_trans(karg, arg32);
4027                break;
4028        case NFSCTL_GETFD:
4029                err = nfs_getfd32_trans(karg, arg32);
4030                break;
4031        case NFSCTL_GETFS:
4032                err = nfs_getfs32_trans(karg, arg32);
4033                break;
4034        default:
4035                err = -EINVAL;
4036                break;
4037        }
4038        if(err)
4039                goto done;
4040        oldfs = get_fs();
4041        set_fs(KERNEL_DS);
4042        err = sys_nfsservctl(cmd, karg, kres);
4043        set_fs(oldfs);
4044
4045        if (err)
4046                goto done;
4047
4048        if((cmd == NFSCTL_GETFH) ||
4049           (cmd == NFSCTL_GETFD) ||
4050           (cmd == NFSCTL_GETFS))
4051                err = nfs_getfh32_res_trans(kres, res32);
4052
4053done:
4054        if(karg) {
4055                if(cmd == NFSCTL_UGIDUPDATE) {
4056                        if(karg->ca_umap.ug_ident)
4057                                kfree(karg->ca_umap.ug_ident);
4058                        if(karg->ca_umap.ug_udimap)
4059                                kfree(karg->ca_umap.ug_udimap);
4060                        if(karg->ca_umap.ug_gdimap)
4061                                kfree(karg->ca_umap.ug_gdimap);
4062                }
4063                kfree(karg);
4064        }
4065        if(kres)
4066                kfree(kres);
4067        return err;
4068}
4069#else /* !NFSD */
4070extern asmlinkage long sys_ni_syscall(void);
4071int asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2)
4072{
4073        return sys_ni_syscall();
4074}
4075#endif
4076
4077/* Translations due to time_t size differences.  Which affects all
4078   sorts of things, like timeval and itimerval.  */
4079
4080extern struct timezone sys_tz;
4081extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
4082
4083asmlinkage int sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
4084{
4085        if (tv) {
4086                struct timeval ktv;
4087                do_gettimeofday(&ktv);
4088                if (put_tv32(tv, &ktv))
4089                        return -EFAULT;
4090        }
4091        if (tz) {
4092                if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
4093                        return -EFAULT;
4094        }
4095        return 0;
4096}
4097
4098asmlinkage int sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
4099{
4100        struct timeval ktv;
4101        struct timezone ktz;
4102
4103        if (tv) {
4104                if (get_tv32(&ktv, tv))
4105                        return -EFAULT;
4106        }
4107        if (tz) {
4108                if (copy_from_user(&ktz, tz, sizeof(ktz)))
4109                        return -EFAULT;
4110        }
4111
4112        return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
4113}
4114
4115extern int do_getitimer(int which, struct itimerval *value);
4116
4117asmlinkage int sys32_getitimer(int which, struct itimerval32 *it)
4118{
4119        struct itimerval kit;
4120        int error;
4121
4122        error = do_getitimer(which, &kit);
4123        if (!error && put_it32(it, &kit))
4124                error = -EFAULT;
4125
4126        return error;
4127}
4128
4129extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
4130
4131asmlinkage int sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
4132{
4133        struct itimerval kin, kout;
4134        int error;
4135
4136        if (in) {
4137                if (get_it32(&kin, in))
4138                        return -EFAULT;
4139        } else
4140                memset(&kin, 0, sizeof(kin));
4141
4142        error = do_setitimer(which, &kin, out ? &kout : NULL);
4143        if (error || !out)
4144                return error;
4145        if (put_it32(out, &kout))
4146                return -EFAULT;
4147
4148        return 0;
4149
4150}
4151
4152asmlinkage int sys_utimes(char *, struct timeval *);
4153
4154asmlinkage int sys32_utimes(char *filename, struct timeval32 *tvs)
4155{
4156        char *kfilename;
4157        struct timeval ktvs[2];
4158        mm_segment_t old_fs;
4159        int ret;
4160
4161        kfilename = getname(filename);
4162        ret = PTR_ERR(kfilename);
4163        if (!IS_ERR(kfilename)) {
4164                if (tvs) {
4165                        if (get_tv32(&ktvs[0], tvs) ||
4166                            get_tv32(&ktvs[1], 1+tvs))
4167                                return -EFAULT;
4168                }
4169
4170                old_fs = get_fs();
4171                set_fs(KERNEL_DS);
4172                ret = sys_utimes(kfilename, &ktvs[0]);
4173                set_fs(old_fs);
4174
4175                putname(kfilename);
4176        }
4177        return ret;
4178}
4179
4180/* These are here just in case some old sparc32 binary calls it. */
4181asmlinkage int sys32_pause(void)
4182{
4183        current->state = TASK_INTERRUPTIBLE;
4184        schedule();
4185        return -ERESTARTNOHAND;
4186}
4187
4188/* PCI config space poking. */
4189extern asmlinkage int sys_pciconfig_read(unsigned long bus,
4190                                         unsigned long dfn,
4191                                         unsigned long off,
4192                                         unsigned long len,
4193                                         unsigned char *buf);
4194
4195extern asmlinkage int sys_pciconfig_write(unsigned long bus,
4196                                          unsigned long dfn,
4197                                          unsigned long off,
4198                                          unsigned long len,
4199                                          unsigned char *buf);
4200
4201asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
4202{
4203        return sys_pciconfig_read((unsigned long) bus,
4204                                  (unsigned long) dfn,
4205                                  (unsigned long) off,
4206                                  (unsigned long) len,
4207                                  (unsigned char *)AA(ubuf));
4208}
4209
4210asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
4211{
4212        return sys_pciconfig_write((unsigned long) bus,
4213                                   (unsigned long) dfn,
4214                                   (unsigned long) off,
4215                                   (unsigned long) len,
4216                                   (unsigned char *)AA(ubuf));
4217}
4218
4219extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
4220                                unsigned long arg4, unsigned long arg5);
4221
4222asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
4223{
4224        return sys_prctl(option,
4225                         (unsigned long) arg2,
4226                         (unsigned long) arg3,
4227                         (unsigned long) arg4,
4228                         (unsigned long) arg5);
4229}
4230
4231
4232extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
4233                                    size_t count, loff_t pos);
4234
4235extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
4236                                     size_t count, loff_t pos);
4237
4238typedef __kernel_ssize_t32 ssize_t32;
4239
4240asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf,
4241                                 __kernel_size_t32 count, u32 poshi, u32 poslo)
4242{
4243        return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
4244}
4245
4246asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
4247                                  __kernel_size_t32 count, u32 poshi, u32 poslo)
4248{
4249        return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
4250}
4251
4252extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);
4253
4254asmlinkage ssize_t32 sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count)
4255{
4256        return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
4257}
4258
4259extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
4260
4261asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
4262{
4263        mm_segment_t old_fs = get_fs();
4264        int ret;
4265        off_t of;
4266        
4267        if (offset && get_user(of, offset))
4268                return -EFAULT;
4269                
4270        set_fs(KERNEL_DS);
4271        ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
4272        set_fs(old_fs);
4273        
4274        if (offset && put_user(of, offset))
4275                return -EFAULT;
4276                
4277        return ret;
4278}
4279
4280/* Handle adjtimex compatability. */
4281
4282struct timex32 {
4283        u32 modes;
4284        s32 offset, freq, maxerror, esterror;
4285        s32 status, constant, precision, tolerance;
4286        struct timeval32 time;
4287        s32 tick;
4288        s32 ppsfreq, jitter, shift, stabil;
4289        s32 jitcnt, calcnt, errcnt, stbcnt;
4290        s32  :32; s32  :32; s32  :32; s32  :32;
4291        s32  :32; s32  :32; s32  :32; s32  :32;
4292        s32  :32; s32  :32; s32  :32; s32  :32;
4293};
4294
4295extern int do_adjtimex(struct timex *);
4296
4297asmlinkage int sys32_adjtimex(struct timex32 *utp)
4298{
4299        struct timex txc;
4300        int ret;
4301
4302        memset(&txc, 0, sizeof(struct timex));
4303
4304        if(get_user(txc.modes, &utp->modes) ||
4305           __get_user(txc.offset, &utp->offset) ||
4306           __get_user(txc.freq, &utp->freq) ||
4307           __get_user(txc.maxerror, &utp->maxerror) ||
4308           __get_user(txc.esterror, &utp->esterror) ||
4309           __get_user(txc.status, &utp->status) ||
4310           __get_user(txc.constant, &utp->constant) ||
4311           __get_user(txc.precision, &utp->precision) ||
4312           __get_user(txc.tolerance, &utp->tolerance) ||
4313           __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
4314           __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
4315           __get_user(txc.tick, &utp->tick) ||
4316           __get_user(txc.ppsfreq, &utp->ppsfreq) ||
4317           __get_user(txc.jitter, &utp->jitter) ||
4318           __get_user(txc.shift, &utp->shift) ||
4319           __get_user(txc.stabil, &utp->stabil) ||
4320           __get_user(txc.jitcnt, &utp->jitcnt) ||
4321           __get_user(txc.calcnt, &utp->calcnt) ||
4322           __get_user(txc.errcnt, &utp->errcnt) ||
4323           __get_user(txc.stbcnt, &utp->stbcnt))
4324                return -EFAULT;
4325
4326        ret = do_adjtimex(&txc);
4327
4328        if(put_user(txc.modes, &utp->modes) ||
4329           __put_user(txc.offset, &utp->offset) ||
4330           __put_user(txc.freq, &utp->freq) ||
4331           __put_user(txc.maxerror, &utp->maxerror) ||
4332           __put_user(txc.esterror, &utp->esterror) ||
4333           __put_user(txc.status, &utp->status) ||
4334           __put_user(txc.constant, &utp->constant) ||
4335           __put_user(txc.precision, &utp->precision) ||
4336           __put_user(txc.tolerance, &utp->tolerance) ||
4337           __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
4338           __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
4339           __put_user(txc.tick, &utp->tick) ||
4340           __put_user(txc.ppsfreq, &utp->ppsfreq) ||
4341           __put_user(txc.jitter, &utp->jitter) ||
4342           __put_user(txc.shift, &utp->shift) ||
4343           __put_user(txc.stabil, &utp->stabil) ||
4344           __put_user(txc.jitcnt, &utp->jitcnt) ||
4345           __put_user(txc.calcnt, &utp->calcnt) ||
4346           __put_user(txc.errcnt, &utp->errcnt) ||
4347           __put_user(txc.stbcnt, &utp->stbcnt))
4348                ret = -EFAULT;
4349
4350        return ret;
4351}
4352
4353/* This is just a version for 32-bit applications which does
4354 * not force O_LARGEFILE on.
4355 */
4356
4357asmlinkage long sparc32_open(const char * filename, int flags, int mode)
4358{
4359        char * tmp;
4360        int fd, error;
4361
4362        tmp = getname(filename);
4363        fd = PTR_ERR(tmp);
4364        if (!IS_ERR(tmp)) {
4365                fd = get_unused_fd();
4366                if (fd >= 0) {
4367                        struct file * f = filp_open(tmp, flags, mode);
4368                        error = PTR_ERR(f);
4369                        if (IS_ERR(f))
4370                                goto out_error;
4371                        fd_install(fd, f);
4372                }
4373out:
4374                putname(tmp);
4375        }
4376        return fd;
4377
4378out_error:
4379        put_unused_fd(fd);
4380        fd = error;
4381        goto out;
4382}
4383
4384extern unsigned long do_mremap(unsigned long addr,
4385        unsigned long old_len, unsigned long new_len,
4386        unsigned long flags, unsigned long new_addr);
4387                
4388asmlinkage unsigned long sys32_mremap(unsigned long addr,
4389        unsigned long old_len, unsigned long new_len,
4390        unsigned long flags, u32 __new_addr)
4391{
4392        struct vm_area_struct *vma;
4393        unsigned long ret = -EINVAL;
4394        unsigned long new_addr = AA(__new_addr);
4395
4396        if (old_len > 0xf0000000UL || new_len > 0xf0000000UL)
4397                goto out;
4398        if (addr > 0xf0000000UL - old_len)
4399                goto out;
4400        down_write(&current->mm->mmap_sem);
4401        if (flags & MREMAP_FIXED) {
4402                if (new_addr > 0xf0000000UL - new_len)
4403                        goto out_sem;
4404        } else if (addr > 0xf0000000UL - new_len) {
4405                unsigned long map_flags = 0;
4406                struct file *file = NULL;
4407
4408                ret = -ENOMEM;
4409                if (!(flags & MREMAP_MAYMOVE))
4410                        goto out_sem;
4411
4412                vma = find_vma(current->mm, addr);
4413                if (vma) {
4414                        if (vma->vm_flags & VM_SHARED)
4415                                map_flags |= MAP_SHARED;
4416                        file = vma->vm_file;
4417                }
4418
4419                /* MREMAP_FIXED checked above. */
4420                new_addr = get_unmapped_area(file, addr, new_len,
4421                                    vma ? vma->vm_pgoff : 0,
4422                                    map_flags);
4423                ret = new_addr;
4424                if (new_addr & ~PAGE_MASK)
4425                        goto out_sem;
4426                flags |= MREMAP_FIXED;
4427        }
4428        ret = do_mremap(addr, old_len, new_len, flags, new_addr);
4429out_sem:
4430        up_write(&current->mm->mmap_sem);
4431out:
4432        return ret;       
4433}
4434
4435extern asmlinkage long sys_setpriority(int which, int who, int niceval);
4436
4437asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval)
4438{
4439        return sys_setpriority((int) which,
4440                               (int) who,
4441                               (int) niceval);
4442}
4443
4444struct __sysctl_args32 {
4445        u32 name;
4446        int nlen;
4447        u32 oldval;
4448        u32 oldlenp;
4449        u32 newval;
4450        u32 newlen;
4451        u32 __unused[4];
4452};
4453
4454extern asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
4455{
4456#ifndef CONFIG_SYSCTL
4457        return -ENOSYS;
4458#else
4459        struct __sysctl_args32 tmp;
4460        int error;
4461        size_t oldlen, *oldlenp = NULL;
4462        unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
4463
4464        if (copy_from_user(&tmp, args, sizeof(tmp)))
4465                return -EFAULT;
4466
4467        if (tmp.oldval && tmp.oldlenp) {
4468                /* Duh, this is ugly and might not work if sysctl_args
4469                   is in read-only memory, but do_sysctl does indirectly
4470                   a lot of uaccess in both directions and we'd have to
4471                   basically copy the whole sysctl.c here, and
4472                   glibc's __sysctl uses rw memory for the structure
4473                   anyway.  */
4474                if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
4475                    put_user(oldlen, (size_t *)addr))
4476                        return -EFAULT;
4477                oldlenp = (size_t *)addr;
4478        }
4479
4480        lock_kernel();
4481        error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
4482                          oldlenp, (void *)A(tmp.newval), tmp.newlen);
4483        unlock_kernel();
4484        if (oldlenp) {
4485                if (!error) {
4486                        if (get_user(oldlen, (size_t *)addr) ||
4487                            put_user(oldlen, (u32 *)A(tmp.oldlenp)))
4488                                error = -EFAULT;
4489                }
4490                copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
4491        }
4492        return error;
4493#endif
4494}
4495
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.