b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * linux/fs/stat.c
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Copyright (C) 1991, 1992 Linus Torvalds
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 6) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 7)
630d9c47274aa (Paul Gortmaker 2011-11-16 23:57:37 -0500 8) #include <linux/export.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 9) #include <linux/mm.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 10) #include <linux/errno.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 11) #include <linux/file.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 12) #include <linux/highuid.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) #include <linux/fs.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) #include <linux/namei.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15) #include <linux/security.h>
5b825c3af1d8a (Ingo Molnar 2017-02-02 17:54:15 +0100 16) #include <linux/cred.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 17) #include <linux/syscalls.h>
ba52de123d454 (Theodore Ts'o 2006-09-27 01:50:49 -0700 18) #include <linux/pagemap.h>
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 19) #include <linux/compat.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 20)
7c0f6ba682b9c (Linus Torvalds 2016-12-24 11:46:01 -0800 21) #include <linux/uaccess.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 22) #include <asm/unistd.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 23)
3934e36f6099e (Jens Axboe 2019-12-14 13:26:33 -0700 24) #include "internal.h"
fa2fcf4f1df15 (Miklos Szeredi 2020-05-14 16:44:24 +0200 25) #include "mount.h"
3934e36f6099e (Jens Axboe 2019-12-14 13:26:33 -0700 26)
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 27) /**
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 28) * generic_fillattr - Fill in the basic attributes from the inode struct
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 29) * @mnt_userns: user namespace of the mount the inode was found from
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 30) * @inode: Inode to use as the source
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 31) * @stat: Where to fill in the attributes
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 32) *
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 33) * Fill in the basic attributes in the kstat structure from data that's to be
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 34) * found on the VFS inode structure. This is the default if no getattr inode
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 35) * operation is supplied.
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 36) *
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 37) * If the inode has been found through an idmapped mount the user namespace of
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 38) * the vfsmount must be passed through @mnt_userns. This function will then
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 39) * take care to map the inode according to @mnt_userns before filling in the
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 40) * uid and gid filds. On non-idmapped mounts or if permission checking is to be
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 41) * performed on the raw inode simply passs init_user_ns.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 42) */
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 43) void generic_fillattr(struct user_namespace *mnt_userns, struct inode *inode,
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 44) struct kstat *stat)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 45) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 46) stat->dev = inode->i_sb->s_dev;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47) stat->ino = inode->i_ino;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 48) stat->mode = inode->i_mode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 49) stat->nlink = inode->i_nlink;
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 50) stat->uid = i_uid_into_mnt(mnt_userns, inode);
0d56a4518d5ea (Christian Brauner 2021-01-21 14:19:30 +0100 51) stat->gid = i_gid_into_mnt(mnt_userns, inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 52) stat->rdev = inode->i_rdev;
3ddcd0569cd68 (Linus Torvalds 2011-08-06 22:45:50 -0700 53) stat->size = i_size_read(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 54) stat->atime = inode->i_atime;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 55) stat->mtime = inode->i_mtime;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 56) stat->ctime = inode->i_ctime;
93407472a21b8 (Fabian Frederick 2017-02-27 14:28:32 -0800 57) stat->blksize = i_blocksize(inode);
3ddcd0569cd68 (Linus Torvalds 2011-08-06 22:45:50 -0700 58) stat->blocks = inode->i_blocks;
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 59) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 60) EXPORT_SYMBOL(generic_fillattr);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 61)
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 62) /**
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 63) * vfs_getattr_nosec - getattr without security checks
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 64) * @path: file to get attributes from
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 65) * @stat: structure to return attributes in
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 66) * @request_mask: STATX_xxx flags indicating what the caller wants
f2d077ff1b5c1 (Christoph Hellwig 2020-09-26 09:04:01 +0200 67) * @query_flags: Query mode (AT_STATX_SYNC_TYPE)
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 68) *
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 69) * Get attributes without calling security_inode_getattr.
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 70) *
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 71) * Currently the only caller other than vfs_getattr is internal to the
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 72) * filehandle lookup code, which uses only the inode number and returns no
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 73) * attributes to any user. Any other code probably wants vfs_getattr.
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 74) */
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 75) int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 76) u32 request_mask, unsigned int query_flags)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 77) {
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 78) struct user_namespace *mnt_userns;
bb668734c4c96 (David Howells 2015-03-17 22:26:21 +0000 79) struct inode *inode = d_backing_inode(path->dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 80)
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 81) memset(stat, 0, sizeof(*stat));
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 82) stat->result_mask |= STATX_BASIC_STATS;
f2d077ff1b5c1 (Christoph Hellwig 2020-09-26 09:04:01 +0200 83) query_flags &= AT_STATX_SYNC_TYPE;
801e523796004 (Christoph Hellwig 2019-01-21 16:23:26 +0100 84)
801e523796004 (Christoph Hellwig 2019-01-21 16:23:26 +0100 85) /* allow the fs to override these if it really wants to */
761e28fa270a3 (Miklos Szeredi 2020-05-14 16:44:24 +0200 86) /* SB_NOATIME means filesystem supplies dummy atime value */
761e28fa270a3 (Miklos Szeredi 2020-05-14 16:44:24 +0200 87) if (inode->i_sb->s_flags & SB_NOATIME)
801e523796004 (Christoph Hellwig 2019-01-21 16:23:26 +0100 88) stat->result_mask &= ~STATX_ATIME;
5afa7e8b70d65 (Theodore Ts'o 2021-04-17 23:03:50 -0400 89)
5afa7e8b70d65 (Theodore Ts'o 2021-04-17 23:03:50 -0400 90) /*
5afa7e8b70d65 (Theodore Ts'o 2021-04-17 23:03:50 -0400 91) * Note: If you add another clause to set an attribute flag, please
5afa7e8b70d65 (Theodore Ts'o 2021-04-17 23:03:50 -0400 92) * update attributes_mask below.
5afa7e8b70d65 (Theodore Ts'o 2021-04-17 23:03:50 -0400 93) */
801e523796004 (Christoph Hellwig 2019-01-21 16:23:26 +0100 94) if (IS_AUTOMOUNT(inode))
801e523796004 (Christoph Hellwig 2019-01-21 16:23:26 +0100 95) stat->attributes |= STATX_ATTR_AUTOMOUNT;
801e523796004 (Christoph Hellwig 2019-01-21 16:23:26 +0100 96)
712b2698e4c02 (Ira Weiny 2020-04-30 07:41:34 -0700 97) if (IS_DAX(inode))
712b2698e4c02 (Ira Weiny 2020-04-30 07:41:34 -0700 98) stat->attributes |= STATX_ATTR_DAX;
712b2698e4c02 (Ira Weiny 2020-04-30 07:41:34 -0700 99)
5afa7e8b70d65 (Theodore Ts'o 2021-04-17 23:03:50 -0400 100) stat->attributes_mask |= (STATX_ATTR_AUTOMOUNT |
5afa7e8b70d65 (Theodore Ts'o 2021-04-17 23:03:50 -0400 101) STATX_ATTR_DAX);
5afa7e8b70d65 (Theodore Ts'o 2021-04-17 23:03:50 -0400 102)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 103) mnt_userns = mnt_user_ns(path->mnt);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 104) if (inode->i_op->getattr)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 105) return inode->i_op->getattr(mnt_userns, path, stat,
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 106) request_mask, query_flags);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 107)
549c7297717c3 (Christian Brauner 2021-01-21 14:19:43 +0100 108) generic_fillattr(mnt_userns, inode, stat);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 109) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 110) }
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 111) EXPORT_SYMBOL(vfs_getattr_nosec);
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 112)
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 113) /*
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 114) * vfs_getattr - Get the enhanced basic attributes of a file
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 115) * @path: The file of interest
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 116) * @stat: Where to return the statistics
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 117) * @request_mask: STATX_xxx flags indicating what the caller wants
f2d077ff1b5c1 (Christoph Hellwig 2020-09-26 09:04:01 +0200 118) * @query_flags: Query mode (AT_STATX_SYNC_TYPE)
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 119) *
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 120) * Ask the filesystem for a file's attributes. The caller must indicate in
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 121) * request_mask and query_flags to indicate what they want.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 122) *
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 123) * If the file is remote, the filesystem can be forced to update the attributes
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 124) * from the backing store by passing AT_STATX_FORCE_SYNC in query_flags or can
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 125) * suppress the update by passing AT_STATX_DONT_SYNC.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 126) *
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 127) * Bits must have been set in request_mask to indicate which attributes the
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 128) * caller wants retrieving. Any such attribute not requested may be returned
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 129) * anyway, but the value may be approximate, and, if remote, may not have been
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 130) * synchronised with the server.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 131) *
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 132) * 0 will be returned on success, and a -ve error code if unsuccessful.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 133) */
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 134) int vfs_getattr(const struct path *path, struct kstat *stat,
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 135) u32 request_mask, unsigned int query_flags)
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 136) {
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 137) int retval;
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 138)
3f7036a071b87 (Al Viro 2015-03-08 19:28:30 -0400 139) retval = security_inode_getattr(path);
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 140) if (retval)
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 141) return retval;
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 142) return vfs_getattr_nosec(path, stat, request_mask, query_flags);
b7a6ec52dd4ec (J. Bruce Fields 2013-10-02 17:01:18 -0400 143) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 144) EXPORT_SYMBOL(vfs_getattr);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 145)
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 146) /**
da9aa5d96bfe4 (Christoph Hellwig 2020-09-26 09:03:57 +0200 147) * vfs_fstat - Get the basic attributes by file descriptor
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 148) * @fd: The file descriptor referring to the file of interest
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 149) * @stat: The result structure to fill in.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 150) *
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 151) * This function is a wrapper around vfs_getattr(). The main difference is
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 152) * that it uses a file descriptor to determine the file location.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 153) *
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 154) * 0 will be returned on success, and a -ve error code if unsuccessful.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 155) */
da9aa5d96bfe4 (Christoph Hellwig 2020-09-26 09:03:57 +0200 156) int vfs_fstat(int fd, struct kstat *stat)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 157) {
8c7493aa3e9ae (Eric Biggers 2017-03-31 18:31:32 +0100 158) struct fd f;
da9aa5d96bfe4 (Christoph Hellwig 2020-09-26 09:03:57 +0200 159) int error;
8c7493aa3e9ae (Eric Biggers 2017-03-31 18:31:32 +0100 160)
8c7493aa3e9ae (Eric Biggers 2017-03-31 18:31:32 +0100 161) f = fdget_raw(fd);
da9aa5d96bfe4 (Christoph Hellwig 2020-09-26 09:03:57 +0200 162) if (!f.file)
da9aa5d96bfe4 (Christoph Hellwig 2020-09-26 09:03:57 +0200 163) return -EBADF;
da9aa5d96bfe4 (Christoph Hellwig 2020-09-26 09:03:57 +0200 164) error = vfs_getattr(&f.file->f_path, stat, STATX_BASIC_STATS, 0);
da9aa5d96bfe4 (Christoph Hellwig 2020-09-26 09:03:57 +0200 165) fdput(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 166) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 167) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 168)
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 169) /**
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 170) * vfs_statx - Get basic and extra attributes by filename
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 171) * @dfd: A file descriptor representing the base dir for a relative filename
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 172) * @filename: The name of the file of interest
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 173) * @flags: Flags to control the query
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 174) * @stat: The result structure to fill in.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 175) * @request_mask: STATX_xxx flags indicating what the caller wants
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 176) *
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 177) * This function is a wrapper around vfs_getattr(). The main difference is
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 178) * that it uses a filename and base directory to determine the file location.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 179) * Additionally, the use of AT_SYMLINK_NOFOLLOW in flags will prevent a symlink
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 180) * at the given name from being referenced.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 181) *
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 182) * 0 will be returned on success, and a -ve error code if unsuccessful.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 183) */
09f1bde4017e9 (Christoph Hellwig 2020-09-26 09:03:59 +0200 184) static int vfs_statx(int dfd, const char __user *filename, int flags,
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 185) struct kstat *stat, u32 request_mask)
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 186) {
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 187) struct path path;
b3f0515004a5e (Christoph Hellwig 2020-09-26 09:04:00 +0200 188) unsigned lookup_flags = 0;
b3f0515004a5e (Christoph Hellwig 2020-09-26 09:04:00 +0200 189) int error;
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 190)
b3f0515004a5e (Christoph Hellwig 2020-09-26 09:04:00 +0200 191) if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH |
f2d077ff1b5c1 (Christoph Hellwig 2020-09-26 09:04:01 +0200 192) AT_STATX_SYNC_TYPE))
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 193) return -EINVAL;
b3f0515004a5e (Christoph Hellwig 2020-09-26 09:04:00 +0200 194)
b3f0515004a5e (Christoph Hellwig 2020-09-26 09:04:00 +0200 195) if (!(flags & AT_SYMLINK_NOFOLLOW))
b3f0515004a5e (Christoph Hellwig 2020-09-26 09:04:00 +0200 196) lookup_flags |= LOOKUP_FOLLOW;
b3f0515004a5e (Christoph Hellwig 2020-09-26 09:04:00 +0200 197) if (!(flags & AT_NO_AUTOMOUNT))
b3f0515004a5e (Christoph Hellwig 2020-09-26 09:04:00 +0200 198) lookup_flags |= LOOKUP_AUTOMOUNT;
b3f0515004a5e (Christoph Hellwig 2020-09-26 09:04:00 +0200 199) if (flags & AT_EMPTY_PATH)
b3f0515004a5e (Christoph Hellwig 2020-09-26 09:04:00 +0200 200) lookup_flags |= LOOKUP_EMPTY;
b3f0515004a5e (Christoph Hellwig 2020-09-26 09:04:00 +0200 201)
836fb7e7b978e (Jeff Layton 2012-12-11 12:10:05 -0500 202) retry:
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 203) error = user_path_at(dfd, filename, lookup_flags, &path);
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 204) if (error)
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 205) goto out;
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 206)
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 207) error = vfs_getattr(&path, stat, request_mask, flags);
fa2fcf4f1df15 (Miklos Szeredi 2020-05-14 16:44:24 +0200 208) stat->mnt_id = real_mount(path.mnt)->mnt_id;
fa2fcf4f1df15 (Miklos Szeredi 2020-05-14 16:44:24 +0200 209) stat->result_mask |= STATX_MNT_ID;
80340fe3605c0 (Miklos Szeredi 2020-05-14 16:44:24 +0200 210) if (path.mnt->mnt_root == path.dentry)
80340fe3605c0 (Miklos Szeredi 2020-05-14 16:44:24 +0200 211) stat->attributes |= STATX_ATTR_MOUNT_ROOT;
80340fe3605c0 (Miklos Szeredi 2020-05-14 16:44:24 +0200 212) stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 213) path_put(&path);
836fb7e7b978e (Jeff Layton 2012-12-11 12:10:05 -0500 214) if (retry_estale(error, lookup_flags)) {
836fb7e7b978e (Jeff Layton 2012-12-11 12:10:05 -0500 215) lookup_flags |= LOOKUP_REVAL;
836fb7e7b978e (Jeff Layton 2012-12-11 12:10:05 -0500 216) goto retry;
836fb7e7b978e (Jeff Layton 2012-12-11 12:10:05 -0500 217) }
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 218) out:
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 219) return error;
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 220) }
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 221)
09f1bde4017e9 (Christoph Hellwig 2020-09-26 09:03:59 +0200 222) int vfs_fstatat(int dfd, const char __user *filename,
09f1bde4017e9 (Christoph Hellwig 2020-09-26 09:03:59 +0200 223) struct kstat *stat, int flags)
09f1bde4017e9 (Christoph Hellwig 2020-09-26 09:03:59 +0200 224) {
09f1bde4017e9 (Christoph Hellwig 2020-09-26 09:03:59 +0200 225) return vfs_statx(dfd, filename, flags | AT_NO_AUTOMOUNT,
09f1bde4017e9 (Christoph Hellwig 2020-09-26 09:03:59 +0200 226) stat, STATX_BASIC_STATS);
09f1bde4017e9 (Christoph Hellwig 2020-09-26 09:03:59 +0200 227) }
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 228)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 229) #ifdef __ARCH_WANT_OLD_STAT
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 230)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 231) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 232) * For backward compatibility? Maybe this should be moved
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 233) * into arch/i386 instead?
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 234) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 235) static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * statbuf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 236) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 237) static int warncount = 5;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 238) struct __old_kernel_stat tmp;
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 239)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 240) if (warncount > 0) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 241) warncount--;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 242) printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 243) current->comm);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 244) } else if (warncount < 0) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 245) /* it's laughable, but... */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 246) warncount = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 247) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 248)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 249) memset(&tmp, 0, sizeof(struct __old_kernel_stat));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 250) tmp.st_dev = old_encode_dev(stat->dev);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 251) tmp.st_ino = stat->ino;
afefdbb28a0a2 (David Howells 2006-10-03 01:13:46 -0700 252) if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
afefdbb28a0a2 (David Howells 2006-10-03 01:13:46 -0700 253) return -EOVERFLOW;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 254) tmp.st_mode = stat->mode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 255) tmp.st_nlink = stat->nlink;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 256) if (tmp.st_nlink != stat->nlink)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 257) return -EOVERFLOW;
a7c1938e22c02 (Eric W. Biederman 2012-02-09 09:10:30 -0800 258) SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
a7c1938e22c02 (Eric W. Biederman 2012-02-09 09:10:30 -0800 259) SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 260) tmp.st_rdev = old_encode_dev(stat->rdev);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 261) #if BITS_PER_LONG == 32
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 262) if (stat->size > MAX_NON_LFS)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 263) return -EOVERFLOW;
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 264) #endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 265) tmp.st_size = stat->size;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 266) tmp.st_atime = stat->atime.tv_sec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 267) tmp.st_mtime = stat->mtime.tv_sec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 268) tmp.st_ctime = stat->ctime.tv_sec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 269) return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 270) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 271)
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 272) SYSCALL_DEFINE2(stat, const char __user *, filename,
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 273) struct __old_kernel_stat __user *, statbuf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 274) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 275) struct kstat stat;
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 276) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 277)
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 278) error = vfs_stat(filename, &stat);
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 279) if (error)
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 280) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 281)
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 282) return cp_old_stat(&stat, statbuf);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 283) }
257ac264d6901 (Heiko Carstens 2009-01-14 14:14:13 +0100 284)
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 285) SYSCALL_DEFINE2(lstat, const char __user *, filename,
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 286) struct __old_kernel_stat __user *, statbuf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 287) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 288) struct kstat stat;
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 289) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 290)
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 291) error = vfs_lstat(filename, &stat);
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 292) if (error)
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 293) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 294)
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 295) return cp_old_stat(&stat, statbuf);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 296) }
257ac264d6901 (Heiko Carstens 2009-01-14 14:14:13 +0100 297)
257ac264d6901 (Heiko Carstens 2009-01-14 14:14:13 +0100 298) SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, statbuf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 299) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 300) struct kstat stat;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 301) int error = vfs_fstat(fd, &stat);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 302)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 303) if (!error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 304) error = cp_old_stat(&stat, statbuf);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 305)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 306) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 307) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 308)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 309) #endif /* __ARCH_WANT_OLD_STAT */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 310)
82b355d161c95 (Arnd Bergmann 2018-04-13 11:50:12 +0200 311) #ifdef __ARCH_WANT_NEW_STAT
82b355d161c95 (Arnd Bergmann 2018-04-13 11:50:12 +0200 312)
a52dd971f9478 (Linus Torvalds 2012-05-06 17:47:30 -0700 313) #if BITS_PER_LONG == 32
a52dd971f9478 (Linus Torvalds 2012-05-06 17:47:30 -0700 314) # define choose_32_64(a,b) a
a52dd971f9478 (Linus Torvalds 2012-05-06 17:47:30 -0700 315) #else
a52dd971f9478 (Linus Torvalds 2012-05-06 17:47:30 -0700 316) # define choose_32_64(a,b) b
a52dd971f9478 (Linus Torvalds 2012-05-06 17:47:30 -0700 317) #endif
a52dd971f9478 (Linus Torvalds 2012-05-06 17:47:30 -0700 318)
4c416f42ee961 (Yaowei Bai 2016-01-15 16:58:01 -0800 319) #define valid_dev(x) choose_32_64(old_valid_dev(x),true)
a52dd971f9478 (Linus Torvalds 2012-05-06 17:47:30 -0700 320) #define encode_dev(x) choose_32_64(old_encode_dev,new_encode_dev)(x)
a52dd971f9478 (Linus Torvalds 2012-05-06 17:47:30 -0700 321)
8529f613b6945 (Linus Torvalds 2012-05-06 18:02:40 -0700 322) #ifndef INIT_STRUCT_STAT_PADDING
8529f613b6945 (Linus Torvalds 2012-05-06 18:02:40 -0700 323) # define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st))
8529f613b6945 (Linus Torvalds 2012-05-06 18:02:40 -0700 324) #endif
8529f613b6945 (Linus Torvalds 2012-05-06 18:02:40 -0700 325)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 326) static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 327) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 328) struct stat tmp;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 329)
a52dd971f9478 (Linus Torvalds 2012-05-06 17:47:30 -0700 330) if (!valid_dev(stat->dev) || !valid_dev(stat->rdev))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 331) return -EOVERFLOW;
a52dd971f9478 (Linus Torvalds 2012-05-06 17:47:30 -0700 332) #if BITS_PER_LONG == 32
a52dd971f9478 (Linus Torvalds 2012-05-06 17:47:30 -0700 333) if (stat->size > MAX_NON_LFS)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 334) return -EOVERFLOW;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 335) #endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 336)
8529f613b6945 (Linus Torvalds 2012-05-06 18:02:40 -0700 337) INIT_STRUCT_STAT_PADDING(tmp);
a52dd971f9478 (Linus Torvalds 2012-05-06 17:47:30 -0700 338) tmp.st_dev = encode_dev(stat->dev);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 339) tmp.st_ino = stat->ino;
afefdbb28a0a2 (David Howells 2006-10-03 01:13:46 -0700 340) if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
afefdbb28a0a2 (David Howells 2006-10-03 01:13:46 -0700 341) return -EOVERFLOW;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 342) tmp.st_mode = stat->mode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 343) tmp.st_nlink = stat->nlink;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 344) if (tmp.st_nlink != stat->nlink)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 345) return -EOVERFLOW;
a7c1938e22c02 (Eric W. Biederman 2012-02-09 09:10:30 -0800 346) SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
a7c1938e22c02 (Eric W. Biederman 2012-02-09 09:10:30 -0800 347) SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
a52dd971f9478 (Linus Torvalds 2012-05-06 17:47:30 -0700 348) tmp.st_rdev = encode_dev(stat->rdev);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 349) tmp.st_size = stat->size;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 350) tmp.st_atime = stat->atime.tv_sec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 351) tmp.st_mtime = stat->mtime.tv_sec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 352) tmp.st_ctime = stat->ctime.tv_sec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 353) #ifdef STAT_HAVE_NSEC
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 354) tmp.st_atime_nsec = stat->atime.tv_nsec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 355) tmp.st_mtime_nsec = stat->mtime.tv_nsec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 356) tmp.st_ctime_nsec = stat->ctime.tv_nsec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 357) #endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 358) tmp.st_blocks = stat->blocks;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 359) tmp.st_blksize = stat->blksize;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 360) return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 361) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 362)
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 363) SYSCALL_DEFINE2(newstat, const char __user *, filename,
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 364) struct stat __user *, statbuf)
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 365) {
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 366) struct kstat stat;
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 367) int error = vfs_stat(filename, &stat);
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 368)
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 369) if (error)
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 370) return error;
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 371) return cp_new_stat(&stat, statbuf);
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 372) }
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 373)
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 374) SYSCALL_DEFINE2(newlstat, const char __user *, filename,
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 375) struct stat __user *, statbuf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 376) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 377) struct kstat stat;
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 378) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 379)
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 380) error = vfs_lstat(filename, &stat);
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 381) if (error)
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 382) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 383)
2eae7a1874ca5 (Christoph Hellwig 2009-04-08 16:34:03 -0400 384) return cp_new_stat(&stat, statbuf);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 385) }
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 386)
2833c28aa0d03 (Andreas Schwab 2006-04-27 15:46:42 +0200 387) #if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 388) SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
6559eed8ca7db (Heiko Carstens 2009-01-14 14:14:32 +0100 389) struct stat __user *, statbuf, int, flag)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 390) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 391) struct kstat stat;
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 392) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 393)
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 394) error = vfs_fstatat(dfd, filename, &stat, flag);
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 395) if (error)
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 396) return error;
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 397) return cp_new_stat(&stat, statbuf);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 398) }
cff2b760096d1 (Ulrich Drepper 2006-02-11 17:55:47 -0800 399) #endif
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 400)
257ac264d6901 (Heiko Carstens 2009-01-14 14:14:13 +0100 401) SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct stat __user *, statbuf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 402) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 403) struct kstat stat;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 404) int error = vfs_fstat(fd, &stat);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 405)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 406) if (!error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 407) error = cp_new_stat(&stat, statbuf);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 408)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 409) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 410) }
82b355d161c95 (Arnd Bergmann 2018-04-13 11:50:12 +0200 411) #endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 412)
2dae0248061e6 (Dominik Brodowski 2018-03-11 11:34:27 +0100 413) static int do_readlinkat(int dfd, const char __user *pathname,
2dae0248061e6 (Dominik Brodowski 2018-03-11 11:34:27 +0100 414) char __user *buf, int bufsiz)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 415) {
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 416) struct path path;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 417) int error;
1fa1e7f615f4d (Andy Whitcroft 2011-11-02 09:44:39 +0100 418) int empty = 0;
7955119e02d9f (Jeff Layton 2012-12-11 12:10:06 -0500 419) unsigned int lookup_flags = LOOKUP_EMPTY;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 420)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 421) if (bufsiz <= 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 422) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 423)
7955119e02d9f (Jeff Layton 2012-12-11 12:10:06 -0500 424) retry:
7955119e02d9f (Jeff Layton 2012-12-11 12:10:06 -0500 425) error = user_path_at_empty(dfd, pathname, lookup_flags, &path, &empty);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 426) if (!error) {
bb668734c4c96 (David Howells 2015-03-17 22:26:21 +0000 427) struct inode *inode = d_backing_inode(path.dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 428)
1fa1e7f615f4d (Andy Whitcroft 2011-11-02 09:44:39 +0100 429) error = empty ? -ENOENT : -EINVAL;
fd4a0edf2a3d7 (Miklos Szeredi 2016-12-09 16:45:04 +0100 430) /*
fd4a0edf2a3d7 (Miklos Szeredi 2016-12-09 16:45:04 +0100 431) * AFS mountpoints allow readlink(2) but are not symlinks
fd4a0edf2a3d7 (Miklos Szeredi 2016-12-09 16:45:04 +0100 432) */
fd4a0edf2a3d7 (Miklos Szeredi 2016-12-09 16:45:04 +0100 433) if (d_is_symlink(path.dentry) || inode->i_op->readlink) {
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 434) error = security_inode_readlink(path.dentry);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 435) if (!error) {
68ac1234fb949 (Al Viro 2012-03-15 08:21:57 -0400 436) touch_atime(&path);
fd4a0edf2a3d7 (Miklos Szeredi 2016-12-09 16:45:04 +0100 437) error = vfs_readlink(path.dentry, buf, bufsiz);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 438) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 439) }
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 440) path_put(&path);
7955119e02d9f (Jeff Layton 2012-12-11 12:10:06 -0500 441) if (retry_estale(error, lookup_flags)) {
7955119e02d9f (Jeff Layton 2012-12-11 12:10:06 -0500 442) lookup_flags |= LOOKUP_REVAL;
7955119e02d9f (Jeff Layton 2012-12-11 12:10:06 -0500 443) goto retry;
7955119e02d9f (Jeff Layton 2012-12-11 12:10:06 -0500 444) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 445) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 446) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 447) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 448)
2dae0248061e6 (Dominik Brodowski 2018-03-11 11:34:27 +0100 449) SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
2dae0248061e6 (Dominik Brodowski 2018-03-11 11:34:27 +0100 450) char __user *, buf, int, bufsiz)
2dae0248061e6 (Dominik Brodowski 2018-03-11 11:34:27 +0100 451) {
2dae0248061e6 (Dominik Brodowski 2018-03-11 11:34:27 +0100 452) return do_readlinkat(dfd, pathname, buf, bufsiz);
2dae0248061e6 (Dominik Brodowski 2018-03-11 11:34:27 +0100 453) }
2dae0248061e6 (Dominik Brodowski 2018-03-11 11:34:27 +0100 454)
002c8976ee537 (Heiko Carstens 2009-01-14 14:14:18 +0100 455) SYSCALL_DEFINE3(readlink, const char __user *, path, char __user *, buf,
002c8976ee537 (Heiko Carstens 2009-01-14 14:14:18 +0100 456) int, bufsiz)
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 457) {
2dae0248061e6 (Dominik Brodowski 2018-03-11 11:34:27 +0100 458) return do_readlinkat(AT_FDCWD, path, buf, bufsiz);
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 459) }
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 460)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 461)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 462) /* ---------- LFS-64 ----------- */
0753f70f07fbb (Catalin Marinas 2012-03-19 15:13:51 +0000 463) #if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 464)
8529f613b6945 (Linus Torvalds 2012-05-06 18:02:40 -0700 465) #ifndef INIT_STRUCT_STAT64_PADDING
8529f613b6945 (Linus Torvalds 2012-05-06 18:02:40 -0700 466) # define INIT_STRUCT_STAT64_PADDING(st) memset(&st, 0, sizeof(st))
8529f613b6945 (Linus Torvalds 2012-05-06 18:02:40 -0700 467) #endif
8529f613b6945 (Linus Torvalds 2012-05-06 18:02:40 -0700 468)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 469) static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 470) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 471) struct stat64 tmp;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 472)
8529f613b6945 (Linus Torvalds 2012-05-06 18:02:40 -0700 473) INIT_STRUCT_STAT64_PADDING(tmp);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 474) #ifdef CONFIG_MIPS
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 475) /* mips has weird padding, so we don't get 64 bits there */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 476) tmp.st_dev = new_encode_dev(stat->dev);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 477) tmp.st_rdev = new_encode_dev(stat->rdev);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 478) #else
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 479) tmp.st_dev = huge_encode_dev(stat->dev);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 480) tmp.st_rdev = huge_encode_dev(stat->rdev);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 481) #endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 482) tmp.st_ino = stat->ino;
afefdbb28a0a2 (David Howells 2006-10-03 01:13:46 -0700 483) if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
afefdbb28a0a2 (David Howells 2006-10-03 01:13:46 -0700 484) return -EOVERFLOW;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 485) #ifdef STAT64_HAS_BROKEN_ST_INO
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 486) tmp.__st_ino = stat->ino;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 487) #endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 488) tmp.st_mode = stat->mode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 489) tmp.st_nlink = stat->nlink;
a7c1938e22c02 (Eric W. Biederman 2012-02-09 09:10:30 -0800 490) tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid);
a7c1938e22c02 (Eric W. Biederman 2012-02-09 09:10:30 -0800 491) tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 492) tmp.st_atime = stat->atime.tv_sec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 493) tmp.st_atime_nsec = stat->atime.tv_nsec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 494) tmp.st_mtime = stat->mtime.tv_sec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 495) tmp.st_mtime_nsec = stat->mtime.tv_nsec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 496) tmp.st_ctime = stat->ctime.tv_sec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 497) tmp.st_ctime_nsec = stat->ctime.tv_nsec;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 498) tmp.st_size = stat->size;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 499) tmp.st_blocks = stat->blocks;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 500) tmp.st_blksize = stat->blksize;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 501) return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 502) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 503)
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 504) SYSCALL_DEFINE2(stat64, const char __user *, filename,
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 505) struct stat64 __user *, statbuf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 506) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 507) struct kstat stat;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 508) int error = vfs_stat(filename, &stat);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 509)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 510) if (!error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 511) error = cp_new_stat64(&stat, statbuf);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 512)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 513) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 514) }
257ac264d6901 (Heiko Carstens 2009-01-14 14:14:13 +0100 515)
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 516) SYSCALL_DEFINE2(lstat64, const char __user *, filename,
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 517) struct stat64 __user *, statbuf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 518) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 519) struct kstat stat;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 520) int error = vfs_lstat(filename, &stat);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 521)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 522) if (!error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 523) error = cp_new_stat64(&stat, statbuf);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 524)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 525) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 526) }
257ac264d6901 (Heiko Carstens 2009-01-14 14:14:13 +0100 527)
257ac264d6901 (Heiko Carstens 2009-01-14 14:14:13 +0100 528) SYSCALL_DEFINE2(fstat64, unsigned long, fd, struct stat64 __user *, statbuf)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 529) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 530) struct kstat stat;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 531) int error = vfs_fstat(fd, &stat);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 532)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 533) if (!error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 534) error = cp_new_stat64(&stat, statbuf);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 535)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 536) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 537) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 538)
c7887325230ae (David Howells 2010-08-11 11:26:22 +0100 539) SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
6559eed8ca7db (Heiko Carstens 2009-01-14 14:14:32 +0100 540) struct stat64 __user *, statbuf, int, flag)
cff2b760096d1 (Ulrich Drepper 2006-02-11 17:55:47 -0800 541) {
cff2b760096d1 (Ulrich Drepper 2006-02-11 17:55:47 -0800 542) struct kstat stat;
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 543) int error;
cff2b760096d1 (Ulrich Drepper 2006-02-11 17:55:47 -0800 544)
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 545) error = vfs_fstatat(dfd, filename, &stat, flag);
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 546) if (error)
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 547) return error;
0112fc2229847 (Oleg Drokin 2009-04-08 20:05:42 +0400 548) return cp_new_stat64(&stat, statbuf);
cff2b760096d1 (Ulrich Drepper 2006-02-11 17:55:47 -0800 549) }
0753f70f07fbb (Catalin Marinas 2012-03-19 15:13:51 +0000 550) #endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 551)
6f88cc176a335 (Bijan Mottahedeh 2020-05-22 21:31:19 -0700 552) static noinline_for_stack int
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 553) cp_statx(const struct kstat *stat, struct statx __user *buffer)
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 554) {
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 555) struct statx tmp;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 556)
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 557) memset(&tmp, 0, sizeof(tmp));
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 558)
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 559) tmp.stx_mask = stat->result_mask;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 560) tmp.stx_blksize = stat->blksize;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 561) tmp.stx_attributes = stat->attributes;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 562) tmp.stx_nlink = stat->nlink;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 563) tmp.stx_uid = from_kuid_munged(current_user_ns(), stat->uid);
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 564) tmp.stx_gid = from_kgid_munged(current_user_ns(), stat->gid);
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 565) tmp.stx_mode = stat->mode;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 566) tmp.stx_ino = stat->ino;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 567) tmp.stx_size = stat->size;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 568) tmp.stx_blocks = stat->blocks;
3209f68b3ca46 (David Howells 2017-03-31 18:32:17 +0100 569) tmp.stx_attributes_mask = stat->attributes_mask;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 570) tmp.stx_atime.tv_sec = stat->atime.tv_sec;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 571) tmp.stx_atime.tv_nsec = stat->atime.tv_nsec;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 572) tmp.stx_btime.tv_sec = stat->btime.tv_sec;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 573) tmp.stx_btime.tv_nsec = stat->btime.tv_nsec;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 574) tmp.stx_ctime.tv_sec = stat->ctime.tv_sec;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 575) tmp.stx_ctime.tv_nsec = stat->ctime.tv_nsec;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 576) tmp.stx_mtime.tv_sec = stat->mtime.tv_sec;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 577) tmp.stx_mtime.tv_nsec = stat->mtime.tv_nsec;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 578) tmp.stx_rdev_major = MAJOR(stat->rdev);
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 579) tmp.stx_rdev_minor = MINOR(stat->rdev);
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 580) tmp.stx_dev_major = MAJOR(stat->dev);
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 581) tmp.stx_dev_minor = MINOR(stat->dev);
fa2fcf4f1df15 (Miklos Szeredi 2020-05-14 16:44:24 +0200 582) tmp.stx_mnt_id = stat->mnt_id;
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 583)
64bd72048a2ac (Eric Biggers 2017-03-31 18:31:48 +0100 584) return copy_to_user(buffer, &tmp, sizeof(tmp)) ? -EFAULT : 0;
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 585) }
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 586)
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 587) int do_statx(int dfd, const char __user *filename, unsigned flags,
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 588) unsigned int mask, struct statx __user *buffer)
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 589) {
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 590) struct kstat stat;
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 591) int error;
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 592)
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 593) if (mask & STATX__RESERVED)
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 594) return -EINVAL;
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 595) if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 596) return -EINVAL;
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 597)
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 598) error = vfs_statx(dfd, filename, flags, &stat, mask);
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 599) if (error)
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 600) return error;
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 601)
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 602) return cp_statx(&stat, buffer);
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 603) }
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 604)
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 605) /**
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 606) * sys_statx - System call to get enhanced stats
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 607) * @dfd: Base directory to pathwalk from *or* fd to stat.
1e2f82d1e9d12 (David Howells 2017-04-26 22:15:55 +0100 608) * @filename: File to stat or "" with AT_EMPTY_PATH
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 609) * @flags: AT_* flags to control pathwalk.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 610) * @mask: Parts of statx struct actually required.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 611) * @buffer: Result buffer.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 612) *
1e2f82d1e9d12 (David Howells 2017-04-26 22:15:55 +0100 613) * Note that fstat() can be emulated by setting dfd to the fd of interest,
1e2f82d1e9d12 (David Howells 2017-04-26 22:15:55 +0100 614) * supplying "" as the filename and setting AT_EMPTY_PATH in the flags.
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 615) */
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 616) SYSCALL_DEFINE5(statx,
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 617) int, dfd, const char __user *, filename, unsigned, flags,
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 618) unsigned int, mask,
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 619) struct statx __user *, buffer)
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 620) {
0018784fc84f6 (Bijan Mottahedeh 2020-05-22 21:31:17 -0700 621) return do_statx(dfd, filename, flags, mask, buffer);
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 622) }
a528d35e8bfcc (David Howells 2017-01-31 16:46:22 +0000 623)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 624) #ifdef CONFIG_COMPAT
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 625) static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 626) {
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 627) struct compat_stat tmp;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 628)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 629) if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 630) return -EOVERFLOW;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 631)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 632) memset(&tmp, 0, sizeof(tmp));
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 633) tmp.st_dev = old_encode_dev(stat->dev);
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 634) tmp.st_ino = stat->ino;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 635) if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 636) return -EOVERFLOW;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 637) tmp.st_mode = stat->mode;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 638) tmp.st_nlink = stat->nlink;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 639) if (tmp.st_nlink != stat->nlink)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 640) return -EOVERFLOW;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 641) SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 642) SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 643) tmp.st_rdev = old_encode_dev(stat->rdev);
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 644) if ((u64) stat->size > MAX_NON_LFS)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 645) return -EOVERFLOW;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 646) tmp.st_size = stat->size;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 647) tmp.st_atime = stat->atime.tv_sec;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 648) tmp.st_atime_nsec = stat->atime.tv_nsec;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 649) tmp.st_mtime = stat->mtime.tv_sec;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 650) tmp.st_mtime_nsec = stat->mtime.tv_nsec;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 651) tmp.st_ctime = stat->ctime.tv_sec;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 652) tmp.st_ctime_nsec = stat->ctime.tv_nsec;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 653) tmp.st_blocks = stat->blocks;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 654) tmp.st_blksize = stat->blksize;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 655) return copy_to_user(ubuf, &tmp, sizeof(tmp)) ? -EFAULT : 0;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 656) }
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 657)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 658) COMPAT_SYSCALL_DEFINE2(newstat, const char __user *, filename,
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 659) struct compat_stat __user *, statbuf)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 660) {
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 661) struct kstat stat;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 662) int error;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 663)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 664) error = vfs_stat(filename, &stat);
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 665) if (error)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 666) return error;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 667) return cp_compat_stat(&stat, statbuf);
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 668) }
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 669)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 670) COMPAT_SYSCALL_DEFINE2(newlstat, const char __user *, filename,
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 671) struct compat_stat __user *, statbuf)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 672) {
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 673) struct kstat stat;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 674) int error;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 675)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 676) error = vfs_lstat(filename, &stat);
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 677) if (error)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 678) return error;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 679) return cp_compat_stat(&stat, statbuf);
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 680) }
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 681)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 682) #ifndef __ARCH_WANT_STAT64
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 683) COMPAT_SYSCALL_DEFINE4(newfstatat, unsigned int, dfd,
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 684) const char __user *, filename,
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 685) struct compat_stat __user *, statbuf, int, flag)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 686) {
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 687) struct kstat stat;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 688) int error;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 689)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 690) error = vfs_fstatat(dfd, filename, &stat, flag);
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 691) if (error)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 692) return error;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 693) return cp_compat_stat(&stat, statbuf);
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 694) }
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 695) #endif
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 696)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 697) COMPAT_SYSCALL_DEFINE2(newfstat, unsigned int, fd,
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 698) struct compat_stat __user *, statbuf)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 699) {
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 700) struct kstat stat;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 701) int error = vfs_fstat(fd, &stat);
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 702)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 703) if (!error)
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 704) error = cp_compat_stat(&stat, statbuf);
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 705) return error;
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 706) }
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 707) #endif
ac565de31c950 (Al Viro 2017-04-08 18:13:00 -0400 708)
b462707e7ccad (Dmitry Monakhov 2009-12-14 15:21:12 +0300 709) /* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
b462707e7ccad (Dmitry Monakhov 2009-12-14 15:21:12 +0300 710) void __inode_add_bytes(struct inode *inode, loff_t bytes)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 711) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 712) inode->i_blocks += bytes >> 9;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 713) bytes &= 511;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 714) inode->i_bytes += bytes;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 715) if (inode->i_bytes >= 512) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 716) inode->i_blocks++;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 717) inode->i_bytes -= 512;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 718) }
b462707e7ccad (Dmitry Monakhov 2009-12-14 15:21:12 +0300 719) }
eb315d2ae6144 (Al Viro 2017-06-08 21:15:03 -0400 720) EXPORT_SYMBOL(__inode_add_bytes);
b462707e7ccad (Dmitry Monakhov 2009-12-14 15:21:12 +0300 721)
b462707e7ccad (Dmitry Monakhov 2009-12-14 15:21:12 +0300 722) void inode_add_bytes(struct inode *inode, loff_t bytes)
b462707e7ccad (Dmitry Monakhov 2009-12-14 15:21:12 +0300 723) {
b462707e7ccad (Dmitry Monakhov 2009-12-14 15:21:12 +0300 724) spin_lock(&inode->i_lock);
b462707e7ccad (Dmitry Monakhov 2009-12-14 15:21:12 +0300 725) __inode_add_bytes(inode, bytes);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 726) spin_unlock(&inode->i_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 727) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 728)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 729) EXPORT_SYMBOL(inode_add_bytes);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 730)
1c8924eb106c1 (Jan Kara 2013-08-17 09:32:32 -0400 731) void __inode_sub_bytes(struct inode *inode, loff_t bytes)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 732) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 733) inode->i_blocks -= bytes >> 9;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 734) bytes &= 511;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 735) if (inode->i_bytes < bytes) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 736) inode->i_blocks--;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 737) inode->i_bytes += 512;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 738) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 739) inode->i_bytes -= bytes;
1c8924eb106c1 (Jan Kara 2013-08-17 09:32:32 -0400 740) }
1c8924eb106c1 (Jan Kara 2013-08-17 09:32:32 -0400 741)
1c8924eb106c1 (Jan Kara 2013-08-17 09:32:32 -0400 742) EXPORT_SYMBOL(__inode_sub_bytes);
1c8924eb106c1 (Jan Kara 2013-08-17 09:32:32 -0400 743)
1c8924eb106c1 (Jan Kara 2013-08-17 09:32:32 -0400 744) void inode_sub_bytes(struct inode *inode, loff_t bytes)
1c8924eb106c1 (Jan Kara 2013-08-17 09:32:32 -0400 745) {
1c8924eb106c1 (Jan Kara 2013-08-17 09:32:32 -0400 746) spin_lock(&inode->i_lock);
1c8924eb106c1 (Jan Kara 2013-08-17 09:32:32 -0400 747) __inode_sub_bytes(inode, bytes);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 748) spin_unlock(&inode->i_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 749) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 750)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 751) EXPORT_SYMBOL(inode_sub_bytes);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 752)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 753) loff_t inode_get_bytes(struct inode *inode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 754) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 755) loff_t ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 756)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 757) spin_lock(&inode->i_lock);
f4a8116a4c8c8 (Jan Kara 2017-08-08 09:54:36 +0200 758) ret = __inode_get_bytes(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 759) spin_unlock(&inode->i_lock);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 760) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 761) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 762)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 763) EXPORT_SYMBOL(inode_get_bytes);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 764)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 765) void inode_set_bytes(struct inode *inode, loff_t bytes)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 766) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 767) /* Caller is here responsible for sufficient locking
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 768) * (ie. inode->i_lock) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 769) inode->i_blocks = bytes >> 9;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 770) inode->i_bytes = bytes & 511;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 771) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 772)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 773) EXPORT_SYMBOL(inode_set_bytes);