stat.c 20.1 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
L
Linus Torvalds 已提交
2 3 4 5 6 7
/*
 *  linux/fs/stat.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */

8
#include <linux/export.h>
L
Linus Torvalds 已提交
9 10 11 12 13 14 15
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/file.h>
#include <linux/highuid.h>
#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/security.h>
16
#include <linux/cred.h>
L
Linus Torvalds 已提交
17
#include <linux/syscalls.h>
18
#include <linux/pagemap.h>
19
#include <linux/compat.h>
L
Linus Torvalds 已提交
20

21
#include <linux/uaccess.h>
L
Linus Torvalds 已提交
22 23
#include <asm/unistd.h>

24
#include "internal.h"
M
Miklos Szeredi 已提交
25
#include "mount.h"
26

27 28 29 30 31 32 33 34 35
/**
 * generic_fillattr - Fill in the basic attributes from the inode struct
 * @inode: Inode to use as the source
 * @stat: Where to fill in the attributes
 *
 * Fill in the basic attributes in the kstat structure from data that's to be
 * found on the VFS inode structure.  This is the default if no getattr inode
 * operation is supplied.
 */
L
Linus Torvalds 已提交
36 37 38 39 40 41 42 43 44
void generic_fillattr(struct inode *inode, struct kstat *stat)
{
	stat->dev = inode->i_sb->s_dev;
	stat->ino = inode->i_ino;
	stat->mode = inode->i_mode;
	stat->nlink = inode->i_nlink;
	stat->uid = inode->i_uid;
	stat->gid = inode->i_gid;
	stat->rdev = inode->i_rdev;
45
	stat->size = i_size_read(inode);
L
Linus Torvalds 已提交
46 47 48
	stat->atime = inode->i_atime;
	stat->mtime = inode->i_mtime;
	stat->ctime = inode->i_ctime;
F
Fabian Frederick 已提交
49
	stat->blksize = i_blocksize(inode);
50
	stat->blocks = inode->i_blocks;
51
}
L
Linus Torvalds 已提交
52 53
EXPORT_SYMBOL(generic_fillattr);

J
J. Bruce Fields 已提交
54 55 56 57
/**
 * vfs_getattr_nosec - getattr without security checks
 * @path: file to get attributes from
 * @stat: structure to return attributes in
58
 * @request_mask: STATX_xxx flags indicating what the caller wants
C
Christoph Hellwig 已提交
59
 * @query_flags: Query mode (AT_STATX_SYNC_TYPE)
J
J. Bruce Fields 已提交
60 61 62 63
 *
 * Get attributes without calling security_inode_getattr.
 *
 * Currently the only caller other than vfs_getattr is internal to the
64 65
 * filehandle lookup code, which uses only the inode number and returns no
 * attributes to any user.  Any other code probably wants vfs_getattr.
J
J. Bruce Fields 已提交
66
 */
67 68
int vfs_getattr_nosec(const struct path *path, struct kstat *stat,
		      u32 request_mask, unsigned int query_flags)
L
Linus Torvalds 已提交
69
{
70
	struct inode *inode = d_backing_inode(path->dentry);
L
Linus Torvalds 已提交
71

72 73
	memset(stat, 0, sizeof(*stat));
	stat->result_mask |= STATX_BASIC_STATS;
C
Christoph Hellwig 已提交
74
	query_flags &= AT_STATX_SYNC_TYPE;
75 76

	/* allow the fs to override these if it really wants to */
77 78
	/* SB_NOATIME means filesystem supplies dummy atime value */
	if (inode->i_sb->s_flags & SB_NOATIME)
79
		stat->result_mask &= ~STATX_ATIME;
80 81 82 83 84

	/*
	 * Note: If you add another clause to set an attribute flag, please
	 * update attributes_mask below.
	 */
85 86 87
	if (IS_AUTOMOUNT(inode))
		stat->attributes |= STATX_ATTR_AUTOMOUNT;

I
Ira Weiny 已提交
88 89 90
	if (IS_DAX(inode))
		stat->attributes |= STATX_ATTR_DAX;

91 92 93
	stat->attributes_mask |= (STATX_ATTR_AUTOMOUNT |
				  STATX_ATTR_DAX);

L
Linus Torvalds 已提交
94
	if (inode->i_op->getattr)
95 96
		return inode->i_op->getattr(path, stat, request_mask,
					    query_flags);
L
Linus Torvalds 已提交
97 98 99 100

	generic_fillattr(inode, stat);
	return 0;
}
J
J. Bruce Fields 已提交
101 102
EXPORT_SYMBOL(vfs_getattr_nosec);

