]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/stat.c
ftgmac100: Display the discovered PHY device info
[karo-tx-linux.git] / fs / stat.c
index fa0be59340cc9136eb8c508434e10289acc8fc97..c6c963b2546b4f2d0301f40706064498c31fd3b6 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -130,9 +130,13 @@ EXPORT_SYMBOL(vfs_getattr);
 int vfs_statx_fd(unsigned int fd, struct kstat *stat,
                 u32 request_mask, unsigned int query_flags)
 {
-       struct fd f = fdget_raw(fd);
+       struct fd f;
        int error = -EBADF;
 
+       if (query_flags & ~KSTAT_QUERY_FLAGS)
+               return -EINVAL;
+
+       f = fdget_raw(fd);
        if (f.file) {
                error = vfs_getattr(&f.file->f_path, stat,
                                    request_mask, query_flags);
@@ -155,9 +159,6 @@ EXPORT_SYMBOL(vfs_statx_fd);
  * Additionally, the use of AT_SYMLINK_NOFOLLOW in flags will prevent a symlink
  * at the given name from being referenced.
  *
- * The caller must have preset stat->request_mask as for vfs_getattr().  The
- * flags are also used to load up stat->query_flags.
- *
  * 0 will be returned on success, and a -ve error code if unsuccessful.
  */
 int vfs_statx(int dfd, const char __user *filename, int flags,
@@ -509,46 +510,38 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
 }
 #endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */
 
-static inline int __put_timestamp(struct timespec *kts,
-                                 struct statx_timestamp __user *uts)
-{
-       return (__put_user(kts->tv_sec,         &uts->tv_sec            ) ||
-               __put_user(kts->tv_nsec,        &uts->tv_nsec           ) ||
-               __put_user(0,                   &uts->__reserved        ));
-}
-
-/*
- * Set the statx results.
- */
-static long statx_set_result(struct kstat *stat, struct statx __user *buffer)
+static noinline_for_stack int
+cp_statx(const struct kstat *stat, struct statx __user *buffer)
 {
-       uid_t uid = from_kuid_munged(current_user_ns(), stat->uid);
-       gid_t gid = from_kgid_munged(current_user_ns(), stat->gid);
-
-       if (__put_user(stat->result_mask,       &buffer->stx_mask       ) ||
-           __put_user(stat->mode,              &buffer->stx_mode       ) ||
-           __clear_user(&buffer->__spare0, sizeof(buffer->__spare0))     ||
-           __put_user(stat->nlink,             &buffer->stx_nlink      ) ||
-           __put_user(uid,                     &buffer->stx_uid        ) ||
-           __put_user(gid,                     &buffer->stx_gid        ) ||
-           __put_user(stat->attributes,        &buffer->stx_attributes ) ||
-           __put_user(stat->blksize,           &buffer->stx_blksize    ) ||
-           __put_user(MAJOR(stat->rdev),       &buffer->stx_rdev_major ) ||
-           __put_user(MINOR(stat->rdev),       &buffer->stx_rdev_minor ) ||
-           __put_user(MAJOR(stat->dev),        &buffer->stx_dev_major  ) ||
-           __put_user(MINOR(stat->dev),        &buffer->stx_dev_minor  ) ||
-           __put_timestamp(&stat->atime,       &buffer->stx_atime      ) ||
-           __put_timestamp(&stat->btime,       &buffer->stx_btime      ) ||
-           __put_timestamp(&stat->ctime,       &buffer->stx_ctime      ) ||
-           __put_timestamp(&stat->mtime,       &buffer->stx_mtime      ) ||
-           __put_user(stat->ino,               &buffer->stx_ino        ) ||
-           __put_user(stat->size,              &buffer->stx_size       ) ||
-           __put_user(stat->blocks,            &buffer->stx_blocks     ) ||
-           __clear_user(&buffer->__spare1, sizeof(buffer->__spare1))     ||
-           __clear_user(&buffer->__spare2, sizeof(buffer->__spare2)))
-               return -EFAULT;
-
-       return 0;
+       struct statx tmp;
+
+       memset(&tmp, 0, sizeof(tmp));
+
+       tmp.stx_mask = stat->result_mask;
+       tmp.stx_blksize = stat->blksize;
+       tmp.stx_attributes = stat->attributes;
+       tmp.stx_nlink = stat->nlink;
+       tmp.stx_uid = from_kuid_munged(current_user_ns(), stat->uid);
+       tmp.stx_gid = from_kgid_munged(current_user_ns(), stat->gid);
+       tmp.stx_mode = stat->mode;
+       tmp.stx_ino = stat->ino;
+       tmp.stx_size = stat->size;
+       tmp.stx_blocks = stat->blocks;
+       tmp.stx_attributes_mask = stat->attributes_mask;
+       tmp.stx_atime.tv_sec = stat->atime.tv_sec;
+       tmp.stx_atime.tv_nsec = stat->atime.tv_nsec;
+       tmp.stx_btime.tv_sec = stat->btime.tv_sec;
+       tmp.stx_btime.tv_nsec = stat->btime.tv_nsec;
+       tmp.stx_ctime.tv_sec = stat->ctime.tv_sec;
+       tmp.stx_ctime.tv_nsec = stat->ctime.tv_nsec;
+       tmp.stx_mtime.tv_sec = stat->mtime.tv_sec;
+       tmp.stx_mtime.tv_nsec = stat->mtime.tv_nsec;
+       tmp.stx_rdev_major = MAJOR(stat->rdev);
+       tmp.stx_rdev_minor = MINOR(stat->rdev);
+       tmp.stx_dev_major = MAJOR(stat->dev);
+       tmp.stx_dev_minor = MINOR(stat->dev);
+
+       return copy_to_user(buffer, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
 /**
@@ -570,10 +563,10 @@ 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);
@@ -581,7 +574,8 @@ SYSCALL_DEFINE5(statx,
                error = vfs_statx_fd(dfd, &stat, mask, flags);
        if (error)
                return error;
-       return statx_set_result(&stat, buffer);
+
+       return cp_statx(&stat, buffer);
 }
 
 /* Caller is here responsible for sufficient locking (ie. inode->i_lock) */