Merge branch 'work.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 2 May 2017 18:54:26 +0000 (11:54 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 2 May 2017 18:54:26 +0000 (11:54 -0700)
Pull fs/compat.c cleanups from Al Viro:
 "More moving of compat syscalls from fs/compat.c to fs/*.c where the
  native counterparts live.

  And death to compat_sys_getdents64() - the only architecture that used
  to need it was ia64, and _that_ has lost biarch support quite a few
  years ago"

* 'work.compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  fs/compat.c: trim unused includes
  move compat_rw_copy_check_uvector() over to fs/read_write.c
  fhandle: move compat syscalls from compat.c
  open: move compat syscalls from compat.c
  stat: move compat syscalls from compat.c
  fcntl: move compat syscalls from compat.c
  readdir: move compat syscalls from compat.c
  statfs: move compat syscalls from compat.c
  utimes: move compat syscalls from compat.c
  move compat select-related syscalls to fs/select.c
  Remove compat_sys_getdents64()

1  2 
arch/x86/entry/syscalls/syscall_32.tbl
fs/stat.c
include/linux/compat.h

diff --cc fs/stat.c
+++ b/fs/stat.c
@@@ -563,18 -571,105 +564,103 @@@ SYSCALL_DEFINE5(statx
        struct kstat stat;
        int error;
  
 +      if (mask & STATX__RESERVED)
 +              return -EINVAL;
        if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
                return -EINVAL;
 -      if (!access_ok(VERIFY_WRITE, buffer, sizeof(*buffer)))
 -              return -EFAULT;
  
 -      if (filename)
 -              error = vfs_statx(dfd, filename, flags, &stat, mask);
 -      else
 -              error = vfs_statx_fd(dfd, &stat, mask, flags);
 +      error = vfs_statx(dfd, filename, flags, &stat, mask);
        if (error)
                return error;
 -      return statx_set_result(&stat, buffer);
 +
 +      return cp_statx(&stat, buffer);
  }
  
+ #ifdef CONFIG_COMPAT
+ static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
+ {
+       struct compat_stat tmp;
+       if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
+               return -EOVERFLOW;
+       memset(&tmp, 0, sizeof(tmp));
+       tmp.st_dev = old_encode_dev(stat->dev);
+       tmp.st_ino = stat->ino;
+       if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
+               return -EOVERFLOW;
+       tmp.st_mode = stat->mode;
+       tmp.st_nlink = stat->nlink;
+       if (tmp.st_nlink != stat->nlink)
+               return -EOVERFLOW;
+       SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
+       SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
+       tmp.st_rdev = old_encode_dev(stat->rdev);
+       if ((u64) stat->size > MAX_NON_LFS)
+               return -EOVERFLOW;
+       tmp.st_size = stat->size;
+       tmp.st_atime = stat->atime.tv_sec;
+       tmp.st_atime_nsec = stat->atime.tv_nsec;
+       tmp.st_mtime = stat->mtime.tv_sec;
+       tmp.st_mtime_nsec = stat->mtime.tv_nsec;
+       tmp.st_ctime = stat->ctime.tv_sec;
+       tmp.st_ctime_nsec = stat->ctime.tv_nsec;
+       tmp.st_blocks = stat->blocks;
+       tmp.st_blksize = stat->blksize;
+       return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
+ }
+ COMPAT_SYSCALL_DEFINE2(newstat, const char __user *, filename,
+                      struct compat_stat __user *, statbuf)
+ {
+       struct kstat stat;
+       int error;
+       error = vfs_stat(filename, &stat);
+       if (error)
+               return error;
+       return cp_compat_stat(&stat, statbuf);
+ }
+ COMPAT_SYSCALL_DEFINE2(newlstat, const char __user *, filename,
+                      struct compat_stat __user *, statbuf)
+ {
+       struct kstat stat;
+       int error;
+       error = vfs_lstat(filename, &stat);
+       if (error)
+               return error;
+       return cp_compat_stat(&stat, statbuf);
+ }
+ #ifndef __ARCH_WANT_STAT64
+ COMPAT_SYSCALL_DEFINE4(newfstatat, unsigned int, dfd,
+                      const char __user *, filename,
+                      struct compat_stat __user *, statbuf, int, flag)
+ {
+       struct kstat stat;
+       int error;
+       error = vfs_fstatat(dfd, filename, &stat, flag);
+       if (error)
+               return error;
+       return cp_compat_stat(&stat, statbuf);
+ }
+ #endif
+ COMPAT_SYSCALL_DEFINE2(newfstat, unsigned int, fd,
+                      struct compat_stat __user *, statbuf)
+ {
+       struct kstat stat;
+       int error = vfs_fstat(fd, &stat);
+       if (!error)
+               error = cp_compat_stat(&stat, statbuf);
+       return error;
+ }
+ #endif
  /* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
  void __inode_add_bytes(struct inode *inode, loff_t bytes)
  {
Simple merge