103 104 105 106 107
/*
 * vfs_getattr - Get the enhanced basic attributes of a file
 * @path: The file of interest
 * @stat: Where to return the statistics
 * @request_mask: STATX_xxx flags indicating what the caller wants
C
Christoph Hellwig 已提交
108
 * @query_flags: Query mode (AT_STATX_SYNC_TYPE)
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
 *
 * Ask the filesystem for a file's attributes.  The caller must indicate in
 * request_mask and query_flags to indicate what they want.
 *
 * If the file is remote, the filesystem can be forced to update the attributes
 * from the backing store by passing AT_STATX_FORCE_SYNC in query_flags or can
 * suppress the update by passing AT_STATX_DONT_SYNC.
 *
 * Bits must have been set in request_mask to indicate which attributes the
 * caller wants retrieving.  Any such attribute not requested may be returned
 * anyway, but the value may be approximate, and, if remote, may not have been
 * synchronised with the server.
 *
 * 0 will be returned on success, and a -ve error code if unsuccessful.
 */
int vfs_getattr(const struct path *path, struct kstat *stat,
		u32 request_mask, unsigned int query_flags)
J
J. Bruce Fields 已提交
126 127 128
{
	int retval;

129
	retval = security_inode_getattr(path);
J
J. Bruce Fields 已提交
130 131
	if (retval)
		return retval;
132
	return vfs_getattr_nosec(path, stat, request_mask, query_flags);
J
J. Bruce Fields 已提交
133
}
L
Linus Torvalds 已提交
134 135
EXPORT_SYMBOL(vfs_getattr);

136
/**
C
Christoph Hellwig 已提交
137
 * vfs_fstat - Get the basic attributes by file descriptor
138 139 140 141 142 143 144 145
 * @fd: The file descriptor referring to the file of interest
 * @stat: The result structure to fill in.
 *
 * This function is a wrapper around vfs_getattr().  The main difference is
 * that it uses a file descriptor to determine the file location.
 *
 * 0 will be returned on success, and a -ve error code if unsuccessful.
 */
C
Christoph Hellwig 已提交
146
int vfs_fstat(int fd, struct kstat *stat)
L
Linus Torvalds 已提交
147
{
148
	struct fd f;
C
Christoph Hellwig 已提交
149
	int error;
150 151

	f = fdget_raw(fd);
C
Christoph Hellwig 已提交
152 153 154 155
	if (!f.file)
		return -EBADF;
	error = vfs_getattr(&f.file->f_path, stat, STATX_BASIC_STATS, 0);
	fdput(f);
L
Linus Torvalds 已提交
156 157 158
	return error;
}

159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
/**
 * vfs_statx - Get basic and extra attributes by filename
 * @dfd: A file descriptor representing the base dir for a relative filename
 * @filename: The name of the file of interest
 * @flags: Flags to control the query
 * @stat: The result structure to fill in.
 * @request_mask: STATX_xxx flags indicating what the caller wants
 *
 * This function is a wrapper around vfs_getattr().  The main difference is
 * that it uses a filename and base directory to determine the file location.
 * Additionally, the use of AT_SYMLINK_NOFOLLOW in flags will prevent a symlink
 * at the given name from being referenced.
 *
 * 0 will be returned on success, and a -ve error code if unsuccessful.
 */
174
static int vfs_statx(int dfd, const char __user *filename, int flags,
175
	      struct kstat *stat, u32 request_mask)
