hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/fs/stat.c
....@@ -21,6 +21,9 @@
2121 #include <linux/uaccess.h>
2222 #include <asm/unistd.h>
2323
24
+#include "internal.h"
25
+#include "mount.h"
26
+
2427 /**
2528 * generic_fillattr - Fill in the basic attributes from the inode struct
2629 * @inode: Inode to use as the source
....@@ -45,20 +48,15 @@
4548 stat->ctime = inode->i_ctime;
4649 stat->blksize = i_blocksize(inode);
4750 stat->blocks = inode->i_blocks;
48
-
49
- if (IS_NOATIME(inode))
50
- stat->result_mask &= ~STATX_ATIME;
51
- if (IS_AUTOMOUNT(inode))
52
- stat->attributes |= STATX_ATTR_AUTOMOUNT;
5351 }
54
-EXPORT_SYMBOL(generic_fillattr);
52
+EXPORT_SYMBOL_NS(generic_fillattr, ANDROID_GKI_VFS_EXPORT_ONLY);
5553
5654 /**
5755 * vfs_getattr_nosec - getattr without security checks
5856 * @path: file to get attributes from
5957 * @stat: structure to return attributes in
6058 * @request_mask: STATX_xxx flags indicating what the caller wants
61
- * @query_flags: Query mode (KSTAT_QUERY_FLAGS)
59
+ * @query_flags: Query mode (AT_STATX_SYNC_TYPE)
6260 *
6361 * Get attributes without calling security_inode_getattr.
6462 *
....@@ -73,8 +71,26 @@
7371
7472 memset(stat, 0, sizeof(*stat));
7573 stat->result_mask |= STATX_BASIC_STATS;
76
- request_mask &= STATX_ALL;
77
- query_flags &= KSTAT_QUERY_FLAGS;
74
+ query_flags &= AT_STATX_SYNC_TYPE;
75
+
76
+ /* allow the fs to override these if it really wants to */
77
+ /* SB_NOATIME means filesystem supplies dummy atime value */
78
+ if (inode->i_sb->s_flags & SB_NOATIME)
79
+ stat->result_mask &= ~STATX_ATIME;
80
+
81
+ /*
82
+ * Note: If you add another clause to set an attribute flag, please
83
+ * update attributes_mask below.
84
+ */
85
+ if (IS_AUTOMOUNT(inode))
86
+ stat->attributes |= STATX_ATTR_AUTOMOUNT;
87
+
88
+ if (IS_DAX(inode))
89
+ stat->attributes |= STATX_ATTR_DAX;
90
+
91
+ stat->attributes_mask |= (STATX_ATTR_AUTOMOUNT |
92
+ STATX_ATTR_DAX);
93
+
7894 if (inode->i_op->getattr)
7995 return inode->i_op->getattr(path, stat, request_mask,
8096 query_flags);
....@@ -89,7 +105,7 @@
89105 * @path: The file of interest
90106 * @stat: Where to return the statistics
91107 * @request_mask: STATX_xxx flags indicating what the caller wants
92
- * @query_flags: Query mode (KSTAT_QUERY_FLAGS)
108
+ * @query_flags: Query mode (AT_STATX_SYNC_TYPE)
93109 *
94110 * Ask the filesystem for a file's attributes. The caller must indicate in
95111 * request_mask and query_flags to indicate what they want.
....@@ -118,35 +134,27 @@
118134 EXPORT_SYMBOL(vfs_getattr);
119135
120136 /**
121
- * vfs_statx_fd - Get the enhanced basic attributes by file descriptor
137
+ * vfs_fstat - Get the basic attributes by file descriptor
122138 * @fd: The file descriptor referring to the file of interest
123139 * @stat: The result structure to fill in.
124
- * @request_mask: STATX_xxx flags indicating what the caller wants
125
- * @query_flags: Query mode (KSTAT_QUERY_FLAGS)
126140 *
127141 * This function is a wrapper around vfs_getattr(). The main difference is
128142 * that it uses a file descriptor to determine the file location.
129143 *
130144 * 0 will be returned on success, and a -ve error code if unsuccessful.
131145 */
132
-int vfs_statx_fd(unsigned int fd, struct kstat *stat,
133
- u32 request_mask, unsigned int query_flags)
146
+int vfs_fstat(int fd, struct kstat *stat)
134147 {
135148 struct fd f;
136
- int error = -EBADF;
137
-
138
- if (query_flags & ~KSTAT_QUERY_FLAGS)
139
- return -EINVAL;
149
+ int error;
140150
141151 f = fdget_raw(fd);
142
- if (f.file) {
143
- error = vfs_getattr(&f.file->f_path, stat,
144
- request_mask, query_flags);
145
- fdput(f);
146
- }
152
+ if (!f.file)
153
+ return -EBADF;
154
+ error = vfs_getattr(&f.file->f_path, stat, STATX_BASIC_STATS, 0);
155
+ fdput(f);
147156 return error;
148157 }
149
-EXPORT_SYMBOL(vfs_statx_fd);
150158
151159 /**
152160 * vfs_statx - Get basic and extra attributes by filename
....@@ -163,21 +171,21 @@
163171 *
164172 * 0 will be returned on success, and a -ve error code if unsuccessful.
165173 */
166
-int vfs_statx(int dfd, const char __user *filename, int flags,
174
+static int vfs_statx(int dfd, const char __user *filename, int flags,
167175 struct kstat *stat, u32 request_mask)
168176 {
169177 struct path path;
170
- int error = -EINVAL;
171
- unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT;
178
+ unsigned lookup_flags = 0;
179
+ int error;
172180
173
- if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
174
- AT_EMPTY_PATH | KSTAT_QUERY_FLAGS)) != 0)
181
+ if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH |
182
+ AT_STATX_SYNC_TYPE))
175183 return -EINVAL;
176184
177
- if (flags & AT_SYMLINK_NOFOLLOW)
178
- lookup_flags &= ~LOOKUP_FOLLOW;
179
- if (flags & AT_NO_AUTOMOUNT)
180
- lookup_flags &= ~LOOKUP_AUTOMOUNT;
185
+ if (!(flags & AT_SYMLINK_NOFOLLOW))
186
+ lookup_flags |= LOOKUP_FOLLOW;
187
+ if (!(flags & AT_NO_AUTOMOUNT))
188
+ lookup_flags |= LOOKUP_AUTOMOUNT;
181189 if (flags & AT_EMPTY_PATH)
182190 lookup_flags |= LOOKUP_EMPTY;
183191
....@@ -187,6 +195,11 @@
187195 goto out;
188196
189197 error = vfs_getattr(&path, stat, request_mask, flags);
198
+ stat->mnt_id = real_mount(path.mnt)->mnt_id;
199
+ stat->result_mask |= STATX_MNT_ID;
200
+ if (path.mnt->mnt_root == path.dentry)
201
+ stat->attributes |= STATX_ATTR_MOUNT_ROOT;
202
+ stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;
190203 path_put(&path);
191204 if (retry_estale(error, lookup_flags)) {
192205 lookup_flags |= LOOKUP_REVAL;
....@@ -195,8 +208,13 @@
195208 out:
196209 return error;
197210 }
198
-EXPORT_SYMBOL(vfs_statx);
199211
212
+int vfs_fstatat(int dfd, const char __user *filename,
213
+ struct kstat *stat, int flags)
214
+{
215
+ return vfs_statx(dfd, filename, flags | AT_NO_AUTOMOUNT,
216
+ stat, STATX_BASIC_STATS);
217
+}
200218
201219 #ifdef __ARCH_WANT_OLD_STAT
202220
....@@ -280,14 +298,13 @@
280298
281299 #endif /* __ARCH_WANT_OLD_STAT */
282300
301
+#ifdef __ARCH_WANT_NEW_STAT
302
+
283303 #if BITS_PER_LONG == 32
284304 # define choose_32_64(a,b) a
285305 #else
286306 # define choose_32_64(a,b) b
287307 #endif
288
-
289
-#define valid_dev(x) choose_32_64(old_valid_dev(x),true)
290
-#define encode_dev(x) choose_32_64(old_encode_dev,new_encode_dev)(x)
291308
292309 #ifndef INIT_STRUCT_STAT_PADDING
293310 # define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st))
....@@ -297,7 +314,9 @@
297314 {
298315 struct stat tmp;
299316
300
- if (!valid_dev(stat->dev) || !valid_dev(stat->rdev))
317
+ if (sizeof(tmp.st_dev) < 4 && !old_valid_dev(stat->dev))
318
+ return -EOVERFLOW;
319
+ if (sizeof(tmp.st_rdev) < 4 && !old_valid_dev(stat->rdev))
301320 return -EOVERFLOW;
302321 #if BITS_PER_LONG == 32
303322 if (stat->size > MAX_NON_LFS)
....@@ -305,7 +324,7 @@
305324 #endif
306325
307326 INIT_STRUCT_STAT_PADDING(tmp);
308
- tmp.st_dev = encode_dev(stat->dev);
327
+ tmp.st_dev = new_encode_dev(stat->dev);
309328 tmp.st_ino = stat->ino;
310329 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
311330 return -EOVERFLOW;
....@@ -315,7 +334,7 @@
315334 return -EOVERFLOW;
316335 SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
317336 SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
318
- tmp.st_rdev = encode_dev(stat->rdev);
337
+ tmp.st_rdev = new_encode_dev(stat->rdev);
319338 tmp.st_size = stat->size;
320339 tmp.st_atime = stat->atime.tv_sec;
321340 tmp.st_mtime = stat->mtime.tv_sec;
....@@ -378,6 +397,7 @@
378397
379398 return error;
380399 }
400
+#endif
381401
382402 static int do_readlinkat(int dfd, const char __user *pathname,
383403 char __user *buf, int bufsiz)
....@@ -548,8 +568,27 @@
548568 tmp.stx_rdev_minor = MINOR(stat->rdev);
549569 tmp.stx_dev_major = MAJOR(stat->dev);
550570 tmp.stx_dev_minor = MINOR(stat->dev);
571
+ tmp.stx_mnt_id = stat->mnt_id;
551572
552573 return copy_to_user(buffer, &tmp, sizeof(tmp)) ? -EFAULT : 0;
574
+}
575
+
576
+int do_statx(int dfd, const char __user *filename, unsigned flags,
577
+ unsigned int mask, struct statx __user *buffer)
578
+{
579
+ struct kstat stat;
580
+ int error;
581
+
582
+ if (mask & STATX__RESERVED)
583
+ return -EINVAL;
584
+ if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
585
+ return -EINVAL;
586
+
587
+ error = vfs_statx(dfd, filename, flags, &stat, mask);
588
+ if (error)
589
+ return error;
590
+
591
+ return cp_statx(&stat, buffer);
553592 }
554593
555594 /**
....@@ -568,19 +607,7 @@
568607 unsigned int, mask,
569608 struct statx __user *, buffer)
570609 {
571
- struct kstat stat;
572
- int error;
573
-
574
- if (mask & STATX__RESERVED)
575
- return -EINVAL;
576
- if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
577
- return -EINVAL;
578
-
579
- error = vfs_statx(dfd, filename, flags, &stat, mask);
580
- if (error)
581
- return error;
582
-
583
- return cp_statx(&stat, buffer);
610
+ return do_statx(dfd, filename, flags, mask, buffer);
584611 }
585612
586613 #ifdef CONFIG_COMPAT
....@@ -588,11 +615,13 @@
588615 {
589616 struct compat_stat tmp;
590617
591
- if (!old_valid_dev(stat->dev) || !old_valid_dev(stat->rdev))
618
+ if (sizeof(tmp.st_dev) < 4 && !old_valid_dev(stat->dev))
619
+ return -EOVERFLOW;
620
+ if (sizeof(tmp.st_rdev) < 4 && !old_valid_dev(stat->rdev))
592621 return -EOVERFLOW;
593622
594623 memset(&tmp, 0, sizeof(tmp));
595
- tmp.st_dev = old_encode_dev(stat->dev);
624
+ tmp.st_dev = new_encode_dev(stat->dev);
596625 tmp.st_ino = stat->ino;
597626 if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
598627 return -EOVERFLOW;
....@@ -602,7 +631,7 @@
602631 return -EOVERFLOW;
603632 SET_UID(tmp.st_uid, from_kuid_munged(current_user_ns(), stat->uid));
604633 SET_GID(tmp.st_gid, from_kgid_munged(current_user_ns(), stat->gid));
605
- tmp.st_rdev = old_encode_dev(stat->rdev);
634
+ tmp.st_rdev = new_encode_dev(stat->rdev);
606635 if ((u64) stat->size > MAX_NON_LFS)
607636 return -EOVERFLOW;
608637 tmp.st_size = stat->size;