linux/fs/compat.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/compat.c
   3 *
   4 *  Kernel compatibililty routines for e.g. 32 bit syscall support
   5 *  on 64 bit kernels.
   6 *
   7 *  Copyright (C) 2002       Stephen Rothwell, IBM Corporation
   8 *  Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
   9 *  Copyright (C) 1998       Eddie C. Dost  (ecd@skynet.be)
  10 *  Copyright (C) 2001,2002  Andi Kleen, SuSE Labs 
  11 *  Copyright (C) 2003       Pavel Machek (pavel@suse.cz)
  12 *
  13 *  This program is free software; you can redistribute it and/or modify
  14 *  it under the terms of the GNU General Public License version 2 as
  15 *  published by the Free Software Foundation.
  16 */
  17
  18#include <linux/kernel.h>
  19#include <linux/linkage.h>
  20#include <linux/compat.h>
  21#include <linux/errno.h>
  22#include <linux/time.h>
  23#include <linux/fs.h>
  24#include <linux/fcntl.h>
  25#include <linux/namei.h>
  26#include <linux/file.h>
  27#include <linux/fdtable.h>
  28#include <linux/vfs.h>
  29#include <linux/ioctl.h>
  30#include <linux/init.h>
  31#include <linux/smb.h>
  32#include <linux/smb_mount.h>
  33#include <linux/ncp_mount.h>
  34#include <linux/nfs4_mount.h>
  35#include <linux/smp_lock.h>
  36#include <linux/syscalls.h>
  37#include <linux/ctype.h>
  38#include <linux/module.h>
  39#include <linux/dirent.h>
  40#include <linux/fsnotify.h>
  41#include <linux/highuid.h>
  42#include <linux/sunrpc/svc.h>
  43#include <linux/nfsd/nfsd.h>
  44#include <linux/nfsd/syscall.h>
  45#include <linux/personality.h>
  46#include <linux/rwsem.h>
  47#include <linux/tsacct_kern.h>
  48#include <linux/security.h>
  49#include <linux/highmem.h>
  50#include <linux/signal.h>
  51#include <linux/poll.h>
  52#include <linux/mm.h>
  53#include <linux/eventpoll.h>
  54
  55#include <asm/uaccess.h>
  56#include <asm/mmu_context.h>
  57#include <asm/ioctls.h>
  58#include "internal.h"
  59
  60int compat_log = 1;
  61
  62int compat_printk(const char *fmt, ...)
  63{
  64        va_list ap;
  65        int ret;
  66        if (!compat_log)
  67                return 0;
  68        va_start(ap, fmt);
  69        ret = vprintk(fmt, ap);
  70        va_end(ap);
  71        return ret;
  72}
  73
  74#include "read_write.h"
  75
  76/*
  77 * Not all architectures have sys_utime, so implement this in terms
  78 * of sys_utimes.
  79 */
  80asmlinkage long compat_sys_utime(char __user *filename, struct compat_utimbuf __user *t)
  81{
  82        struct timespec tv[2];
  83
  84        if (t) {
  85                if (get_user(tv[0].tv_sec, &t->actime) ||
  86                    get_user(tv[1].tv_sec, &t->modtime))
  87                        return -EFAULT;
  88                tv[0].tv_nsec = 0;
  89                tv[1].tv_nsec = 0;
  90        }
  91        return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0);
  92}
  93
  94asmlinkage long compat_sys_utimensat(unsigned int dfd, char __user *filename, struct compat_timespec __user *t, int flags)
  95{
  96        struct timespec tv[2];
  97
  98        if  (t) {
  99                if (get_compat_timespec(&tv[0], &t[0]) ||
 100                    get_compat_timespec(&tv[1], &t[1]))
 101                        return -EFAULT;
 102
 103                if ((tv[0].tv_nsec == UTIME_OMIT || tv[0].tv_nsec == UTIME_NOW)
 104                    && tv[0].tv_sec != 0)
 105                        return -EINVAL;
 106                if ((tv[1].tv_nsec == UTIME_OMIT || tv[1].tv_nsec == UTIME_NOW)
 107                    && tv[1].tv_sec != 0)
 108                        return -EINVAL;
 109
 110                if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)
 111                        return 0;
 112        }
 113        return do_utimes(dfd, filename, t ? tv : NULL, flags);
 114}
 115
 116asmlinkage long compat_sys_futimesat(unsigned int dfd, char __user *filename, struct compat_timeval __user *t)
 117{
 118        struct timespec tv[2];
 119
 120        if (t) {
 121                if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
 122                    get_user(tv[0].tv_nsec, &t[0].tv_usec) ||
 123                    get_user(tv[1].tv_sec, &t[1].tv_sec) ||
 124                    get_user(tv[1].tv_nsec, &t[1].tv_usec))
 125                        return -EFAULT;
 126                if (tv[0].tv_nsec >= 1000000 || tv[0].tv_nsec < 0 ||
 127                    tv[1].tv_nsec >= 1000000 || tv[1].tv_nsec < 0)
 128                        return -EINVAL;
 129                tv[0].tv_nsec *= 1000;
 130                tv[1].tv_nsec *= 1000;
 131        }
 132        return do_utimes(dfd, filename, t ? tv : NULL, 0);
 133}
 134
 135asmlinkage long compat_sys_utimes(char __user *filename, struct compat_timeval __user *t)
 136{
 137        return compat_sys_futimesat(AT_FDCWD, filename, t);
 138}
 139
 140static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
 141{
 142        compat_ino_t ino = stat->ino;
 143        typeof(ubuf->st_uid) uid = 0;
 144        typeof(ubuf->st_gid) gid = 0;
 145        int err;
 146
 147        SET_UID(uid, stat->uid);
 148        SET_GID(gid, stat->gid);
 149
 150        if ((u64) stat->size > MAX_NON_LFS ||
 151            !old_valid_dev(stat->dev) ||
 152            !old_valid_dev(stat->rdev))
 153                return -EOVERFLOW;
 154        if (sizeof(ino) < sizeof(stat->ino) && ino != stat->ino)
 155                return -EOVERFLOW;
 156
 157        if (clear_user(ubuf, sizeof(*ubuf)))
 158                return -EFAULT;
 159
 160        err  = __put_user(old_encode_dev(stat->dev), &ubuf->st_dev);
 161        err |= __put_user(ino, &ubuf->st_ino);
 162        err |= __put_user(stat->mode, &ubuf->st_mode);
 163        err |= __put_user(stat->nlink, &ubuf->st_nlink);
 164        err |= __put_user(uid, &ubuf->st_uid);
 165        err |= __put_user(gid, &ubuf->st_gid);
 166        err |= __put_user(old_encode_dev(stat->rdev), &ubuf->st_rdev);
 167        err |= __put_user(stat->size, &ubuf->st_size);
 168        err |= __put_user(stat->atime.tv_sec, &ubuf->st_atime);
 169        err |= __put_user(stat->atime.tv_nsec, &ubuf->st_atime_nsec);
 170        err |= __put_user(stat->mtime.tv_sec, &ubuf->st_mtime);
 171        err |= __put_user(stat->mtime.tv_nsec, &ubuf->st_mtime_nsec);
 172        err |= __put_user(stat->ctime.tv_sec, &ubuf->st_ctime);
 173        err |= __put_user(stat->ctime.tv_nsec, &ubuf->st_ctime_nsec);
 174        err |= __put_user(stat->blksize, &ubuf->st_blksize);
 175        err |= __put_user(stat->blocks, &ubuf->st_blocks);
 176        return err;
 177}
 178
 179asmlinkage long compat_sys_newstat(char __user * filename,
 180                struct compat_stat __user *statbuf)
 181{
 182        struct kstat stat;
 183        int error = vfs_stat_fd(AT_FDCWD, filename, &stat);
 184
 185        if (!error)
 186                error = cp_compat_stat(&stat, statbuf);
 187        return error;
 188}
 189
 190asmlinkage long compat_sys_newlstat(char __user * filename,
 191                struct compat_stat __user *statbuf)
 192{
 193        struct kstat stat;
 194        int error = vfs_lstat_fd(AT_FDCWD, filename, &stat);
 195
 196        if (!error)
 197                error = cp_compat_stat(&stat, statbuf);
 198        return error;
 199}
 200
 201#ifndef __ARCH_WANT_STAT64
 202asmlinkage long compat_sys_newfstatat(unsigned int dfd, char __user *filename,
 203                struct compat_stat __user *statbuf, int flag)
 204{
 205        struct kstat stat;
 206        int error = -EINVAL;
 207
 208        if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)
 209                goto out;
 210
 211        if (flag & AT_SYMLINK_NOFOLLOW)
 212                error = vfs_lstat_fd(dfd, filename, &stat);
 213        else
 214                error = vfs_stat_fd(dfd, filename, &stat);
 215
 216        if (!error)
 217                error = cp_compat_stat(&stat, statbuf);
 218
 219out:
 220        return error;
 221}
 222#endif
 223
 224asmlinkage long compat_sys_newfstat(unsigned int fd,
 225                struct compat_stat __user * statbuf)
 226{
 227        struct kstat stat;
 228        int error = vfs_fstat(fd, &stat);
 229
 230        if (!error)
 231                error = cp_compat_stat(&stat, statbuf);
 232        return error;
 233}
 234
 235static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf)
 236{
 237        
 238        if (sizeof ubuf->f_blocks == 4) {
 239                if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
 240                     kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
 241                        return -EOVERFLOW;
 242                /* f_files and f_ffree may be -1; it's okay
 243                 * to stuff that into 32 bits */
 244                if (kbuf->f_files != 0xffffffffffffffffULL
 245                 && (kbuf->f_files & 0xffffffff00000000ULL))
 246                        return -EOVERFLOW;
 247                if (kbuf->f_ffree != 0xffffffffffffffffULL
 248                 && (kbuf->f_ffree & 0xffffffff00000000ULL))
 249                        return -EOVERFLOW;
 250        }
 251        if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
 252            __put_user(kbuf->f_type, &ubuf->f_type) ||
 253            __put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
 254            __put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
 255            __put_user(kbuf->f_bfree, &ubuf->f_bfree) ||
 256            __put_user(kbuf->f_bavail, &ubuf->f_bavail) ||
 257            __put_user(kbuf->f_files, &ubuf->f_files) ||
 258            __put_user(kbuf->f_ffree, &ubuf->f_ffree) ||
 259            __put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
 260            __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
 261            __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
 262            __put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
 263            __put_user(0, &ubuf->f_spare[0]) || 
 264            __put_user(0, &ubuf->f_spare[1]) || 
 265            __put_user(0, &ubuf->f_spare[2]) || 
 266            __put_user(0, &ubuf->f_spare[3]) || 
 267            __put_user(0, &ubuf->f_spare[4]))
 268                return -EFAULT;
 269        return 0;
 270}
 271
 272/*
 273 * The following statfs calls are copies of code from fs/open.c and
 274 * should be checked against those from time to time
 275 */
 276asmlinkage long compat_sys_statfs(const char __user *pathname, struct compat_statfs __user *buf)
 277{
 278        struct path path;
 279        int error;
 280
 281        error = user_path(pathname, &path);
 282        if (!error) {
 283                struct kstatfs tmp;
 284                error = vfs_statfs(path.dentry, &tmp);
 285                if (!error)
 286                        error = put_compat_statfs(buf, &tmp);
 287                path_put(&path);
 288        }
 289        return error;
 290}
 291
 292asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user *buf)
 293{
 294        struct file * file;
 295        struct kstatfs tmp;
 296        int error;
 297
 298        error = -EBADF;
 299        file = fget(fd);
 300        if (!file)
 301                goto out;
 302        error = vfs_statfs(file->f_path.dentry, &tmp);
 303        if (!error)
 304                error = put_compat_statfs(buf, &tmp);
 305        fput(file);
 306out:
 307        return error;
 308}
 309
 310static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
 311{
 312        if (sizeof ubuf->f_blocks == 4) {
 313                if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
 314                     kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
 315                        return -EOVERFLOW;
 316                /* f_files and f_ffree may be -1; it's okay
 317                 * to stuff that into 32 bits */
 318                if (kbuf->f_files != 0xffffffffffffffffULL
 319                 && (kbuf->f_files & 0xffffffff00000000ULL))
 320                        return -EOVERFLOW;
 321                if (kbuf->f_ffree != 0xffffffffffffffffULL
 322                 && (kbuf->f_ffree & 0xffffffff00000000ULL))
 323                        return -EOVERFLOW;
 324        }
 325        if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
 326            __put_user(kbuf->f_type, &ubuf->f_type) ||
 327            __put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
 328            __put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
 329            __put_user(kbuf->f_bfree, &ubuf->f_bfree) ||
 330            __put_user(kbuf->f_bavail, &ubuf->f_bavail) ||
 331            __put_user(kbuf->f_files, &ubuf->f_files) ||
 332            __put_user(kbuf->f_ffree, &ubuf->f_ffree) ||
 333            __put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
 334            __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
 335            __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
 336            __put_user(kbuf->f_frsize, &ubuf->f_frsize))
 337                return -EFAULT;
 338        return 0;
 339}
 340
 341asmlinkage long compat_sys_statfs64(const char __user *pathname, compat_size_t sz, struct compat_statfs64 __user *buf)
 342{
 343        struct path path;
 344        int error;
 345
 346        if (sz != sizeof(*buf))
 347                return -EINVAL;
 348
 349        error = user_path(pathname, &path);
 350        if (!error) {
 351                struct kstatfs tmp;
 352                error = vfs_statfs(path.dentry, &tmp);
 353                if (!error)
 354                        error = put_compat_statfs64(buf, &tmp);
 355                path_put(&path);
 356        }
 357        return error;
 358}
 359
 360asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf)
 361{
 362        struct file * file;
 363        struct kstatfs tmp;
 364        int error;
 365
 366        if (sz != sizeof(*buf))
 367                return -EINVAL;
 368
 369        error = -EBADF;
 370        file = fget(fd);
 371        if (!file)
 372                goto out;
 373        error = vfs_statfs(file->f_path.dentry, &tmp);
 374        if (!error)
 375                error = put_compat_statfs64(buf, &tmp);
 376        fput(file);
 377out:
 378        return error;
 379}
 380
 381static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
 382{
 383        if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
 384            __get_user(kfl->l_type, &ufl->l_type) ||
 385            __get_user(kfl->l_whence, &ufl->l_whence) ||
 386            __get_user(kfl->l_start, &ufl->l_start) ||
 387            __get_user(kfl->l_len, &ufl->l_len) ||
 388            __get_user(kfl->l_pid, &ufl->l_pid))
 389                return -EFAULT;
 390        return 0;
 391}
 392
 393static int put_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
 394{
 395        if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
 396            __put_user(kfl->l_type, &ufl->l_type) ||
 397            __put_user(kfl->l_whence, &ufl->l_whence) ||
 398            __put_user(kfl->l_start, &ufl->l_start) ||
 399            __put_user(kfl->l_len, &ufl->l_len) ||
 400            __put_user(kfl->l_pid, &ufl->l_pid))
 401                return -EFAULT;
 402        return 0;
 403}
 404
 405#ifndef HAVE_ARCH_GET_COMPAT_FLOCK64
 406static int get_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl)
 407{
 408        if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
 409            __get_user(kfl->l_type, &ufl->l_type) ||
 410            __get_user(kfl->l_whence, &ufl->l_whence) ||
 411            __get_user(kfl->l_start, &ufl->l_start) ||
 412            __get_user(kfl->l_len, &ufl->l_len) ||
 413            __get_user(kfl->l_pid, &ufl->l_pid))
 414                return -EFAULT;
 415        return 0;
 416}
 417#endif
 418
 419#ifndef HAVE_ARCH_PUT_COMPAT_FLOCK64
 420static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl)
 421{
 422        if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
 423            __put_user(kfl->l_type, &ufl->l_type) ||
 424            __put_user(kfl->l_whence, &ufl->l_whence) ||
 425            __put_user(kfl->l_start, &ufl->l_start) ||
 426            __put_user(kfl->l_len, &ufl->l_len) ||
 427            __put_user(kfl->l_pid, &ufl->l_pid))
 428                return -EFAULT;
 429        return 0;
 430}
 431#endif
 432
 433asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
 434                unsigned long arg)
 435{
 436        mm_segment_t old_fs;
 437        struct flock f;
 438        long ret;
 439
 440        switch (cmd) {
 441        case F_GETLK:
 442        case F_SETLK:
 443        case F_SETLKW:
 444                ret = get_compat_flock(&f, compat_ptr(arg));
 445                if (ret != 0)
 446                        break;
 447                old_fs = get_fs();
 448                set_fs(KERNEL_DS);
 449                ret = sys_fcntl(fd, cmd, (unsigned long)&f);
 450                set_fs(old_fs);
 451                if (cmd == F_GETLK && ret == 0) {
 452                        /* GETLK was successfule and we need to return the data...
 453                         * but it needs to fit in the compat structure.
 454                         * l_start shouldn't be too big, unless the original
 455                         * start + end is greater than COMPAT_OFF_T_MAX, in which
 456                         * case the app was asking for trouble, so we return
 457                         * -EOVERFLOW in that case.
 458                         * l_len could be too big, in which case we just truncate it,
 459                         * and only allow the app to see that part of the conflicting
 460                         * lock that might make sense to it anyway
 461                         */
 462
 463                        if (f.l_start > COMPAT_OFF_T_MAX)
 464                                ret = -EOVERFLOW;
 465                        if (f.l_len > COMPAT_OFF_T_MAX)
 466                                f.l_len = COMPAT_OFF_T_MAX;
 467                        if (ret == 0)
 468                                ret = put_compat_flock(&f, compat_ptr(arg));
 469                }
 470                break;
 471
 472        case F_GETLK64:
 473        case F_SETLK64:
 474        case F_SETLKW64:
 475                ret = get_compat_flock64(&f, compat_ptr(arg));
 476                if (ret != 0)
 477                        break;
 478                old_fs = get_fs();
 479                set_fs(KERNEL_DS);
 480                ret = sys_fcntl(fd, (cmd == F_GETLK64) ? F_GETLK :
 481                                ((cmd == F_SETLK64) ? F_SETLK : F_SETLKW),
 482                                (unsigned long)&f);
 483                set_fs(old_fs);
 484                if (cmd == F_GETLK64 && ret == 0) {
 485                        /* need to return lock information - see above for commentary */
 486                        if (f.l_start > COMPAT_LOFF_T_MAX)
 487                                ret = -EOVERFLOW;
 488                        if (f.l_len > COMPAT_LOFF_T_MAX)
 489                                f.l_len = COMPAT_LOFF_T_MAX;
 490                        if (ret == 0)
 491                                ret = put_compat_flock64(&f, compat_ptr(arg));
 492                }
 493                break;
 494
 495        default:
 496                ret = sys_fcntl(fd, cmd, arg);
 497                break;
 498        }
 499        return ret;
 500}
 501
 502asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd,
 503                unsigned long arg)
 504{
 505        if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64))
 506                return -EINVAL;
 507        return compat_sys_fcntl64(fd, cmd, arg);
 508}
 509
 510asmlinkage long
 511compat_sys_io_setup(unsigned nr_reqs, u32 __user *ctx32p)
 512{
 513        long ret;
 514        aio_context_t ctx64;
 515
 516        mm_segment_t oldfs = get_fs();
 517        if (unlikely(get_user(ctx64, ctx32p)))
 518                return -EFAULT;
 519
 520        set_fs(KERNEL_DS);
 521        /* The __user pointer cast is valid because of the set_fs() */
 522        ret = sys_io_setup(nr_reqs, (aio_context_t __user *) &ctx64);
 523        set_fs(oldfs);
 524        /* truncating is ok because it's a user address */
 525        if (!ret)
 526                ret = put_user((u32) ctx64, ctx32p);
 527        return ret;
 528}
 529
 530asmlinkage long
 531compat_sys_io_getevents(aio_context_t ctx_id,
 532                                 unsigned long min_nr,
 533                                 unsigned long nr,
 534                                 struct io_event __user *events,
 535                                 struct compat_timespec __user *timeout)
 536{
 537        long ret;
 538        struct timespec t;
 539        struct timespec __user *ut = NULL;
 540
 541        ret = -EFAULT;
 542        if (unlikely(!access_ok(VERIFY_WRITE, events, 
 543                                nr * sizeof(struct io_event))))
 544                goto out;
 545        if (timeout) {
 546                if (get_compat_timespec(&t, timeout))
 547                        goto out;
 548
 549                ut = compat_alloc_user_space(sizeof(*ut));
 550                if (copy_to_user(ut, &t, sizeof(t)) )
 551                        goto out;
 552        } 
 553        ret = sys_io_getevents(ctx_id, min_nr, nr, events, ut);
 554out:
 555        return ret;
 556}
 557
 558static inline long
 559copy_iocb(long nr, u32 __user *ptr32, struct iocb __user * __user *ptr64)
 560{
 561        compat_uptr_t uptr;
 562        int i;
 563
 564        for (i = 0; i < nr; ++i) {
 565                if (get_user(uptr, ptr32 + i))
 566                        return -EFAULT;
 567                if (put_user(compat_ptr(uptr), ptr64 + i))
 568                        return -EFAULT;
 569        }
 570        return 0;
 571}
 572
 573#define MAX_AIO_SUBMITS         (PAGE_SIZE/sizeof(struct iocb *))
 574
 575asmlinkage long
 576compat_sys_io_submit(aio_context_t ctx_id, int nr, u32 __user *iocb)
 577{
 578        struct iocb __user * __user *iocb64; 
 579        long ret;
 580
 581        if (unlikely(nr < 0))
 582                return -EINVAL;
 583
 584        if (nr > MAX_AIO_SUBMITS)
 585                nr = MAX_AIO_SUBMITS;
 586        
 587        iocb64 = compat_alloc_user_space(nr * sizeof(*iocb64));
 588        ret = copy_iocb(nr, iocb, iocb64);
 589        if (!ret)
 590                ret = sys_io_submit(ctx_id, nr, iocb64);
 591        return ret;
 592}
 593
 594struct compat_ncp_mount_data {
 595        compat_int_t version;
 596        compat_uint_t ncp_fd;
 597        __compat_uid_t mounted_uid;
 598        compat_pid_t wdog_pid;
 599        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
 600        compat_uint_t time_out;
 601        compat_uint_t retry_count;
 602        compat_uint_t flags;
 603        __compat_uid_t uid;
 604        __compat_gid_t gid;
 605        compat_mode_t file_mode;
 606        compat_mode_t dir_mode;
 607};
 608
 609struct compat_ncp_mount_data_v4 {
 610        compat_int_t version;
 611        compat_ulong_t flags;
 612        compat_ulong_t mounted_uid;
 613        compat_long_t wdog_pid;
 614        compat_uint_t ncp_fd;
 615        compat_uint_t time_out;
 616        compat_uint_t retry_count;
 617        compat_ulong_t uid;
 618        compat_ulong_t gid;
 619        compat_ulong_t file_mode;
 620        compat_ulong_t dir_mode;
 621};
 622
 623static void *do_ncp_super_data_conv(void *raw_data)
 624{
 625        int version = *(unsigned int *)raw_data;
 626
 627        if (version == 3) {
 628                struct compat_ncp_mount_data *c_n = raw_data;
 629                struct ncp_mount_data *n = raw_data;
 630
 631                n->dir_mode = c_n->dir_mode;
 632                n->file_mode = c_n->file_mode;
 633                n->gid = c_n->gid;
 634                n->uid = c_n->uid;
 635                memmove (n->mounted_vol, c_n->mounted_vol, (sizeof (c_n->mounted_vol) + 3 * sizeof (unsigned int)));
 636                n->wdog_pid = c_n->wdog_pid;
 637                n->mounted_uid = c_n->mounted_uid;
 638        } else if (version == 4) {
 639                struct compat_ncp_mount_data_v4 *c_n = raw_data;
 640                struct ncp_mount_data_v4 *n = raw_data;
 641
 642                n->dir_mode = c_n->dir_mode;
 643                n->file_mode = c_n->file_mode;
 644                n->gid = c_n->gid;
 645                n->uid = c_n->uid;
 646                n->retry_count = c_n->retry_count;
 647                n->time_out = c_n->time_out;
 648                n->ncp_fd = c_n->ncp_fd;
 649                n->wdog_pid = c_n->wdog_pid;
 650                n->mounted_uid = c_n->mounted_uid;
 651                n->flags = c_n->flags;
 652        } else if (version != 5) {
 653                return NULL;
 654        }
 655
 656        return raw_data;
 657}
 658
 659struct compat_smb_mount_data {
 660        compat_int_t version;
 661        __compat_uid_t mounted_uid;
 662        __compat_uid_t uid;
 663        __compat_gid_t gid;
 664        compat_mode_t file_mode;
 665        compat_mode_t dir_mode;
 666};
 667
 668static void *do_smb_super_data_conv(void *raw_data)
 669{
 670        struct smb_mount_data *s = raw_data;
 671        struct compat_smb_mount_data *c_s = raw_data;
 672
 673        if (c_s->version != SMB_MOUNT_OLDVERSION)
 674                goto out;
 675        s->dir_mode = c_s->dir_mode;
 676        s->file_mode = c_s->file_mode;
 677        s->gid = c_s->gid;
 678        s->uid = c_s->uid;
 679        s->mounted_uid = c_s->mounted_uid;
 680 out:
 681        return raw_data;
 682}
 683
 684struct compat_nfs_string {
 685        compat_uint_t len;
 686        compat_uptr_t data;
 687};
 688
 689static inline void compat_nfs_string(struct nfs_string *dst,
 690                                     struct compat_nfs_string *src)
 691{
 692        dst->data = compat_ptr(src->data);
 693        dst->len = src->len;
 694}
 695
 696struct compat_nfs4_mount_data_v1 {
 697        compat_int_t version;
 698        compat_int_t flags;
 699        compat_int_t rsize;
 700        compat_int_t wsize;
 701        compat_int_t timeo;
 702        compat_int_t retrans;
 703        compat_int_t acregmin;
 704        compat_int_t acregmax;
 705        compat_int_t acdirmin;
 706        compat_int_t acdirmax;
 707        struct compat_nfs_string client_addr;
 708        struct compat_nfs_string mnt_path;
 709        struct compat_nfs_string hostname;
 710        compat_uint_t host_addrlen;
 711        compat_uptr_t host_addr;
 712        compat_int_t proto;
 713        compat_int_t auth_flavourlen;
 714        compat_uptr_t auth_flavours;
 715};
 716
 717static int do_nfs4_super_data_conv(void *raw_data)
 718{
 719        int version = *(compat_uint_t *) raw_data;
 720
 721        if (version == 1) {
 722                struct compat_nfs4_mount_data_v1 *raw = raw_data;
 723                struct nfs4_mount_data *real = raw_data;
 724
 725                /* copy the fields backwards */
 726                real->auth_flavours = compat_ptr(raw->auth_flavours);
 727                real->auth_flavourlen = raw->auth_flavourlen;
 728                real->proto = raw->proto;
 729                real->host_addr = compat_ptr(raw->host_addr);
 730                real->host_addrlen = raw->host_addrlen;
 731                compat_nfs_string(&real->hostname, &raw->hostname);
 732                compat_nfs_string(&real->mnt_path, &raw->mnt_path);
 733                compat_nfs_string(&real->client_addr, &raw->client_addr);
 734                real->acdirmax = raw->acdirmax;
 735                real->acdirmin = raw->acdirmin;
 736                real->acregmax = raw->acregmax;
 737                real->acregmin = raw->acregmin;
 738                real->retrans = raw->retrans;
 739                real->timeo = raw->timeo;
 740                real->wsize = raw->wsize;
 741                real->rsize = raw->rsize;
 742                real->flags = raw->flags;
 743                real->version = raw->version;
 744        }
 745
 746        return 0;
 747}
 748
 749#define SMBFS_NAME      "smbfs"
 750#define NCPFS_NAME      "ncpfs"
 751#define NFS4_NAME       "nfs4"
 752
 753asmlinkage long compat_sys_mount(char __user * dev_name, char __user * dir_name,
 754                                 char __user * type, unsigned long flags,
 755                                 void __user * data)
 756{
 757        unsigned long type_page;
 758        unsigned long data_page;
 759        unsigned long dev_page;
 760        char *dir_page;
 761        int retval;
 762
 763        retval = copy_mount_options (type, &type_page);
 764        if (retval < 0)
 765                goto out;
 766
 767        dir_page = getname(dir_name);
 768        retval = PTR_ERR(dir_page);
 769        if (IS_ERR(dir_page))
 770                goto out1;
 771
 772        retval = copy_mount_options (dev_name, &dev_page);
 773        if (retval < 0)
 774                goto out2;
 775
 776        retval = copy_mount_options (data, &data_page);
 777        if (retval < 0)
 778                goto out3;
 779
 780        retval = -EINVAL;
 781
 782        if (type_page && data_page) {
 783                if (!strcmp((char *)type_page, SMBFS_NAME)) {
 784                        do_smb_super_data_conv((void *)data_page);
 785                } else if (!strcmp((char *)type_page, NCPFS_NAME)) {
 786                        do_ncp_super_data_conv((void *)data_page);
 787                } else if (!strcmp((char *)type_page, NFS4_NAME)) {
 788                        if (do_nfs4_super_data_conv((void *) data_page))
 789                                goto out4;
 790                }
 791        }
 792
 793        lock_kernel();
 794        retval = do_mount((char*)dev_page, dir_page, (char*)type_page,
 795                        flags, (void*)data_page);
 796        unlock_kernel();
 797
 798 out4:
 799        free_page(data_page);
 800 out3:
 801        free_page(dev_page);
 802 out2:
 803        putname(dir_page);
 804 out1:
 805        free_page(type_page);
 806 out:
 807        return retval;
 808}
 809
 810#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
 811
 812struct compat_old_linux_dirent {
 813        compat_ulong_t  d_ino;
 814        compat_ulong_t  d_offset;
 815        unsigned short  d_namlen;
 816        char            d_name[1];
 817};
 818
 819struct compat_readdir_callback {
 820        struct compat_old_linux_dirent __user *dirent;
 821        int result;
 822};
 823
 824static int compat_fillonedir(void *__buf, const char *name, int namlen,
 825                        loff_t offset, u64 ino, unsigned int d_type)
 826{
 827        struct compat_readdir_callback *buf = __buf;
 828        struct compat_old_linux_dirent __user *dirent;
 829        compat_ulong_t d_ino;
 830
 831        if (buf->result)
 832                return -EINVAL;
 833        d_ino = ino;
 834        if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
 835                buf->result = -EOVERFLOW;
 836                return -EOVERFLOW;
 837        }
 838        buf->result++;
 839        dirent = buf->dirent;
 840        if (!access_ok(VERIFY_WRITE, dirent,
 841                        (unsigned long)(dirent->d_name + namlen + 1) -
 842                                (unsigned long)dirent))
 843                goto efault;
 844        if (    __put_user(d_ino, &dirent->d_ino) ||
 845                __put_user(offset, &dirent->d_offset) ||
 846                __put_user(namlen, &dirent->d_namlen) ||
 847                __copy_to_user(dirent->d_name, name, namlen) ||
 848                __put_user(0, dirent->d_name + namlen))
 849                goto efault;
 850        return 0;
 851efault:
 852        buf->result = -EFAULT;
 853        return -EFAULT;
 854}
 855
 856asmlinkage long compat_sys_old_readdir(unsigned int fd,
 857        struct compat_old_linux_dirent __user *dirent, unsigned int count)
 858{
 859        int error;
 860        struct file *file;
 861        struct compat_readdir_callback buf;
 862
 863        error = -EBADF;
 864        file = fget(fd);
 865        if (!file)
 866                goto out;
 867
 868        buf.result = 0;
 869        buf.dirent = dirent;
 870
 871        error = vfs_readdir(file, compat_fillonedir, &buf);
 872        if (buf.result)
 873                error = buf.result;
 874
 875        fput(file);
 876out:
 877        return error;
 878}
 879
 880struct compat_linux_dirent {
 881        compat_ulong_t  d_ino;
 882        compat_ulong_t  d_off;
 883        unsigned short  d_reclen;
 884        char            d_name[1];
 885};
 886
 887struct compat_getdents_callback {
 888        struct compat_linux_dirent __user *current_dir;
 889        struct compat_linux_dirent __user *previous;
 890        int count;
 891        int error;
 892};
 893
 894static int compat_filldir(void *__buf, const char *name, int namlen,
 895                loff_t offset, u64 ino, unsigned int d_type)
 896{
 897        struct compat_linux_dirent __user * dirent;
 898        struct compat_getdents_callback *buf = __buf;
 899        compat_ulong_t d_ino;
 900        int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 2, sizeof(compat_long_t));
 901
 902        buf->error = -EINVAL;   /* only used if we fail.. */
 903        if (reclen > buf->count)
 904                return -EINVAL;
 905        d_ino = ino;
 906        if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
 907                buf->error = -EOVERFLOW;
 908                return -EOVERFLOW;
 909        }
 910        dirent = buf->previous;
 911        if (dirent) {
 912                if (__put_user(offset, &dirent->d_off))
 913                        goto efault;
 914        }
 915        dirent = buf->current_dir;
 916        if (__put_user(d_ino, &dirent->d_ino))
 917                goto efault;
 918        if (__put_user(reclen, &dirent->d_reclen))
 919                goto efault;
 920        if (copy_to_user(dirent->d_name, name, namlen))
 921                goto efault;
 922        if (__put_user(0, dirent->d_name + namlen))
 923                goto efault;
 924        if (__put_user(d_type, (char  __user *) dirent + reclen - 1))
 925                goto efault;
 926        buf->previous = dirent;
 927        dirent = (void __user *)dirent + reclen;
 928        buf->current_dir = dirent;
 929        buf->count -= reclen;
 930        return 0;
 931efault:
 932        buf->error = -EFAULT;
 933        return -EFAULT;
 934}
 935
 936asmlinkage long compat_sys_getdents(unsigned int fd,
 937                struct compat_linux_dirent __user *dirent, unsigned int count)
 938{
 939        struct file * file;
 940        struct compat_linux_dirent __user * lastdirent;
 941        struct compat_getdents_callback buf;
 942        int error;
 943
 944        error = -EFAULT;
 945        if (!access_ok(VERIFY_WRITE, dirent, count))
 946                goto out;
 947
 948        error = -EBADF;
 949        file = fget(fd);
 950        if (!file)
 951                goto out;
 952
 953        buf.current_dir = dirent;
 954        buf.previous = NULL;
 955        buf.count = count;
 956        buf.error = 0;
 957
 958        error = vfs_readdir(file, compat_filldir, &buf);
 959        if (error >= 0)
 960                error = buf.error;
 961        lastdirent = buf.previous;
 962        if (lastdirent) {
 963                if (put_user(file->f_pos, &lastdirent->d_off))
 964                        error = -EFAULT;
 965                else
 966                        error = count - buf.count;
 967        }
 968        fput(file);
 969out:
 970        return error;
 971}
 972
 973#ifndef __ARCH_OMIT_COMPAT_SYS_GETDENTS64
 974
 975struct compat_getdents_callback64 {
 976        struct linux_dirent64 __user *current_dir;
 977        struct linux_dirent64 __user *previous;
 978        int count;
 979        int error;
 980};
 981
 982static int compat_filldir64(void * __buf, const char * name, int namlen, loff_t offset,
 983                     u64 ino, unsigned int d_type)
 984{
 985        struct linux_dirent64 __user *dirent;
 986        struct compat_getdents_callback64 *buf = __buf;
 987        int jj = NAME_OFFSET(dirent);
 988        int reclen = ALIGN(jj + namlen + 1, sizeof(u64));
 989        u64 off;
 990
 991        buf->error = -EINVAL;   /* only used if we fail.. */
 992        if (reclen > buf->count)
 993                return -EINVAL;
 994        dirent = buf->previous;
 995
 996        if (dirent) {
 997                if (__put_user_unaligned(offset, &dirent->d_off))
 998                        goto efault;
 999        }
1000        dirent = buf->current_dir;
1001        if (__put_user_unaligned(ino, &dirent->d_ino))
1002                goto efault;
1003        off = 0;
1004        if (__put_user_unaligned(off, &dirent->d_off))
1005                goto efault;
1006        if (__put_user(reclen, &dirent->d_reclen))
1007                goto efault;
1008        if (__put_user(d_type, &dirent->d_type))
1009                goto efault;
1010        if (copy_to_user(dirent->d_name, name, namlen))
1011                goto efault;
1012        if (__put_user(0, dirent->d_name + namlen))
1013                goto efault;
1014        buf->previous = dirent;
1015        dirent = (void __user *)dirent + reclen;
1016        buf->current_dir = dirent;
1017        buf->count -= reclen;
1018        return 0;
1019efault:
1020        buf->error = -EFAULT;
1021        return -EFAULT;
1022}
1023
1024asmlinkage long compat_sys_getdents64(unsigned int fd,
1025                struct linux_dirent64 __user * dirent, unsigned int count)
1026{
1027        struct file * file;
1028        struct linux_dirent64 __user * lastdirent;
1029        struct compat_getdents_callback64 buf;
1030        int error;
1031
1032        error = -EFAULT;
1033        if (!access_ok(VERIFY_WRITE, dirent, count))
1034                goto out;
1035
1036        error = -EBADF;
1037        file = fget(fd);
1038        if (!file)
1039                goto out;
1040
1041        buf.current_dir = dirent;
1042        buf.previous = NULL;
1043        buf.count = count;
1044        buf.error = 0;
1045
1046        error = vfs_readdir(file, compat_filldir64, &buf);
1047        if (error >= 0)
1048                error = buf.error;
1049        lastdirent = buf.previous;
1050        if (lastdirent) {
1051                typeof(lastdirent->d_off) d_off = file->f_pos;
1052                if (__put_user_unaligned(d_off, &lastdirent->d_off))
1053                        error = -EFAULT;
1054                else
1055                        error = count - buf.count;
1056        }
1057        fput(file);
1058out:
1059        return error;
1060}
1061#endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */
1062
1063static ssize_t compat_do_readv_writev(int type, struct file *file,
1064                               const struct compat_iovec __user *uvector,
1065                               unsigned long nr_segs, loff_t *pos)
1066{
1067        compat_ssize_t tot_len;
1068        struct iovec iovstack[UIO_FASTIOV];
1069        struct iovec *iov=iovstack, *vector;
1070        ssize_t ret;
1071        int seg;
1072        io_fn_t fn;
1073        iov_fn_t fnv;
1074
1075        /*
1076         * SuS says "The readv() function *may* fail if the iovcnt argument
1077         * was less than or equal to 0, or greater than {IOV_MAX}.  Linux has
1078         * traditionally returned zero for zero segments, so...
1079         */
1080        ret = 0;
1081        if (nr_segs == 0)
1082                goto out;
1083
1084        /*
1085         * First get the "struct iovec" from user memory and
1086         * verify all the pointers
1087         */
1088        ret = -EINVAL;
1089        if ((nr_segs > UIO_MAXIOV) || (nr_segs <= 0))
1090                goto out;
1091        if (!file->f_op)
1092                goto out;
1093        if (nr_segs > UIO_FASTIOV) {
1094                ret = -ENOMEM;
1095                iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
1096                if (!iov)
1097                        goto out;
1098        }
1099        ret = -EFAULT;
1100        if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
1101                goto out;
1102
1103        /*
1104         * Single unix specification:
1105         * We should -EINVAL if an element length is not >= 0 and fitting an
1106         * ssize_t.  The total length is fitting an ssize_t
1107         *
1108         * Be careful here because iov_len is a size_t not an ssize_t
1109         */
1110        tot_len = 0;
1111        vector = iov;
1112        ret = -EINVAL;
1113        for (seg = 0 ; seg < nr_segs; seg++) {
1114                compat_ssize_t tmp = tot_len;
1115                compat_ssize_t len;
1116                compat_uptr_t buf;
1117
1118                if (__get_user(len, &uvector->iov_len) ||
1119                    __get_user(buf, &uvector->iov_base)) {
1120                        ret = -EFAULT;
1121                        goto out;
1122                }
1123                if (len < 0)    /* size_t not fitting an compat_ssize_t .. */
1124                        goto out;
1125                tot_len += len;
1126                if (tot_len < tmp) /* maths overflow on the compat_ssize_t */
1127                        goto out;
1128                vector->iov_base = compat_ptr(buf);
1129                vector->iov_len = (compat_size_t) len;
1130                uvector++;
1131                vector++;
1132        }
1133        if (tot_len == 0) {
1134                ret = 0;
1135                goto out;
1136        }
1137
1138        ret = rw_verify_area(type, file, pos, tot_len);
1139        if (ret < 0)
1140                goto out;
1141
1142        fnv = NULL;
1143        if (type == READ) {
1144                fn = file->f_op->read;
1145                fnv = file->f_op->aio_read;
1146        } else {
1147                fn = (io_fn_t)file->f_op->write;
1148                fnv = file->f_op->aio_write;
1149        }
1150
1151        if (fnv)
1152                ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
1153                                                pos, fnv);
1154        else
1155                ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
1156
1157out:
1158        if (iov != iovstack)
1159                kfree(iov);
1160        if ((ret + (type == READ)) > 0) {
1161                struct dentry *dentry = file->f_path.dentry;
1162                if (type == READ)
1163                        fsnotify_access(dentry);
1164                else
1165                        fsnotify_modify(dentry);
1166        }
1167        return ret;
1168}
1169
1170asmlinkage ssize_t
1171compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen)
1172{
1173        struct file *file;
1174        ssize_t ret = -EBADF;
1175
1176        file = fget(fd);
1177        if (!file)
1178                return -EBADF;
1179
1180        if (!(file->f_mode & FMODE_READ))
1181                goto out;
1182
1183        ret = -EINVAL;
1184        if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read))
1185                goto out;
1186
1187        ret = compat_do_readv_writev(READ, file, vec, vlen, &file->f_pos);
1188
1189out:
1190        fput(file);
1191        return ret;
1192}
1193
1194asmlinkage ssize_t
1195compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen)
1196{
1197        struct file *file;
1198        ssize_t ret = -EBADF;
1199
1200        file = fget(fd);
1201        if (!file)
1202                return -EBADF;
1203        if (!(file->f_mode & FMODE_WRITE))
1204                goto out;
1205
1206        ret = -EINVAL;
1207        if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write))
1208                goto out;
1209
1210        ret = compat_do_readv_writev(WRITE, file, vec, vlen, &file->f_pos);
1211
1212out:
1213        fput(file);
1214        return ret;
1215}
1216
1217asmlinkage long
1218compat_sys_vmsplice(int fd, const struct compat_iovec __user *iov32,
1219                    unsigned int nr_segs, unsigned int flags)
1220{
1221        unsigned i;
1222        struct iovec __user *iov;
1223        if (nr_segs > UIO_MAXIOV)
1224                return -EINVAL;
1225        iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
1226        for (i = 0; i < nr_segs; i++) {
1227                struct compat_iovec v;
1228                if (get_user(v.iov_base, &iov32[i].iov_base) ||
1229                    get_user(v.iov_len, &iov32[i].iov_len) ||
1230                    put_user(compat_ptr(v.iov_base), &iov[i].iov_base) ||
1231                    put_user(v.iov_len, &iov[i].iov_len))
1232                        return -EFAULT;
1233        }
1234        return sys_vmsplice(fd, iov, nr_segs, flags);
1235}
1236
1237/*
1238 * Exactly like fs/open.c:sys_open(), except that it doesn't set the
1239 * O_LARGEFILE flag.
1240 */
1241asmlinkage long
1242compat_sys_open(const char __user *filename, int flags, int mode)
1243{
1244        return do_sys_open(AT_FDCWD, filename, flags, mode);
1245}
1246
1247/*
1248 * Exactly like fs/open.c:sys_openat(), except that it doesn't set the
1249 * O_LARGEFILE flag.
1250 */
1251asmlinkage long
1252compat_sys_openat(unsigned int dfd, const char __user *filename, int flags, int mode)
1253{
1254        return do_sys_open(dfd, filename, flags, mode);
1255}
1256
1257/*
1258 * compat_count() counts the number of arguments/envelopes. It is basically
1259 * a copy of count() from fs/exec.c, except that it works with 32 bit argv
1260 * and envp pointers.
1261 */
1262static int compat_count(compat_uptr_t __user *argv, int max)
1263{
1264        int i = 0;
1265
1266        if (argv != NULL) {
1267                for (;;) {
1268                        compat_uptr_t p;
1269
1270                        if (get_user(p, argv))
1271                                return -EFAULT;
1272                        if (!p)
1273                                break;
1274                        argv++;
1275                        if (i++ >= max)
1276                                return -E2BIG;
1277                }
1278        }
1279        return i;
1280}
1281
1282/*
1283 * compat_copy_strings() is basically a copy of copy_strings() from fs/exec.c
1284 * except that it works with 32 bit argv and envp pointers.
1285 */
1286static int compat_copy_strings(int argc, compat_uptr_t __user *argv,
1287                                struct linux_binprm *bprm)
1288{
1289        struct page *kmapped_page = NULL;
1290        char *kaddr = NULL;
1291        unsigned long kpos = 0;
1292        int ret;
1293
1294        while (argc-- > 0) {
1295                compat_uptr_t str;
1296                int len;
1297                unsigned long pos;
1298
1299                if (get_user(str, argv+argc) ||
1300                    !(len = strnlen_user(compat_ptr(str), MAX_ARG_STRLEN))) {
1301                        ret = -EFAULT;
1302                        goto out;
1303                }
1304
1305                if (len > MAX_ARG_STRLEN) {
1306                        ret = -E2BIG;
1307                        goto out;
1308                }
1309
1310                /* We're going to work our way backwords. */
1311                pos = bprm->p;
1312                str += len;
1313                bprm->p -= len;
1314
1315                while (len > 0) {
1316                        int offset, bytes_to_copy;
1317
1318                        offset = pos % PAGE_SIZE;
1319                        if (offset == 0)
1320                                offset = PAGE_SIZE;
1321
1322                        bytes_to_copy = offset;
1323                        if (bytes_to_copy > len)
1324                                bytes_to_copy = len;
1325
1326                        offset -= bytes_to_copy;
1327                        pos -= bytes_to_copy;
1328                        str -= bytes_to_copy;
1329                        len -= bytes_to_copy;
1330
1331                        if (!kmapped_page || kpos != (pos & PAGE_MASK)) {
1332                                struct page *page;
1333
1334#ifdef CONFIG_STACK_GROWSUP
1335                                ret = expand_stack_downwards(bprm->vma, pos);
1336                                if (ret < 0) {
1337                                        /* We've exceed the stack rlimit. */
1338                                        ret = -E2BIG;
1339                                        goto out;
1340                                }
1341#endif
1342                                ret = get_user_pages(current, bprm->mm, pos,
1343                                                     1, 1, 1, &page, NULL);
1344                                if (ret <= 0) {
1345                                        /* We've exceed the stack rlimit. */
1346                                        ret = -E2BIG;
1347                                        goto out;
1348                                }
1349
1350                                if (kmapped_page) {
1351                                        flush_kernel_dcache_page(kmapped_page);
1352                                        kunmap(kmapped_page);
1353                                        put_page(kmapped_page);
1354                                }
1355                                kmapped_page = page;
1356                                kaddr = kmap(kmapped_page);
1357                                kpos = pos & PAGE_MASK;
1358                                flush_cache_page(bprm->vma, kpos,
1359                                                 page_to_pfn(kmapped_page));
1360                        }
1361                        if (copy_from_user(kaddr+offset, compat_ptr(str),
1362                                                bytes_to_copy)) {
1363                                ret = -EFAULT;
1364                                goto out;
1365                        }
1366                }
1367        }
1368        ret = 0;
1369out:
1370        if (kmapped_page) {
1371                flush_kernel_dcache_page(kmapped_page);
1372                kunmap(kmapped_page);
1373                put_page(kmapped_page);
1374        }
1375        return ret;
1376}
1377
1378/*
1379 * compat_do_execve() is mostly a copy of do_execve(), with the exception
1380 * that it processes 32 bit argv and envp pointers.
1381 */
1382int compat_do_execve(char * filename,
1383        compat_uptr_t __user *argv,
1384        compat_uptr_t __user *envp,
1385        struct pt_regs * regs)
1386{
1387        struct linux_binprm *bprm;
1388        struct file *file;
1389        int retval;
1390
1391        retval = -ENOMEM;
1392        bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
1393        if (!bprm)
1394                goto out_ret;
1395
1396        file = open_exec(filename);
1397        retval = PTR_ERR(file);
1398        if (IS_ERR(file))
1399                goto out_kfree;
1400
1401        sched_exec();
1402
1403        bprm->file = file;
1404        bprm->filename = filename;
1405        bprm->interp = filename;
1406
1407        retval = bprm_mm_init(bprm);
1408        if (retval)
1409                goto out_file;
1410
1411        bprm->argc = compat_count(argv, MAX_ARG_STRINGS);
1412        if ((retval = bprm->argc) < 0)
1413                goto out_mm;
1414
1415        bprm->envc = compat_count(envp, MAX_ARG_STRINGS);
1416        if ((retval = bprm->envc) < 0)
1417                goto out_mm;
1418
1419        retval = security_bprm_alloc(bprm);
1420        if (retval)
1421                goto out;
1422
1423        retval = prepare_binprm(bprm);
1424        if (retval < 0)
1425                goto out;
1426
1427        retval = copy_strings_kernel(1, &bprm->filename, bprm);
1428        if (retval < 0)
1429                goto out;
1430
1431        bprm->exec = bprm->p;
1432        retval = compat_copy_strings(bprm->envc, envp, bprm);
1433        if (retval < 0)
1434                goto out;
1435
1436        retval = compat_copy_strings(bprm->argc, argv, bprm);
1437        if (retval < 0)
1438                goto out;
1439
1440        retval = search_binary_handler(bprm, regs);
1441        if (retval >= 0) {
1442                /* execve success */
1443                security_bprm_free(bprm);
1444                acct_update_integrals(current);
1445                free_bprm(bprm);
1446                return retval;
1447        }
1448
1449out:
1450        if (bprm->security)
1451                security_bprm_free(bprm);
1452
1453out_mm:
1454        if (bprm->mm)
1455                mmput(bprm->mm);
1456
1457out_file:
1458        if (bprm->file) {
1459                allow_write_access(bprm->file);
1460                fput(bprm->file);
1461        }
1462
1463out_kfree:
1464        free_bprm(bprm);
1465
1466out_ret:
1467        return retval;
1468}
1469
1470#define __COMPAT_NFDBITS       (8 * sizeof(compat_ulong_t))
1471
1472static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,
1473                                      int timeval, int ret)
1474{
1475        struct timespec ts;
1476
1477        if (!p)
1478                return ret;
1479
1480        if (current->personality & STICKY_TIMEOUTS)
1481                goto sticky;
1482
1483        /* No update for zero timeout */
1484        if (!end_time->tv_sec && !end_time->tv_nsec)
1485                return ret;
1486
1487        ktime_get_ts(&ts);
1488        ts = timespec_sub(*end_time, ts);
1489        if (ts.tv_sec < 0)
1490                ts.tv_sec = ts.tv_nsec = 0;
1491
1492        if (timeval) {
1493                struct compat_timeval rtv;
1494
1495                rtv.tv_sec = ts.tv_sec;
1496                rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
1497
1498                if (!copy_to_user(p, &rtv, sizeof(rtv)))
1499                        return ret;
1500        } else {
1501                struct compat_timespec rts;
1502
1503                rts.tv_sec = ts.tv_sec;
1504                rts.tv_nsec = ts.tv_nsec;
1505
1506                if (!copy_to_user(p, &rts, sizeof(rts)))
1507                        return ret;
1508        }
1509        /*
1510         * If an application puts its timeval in read-only memory, we
1511         * don't want the Linux-specific update to the timeval to
1512         * cause a fault after the select has completed
1513         * successfully. However, because we're not updating the
1514         * timeval, we can't restart the system call.
1515         */
1516
1517sticky:
1518        if (ret == -ERESTARTNOHAND)
1519                ret = -EINTR;
1520        return ret;
1521}
1522
1523/*
1524 * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
1525 * 64-bit unsigned longs.
1526 */
1527static
1528int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1529                        unsigned long *fdset)
1530{
1531        nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
1532        if (ufdset) {
1533                unsigned long odd;
1534
1535                if (!access_ok(VERIFY_WRITE, ufdset, nr*sizeof(compat_ulong_t)))
1536                        return -EFAULT;
1537
1538                odd = nr & 1UL;
1539                nr &= ~1UL;
1540                while (nr) {
1541                        unsigned long h, l;
1542                        if (__get_user(l, ufdset) || __get_user(h, ufdset+1))
1543                                return -EFAULT;
1544                        ufdset += 2;
1545                        *fdset++ = h << 32 | l;
1546                        nr -= 2;
1547                }
1548                if (odd && __get_user(*fdset, ufdset))
1549                        return -EFAULT;
1550        } else {
1551                /* Tricky, must clear full unsigned long in the
1552                 * kernel fdset at the end, this makes sure that
1553                 * actually happens.
1554                 */
1555                memset(fdset, 0, ((nr + 1) & ~1)*sizeof(compat_ulong_t));
1556        }
1557        return 0;
1558}
1559
1560static
1561int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1562                      unsigned long *fdset)
1563{
1564        unsigned long odd;
1565        nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
1566
1567        if (!ufdset)
1568                return 0;
1569
1570        odd = nr & 1UL;
1571        nr &= ~1UL;
1572        while (nr) {
1573                unsigned long h, l;
1574                l = *fdset++;
1575                h = l >> 32;
1576                if (__put_user(l, ufdset) || __put_user(h, ufdset+1))
1577                        return -EFAULT;
1578                ufdset += 2;
1579                nr -= 2;
1580        }
1581        if (odd && __put_user(*fdset, ufdset))
1582                return -EFAULT;
1583        return 0;
1584}
1585
1586
1587/*
1588 * This is a virtual copy of sys_select from fs/select.c and probably
1589 * should be compared to it from time to time
1590 */
1591
1592/*
1593 * We can actually return ERESTARTSYS instead of EINTR, but I'd
1594 * like to be certain this leads to no problems. So I return
1595 * EINTR just for safety.
1596 *
1597 * Update: ERESTARTSYS breaks at least the xview clock binary, so
1598 * I'm trying ERESTARTNOHAND which restart only when you want to.
1599 */
1600#define MAX_SELECT_SECONDS \
1601        ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
1602
1603int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1604        compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1605        struct timespec *end_time)
1606{
1607        fd_set_bits fds;
1608        void *bits;
1609        int size, max_fds, ret = -EINVAL;
1610        struct fdtable *fdt;
1611        long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
1612
1613        if (n < 0)
1614                goto out_nofds;
1615
1616        /* max_fds can increase, so grab it once to avoid race */
1617        rcu_read_lock();
1618        fdt = files_fdtable(current->files);
1619        max_fds = fdt->max_fds;
1620        rcu_read_unlock();
1621        if (n > max_fds)
1622                n = max_fds;
1623
1624        /*
1625         * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
1626         * since we used fdset we need to allocate memory in units of
1627         * long-words.
1628         */
1629        size = FDS_BYTES(n);
1630        bits = stack_fds;
1631        if (size > sizeof(stack_fds) / 6) {
1632                bits = kmalloc(6 * size, GFP_KERNEL);
1633                ret = -ENOMEM;
1634                if (!bits)
1635                        goto out_nofds;
1636        }
1637        fds.in      = (unsigned long *)  bits;
1638        fds.out     = (unsigned long *) (bits +   size);
1639        fds.ex      = (unsigned long *) (bits + 2*size);
1640        fds.res_in  = (unsigned long *) (bits + 3*size);
1641        fds.res_out = (unsigned long *) (bits + 4*size);
1642        fds.res_ex  = (unsigned long *) (bits + 5*size);
1643
1644        if ((ret = compat_get_fd_set(n, inp, fds.in)) ||
1645            (ret = compat_get_fd_set(n, outp, fds.out)) ||
1646            (ret = compat_get_fd_set(n, exp, fds.ex)))
1647                goto out;
1648        zero_fd_set(n, fds.res_in);
1649        zero_fd_set(n, fds.res_out);
1650        zero_fd_set(n, fds.res_ex);
1651
1652        ret = do_select(n, &fds, end_time);
1653
1654        if (ret < 0)
1655                goto out;
1656        if (!ret) {
1657                ret = -ERESTARTNOHAND;
1658                if (signal_pending(current))
1659                        goto out;
1660                ret = 0;
1661        }
1662
1663        if (compat_set_fd_set(n, inp, fds.res_in) ||
1664            compat_set_fd_set(n, outp, fds.res_out) ||
1665            compat_set_fd_set(n, exp, fds.res_ex))
1666                ret = -EFAULT;
1667out:
1668        if (bits != stack_fds)
1669                kfree(bits);
1670out_nofds:
1671        return ret;
1672}
1673
1674asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
1675        compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1676        struct compat_timeval __user *tvp)
1677{
1678        struct timespec end_time, *to = NULL;
1679        struct compat_timeval tv;
1680        int ret;
1681
1682        if (tvp) {
1683                if (copy_from_user(&tv, tvp, sizeof(tv)))
1684                        return -EFAULT;
1685
1686                to = &end_time;
1687                if (poll_select_set_timeout(to,
1688                                tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
1689                                (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
1690                        return -EINVAL;
1691        }
1692
1693        ret = compat_core_sys_select(n, inp, outp, exp, to);
1694        ret = poll_select_copy_remaining(&end_time, tvp, 1, ret);
1695
1696        return ret;
1697}
1698
1699#ifdef HAVE_SET_RESTORE_SIGMASK
1700static long do_compat_pselect(int n, compat_ulong_t __user *inp,
1701        compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1702        struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
1703        compat_size_t sigsetsize)
1704{
1705        compat_sigset_t ss32;
1706        sigset_t ksigmask, sigsaved;
1707        struct compat_timespec ts;
1708        struct timespec end_time, *to = NULL;
1709        int ret;
1710
1711        if (tsp) {
1712                if (copy_from_user(&ts, tsp, sizeof(ts)))
1713                        return -EFAULT;
1714
1715                to = &end_time;
1716                if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1717                        return -EINVAL;
1718        }
1719
1720        if (sigmask) {
1721                if (sigsetsize != sizeof(compat_sigset_t))
1722                        return -EINVAL;
1723                if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1724                        return -EFAULT;
1725                sigset_from_compat(&ksigmask, &ss32);
1726
1727                sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1728                sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1729        }
1730
1731        ret = compat_core_sys_select(n, inp, outp, exp, to);
1732        ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1733
1734        if (ret == -ERESTARTNOHAND) {
1735                /*
1736                 * Don't restore the signal mask yet. Let do_signal() deliver
1737                 * the signal on the way back to userspace, before the signal
1738                 * mask is restored.
1739                 */
1740                if (sigmask) {
1741                        memcpy(&current->saved_sigmask, &sigsaved,
1742                                        sizeof(sigsaved));
1743                        set_restore_sigmask();
1744                }
1745        } else if (sigmask)
1746                sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1747
1748        return ret;
1749}
1750
1751asmlinkage long compat_sys_pselect6(int n, compat_ulong_t __user *inp,
1752        compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1753        struct compat_timespec __user *tsp, void __user *sig)
1754{
1755        compat_size_t sigsetsize = 0;
1756        compat_uptr_t up = 0;
1757
1758        if (sig) {
1759                if (!access_ok(VERIFY_READ, sig,
1760                                sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
1761                        __get_user(up, (compat_uptr_t __user *)sig) ||
1762                        __get_user(sigsetsize,
1763                                (compat_size_t __user *)(sig+sizeof(up))))
1764                        return -EFAULT;
1765        }
1766        return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up),
1767                                 sigsetsize);
1768}
1769
1770asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1771        unsigned int nfds, struct compat_timespec __user *tsp,
1772        const compat_sigset_t __user *sigmask, compat_size_t sigsetsize)
1773{
1774        compat_sigset_t ss32;
1775        sigset_t ksigmask, sigsaved;
1776        struct compat_timespec ts;
1777        struct timespec end_time, *to = NULL;
1778        int ret;
1779
1780        if (tsp) {
1781                if (copy_from_user(&ts, tsp, sizeof(ts)))
1782                        return -EFAULT;
1783
1784                to = &end_time;
1785                if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1786                        return -EINVAL;
1787        }
1788
1789        if (sigmask) {
1790                if (sigsetsize != sizeof(compat_sigset_t))
1791                        return -EINVAL;
1792                if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1793                        return -EFAULT;
1794                sigset_from_compat(&ksigmask, &ss32);
1795
1796                sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1797                sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1798        }
1799
1800        ret = do_sys_poll(ufds, nfds, to);
1801
1802        /* We can restart this syscall, usually */
1803        if (ret == -EINTR) {
1804                /*
1805                 * Don't restore the signal mask yet. Let do_signal() deliver
1806                 * the signal on the way back to userspace, before the signal
1807                 * mask is restored.
1808                 */
1809                if (sigmask) {
1810                        memcpy(&current->saved_sigmask, &sigsaved,
1811                                sizeof(sigsaved));
1812                        set_restore_sigmask();
1813                }
1814                ret = -ERESTARTNOHAND;
1815        } else if (sigmask)
1816                sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1817
1818        ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1819
1820        return ret;
1821}
1822#endif /* HAVE_SET_RESTORE_SIGMASK */
1823
1824#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
1825/* Stuff for NFS server syscalls... */
1826struct compat_nfsctl_svc {
1827        u16                     svc32_port;
1828        s32                     svc32_nthreads;
1829};
1830
1831struct compat_nfsctl_client {
1832        s8                      cl32_ident[NFSCLNT_IDMAX+1];
1833        s32                     cl32_naddr;
1834        struct in_addr          cl32_addrlist[NFSCLNT_ADDRMAX];
1835        s32                     cl32_fhkeytype;
1836        s32                     cl32_fhkeylen;
1837        u8                      cl32_fhkey[NFSCLNT_KEYMAX];
1838};
1839
1840struct compat_nfsctl_export {
1841        char            ex32_client[NFSCLNT_IDMAX+1];
1842        char            ex32_path[NFS_MAXPATHLEN+1];
1843        compat_dev_t    ex32_dev;
1844        compat_ino_t    ex32_ino;
1845        compat_int_t    ex32_flags;
1846        __compat_uid_t  ex32_anon_uid;
1847        __compat_gid_t  ex32_anon_gid;
1848};
1849
1850struct compat_nfsctl_fdparm {
1851        struct sockaddr         gd32_addr;
1852        s8                      gd32_path[NFS_MAXPATHLEN+1];
1853        compat_int_t            gd32_version;
1854};
1855
1856struct compat_nfsctl_fsparm {
1857        struct sockaddr         gd32_addr;
1858        s8                      gd32_path[NFS_MAXPATHLEN+1];
1859        compat_int_t            gd32_maxlen;
1860};
1861
1862struct compat_nfsctl_arg {
1863        compat_int_t            ca32_version;   /* safeguard */
1864        union {
1865                struct compat_nfsctl_svc        u32_svc;
1866                struct compat_nfsctl_client     u32_client;
1867                struct compat_nfsctl_export     u32_export;
1868                struct compat_nfsctl_fdparm     u32_getfd;
1869                struct compat_nfsctl_fsparm     u32_getfs;
1870        } u;
1871#define ca32_svc        u.u32_svc
1872#define ca32_client     u.u32_client
1873#define ca32_export     u.u32_export
1874#define ca32_getfd      u.u32_getfd
1875#define ca32_getfs      u.u32_getfs
1876};
1877
1878union compat_nfsctl_res {
1879        __u8                    cr32_getfh[NFS_FHSIZE];
1880        struct knfsd_fh         cr32_getfs;
1881};
1882
1883static int compat_nfs_svc_trans(struct nfsctl_arg *karg,
1884                                struct compat_nfsctl_arg __user *arg)
1885{
1886        if (!access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)) ||
1887                get_user(karg->ca_version, &arg->ca32_version) ||
1888                __get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port) ||
1889                __get_user(karg->ca_svc.svc_nthreads,
1890                                &arg->ca32_svc.svc32_nthreads))
1891                return -EFAULT;
1892        return 0;
1893}
1894
1895static int compat_nfs_clnt_trans(struct nfsctl_arg *karg,
1896                                struct compat_nfsctl_arg __user *arg)
1897{
1898        if (!access_ok(VERIFY_READ, &arg->ca32_client,
1899                        sizeof(arg->ca32_client)) ||
1900                get_user(karg->ca_version, &arg->ca32_version) ||
1901                __copy_from_user(&karg->ca_client.cl_ident[0],
1902                                &arg->ca32_client.cl32_ident[0],
1903                                NFSCLNT_IDMAX) ||
1904                __get_user(karg->ca_client.cl_naddr,
1905                                &arg->ca32_client.cl32_naddr) ||
1906                __copy_from_user(&karg->ca_client.cl_addrlist[0],
1907                                &arg->ca32_client.cl32_addrlist[0],
1908                                (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)) ||
1909                __get_user(karg->ca_client.cl_fhkeytype,
1910                                &arg->ca32_client.cl32_fhkeytype) ||
1911                __get_user(karg->ca_client.cl_fhkeylen,
1912                                &arg->ca32_client.cl32_fhkeylen) ||
1913                __copy_from_user(&karg->ca_client.cl_fhkey[0],
1914                                &arg->ca32_client.cl32_fhkey[0],
1915                                NFSCLNT_KEYMAX))
1916                return -EFAULT;
1917
1918        return 0;
1919}
1920
1921static int compat_nfs_exp_trans(struct nfsctl_arg *karg,
1922                                struct compat_nfsctl_arg __user *arg)
1923{
1924        if (!access_ok(VERIFY_READ, &arg->ca32_export,
1925                                sizeof(arg->ca32_export)) ||
1926                get_user(karg->ca_version, &arg->ca32_version) ||
1927                __copy_from_user(&karg->ca_export.ex_client[0],
1928                                &arg->ca32_export.ex32_client[0],
1929                                NFSCLNT_IDMAX) ||
1930                __copy_from_user(&karg->ca_export.ex_path[0],
1931                                &arg->ca32_export.ex32_path[0],
1932                                NFS_MAXPATHLEN) ||
1933                __get_user(karg->ca_export.ex_dev,
1934                                &arg->ca32_export.ex32_dev) ||
1935                __get_user(karg->ca_export.ex_ino,
1936                                &arg->ca32_export.ex32_ino) ||
1937                __get_user(karg->ca_export.ex_flags,
1938                                &arg->ca32_export.ex32_flags) ||
1939                __get_user(karg->ca_export.ex_anon_uid,
1940                                &arg->ca32_export.ex32_anon_uid) ||
1941                __get_user(karg->ca_export.ex_anon_gid,
1942                                &arg->ca32_export.ex32_anon_gid))
1943                return -EFAULT;
1944        SET_UID(karg->ca_export.ex_anon_uid, karg->ca_export.ex_anon_uid);
1945        SET_GID(karg->ca_export.ex_anon_gid, karg->ca_export.ex_anon_gid);
1946
1947        return 0;
1948}
1949
1950static int compat_nfs_getfd_trans(struct nfsctl_arg *karg,
1951                                struct compat_nfsctl_arg __user *arg)
1952{
1953        if (!access_ok(VERIFY_READ, &arg->ca32_getfd,
1954                        sizeof(arg->ca32_getfd)) ||
1955                get_user(karg->ca_version, &arg->ca32_version) ||
1956                __copy_from_user(&karg->ca_getfd.gd_addr,
1957                                &arg->ca32_getfd.gd32_addr,
1958                                (sizeof(struct sockaddr))) ||
1959                __copy_from_user(&karg->ca_getfd.gd_path,
1960                                &arg->ca32_getfd.gd32_path,
1961                                (NFS_MAXPATHLEN+1)) ||
1962                __get_user(karg->ca_getfd.gd_version,
1963                                &arg->ca32_getfd.gd32_version))
1964                return -EFAULT;
1965
1966        return 0;
1967}
1968
1969static int compat_nfs_getfs_trans(struct nfsctl_arg *karg,
1970                                struct compat_nfsctl_arg __user *arg)
1971{
1972        if (!access_ok(VERIFY_READ,&arg->ca32_getfs,sizeof(arg->ca32_getfs)) ||
1973                get_user(karg->ca_version, &arg->ca32_version) ||
1974                __copy_from_user(&karg->ca_getfs.gd_addr,
1975                                &arg->ca32_getfs.gd32_addr,
1976                                (sizeof(struct sockaddr))) ||
1977                __copy_from_user(&karg->ca_getfs.gd_path,
1978                                &arg->ca32_getfs.gd32_path,
1979                                (NFS_MAXPATHLEN+1)) ||
1980                __get_user(karg->ca_getfs.gd_maxlen,
1981                                &arg->ca32_getfs.gd32_maxlen))
1982                return -EFAULT;
1983
1984        return 0;
1985}
1986
1987/* This really doesn't need translations, we are only passing
1988 * back a union which contains opaque nfs file handle data.
1989 */
1990static int compat_nfs_getfh_res_trans(union nfsctl_res *kres,
1991                                union compat_nfsctl_res __user *res)
1992{
1993        int err;
1994
1995        err = copy_to_user(res, kres, sizeof(*res));
1996
1997        return (err) ? -EFAULT : 0;
1998}
1999
2000asmlinkage long compat_sys_nfsservctl(int cmd,
2001                                struct compat_nfsctl_arg __user *arg,
2002                                union compat_nfsctl_res __user *res)
2003{
2004        struct nfsctl_arg *karg;
2005        union nfsctl_res *kres;
2006        mm_segment_t oldfs;
2007        int err;
2008
2009        karg = kmalloc(sizeof(*karg), GFP_USER);
2010        kres = kmalloc(sizeof(*kres), GFP_USER);
2011        if(!karg || !kres) {
2012                err = -ENOMEM;
2013                goto done;
2014        }
2015
2016        switch(cmd) {
2017        case NFSCTL_SVC:
2018                err = compat_nfs_svc_trans(karg, arg);
2019                break;
2020
2021        case NFSCTL_ADDCLIENT:
2022                err = compat_nfs_clnt_trans(karg, arg);
2023                break;
2024
2025        case NFSCTL_DELCLIENT:
2026                err = compat_nfs_clnt_trans(karg, arg);
2027                break;
2028
2029        case NFSCTL_EXPORT:
2030        case NFSCTL_UNEXPORT:
2031                err = compat_nfs_exp_trans(karg, arg);
2032                break;
2033
2034        case NFSCTL_GETFD:
2035                err = compat_nfs_getfd_trans(karg, arg);
2036                break;
2037
2038        case NFSCTL_GETFS:
2039                err = compat_nfs_getfs_trans(karg, arg);
2040                break;
2041
2042        default:
2043                err = -EINVAL;
2044                break;
2045        }
2046
2047        if (err)
2048                goto done;
2049
2050        oldfs = get_fs();
2051        set_fs(KERNEL_DS);
2052        /* The __user pointer casts are valid because of the set_fs() */
2053        err = sys_nfsservctl(cmd, (void __user *) karg, (void __user *) kres);
2054        set_fs(oldfs);
2055
2056        if (err)
2057                goto done;
2058
2059        if((cmd == NFSCTL_GETFD) ||
2060           (cmd == NFSCTL_GETFS))
2061                err = compat_nfs_getfh_res_trans(kres, res);
2062
2063done:
2064        kfree(karg);
2065        kfree(kres);
2066        return err;
2067}
2068#else /* !NFSD */
2069long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2)
2070{
2071        return sys_ni_syscall();
2072}
2073#endif
2074
2075#ifdef CONFIG_EPOLL
2076
2077#ifdef HAVE_SET_RESTORE_SIGMASK
2078asmlinkage long compat_sys_epoll_pwait(int epfd,
2079                        struct compat_epoll_event __user *events,
2080                        int maxevents, int timeout,
2081                        const compat_sigset_t __user *sigmask,
2082                        compat_size_t sigsetsize)
2083{
2084        long err;
2085        compat_sigset_t csigmask;
2086        sigset_t ksigmask, sigsaved;
2087
2088        /*
2089         * If the caller wants a certain signal mask to be set during the wait,
2090         * we apply it here.
2091         */
2092        if (sigmask) {
2093                if (sigsetsize != sizeof(compat_sigset_t))
2094                        return -EINVAL;
2095                if (copy_from_user(&csigmask, sigmask, sizeof(csigmask)))
2096                        return -EFAULT;
2097                sigset_from_compat(&ksigmask, &csigmask);
2098                sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
2099                sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
2100        }
2101
2102        err = sys_epoll_wait(epfd, events, maxevents, timeout);
2103
2104        /*
2105         * If we changed the signal mask, we need to restore the original one.
2106         * In case we've got a signal while waiting, we do not restore the
2107         * signal mask yet, and we allow do_signal() to deliver the signal on
2108         * the way back to userspace, before the signal mask is restored.
2109         */
2110        if (sigmask) {
2111                if (err == -EINTR) {
2112                        memcpy(&current->saved_sigmask, &sigsaved,
2113                               sizeof(sigsaved));
2114                        set_restore_sigmask();
2115                } else
2116                        sigprocmask(SIG_SETMASK, &sigsaved, NULL);
2117        }
2118
2119        return err;
2120}
2121#endif /* HAVE_SET_RESTORE_SIGMASK */
2122
2123#endif /* CONFIG_EPOLL */
2124
2125#ifdef CONFIG_SIGNALFD
2126
2127asmlinkage long compat_sys_signalfd4(int ufd,
2128                                     const compat_sigset_t __user *sigmask,
2129                                     compat_size_t sigsetsize, int flags)
2130{
2131        compat_sigset_t ss32;
2132        sigset_t tmp;
2133        sigset_t __user *ksigmask;
2134
2135        if (sigsetsize != sizeof(compat_sigset_t))
2136                return -EINVAL;
2137        if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
2138                return -EFAULT;
2139        sigset_from_compat(&tmp, &ss32);
2140        ksigmask = compat_alloc_user_space(sizeof(sigset_t));
2141        if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
2142                return -EFAULT;
2143
2144        return sys_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags);
2145}
2146
2147asmlinkage long compat_sys_signalfd(int ufd,
2148                                    const compat_sigset_t __user *sigmask,
2149                                    compat_size_t sigsetsize)
2150{
2151        return compat_sys_signalfd4(ufd, sigmask, sigsetsize, 0);
2152}
2153#endif /* CONFIG_SIGNALFD */
2154
2155#ifdef CONFIG_TIMERFD
2156
2157asmlinkage long compat_sys_timerfd_settime(int ufd, int flags,
2158                                   const struct compat_itimerspec __user *utmr,
2159                                   struct compat_itimerspec __user *otmr)
2160{
2161        int error;
2162        struct itimerspec t;
2163        struct itimerspec __user *ut;
2164
2165        if (get_compat_itimerspec(&t, utmr))
2166                return -EFAULT;
2167        ut = compat_alloc_user_space(2 * sizeof(struct itimerspec));
2168        if (copy_to_user(&ut[0], &t, sizeof(t)))
2169                return -EFAULT;
2170        error = sys_timerfd_settime(ufd, flags, &ut[0], &ut[1]);
2171        if (!error && otmr)
2172                error = (copy_from_user(&t, &ut[1], sizeof(struct itimerspec)) ||
2173                         put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0;
2174
2175        return error;
2176}
2177
2178asmlinkage long compat_sys_timerfd_gettime(int ufd,
2179                                   struct compat_itimerspec __user *otmr)
2180{
2181        int error;
2182        struct itimerspec t;
2183        struct itimerspec __user *ut;
2184
2185        ut = compat_alloc_user_space(sizeof(struct itimerspec));
2186        error = sys_timerfd_gettime(ufd, ut);
2187        if (!error)
2188                error = (copy_from_user(&t, ut, sizeof(struct itimerspec)) ||
2189                         put_compat_itimerspec(otmr, &t)) ? -EFAULT: 0;
2190
2191        return error;
2192}
2193
2194#endif /* CONFIG_TIMERFD */
2195