Back to home page

LXR

 
 

    


0001 /*
0002  *  linux/fs/compat.c
0003  *
0004  *  Kernel compatibililty routines for e.g. 32 bit syscall support
0005  *  on 64 bit kernels.
0006  *
0007  *  Copyright (C) 2002       Stephen Rothwell, IBM Corporation
0008  *  Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
0009  *  Copyright (C) 1998       Eddie C. Dost  (ecd@skynet.be)
0010  *  Copyright (C) 2001,2002  Andi Kleen, SuSE Labs 
0011  *  Copyright (C) 2003       Pavel Machek (pavel@ucw.cz)
0012  *
0013  *  This program is free software; you can redistribute it and/or modify
0014  *  it under the terms of the GNU General Public License version 2 as
0015  *  published by the Free Software Foundation.
0016  */
0017 
0018 #include <linux/stddef.h>
0019 #include <linux/kernel.h>
0020 #include <linux/linkage.h>
0021 #include <linux/compat.h>
0022 #include <linux/errno.h>
0023 #include <linux/time.h>
0024 #include <linux/fs.h>
0025 #include <linux/fcntl.h>
0026 #include <linux/namei.h>
0027 #include <linux/file.h>
0028 #include <linux/fdtable.h>
0029 #include <linux/vfs.h>
0030 #include <linux/ioctl.h>
0031 #include <linux/init.h>
0032 #include <linux/ncp_mount.h>
0033 #include <linux/nfs4_mount.h>
0034 #include <linux/syscalls.h>
0035 #include <linux/ctype.h>
0036 #include <linux/dirent.h>
0037 #include <linux/fsnotify.h>
0038 #include <linux/highuid.h>
0039 #include <linux/personality.h>
0040 #include <linux/rwsem.h>
0041 #include <linux/tsacct_kern.h>
0042 #include <linux/security.h>
0043 #include <linux/highmem.h>
0044 #include <linux/signal.h>
0045 #include <linux/poll.h>
0046 #include <linux/mm.h>
0047 #include <linux/fs_struct.h>
0048 #include <linux/slab.h>
0049 #include <linux/pagemap.h>
0050 #include <linux/aio.h>
0051 
0052 #include <linux/uaccess.h>
0053 #include <asm/mmu_context.h>
0054 #include <asm/ioctls.h>
0055 #include "internal.h"
0056 
0057 /*
0058  * Not all architectures have sys_utime, so implement this in terms
0059  * of sys_utimes.
0060  */
0061 COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename,
0062                struct compat_utimbuf __user *, t)
0063 {
0064     struct timespec tv[2];
0065 
0066     if (t) {
0067         if (get_user(tv[0].tv_sec, &t->actime) ||
0068             get_user(tv[1].tv_sec, &t->modtime))
0069             return -EFAULT;
0070         tv[0].tv_nsec = 0;
0071         tv[1].tv_nsec = 0;
0072     }
0073     return do_utimes(AT_FDCWD, filename, t ? tv : NULL, 0);
0074 }
0075 
0076 COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags)
0077 {
0078     struct timespec tv[2];
0079 
0080     if  (t) {
0081         if (compat_get_timespec(&tv[0], &t[0]) ||
0082             compat_get_timespec(&tv[1], &t[1]))
0083             return -EFAULT;
0084 
0085         if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT)
0086             return 0;
0087     }
0088     return do_utimes(dfd, filename, t ? tv : NULL, flags);
0089 }
0090 
0091 COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t)
0092 {
0093     struct timespec tv[2];
0094 
0095     if (t) {
0096         if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
0097             get_user(tv[0].tv_nsec, &t[0].tv_usec) ||
0098             get_user(tv[1].tv_sec, &t[1].tv_sec) ||
0099             get_user(tv[1].tv_nsec, &t[1].tv_usec))
0100             return -EFAULT;
0101         if (tv[0].tv_nsec >= 1000000 || tv[0].tv_nsec < 0 ||
0102             tv[1].tv_nsec >= 1000000 || tv[1].tv_nsec < 0)
0103             return -EINVAL;
0104         tv[0].tv_nsec *= 1000;
0105         tv[1].tv_nsec *= 1000;
0106     }
0107     return do_utimes(dfd, filename, t ? tv : NULL, 0);
0108 }
0109 
0110 COMPAT_SYSCALL_DEFINE2(utimes, const char __user *, filename, struct compat_timeval __user *, t)
0111 {
0112     return compat_sys_futimesat(AT_FDCWD, filename, t);
0113 }
0114 
0115 static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
0116 {
0117     struct compat_stat tmp;
0118 
0119     if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
0120         return -EOVERFLOW;
0121 
0122     memset(&tmp, 0, sizeof(tmp));
0123     tmp.st_dev = old_encode_dev(stat->dev);
0124     tmp.st_ino = stat->ino;
0125     if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
0126         return -EOVERFLOW;
0127     tmp.st_mode = stat->mode;
0128     tmp.st_nlink = stat->nlink;
0129     if (tmp.st_nlink != stat->nlink)
0130         return -EOVERFLOW;
0131     SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
0132     SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
0133     tmp.st_rdev = old_encode_dev(stat->rdev);
0134     if ((u64) stat->size > MAX_NON_LFS)
0135         return -EOVERFLOW;
0136     tmp.st_size = stat->size;
0137     tmp.st_atime = stat->atime.tv_sec;
0138     tmp.st_atime_nsec = stat->atime.tv_nsec;
0139     tmp.st_mtime = stat->mtime.tv_sec;
0140     tmp.st_mtime_nsec = stat->mtime.tv_nsec;
0141     tmp.st_ctime = stat->ctime.tv_sec;
0142     tmp.st_ctime_nsec = stat->ctime.tv_nsec;
0143     tmp.st_blocks = stat->blocks;
0144     tmp.st_blksize = stat->blksize;
0145     return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
0146 }
0147 
0148 COMPAT_SYSCALL_DEFINE2(newstat, const char __user *, filename,
0149                struct compat_stat __user *, statbuf)
0150 {
0151     struct kstat stat;
0152     int error;
0153 
0154     error = vfs_stat(filename, &stat);
0155     if (error)
0156         return error;
0157     return cp_compat_stat(&stat, statbuf);
0158 }
0159 
0160 COMPAT_SYSCALL_DEFINE2(newlstat, const char __user *, filename,
0161                struct compat_stat __user *, statbuf)
0162 {
0163     struct kstat stat;
0164     int error;
0165 
0166     error = vfs_lstat(filename, &stat);
0167     if (error)
0168         return error;
0169     return cp_compat_stat(&stat, statbuf);
0170 }
0171 
0172 #ifndef __ARCH_WANT_STAT64
0173 COMPAT_SYSCALL_DEFINE4(newfstatat, unsigned int, dfd,
0174                const char __user *, filename,
0175                struct compat_stat __user *, statbuf, int, flag)
0176 {
0177     struct kstat stat;
0178     int error;
0179 
0180     error = vfs_fstatat(dfd, filename, &stat, flag);
0181     if (error)
0182         return error;
0183     return cp_compat_stat(&stat, statbuf);
0184 }
0185 #endif
0186 
0187 COMPAT_SYSCALL_DEFINE2(newfstat, unsigned int, fd,
0188                struct compat_stat __user *, statbuf)
0189 {
0190     struct kstat stat;
0191     int error = vfs_fstat(fd, &stat);
0192 
0193     if (!error)
0194         error = cp_compat_stat(&stat, statbuf);
0195     return error;
0196 }
0197 
0198 static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf)
0199 {
0200     
0201     if (sizeof ubuf->f_blocks == 4) {
0202         if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail |
0203              kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL)
0204             return -EOVERFLOW;
0205         /* f_files and f_ffree may be -1; it's okay
0206          * to stuff that into 32 bits */
0207         if (kbuf->f_files != 0xffffffffffffffffULL
0208          && (kbuf->f_files & 0xffffffff00000000ULL))
0209             return -EOVERFLOW;
0210         if (kbuf->f_ffree != 0xffffffffffffffffULL
0211          && (kbuf->f_ffree & 0xffffffff00000000ULL))
0212             return -EOVERFLOW;
0213     }
0214     if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
0215         __put_user(kbuf->f_type, &ubuf->f_type) ||
0216         __put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
0217         __put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
0218         __put_user(kbuf->f_bfree, &ubuf->f_bfree) ||
0219         __put_user(kbuf->f_bavail, &ubuf->f_bavail) ||
0220         __put_user(kbuf->f_files, &ubuf->f_files) ||
0221         __put_user(kbuf->f_ffree, &ubuf->f_ffree) ||
0222         __put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
0223         __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
0224         __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
0225         __put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
0226         __put_user(kbuf->f_flags, &ubuf->f_flags) ||
0227         __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare)))
0228         return -EFAULT;
0229     return 0;
0230 }
0231 
0232 /*
0233  * The following statfs calls are copies of code from fs/statfs.c and
0234  * should be checked against those from time to time
0235  */
0236 COMPAT_SYSCALL_DEFINE2(statfs, const char __user *, pathname, struct compat_statfs __user *, buf)
0237 {
0238     struct kstatfs tmp;
0239     int error = user_statfs(pathname, &tmp);
0240     if (!error)
0241         error = put_compat_statfs(buf, &tmp);
0242     return error;
0243 }
0244 
0245 COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, buf)
0246 {
0247     struct kstatfs tmp;
0248     int error = fd_statfs(fd, &tmp);
0249     if (!error)
0250         error = put_compat_statfs(buf, &tmp);
0251     return error;
0252 }
0253 
0254 static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf)
0255 {
0256     if (sizeof(ubuf->f_bsize) == 4) {
0257         if ((kbuf->f_type | kbuf->f_bsize | kbuf->f_namelen |
0258              kbuf->f_frsize | kbuf->f_flags) & 0xffffffff00000000ULL)
0259             return -EOVERFLOW;
0260         /* f_files and f_ffree may be -1; it's okay
0261          * to stuff that into 32 bits */
0262         if (kbuf->f_files != 0xffffffffffffffffULL
0263          && (kbuf->f_files & 0xffffffff00000000ULL))
0264             return -EOVERFLOW;
0265         if (kbuf->f_ffree != 0xffffffffffffffffULL
0266          && (kbuf->f_ffree & 0xffffffff00000000ULL))
0267             return -EOVERFLOW;
0268     }
0269     if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
0270         __put_user(kbuf->f_type, &ubuf->f_type) ||
0271         __put_user(kbuf->f_bsize, &ubuf->f_bsize) ||
0272         __put_user(kbuf->f_blocks, &ubuf->f_blocks) ||
0273         __put_user(kbuf->f_bfree, &ubuf->f_bfree) ||
0274         __put_user(kbuf->f_bavail, &ubuf->f_bavail) ||
0275         __put_user(kbuf->f_files, &ubuf->f_files) ||
0276         __put_user(kbuf->f_ffree, &ubuf->f_ffree) ||
0277         __put_user(kbuf->f_namelen, &ubuf->f_namelen) ||
0278         __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) ||
0279         __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) ||
0280         __put_user(kbuf->f_frsize, &ubuf->f_frsize) ||
0281         __put_user(kbuf->f_flags, &ubuf->f_flags) ||
0282         __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare)))
0283         return -EFAULT;
0284     return 0;
0285 }
0286 
0287 COMPAT_SYSCALL_DEFINE3(statfs64, const char __user *, pathname, compat_size_t, sz, struct compat_statfs64 __user *, buf)
0288 {
0289     struct kstatfs tmp;
0290     int error;
0291 
0292     if (sz != sizeof(*buf))
0293         return -EINVAL;
0294 
0295     error = user_statfs(pathname, &tmp);
0296     if (!error)
0297         error = put_compat_statfs64(buf, &tmp);
0298     return error;
0299 }
0300 
0301 COMPAT_SYSCALL_DEFINE3(fstatfs64, unsigned int, fd, compat_size_t, sz, struct compat_statfs64 __user *, buf)
0302 {
0303     struct kstatfs tmp;
0304     int error;
0305 
0306     if (sz != sizeof(*buf))
0307         return -EINVAL;
0308 
0309     error = fd_statfs(fd, &tmp);
0310     if (!error)
0311         error = put_compat_statfs64(buf, &tmp);
0312     return error;
0313 }
0314 
0315 /*
0316  * This is a copy of sys_ustat, just dealing with a structure layout.
0317  * Given how simple this syscall is that apporach is more maintainable
0318  * than the various conversion hacks.
0319  */
0320 COMPAT_SYSCALL_DEFINE2(ustat, unsigned, dev, struct compat_ustat __user *, u)
0321 {
0322     struct compat_ustat tmp;
0323     struct kstatfs sbuf;
0324     int err = vfs_ustat(new_decode_dev(dev), &sbuf);
0325     if (err)
0326         return err;
0327 
0328     memset(&tmp, 0, sizeof(struct compat_ustat));
0329     tmp.f_tfree = sbuf.f_bfree;
0330     tmp.f_tinode = sbuf.f_ffree;
0331     if (copy_to_user(u, &tmp, sizeof(struct compat_ustat)))
0332         return -EFAULT;
0333     return 0;
0334 }
0335 
0336 static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
0337 {
0338     if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
0339         __get_user(kfl->l_type, &ufl->l_type) ||
0340         __get_user(kfl->l_whence, &ufl->l_whence) ||
0341         __get_user(kfl->l_start, &ufl->l_start) ||
0342         __get_user(kfl->l_len, &ufl->l_len) ||
0343         __get_user(kfl->l_pid, &ufl->l_pid))
0344         return -EFAULT;
0345     return 0;
0346 }
0347 
0348 static int put_compat_flock(struct flock *kfl, struct compat_flock __user *ufl)
0349 {
0350     if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
0351         __put_user(kfl->l_type, &ufl->l_type) ||
0352         __put_user(kfl->l_whence, &ufl->l_whence) ||
0353         __put_user(kfl->l_start, &ufl->l_start) ||
0354         __put_user(kfl->l_len, &ufl->l_len) ||
0355         __put_user(kfl->l_pid, &ufl->l_pid))
0356         return -EFAULT;
0357     return 0;
0358 }
0359 
0360 #ifndef HAVE_ARCH_GET_COMPAT_FLOCK64
0361 static int get_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl)
0362 {
0363     if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
0364         __get_user(kfl->l_type, &ufl->l_type) ||
0365         __get_user(kfl->l_whence, &ufl->l_whence) ||
0366         __get_user(kfl->l_start, &ufl->l_start) ||
0367         __get_user(kfl->l_len, &ufl->l_len) ||
0368         __get_user(kfl->l_pid, &ufl->l_pid))
0369         return -EFAULT;
0370     return 0;
0371 }
0372 #endif
0373 
0374 #ifndef HAVE_ARCH_PUT_COMPAT_FLOCK64
0375 static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl)
0376 {
0377     if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
0378         __put_user(kfl->l_type, &ufl->l_type) ||
0379         __put_user(kfl->l_whence, &ufl->l_whence) ||
0380         __put_user(kfl->l_start, &ufl->l_start) ||
0381         __put_user(kfl->l_len, &ufl->l_len) ||
0382         __put_user(kfl->l_pid, &ufl->l_pid))
0383         return -EFAULT;
0384     return 0;
0385 }
0386 #endif
0387 
0388 static unsigned int
0389 convert_fcntl_cmd(unsigned int cmd)
0390 {
0391     switch (cmd) {
0392     case F_GETLK64:
0393         return F_GETLK;
0394     case F_SETLK64:
0395         return F_SETLK;
0396     case F_SETLKW64:
0397         return F_SETLKW;
0398     }
0399 
0400     return cmd;
0401 }
0402 
0403 COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
0404                compat_ulong_t, arg)
0405 {
0406     mm_segment_t old_fs;
0407     struct flock f;
0408     long ret;
0409     unsigned int conv_cmd;
0410 
0411     switch (cmd) {
0412     case F_GETLK:
0413     case F_SETLK:
0414     case F_SETLKW:
0415         ret = get_compat_flock(&f, compat_ptr(arg));
0416         if (ret != 0)
0417             break;
0418         old_fs = get_fs();
0419         set_fs(KERNEL_DS);
0420         ret = sys_fcntl(fd, cmd, (unsigned long)&f);
0421         set_fs(old_fs);
0422         if (cmd == F_GETLK && ret == 0) {
0423             /* GETLK was successful and we need to return the data...
0424              * but it needs to fit in the compat structure.
0425              * l_start shouldn't be too big, unless the original
0426              * start + end is greater than COMPAT_OFF_T_MAX, in which
0427              * case the app was asking for trouble, so we return
0428              * -EOVERFLOW in that case.
0429              * l_len could be too big, in which case we just truncate it,
0430              * and only allow the app to see that part of the conflicting
0431              * lock that might make sense to it anyway
0432              */
0433 
0434             if (f.l_start > COMPAT_OFF_T_MAX)
0435                 ret = -EOVERFLOW;
0436             if (f.l_len > COMPAT_OFF_T_MAX)
0437                 f.l_len = COMPAT_OFF_T_MAX;
0438             if (ret == 0)
0439                 ret = put_compat_flock(&f, compat_ptr(arg));
0440         }
0441         break;
0442 
0443     case F_GETLK64:
0444     case F_SETLK64:
0445     case F_SETLKW64:
0446     case F_OFD_GETLK:
0447     case F_OFD_SETLK:
0448     case F_OFD_SETLKW:
0449         ret = get_compat_flock64(&f, compat_ptr(arg));
0450         if (ret != 0)
0451             break;
0452         old_fs = get_fs();
0453         set_fs(KERNEL_DS);
0454         conv_cmd = convert_fcntl_cmd(cmd);
0455         ret = sys_fcntl(fd, conv_cmd, (unsigned long)&f);
0456         set_fs(old_fs);
0457         if ((conv_cmd == F_GETLK || conv_cmd == F_OFD_GETLK) && ret == 0) {
0458             /* need to return lock information - see above for commentary */
0459             if (f.l_start > COMPAT_LOFF_T_MAX)
0460                 ret = -EOVERFLOW;
0461             if (f.l_len > COMPAT_LOFF_T_MAX)
0462                 f.l_len = COMPAT_LOFF_T_MAX;
0463             if (ret == 0)
0464                 ret = put_compat_flock64(&f, compat_ptr(arg));
0465         }
0466         break;
0467 
0468     default:
0469         ret = sys_fcntl(fd, cmd, arg);
0470         break;
0471     }
0472     return ret;
0473 }
0474 
0475 COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd,
0476                compat_ulong_t, arg)
0477 {
0478     switch (cmd) {
0479     case F_GETLK64:
0480     case F_SETLK64:
0481     case F_SETLKW64:
0482     case F_OFD_GETLK:
0483     case F_OFD_SETLK:
0484     case F_OFD_SETLKW:
0485         return -EINVAL;
0486     }
0487     return compat_sys_fcntl64(fd, cmd, arg);
0488 }
0489 
0490 /* A write operation does a read from user space and vice versa */
0491 #define vrfy_dir(type) ((type) == READ ? VERIFY_WRITE : VERIFY_READ)
0492 
0493 ssize_t compat_rw_copy_check_uvector(int type,
0494         const struct compat_iovec __user *uvector, unsigned long nr_segs,
0495         unsigned long fast_segs, struct iovec *fast_pointer,
0496         struct iovec **ret_pointer)
0497 {
0498     compat_ssize_t tot_len;
0499     struct iovec *iov = *ret_pointer = fast_pointer;
0500     ssize_t ret = 0;
0501     int seg;
0502 
0503     /*
0504      * SuS says "The readv() function *may* fail if the iovcnt argument
0505      * was less than or equal to 0, or greater than {IOV_MAX}.  Linux has
0506      * traditionally returned zero for zero segments, so...
0507      */
0508     if (nr_segs == 0)
0509         goto out;
0510 
0511     ret = -EINVAL;
0512     if (nr_segs > UIO_MAXIOV)
0513         goto out;
0514     if (nr_segs > fast_segs) {
0515         ret = -ENOMEM;
0516         iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
0517         if (iov == NULL)
0518             goto out;
0519     }
0520     *ret_pointer = iov;
0521 
0522     ret = -EFAULT;
0523     if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
0524         goto out;
0525 
0526     /*
0527      * Single unix specification:
0528      * We should -EINVAL if an element length is not >= 0 and fitting an
0529      * ssize_t.
0530      *
0531      * In Linux, the total length is limited to MAX_RW_COUNT, there is
0532      * no overflow possibility.
0533      */
0534     tot_len = 0;
0535     ret = -EINVAL;
0536     for (seg = 0; seg < nr_segs; seg++) {
0537         compat_uptr_t buf;
0538         compat_ssize_t len;
0539 
0540         if (__get_user(len, &uvector->iov_len) ||
0541            __get_user(buf, &uvector->iov_base)) {
0542             ret = -EFAULT;
0543             goto out;
0544         }
0545         if (len < 0)    /* size_t not fitting in compat_ssize_t .. */
0546             goto out;
0547         if (type >= 0 &&
0548             !access_ok(vrfy_dir(type), compat_ptr(buf), len)) {
0549             ret = -EFAULT;
0550             goto out;
0551         }
0552         if (len > MAX_RW_COUNT - tot_len)
0553             len = MAX_RW_COUNT - tot_len;
0554         tot_len += len;
0555         iov->iov_base = compat_ptr(buf);
0556         iov->iov_len = (compat_size_t) len;
0557         uvector++;
0558         iov++;
0559     }
0560     ret = tot_len;
0561 
0562 out:
0563     return ret;
0564 }
0565 
0566 struct compat_ncp_mount_data {
0567     compat_int_t version;
0568     compat_uint_t ncp_fd;
0569     __compat_uid_t mounted_uid;
0570     compat_pid_t wdog_pid;
0571     unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
0572     compat_uint_t time_out;
0573     compat_uint_t retry_count;
0574     compat_uint_t flags;
0575     __compat_uid_t uid;
0576     __compat_gid_t gid;
0577     compat_mode_t file_mode;
0578     compat_mode_t dir_mode;
0579 };
0580 
0581 struct compat_ncp_mount_data_v4 {
0582     compat_int_t version;
0583     compat_ulong_t flags;
0584     compat_ulong_t mounted_uid;
0585     compat_long_t wdog_pid;
0586     compat_uint_t ncp_fd;
0587     compat_uint_t time_out;
0588     compat_uint_t retry_count;
0589     compat_ulong_t uid;
0590     compat_ulong_t gid;
0591     compat_ulong_t file_mode;
0592     compat_ulong_t dir_mode;
0593 };
0594 
0595 static void *do_ncp_super_data_conv(void *raw_data)
0596 {
0597     int version = *(unsigned int *)raw_data;
0598 
0599     if (version == 3) {
0600         struct compat_ncp_mount_data *c_n = raw_data;
0601         struct ncp_mount_data *n = raw_data;
0602 
0603         n->dir_mode = c_n->dir_mode;
0604         n->file_mode = c_n->file_mode;
0605         n->gid = c_n->gid;
0606         n->uid = c_n->uid;
0607         memmove (n->mounted_vol, c_n->mounted_vol, (sizeof (c_n->mounted_vol) + 3 * sizeof (unsigned int)));
0608         n->wdog_pid = c_n->wdog_pid;
0609         n->mounted_uid = c_n->mounted_uid;
0610     } else if (version == 4) {
0611         struct compat_ncp_mount_data_v4 *c_n = raw_data;
0612         struct ncp_mount_data_v4 *n = raw_data;
0613 
0614         n->dir_mode = c_n->dir_mode;
0615         n->file_mode = c_n->file_mode;
0616         n->gid = c_n->gid;
0617         n->uid = c_n->uid;
0618         n->retry_count = c_n->retry_count;
0619         n->time_out = c_n->time_out;
0620         n->ncp_fd = c_n->ncp_fd;
0621         n->wdog_pid = c_n->wdog_pid;
0622         n->mounted_uid = c_n->mounted_uid;
0623         n->flags = c_n->flags;
0624     } else if (version != 5) {
0625         return NULL;
0626     }
0627 
0628     return raw_data;
0629 }
0630 
0631 
0632 struct compat_nfs_string {
0633     compat_uint_t len;
0634     compat_uptr_t data;
0635 };
0636 
0637 static inline void compat_nfs_string(struct nfs_string *dst,
0638                      struct compat_nfs_string *src)
0639 {
0640     dst->data = compat_ptr(src->data);
0641     dst->len = src->len;
0642 }
0643 
0644 struct compat_nfs4_mount_data_v1 {
0645     compat_int_t version;
0646     compat_int_t flags;
0647     compat_int_t rsize;
0648     compat_int_t wsize;
0649     compat_int_t timeo;
0650     compat_int_t retrans;
0651     compat_int_t acregmin;
0652     compat_int_t acregmax;
0653     compat_int_t acdirmin;
0654     compat_int_t acdirmax;
0655     struct compat_nfs_string client_addr;
0656     struct compat_nfs_string mnt_path;
0657     struct compat_nfs_string hostname;
0658     compat_uint_t host_addrlen;
0659     compat_uptr_t host_addr;
0660     compat_int_t proto;
0661     compat_int_t auth_flavourlen;
0662     compat_uptr_t auth_flavours;
0663 };
0664 
0665 static int do_nfs4_super_data_conv(void *raw_data)
0666 {
0667     int version = *(compat_uint_t *) raw_data;
0668 
0669     if (version == 1) {
0670         struct compat_nfs4_mount_data_v1 *raw = raw_data;
0671         struct nfs4_mount_data *real = raw_data;
0672 
0673         /* copy the fields backwards */
0674         real->auth_flavours = compat_ptr(raw->auth_flavours);
0675         real->auth_flavourlen = raw->auth_flavourlen;
0676         real->proto = raw->proto;
0677         real->host_addr = compat_ptr(raw->host_addr);
0678         real->host_addrlen = raw->host_addrlen;
0679         compat_nfs_string(&real->hostname, &raw->hostname);
0680         compat_nfs_string(&real->mnt_path, &raw->mnt_path);
0681         compat_nfs_string(&real->client_addr, &raw->client_addr);
0682         real->acdirmax = raw->acdirmax;
0683         real->acdirmin = raw->acdirmin;
0684         real->acregmax = raw->acregmax;
0685         real->acregmin = raw->acregmin;
0686         real->retrans = raw->retrans;
0687         real->timeo = raw->timeo;
0688         real->wsize = raw->wsize;
0689         real->rsize = raw->rsize;
0690         real->flags = raw->flags;
0691         real->version = raw->version;
0692     }
0693 
0694     return 0;
0695 }
0696 
0697 #define NCPFS_NAME      "ncpfs"
0698 #define NFS4_NAME   "nfs4"
0699 
0700 COMPAT_SYSCALL_DEFINE5(mount, const char __user *, dev_name,
0701                const char __user *, dir_name,
0702                const char __user *, type, compat_ulong_t, flags,
0703                const void __user *, data)
0704 {
0705     char *kernel_type;
0706     void *options;
0707     char *kernel_dev;
0708     int retval;
0709 
0710     kernel_type = copy_mount_string(type);
0711     retval = PTR_ERR(kernel_type);
0712     if (IS_ERR(kernel_type))
0713         goto out;
0714 
0715     kernel_dev = copy_mount_string(dev_name);
0716     retval = PTR_ERR(kernel_dev);
0717     if (IS_ERR(kernel_dev))
0718         goto out1;
0719 
0720     options = copy_mount_options(data);
0721     retval = PTR_ERR(options);
0722     if (IS_ERR(options))
0723         goto out2;
0724 
0725     if (kernel_type && options) {
0726         if (!strcmp(kernel_type, NCPFS_NAME)) {
0727             do_ncp_super_data_conv(options);
0728         } else if (!strcmp(kernel_type, NFS4_NAME)) {
0729             retval = -EINVAL;
0730             if (do_nfs4_super_data_conv(options))
0731                 goto out3;
0732         }
0733     }
0734 
0735     retval = do_mount(kernel_dev, dir_name, kernel_type, flags, options);
0736 
0737  out3:
0738     kfree(options);
0739  out2:
0740     kfree(kernel_dev);
0741  out1:
0742     kfree(kernel_type);
0743  out:
0744     return retval;
0745 }
0746 
0747 struct compat_old_linux_dirent {
0748     compat_ulong_t  d_ino;
0749     compat_ulong_t  d_offset;
0750     unsigned short  d_namlen;
0751     char        d_name[1];
0752 };
0753 
0754 struct compat_readdir_callback {
0755     struct dir_context ctx;
0756     struct compat_old_linux_dirent __user *dirent;
0757     int result;
0758 };
0759 
0760 static int compat_fillonedir(struct dir_context *ctx, const char *name,
0761                  int namlen, loff_t offset, u64 ino,
0762                  unsigned int d_type)
0763 {
0764     struct compat_readdir_callback *buf =
0765         container_of(ctx, struct compat_readdir_callback, ctx);
0766     struct compat_old_linux_dirent __user *dirent;
0767     compat_ulong_t d_ino;
0768 
0769     if (buf->result)
0770         return -EINVAL;
0771     d_ino = ino;
0772     if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
0773         buf->result = -EOVERFLOW;
0774         return -EOVERFLOW;
0775     }
0776     buf->result++;
0777     dirent = buf->dirent;
0778     if (!access_ok(VERIFY_WRITE, dirent,
0779             (unsigned long)(dirent->d_name + namlen + 1) -
0780                 (unsigned long)dirent))
0781         goto efault;
0782     if (    __put_user(d_ino, &dirent->d_ino) ||
0783         __put_user(offset, &dirent->d_offset) ||
0784         __put_user(namlen, &dirent->d_namlen) ||
0785         __copy_to_user(dirent->d_name, name, namlen) ||
0786         __put_user(0, dirent->d_name + namlen))
0787         goto efault;
0788     return 0;
0789 efault:
0790     buf->result = -EFAULT;
0791     return -EFAULT;
0792 }
0793 
0794 COMPAT_SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
0795         struct compat_old_linux_dirent __user *, dirent, unsigned int, count)
0796 {
0797     int error;
0798     struct fd f = fdget_pos(fd);
0799     struct compat_readdir_callback buf = {
0800         .ctx.actor = compat_fillonedir,
0801         .dirent = dirent
0802     };
0803 
0804     if (!f.file)
0805         return -EBADF;
0806 
0807     error = iterate_dir(f.file, &buf.ctx);
0808     if (buf.result)
0809         error = buf.result;
0810 
0811     fdput_pos(f);
0812     return error;
0813 }
0814 
0815 struct compat_linux_dirent {
0816     compat_ulong_t  d_ino;
0817     compat_ulong_t  d_off;
0818     unsigned short  d_reclen;
0819     char        d_name[1];
0820 };
0821 
0822 struct compat_getdents_callback {
0823     struct dir_context ctx;
0824     struct compat_linux_dirent __user *current_dir;
0825     struct compat_linux_dirent __user *previous;
0826     int count;
0827     int error;
0828 };
0829 
0830 static int compat_filldir(struct dir_context *ctx, const char *name, int namlen,
0831         loff_t offset, u64 ino, unsigned int d_type)
0832 {
0833     struct compat_linux_dirent __user * dirent;
0834     struct compat_getdents_callback *buf =
0835         container_of(ctx, struct compat_getdents_callback, ctx);
0836     compat_ulong_t d_ino;
0837     int reclen = ALIGN(offsetof(struct compat_linux_dirent, d_name) +
0838         namlen + 2, sizeof(compat_long_t));
0839 
0840     buf->error = -EINVAL;   /* only used if we fail.. */
0841     if (reclen > buf->count)
0842         return -EINVAL;
0843     d_ino = ino;
0844     if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) {
0845         buf->error = -EOVERFLOW;
0846         return -EOVERFLOW;
0847     }
0848     dirent = buf->previous;
0849     if (dirent) {
0850         if (signal_pending(current))
0851             return -EINTR;
0852         if (__put_user(offset, &dirent->d_off))
0853             goto efault;
0854     }
0855     dirent = buf->current_dir;
0856     if (__put_user(d_ino, &dirent->d_ino))
0857         goto efault;
0858     if (__put_user(reclen, &dirent->d_reclen))
0859         goto efault;
0860     if (copy_to_user(dirent->d_name, name, namlen))
0861         goto efault;
0862     if (__put_user(0, dirent->d_name + namlen))
0863         goto efault;
0864     if (__put_user(d_type, (char  __user *) dirent + reclen - 1))
0865         goto efault;
0866     buf->previous = dirent;
0867     dirent = (void __user *)dirent + reclen;
0868     buf->current_dir = dirent;
0869     buf->count -= reclen;
0870     return 0;
0871 efault:
0872     buf->error = -EFAULT;
0873     return -EFAULT;
0874 }
0875 
0876 COMPAT_SYSCALL_DEFINE3(getdents, unsigned int, fd,
0877         struct compat_linux_dirent __user *, dirent, unsigned int, count)
0878 {
0879     struct fd f;
0880     struct compat_linux_dirent __user * lastdirent;
0881     struct compat_getdents_callback buf = {
0882         .ctx.actor = compat_filldir,
0883         .current_dir = dirent,
0884         .count = count
0885     };
0886     int error;
0887 
0888     if (!access_ok(VERIFY_WRITE, dirent, count))
0889         return -EFAULT;
0890 
0891     f = fdget_pos(fd);
0892     if (!f.file)
0893         return -EBADF;
0894 
0895     error = iterate_dir(f.file, &buf.ctx);
0896     if (error >= 0)
0897         error = buf.error;
0898     lastdirent = buf.previous;
0899     if (lastdirent) {
0900         if (put_user(buf.ctx.pos, &lastdirent->d_off))
0901             error = -EFAULT;
0902         else
0903             error = count - buf.count;
0904     }
0905     fdput_pos(f);
0906     return error;
0907 }
0908 
0909 #ifdef __ARCH_WANT_COMPAT_SYS_GETDENTS64
0910 
0911 struct compat_getdents_callback64 {
0912     struct dir_context ctx;
0913     struct linux_dirent64 __user *current_dir;
0914     struct linux_dirent64 __user *previous;
0915     int count;
0916     int error;
0917 };
0918 
0919 static int compat_filldir64(struct dir_context *ctx, const char *name,
0920                 int namlen, loff_t offset, u64 ino,
0921                 unsigned int d_type)
0922 {
0923     struct linux_dirent64 __user *dirent;
0924     struct compat_getdents_callback64 *buf =
0925         container_of(ctx, struct compat_getdents_callback64, ctx);
0926     int reclen = ALIGN(offsetof(struct linux_dirent64, d_name) + namlen + 1,
0927         sizeof(u64));
0928     u64 off;
0929 
0930     buf->error = -EINVAL;   /* only used if we fail.. */
0931     if (reclen > buf->count)
0932         return -EINVAL;
0933     dirent = buf->previous;
0934 
0935     if (dirent) {
0936         if (signal_pending(current))
0937             return -EINTR;
0938         if (__put_user_unaligned(offset, &dirent->d_off))
0939             goto efault;
0940     }
0941     dirent = buf->current_dir;
0942     if (__put_user_unaligned(ino, &dirent->d_ino))
0943         goto efault;
0944     off = 0;
0945     if (__put_user_unaligned(off, &dirent->d_off))
0946         goto efault;
0947     if (__put_user(reclen, &dirent->d_reclen))
0948         goto efault;
0949     if (__put_user(d_type, &dirent->d_type))
0950         goto efault;
0951     if (copy_to_user(dirent->d_name, name, namlen))
0952         goto efault;
0953     if (__put_user(0, dirent->d_name + namlen))
0954         goto efault;
0955     buf->previous = dirent;
0956     dirent = (void __user *)dirent + reclen;
0957     buf->current_dir = dirent;
0958     buf->count -= reclen;
0959     return 0;
0960 efault:
0961     buf->error = -EFAULT;
0962     return -EFAULT;
0963 }
0964 
0965 COMPAT_SYSCALL_DEFINE3(getdents64, unsigned int, fd,
0966         struct linux_dirent64 __user *, dirent, unsigned int, count)
0967 {
0968     struct fd f;
0969     struct linux_dirent64 __user * lastdirent;
0970     struct compat_getdents_callback64 buf = {
0971         .ctx.actor = compat_filldir64,
0972         .current_dir = dirent,
0973         .count = count
0974     };
0975     int error;
0976 
0977     if (!access_ok(VERIFY_WRITE, dirent, count))
0978         return -EFAULT;
0979 
0980     f = fdget_pos(fd);
0981     if (!f.file)
0982         return -EBADF;
0983 
0984     error = iterate_dir(f.file, &buf.ctx);
0985     if (error >= 0)
0986         error = buf.error;
0987     lastdirent = buf.previous;
0988     if (lastdirent) {
0989         typeof(lastdirent->d_off) d_off = buf.ctx.pos;
0990         if (__put_user_unaligned(d_off, &lastdirent->d_off))
0991             error = -EFAULT;
0992         else
0993             error = count - buf.count;
0994     }
0995     fdput_pos(f);
0996     return error;
0997 }
0998 #endif /* __ARCH_WANT_COMPAT_SYS_GETDENTS64 */
0999 
1000 /*
1001  * Exactly like fs/open.c:sys_open(), except that it doesn't set the
1002  * O_LARGEFILE flag.
1003  */
1004 COMPAT_SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
1005 {
1006     return do_sys_open(AT_FDCWD, filename, flags, mode);
1007 }
1008 
1009 /*
1010  * Exactly like fs/open.c:sys_openat(), except that it doesn't set the
1011  * O_LARGEFILE flag.
1012  */
1013 COMPAT_SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, umode_t, mode)
1014 {
1015     return do_sys_open(dfd, filename, flags, mode);
1016 }
1017 
1018 #define __COMPAT_NFDBITS       (8 * sizeof(compat_ulong_t))
1019 
1020 static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,
1021                       int timeval, int ret)
1022 {
1023     struct timespec ts;
1024 
1025     if (!p)
1026         return ret;
1027 
1028     if (current->personality & STICKY_TIMEOUTS)
1029         goto sticky;
1030 
1031     /* No update for zero timeout */
1032     if (!end_time->tv_sec && !end_time->tv_nsec)
1033         return ret;
1034 
1035     ktime_get_ts(&ts);
1036     ts = timespec_sub(*end_time, ts);
1037     if (ts.tv_sec < 0)
1038         ts.tv_sec = ts.tv_nsec = 0;
1039 
1040     if (timeval) {
1041         struct compat_timeval rtv;
1042 
1043         rtv.tv_sec = ts.tv_sec;
1044         rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
1045 
1046         if (!copy_to_user(p, &rtv, sizeof(rtv)))
1047             return ret;
1048     } else {
1049         struct compat_timespec rts;
1050 
1051         rts.tv_sec = ts.tv_sec;
1052         rts.tv_nsec = ts.tv_nsec;
1053 
1054         if (!copy_to_user(p, &rts, sizeof(rts)))
1055             return ret;
1056     }
1057     /*
1058      * If an application puts its timeval in read-only memory, we
1059      * don't want the Linux-specific update to the timeval to
1060      * cause a fault after the select has completed
1061      * successfully. However, because we're not updating the
1062      * timeval, we can't restart the system call.
1063      */
1064 
1065 sticky:
1066     if (ret == -ERESTARTNOHAND)
1067         ret = -EINTR;
1068     return ret;
1069 }
1070 
1071 /*
1072  * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
1073  * 64-bit unsigned longs.
1074  */
1075 static
1076 int compat_get_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1077             unsigned long *fdset)
1078 {
1079     nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
1080     if (ufdset) {
1081         unsigned long odd;
1082 
1083         if (!access_ok(VERIFY_WRITE, ufdset, nr*sizeof(compat_ulong_t)))
1084             return -EFAULT;
1085 
1086         odd = nr & 1UL;
1087         nr &= ~1UL;
1088         while (nr) {
1089             unsigned long h, l;
1090             if (__get_user(l, ufdset) || __get_user(h, ufdset+1))
1091                 return -EFAULT;
1092             ufdset += 2;
1093             *fdset++ = h << 32 | l;
1094             nr -= 2;
1095         }
1096         if (odd && __get_user(*fdset, ufdset))
1097             return -EFAULT;
1098     } else {
1099         /* Tricky, must clear full unsigned long in the
1100          * kernel fdset at the end, this makes sure that
1101          * actually happens.
1102          */
1103         memset(fdset, 0, ((nr + 1) & ~1)*sizeof(compat_ulong_t));
1104     }
1105     return 0;
1106 }
1107 
1108 static
1109 int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1110               unsigned long *fdset)
1111 {
1112     unsigned long odd;
1113     nr = DIV_ROUND_UP(nr, __COMPAT_NFDBITS);
1114 
1115     if (!ufdset)
1116         return 0;
1117 
1118     odd = nr & 1UL;
1119     nr &= ~1UL;
1120     while (nr) {
1121         unsigned long h, l;
1122         l = *fdset++;
1123         h = l >> 32;
1124         if (__put_user(l, ufdset) || __put_user(h, ufdset+1))
1125             return -EFAULT;
1126         ufdset += 2;
1127         nr -= 2;
1128     }
1129     if (odd && __put_user(*fdset, ufdset))
1130         return -EFAULT;
1131     return 0;
1132 }
1133 
1134 
1135 /*
1136  * This is a virtual copy of sys_select from fs/select.c and probably
1137  * should be compared to it from time to time
1138  */
1139 
1140 /*
1141  * We can actually return ERESTARTSYS instead of EINTR, but I'd
1142  * like to be certain this leads to no problems. So I return
1143  * EINTR just for safety.
1144  *
1145  * Update: ERESTARTSYS breaks at least the xview clock binary, so
1146  * I'm trying ERESTARTNOHAND which restart only when you want to.
1147  */
1148 int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1149     compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1150     struct timespec *end_time)
1151 {
1152     fd_set_bits fds;
1153     void *bits;
1154     int size, max_fds, ret = -EINVAL;
1155     struct fdtable *fdt;
1156     long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
1157 
1158     if (n < 0)
1159         goto out_nofds;
1160 
1161     /* max_fds can increase, so grab it once to avoid race */
1162     rcu_read_lock();
1163     fdt = files_fdtable(current->files);
1164     max_fds = fdt->max_fds;
1165     rcu_read_unlock();
1166     if (n > max_fds)
1167         n = max_fds;
1168 
1169     /*
1170      * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
1171      * since we used fdset we need to allocate memory in units of
1172      * long-words.
1173      */
1174     size = FDS_BYTES(n);
1175     bits = stack_fds;
1176     if (size > sizeof(stack_fds) / 6) {
1177         bits = kmalloc(6 * size, GFP_KERNEL);
1178         ret = -ENOMEM;
1179         if (!bits)
1180             goto out_nofds;
1181     }
1182     fds.in      = (unsigned long *)  bits;
1183     fds.out     = (unsigned long *) (bits +   size);
1184     fds.ex      = (unsigned long *) (bits + 2*size);
1185     fds.res_in  = (unsigned long *) (bits + 3*size);
1186     fds.res_out = (unsigned long *) (bits + 4*size);
1187     fds.res_ex  = (unsigned long *) (bits + 5*size);
1188 
1189     if ((ret = compat_get_fd_set(n, inp, fds.in)) ||
1190         (ret = compat_get_fd_set(n, outp, fds.out)) ||
1191         (ret = compat_get_fd_set(n, exp, fds.ex)))
1192         goto out;
1193     zero_fd_set(n, fds.res_in);
1194     zero_fd_set(n, fds.res_out);
1195     zero_fd_set(n, fds.res_ex);
1196 
1197     ret = do_select(n, &fds, end_time);
1198 
1199     if (ret < 0)
1200         goto out;
1201     if (!ret) {
1202         ret = -ERESTARTNOHAND;
1203         if (signal_pending(current))
1204             goto out;
1205         ret = 0;
1206     }
1207 
1208     if (compat_set_fd_set(n, inp, fds.res_in) ||
1209         compat_set_fd_set(n, outp, fds.res_out) ||
1210         compat_set_fd_set(n, exp, fds.res_ex))
1211         ret = -EFAULT;
1212 out:
1213     if (bits != stack_fds)
1214         kfree(bits);
1215 out_nofds:
1216     return ret;
1217 }
1218 
1219 COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp,
1220     compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
1221     struct compat_timeval __user *, tvp)
1222 {
1223     struct timespec end_time, *to = NULL;
1224     struct compat_timeval tv;
1225     int ret;
1226 
1227     if (tvp) {
1228         if (copy_from_user(&tv, tvp, sizeof(tv)))
1229             return -EFAULT;
1230 
1231         to = &end_time;
1232         if (poll_select_set_timeout(to,
1233                 tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
1234                 (tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
1235             return -EINVAL;
1236     }
1237 
1238     ret = compat_core_sys_select(n, inp, outp, exp, to);
1239     ret = poll_select_copy_remaining(&end_time, tvp, 1, ret);
1240 
1241     return ret;
1242 }
1243 
1244 struct compat_sel_arg_struct {
1245     compat_ulong_t n;
1246     compat_uptr_t inp;
1247     compat_uptr_t outp;
1248     compat_uptr_t exp;
1249     compat_uptr_t tvp;
1250 };
1251 
1252 COMPAT_SYSCALL_DEFINE1(old_select, struct compat_sel_arg_struct __user *, arg)
1253 {
1254     struct compat_sel_arg_struct a;
1255 
1256     if (copy_from_user(&a, arg, sizeof(a)))
1257         return -EFAULT;
1258     return compat_sys_select(a.n, compat_ptr(a.inp), compat_ptr(a.outp),
1259                  compat_ptr(a.exp), compat_ptr(a.tvp));
1260 }
1261 
1262 static long do_compat_pselect(int n, compat_ulong_t __user *inp,
1263     compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1264     struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
1265     compat_size_t sigsetsize)
1266 {
1267     compat_sigset_t ss32;
1268     sigset_t ksigmask, sigsaved;
1269     struct compat_timespec ts;
1270     struct timespec end_time, *to = NULL;
1271     int ret;
1272 
1273     if (tsp) {
1274         if (copy_from_user(&ts, tsp, sizeof(ts)))
1275             return -EFAULT;
1276 
1277         to = &end_time;
1278         if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1279             return -EINVAL;
1280     }
1281 
1282     if (sigmask) {
1283         if (sigsetsize != sizeof(compat_sigset_t))
1284             return -EINVAL;
1285         if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1286             return -EFAULT;
1287         sigset_from_compat(&ksigmask, &ss32);
1288 
1289         sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1290         sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1291     }
1292 
1293     ret = compat_core_sys_select(n, inp, outp, exp, to);
1294     ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1295 
1296     if (ret == -ERESTARTNOHAND) {
1297         /*
1298          * Don't restore the signal mask yet. Let do_signal() deliver
1299          * the signal on the way back to userspace, before the signal
1300          * mask is restored.
1301          */
1302         if (sigmask) {
1303             memcpy(&current->saved_sigmask, &sigsaved,
1304                     sizeof(sigsaved));
1305             set_restore_sigmask();
1306         }
1307     } else if (sigmask)
1308         sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1309 
1310     return ret;
1311 }
1312 
1313 COMPAT_SYSCALL_DEFINE6(pselect6, int, n, compat_ulong_t __user *, inp,
1314     compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
1315     struct compat_timespec __user *, tsp, void __user *, sig)
1316 {
1317     compat_size_t sigsetsize = 0;
1318     compat_uptr_t up = 0;
1319 
1320     if (sig) {
1321         if (!access_ok(VERIFY_READ, sig,
1322                 sizeof(compat_uptr_t)+sizeof(compat_size_t)) ||
1323                 __get_user(up, (compat_uptr_t __user *)sig) ||
1324                 __get_user(sigsetsize,
1325                 (compat_size_t __user *)(sig+sizeof(up))))
1326             return -EFAULT;
1327     }
1328     return do_compat_pselect(n, inp, outp, exp, tsp, compat_ptr(up),
1329                  sigsetsize);
1330 }
1331 
1332 COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
1333     unsigned int,  nfds, struct compat_timespec __user *, tsp,
1334     const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)
1335 {
1336     compat_sigset_t ss32;
1337     sigset_t ksigmask, sigsaved;
1338     struct compat_timespec ts;
1339     struct timespec end_time, *to = NULL;
1340     int ret;
1341 
1342     if (tsp) {
1343         if (copy_from_user(&ts, tsp, sizeof(ts)))
1344             return -EFAULT;
1345 
1346         to = &end_time;
1347         if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1348             return -EINVAL;
1349     }
1350 
1351     if (sigmask) {
1352         if (sigsetsize != sizeof(compat_sigset_t))
1353             return -EINVAL;
1354         if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
1355             return -EFAULT;
1356         sigset_from_compat(&ksigmask, &ss32);
1357 
1358         sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
1359         sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1360     }
1361 
1362     ret = do_sys_poll(ufds, nfds, to);
1363 
1364     /* We can restart this syscall, usually */
1365     if (ret == -EINTR) {
1366         /*
1367          * Don't restore the signal mask yet. Let do_signal() deliver
1368          * the signal on the way back to userspace, before the signal
1369          * mask is restored.
1370          */
1371         if (sigmask) {
1372             memcpy(&current->saved_sigmask, &sigsaved,
1373                 sizeof(sigsaved));
1374             set_restore_sigmask();
1375         }
1376         ret = -ERESTARTNOHAND;
1377     } else if (sigmask)
1378         sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1379 
1380     ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1381 
1382     return ret;
1383 }
1384 
1385 #ifdef CONFIG_FHANDLE
1386 /*
1387  * Exactly like fs/open.c:sys_open_by_handle_at(), except that it
1388  * doesn't set the O_LARGEFILE flag.
1389  */
1390 COMPAT_SYSCALL_DEFINE3(open_by_handle_at, int, mountdirfd,
1391                  struct file_handle __user *, handle, int, flags)
1392 {
1393     return do_handle_open(mountdirfd, handle, flags);
1394 }
1395 #endif