176
{
177
	struct path path;
178 179
	unsigned lookup_flags = 0;
	int error;
180

181
	if (flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT | AT_EMPTY_PATH |
C
Christoph Hellwig 已提交
182
		      AT_STATX_SYNC_TYPE))
183
		return -EINVAL;
184 185 186 187 188 189 190 191

	if (!(flags & AT_SYMLINK_NOFOLLOW))
		lookup_flags |= LOOKUP_FOLLOW;
	if (!(flags & AT_NO_AUTOMOUNT))
		lookup_flags |= LOOKUP_AUTOMOUNT;
	if (flags & AT_EMPTY_PATH)
		lookup_flags |= LOOKUP_EMPTY;

192
retry:
193 194 195 196
	error = user_path_at(dfd, filename, lookup_flags, &path);
	if (error)
		goto out;

197
	error = vfs_getattr(&path, stat, request_mask, flags);
M
Miklos Szeredi 已提交
198 199
	stat->mnt_id = real_mount(path.mnt)->mnt_id;
	stat->result_mask |= STATX_MNT_ID;
M
Miklos Szeredi 已提交
200 201 202
	if (path.mnt->mnt_root == path.dentry)
		stat->attributes |= STATX_ATTR_MOUNT_ROOT;
	stat->attributes_mask |= STATX_ATTR_MOUNT_ROOT;
203
	path_put(&path);
204 205 206 207
	if (retry_estale(error, lookup_flags)) {
		lookup_flags |= LOOKUP_REVAL;
		goto retry;
	}
208 209 210
out:
	return error;
}
211

212 213 214 215 216 217
int vfs_fstatat(int dfd, const char __user *filename,
			      struct kstat *stat, int flags)
{
	return vfs_statx(dfd, filename, flags | AT_NO_AUTOMOUNT,
			 stat, STATX_BASIC_STATS);
}
218

L
Linus Torvalds 已提交
219 220 221 222 223 224 225 226 227
#ifdef __ARCH_WANT_OLD_STAT

/*
 * For backward compatibility?  Maybe this should be moved
 * into arch/i386 instead?
 */
static int cp_old_stat(struct kstat *stat, struct __old_kernel_stat __user * statbuf)
{
	static int warncount = 5;
228
	struct __old_kernel_stat __aligned(16) tmp;
229

L
Linus Torvalds 已提交
230 231 232 233 234 235 236 237 238 239 240 241
	if (warncount > 0) {
		warncount--;
		printk(KERN_WARNING "VFS: Warning: %s using old stat() call. Recompile your binary.\n",
			current->comm);
	} else if (warncount < 0) {
		/* it's laughable, but... */
		warncount = 0;
	}

	memset(&tmp, 0, sizeof(struct __old_kernel_stat));
	tmp.st_dev = old_encode_dev(stat->dev);
	tmp.st_ino = stat->ino;
242 243
	if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
		return -EOVERFLOW;
L
Linus Torvalds 已提交
244 245 246 247
	tmp.st_mode = stat->mode;
	tmp.st_nlink = stat->nlink;
	if (tmp.st_nlink != stat->nlink)
		return -EOVERFLOW;
248 249
	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));
L
Linus Torvalds 已提交
250 251 252 253
	tmp.st_rdev = old_encode_dev(stat->rdev);
#if BITS_PER_LONG == 32
	if (stat->size > MAX_NON_LFS)
		return -EOVERFLOW;
254
#endif
L
Linus Torvalds 已提交
255 256 257 258 259 260 261
	tmp.st_size = stat->size;
	tmp.st_atime = stat->atime.tv_sec;
	tmp.st_mtime = stat->mtime.tv_sec;
	tmp.st_ctime = stat->ctime.tv_sec;
	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}

262 263
SYSCALL_DEFINE2(stat, const char __user *, filename,
		struct __old_kernel_stat __user *, statbuf)
