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