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@ucw.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/stddef.h>
  19#include <linux/kernel.h>
  20#include <linux/linkage.h>
  21#include <linux/compat.h>
  22#include <linux/errno.h>
  23#include <linux/time.h>
  24#include <linux/fs.h>
  25#include <linux/fcntl.h>
  26#include <linux/namei.h>
  27#include <linux/file.h>
  28#include <linux/fdtable.h>
  29#include <linux/vfs.h>
  30#include <linux/ioctl.h>
  31#include <linux/init.h>
  32#include <linux/ncp_mount.h>
  33#include <linux/nfs4_mount.h>
  34#include <linux/syscalls.h>
  35#include <linux/ctype.h>
  36#include <linux/dirent.h>
  37#include <linux/fsnotify.h>
  38#include <linux/highuid.h>
  39#include <linux/personality.h>
  40#include <linux/rwsem.h>
  41#include <linux/tsacct_kern.h>
  42#include <linux/security.h>
  43#include <linux/highmem.h>
  44#include <linux/signal.h>
  45#include <linux/poll.h>
  46#include <linux/mm.h>
  47#include <linux/fs_struct.h>
  48#include <linux/slab.h>
  49#include <linux/pagemap.h>
  50#include <linux/aio.h>
  51
  52#include <asm/uaccess.h>
  53#include <asm/mmu_context.h>
  54#include <asm/ioctls.h>
  55#include "internal.h"
  56
  57/*
  58 * Not all architectures have sys_utime, so implement this in terms
  59 * of sys_utimes.
  60 */
  61COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename,
  62                       struct compat_utimbuf __user *, t)
  63{
  64        struct timespec tv[2];
  65
  66        if (t) {
  67                if (get_user(tv[0].tv_sec, &t->actime) ||
  68                    get_user(tv[1].tv_sec, &t->modtime))
  69                        return -EFAULT;
  70                tv[0].tv_nsec = 0;
  71                tv[1].tv_nsec = 0;
  72        }
  73        return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0);
  74}
  75
  76COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags)
  77{
  78        struct timespec tv[2];
  79
  80        if  (t) {
  81                if (compat_get_timespec(&tv[0], &t[0]) ||
  82                    compat_get_timespec(&tv[1], &t[1]))
  83                        return -EFAULT;
  84
  85                if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)
  86                        return 0;
  87        }
  88        return do_utimes(dfd, filename, t ? tv : NULL, flags);
  89}
  90
  91COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t)
  92{
  93        struct timespec tv[2];
  94
  95        if (t) {
  96                if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
  97                    get_user(tv[0].tv_nsec, &t[0].tv_usec) ||
  98                    get_user(tv[1].tv_sec, &t[1].tv_sec) ||
  99                    get_user(tv[1].tv_nsec, &t[1].tv_usec))
 100                        return -EFAULT;
 101                if (tv[0].tv_nsec >= 1000000 || tv[0].tv_nsec < 0 ||
 102                    tv[1].tv_nsec >= 1000000 || tv[1].tv_nsec < 0)
 103                        return -EINVAL;
 104                tv[0].tv_nsec *= 1000;
 105                tv[1].tv_nsec *= 1000;
 106        }
 107        return do_utimes(dfd, filename, t ? tv : NULL, 0);
 108}
 109
 110COMPAT_SYSCALL_DEFINE2(utimes, const char __user *, filename, struct compat_timeval __user *, t)
 111{
 112        return compat_sys_futimesat(AT_FDCWD, filename, t);
 113}
 114
 115static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
 116{
 117        struct compat_stat tmp;
 118
 119        if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
 120                return -EOVERFLOW;
 121
 122        memset(&tmp, 0, sizeof(tmp));
 123        tmp.st_dev = old_encode_dev(stat->dev);
 124        tmp.st_ino = stat->ino;
 125        if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
 126                return -EOVERFLOW;
 127        tmp.st_mode = stat->mode;
 128        tmp.st_nlink = stat->nlink;
 129        if (tmp.st_nlink != stat->nlink)
 130                return -EOVERFLOW;
 131        SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
 132        SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
 133        tmp.st_rdev = old_encode_dev(stat->rdev);
 134        if ((u64) stat->size > MAX_NON_LFS)
 135                return -EOVERFLOW;
 136        tmp.st_size = stat->size;
 137        tmp.st_atime = stat->atime.tv_sec;
 138        tmp.st_atime_nsec = stat->atime.tv_nsec;
 139        tmp.st_mtime = stat->mtime.tv_sec;
 140        tmp.st_mtime_nsec = stat->mtime.tv_nsec;
 141        tmp.st_ctime = stat->ctime.tv_sec;
 142        tmp.st_ctime_nsec = stat->ctime.tv_nsec;
 143        tmp.st_blocks = stat->blocks;
 144        tmp.st_blksize = stat->blksize;
 145        return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 146}
 147
 148COMPAT_SYSCALL_DEFINE2(newstat, const char __user *, filename,
 149                       struct compat_stat __user *, statbuf)
 150{
 151        struct kstat stat;
 152        int error;
 153
 154        error = vfs_stat(filename, &stat);
 155        if (error)
 156                return error;
 157        return cp_compat_stat(&stat, statbuf);
 158}
 159
 160COMPAT_SYSCALL_DEFINE2(newlstat, const char __user *, filename,
 161                       struct compat_stat __user *, statbuf)
 162{
 163        struct kstat stat;
 164        int error;
 165
 166        error = vfs_lstat(filename, &stat);
 167        if (error)
 168                return error;
 169        return cp_compat_stat(&stat, statbuf);
 170}
 171
 172#ifndef __ARCH_WANT_STAT64
 173COMPAT_SYSCALL_DEFINE4(newfstatat, unsigned int, dfd,
 174                       const char __user *, filename,
 175                       struct compat_stat __user *, statbuf, int, flag)
 176{
 177        struct kstat stat;
 178        int error;
 179
 180        error = vfs_fstatat(dfd, filename, &stat, flag);
 181        if (error)
 182                return error;
 183        return cp_compat_stat(&stat, statbuf);
 184}
 185#endif
 186
 187COMPAT_SYSCALL_DEFINE2(newfstat, unsigned int, fd,
 188                       struct compat_stat __user *, statbuf)
 189{
 190        struct kstat stat;
 191        int error = vfs_fstat(fd, &stat);
 192
 193        if (!error)
 194                error = cp_compat_stat(&stat, statbuf);
 195        return error;
 196}
 197
 198static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf)
 199{
 200        
 201        if (sizeof ubuf->f_blocks == 4) {
 202                if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
 203                     kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
 204                        return -EOVERFLOW;
 205                /* f_files and f_ffree may be -1; it's okay
 206                 * to stuff that into 32 bits */
 207                if (kbuf->f_files != 0xffffffffffffffffULL
 208                 && (kbuf->f_files & 0xffffffff00000000ULL))
 209                        return -EOVERFLOW;
 210                if (kbuf->f_ffree != 0xffffffffffffffffULL
 211                 && (kbuf->f_ffree & 0xffffffff00000000ULL))
 212                        return -EOVERFLOW;
 213        }
 214        if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
 215            __put_user(kbuf->f_type, &ubuf->f_type) ||
 216            __put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
 217            __put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
 218            __put_user(kbuf->f_bfree, &ubuf->f_bfree) ||
 219            __put_user(kbuf->f_bavail, &ubuf->f_bavail) ||
 220            __put_user(kbuf->f_files, &ubuf->f_files) ||
 221            __put_user(kbuf->f_ffree, &ubuf->f_ffree) ||
 222            __put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
 223            __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
 224            __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
 225            __put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
 226            __put_user(kbuf->f_flags, &ubuf->f_flags) ||
 227            __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare)))
 228                return -EFAULT;
 229        return 0;
 230}
 231
 232/*
 233 * The following statfs calls are copies of code from fs/statfs.c and
 234 * should be checked against those from time to time
 235 */
 236COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf)
 237{
 238        struct kstatfs tmp;
 239        int error = user_statfs(pathname, &tmp);
 240        if (!error)
 241                error = put_compat_statfs(buf, &tmp);
 242        return error;
 243}
 244
 245COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf)
 246{
 247        struct kstatfs tmp;
 248        int error = fd_statfs(fd, &tmp);
 249        if (!error)
 250                error = put_compat_statfs(buf, &tmp);
 251        return error;
 252}
 253
 254static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
 255{
 256        if (sizeof ubuf->f_blocks == 4) {
 257                if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
 258                     kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
 259                        return -EOVERFLOW;
 260                /* f_files and f_ffree may be -1; it's okay
 261                 * to stuff that into 32 bits */
 262                if (kbuf->f_files != 0xffffffffffffffffULL
 263                 && (kbuf->f_files & 0xffffffff00000000ULL))
 264                        return -EOVERFLOW;
 265                if (kbuf->f_ffree != 0xffffffffffffffffULL
 266                 && (kbuf->f_ffree & 0xffffffff00000000ULL))
 267                        return -EOVERFLOW;
 268        }
 269        if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
 270            __put_user(kbuf->f_type, &ubuf->f_type) ||
 271            __put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
 272            __put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
 273            __put_user(kbuf->f_bfree, &ubuf->f_bfree) ||
 274            __put_user(kbuf->f_bavail, &ubuf->f_bavail) ||
 275            __put_user(kbuf->f_files, &ubuf->f_files) ||
 276            __put_user(kbuf->f_ffree, &ubuf->f_ffree) ||
 277            __put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
 278            __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
 279            __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
 280            __put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
 281            __put_user(kbuf->f_flags, &ubuf->f_flags) ||
 282            __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare)))
 283                return -EFAULT;
 284        return 0;
 285}
 286
 287COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf)
 288{
 289        struct kstatfs tmp;
 290        int error;
 291
 292        if (sz != sizeof(*buf))
 293                return -EINVAL;
 294
 295        error = user_statfs(pathname, &tmp);
 296        if (!error)
 297                error = put_compat_statfs64(buf, &tmp);
 298        return error;
 299}
 300
 301COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf)
 302{
 303        struct kstatfs tmp;
 304        int error;
 305
 306        if (sz != sizeof(*buf))
 307                return -EINVAL;
 308
 309        error = fd_statfs(fd, &tmp);
 310        if (!error)
 311                error = put_compat_statfs64(buf, &tmp);
 312        return error;
 313}
 314
 315/*
 316 * This is a copy of sys_ustat, just dealing with a structure layout.
 317 * Given how simple this syscall is that apporach is more maintainable
 318 * than the various conversion hacks.
 319 */
 320COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u)
 321{
 322        struct compat_ustat tmp;
 323        struct kstatfs sbuf;
 324        int err = vfs_ustat(new_decode_dev(dev), &sbuf);
 325        if (err)
 326                return err;
 327
 328        memset(&tmp, 0, sizeof(struct compat_ustat));
 329        tmp.f_tfree = sbuf.f_bfree;
 330        tmp.f_tinode = sbuf.f_ffree;
 331        if (copy_to_user(u, &tmp, sizeof(struct compat_ustat)))
 332                return -EFAULT;
 333        return 0;
 334}
 335
 336static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
 337{
 338        if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
 339            __get_user(kfl->l_type, &ufl->l_type) ||
 340            __get_user(kfl->l_whence, &ufl->l_whence) ||
 341            __get_user(kfl->l_start, &ufl->l_start) ||
 342            __get_user(kfl->l_len, &ufl->l_len) ||
 343            __get_user(kfl->l_pid, &ufl->l_pid))
 344                return -EFAULT;
 345        return 0;
 346}
 347
 348static int put_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
 349{
 350        if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
 351            __put_user(kfl->l_type, &ufl->l_type) ||
 352            __put_user(kfl->l_whence, &ufl->l_whence) ||
 353            __put_user(kfl->l_start, &ufl->l_start) ||
 354            __put_user(kfl->l_len, &ufl->l_len) ||
 355            __put_user(kfl->l_pid, &ufl->l_pid))
 356                return -EFAULT;
 357        return 0;
 358}
 359
 360#ifndef HAVE_ARCH_GET_COMPAT_FLOCK64
 361static int get_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl)
 362{
 363        if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
 364            __get_user(kfl->l_type, &ufl->l_type) ||
 365            __get_user(kfl->l_whence, &ufl->l_whence) ||
 366            __get_user(kfl->l_start, &ufl->l_start) ||
 367            __get_user(kfl->l_len, &ufl->l_len) ||
 368            __get_user(kfl->l_pid, &ufl->l_pid))
 369                return -EFAULT;
 370        return 0;
 371}
 372#endif
 373
 374#ifndef HAVE_ARCH_PUT_COMPAT_FLOCK64
 375static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl)
 376{
 377        if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
 378            __put_user(kfl->l_type, &ufl->l_type) ||
 379            __put_user(kfl->l_whence, &ufl->l_whence) ||
 380            __put_user(kfl->l_start, &ufl->l_start) ||
 381            __put_user(kfl->l_len, &ufl->l_len) ||
 382            __put_user(kfl->l_pid, &ufl->l_pid))
 383                return -EFAULT;
 384        return 0;
 385}
 386#endif
 387
 388static unsigned int
 389convert_fcntl_cmd(unsigned int cmd)
 390{
 391        switch (cmd) {
 392        case F_GETLK64:
 393                return F_GETLK;
 394        case F_SETLK64:
 395                return F_SETLK;
 396        case F_SETLKW64:
 397                return F_SETLKW;
 398        }
 399
 400        return cmd;
 401}
 402
 403COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
 404                       compat_ulong_t, arg)
 405{
 406        mm_segment_t old_fs;
 407        struct flock f;
 408        long ret;
 409        unsigned int conv_cmd;
 410
 411        switch (cmd) {
 412        case F_GETLK:
 413        case F_SETLK:
 414        case F_SETLKW:
 415                ret = get_compat_flock(&f, compat_ptr(arg));
 416                if (ret != 0)
 417                        break;
 418                old_fs = get_fs();
 419                set_fs(KERNEL_DS);
 420                ret = sys_fcntl(fd, cmd, (unsigned long)&f);
 421                set_fs(old_fs);
 422                if (cmd == F_GETLK && ret == 0) {
 423                        /* GETLK was successful and we need to return the data...
 424                         * but it needs to fit in the compat structure.
 425                         * l_start shouldn't be too big, unless the original
 426                         * start + end is greater than COMPAT_OFF_T_MAX, in which
 427                         * case the app was asking for trouble, so we return
 428                         * -EOVERFLOW in that case.
 429                         * l_len could be too big, in which case we just truncate it,
 430                         * and only allow the app to see that part of the conflicting
 431                         * lock that might make sense to it anyway
 432                         */
 433
 434                        if (f.l_start > COMPAT_OFF_T_MAX)
 435                                ret = -EOVERFLOW;
 436                        if (f.l_len > COMPAT_OFF_T_MAX)
 437                                f.l_len = COMPAT_OFF_T_MAX;
 438                        if (ret == 0)
 439                                ret = put_compat_flock(&f, compat_ptr(arg));
 440                }
 441                break;
 442
 443        case F_GETLK64:
 444        case F_SETLK64:
 445        case F_SETLKW64:
 446        case F_OFD_GETLK:
 447        case F_OFD_SETLK:
 448        case F_OFD_SETLKW:
 449                ret = get_compat_flock64(&f, compat_ptr(arg));
 450                if (ret != 0)
 451                        break;
 452                old_fs = get_fs();
 453                set_fs(KERNEL_DS);
 454                conv_cmd = convert_fcntl_cmd(cmd);
 455                ret = sys_fcntl(fd, conv_cmd, (unsigned long)&f);
 456                set_fs(old_fs);
 457                if ((conv_cmd == F_GETLK || conv_cmd == F_OFD_GETLK) && ret == 0) {
 458                        /* need to return lock information - see above for commentary */
 459                        if (f.l_start > COMPAT_LOFF_T_MAX)
 460                                ret = -EOVERFLOW;
 461                        if (f.l_len > COMPAT_LOFF_T_MAX)
 462                                f.l_len = COMPAT_LOFF_T_MAX;
 463                        if (ret == 0)
 464                                ret = put_compat_flock64(&f, compat_ptr(arg));
 465                }
 466                break;
 467
 468        default:
 469                ret = sys_fcntl(fd, cmd, arg);
 470                break;
 471        }
 472        return ret;
 473}
 474
 475COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd,
 476                       compat_ulong_t, arg)
 477{
 478        switch (cmd) {
 479        case F_GETLK64:
 480        case F_SETLK64:
 481        case F_SETLKW64:
 482        case F_OFD_GETLK:
 483        case F_OFD_SETLK:
 484        case F_OFD_SETLKW:
 485                return -EINVAL;
 486        }
 487        return compat_sys_fcntl64(fd, cmd, arg);
 488}
 489
 490COMPAT_SYSCALL_DEFINE2(io_setup, unsigned, nr_reqs, u32 __user *, ctx32p)
 491{
 492        long ret;
 493        aio_context_t ctx64;
 494
 495        mm_segment_t oldfs = get_fs();
 496        if (unlikely(get_user(ctx64, ctx32p)))
 497                return -EFAULT;
 498
 499        set_fs(KERNEL_DS);
 500        /* The __user pointer cast is valid because of the set_fs() */
 501        ret = sys_io_setup(nr_reqs, (aio_context_t __user *) &ctx64);
 502        set_fs(oldfs);
 503        /* truncating is ok because it's a user address */
 504        if (!ret)
 505                ret = put_user((u32) ctx64, ctx32p);
 506        return ret;
 507}
 508
 509COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id,
 510                       compat_long_t, min_nr,
 511                       compat_long_t, nr,
 512                       struct io_event __user *, events,
 513                       struct compat_timespec __user *, timeout)
 514{
 515        struct timespec t;
 516        struct timespec __user *ut = NULL;
 517
 518        if (timeout) {
 519                if (compat_get_timespec(&t, timeout))
 520                        return -EFAULT;
 521
 522                ut = compat_alloc_user_space(sizeof(*ut));
 523                if (copy_to_user(ut, &t, sizeof(t)) )
 524                        return -EFAULT;
 525        } 
 526        return sys_io_getevents(ctx_id, min_nr, nr, events, ut);
 527}
 528
 529/* A write operation does a read from user space and vice versa */
 530#define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
 531
 532ssize_t compat_rw_copy_check_uvector(int type,
 533                const struct compat_iovec __user *uvector, unsigned long nr_segs,
 534                unsigned long fast_segs, struct iovec *fast_pointer,
 535                struct iovec **ret_pointer)
 536{
 537        compat_ssize_t tot_len;
 538        struct iovec *iov = *ret_pointer = fast_pointer;
 539        ssize_t ret = 0;
 540        int seg;
 541
 542        /*
 543         * SuS says "The readv() function *may* fail if the iovcnt argument
 544         * was less than or equal to 0, or greater than {IOV_MAX}.  Linux has
 545         * traditionally returned zero for zero segments, so...
 546         */
 547        if (nr_segs == 0)
 548                goto out;
 549
 550        ret = -EINVAL;
 551        if (nr_segs > UIO_MAXIOV)
 552                goto out;
 553        if (nr_segs > fast_segs) {
 554                ret = -ENOMEM;
 555                iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
 556                if (iov == NULL)
 557                        goto out;
 558        }
 559        *ret_pointer = iov;
 560
 561        ret = -EFAULT;
 562        if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
 563                goto out;
 564
 565        /*
 566         * Single unix specification:
 567         * We should -EINVAL if an element length is not >= 0 and fitting an
 568         * ssize_t.
 569         *
 570         * In Linux, the total length is limited to MAX_RW_COUNT, there is
 571         * no overflow possibility.
 572         */
 573        tot_len = 0;
 574        ret = -EINVAL;
 575        for (seg = 0; seg < nr_segs; seg++) {
 576                compat_uptr_t buf;
 577                compat_ssize_t len;
 578
 579                if (__get_user(len, &uvector->iov_len) ||
 580                   __get_user(buf, &uvector->iov_base)) {
 581                        ret = -EFAULT;
 582                        goto out;
 583                }
 584                if (len < 0)    /* size_t not fitting in compat_ssize_t .. */
 585                        goto out;
 586                if (type >= 0 &&
 587                    !access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
 588                        ret = -EFAULT;
 589                        goto out;
 590                }
 591                if (len > MAX_RW_COUNT - tot_len)
 592                        len = MAX_RW_COUNT - tot_len;
 593                tot_len += len;
 594                iov->iov_base = compat_ptr(buf);
 595                iov->iov_len = (compat_size_t) len;
 596                uvector++;
 597                iov++;
 598        }
 599        ret = tot_len;
 600
 601out:
 602        return ret;
 603}
 604
 605static inline long
 606copy_iocb(long nr, u32 __user *ptr32, struct iocb __user * __user *ptr64)
 607{
 608        compat_uptr_t uptr;
 609        int i;
 610
 611        for (i = 0; i < nr; ++i) {
 612                if (get_user(uptr, ptr32 + i))
 613                        return -EFAULT;
 614                if (put_user(compat_ptr(uptr), ptr64 + i))
 615                        return -EFAULT;
 616        }
 617        return 0;
 618}
 619
 620#define MAX_AIO_SUBMITS         (PAGE_SIZE/sizeof(struct iocb *))
 621
 622COMPAT_SYSCALL_DEFINE3(io_submit, compat_aio_context_t, ctx_id,
 623                       int, nr, u32 __user *, iocb)
 624{
 625        struct iocb __user * __user *iocb64; 
 626        long ret;
 627
 628        if (unlikely(nr < 0))
 629                return -EINVAL;
 630
 631        if (nr > MAX_AIO_SUBMITS)
 632                nr = MAX_AIO_SUBMITS;
 633        
 634        iocb64 = compat_alloc_user_space(nr * sizeof(*iocb64));
 635        ret = copy_iocb(nr, iocb, iocb64);
 636        if (!ret)
 637                ret = do_io_submit(ctx_id, nr, iocb64, 1);
 638        return ret;
 639}
 640
 641struct compat_ncp_mount_data {
 642        compat_int_t version;
 643        compat_uint_t ncp_fd;
 644        __compat_uid_t mounted_uid;
 645        compat_pid_t wdog_pid;
 646        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
 647        compat_uint_t time_out;
 648        compat_uint_t retry_count;
 649        compat_uint_t flags;
 650        __compat_uid_t uid;
 651        __compat_gid_t gid;
 652        compat_mode_t file_mode;
 653        compat_mode_t dir_mode;
 654};
 655
 656struct compat_ncp_mount_data_v4 {
 657        compat_int_t version;
 658        compat_ulong_t flags;
 659        compat_ulong_t mounted_uid;
 660        compat_long_t wdog_pid;
 661        compat_uint_t ncp_fd;
 662        compat_uint_t time_out;
 663        compat_uint_t retry_count;
 664        compat_ulong_t uid;
 665        compat_ulong_t gid;
 666        compat_ulong_t file_mode;
 667        compat_ulong_t dir_mode;
 668};
 669
 670static void *do_ncp_super_data_conv(void *raw_data)
 671{
 672        int version = *(unsigned int *)raw_data;
 673
 674        if (version == 3) {
 675                struct compat_ncp_mount_data *c_n = raw_data;
 676                struct ncp_mount_data *n = raw_data;
 677
 678                n->dir_mode = c_n->dir_mode;
 679                n->file_mode = c_n->file_mode;
 680                n->gid = c_n->gid;
 681                n->uid = c_n->uid;
 682                memmove (n->mounted_vol, c_n->mounted_vol, (sizeof (c_n->mounted_vol) + 3 * sizeof (unsigned int)));
 683                n->wdog_pid = c_n->wdog_pid;
 684                n->mounted_uid = c_n->mounted_uid;
 685        } else if (version == 4) {
 686                struct compat_ncp_mount_data_v4 *c_n = raw_data;
 687                struct ncp_mount_data_v4 *n = raw_data;
 688
 689                n->dir_mode = c_n->dir_mode;
 690                n->file_mode = c_n->file_mode;
 691                n->gid = c_n->gid;
 692                n->uid = c_n->uid;
 693                n->retry_count = c_n->retry_count;
 694                n->time_out = c_n->time_out;
 695                n->ncp_fd = c_n->ncp_fd;
 696                n->wdog_pid = c_n->wdog_pid;
 697                n->mounted_uid = c_n->mounted_uid;
 698                n->flags = c_n->flags;
 699        } else if (version != 5) {
 700                return NULL;
 701        }
 702
 703        return raw_data;
 704}
 705
 706
 707struct compat_nfs_string {
 708        compat_uint_t len;
 709        compat_uptr_t data;
 710};
 711
 712static inline void compat_nfs_string(struct nfs_string *dst,
 713                                     struct compat_nfs_string *src)
 714{
 715        dst->data = compat_ptr(src->data);
 716        dst->len = src->len;
 717}
 718
 719struct compat_nfs4_mount_data_v1 {
 720        compat_int_t version;
 721        compat_int_t flags;
 722        compat_int_t rsize;
 723        compat_int_t wsize;
 724        compat_int_t timeo;
 725        compat_int_t retrans;
 726        compat_int_t acregmin;
 727        compat_int_t acregmax;
 728        compat_int_t acdirmin;
 729        compat_int_t acdirmax;
 730        struct compat_nfs_string client_addr;
 731        struct compat_nfs_string mnt_path;
 732        struct compat_nfs_string hostname;
 733        compat_uint_t host_addrlen;
 734        compat_uptr_t host_addr;
 735        compat_int_t proto;
 736        compat_int_t auth_flavourlen;
 737        compat_uptr_t auth_flavours;
 738};
 739
 740static int do_nfs4_super_data_conv(void *raw_data)
 741{
 742        int version = *(compat_uint_t *) raw_data;
 743
 744        if (version == 1) {
 745                struct compat_nfs4_mount_data_v1 *raw = raw_data;
 746                struct nfs4_mount_data *real = raw_data;
 747
 748                /* copy the fields backwards */
 749                real->auth_flavours = compat_ptr(raw->auth_flavours);
 750                real->auth_flavourlen = raw->auth_flavourlen;
 751                real->proto = raw->proto;
 752                real->host_addr = compat_ptr(raw->host_addr);
 753                real->host_addrlen = raw->host_addrlen;
 754                compat_nfs_string(&real->hostname, &raw->hostname);
 755                compat_nfs_string(&real->mnt_path, &raw->mnt_path);
 756                compat_nfs_string(&real->client_addr, &raw->client_addr);
 757                real->acdirmax = raw->acdirmax;
 758                real->acdirmin = raw->acdirmin;
 759                real->acregmax = raw->acregmax;
 760                real->acregmin = raw->acregmin;
 761                real->retrans = raw->retrans;
 762                real->timeo = raw->timeo;
 763                real->wsize = raw->wsize;
 764                real->rsize = raw->rsize;
 765                real->flags = raw->flags;
 766                real->version = raw->version;
 767        }
 768
 769        return 0;
 770}
 771
 772#define NCPFS_NAME      "ncpfs"
 773#define NFS4_NAME       "nfs4"
 774
 775COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name,
 776                       const char __user *, dir_name,
 777                       const char __user *, type, compat_ulong_t, flags,
 778                       const void __user *, data)
 779{
 780        char *kernel_type;
 781        void *options;
 782        char *kernel_dev;
 783        int retval;
 784
 785        kernel_type = copy_mount_string(type);
 786        retval = PTR_ERR(kernel_type);
 787        if (IS_ERR(kernel_type))
 788                goto out;
 789
 790        kernel_dev = copy_mount_string(dev_name);
 791        retval = PTR_ERR(kernel_dev);
 792        if (IS_ERR(kernel_dev))
 793                goto out1;
 794
 795        options = copy_mount_options(data);
 796        retval = PTR_ERR(options);
 797        if (IS_ERR(options))
 798                goto out2;
 799
 800        if (kernel_type && options) {
 801                if (!strcmp(kernel_type, NCPFS_NAME)) {
 802                        do_ncp_super_data_conv(options);
 803                } else if (!strcmp(kernel_type, NFS4_NAME)) {
 804                        retval = -EINVAL;
 805                        if (do_nfs4_super_data_conv(options))
 806                                goto out3;
 807                }
 808        }
 809
 810        retval = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
 811
 812 out3:
 813        kfree(options);
 814 out2:
 815        kfree(kernel_dev);
 816 out1:
 817        kfree(kernel_type);
 818 out:
 819        return retval;
 820}
 821
 822struct compat_old_linux_dirent {
 823        compat_ulong_t  d_ino;
 824        compat_ulong_t  d_offset;
 825        unsigned short  d_namlen;
 826        char            d_name[1];
 827};
 828
 829struct compat_readdir_callback {
 830        struct dir_context ctx;
 831        struct compat_old_linux_dirent __user *dirent;
 832        int result;
 833};
 834
 835static int compat_fillonedir(struct dir_context *ctx, const char *name,
 836                             int namlen, loff_t offset, u64 ino,
 837                             unsigned int d_type)
 838{
 839        struct compat_readdir_callback *buf =
 840                container_of(ctx, struct compat_readdir_callback, ctx);
 841        struct compat_old_linux_dirent __user *dirent;
 842        compat_ulong_t d_ino;
 843
 844        if (buf->result)
 845                return -EINVAL;
 846        d_ino = ino;
 847        if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
 848                buf->result = -EOVERFLOW;
 849                return -EOVERFLOW;
 850        }
 851        buf->result++;
 852        dirent = buf->dirent;
 853        if (!access_ok(VERIFY_WRITE, dirent,
 854                        (unsigned long)(dirent->d_name + namlen + 1) -
 855                                (unsigned long)dirent))
 856                goto efault;
 857        if (    __put_user(d_ino, &dirent->d_ino) ||
 858                __put_user(offset, &dirent->d_offset) ||
 859                __put_user(namlen, &dirent->d_namlen) ||
 860                __copy_to_user(dirent->d_name, name, namlen) ||
 861                __put_user(0, dirent->d_name + namlen))
 862                goto efault;
 863        return 0;
 864efault:
 865        buf->result = -EFAULT;
 866        return -EFAULT;
 867}
 868
 869COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
 870                struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
 871{
 872        int error;
 873        struct fd f = fdget_pos(fd);
 874        struct compat_readdir_callback buf = {
 875                .ctx.actor = compat_fillonedir,
 876                .dirent = dirent
 877        };
 878
 879        if (!f.file)
 880                return -EBADF;
 881
 882        error = iterate_dir(f.file, &buf.ctx);
 883        if (buf.result)
 884                error = buf.result;
 885
 886        fdput_pos(f);
 887        return error;
 888}
 889
 890struct compat_linux_dirent {
 891        compat_ulong_t  d_ino;
 892        compat_ulong_t  d_off;
 893        unsigned short  d_reclen;
 894        char            d_name[1];
 895};
 896
 897struct compat_getdents_callback {
 898        struct dir_context ctx;
 899        struct compat_linux_dirent __user *current_dir;
 900        struct compat_linux_dirent __user *previous;
 901        int count;
 902        int error;
 903};
 904
 905static int compat_filldir(struct dir_context *ctx, const char *name, int namlen,
 906                loff_t offset, u64 ino, unsigned int d_type)
 907{
 908        struct compat_linux_dirent __user * dirent;
 909        struct compat_getdents_callback *buf =
 910                container_of(ctx, struct compat_getdents_callback, ctx);
 911        compat_ulong_t d_ino;
 912        int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) +
 913                namlen + 2, sizeof(compat_long_t));
 914
 915        buf->error = -EINVAL;   /* only used if we fail.. */
 916        if (reclen > buf->count)
 917                return -EINVAL;
 918        d_ino = ino;
 919        if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
 920                buf->error = -EOVERFLOW;
 921                return -EOVERFLOW;
 922        }
 923        dirent = buf->previous;
 924        if (dirent) {
 925                if (signal_pending(current))
 926                        return -EINTR;
 927                if (__put_user(offset, &dirent->d_off))
 928                        goto efault;
 929        }
 930        dirent = buf->current_dir;
 931        if (__put_user(d_ino, &dirent->d_ino))
 932                goto efault;
 933        if (__put_user(reclen, &dirent->d_reclen))
 934                goto efault;
 935        if (copy_to_user(dirent->d_name, name, namlen))
 936                goto efault;
 937        if (__put_user(0, dirent->d_name + namlen))
 938                goto efault;
 939        if (__put_user(d_type, (char  __user *) dirent + reclen - 1))
 940                goto efault;
 941        buf->previous = dirent;
 942        dirent = (void __user *)dirent + reclen;
 943        buf->current_dir = dirent;
 944        buf->count -= reclen;
 945        return 0;
 946efault:
 947        buf->error = -EFAULT;
 948        return -EFAULT;
 949}
 950
 951COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
 952                struct compat_linux_dirent __user *, dirent, unsigned int, count)
 953{
 954        struct fd f;
 955        struct compat_linux_dirent __user * lastdirent;
 956        struct compat_getdents_callback buf = {
 957                .ctx.actor = compat_filldir,
 958                .current_dir = dirent,
 959                .count = count
 960        };
 961        int error;
 962
 963        if (!access_ok(VERIFY_WRITE, dirent, count))
 964                return -EFAULT;
 965
 966        f = fdget_pos(fd);
 967        if (!f.file)
 968                return -EBADF;
 969
 970        error = iterate_dir(f.file, &buf.ctx);
 971        if (error >= 0)
 972                error = buf.error;
 973        lastdirent = buf.previous;
 974        if (lastdirent) {
 975                if (put_user(buf.ctx.pos, &lastdirent->d_off))
 976                        error = -EFAULT;
 977                else
 978                        error = count - buf.count;
 979        }
 980        fdput_pos(f);
 981        return error;
 982}
 983
 984#ifdef __ARCH_WANT_COMPAT_SYS_GETDENTS64
 985
 986struct compat_getdents_callback64 {
 987        struct dir_context ctx;
 988        struct linux_dirent64 __user *current_dir;
 989        struct linux_dirent64 __user *previous;
 990        int count;
 991        int error;
 992};
 993
 994static int compat_filldir64(struct dir_context *ctx, const char *name,
 995                            int namlen, loff_t offset, u64 ino,
 996                            unsigned int d_type)
 997{
 998        struct linux_dirent64 __user *dirent;
 999        struct compat_getdents_callback64 *buf =
1000                container_of(ctx, struct compat_getdents_callback64, ctx);
1001        int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1,
1002                sizeof(u64));
1003        u64 off;
1004
1005        buf->error = -EINVAL;   /* only used if we fail.. */
1006        if (reclen > buf->count)
1007                return -EINVAL;
1008        dirent = buf->previous;
1009
1010        if (dirent) {
1011                if (signal_pending(current))
1012                        return -EINTR;
1013                if (__put_user_unaligned(offset, &dirent->d_off))
1014                        goto efault;
1015        }
1016        dirent = buf->current_dir;
1017        if (__put_user_unaligned(ino, &dirent->d_ino))
1018                goto efault;
1019        off = 0;
1020        if (__put_user_unaligned(off, &dirent->d_off))
1021                goto efault;
1022        if (__put_user(reclen, &dirent->d_reclen))
1023                goto efault;
1024        if (__put_user(d_type, &dirent->d_type))
1025                goto efault;
1026        if (copy_to_user(dirent->d_name, name, namlen))
1027                goto efault;
1028        if (__put_user(0, dirent->d_name + namlen))
1029                goto efault;
1030        buf->previous = dirent;
1031        dirent = (void __user *)dirent + reclen;
1032        buf->current_dir = dirent;
1033        buf->count -= reclen;
1034        return 0;
1035efault:
1036        buf->error = -EFAULT;
1037        return -EFAULT;
1038}
1039
1040COMPAT_SYSCALL_DEFINE3(getdents64, unsigned int, fd,
1041                struct linux_dirent64 __user *, dirent, unsigned int, count)
1042{
1043        struct fd f;
1044        struct linux_dirent64 __user * lastdirent;
1045        struct compat_getdents_callback64 buf = {
1046                .ctx.actor = compat_filldir64,
1047                .current_dir = dirent,
1048                .count = count
1049        };
1050        int error;
1051
1052        if (!access_ok(VERIFY_WRITE, dirent, count))
1053                return -EFAULT;
1054
1055        f = fdget_pos(fd);
1056        if (!f.file)
1057                return -EBADF;
1058
1059        error = iterate_dir(f.file, &buf.ctx);
1060        if (error >= 0)
1061                error = buf.error;
1062        lastdirent = buf.previous;
1063        if (lastdirent) {
1064                typeof(lastdirent->d_off) d_off = buf.ctx.pos;
1065                if (__put_user_unaligned(d_off, &lastdirent->d_off))
1066                        error = -EFAULT;
1067                else
1068                        error = count - buf.count;
1069        }
1070        fdput_pos(f);
1071        return error;
1072}
1073#endif /* __ARCH_WANT_COMPAT_SYS_GETDENTS64 */
1074
1075/*
1076 * Exactly like fs/open.c:sys_open(), except that it doesn't set the
1077 * O_LARGEFILE flag.
1078 */
1079COMPAT_SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
1080{
1081        return do_sys_open(AT_FDCWD, filename, flags, mode);
1082}
1083
1084/*
1085 * Exactly like fs/open.c:sys_openat(), except that it doesn't set the
1086 * O_LARGEFILE flag.
1087 */
1088COMPAT_SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, umode_t, mode)
1089{
1090        return do_sys_open(dfd, filename, flags, mode);
1091}
1092
1093#define __COMPAT_NFDBITS       (8 * sizeof(compat_ulong_t))
1094
1095static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,
1096                                      int timeval, int ret)
1097{
1098        struct timespec ts;
1099
1100        if (!p)
1101                return ret;
1102
1103        if (current->personality & STICKY_TIMEOUTS)
1104                goto sticky;
1105
1106        /* No update for zero timeout */
1107        if (!end_time->tv_sec && !end_time->tv_nsec)
1108                return ret;
1109
1110        ktime_get_ts(&ts);
1111        ts = timespec_sub(*end_time, ts);
1112        if (ts.tv_sec < 0)
1113                ts.tv_sec = ts.tv_nsec = 0;
1114
1115        if (timeval) {
1116                struct compat_timeval rtv;
1117
1118                rtv.tv_sec = ts.tv_sec;
1119                rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
1120
1121                if (!copy_to_user(p, &rtv, sizeof(rtv)))
1122                        return ret;
1123        } else {
1124                struct compat_timespec rts;
1125
1126                rts.tv_sec = ts.tv_sec;
1127                rts.tv_nsec = ts.tv_nsec;
1128
1129                if (!copy_to_user(p, &rts, sizeof(rts)))
1130                        return ret;
1131        }
1132        /*
1133         * If an application puts its timeval in read-only memory, we
1134         * don't want the Linux-specific update to the timeval to
1135         * cause a fault after the select has completed
1136         * successfully. However, because we're not updating the
1137         * timeval, we can't restart the system call.
1138         */
1139
1140sticky:
1141        if (ret == -ERESTARTNOHAND)
1142                ret = -EINTR;
1143        return ret;
1144}
1145
1146/*
1147 * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
1148 * 64-bit unsigned longs.
1149 */
1150static
1151int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1152                        unsigned long *fdset)
1153{
1154        nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
1155        if (ufdset) {
1156                unsigned long odd;
1157
1158                if (!access_ok(VERIFY_WRITE, ufdset, nr*sizeof(compat_ulong_t)))
1159                        return -EFAULT;
1160
1161                odd = nr & 1UL;
1162                nr &= ~1UL;
1163                while (nr) {
1164                        unsigned long h, l;
1165                        if (__get_user(l, ufdset) || __get_user(h, ufdset+1))
1166                                return -EFAULT;
1167                        ufdset += 2;
1168                        *fdset++ = h << 32 | l;
1169                        nr -= 2;
1170                }
1171                if (odd && __get_user(*fdset, ufdset))
1172                        return -EFAULT;
1173        } else {
1174                /* Tricky, must clear full unsigned long in the
1175                 * kernel fdset at the end, this makes sure that
1176                 * actually happens.
1177                 */
1178                memset(fdset, 0, ((nr + 1) & ~1)*sizeof(compat_ulong_t));
1179        }
1180        return 0;
1181}
1182
1183static
1184int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1185                      unsigned long *fdset)
1186{
1187        unsigned long odd;
1188        nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
1189
1190        if (!ufdset)
1191                return 0;
1192
1193        odd = nr & 1UL;
1194        nr &= ~1UL;
1195        while (nr) {
1196                unsigned long h, l;
1197                l = *fdset++;
1198                h = l >> 32;
1199                if (__put_user(l, ufdset) || __put_user(h, ufdset+1))
1200                        return -EFAULT;
1201                ufdset += 2;
1202                nr -= 2;
1203        }
1204        if (odd && __put_user(*fdset, ufdset))
1205                return -EFAULT;
1206        return 0;
1207}
1208
1209
1210/*
1211 * This is a virtual copy of sys_select from fs/select.c and probably
1212 * should be compared to it from time to time
1213 */
1214
1215/*
1216 * We can actually return ERESTARTSYS instead of EINTR, but I'd
1217 * like to be certain this leads to no problems. So I return
1218 * EINTR just for safety.
1219 *
1220 * Update: ERESTARTSYS breaks at least the xview clock binary, so
1221 * I'm trying ERESTARTNOHAND which restart only when you want to.
1222 */
1223int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1224        compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1225        struct timespec *end_time)
1226{
1227        fd_set_bits fds;
1228        void *bits;
1229        int size, max_fds, ret = -EINVAL;
1230        struct fdtable *fdt;
1231        long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
1232
1233        if (n < 0)
1234                goto out_nofds;
1235
1236        /* max_fds can increase, so grab it once to avoid race */
1237        rcu_read_lock();
1238        fdt = files_fdtable(current->files);
1239        max_fds = fdt->max_fds;
1240        rcu_read_unlock();
1241        if (n > max_fds)
1242                n = max_fds;
1243
1244        /*
1245         * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
1246         * since we used fdset we need to allocate memory in units of
1247         * long-words.
1248         */
1249        size = FDS_BYTES(n);
1250        bits = stack_fds;
1251        if (size > sizeof(stack_fds) / 6) {
1252                bits = kmalloc(6 * size, GFP_KERNEL);
1253                ret = -ENOMEM;
1254                if (!bits)
1255                        goto out_nofds;
1256        }
1257        fds.in      = (unsigned long *)  bits;
1258        fds.out     = (unsigned long *) (bits +   size);
1259        fds.ex      = (unsigned long *) (bits + 2*size);
1260        fds.res_in  = (unsigned long *) (bits + 3*size);
1261        fds.res_out = (unsigned long *) (bits + 4*size);
1262        fds.res_ex  = (unsigned long *) (bits + 5*size);
1263
1264        if ((ret = compat_get_fd_set(n, inp, fds.in)) ||
1265            (ret = compat_get_fd_set(n, outp, fds.out)) ||
1266            (ret = compat_get_fd_set(n, exp, fds.ex)))
1267                goto out;
1268        zero_fd_set(n, fds.res_in);
1269        zero_fd_set(n, fds.res_out);
1270        zero_fd_set(n, fds.res_ex);
1271
1272        ret = do_select(n, &fds, end_time);
1273
1274        if (ret < 0)
1275                goto out;
1276        if (!ret) {
1277                ret = -ERESTARTNOHAND;
1278                if (signal_pending(current))
1279                        goto out;
1280                ret = 0;
1281        }
1282
1283        if (compat_set_fd_set(n, inp, fds.res_in) ||
1284            compat_set_fd_set(n, outp, fds.res_out) ||
1285            compat_set_fd_set(n, exp, fds.res_ex))
1286                ret = -EFAULT;
1287out:
1288        if (bits != stack_fds)
1289                kfree(bits);
1290out_nofds:
1291        return ret;
1292}
1293
1294COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp,
1295        compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
1296        struct compat_timeval __user *, tvp)
1297{
1298        struct timespec end_time, *to = NULL;
1299        struct compat_timeval tv;
1300        int ret;
1301
1302        if (tvp) {
1303                if (copy_from_user(&tv, tvp, sizeof(tv)))
1304                        return -EFAULT;
1305
1306                to = &end_time;
1307                if (poll_select_set_timeout(to,
1308                                tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
1309                                (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
1310                        return -EINVAL;
1311        }
1312
1313        ret = compat_core_sys_select(n, inp, outp, exp, to);
1314        ret = poll_select_copy_remaining(&end_time, tvp, 1, ret);
1315
1316        return ret;
1317}
1318
1319struct compat_sel_arg_struct {
1320        compat_ulong_t n;
1321        compat_uptr_t inp;
1322        compat_uptr_t outp;
1323        compat_uptr_t exp;
1324        compat_uptr_t tvp;
1325};
1326
1327COMPAT_SYSCALL_DEFINE1(old_select, struct compat_sel_arg_struct __user *, arg)
1328{
1329        struct compat_sel_arg_struct a;
1330
1331        if (copy_from_user(&a, arg, sizeof(a)))
1332                return -EFAULT;
1333        return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp),
1334                                 compat_ptr(a.exp), compat_ptr(a.tvp));
1335}
1336
1337static long do_compat_pselect(int n, compat_ulong_t __user *inp,
1338        compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1339        struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
1340        compat_size_t sigsetsize)
1341{
1342        compat_sigset_t ss32;
1343        sigset_t ksigmask, sigsaved;
1344        struct compat_timespec ts;
1345        struct timespec end_time, *to = NULL;
1346        int ret;
1347
1348        if (tsp) {
1349                if (copy_from_user(&ts, tsp, sizeof(ts)))
1350                        return -EFAULT;
1351
1352                to = &end_time;
1353                if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1354                        return -EINVAL;
1355        }
1356
1357        if (sigmask) {
1358                if (sigsetsize != sizeof(compat_sigset_t))
1359                        return -EINVAL;
1360                if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1361                        return -EFAULT;
1362                sigset_from_compat(&ksigmask, &ss32);
1363
1364                sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1365                sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1366        }
1367
1368        ret = compat_core_sys_select(n, inp, outp, exp, to);
1369        ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1370
1371        if (ret == -ERESTARTNOHAND) {
1372                /*
1373                 * Don't restore the signal mask yet. Let do_signal() deliver
1374                 * the signal on the way back to userspace, before the signal
1375                 * mask is restored.
1376                 */
1377                if (sigmask) {
1378                        memcpy(&current->saved_sigmask, &sigsaved,
1379                                        sizeof(sigsaved));
1380                        set_restore_sigmask();
1381                }
1382        } else if (sigmask)
1383                sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1384
1385        return ret;
1386}
1387
1388COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp,
1389        compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
1390        struct compat_timespec __user *, tsp, void __user *, sig)
1391{
1392        compat_size_t sigsetsize = 0;
1393        compat_uptr_t up = 0;
1394
1395        if (sig) {
1396                if (!access_ok(VERIFY_READ, sig,
1397                                sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
1398                        __get_user(up, (compat_uptr_t __user *)sig) ||
1399                        __get_user(sigsetsize,
1400                                (compat_size_t __user *)(sig+sizeof(up))))
1401                        return -EFAULT;
1402        }
1403        return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up),
1404                                 sigsetsize);
1405}
1406
1407COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
1408        unsigned int,  nfds, struct compat_timespec __user *, tsp,
1409        const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)
1410{
1411        compat_sigset_t ss32;
1412        sigset_t ksigmask, sigsaved;
1413        struct compat_timespec ts;
1414        struct timespec end_time, *to = NULL;
1415        int ret;
1416
1417        if (tsp) {
1418                if (copy_from_user(&ts, tsp, sizeof(ts)))
1419                        return -EFAULT;
1420
1421                to = &end_time;
1422                if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1423                        return -EINVAL;
1424        }
1425
1426        if (sigmask) {
1427                if (sigsetsize != sizeof(compat_sigset_t))
1428                        return -EINVAL;
1429                if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1430                        return -EFAULT;
1431                sigset_from_compat(&ksigmask, &ss32);
1432
1433                sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1434                sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1435        }
1436
1437        ret = do_sys_poll(ufds, nfds, to);
1438
1439        /* We can restart this syscall, usually */
1440        if (ret == -EINTR) {
1441                /*
1442                 * Don't restore the signal mask yet. Let do_signal() deliver
1443                 * the signal on the way back to userspace, before the signal
1444                 * mask is restored.
1445                 */
1446                if (sigmask) {
1447                        memcpy(&current->saved_sigmask, &sigsaved,
1448                                sizeof(sigsaved));
1449                        set_restore_sigmask();
1450                }
1451                ret = -ERESTARTNOHAND;
1452        } else if (sigmask)
1453                sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1454
1455        ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1456
1457        return ret;
1458}
1459
1460#ifdef CONFIG_FHANDLE
1461/*
1462 * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
1463 * doesn't set the O_LARGEFILE flag.
1464 */
1465COMPAT_SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
1466                             struct file_handle __user *, handle, int, flags)
1467{
1468        return do_handle_open(mountdirfd, handle, flags);
1469}
1470#endif
1471