L
Linus Torvalds 已提交
264 265
{
	struct kstat stat;
266
	int error;
L
Linus Torvalds 已提交
267

268 269 270
	error = vfs_stat(filename, &stat);
	if (error)
		return error;
L
Linus Torvalds 已提交
271

272
	return cp_old_stat(&stat, statbuf);
L
Linus Torvalds 已提交
273
}
274

275 276
SYSCALL_DEFINE2(lstat, const char __user *, filename,
		struct __old_kernel_stat __user *, statbuf)
L
Linus Torvalds 已提交
277 278
{
	struct kstat stat;
279
	int error;
L
Linus Torvalds 已提交
280

281 282 283
	error = vfs_lstat(filename, &stat);
	if (error)
		return error;
L
Linus Torvalds 已提交
284

285
	return cp_old_stat(&stat, statbuf);
L
Linus Torvalds 已提交
286
}
287 288

SYSCALL_DEFINE2(fstat, unsigned int, fd, struct __old_kernel_stat __user *, statbuf)
L
Linus Torvalds 已提交
289 290 291 292 293 294 295 296 297 298 299 300
{
	struct kstat stat;
	int error = vfs_fstat(fd, &stat);

	if (!error)
		error = cp_old_stat(&stat, statbuf);

	return error;
}

#endif /* __ARCH_WANT_OLD_STAT */

301 302
#ifdef __ARCH_WANT_NEW_STAT

303 304 305 306 307 308
#if BITS_PER_LONG == 32
#  define choose_32_64(a,b) a
#else
#  define choose_32_64(a,b) b
#endif

309 310 311 312
#ifndef INIT_STRUCT_STAT_PADDING
#  define INIT_STRUCT_STAT_PADDING(st) memset(&st, 0, sizeof(st))
#endif

L
Linus Torvalds 已提交
313 314
static int cp_new_stat(struct kstat *stat, struct stat __user *statbuf)
{
315
	struct stat __aligned(16) tmp;
L
Linus Torvalds 已提交
316

317 318 319
	if (sizeof(tmp.st_dev) < 4 && !old_valid_dev(stat->dev))
		return -EOVERFLOW;
	if (sizeof(tmp.st_rdev) < 4 && !old_valid_dev(stat->rdev))
L
Linus Torvalds 已提交
320
		return -EOVERFLOW;
321 322
#if BITS_PER_LONG == 32
	if (stat->size > MAX_NON_LFS)
L
Linus Torvalds 已提交
323 324 325
		return -EOVERFLOW;
#endif

326
	INIT_STRUCT_STAT_PADDING(tmp);
327
	tmp.st_dev = new_encode_dev(stat->dev);
L
Linus Torvalds 已提交
328
	tmp.st_ino = stat->ino;
329 330
	if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
		return -EOVERFLOW;
L
Linus Torvalds 已提交
331 332 333 334
	tmp.st_mode = stat->mode;
	tmp.st_nlink = stat->nlink;
	if (tmp.st_nlink != stat->nlink)
		return -EOVERFLOW;
335 336
	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));
337
	tmp.st_rdev = new_encode_dev(stat->rdev);
L
Linus Torvalds 已提交
338 339 340 341 342 343 344 345 346 347 348 349 350 351
	tmp.st_size = stat->size;
	tmp.st_atime = stat->atime.tv_sec;
	tmp.st_mtime = stat->mtime.tv_sec;
	tmp.st_ctime = stat->ctime.tv_sec;
#ifdef STAT_HAVE_NSEC
	tmp.st_atime_nsec = stat->atime.tv_nsec;
	tmp.st_mtime_nsec = stat->mtime.tv_nsec;
	tmp.st_ctime_nsec = stat->ctime.tv_nsec;
#endif
	tmp.st_blocks = stat->blocks;
	tmp.st_blksize = stat->blksize;
	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}

352 353
SYSCALL_DEFINE2(newstat, const char __user *, filename,
		struct stat __user *, statbuf)
354 355
{
	struct kstat stat;
356
	int error = vfs_stat(filename, &stat);
357

358 359 360
	if (error)
		return error;
	return cp_new_stat(&stat, statbuf);
361 362
}

