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        dirent = (void *) 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 (level == SOL_SOCKET && optname == SO_ATTACH_FILTER)
3000                return do_set_attach_filter(fd, level, optname,
3001                                            optval, optlen);
3002        if (level == SOL_SOCKET && 
3003            (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO))
3004                return do_set_sock_timeout(fd, level, optname, optval, optlen);
3005
3006        return sys_setsockopt(fd, level, optname, optval, optlen);
3007}
3008
3009extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
3010                                      char *optval, int *optlen);
3011
3012static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen)
3013{
3014        struct timeval32 *up = (struct timeval32 *) optval;
3015        struct timeval ktime;
3016        mm_segment_t old_fs;
3017        int len, err;
3018
3019        if (get_user(len, optlen))
3020                return -EFAULT;
3021        if (len < sizeof(*up))
3022                return -EINVAL;
3023        len = sizeof(ktime);
3024        old_fs = get_fs();
3025        set_fs(KERNEL_DS);
3026        err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len);
3027        set_fs(old_fs);
3028
3029        if (!err) {
3030                if (put_user(sizeof(*up), optlen) ||
3031                    put_user(ktime.tv_sec, &up->tv_sec) ||
3032                    __put_user(ktime.tv_usec, &up->tv_usec))
3033                        err = -EFAULT;
3034        }
3035        return err;
3036}
3037
3038asmlinkage int sys32_getsockopt(int fd, int level, int optname,
3039                                char *optval, int *optlen)
3040{
3041        if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)
3042                return do_get_sock_timeout(fd, level, optname, optval, optlen);
3043        return sys_getsockopt(fd, level, optname, optval, optlen);
3044}
3045
3046extern void check_pending(int signum);
3047
3048asmlinkage int sys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
3049{
3050        struct k_sigaction new_ka, old_ka;
3051        int ret;
3052
3053        if(sig < 0) {
3054                current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
3055                sig = -sig;
3056        }
3057
3058        if (act) {
3059                old_sigset_t32 mask;
3060                u32 u_handler, u_restorer;
3061                
3062                ret = get_user(u_handler, &act->sa_handler);
3063                new_ka.sa.sa_handler = (void *) (long) u_handler;
3064                ret |= __get_user(u_restorer, &act->sa_restorer);
3065                new_ka.sa.sa_restorer = (void *) (long) u_restorer;
3066                ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
3067                ret |= __get_user(mask, &act->sa_mask);
3068                if (ret)
3069                        return ret;
3070                new_ka.ka_restorer = NULL;
3071                siginitset(&new_ka.sa.sa_mask, mask);
3072        }
3073
3074        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
3075
3076        if (!ret && oact) {
3077                ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
3078                ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
3079                ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
3080                ret |= __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
3081        }
3082
3083        return ret;
3084}
3085
3086asmlinkage int
3087sys32_rt_sigaction(int sig, struct sigaction32 *act, struct sigaction32 *oact,
3088                   void *restorer, __kernel_size_t32 sigsetsize)
3089{
3090        struct k_sigaction new_ka, old_ka;
3091        int ret;
3092        sigset_t32 set32;
3093
3094        /* XXX: Don't preclude handling different sized sigset_t's.  */
3095        if (sigsetsize != sizeof(sigset_t32))
3096                return -EINVAL;
3097
3098        /* All tasks which use RT signals (effectively) use
3099         * new style signals.
3100         */
3101        current->thread.flags |= SPARC_FLAG_NEWSIGNALS;
3102
3103        if (act) {
3104                u32 u_handler, u_restorer;
3105
3106                new_ka.ka_restorer = restorer;
3107                ret = get_user(u_handler, &act->sa_handler);
3108                new_ka.sa.sa_handler = (void *) (long) u_handler;
3109                ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(sigset_t32));
3110                switch (_NSIG_WORDS) {
3111                case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] | (((long)set32.sig[7]) << 32);
3112                case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] | (((long)set32.sig[5]) << 32);
3113                case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] | (((long)set32.sig[3]) << 32);
3114                case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] | (((long)set32.sig[1]) << 32);
3115                }
3116                ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
3117                ret |= __get_user(u_restorer, &act->sa_restorer);
3118                new_ka.sa.sa_restorer = (void *) (long) u_restorer;
3119                if (ret)
3120                        return -EFAULT;
3121        }
3122
3123        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
3124
3125        if (!ret && oact) {
3126                switch (_NSIG_WORDS) {
3127                case 4: set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); set32.sig[6] = old_ka.sa.sa_mask.sig[3];
3128                case 3: set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); set32.sig[4] = old_ka.sa.sa_mask.sig[2];
3129                case 2: set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); set32.sig[2] = old_ka.sa.sa_mask.sig[1];
3130                case 1: set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); set32.sig[0] = old_ka.sa.sa_mask.sig[0];
3131                }
3132                ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
3133                ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(sigset_t32));
3134                ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
3135                ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
3136                if (ret)
3137                        ret = -EFAULT;
3138        }
3139
3140        return ret;
3141}
3142
3143
3144/*
3145 * count32() counts the number of arguments/envelopes
3146 */
3147static int count32(u32 * argv, int max)
3148{
3149        int i = 0;
3150
3151        if (argv != NULL) {
3152                for (;;) {
3153                        u32 p; int error;
3154
3155                        error = get_user(p,argv);
3156                        if (error)
3157                                return error;
3158                        if (!p)
3159                                break;
3160                        argv++;
3161                        if (++i > max)
3162                                return -E2BIG;
3163                }
3164        }
3165        return i;
3166}
3167
3168/*
3169 * 'copy_string32()' copies argument/envelope strings from user
3170 * memory to free pages in kernel mem. These are in a format ready
3171 * to be put directly into the top of new user memory.
3172 */
3173static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
3174{
3175        while (argc-- > 0) {
3176                u32 str;
3177                int len;
3178                unsigned long pos;
3179
3180                if (get_user(str, argv + argc) ||
3181                    !str ||
3182                    !(len = strnlen_user((char *)A(str), bprm->p)))
3183                        return -EFAULT;
3184
3185                if (bprm->p < len)
3186                        return -E2BIG;
3187
3188                bprm->p -= len;
3189
3190                pos = bprm->p;
3191                while (len) {
3192                        char *kaddr;
3193                        struct page *page;
3194                        int offset, bytes_to_copy, new, err;
3195
3196                        offset = pos % PAGE_SIZE;
3197                        page = bprm->page[pos / PAGE_SIZE];
3198                        new = 0;
3199                        if (!page) {
3200                                page = alloc_page(GFP_USER);
3201                                bprm->page[pos / PAGE_SIZE] = page;
3202                                if (!page)
3203                                        return -ENOMEM;
3204                                new = 1;
3205                        }
3206                        kaddr = kmap(page);
3207
3208                        if (new && offset)
3209                                memset(kaddr, 0, offset);
3210                        bytes_to_copy = PAGE_SIZE - offset;
3211                        if (bytes_to_copy > len) {
3212                                bytes_to_copy = len;
3213                                if (new)
3214                                        memset(kaddr+offset+len, 0,
3215                                               PAGE_SIZE-offset-len);
3216                        }
3217
3218                        err = copy_from_user(kaddr + offset, (char *)A(str),
3219                                             bytes_to_copy);
3220                        kunmap(page);
3221
3222                        if (err)
3223                                return -EFAULT;
3224
3225                        pos += bytes_to_copy;
3226                        str += bytes_to_copy;
3227                        len -= bytes_to_copy;
3228                }
3229        }
3230        return 0;
3231}
3232
3233/*
3234 * sys32_execve() executes a new program.
3235 */
3236static inline int 
3237do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
3238{
3239        struct linux_binprm bprm;
3240        struct file * file;
3241        int retval;
3242        int i;
3243
3244        bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
3245        memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
3246
3247        file = open_exec(filename);
3248
3249        retval = PTR_ERR(file);
3250        if (IS_ERR(file))
3251                return retval;
3252
3253        bprm.file = file;
3254        bprm.filename = filename;
3255        bprm.sh_bang = 0;
3256        bprm.loader = 0;
3257        bprm.exec = 0;
3258        if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) {
3259                allow_write_access(file);
3260                fput(file);
3261                return bprm.argc;
3262        }
3263        if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) {
3264                allow_write_access(file);
3265                fput(file);
3266                return bprm.envc;
3267        }
3268
3269        retval = prepare_binprm(&bprm);
3270        if (retval < 0)
3271                goto out;
3272        
3273        retval = copy_strings_kernel(1, &bprm.filename, &bprm);
3274        if (retval < 0)
3275                goto out;
3276
3277        bprm.exec = bprm.p;
3278        retval = copy_strings32(bprm.envc, envp, &bprm);
3279        if (retval < 0)
3280                goto out;
3281
3282        retval = copy_strings32(bprm.argc, argv, &bprm);
3283        if (retval < 0)
3284                goto out;
3285
3286        retval = search_binary_handler(&bprm, regs);
3287        if (retval >= 0)
3288                /* execve success */
3289                return retval;
3290
3291out:
3292        /* Something went wrong, return the inode and free the argument pages*/
3293        allow_write_access(bprm.file);
3294        if (bprm.file)
3295                fput(bprm.file);
3296
3297        for (i=0 ; i<MAX_ARG_PAGES ; i++)
3298                if (bprm.page[i])
3299                        __free_page(bprm.page[i]);
3300
3301        return retval;
3302}
3303
3304/*
3305 * sparc32_execve() executes a new program after the asm stub has set
3306 * things up for us.  This should basically do what I want it to.
3307 */
3308asmlinkage int sparc32_execve(struct pt_regs *regs)
3309{
3310        int error, base = 0;
3311        char *filename;
3312
3313        /* User register window flush is done by entry.S */
3314
3315        /* Check for indirect call. */
3316        if((u32)regs->u_regs[UREG_G1] == 0)
3317                base = 1;
3318
3319        filename = getname((char *)AA(regs->u_regs[base + UREG_I0]));
3320        error = PTR_ERR(filename);
3321        if(IS_ERR(filename))
3322                goto out;
3323        error = do_execve32(filename,
3324                (u32 *)AA((u32)regs->u_regs[base + UREG_I1]),
3325                (u32 *)AA((u32)regs->u_regs[base + UREG_I2]), regs);
3326        putname(filename);
3327
3328        if(!error) {
3329                fprs_write(0);
3330                current->thread.xfsr[0] = 0;
3331                current->thread.fpsaved[0] = 0;
3332                regs->tstate &= ~TSTATE_PEF;
3333        }
3334out:
3335        return error;
3336}
3337
3338#ifdef CONFIG_MODULES
3339
3340extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size);
3341
3342asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size)
3343{
3344        return sys_create_module(name_user, (size_t)size);
3345}
3346
3347extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user);
3348
3349/* Hey, when you're trying to init module, take time and prepare us a nice 64bit
3350 * module structure, even if from 32bit modutils... Why to pollute kernel... :))
3351 */
3352asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user)
3353{
3354        return sys_init_module(name_user, mod_user);
3355}
3356
3357extern asmlinkage int sys_delete_module(const char *name_user);
3358
3359asmlinkage int sys32_delete_module(const char *name_user)
3360{
3361        return sys_delete_module(name_user);
3362}
3363
3364struct module_info32 {
3365        u32 addr;
3366        u32 size;
3367        u32 flags;
3368        s32 usecount;
3369};
3370
3371/* Query various bits about modules.  */
3372
3373static inline long
3374get_mod_name(const char *user_name, char **buf)
3375{
3376        unsigned long page;
3377        long retval;
3378
3379        if ((unsigned long)user_name >= TASK_SIZE
3380            && !segment_eq(get_fs (), KERNEL_DS))
3381                return -EFAULT;
3382
3383        page = __get_free_page(GFP_KERNEL);
3384        if (!page)
3385                return -ENOMEM;
3386
3387        retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
3388        if (retval > 0) {
3389                if (retval < PAGE_SIZE) {
3390                        *buf = (char *)page;
3391                        return retval;
3392                }
3393                retval = -ENAMETOOLONG;
3394        } else if (!retval)
3395                retval = -EINVAL;
3396
3397        free_page(page);
3398        return retval;
3399}
3400
3401static inline void
3402put_mod_name(char *buf)
3403{
3404        free_page((unsigned long)buf);
3405}
3406
3407static __inline__ struct module *find_module(const char *name)
3408{
3409        struct module *mod;
3410
3411        for (mod = module_list; mod ; mod = mod->next) {
3412                if (mod->flags & MOD_DELETED)
3413                        continue;
3414                if (!strcmp(mod->name, name))
3415                        break;
3416        }
3417
3418        return mod;
3419}
3420
3421static int
3422qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
3423{
3424        struct module *mod;
3425        size_t nmod, space, len;
3426
3427        nmod = space = 0;
3428
3429        for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
3430                len = strlen(mod->name)+1;
3431                if (len > bufsize)
3432                        goto calc_space_needed;
3433                if (copy_to_user(buf, mod->name, len))
3434                        return -EFAULT;
3435                buf += len;
3436                bufsize -= len;
3437                space += len;
3438        }
3439
3440        if (put_user(nmod, ret))
3441                return -EFAULT;
3442        else
3443                return 0;
3444
3445calc_space_needed:
3446        space += len;
3447        while ((mod = mod->next)->next != NULL)
3448                space += strlen(mod->name)+1;
3449
3450        if (put_user(space, ret))
3451                return -EFAULT;
3452        else
3453                return -ENOSPC;
3454}
3455
3456static int
3457qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3458{
3459        size_t i, space, len;
3460
3461        if (mod->next == NULL)
3462                return -EINVAL;
3463        if (!MOD_CAN_QUERY(mod))
3464                return put_user(0, ret);
3465
3466        space = 0;
3467        for (i = 0; i < mod->ndeps; ++i) {
3468                const char *dep_name = mod->deps[i].dep->name;
3469
3470                len = strlen(dep_name)+1;
3471                if (len > bufsize)
3472                        goto calc_space_needed;
3473                if (copy_to_user(buf, dep_name, len))
3474                        return -EFAULT;
3475                buf += len;
3476                bufsize -= len;
3477                space += len;
3478        }
3479
3480        return put_user(i, ret);
3481
3482calc_space_needed:
3483        space += len;
3484        while (++i < mod->ndeps)
3485                space += strlen(mod->deps[i].dep->name)+1;
3486
3487        if (put_user(space, ret))
3488                return -EFAULT;
3489        else
3490                return -ENOSPC;
3491}
3492
3493static int
3494qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3495{
3496        size_t nrefs, space, len;
3497        struct module_ref *ref;
3498
3499        if (mod->next == NULL)
3500                return -EINVAL;
3501        if (!MOD_CAN_QUERY(mod))
3502                if (put_user(0, ret))
3503                        return -EFAULT;
3504                else
3505                        return 0;
3506
3507        space = 0;
3508        for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
3509                const char *ref_name = ref->ref->name;
3510
3511                len = strlen(ref_name)+1;
3512                if (len > bufsize)
3513                        goto calc_space_needed;
3514                if (copy_to_user(buf, ref_name, len))
3515                        return -EFAULT;
3516                buf += len;
3517                bufsize -= len;
3518                space += len;
3519        }
3520
3521        if (put_user(nrefs, ret))
3522                return -EFAULT;
3523        else
3524                return 0;
3525
3526calc_space_needed:
3527        space += len;
3528        while ((ref = ref->next_ref) != NULL)
3529                space += strlen(ref->ref->name)+1;
3530
3531        if (put_user(space, ret))
3532                return -EFAULT;
3533        else
3534                return -ENOSPC;
3535}
3536
3537static inline int
3538qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3539{
3540        size_t i, space, len;
3541        struct module_symbol *s;
3542        char *strings;
3543        unsigned *vals;
3544
3545        if (!MOD_CAN_QUERY(mod))
3546                if (put_user(0, ret))
3547                        return -EFAULT;
3548                else
3549                        return 0;
3550
3551        space = mod->nsyms * 2*sizeof(u32);
3552
3553        i = len = 0;
3554        s = mod->syms;
3555
3556        if (space > bufsize)
3557                goto calc_space_needed;
3558
3559        if (!access_ok(VERIFY_WRITE, buf, space))
3560                return -EFAULT;
3561
3562        bufsize -= space;
3563        vals = (unsigned *)buf;
3564        strings = buf+space;
3565
3566        for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
3567                len = strlen(s->name)+1;
3568                if (len > bufsize)
3569                        goto calc_space_needed;
3570
3571                if (copy_to_user(strings, s->name, len)
3572                    || __put_user(s->value, vals+0)
3573                    || __put_user(space, vals+1))
3574                        return -EFAULT;
3575
3576                strings += len;
3577                bufsize -= len;
3578                space += len;
3579        }
3580
3581        if (put_user(i, ret))
3582                return -EFAULT;
3583        else
3584                return 0;
3585
3586calc_space_needed:
3587        for (; i < mod->nsyms; ++i, ++s)
3588                space += strlen(s->name)+1;
3589
3590        if (put_user(space, ret))
3591                return -EFAULT;
3592        else
3593                return -ENOSPC;
3594}
3595
3596static inline int
3597qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
3598{
3599        int error = 0;
3600
3601        if (mod->next == NULL)
3602                return -EINVAL;
3603
3604        if (sizeof(struct module_info32) <= bufsize) {
3605                struct module_info32 info;
3606                info.addr = (unsigned long)mod;
3607                info.size = mod->size;
3608                info.flags = mod->flags;
3609                info.usecount =
3610                        ((mod_member_present(mod, can_unload)
3611                          && mod->can_unload)
3612                         ? -1 : atomic_read(&mod->uc.usecount));
3613
3614                if (copy_to_user(buf, &info, sizeof(struct module_info32)))
3615                        return -EFAULT;
3616        } else
3617                error = -ENOSPC;
3618
3619        if (put_user(sizeof(struct module_info32), ret))
3620                return -EFAULT;
3621
3622        return error;
3623}
3624
3625asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, u32 ret)
3626{
3627        struct module *mod;
3628        int err;
3629
3630        lock_kernel();
3631        if (name_user == 0) {
3632                /* This finds "kernel_module" which is not exported. */
3633                for(mod = module_list; mod->next != NULL; mod = mod->next)
3634                        ;
3635        } else {
3636                long namelen;
3637                char *name;
3638
3639                if ((namelen = get_mod_name(name_user, &name)) < 0) {
3640                        err = namelen;
3641                        goto out;
3642                }
3643                err = -ENOENT;
3644                if (namelen == 0) {
3645                        /* This finds "kernel_module" which is not exported. */
3646                        for(mod = module_list; mod->next != NULL; mod = mod->next)
3647                                ;
3648                } else if ((mod = find_module(name)) == NULL) {
3649                        put_mod_name(name);
3650                        goto out;
3651                }
3652                put_mod_name(name);
3653        }
3654
3655        switch (which)
3656        {
3657        case 0:
3658                err = 0;
3659                break;
3660        case QM_MODULES:
3661                err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret));
3662                break;
3663        case QM_DEPS:
3664                err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3665                break;
3666        case QM_REFS:
3667                err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3668                break;
3669        case QM_SYMBOLS:
3670                err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3671                break;
3672        case QM_INFO:
3673                err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
3674                break;
3675        default:
3676                err = -EINVAL;
3677                break;
3678        }
3679out:
3680        unlock_kernel();
3681        return err;
3682}
3683
3684struct kernel_sym32 {
3685        u32 value;
3686        char name[60];
3687};
3688                 
3689extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);
3690
3691asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table)
3692{
3693        int len, i;
3694        struct kernel_sym *tbl;
3695        mm_segment_t old_fs;
3696        
3697        len = sys_get_kernel_syms(NULL);
3698        if (!table) return len;
3699        tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
3700        if (!tbl) return -ENOMEM;
3701        old_fs = get_fs();
3702        set_fs (KERNEL_DS);
3703        sys_get_kernel_syms(tbl);
3704        set_fs (old_fs);
3705        for (i = 0; i < len; i++, table++) {
3706                if (put_user (tbl[i].value, &table->value) ||
3707                    copy_to_user (table->name, tbl[i].name, 60))
3708                        break;
3709        }
3710        kfree (tbl);
3711        return i;
3712}
3713
3714#else /* CONFIG_MODULES */
3715
3716asmlinkage unsigned long
3717sys32_create_module(const char *name_user, size_t size)
3718{
3719        return -ENOSYS;
3720}
3721
3722asmlinkage int
3723sys32_init_module(const char *name_user, struct module *mod_user)
3724{
3725        return -ENOSYS;
3726}
3727
3728asmlinkage int
3729sys32_delete_module(const char *name_user)
3730{
3731        return -ENOSYS;
3732}
3733
3734asmlinkage int
3735sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize,
3736                 size_t *ret)
3737{
3738        /* Let the program know about the new interface.  Not that
3739           it'll do them much good.  */
3740        if (which == 0)
3741                return 0;
3742
3743        return -ENOSYS;
3744}
3745
3746asmlinkage int
3747sys32_get_kernel_syms(struct kernel_sym *table)
3748{
3749        return -ENOSYS;
3750}
3751
3752#endif  /* CONFIG_MODULES */
3753
3754#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
3755/* Stuff for NFS server syscalls... */
3756struct nfsctl_svc32 {
3757        u16                     svc32_port;
3758        s32                     svc32_nthreads;
3759};
3760
3761struct nfsctl_client32 {
3762        s8                      cl32_ident[NFSCLNT_IDMAX+1];
3763        s32                     cl32_naddr;
3764        struct in_addr          cl32_addrlist[NFSCLNT_ADDRMAX];
3765        s32                     cl32_fhkeytype;
3766        s32                     cl32_fhkeylen;
3767        u8                      cl32_fhkey[NFSCLNT_KEYMAX];
3768};
3769
3770struct nfsctl_export32 {
3771        s8                      ex32_client[NFSCLNT_IDMAX+1];
3772        s8                      ex32_path[NFS_MAXPATHLEN+1];
3773        __kernel_dev_t32        ex32_dev;
3774        __kernel_ino_t32        ex32_ino;
3775        s32                     ex32_flags;
3776        __kernel_uid_t32        ex32_anon_uid;
3777        __kernel_gid_t32        ex32_anon_gid;
3778};
3779
3780struct nfsctl_uidmap32 {
3781        u32                     ug32_ident;   /* char * */
3782        __kernel_uid_t32        ug32_uidbase;
3783        s32                     ug32_uidlen;
3784        u32                     ug32_udimap;  /* uid_t * */
3785        __kernel_uid_t32        ug32_gidbase;
3786        s32                     ug32_gidlen;
3787        u32                     ug32_gdimap;  /* gid_t * */
3788};
3789
3790struct nfsctl_fhparm32 {
3791        struct sockaddr         gf32_addr;
3792        __kernel_dev_t32        gf32_dev;
3793        __kernel_ino_t32        gf32_ino;
3794        s32                     gf32_version;
3795};
3796
3797struct nfsctl_fdparm32 {
3798        struct sockaddr         gd32_addr;
3799        s8                      gd32_path[NFS_MAXPATHLEN+1];
3800        s32                     gd32_version;
3801};
3802
3803struct nfsctl_fsparm32 {
3804        struct sockaddr         gd32_addr;
3805        s8                      gd32_path[NFS_MAXPATHLEN+1];
3806        s32                     gd32_maxlen;
3807};
3808
3809struct nfsctl_arg32 {
3810        s32                     ca32_version;   /* safeguard */
3811        union {
3812                struct nfsctl_svc32     u32_svc;
3813                struct nfsctl_client32  u32_client;
3814                struct nfsctl_export32  u32_export;
3815                struct nfsctl_uidmap32  u32_umap;
3816                struct nfsctl_fhparm32  u32_getfh;
3817                struct nfsctl_fdparm32  u32_getfd;
3818                struct nfsctl_fsparm32  u32_getfs;
3819        } u;
3820#define ca32_svc        u.u32_svc
3821#define ca32_client     u.u32_client
3822#define ca32_export     u.u32_export
3823#define ca32_umap       u.u32_umap
3824#define ca32_getfh      u.u32_getfh
3825#define ca32_getfd      u.u32_getfd
3826#define ca32_getfs      u.u32_getfs
3827#define ca32_authd      u.u32_authd
3828};
3829
3830union nfsctl_res32 {
3831        __u8                    cr32_getfh[NFS_FHSIZE];
3832        struct knfsd_fh         cr32_getfs;
3833};
3834
3835static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3836{
3837        int err;
3838        
3839        err = __get_user(karg->ca_version, &arg32->ca32_version);
3840        err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
3841        err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads);
3842        return err;
3843}
3844
3845static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3846{
3847        int err;
3848        
3849        err = __get_user(karg->ca_version, &arg32->ca32_version);
3850        err |= copy_from_user(&karg->ca_client.cl_ident[0],
3851                          &arg32->ca32_client.cl32_ident[0],
3852                          NFSCLNT_IDMAX);
3853        err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr);
3854        err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
3855                          &arg32->ca32_client.cl32_addrlist[0],
3856                          (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
3857        err |= __get_user(karg->ca_client.cl_fhkeytype,
3858                      &arg32->ca32_client.cl32_fhkeytype);
3859        err |= __get_user(karg->ca_client.cl_fhkeylen,
3860                      &arg32->ca32_client.cl32_fhkeylen);
3861        err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
3862                          &arg32->ca32_client.cl32_fhkey[0],
3863                          NFSCLNT_KEYMAX);
3864        return (err ? -EFAULT : 0);
3865}
3866
3867static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3868{
3869        int err;
3870        
3871        err = __get_user(karg->ca_version, &arg32->ca32_version);
3872        err |= copy_from_user(&karg->ca_export.ex_client[0],
3873                          &arg32->ca32_export.ex32_client[0],
3874                          NFSCLNT_IDMAX);
3875        err |= copy_from_user(&karg->ca_export.ex_path[0],
3876                          &arg32->ca32_export.ex32_path[0],
3877                          NFS_MAXPATHLEN);
3878        err |= __get_user(karg->ca_export.ex_dev,
3879                      &arg32->ca32_export.ex32_dev);
3880        err |= __get_user(karg->ca_export.ex_ino,
3881                      &arg32->ca32_export.ex32_ino);
3882        err |= __get_user(karg->ca_export.ex_flags,
3883                      &arg32->ca32_export.ex32_flags);
3884        err |= __get_user(karg->ca_export.ex_anon_uid,
3885                      &arg32->ca32_export.ex32_anon_uid);
3886        err |= __get_user(karg->ca_export.ex_anon_gid,
3887                      &arg32->ca32_export.ex32_anon_gid);
3888        karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid);
3889        karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid);
3890        return (err ? -EFAULT : 0);
3891}
3892
3893static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3894{
3895        u32 uaddr;
3896        int i;
3897        int err;
3898
3899        memset(karg, 0, sizeof(*karg));
3900        if(__get_user(karg->ca_version, &arg32->ca32_version))
3901                return -EFAULT;
3902        karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER);
3903        if(!karg->ca_umap.ug_ident)
3904                return -ENOMEM;
3905        err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
3906        if(strncpy_from_user(karg->ca_umap.ug_ident,
3907                             (char *)A(uaddr), PAGE_SIZE) <= 0)
3908                return -EFAULT;
3909        err |= __get_user(karg->ca_umap.ug_uidbase,
3910                      &arg32->ca32_umap.ug32_uidbase);
3911        err |= __get_user(karg->ca_umap.ug_uidlen,
3912                      &arg32->ca32_umap.ug32_uidlen);
3913        err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
3914        if (err)
3915                return -EFAULT;
3916        karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
3917                                          GFP_USER);
3918        if(!karg->ca_umap.ug_udimap)
3919                return -ENOMEM;
3920        for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
3921                err |= __get_user(karg->ca_umap.ug_udimap[i],
3922                              &(((__kernel_uid_t32 *)A(uaddr))[i]));
3923        err |= __get_user(karg->ca_umap.ug_gidbase,
3924                      &arg32->ca32_umap.ug32_gidbase);
3925        err |= __get_user(karg->ca_umap.ug_uidlen,
3926                      &arg32->ca32_umap.ug32_gidlen);
3927        err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
3928        if (err)
3929                return -EFAULT;
3930        karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
3931                                          GFP_USER);
3932        if(!karg->ca_umap.ug_gdimap)
3933                return -ENOMEM;
3934        for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
3935                err |= __get_user(karg->ca_umap.ug_gdimap[i],
3936                              &(((__kernel_gid_t32 *)A(uaddr))[i]));
3937
3938        return (err ? -EFAULT : 0);
3939}
3940
3941static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3942{
3943        int err;
3944        
3945        err = __get_user(karg->ca_version, &arg32->ca32_version);
3946        err |= copy_from_user(&karg->ca_getfh.gf_addr,
3947                          &arg32->ca32_getfh.gf32_addr,
3948                          (sizeof(struct sockaddr)));
3949        err |= __get_user(karg->ca_getfh.gf_dev,
3950                      &arg32->ca32_getfh.gf32_dev);
3951        err |= __get_user(karg->ca_getfh.gf_ino,
3952                      &arg32->ca32_getfh.gf32_ino);
3953        err |= __get_user(karg->ca_getfh.gf_version,
3954                      &arg32->ca32_getfh.gf32_version);
3955        return (err ? -EFAULT : 0);
3956}
3957
3958static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3959{
3960        int err;
3961        
3962        err = __get_user(karg->ca_version, &arg32->ca32_version);
3963        err |= copy_from_user(&karg->ca_getfd.gd_addr,
3964                          &arg32->ca32_getfd.gd32_addr,
3965                          (sizeof(struct sockaddr)));
3966        err |= copy_from_user(&karg->ca_getfd.gd_path,
3967                          &arg32->ca32_getfd.gd32_path,
3968                          (NFS_MAXPATHLEN+1));
3969        err |= __get_user(karg->ca_getfd.gd_version,
3970                      &arg32->ca32_getfd.gd32_version);
3971        return (err ? -EFAULT : 0);
3972}
3973
3974static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
3975{
3976        int err;
3977        
3978        err = __get_user(karg->ca_version, &arg32->ca32_version);
3979        err |= copy_from_user(&karg->ca_getfs.gd_addr,
3980                          &arg32->ca32_getfs.gd32_addr,
3981                          (sizeof(struct sockaddr)));
3982        err |= copy_from_user(&karg->ca_getfs.gd_path,
3983                          &arg32->ca32_getfs.gd32_path,
3984                          (NFS_MAXPATHLEN+1));
3985        err |= __get_user(karg->ca_getfs.gd_maxlen,
3986                      &arg32->ca32_getfs.gd32_maxlen);
3987        return (err ? -EFAULT : 0);
3988}
3989
3990/* This really doesn't need translations, we are only passing
3991 * back a union which contains opaque nfs file handle data.
3992 */
3993static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
3994{
3995        return (copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0);
3996}
3997
3998int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
3999{
4000        struct nfsctl_arg *karg = NULL;
4001        union nfsctl_res *kres = NULL;
4002        mm_segment_t oldfs;
4003        int err;
4004
4005        karg = kmalloc(sizeof(*karg), GFP_USER);
4006        if(!karg)
4007                return -ENOMEM;
4008        if(res32) {
4009                kres = kmalloc(sizeof(*kres), GFP_USER);
4010                if(!kres) {
4011                        kfree(karg);
4012                        return -ENOMEM;
4013                }
4014        }
4015        switch(cmd) {
4016        case NFSCTL_SVC:
4017                err = nfs_svc32_trans(karg, arg32);
4018                break;
4019        case NFSCTL_ADDCLIENT:
4020                err = nfs_clnt32_trans(karg, arg32);
4021                break;
4022        case NFSCTL_DELCLIENT:
4023                err = nfs_clnt32_trans(karg, arg32);
4024                break;
4025        case NFSCTL_EXPORT:
4026        case NFSCTL_UNEXPORT:
4027                err = nfs_exp32_trans(karg, arg32);
4028                break;
4029        /* This one is unimplemented, be we're ready for it. */
4030        case NFSCTL_UGIDUPDATE:
4031                err = nfs_uud32_trans(karg, arg32);
4032                break;
4033        case NFSCTL_GETFH:
4034                err = nfs_getfh32_trans(karg, arg32);
4035                break;
4036        case NFSCTL_GETFD:
4037                err = nfs_getfd32_trans(karg, arg32);
4038                break;
4039        case NFSCTL_GETFS:
4040                err = nfs_getfs32_trans(karg, arg32);
4041                break;
4042        default:
4043                err = -EINVAL;
4044                break;
4045        }
4046        if(err)
4047                goto done;
4048        oldfs = get_fs();
4049        set_fs(KERNEL_DS);
4050        err = sys_nfsservctl(cmd, karg, kres);
4051        set_fs(oldfs);
4052
4053        if (err)
4054                goto done;
4055
4056        if((cmd == NFSCTL_GETFH) ||
4057           (cmd == NFSCTL_GETFD) ||
4058           (cmd == NFSCTL_GETFS))
4059                err = nfs_getfh32_res_trans(kres, res32);
4060
4061done:
4062        if(karg) {
4063                if(cmd == NFSCTL_UGIDUPDATE) {
4064                        if(karg->ca_umap.ug_ident)
4065                                kfree(karg->ca_umap.ug_ident);
4066                        if(karg->ca_umap.ug_udimap)
4067                                kfree(karg->ca_umap.ug_udimap);
4068                        if(karg->ca_umap.ug_gdimap)
4069                                kfree(karg->ca_umap.ug_gdimap);
4070                }
4071                kfree(karg);
4072        }
4073        if(kres)
4074                kfree(kres);
4075        return err;
4076}
4077#else /* !NFSD */
4078extern asmlinkage long sys_ni_syscall(void);
4079int asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2)
4080{
4081        return sys_ni_syscall();
4082}
4083#endif
4084
4085/* Translations due to time_t size differences.  Which affects all
4086   sorts of things, like timeval and itimerval.  */
4087
4088extern struct timezone sys_tz;
4089extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
4090
4091asmlinkage int sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
4092{
4093        if (tv) {
4094                struct timeval ktv;
4095                do_gettimeofday(&ktv);
4096                if (put_tv32(tv, &ktv))
4097                        return -EFAULT;
4098        }
4099        if (tz) {
4100                if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
4101                        return -EFAULT;
4102        }
4103        return 0;
4104}
4105
4106asmlinkage int sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
4107{
4108        struct timeval ktv;
4109        struct timezone ktz;
4110
4111        if (tv) {
4112                if (get_tv32(&ktv, tv))
4113                        return -EFAULT;
4114        }
4115        if (tz) {
4116                if (copy_from_user(&ktz, tz, sizeof(ktz)))
4117                        return -EFAULT;
4118        }
4119
4120        return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
4121}
4122
4123extern int do_getitimer(int which, struct itimerval *value);
4124
4125asmlinkage int sys32_getitimer(int which, struct itimerval32 *it)
4126{
4127        struct itimerval kit;
4128        int error;
4129
4130        error = do_getitimer(which, &kit);
4131        if (!error && put_it32(it, &kit))
4132                error = -EFAULT;
4133
4134        return error;
4135}
4136
4137extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
4138
4139asmlinkage int sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
4140{
4141        struct itimerval kin, kout;
4142        int error;
4143
4144        if (in) {
4145                if (get_it32(&kin, in))
4146                        return -EFAULT;
4147        } else
4148                memset(&kin, 0, sizeof(kin));
4149
4150        error = do_setitimer(which, &kin, out ? &kout : NULL);
4151        if (error || !out)
4152                return error;
4153        if (put_it32(out, &kout))
4154                return -EFAULT;
4155
4156        return 0;
4157
4158}
4159
4160asmlinkage int sys_utimes(char *, struct timeval *);
4161
4162asmlinkage int sys32_utimes(char *filename, struct timeval32 *tvs)
4163{
4164        char *kfilename;
4165        struct timeval ktvs[2];
4166        mm_segment_t old_fs;
4167        int ret;
4168
4169        kfilename = getname(filename);
4170        ret = PTR_ERR(kfilename);
4171        if (!IS_ERR(kfilename)) {
4172                if (tvs) {
4173                        if (get_tv32(&ktvs[0], tvs) ||
4174                            get_tv32(&ktvs[1], 1+tvs))
4175                                return -EFAULT;
4176                }
4177
4178                old_fs = get_fs();
4179                set_fs(KERNEL_DS);
4180                ret = sys_utimes(kfilename, &ktvs[0]);
4181                set_fs(old_fs);
4182
4183                putname(kfilename);
4184        }
4185        return ret;
4186}
4187
4188/* These are here just in case some old sparc32 binary calls it. */
4189asmlinkage int sys32_pause(void)
4190{
4191        current->state = TASK_INTERRUPTIBLE;
4192        schedule();
4193        return -ERESTARTNOHAND;
4194}
4195
4196/* PCI config space poking. */
4197extern asmlinkage int sys_pciconfig_read(unsigned long bus,
4198                                         unsigned long dfn,
4199                                         unsigned long off,
4200                                         unsigned long len,
4201                                         unsigned char *buf);
4202
4203extern asmlinkage int sys_pciconfig_write(unsigned long bus,
4204                                          unsigned long dfn,
4205                                          unsigned long off,
4206                                          unsigned long len,
4207                                          unsigned char *buf);
4208
4209asmlinkage int sys32_pciconfig_read(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
4210{
4211        return sys_pciconfig_read((unsigned long) bus,
4212                                  (unsigned long) dfn,
4213                                  (unsigned long) off,
4214                                  (unsigned long) len,
4215                                  (unsigned char *)AA(ubuf));
4216}
4217
4218asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf)
4219{
4220        return sys_pciconfig_write((unsigned long) bus,
4221                                   (unsigned long) dfn,
4222                                   (unsigned long) off,
4223                                   (unsigned long) len,
4224                                   (unsigned char *)AA(ubuf));
4225}
4226
4227extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
4228                                unsigned long arg4, unsigned long arg5);
4229
4230asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
4231{
4232        return sys_prctl(option,
4233                         (unsigned long) arg2,
4234                         (unsigned long) arg3,
4235                         (unsigned long) arg4,
4236                         (unsigned long) arg5);
4237}
4238
4239
4240extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
4241                                    size_t count, loff_t pos);
4242
4243extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
4244                                     size_t count, loff_t pos);
4245
4246typedef __kernel_ssize_t32 ssize_t32;
4247
4248asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf,
4249                                 __kernel_size_t32 count, u32 poshi, u32 poslo)
4250{
4251        return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
4252}
4253
4254asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
4255                                  __kernel_size_t32 count, u32 poshi, u32 poslo)
4256{
4257        return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
4258}
4259
4260extern asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);
4261
4262asmlinkage ssize_t32 sys32_readahead(int fd, u32 offhi, u32 offlo, s32 count)
4263{
4264        return sys_readahead(fd, ((loff_t)AA(offhi) << 32) | AA(offlo), count);
4265}
4266
4267extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
4268
4269asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
4270{
4271        mm_segment_t old_fs = get_fs();
4272        int ret;
4273        off_t of;
4274        
4275        if (offset && get_user(of, offset))
4276                return -EFAULT;
4277                
4278        set_fs(KERNEL_DS);
4279        ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
4280        set_fs(old_fs);
4281        
4282        if (offset && put_user(of, offset))
4283                return -EFAULT;
4284                
4285        return ret;
4286}
4287
4288/* Handle adjtimex compatability. */
4289
4290struct timex32 {
4291        u32 modes;
4292        s32 offset, freq, maxerror, esterror;
4293        s32 status, constant, precision, tolerance;
4294        struct timeval32 time;
4295        s32 tick;
4296        s32 ppsfreq, jitter, shift, stabil;
4297        s32 jitcnt, calcnt, errcnt, stbcnt;
4298        s32  :32; s32  :32; s32  :32; s32  :32;
4299        s32  :32; s32  :32; s32  :32; s32  :32;
4300        s32  :32; s32  :32; s32  :32; s32  :32;
4301};
4302
4303extern int do_adjtimex(struct timex *);
4304
4305asmlinkage int sys32_adjtimex(struct timex32 *utp)
4306{
4307        struct timex txc;
4308        int ret;
4309
4310        memset(&txc, 0, sizeof(struct timex));
4311
4312        if(get_user(txc.modes, &utp->modes) ||
4313           __get_user(txc.offset, &utp->offset) ||
4314           __get_user(txc.freq, &utp->freq) ||
4315           __get_user(txc.maxerror, &utp->maxerror) ||
4316           __get_user(txc.esterror, &utp->esterror) ||
4317           __get_user(txc.status, &utp->status) ||
4318           __get_user(txc.constant, &utp->constant) ||
4319           __get_user(txc.precision, &utp->precision) ||
4320           __get_user(txc.tolerance, &utp->tolerance) ||
4321           __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
4322           __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
4323           __get_user(txc.tick, &utp->tick) ||
4324           __get_user(txc.ppsfreq, &utp->ppsfreq) ||
4325           __get_user(txc.jitter, &utp->jitter) ||
4326           __get_user(txc.shift, &utp->shift) ||
4327           __get_user(txc.stabil, &utp->stabil) ||
4328           __get_user(txc.jitcnt, &utp->jitcnt) ||
4329           __get_user(txc.calcnt, &utp->calcnt) ||
4330           __get_user(txc.errcnt, &utp->errcnt) ||
4331           __get_user(txc.stbcnt, &utp->stbcnt))
4332                return -EFAULT;
4333
4334        ret = do_adjtimex(&txc);
4335
4336        if(put_user(txc.modes, &utp->modes) ||
4337           __put_user(txc.offset, &utp->offset) ||
4338           __put_user(txc.freq, &utp->freq) ||
4339           __put_user(txc.maxerror, &utp->maxerror) ||
4340           __put_user(txc.esterror, &utp->esterror) ||
4341           __put_user(txc.status, &utp->status) ||
4342           __put_user(txc.constant, &utp->constant) ||
4343           __put_user(txc.precision, &utp->precision) ||
4344           __put_user(txc.tolerance, &utp->tolerance) ||
4345           __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
4346           __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
4347           __put_user(txc.tick, &utp->tick) ||
4348           __put_user(txc.ppsfreq, &utp->ppsfreq) ||
4349           __put_user(txc.jitter, &utp->jitter) ||
4350           __put_user(txc.shift, &utp->shift) ||
4351           __put_user(txc.stabil, &utp->stabil) ||
4352           __put_user(txc.jitcnt, &utp->jitcnt) ||
4353           __put_user(txc.calcnt, &utp->calcnt) ||
4354           __put_user(txc.errcnt, &utp->errcnt) ||
4355           __put_user(txc.stbcnt, &utp->stbcnt))
4356                ret = -EFAULT;
4357
4358        return ret;
4359}
4360
4361/* This is just a version for 32-bit applications which does
4362 * not force O_LARGEFILE on.
4363 */
4364
4365asmlinkage long sparc32_open(const char * filename, int flags, int mode)
4366{
4367        char * tmp;
4368        int fd, error;
4369
4370        tmp = getname(filename);
4371        fd = PTR_ERR(tmp);
4372        if (!IS_ERR(tmp)) {
4373                fd = get_unused_fd();
4374                if (fd >= 0) {
4375                        struct file * f = filp_open(tmp, flags, mode);
4376                        error = PTR_ERR(f);
4377                        if (IS_ERR(f))
4378                                goto out_error;
4379                        fd_install(fd, f);
4380                }
4381out:
4382                putname(tmp);
4383        }
4384        return fd;
4385
4386out_error:
4387        put_unused_fd(fd);
4388        fd = error;
4389        goto out;
4390}
4391
4392extern unsigned long do_mremap(unsigned long addr,
4393        unsigned long old_len, unsigned long new_len,
4394        unsigned long flags, unsigned long new_addr);
4395                
4396asmlinkage unsigned long sys32_mremap(unsigned long addr,
4397        unsigned long old_len, unsigned long new_len,
4398        unsigned long flags, u32 __new_addr)
4399{
4400        struct vm_area_struct *vma;
4401        unsigned long ret = -EINVAL;
4402        unsigned long new_addr = AA(__new_addr);
4403
4404        if (old_len > 0xf0000000UL || new_len > 0xf0000000UL)
4405                goto out;
4406        if (addr > 0xf0000000UL - old_len)
4407                goto out;
4408        down_write(&current->mm->mmap_sem);
4409        if (flags & MREMAP_FIXED) {
4410                if (new_addr > 0xf0000000UL - new_len)
4411                        goto out_sem;
4412        } else if (addr > 0xf0000000UL - new_len) {
4413                unsigned long map_flags = 0;
4414                struct file *file = NULL;
4415
4416                ret = -ENOMEM;
4417                if (!(flags & MREMAP_MAYMOVE))
4418                        goto out_sem;
4419
4420                vma = find_vma(current->mm, addr);
4421                if (vma) {
4422                        if (vma->vm_flags & VM_SHARED)
4423                                map_flags |= MAP_SHARED;
4424                        file = vma->vm_file;
4425                }
4426
4427                /* MREMAP_FIXED checked above. */
4428                new_addr = get_unmapped_area(file, addr, new_len,
4429                                    vma ? vma->vm_pgoff : 0,
4430                                    map_flags);
4431                ret = new_addr;
4432                if (new_addr & ~PAGE_MASK)
4433                        goto out_sem;
4434                flags |= MREMAP_FIXED;
4435        }
4436        ret = do_mremap(addr, old_len, new_len, flags, new_addr);
4437out_sem:
4438        up_write(&current->mm->mmap_sem);
4439out:
4440        return ret;       
4441}
4442
4443extern asmlinkage long sys_setpriority(int which, int who, int niceval);
4444
4445asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval)
4446{
4447        return sys_setpriority((int) which,
4448                               (int) who,
4449                               (int) niceval);
4450}
4451
4452struct __sysctl_args32 {
4453        u32 name;
4454        int nlen;
4455        u32 oldval;
4456        u32 oldlenp;
4457        u32 newval;
4458        u32 newlen;
4459        u32 __unused[4];
4460};
4461
4462extern asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
4463{
4464#ifndef CONFIG_SYSCTL
4465        return -ENOSYS;
4466#else
4467        struct __sysctl_args32 tmp;
4468        int error;
4469        size_t oldlen, *oldlenp = NULL;
4470        unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
4471
4472        if (copy_from_user(&tmp, args, sizeof(tmp)))
4473                return -EFAULT;
4474
4475        if (tmp.oldval && tmp.oldlenp) {
4476                /* Duh, this is ugly and might not work if sysctl_args
4477                   is in read-only memory, but do_sysctl does indirectly
4478                   a lot of uaccess in both directions and we'd have to
4479                   basically copy the whole sysctl.c here, and
4480                   glibc's __sysctl uses rw memory for the structure
4481                   anyway.  */
4482                if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
4483                    put_user(oldlen, (size_t *)addr))
4484                        return -EFAULT;
4485                oldlenp = (size_t *)addr;
4486        }
4487
4488        lock_kernel();
4489        error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
4490                          oldlenp, (void *)A(tmp.newval), tmp.newlen);
4491        unlock_kernel();
4492        if (oldlenp) {
4493                if (!error) {
4494                        if (get_user(oldlen, (size_t *)addr) ||
4495                            put_user(oldlen, (u32 *)A(tmp.oldlenp)))
4496                                error = -EFAULT;
4497                }
4498                copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
4499        }
4500        return error;
4501#endif
4502}
4503
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.