363 364
SYSCALL_DEFINE2(newlstat, const char __user *, filename,
		struct stat __user *, statbuf)
L
Linus Torvalds 已提交
365 366
{
	struct kstat stat;
367
	int error;
L
Linus Torvalds 已提交
368

369 370 371
	error = vfs_lstat(filename, &stat);
	if (error)
		return error;
L
Linus Torvalds 已提交
372

373
	return cp_new_stat(&stat, statbuf);
L
Linus Torvalds 已提交
374
}
375

376
#if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
377
SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
378
		struct stat __user *, statbuf, int, flag)
L
Linus Torvalds 已提交
379 380
{
	struct kstat stat;
381
	int error;
L
Linus Torvalds 已提交
382

383 384 385 386
	error = vfs_fstatat(dfd, filename, &stat, flag);
	if (error)
		return error;
	return cp_new_stat(&stat, statbuf);
L
Linus Torvalds 已提交
387
}
U
Ulrich Drepper 已提交
388
#endif
389

390
SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct stat __user *, statbuf)
L
Linus Torvalds 已提交
391 392 393 394 395 396 397 398 399
{
	struct kstat stat;
	int error = vfs_fstat(fd, &stat);

	if (!error)
		error = cp_new_stat(&stat, statbuf);

	return error;
}
400
#endif
L
Linus Torvalds 已提交
401

402 403
static int do_readlinkat(int dfd, const char __user *pathname,
			 char __user *buf, int bufsiz)
L
Linus Torvalds 已提交
404
{
405
	struct path path;
L
Linus Torvalds 已提交
406
	int error;
407
	int empty = 0;
408
	unsigned int lookup_flags = LOOKUP_EMPTY;
L
Linus Torvalds 已提交
409 410 411 412

	if (bufsiz <= 0)
		return -EINVAL;

413 414
retry:
	error = user_path_at_empty(dfd, pathname, lookup_flags, &path, &empty);
L
Linus Torvalds 已提交
415
	if (!error) {
416
		struct inode *inode = d_backing_inode(path.dentry);
L
Linus Torvalds 已提交
417

418
		error = empty ? -ENOENT : -EINVAL;
419 420 421 422
		/*
		 * AFS mountpoints allow readlink(2) but are not symlinks
		 */
		if (d_is_symlink(path.dentry) || inode->i_op->readlink) {
423
			error = security_inode_readlink(path.dentry);
L
Linus Torvalds 已提交
424
			if (!error) {
A
Al Viro 已提交
425
				touch_atime(&path);
426
				error = vfs_readlink(path.dentry, buf, bufsiz);
L
Linus Torvalds 已提交
427 428
			}
		}
429
		path_put(&path);
430 431 432 433
		if (retry_estale(error, lookup_flags)) {
			lookup_flags |= LOOKUP_REVAL;
			goto retry;
		}
L
Linus Torvalds 已提交
434 435 436 437
	}
	return error;
}

438 439 440 441 442 443
SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname,
		char __user *, buf, int, bufsiz)
{
	return do_readlinkat(dfd, pathname, buf, bufsiz);
}

444 445
SYSCALL_DEFINE3(readlink, const char __user *, path, char __user *, buf,
		int, bufsiz)
446
{
447
	return do_readlinkat(AT_FDCWD, path, buf, bufsiz);
448 449
}

L
Linus Torvalds 已提交
450 451

/* ---------- LFS-64 ----------- */
452
#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64)
L
Linus Torvalds 已提交
453

454 455 456 457
#ifndef INIT_STRUCT_STAT64_PADDING
#  define INIT_STRUCT_STAT64_PADDING(st) memset(&st, 0, sizeof(st))
#endif

L
Linus Torvalds 已提交
458 459
static long cp_new_stat64(struct kstat *stat, struct stat64 __user *statbuf)
{
460
	struct stat64 __aligned(16) tmp;
L
Linus Torvalds 已提交
461

462
	INIT_STRUCT_STAT64_PADDING(tmp);
L
Linus Torvalds 已提交
463 464 465 466 467 468 469 470 471
#ifdef CONFIG_MIPS
	/* mips has weird padding, so we don't get 64 bits there */
	tmp.st_dev = new_encode_dev(stat->dev);
	tmp.st_rdev = new_encode_dev(stat->rdev);
#else
	tmp.st_dev = huge_encode_dev(stat->dev);
	tmp.st_rdev = huge_encode_dev(stat->rdev);
#endif
	tmp.st_ino = stat->ino;
472 473
	if (sizeof(tmp.st_ino) < sizeof(stat->ino) && tmp.st_ino != stat->ino)
		return -EOVERFLOW;
L
Linus Torvalds 已提交
474 475 476 477 478
#ifdef STAT64_HAS_BROKEN_ST_INO
	tmp.__st_ino = stat->ino;
#endif
	tmp.st_mode = stat->mode;
	tmp.st_nlink = stat->nlink;
479 480
	tmp.st_uid = from_kuid_munged(current_user_ns(), stat->uid);
	tmp.st_gid = from_kgid_munged(current_user_ns(), stat->gid);
L
Linus Torvalds 已提交
481 482 483 484 485 486 487 488 489 490 491 492
	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_size = stat->size;
	tmp.st_blocks = stat->blocks;
	tmp.st_blksize = stat->blksize;
	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
}

493 494
SYSCALL_DEFINE2(stat64, const char __user *, filename,
		struct stat64 __user *, statbuf)
L
Linus Torvalds 已提交
495 496 497 498 499 500 501 502 503
{
	struct kstat stat;
	int error = vfs_stat(filename, &stat);

	if (!error)
		error = cp_new_stat64(&stat, statbuf);

	return error;
}
504

505 506
SYSCALL_DEFINE2(lstat64, const char __user *, filename,
		struct stat64 __user *, statbuf)
L
Linus Torvalds 已提交
507 508 509 510 511 512 513 514 515
{
	struct kstat stat;
	int error = vfs_lstat(filename, &stat);

	if (!error)
		error = cp_new_stat64(&stat, statbuf);

	return error;
}
516 517

SYSCALL_DEFINE2(fstat64, unsigned long, fd, struct stat64 __user *, statbuf)
L
Linus Torvalds 已提交
518 519 520 521 522 523 524 525 526 527
{
	struct kstat stat;
	int error = vfs_fstat(fd, &stat);

	if (!error)
		error = cp_new_stat64(&stat, statbuf);

	return error;
}

528
SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
529
		struct stat64 __user *, statbuf, int, flag)
U
Ulrich Drepper 已提交
530 531
{
	struct kstat stat;
532
	int error;
U
Ulrich Drepper 已提交
533

534 535 536 537
	error = vfs_fstatat(dfd, filename, &stat, flag);
	if (error)
		return error;
	return cp_new_stat64(&stat, statbuf);
U
Ulrich Drepper 已提交
538
}
539
#endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */
L
Linus Torvalds 已提交
540

541
static noinline_for_stack int
542
cp_statx(const struct kstat *stat, struct statx __user *buffer)
543
{
544
	struct statx __aligned(16) tmp;
545 546 547 548 549 550 551 552 553 554 555 556 557

	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;
558
	tmp.stx_attributes_mask = stat->attributes_mask;
559 560 561 562 563 564 565 566 567 568 569 570
	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);
M
Miklos Szeredi 已提交
571
	tmp.stx_mnt_id = stat->mnt_id;
572 573

	return copy_to_user(buffer, &tmp, sizeof(tmp)) ? -EFAULT : 0;
574 575
}

576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
int do_statx(int dfd, const char __user *filename, unsigned flags,
	     unsigned int mask, struct statx __user *buffer)
{
	struct kstat stat;
	int error;

	if (mask & STATX__RESERVED)
		return -EINVAL;
	if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
		return -EINVAL;

	error = vfs_statx(dfd, filename, flags, &stat, mask);
	if (error)
		return error;

	return cp_statx(&stat, buffer);
}

594 595 596
/**
 * sys_statx - System call to get enhanced stats
 * @dfd: Base directory to pathwalk from *or* fd to stat.
597
 * @filename: File to stat or "" with AT_EMPTY_PATH
598 599 600 601
 * @flags: AT_* flags to control pathwalk.
 * @mask: Parts of statx struct actually required.
 * @buffer: Result buffer.
 *
602 603
 * Note that fstat() can be emulated by setting dfd to the fd of interest,
 * supplying "" as the filename and setting AT_EMPTY_PATH in the flags.
604 605 606 607 608 609
 */
SYSCALL_DEFINE5(statx,
		int, dfd, const char __user *, filename, unsigned, flags,
		unsigned int, mask,
		struct statx __user *, buffer)
{
610
	return do_statx(dfd, filename, flags, mask, buffer);
611 612
}

613 614 615
#ifdef CONFIG_COMPAT
static int cp_compat_stat(struct kstat *stat, struct compat_stat __user *ubuf)
{
616
	struct compat_stat __aligned(16) tmp;
617

618 619 620
	if (sizeof(tmp.st_dev) < 4 && !old_valid_dev(stat->dev))
		return -EOVERFLOW;
	if (sizeof(tmp.st_rdev) < 4 && !old_valid_dev(stat->rdev))
621 622 623
		return -EOVERFLOW;

	memset(&tmp, 0, sizeof(tmp));
624
	tmp.st_dev = new_encode_dev(stat->dev);
625 626 627 628 629 630 631 632 633
	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));
634
	tmp.st_rdev = new_encode_dev(stat->rdev);
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699
	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

700 701
/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
void __inode_add_bytes(struct inode *inode, loff_t bytes)
L
Linus Torvalds 已提交
702 703 704 705 706 707 708 709
{
	inode->i_blocks += bytes >> 9;
	bytes &= 511;
	inode->i_bytes += bytes;
	if (inode->i_bytes >= 512) {
		inode->i_blocks++;
		inode->i_bytes -= 512;
	}
710
}
A
Al Viro 已提交
711
EXPORT_SYMBOL(__inode_add_bytes);
712 713 714 715 716

void inode_add_bytes(struct inode *inode, loff_t bytes)
{
	spin_lock(&inode->i_lock);
	__inode_add_bytes(inode, bytes);
L
Linus Torvalds 已提交
717 718 719 720 721
	spin_unlock(&inode->i_lock);
}

EXPORT_SYMBOL(inode_add_bytes);

722
void __inode_sub_bytes(struct inode *inode, loff_t bytes)
L
Linus Torvalds 已提交
723 724 725 726 727 728 729 730
{
	inode->i_blocks -= bytes >> 9;
	bytes &= 511;
	if (inode->i_bytes < bytes) {
		inode->i_blocks--;
		inode->i_bytes += 512;
	}
	inode->i_bytes -= bytes;
731 732 733 734 735 736 737 738
}

EXPORT_SYMBOL(__inode_sub_bytes);

void inode_sub_bytes(struct inode *inode, loff_t bytes)
{
	spin_lock(&inode->i_lock);
	__inode_sub_bytes(inode, bytes);
L
Linus Torvalds 已提交
739 740 741 742 743 744 745 746 747 748
	spin_unlock(&inode->i_lock);
}

EXPORT_SYMBOL(inode_sub_bytes);

loff_t inode_get_bytes(struct inode *inode)
{
	loff_t ret;

	spin_lock(&inode->i_lock);
J
Jan Kara 已提交
749
	ret = __inode_get_bytes(inode);
L
Linus Torvalds 已提交
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
	spin_unlock(&inode->i_lock);
	return ret;
}

EXPORT_SYMBOL(inode_get_bytes);

void inode_set_bytes(struct inode *inode, loff_t bytes)
{
	/* Caller is here responsible for sufficient locking
	 * (ie. inode->i_lock) */
	inode->i_blocks = bytes >> 9;
	inode->i_bytes = bytes & 511;
}

EXPORT_SYMBOL(inode_set_bytes);