457c899653991 (Thomas Gleixner 2019-05-19 13:08:55 +0100 1) // SPDX-License-Identifier: GPL-2.0-only
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * linux/fs/open.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)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 8) #include <linux/string.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/file.h>
9f3acc3140444 (Al Viro 2008-04-24 07:44:08 -0400 11) #include <linux/fdtable.h>
0eeca28300df1 (Robert Love 2005-07-12 17:06:03 -0400 12) #include <linux/fsnotify.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 13) #include <linux/module.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 14) #include <linux/tty.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 15) #include <linux/namei.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 16) #include <linux/backing-dev.h>
16f7e0fe2ecc3 (Randy Dunlap 2006-01-11 12:17:46 -0800 17) #include <linux/capability.h>
086f7316f0d40 (Andrew G. Morgan 2008-07-04 09:59:58 -0700 18) #include <linux/securebits.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 19) #include <linux/security.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 20) #include <linux/mount.h>
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 21) #include <linux/fcntl.h>
5a0e3ad6af866 (Tejun Heo 2010-03-24 17:04:11 +0900 22) #include <linux/slab.h>
7c0f6ba682b9c (Linus Torvalds 2016-12-24 11:46:01 -0800 23) #include <linux/uaccess.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 24) #include <linux/fs.h>
ef3daeda7b58f (Yoav Zach 2005-06-23 00:09:58 -0700 25) #include <linux/personality.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 26) #include <linux/pagemap.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 27) #include <linux/syscalls.h>
ab2af1f500506 (Dipankar Sarma 2005-09-09 13:04:13 -0700 28) #include <linux/rcupdate.h>
73241ccca0f77 (Amy Griffis 2005-11-03 16:00:25 +0000 29) #include <linux/audit.h>
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 30) #include <linux/falloc.h>
5ad4e53bd5406 (Al Viro 2009-03-29 19:50:06 -0400 31) #include <linux/fs_struct.h>
b65a9cfc2c38e (Al Viro 2009-12-16 06:27:40 -0500 32) #include <linux/ima.h>
2dfc1cae4c42b (Eric Paris 2009-12-17 20:30:52 -0500 33) #include <linux/dnotify.h>
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 34) #include <linux/compat.h>
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 35)
e81e3f4dca6c5 (Eric Paris 2009-12-04 15:47:36 -0500 36) #include "internal.h"
e81e3f4dca6c5 (Eric Paris 2009-12-04 15:47:36 -0500 37)
643fe55a0679a (Christian Brauner 2021-01-21 14:19:34 +0100 38) int do_truncate(struct user_namespace *mnt_userns, struct dentry *dentry,
643fe55a0679a (Christian Brauner 2021-01-21 14:19:34 +0100 39) loff_t length, unsigned int time_attrs, struct file *filp)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 40) {
939a9421eb53d (Amerigo Wang 2009-08-20 19:29:03 -0700 41) int ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 42) struct iattr newattrs;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 43)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 44) /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 45) if (length < 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 46) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 47)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 48) newattrs.ia_size = length;
4a30131e7dbb1 (NeilBrown 2006-01-08 01:02:39 -0800 49) newattrs.ia_valid = ATTR_SIZE | time_attrs;
cc4e69dee4a08 (Miklos Szeredi 2005-11-07 00:59:49 -0800 50) if (filp) {
cc4e69dee4a08 (Miklos Szeredi 2005-11-07 00:59:49 -0800 51) newattrs.ia_file = filp;
cc4e69dee4a08 (Miklos Szeredi 2005-11-07 00:59:49 -0800 52) newattrs.ia_valid |= ATTR_FILE;
cc4e69dee4a08 (Miklos Szeredi 2005-11-07 00:59:49 -0800 53) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 54)
45f147a1bc97c (Jan Kara 2015-05-21 16:05:55 +0200 55) /* Remove suid, sgid, and file capabilities on truncate too */
45f147a1bc97c (Jan Kara 2015-05-21 16:05:55 +0200 56) ret = dentry_needs_remove_privs(dentry);
45f147a1bc97c (Jan Kara 2015-05-21 16:05:55 +0200 57) if (ret < 0)
45f147a1bc97c (Jan Kara 2015-05-21 16:05:55 +0200 58) return ret;
939a9421eb53d (Amerigo Wang 2009-08-20 19:29:03 -0700 59) if (ret)
939a9421eb53d (Amerigo Wang 2009-08-20 19:29:03 -0700 60) newattrs.ia_valid |= ret | ATTR_FORCE;
7b82dc0e64e93 (Linus Torvalds 2007-05-08 20:10:00 -0700 61)
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 62) inode_lock(dentry->d_inode);
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 63) /* Note any delegations or leases have already been broken: */
643fe55a0679a (Christian Brauner 2021-01-21 14:19:34 +0100 64) ret = notify_change(mnt_userns, dentry, &newattrs, NULL);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 65) inode_unlock(dentry->d_inode);
939a9421eb53d (Amerigo Wang 2009-08-20 19:29:03 -0700 66) return ret;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 67) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 68)
7df818b2370a9 (Al Viro 2016-03-25 14:24:09 -0400 69) long vfs_truncate(const struct path *path, loff_t length)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 70) {
643fe55a0679a (Christian Brauner 2021-01-21 14:19:34 +0100 71) struct user_namespace *mnt_userns;
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 72) struct inode *inode;
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 73) long error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74)
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 75) inode = path->dentry->d_inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 76)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 77) /* For directories it's -EISDIR, for other non-regulars - -EINVAL */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 78) if (S_ISDIR(inode->i_mode))
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 79) return -EISDIR;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 80) if (!S_ISREG(inode->i_mode))
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 81) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 82)
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 83) error = mnt_want_write(path->mnt);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 84) if (error)
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 85) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 86)
643fe55a0679a (Christian Brauner 2021-01-21 14:19:34 +0100 87) mnt_userns = mnt_user_ns(path->mnt);
643fe55a0679a (Christian Brauner 2021-01-21 14:19:34 +0100 88) error = inode_permission(mnt_userns, inode, MAY_WRITE);
9ac9b8474c39c (Dave Hansen 2008-02-15 14:37:52 -0800 89) if (error)
9ac9b8474c39c (Dave Hansen 2008-02-15 14:37:52 -0800 90) goto mnt_drop_write_and_out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 91)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 92) error = -EPERM;
c82e42da8a6b2 (Miklos Szeredi 2008-06-24 16:50:12 +0200 93) if (IS_APPEND(inode))
9ac9b8474c39c (Dave Hansen 2008-02-15 14:37:52 -0800 94) goto mnt_drop_write_and_out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 95)
8cf9ee5061037 (Miklos Szeredi 2018-07-18 15:44:43 +0200 96) error = get_write_access(inode);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 97) if (error)
9ac9b8474c39c (Dave Hansen 2008-02-15 14:37:52 -0800 98) goto mnt_drop_write_and_out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 99)
9700382c3c9ff (david m. richter 2007-07-31 00:39:12 -0700 100) /*
9700382c3c9ff (david m. richter 2007-07-31 00:39:12 -0700 101) * Make sure that there are no leases. get_write_access() protects
9700382c3c9ff (david m. richter 2007-07-31 00:39:12 -0700 102) * against the truncate racing with a lease-granting setlease().
9700382c3c9ff (david m. richter 2007-07-31 00:39:12 -0700 103) */
8737c9305bd56 (Al Viro 2009-12-24 06:47:55 -0500 104) error = break_lease(inode, O_WRONLY);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 105) if (error)
9700382c3c9ff (david m. richter 2007-07-31 00:39:12 -0700 106) goto put_write_and_out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 107)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 108) error = locks_verify_truncate(inode, NULL, length);
be6d3e56a6b9b (Kentaro Takeda 2008-12-17 13:24:15 +0900 109) if (!error)
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 110) error = security_path_truncate(path);
907f4554e2521 (Christoph Hellwig 2010-03-03 09:05:06 -0500 111) if (!error)
643fe55a0679a (Christian Brauner 2021-01-21 14:19:34 +0100 112) error = do_truncate(mnt_userns, path->dentry, length, 0, NULL);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 113)
9700382c3c9ff (david m. richter 2007-07-31 00:39:12 -0700 114) put_write_and_out:
8cf9ee5061037 (Miklos Szeredi 2018-07-18 15:44:43 +0200 115) put_write_access(inode);
9ac9b8474c39c (Dave Hansen 2008-02-15 14:37:52 -0800 116) mnt_drop_write_and_out:
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 117) mnt_drop_write(path->mnt);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 118) out:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 119) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 120) }
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 121) EXPORT_SYMBOL_GPL(vfs_truncate);
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 122)
df260e21e6cd5 (Dominik Brodowski 2018-03-19 17:32:11 +0100 123) long do_sys_truncate(const char __user *pathname, loff_t length)
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 124) {
48f7530d3f722 (Jeff Layton 2012-12-11 12:10:11 -0500 125) unsigned int lookup_flags = LOOKUP_FOLLOW;
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 126) struct path path;
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 127) int error;
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 128)
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 129) if (length < 0) /* sorry, but loff_t says... */
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 130) return -EINVAL;
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 131)
48f7530d3f722 (Jeff Layton 2012-12-11 12:10:11 -0500 132) retry:
48f7530d3f722 (Jeff Layton 2012-12-11 12:10:11 -0500 133) error = user_path_at(AT_FDCWD, pathname, lookup_flags, &path);
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 134) if (!error) {
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 135) error = vfs_truncate(&path, length);
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 136) path_put(&path);
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 137) }
48f7530d3f722 (Jeff Layton 2012-12-11 12:10:11 -0500 138) if (retry_estale(error, lookup_flags)) {
48f7530d3f722 (Jeff Layton 2012-12-11 12:10:11 -0500 139) lookup_flags |= LOOKUP_REVAL;
48f7530d3f722 (Jeff Layton 2012-12-11 12:10:11 -0500 140) goto retry;
48f7530d3f722 (Jeff Layton 2012-12-11 12:10:11 -0500 141) }
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 142) return error;
a02de9608595c (David Howells 2012-12-20 21:52:36 +0000 143) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 144)
4fd8da8d62416 (Heiko Carstens 2009-09-23 17:49:55 +0200 145) SYSCALL_DEFINE2(truncate, const char __user *, path, long, length)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 146) {
4fd8da8d62416 (Heiko Carstens 2009-09-23 17:49:55 +0200 147) return do_sys_truncate(path, length);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 148) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 149)
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 150) #ifdef CONFIG_COMPAT
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 151) COMPAT_SYSCALL_DEFINE2(truncate, const char __user *, path, compat_off_t, length)
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 152) {
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 153) return do_sys_truncate(path, length);
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 154) }
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 155) #endif
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 156)
411d9475cf901 (Dominik Brodowski 2018-03-11 11:34:54 +0100 157) long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 158) {
bf2965d5b5950 (Al Viro 2012-08-26 20:13:36 -0400 159) struct inode *inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 160) struct dentry *dentry;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 161) struct fd f;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 162) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 163)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 164) error = -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 165) if (length < 0)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 166) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 167) error = -EBADF;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 168) f = fdget(fd);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 169) if (!f.file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 170) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 171)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 172) /* explicitly opened as large or we are on 64-bit box */
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 173) if (f.file->f_flags & O_LARGEFILE)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 174) small = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 175)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 176) dentry = f.file->f_path.dentry;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 177) inode = dentry->d_inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 178) error = -EINVAL;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 179) if (!S_ISREG(inode->i_mode) || !(f.file->f_mode & FMODE_WRITE))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 180) goto out_putf;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 181)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 182) error = -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 183) /* Cannot ftruncate over 2^31 bytes without large file support */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 184) if (small && length > MAX_NON_LFS)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 185) goto out_putf;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 186)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 187) error = -EPERM;
78757af6518a3 (Amir Goldstein 2017-04-08 14:49:06 +0300 188) /* Check IS_APPEND on real upper inode */
78757af6518a3 (Amir Goldstein 2017-04-08 14:49:06 +0300 189) if (IS_APPEND(file_inode(f.file)))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 190) goto out_putf;
14da9200140f8 (Jan Kara 2012-06-12 16:20:37 +0200 191) sb_start_write(inode->i_sb);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 192) error = locks_verify_truncate(inode, f.file, length);
be6d3e56a6b9b (Kentaro Takeda 2008-12-17 13:24:15 +0900 193) if (!error)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 194) error = security_path_truncate(&f.file->f_path);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 195) if (!error)
643fe55a0679a (Christian Brauner 2021-01-21 14:19:34 +0100 196) error = do_truncate(file_mnt_user_ns(f.file), dentry, length,
643fe55a0679a (Christian Brauner 2021-01-21 14:19:34 +0100 197) ATTR_MTIME | ATTR_CTIME, f.file);
14da9200140f8 (Jan Kara 2012-06-12 16:20:37 +0200 198) sb_end_write(inode->i_sb);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 199) out_putf:
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 200) fdput(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 201) out:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 202) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 203) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 204)
bdc480e3bef6e (Heiko Carstens 2009-01-14 14:14:12 +0100 205) SYSCALL_DEFINE2(ftruncate, unsigned int, fd, unsigned long, length)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 206) {
2cf0966683430 (Al Viro 2013-01-21 15:25:54 -0500 207) return do_sys_ftruncate(fd, length, 1);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 208) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 209)
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 210) #ifdef CONFIG_COMPAT
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 211) COMPAT_SYSCALL_DEFINE2(ftruncate, unsigned int, fd, compat_ulong_t, length)
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 212) {
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 213) return do_sys_ftruncate(fd, length, 1);
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 214) }
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 215) #endif
3f6d078d4accf (Al Viro 2013-02-24 13:49:08 -0500 216)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 217) /* LFS versions of truncate are only needed on 32 bit machines */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 218) #if BITS_PER_LONG == 32
4a0fd5bf0fd07 (Al Viro 2013-01-21 15:16:58 -0500 219) SYSCALL_DEFINE2(truncate64, const char __user *, path, loff_t, length)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 220) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 221) return do_sys_truncate(path, length);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 222) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 223)
4a0fd5bf0fd07 (Al Viro 2013-01-21 15:16:58 -0500 224) SYSCALL_DEFINE2(ftruncate64, unsigned int, fd, loff_t, length)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 225) {
2cf0966683430 (Al Viro 2013-01-21 15:25:54 -0500 226) return do_sys_ftruncate(fd, length, 0);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 227) }
6673e0c3fbeae (Heiko Carstens 2009-01-14 14:14:02 +0100 228) #endif /* BITS_PER_LONG == 32 */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 229)
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 230)
72c72bdf7bf53 (Anna Schumaker 2014-11-07 14:44:25 -0500 231) int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 232) {
496ad9aa8ef44 (Al Viro 2013-01-23 17:07:38 -0500 233) struct inode *inode = file_inode(file);
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 234) long ret;
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 235)
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 236) if (offset < 0 || len <= 0)
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 237) return -EINVAL;
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 238)
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 239) /* Return error if mode is not supported */
dd46c787788d5 (Namjae Jeon 2015-03-25 15:07:05 +1100 240) if (mode & ~FALLOC_FL_SUPPORTED_MASK)
409332b65d3ed (Lukas Czerner 2014-03-13 19:07:42 +1100 241) return -EOPNOTSUPP;
409332b65d3ed (Lukas Czerner 2014-03-13 19:07:42 +1100 242)
409332b65d3ed (Lukas Czerner 2014-03-13 19:07:42 +1100 243) /* Punch hole and zero range are mutually exclusive */
409332b65d3ed (Lukas Czerner 2014-03-13 19:07:42 +1100 244) if ((mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE)) ==
409332b65d3ed (Lukas Czerner 2014-03-13 19:07:42 +1100 245) (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_ZERO_RANGE))
79124f18b3351 (Josef Bacik 2010-11-17 20:46:15 -0500 246) return -EOPNOTSUPP;
79124f18b3351 (Josef Bacik 2010-11-17 20:46:15 -0500 247)
79124f18b3351 (Josef Bacik 2010-11-17 20:46:15 -0500 248) /* Punch hole must have keep size set */
79124f18b3351 (Josef Bacik 2010-11-17 20:46:15 -0500 249) if ((mode & FALLOC_FL_PUNCH_HOLE) &&
79124f18b3351 (Josef Bacik 2010-11-17 20:46:15 -0500 250) !(mode & FALLOC_FL_KEEP_SIZE))
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 251) return -EOPNOTSUPP;
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 252)
00f5e61998dd1 (Namjae Jeon 2014-02-24 10:58:15 +1100 253) /* Collapse range should only be used exclusively. */
00f5e61998dd1 (Namjae Jeon 2014-02-24 10:58:15 +1100 254) if ((mode & FALLOC_FL_COLLAPSE_RANGE) &&
00f5e61998dd1 (Namjae Jeon 2014-02-24 10:58:15 +1100 255) (mode & ~FALLOC_FL_COLLAPSE_RANGE))
00f5e61998dd1 (Namjae Jeon 2014-02-24 10:58:15 +1100 256) return -EINVAL;
00f5e61998dd1 (Namjae Jeon 2014-02-24 10:58:15 +1100 257)
dd46c787788d5 (Namjae Jeon 2015-03-25 15:07:05 +1100 258) /* Insert range should only be used exclusively. */
dd46c787788d5 (Namjae Jeon 2015-03-25 15:07:05 +1100 259) if ((mode & FALLOC_FL_INSERT_RANGE) &&
dd46c787788d5 (Namjae Jeon 2015-03-25 15:07:05 +1100 260) (mode & ~FALLOC_FL_INSERT_RANGE))
dd46c787788d5 (Namjae Jeon 2015-03-25 15:07:05 +1100 261) return -EINVAL;
dd46c787788d5 (Namjae Jeon 2015-03-25 15:07:05 +1100 262)
71be6b4942dd6 (Darrick J. Wong 2016-10-03 09:11:14 -0700 263) /* Unshare range should only be used with allocate mode. */
71be6b4942dd6 (Darrick J. Wong 2016-10-03 09:11:14 -0700 264) if ((mode & FALLOC_FL_UNSHARE_RANGE) &&
71be6b4942dd6 (Darrick J. Wong 2016-10-03 09:11:14 -0700 265) (mode & ~(FALLOC_FL_UNSHARE_RANGE | FALLOC_FL_KEEP_SIZE)))
71be6b4942dd6 (Darrick J. Wong 2016-10-03 09:11:14 -0700 266) return -EINVAL;
71be6b4942dd6 (Darrick J. Wong 2016-10-03 09:11:14 -0700 267)
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 268) if (!(file->f_mode & FMODE_WRITE))
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 269) return -EBADF;
1ca551c6caae7 (Marco Stornelli 2011-03-05 11:10:19 +0100 270)
00f5e61998dd1 (Namjae Jeon 2014-02-24 10:58:15 +1100 271) /*
8fc61d92630d1 (Lukas Czerner 2014-04-12 09:51:34 -0400 272) * We can only allow pure fallocate on append only files
00f5e61998dd1 (Namjae Jeon 2014-02-24 10:58:15 +1100 273) */
8fc61d92630d1 (Lukas Czerner 2014-04-12 09:51:34 -0400 274) if ((mode & ~FALLOC_FL_KEEP_SIZE) && IS_APPEND(inode))
1ca551c6caae7 (Marco Stornelli 2011-03-05 11:10:19 +0100 275) return -EPERM;
1ca551c6caae7 (Marco Stornelli 2011-03-05 11:10:19 +0100 276)
1ca551c6caae7 (Marco Stornelli 2011-03-05 11:10:19 +0100 277) if (IS_IMMUTABLE(inode))
1ca551c6caae7 (Marco Stornelli 2011-03-05 11:10:19 +0100 278) return -EPERM;
1ca551c6caae7 (Marco Stornelli 2011-03-05 11:10:19 +0100 279)
0790b31b69374 (Lukas Czerner 2014-04-12 10:05:37 -0400 280) /*
6d2b6170c8914 (Eric Biggers 2014-06-24 23:45:08 -0500 281) * We cannot allow any fallocate operation on an active swapfile
0790b31b69374 (Lukas Czerner 2014-04-12 10:05:37 -0400 282) */
0790b31b69374 (Lukas Czerner 2014-04-12 10:05:37 -0400 283) if (IS_SWAPFILE(inode))
6d2b6170c8914 (Eric Biggers 2014-06-24 23:45:08 -0500 284) return -ETXTBSY;
0790b31b69374 (Lukas Czerner 2014-04-12 10:05:37 -0400 285)
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 286) /*
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 287) * Revalidate the write permissions, in case security policy has
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 288) * changed since the files were opened.
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 289) */
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 290) ret = security_file_permission(file, MAY_WRITE);
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 291) if (ret)
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 292) return ret;
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 293)
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 294) if (S_ISFIFO(inode->i_mode))
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 295) return -ESPIPE;
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 296)
9e79b13263025 (Amir Goldstein 2017-01-31 10:34:55 +0200 297) if (S_ISDIR(inode->i_mode))
9e79b13263025 (Amir Goldstein 2017-01-31 10:34:55 +0200 298) return -EISDIR;
9e79b13263025 (Amir Goldstein 2017-01-31 10:34:55 +0200 299)
9e79b13263025 (Amir Goldstein 2017-01-31 10:34:55 +0200 300) if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 301) return -ENODEV;
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 302)
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 303) /* Check for wrap through zero too */
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 304) if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0))
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 305) return -EFBIG;
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 306)
2fe17c1075836 (Christoph Hellwig 2011-01-14 13:07:43 +0100 307) if (!file->f_op->fallocate)
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 308) return -EOPNOTSUPP;
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 309)
bfe219d373cad (Amir Goldstein 2017-01-31 10:34:57 +0200 310) file_start_write(file);
14da9200140f8 (Jan Kara 2012-06-12 16:20:37 +0200 311) ret = file->f_op->fallocate(file, mode, offset, len);
820c12d5d6c08 (Heinrich Schuchardt 2014-12-12 16:58:34 -0800 312)
820c12d5d6c08 (Heinrich Schuchardt 2014-12-12 16:58:34 -0800 313) /*
820c12d5d6c08 (Heinrich Schuchardt 2014-12-12 16:58:34 -0800 314) * Create inotify and fanotify events.
820c12d5d6c08 (Heinrich Schuchardt 2014-12-12 16:58:34 -0800 315) *
820c12d5d6c08 (Heinrich Schuchardt 2014-12-12 16:58:34 -0800 316) * To keep the logic simple always create events if fallocate succeeds.
820c12d5d6c08 (Heinrich Schuchardt 2014-12-12 16:58:34 -0800 317) * This implies that events are even created if the file size remains
820c12d5d6c08 (Heinrich Schuchardt 2014-12-12 16:58:34 -0800 318) * unchanged, e.g. when using flag FALLOC_FL_KEEP_SIZE.
820c12d5d6c08 (Heinrich Schuchardt 2014-12-12 16:58:34 -0800 319) */
820c12d5d6c08 (Heinrich Schuchardt 2014-12-12 16:58:34 -0800 320) if (ret == 0)
820c12d5d6c08 (Heinrich Schuchardt 2014-12-12 16:58:34 -0800 321) fsnotify_modify(file);
820c12d5d6c08 (Heinrich Schuchardt 2014-12-12 16:58:34 -0800 322)
bfe219d373cad (Amir Goldstein 2017-01-31 10:34:57 +0200 323) file_end_write(file);
14da9200140f8 (Jan Kara 2012-06-12 16:20:37 +0200 324) return ret;
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 325) }
72c72bdf7bf53 (Anna Schumaker 2014-11-07 14:44:25 -0500 326) EXPORT_SYMBOL_GPL(vfs_fallocate);
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 327)
edf292c76b884 (Dominik Brodowski 2018-03-19 17:46:32 +0100 328) int ksys_fallocate(int fd, int mode, loff_t offset, loff_t len)
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 329) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 330) struct fd f = fdget(fd);
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 331) int error = -EBADF;
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 332)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 333) if (f.file) {
72c72bdf7bf53 (Anna Schumaker 2014-11-07 14:44:25 -0500 334) error = vfs_fallocate(f.file, mode, offset, len);
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 335) fdput(f);
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 336) }
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 337) return error;
97ac73506c0ba (Amit Arora 2007-07-17 21:42:44 -0400 338) }
3e63cbb1efca7 (Ankit Jain 2009-06-19 14:28:07 -0400 339)
edf292c76b884 (Dominik Brodowski 2018-03-19 17:46:32 +0100 340) SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
edf292c76b884 (Dominik Brodowski 2018-03-19 17:46:32 +0100 341) {
edf292c76b884 (Dominik Brodowski 2018-03-19 17:46:32 +0100 342) return ksys_fallocate(fd, mode, offset, len);
edf292c76b884 (Dominik Brodowski 2018-03-19 17:46:32 +0100 343) }
edf292c76b884 (Dominik Brodowski 2018-03-19 17:46:32 +0100 344)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 345) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 346) * access() needs to use the real uid/gid, not the effective uid/gid.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 347) * We do this by temporarily clearing all FS-related capabilities and
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 348) * switching the fsuid/fsgid around to the real ones.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 349) */
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 350) static const struct cred *access_override_creds(void)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 351) {
d84f4f992cbd7 (David Howells 2008-11-14 10:39:23 +1100 352) const struct cred *old_cred;
d84f4f992cbd7 (David Howells 2008-11-14 10:39:23 +1100 353) struct cred *override_cred;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 354)
d84f4f992cbd7 (David Howells 2008-11-14 10:39:23 +1100 355) override_cred = prepare_creds();
d84f4f992cbd7 (David Howells 2008-11-14 10:39:23 +1100 356) if (!override_cred)
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 357) return NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 358)
d84f4f992cbd7 (David Howells 2008-11-14 10:39:23 +1100 359) override_cred->fsuid = override_cred->uid;
d84f4f992cbd7 (David Howells 2008-11-14 10:39:23 +1100 360) override_cred->fsgid = override_cred->gid;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 361)
086f7316f0d40 (Andrew G. Morgan 2008-07-04 09:59:58 -0700 362) if (!issecure(SECURE_NO_SETUID_FIXUP)) {
1cdcbec1a3372 (David Howells 2008-11-14 10:39:14 +1100 363) /* Clear the capabilities if we switch to a non-root user */
18815a1808536 (Eric W. Biederman 2012-02-07 16:45:47 -0800 364) kuid_t root_uid = make_kuid(override_cred->user_ns, 0);
18815a1808536 (Eric W. Biederman 2012-02-07 16:45:47 -0800 365) if (!uid_eq(override_cred->uid, root_uid))
d84f4f992cbd7 (David Howells 2008-11-14 10:39:23 +1100 366) cap_clear(override_cred->cap_effective);
086f7316f0d40 (Andrew G. Morgan 2008-07-04 09:59:58 -0700 367) else
d84f4f992cbd7 (David Howells 2008-11-14 10:39:23 +1100 368) override_cred->cap_effective =
d84f4f992cbd7 (David Howells 2008-11-14 10:39:23 +1100 369) override_cred->cap_permitted;
086f7316f0d40 (Andrew G. Morgan 2008-07-04 09:59:58 -0700 370) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 371)
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 372) /*
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 373) * The new set of credentials can *only* be used in
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 374) * task-synchronous circumstances, and does not need
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 375) * RCU freeing, unless somebody then takes a separate
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 376) * reference to it.
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 377) *
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 378) * NOTE! This is _only_ true because this credential
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 379) * is used purely for override_creds() that installs
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 380) * it as the subjective cred. Other threads will be
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 381) * accessing ->real_cred, not the subjective cred.
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 382) *
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 383) * If somebody _does_ make a copy of this (using the
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 384) * 'get_current_cred()' function), that will clear the
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 385) * non_rcu field, because now that other user may be
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 386) * expecting RCU freeing. But normal thread-synchronous
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 387) * cred accesses will keep things non-RCY.
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 388) */
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 389) override_cred->non_rcu = 1;
d7852fbd0f042 (Linus Torvalds 2019-07-11 09:54:40 -0700 390)
d84f4f992cbd7 (David Howells 2008-11-14 10:39:23 +1100 391) old_cred = override_creds(override_cred);
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 392)
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 393) /* override_cred() gets its own ref */
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 394) put_cred(override_cred);
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 395)
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 396) return old_cred;
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 397) }
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 398)
eb9d7d390e511 (Christoph Hellwig 2020-07-22 11:14:02 +0200 399) static long do_faccessat(int dfd, const char __user *filename, int mode, int flags)
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 400) {
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 401) struct path path;
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 402) struct inode *inode;
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 403) int res;
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 404) unsigned int lookup_flags = LOOKUP_FOLLOW;
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 405) const struct cred *old_cred = NULL;
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 406)
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 407) if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 408) return -EINVAL;
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 409)
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 410) if (flags & ~(AT_EACCESS | AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH))
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 411) return -EINVAL;
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 412)
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 413) if (flags & AT_SYMLINK_NOFOLLOW)
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 414) lookup_flags &= ~LOOKUP_FOLLOW;
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 415) if (flags & AT_EMPTY_PATH)
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 416) lookup_flags |= LOOKUP_EMPTY;
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 417)
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 418) if (!(flags & AT_EACCESS)) {
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 419) old_cred = access_override_creds();
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 420) if (!old_cred)
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 421) return -ENOMEM;
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 422) }
9470451505efb (Miklos Szeredi 2020-05-14 16:44:24 +0200 423)
87fa55952b734 (Jeff Layton 2012-12-11 12:10:11 -0500 424) retry:
87fa55952b734 (Jeff Layton 2012-12-11 12:10:11 -0500 425) res = user_path_at(dfd, filename, lookup_flags, &path);
6902d925d568c (Dave Hansen 2006-09-30 23:29:01 -0700 426) if (res)
6902d925d568c (Dave Hansen 2006-09-30 23:29:01 -0700 427) goto out;
6902d925d568c (Dave Hansen 2006-09-30 23:29:01 -0700 428)
63afdfc781e10 (David Howells 2015-05-06 15:59:00 +0100 429) inode = d_backing_inode(path.dentry);
256984a83880f (Al Viro 2008-07-22 08:09:30 -0400 430)
256984a83880f (Al Viro 2008-07-22 08:09:30 -0400 431) if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) {
30524472c2f72 (Al Viro 2008-07-22 00:02:33 -0400 432) /*
30524472c2f72 (Al Viro 2008-07-22 00:02:33 -0400 433) * MAY_EXEC on regular files is denied if the fs is mounted
30524472c2f72 (Al Viro 2008-07-22 00:02:33 -0400 434) * with the "noexec" flag.
30524472c2f72 (Al Viro 2008-07-22 00:02:33 -0400 435) */
30524472c2f72 (Al Viro 2008-07-22 00:02:33 -0400 436) res = -EACCES;
90f8572b0f021 (Eric W. Biederman 2015-06-29 14:42:03 -0500 437) if (path_noexec(&path))
30524472c2f72 (Al Viro 2008-07-22 00:02:33 -0400 438) goto out_path_release;
30524472c2f72 (Al Viro 2008-07-22 00:02:33 -0400 439) }
30524472c2f72 (Al Viro 2008-07-22 00:02:33 -0400 440)
b8b546a061884 (Christian Brauner 2021-01-21 14:19:35 +0100 441) res = inode_permission(mnt_user_ns(path.mnt), inode, mode | MAY_ACCESS);
6902d925d568c (Dave Hansen 2006-09-30 23:29:01 -0700 442) /* SuS v2 requires we report a read only fs too */
256984a83880f (Al Viro 2008-07-22 08:09:30 -0400 443) if (res || !(mode & S_IWOTH) || special_file(inode->i_mode))
6902d925d568c (Dave Hansen 2006-09-30 23:29:01 -0700 444) goto out_path_release;
2f676cbc0d60a (Dave Hansen 2008-02-15 14:37:55 -0800 445) /*
2f676cbc0d60a (Dave Hansen 2008-02-15 14:37:55 -0800 446) * This is a rare case where using __mnt_is_readonly()
2f676cbc0d60a (Dave Hansen 2008-02-15 14:37:55 -0800 447) * is OK without a mnt_want/drop_write() pair. Since
2f676cbc0d60a (Dave Hansen 2008-02-15 14:37:55 -0800 448) * no actual write to the fs is performed here, we do
2f676cbc0d60a (Dave Hansen 2008-02-15 14:37:55 -0800 449) * not need to telegraph to that to anyone.
2f676cbc0d60a (Dave Hansen 2008-02-15 14:37:55 -0800 450) *
2f676cbc0d60a (Dave Hansen 2008-02-15 14:37:55 -0800 451) * By doing this, we accept that this access is
2f676cbc0d60a (Dave Hansen 2008-02-15 14:37:55 -0800 452) * inherently racy and know that the fs may change
2f676cbc0d60a (Dave Hansen 2008-02-15 14:37:55 -0800 453) * state before we even see this result.
2f676cbc0d60a (Dave Hansen 2008-02-15 14:37:55 -0800 454) */
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 455) if (__mnt_is_readonly(path.mnt))
6902d925d568c (Dave Hansen 2006-09-30 23:29:01 -0700 456) res = -EROFS;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 457)
6902d925d568c (Dave Hansen 2006-09-30 23:29:01 -0700 458) out_path_release:
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 459) path_put(&path);
87fa55952b734 (Jeff Layton 2012-12-11 12:10:11 -0500 460) if (retry_estale(res, lookup_flags)) {
87fa55952b734 (Jeff Layton 2012-12-11 12:10:11 -0500 461) lookup_flags |= LOOKUP_REVAL;
87fa55952b734 (Jeff Layton 2012-12-11 12:10:11 -0500 462) goto retry;
87fa55952b734 (Jeff Layton 2012-12-11 12:10:11 -0500 463) }
6902d925d568c (Dave Hansen 2006-09-30 23:29:01 -0700 464) out:
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 465) if (old_cred)
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 466) revert_creds(old_cred);
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 467)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 468) return res;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 469) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 470)
cbfe20f565228 (Dominik Brodowski 2018-03-11 11:34:54 +0100 471) SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
cbfe20f565228 (Dominik Brodowski 2018-03-11 11:34:54 +0100 472) {
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 473) return do_faccessat(dfd, filename, mode, 0);
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 474) }
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 475)
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 476) SYSCALL_DEFINE4(faccessat2, int, dfd, const char __user *, filename, int, mode,
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 477) int, flags)
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 478) {
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 479) return do_faccessat(dfd, filename, mode, flags);
cbfe20f565228 (Dominik Brodowski 2018-03-11 11:34:54 +0100 480) }
cbfe20f565228 (Dominik Brodowski 2018-03-11 11:34:54 +0100 481)
ca013e945b1ba (Heiko Carstens 2009-01-14 14:14:19 +0100 482) SYSCALL_DEFINE2(access, const char __user *, filename, int, mode)
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 483) {
c8ffd8bcdd282 (Miklos Szeredi 2020-05-14 16:44:25 +0200 484) return do_faccessat(AT_FDCWD, filename, mode, 0);
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 485) }
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 486)
db63f1e315384 (Christoph Hellwig 2020-07-22 11:25:21 +0200 487) SYSCALL_DEFINE1(chdir, const char __user *, filename)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 488) {
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 489) struct path path;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 490) int error;
0291c0a551d5b (Jeff Layton 2012-12-11 12:10:12 -0500 491) unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
0291c0a551d5b (Jeff Layton 2012-12-11 12:10:12 -0500 492) retry:
0291c0a551d5b (Jeff Layton 2012-12-11 12:10:12 -0500 493) error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 494) if (error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 495) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 496)
02f92b3868a1b (Christian Brauner 2021-01-21 14:19:22 +0100 497) error = path_permission(&path, MAY_EXEC | MAY_CHDIR);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 498) if (error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 499) goto dput_and_out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 500)
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 501) set_fs_pwd(current->fs, &path);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 502)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 503) dput_and_out:
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 504) path_put(&path);
0291c0a551d5b (Jeff Layton 2012-12-11 12:10:12 -0500 505) if (retry_estale(error, lookup_flags)) {
0291c0a551d5b (Jeff Layton 2012-12-11 12:10:12 -0500 506) lookup_flags |= LOOKUP_REVAL;
0291c0a551d5b (Jeff Layton 2012-12-11 12:10:12 -0500 507) goto retry;
0291c0a551d5b (Jeff Layton 2012-12-11 12:10:12 -0500 508) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 509) out:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 510) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 511) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 512)
3cdad42884bbd (Heiko Carstens 2009-01-14 14:14:22 +0100 513) SYSCALL_DEFINE1(fchdir, unsigned int, fd)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 514) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 515) struct fd f = fdget_raw(fd);
159b095628851 (Al Viro 2017-04-15 15:58:56 -0400 516) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 517)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 518) error = -EBADF;
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 519) if (!f.file)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 520) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 521)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 522) error = -ENOTDIR;
159b095628851 (Al Viro 2017-04-15 15:58:56 -0400 523) if (!d_can_lookup(f.file->f_path.dentry))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 524) goto out_putf;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 525)
02f92b3868a1b (Christian Brauner 2021-01-21 14:19:22 +0100 526) error = file_permission(f.file, MAY_EXEC | MAY_CHDIR);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 527) if (!error)
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 528) set_fs_pwd(current->fs, &f.file->f_path);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 529) out_putf:
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 530) fdput(f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 531) out:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 532) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 533) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 534)
4b7ca5014cbef (Christoph Hellwig 2020-07-22 11:26:13 +0200 535) SYSCALL_DEFINE1(chroot, const char __user *, filename)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 536) {
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 537) struct path path;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 538) int error;
2771261ec5b67 (Jeff Layton 2012-12-20 17:08:32 -0500 539) unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
2771261ec5b67 (Jeff Layton 2012-12-20 17:08:32 -0500 540) retry:
2771261ec5b67 (Jeff Layton 2012-12-20 17:08:32 -0500 541) error = user_path_at(AT_FDCWD, filename, lookup_flags, &path);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 542) if (error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 543) goto out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 544)
02f92b3868a1b (Christian Brauner 2021-01-21 14:19:22 +0100 545) error = path_permission(&path, MAY_EXEC | MAY_CHDIR);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 546) if (error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 547) goto dput_and_out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 548)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 549) error = -EPERM;
c7b96acf1456e (Eric W. Biederman 2013-03-20 12:49:49 -0700 550) if (!ns_capable(current_user_ns(), CAP_SYS_CHROOT))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 551) goto dput_and_out;
8b8efb44033c7 (Tetsuo Handa 2009-10-04 21:49:48 +0900 552) error = security_path_chroot(&path);
8b8efb44033c7 (Tetsuo Handa 2009-10-04 21:49:48 +0900 553) if (error)
8b8efb44033c7 (Tetsuo Handa 2009-10-04 21:49:48 +0900 554) goto dput_and_out;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 555)
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 556) set_fs_root(current->fs, &path);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 557) error = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 558) dput_and_out:
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 559) path_put(&path);
2771261ec5b67 (Jeff Layton 2012-12-20 17:08:32 -0500 560) if (retry_estale(error, lookup_flags)) {
2771261ec5b67 (Jeff Layton 2012-12-20 17:08:32 -0500 561) lookup_flags |= LOOKUP_REVAL;
2771261ec5b67 (Jeff Layton 2012-12-20 17:08:32 -0500 562) goto retry;
2771261ec5b67 (Jeff Layton 2012-12-20 17:08:32 -0500 563) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 564) out:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 565) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 566) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 567)
1097742efc643 (Christoph Hellwig 2020-07-22 11:41:02 +0200 568) int chmod_common(const struct path *path, umode_t mode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 569) {
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 570) struct inode *inode = path->dentry->d_inode;
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 571) struct inode *delegated_inode = NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 572) struct iattr newattrs;
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 573) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 574)
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 575) error = mnt_want_write(path->mnt);
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 576) if (error)
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 577) return error;
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 578) retry_deleg:
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 579) inode_lock(inode);
cdcf116d44e78 (Al Viro 2011-12-08 10:51:53 -0500 580) error = security_path_chmod(path, mode);
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 581) if (error)
fe542cf59bf0b (Tetsuo Handa 2009-11-22 11:49:55 +0900 582) goto out_unlock;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 583) newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 584) newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
b8b546a061884 (Christian Brauner 2021-01-21 14:19:35 +0100 585) error = notify_change(mnt_user_ns(path->mnt), path->dentry,
b8b546a061884 (Christian Brauner 2021-01-21 14:19:35 +0100 586) &newattrs, &delegated_inode);
fe542cf59bf0b (Tetsuo Handa 2009-11-22 11:49:55 +0900 587) out_unlock:
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 588) inode_unlock(inode);
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 589) if (delegated_inode) {
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 590) error = break_deleg_wait(&delegated_inode);
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 591) if (!error)
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 592) goto retry_deleg;
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 593) }
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 594) mnt_drop_write(path->mnt);
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 595) return error;
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 596) }
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 597)
9e96c8c0e94ee (Christoph Hellwig 2020-07-14 08:55:05 +0200 598) int vfs_fchmod(struct file *file, umode_t mode)
9e96c8c0e94ee (Christoph Hellwig 2020-07-14 08:55:05 +0200 599) {
9e96c8c0e94ee (Christoph Hellwig 2020-07-14 08:55:05 +0200 600) audit_file(file);
9e96c8c0e94ee (Christoph Hellwig 2020-07-14 08:55:05 +0200 601) return chmod_common(&file->f_path, mode);
9e96c8c0e94ee (Christoph Hellwig 2020-07-14 08:55:05 +0200 602) }
9e96c8c0e94ee (Christoph Hellwig 2020-07-14 08:55:05 +0200 603)
b25ba7c3c9acd (Christoph Hellwig 2020-07-14 08:59:57 +0200 604) SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 605) {
173c84012a594 (Al Viro 2013-08-30 12:48:53 -0400 606) struct fd f = fdget(fd);
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 607) int err = -EBADF;
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 608)
173c84012a594 (Al Viro 2013-08-30 12:48:53 -0400 609) if (f.file) {
9e96c8c0e94ee (Christoph Hellwig 2020-07-14 08:55:05 +0200 610) err = vfs_fchmod(f.file, mode);
173c84012a594 (Al Viro 2013-08-30 12:48:53 -0400 611) fdput(f);
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 612) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 613) return err;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 614) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 615)
1097742efc643 (Christoph Hellwig 2020-07-22 11:41:02 +0200 616) static int do_fchmodat(int dfd, const char __user *filename, umode_t mode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 617) {
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 618) struct path path;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 619) int error;
14ff690c0f94c (Jeff Layton 2012-12-11 12:10:13 -0500 620) unsigned int lookup_flags = LOOKUP_FOLLOW;
14ff690c0f94c (Jeff Layton 2012-12-11 12:10:13 -0500 621) retry:
14ff690c0f94c (Jeff Layton 2012-12-11 12:10:13 -0500 622) error = user_path_at(dfd, filename, lookup_flags, &path);
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 623) if (!error) {
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 624) error = chmod_common(&path, mode);
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 625) path_put(&path);
14ff690c0f94c (Jeff Layton 2012-12-11 12:10:13 -0500 626) if (retry_estale(error, lookup_flags)) {
14ff690c0f94c (Jeff Layton 2012-12-11 12:10:13 -0500 627) lookup_flags |= LOOKUP_REVAL;
14ff690c0f94c (Jeff Layton 2012-12-11 12:10:13 -0500 628) goto retry;
14ff690c0f94c (Jeff Layton 2012-12-11 12:10:13 -0500 629) }
e57712ebebbb9 (Al Viro 2011-07-26 04:15:54 -0400 630) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 631) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 632) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 633)
03450e271a160 (Dominik Brodowski 2018-03-11 11:34:53 +0100 634) SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename,
03450e271a160 (Dominik Brodowski 2018-03-11 11:34:53 +0100 635) umode_t, mode)
03450e271a160 (Dominik Brodowski 2018-03-11 11:34:53 +0100 636) {
03450e271a160 (Dominik Brodowski 2018-03-11 11:34:53 +0100 637) return do_fchmodat(dfd, filename, mode);
03450e271a160 (Dominik Brodowski 2018-03-11 11:34:53 +0100 638) }
03450e271a160 (Dominik Brodowski 2018-03-11 11:34:53 +0100 639)
49f0a0767211d (Al Viro 2011-07-26 04:22:01 -0400 640) SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 641) {
03450e271a160 (Dominik Brodowski 2018-03-11 11:34:53 +0100 642) return do_fchmodat(AT_FDCWD, filename, mode);
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 643) }
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 644)
b873498f99c77 (Christoph Hellwig 2020-07-22 11:13:26 +0200 645) int chown_common(const struct path *path, uid_t user, gid_t group)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 646) {
b8b546a061884 (Christian Brauner 2021-01-21 14:19:35 +0100 647) struct user_namespace *mnt_userns;
fe542cf59bf0b (Tetsuo Handa 2009-11-22 11:49:55 +0900 648) struct inode *inode = path->dentry->d_inode;
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 649) struct inode *delegated_inode = NULL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 650) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 651) struct iattr newattrs;
52137abe18201 (Eric W. Biederman 2012-03-03 19:52:01 -0800 652) kuid_t uid;
52137abe18201 (Eric W. Biederman 2012-03-03 19:52:01 -0800 653) kgid_t gid;
52137abe18201 (Eric W. Biederman 2012-03-03 19:52:01 -0800 654)
52137abe18201 (Eric W. Biederman 2012-03-03 19:52:01 -0800 655) uid = make_kuid(current_user_ns(), user);
52137abe18201 (Eric W. Biederman 2012-03-03 19:52:01 -0800 656) gid = make_kgid(current_user_ns(), group);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 657)
b8b546a061884 (Christian Brauner 2021-01-21 14:19:35 +0100 658) mnt_userns = mnt_user_ns(path->mnt);
b8b546a061884 (Christian Brauner 2021-01-21 14:19:35 +0100 659) uid = kuid_from_mnt(mnt_userns, uid);
b8b546a061884 (Christian Brauner 2021-01-21 14:19:35 +0100 660) gid = kgid_from_mnt(mnt_userns, gid);
b8b546a061884 (Christian Brauner 2021-01-21 14:19:35 +0100 661)
c1b8940b42bb6 (Andrew Elble 2015-02-23 08:51:24 -0500 662) retry_deleg:
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 663) newattrs.ia_valid = ATTR_CTIME;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 664) if (user != (uid_t) -1) {
52137abe18201 (Eric W. Biederman 2012-03-03 19:52:01 -0800 665) if (!uid_valid(uid))
52137abe18201 (Eric W. Biederman 2012-03-03 19:52:01 -0800 666) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 667) newattrs.ia_valid |= ATTR_UID;
52137abe18201 (Eric W. Biederman 2012-03-03 19:52:01 -0800 668) newattrs.ia_uid = uid;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 669) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 670) if (group != (gid_t) -1) {
52137abe18201 (Eric W. Biederman 2012-03-03 19:52:01 -0800 671) if (!gid_valid(gid))
52137abe18201 (Eric W. Biederman 2012-03-03 19:52:01 -0800 672) return -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 673) newattrs.ia_valid |= ATTR_GID;
52137abe18201 (Eric W. Biederman 2012-03-03 19:52:01 -0800 674) newattrs.ia_gid = gid;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 675) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 676) if (!S_ISDIR(inode->i_mode))
b53767719b6cd (Serge Hallyn 2007-10-16 23:31:36 -0700 677) newattrs.ia_valid |=
b53767719b6cd (Serge Hallyn 2007-10-16 23:31:36 -0700 678) ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 679) inode_lock(inode);
d2b31ca644fdc (Eric W. Biederman 2012-06-01 16:14:19 -0600 680) error = security_path_chown(path, uid, gid);
fe542cf59bf0b (Tetsuo Handa 2009-11-22 11:49:55 +0900 681) if (!error)
b8b546a061884 (Christian Brauner 2021-01-21 14:19:35 +0100 682) error = notify_change(mnt_userns, path->dentry, &newattrs,
2f221d6f7b881 (Christian Brauner 2021-01-21 14:19:26 +0100 683) &delegated_inode);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 684) inode_unlock(inode);
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 685) if (delegated_inode) {
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 686) error = break_deleg_wait(&delegated_inode);
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 687) if (!error)
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 688) goto retry_deleg;
27ac0ffeac80b (J. Bruce Fields 2011-09-20 17:19:26 -0400 689) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 690) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 691) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 692)
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 693) int do_fchownat(int dfd, const char __user *filename, uid_t user, gid_t group,
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 694) int flag)
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 695) {
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 696) struct path path;
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 697) int error = -EINVAL;
65cfc67223615 (Al Viro 2011-03-13 15:56:26 -0400 698) int lookup_flags;
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 699)
65cfc67223615 (Al Viro 2011-03-13 15:56:26 -0400 700) if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_EMPTY_PATH)) != 0)
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 701) goto out;
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 702)
65cfc67223615 (Al Viro 2011-03-13 15:56:26 -0400 703) lookup_flags = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
65cfc67223615 (Al Viro 2011-03-13 15:56:26 -0400 704) if (flag & AT_EMPTY_PATH)
65cfc67223615 (Al Viro 2011-03-13 15:56:26 -0400 705) lookup_flags |= LOOKUP_EMPTY;
99a5df37a03c9 (Jeff Layton 2012-12-11 12:10:13 -0500 706) retry:
65cfc67223615 (Al Viro 2011-03-13 15:56:26 -0400 707) error = user_path_at(dfd, filename, lookup_flags, &path);
6902d925d568c (Dave Hansen 2006-09-30 23:29:01 -0700 708) if (error)
6902d925d568c (Dave Hansen 2006-09-30 23:29:01 -0700 709) goto out;
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 710) error = mnt_want_write(path.mnt);
2af482a7edfb8 (Dave Hansen 2008-02-15 14:37:50 -0800 711) if (error)
2af482a7edfb8 (Dave Hansen 2008-02-15 14:37:50 -0800 712) goto out_release;
fe542cf59bf0b (Tetsuo Handa 2009-11-22 11:49:55 +0900 713) error = chown_common(&path, user, group);
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 714) mnt_drop_write(path.mnt);
2af482a7edfb8 (Dave Hansen 2008-02-15 14:37:50 -0800 715) out_release:
2d8f30380ab8c (Al Viro 2008-07-22 09:59:21 -0400 716) path_put(&path);
99a5df37a03c9 (Jeff Layton 2012-12-11 12:10:13 -0500 717) if (retry_estale(error, lookup_flags)) {
99a5df37a03c9 (Jeff Layton 2012-12-11 12:10:13 -0500 718) lookup_flags |= LOOKUP_REVAL;
99a5df37a03c9 (Jeff Layton 2012-12-11 12:10:13 -0500 719) goto retry;
99a5df37a03c9 (Jeff Layton 2012-12-11 12:10:13 -0500 720) }
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 721) out:
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 722) return error;
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 723) }
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 724)
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 725) SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 726) gid_t, group, int, flag)
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 727) {
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 728) return do_fchownat(dfd, filename, user, group, flag);
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 729) }
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 730)
55e4def0a6e79 (David Howells 2012-06-25 12:55:09 +0100 731) SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 732) {
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 733) return do_fchownat(AT_FDCWD, filename, user, group, 0);
55e4def0a6e79 (David Howells 2012-06-25 12:55:09 +0100 734) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 735)
55e4def0a6e79 (David Howells 2012-06-25 12:55:09 +0100 736) SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
55e4def0a6e79 (David Howells 2012-06-25 12:55:09 +0100 737) {
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 738) return do_fchownat(AT_FDCWD, filename, user, group,
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 739) AT_SYMLINK_NOFOLLOW);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 740) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 741)
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 742) int vfs_fchown(struct file *file, uid_t user, gid_t group)
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 743) {
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 744) int error;
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 745)
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 746) error = mnt_want_write_file(file);
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 747) if (error)
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 748) return error;
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 749) audit_file(file);
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 750) error = chown_common(&file->f_path, user, group);
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 751) mnt_drop_write_file(file);
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 752) return error;
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 753) }
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 754)
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 755) int ksys_fchown(unsigned int fd, uid_t user, gid_t group)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 756) {
2903ff019b346 (Al Viro 2012-08-28 12:52:22 -0400 757) struct fd f = fdget(fd);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 758) int error = -EBADF;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 759)
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 760) if (f.file) {
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 761) error = vfs_fchown(f.file, user, group);
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 762) fdput(f);
c04011fe8cbd8 (Christoph Hellwig 2020-07-14 08:47:43 +0200 763) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 764) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 765) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 766)
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 767) SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 768) {
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 769) return ksys_fchown(fd, user, group);
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 770) }
55731b3cda3a8 (Dominik Brodowski 2018-03-11 11:34:55 +0100 771)
02e5180d991f2 (Al Viro 2012-06-10 14:32:45 -0400 772) static int do_dentry_open(struct file *f,
4bacc9c9234c7 (David Howells 2015-06-18 14:32:31 +0100 773) struct inode *inode,
ae2bb293a3e8a (Al Viro 2018-07-10 13:22:28 -0400 774) int (*open)(struct inode *, struct file *))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 775) {
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 776) static const struct file_operations empty_fops = {};
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 777) int error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 778)
b5bcdda32736b (Al Viro 2012-07-20 23:28:46 +0400 779) path_get(&f->f_path);
4bacc9c9234c7 (David Howells 2015-06-18 14:32:31 +0100 780) f->f_inode = inode;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 781) f->f_mapping = inode->i_mapping;
5660e13d2fd6a (Jeff Layton 2017-07-06 07:02:25 -0400 782) f->f_wb_err = filemap_sample_wb_err(f->f_mapping);
735e4ae5ba28c (Jeff Layton 2020-06-01 21:45:36 -0700 783) f->f_sb_err = file_sample_sb_err(f);
5660e13d2fd6a (Jeff Layton 2017-07-06 07:02:25 -0400 784)
3f4d5a00076b7 (Al Viro 2014-03-14 09:43:29 -0400 785) if (unlikely(f->f_flags & O_PATH)) {
f5d11409e61da (Al Viro 2018-07-09 02:35:08 -0400 786) f->f_mode = FMODE_PATH | FMODE_OPENED;
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 787) f->f_op = &empty_fops;
af04fadcaa932 (Al Viro 2018-06-02 01:31:02 -0400 788) return 0;
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 789) }
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 790)
dd20908a8a06b (Al Viro 2014-03-14 10:56:20 -0400 791) if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) {
0ccb286346c4c (Al Viro 2014-03-14 10:40:46 -0400 792) error = get_write_access(inode);
3f4d5a00076b7 (Al Viro 2014-03-14 09:43:29 -0400 793) if (unlikely(error))
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 794) goto cleanup_file;
0ccb286346c4c (Al Viro 2014-03-14 10:40:46 -0400 795) error = __mnt_want_write(f->f_path.mnt);
3f4d5a00076b7 (Al Viro 2014-03-14 09:43:29 -0400 796) if (unlikely(error)) {
0ccb286346c4c (Al Viro 2014-03-14 10:40:46 -0400 797) put_write_access(inode);
0ccb286346c4c (Al Viro 2014-03-14 10:40:46 -0400 798) goto cleanup_file;
0ccb286346c4c (Al Viro 2014-03-14 10:40:46 -0400 799) }
83f936c75e368 (Al Viro 2014-03-14 12:02:47 -0400 800) f->f_mode |= FMODE_WRITER;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 801) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 802)
2be7d348fe924 (Linus Torvalds 2019-11-26 11:34:06 -0800 803) /* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */
2be7d348fe924 (Linus Torvalds 2019-11-26 11:34:06 -0800 804) if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))
2be7d348fe924 (Linus Torvalds 2019-11-26 11:34:06 -0800 805) f->f_mode |= FMODE_ATOMIC_POS;
2be7d348fe924 (Linus Torvalds 2019-11-26 11:34:06 -0800 806)
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 807) f->f_op = fops_get(inode->i_fop);
7159d54418e0a (Denis Efremov 2019-09-25 16:49:31 -0700 808) if (WARN_ON(!f->f_op)) {
72c2d53192004 (Al Viro 2013-09-22 16:27:52 -0400 809) error = -ENODEV;
72c2d53192004 (Al Viro 2013-09-22 16:27:52 -0400 810) goto cleanup_all;
72c2d53192004 (Al Viro 2013-09-22 16:27:52 -0400 811) }
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 812)
e3f20ae21079e (Al Viro 2018-07-10 13:25:29 -0400 813) error = security_file_open(f);
788e7dd4c22e6 (Yuichi Nakamura 2007-09-14 09:27:07 +0900 814) if (error)
788e7dd4c22e6 (Yuichi Nakamura 2007-09-14 09:27:07 +0900 815) goto cleanup_all;
788e7dd4c22e6 (Yuichi Nakamura 2007-09-14 09:27:07 +0900 816)
c568d68341be7 (Miklos Szeredi 2016-09-16 12:44:20 +0200 817) error = break_lease(locks_inode(f), f->f_flags);
f3c7691e8d30d (J. Bruce Fields 2011-09-21 10:58:13 -0400 818) if (error)
f3c7691e8d30d (J. Bruce Fields 2011-09-21 10:58:13 -0400 819) goto cleanup_all;
f3c7691e8d30d (J. Bruce Fields 2011-09-21 10:58:13 -0400 820)
ea73ea7279884 (Al Viro 2018-07-11 15:00:04 -0400 821) /* normally all 3 are set; ->open() can clear them if needed */
ea73ea7279884 (Al Viro 2018-07-11 15:00:04 -0400 822) f->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
72c2d53192004 (Al Viro 2013-09-22 16:27:52 -0400 823) if (!open)
834f2a4a1554d (Trond Myklebust 2005-10-18 14:20:16 -0700 824) open = f->f_op->open;
834f2a4a1554d (Trond Myklebust 2005-10-18 14:20:16 -0700 825) if (open) {
834f2a4a1554d (Trond Myklebust 2005-10-18 14:20:16 -0700 826) error = open(inode, f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 827) if (error)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 828) goto cleanup_all;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 829) }
f5d11409e61da (Al Viro 2018-07-09 02:35:08 -0400 830) f->f_mode |= FMODE_OPENED;
890275b5eb79e (Mimi Zohar 2010-11-02 10:13:07 -0400 831) if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
890275b5eb79e (Mimi Zohar 2010-11-02 10:13:07 -0400 832) i_readcount_inc(inode);
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 833) if ((f->f_mode & FMODE_READ) &&
8436318205b9f (Al Viro 2015-04-04 01:14:53 -0400 834) likely(f->f_op->read || f->f_op->read_iter))
7f7f25e82d548 (Al Viro 2014-02-11 17:49:24 -0500 835) f->f_mode |= FMODE_CAN_READ;
293bc9822fa9b (Al Viro 2014-02-11 18:37:41 -0500 836) if ((f->f_mode & FMODE_WRITE) &&
8436318205b9f (Al Viro 2015-04-04 01:14:53 -0400 837) likely(f->f_op->write || f->f_op->write_iter))
7f7f25e82d548 (Al Viro 2014-02-11 17:49:24 -0500 838) f->f_mode |= FMODE_CAN_WRITE;
834f2a4a1554d (Trond Myklebust 2005-10-18 14:20:16 -0700 839)
c75b1d9421f80 (Jens Axboe 2017-06-27 11:47:04 -0600 840) f->f_write_hint = WRITE_LIFE_NOT_SET;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 841) f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 842)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 843) file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
af04fadcaa932 (Al Viro 2018-06-02 01:31:02 -0400 844)
69527c554f82d (Al Viro 2018-06-08 13:01:49 -0400 845) /* NB: we're sure to have correct a_ops only after f_op->open */
69527c554f82d (Al Viro 2018-06-08 13:01:49 -0400 846) if (f->f_flags & O_DIRECT) {
69527c554f82d (Al Viro 2018-06-08 13:01:49 -0400 847) if (!f->f_mapping->a_ops || !f->f_mapping->a_ops->direct_IO)
69527c554f82d (Al Viro 2018-06-08 13:01:49 -0400 848) return -EINVAL;
69527c554f82d (Al Viro 2018-06-08 13:01:49 -0400 849) }
09d91cda0e820 (Song Liu 2019-09-23 15:38:03 -0700 850)
09d91cda0e820 (Song Liu 2019-09-23 15:38:03 -0700 851) /*
09d91cda0e820 (Song Liu 2019-09-23 15:38:03 -0700 852) * XXX: Huge page cache doesn't support writing yet. Drop all page
09d91cda0e820 (Song Liu 2019-09-23 15:38:03 -0700 853) * cache for this file before processing writes.
09d91cda0e820 (Song Liu 2019-09-23 15:38:03 -0700 854) */
09d91cda0e820 (Song Liu 2019-09-23 15:38:03 -0700 855) if ((f->f_mode & FMODE_WRITE) && filemap_nr_thps(inode->i_mapping))
09d91cda0e820 (Song Liu 2019-09-23 15:38:03 -0700 856) truncate_pagecache(inode, 0);
09d91cda0e820 (Song Liu 2019-09-23 15:38:03 -0700 857)
96b7e579addd3 (Al Viro 2012-06-10 14:22:04 -0400 858) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 859)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 860) cleanup_all:
6b4e8085c0004 (Al Viro 2018-07-08 21:45:07 -0400 861) if (WARN_ON_ONCE(error > 0))
6b4e8085c0004 (Al Viro 2018-07-08 21:45:07 -0400 862) error = -EINVAL;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 863) fops_put(f->f_op);
83f936c75e368 (Al Viro 2014-03-14 12:02:47 -0400 864) if (f->f_mode & FMODE_WRITER) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 865) put_write_access(inode);
83f936c75e368 (Al Viro 2014-03-14 12:02:47 -0400 866) __mnt_drop_write(f->f_path.mnt);
4a3fd211ccfc0 (Dave Hansen 2008-02-15 14:37:48 -0800 867) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 868) cleanup_file:
02e5180d991f2 (Al Viro 2012-06-10 14:32:45 -0400 869) path_put(&f->f_path);
02e5180d991f2 (Al Viro 2012-06-10 14:32:45 -0400 870) f->f_path.mnt = NULL;
02e5180d991f2 (Al Viro 2012-06-10 14:32:45 -0400 871) f->f_path.dentry = NULL;
dd37978c50bc8 (Al Viro 2013-03-01 19:48:30 -0500 872) f->f_inode = NULL;
96b7e579addd3 (Al Viro 2012-06-10 14:22:04 -0400 873) return error;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 874) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 875)
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 876) /**
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 877) * finish_open - finish opening a file
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 878) * @file: file pointer
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 879) * @dentry: pointer to dentry
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 880) * @open: open callback
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 881) * @opened: state of open
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 882) *
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 883) * This can be used to finish opening a file passed to i_op->atomic_open().
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 884) *
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 885) * If the open callback is set to NULL, then the standard f_op->open()
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 886) * filesystem callback is substituted.
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 887) *
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 888) * NB: the dentry reference is _not_ consumed. If, for example, the dentry is
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 889) * the return value of d_splice_alias(), then the caller needs to perform dput()
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 890) * on it after finish_open().
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 891) *
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 892) * Returns zero on success or -errno if the open failed.
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 893) */
30d904947459c (Al Viro 2012-06-22 12:40:19 +0400 894) int finish_open(struct file *file, struct dentry *dentry,
be12af3ef5e61 (Al Viro 2018-06-08 11:44:56 -0400 895) int (*open)(struct inode *, struct file *))
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 896) {
aad888f828fec (Al Viro 2018-06-08 12:58:04 -0400 897) BUG_ON(file->f_mode & FMODE_OPENED); /* once it's opened, it's opened */
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 898)
b5bcdda32736b (Al Viro 2012-07-20 23:28:46 +0400 899) file->f_path.dentry = dentry;
aad888f828fec (Al Viro 2018-06-08 12:58:04 -0400 900) return do_dentry_open(file, d_backing_inode(dentry), open);
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 901) }
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 902) EXPORT_SYMBOL(finish_open);
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 903)
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 904) /**
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 905) * finish_no_open - finish ->atomic_open() without opening the file
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 906) *
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 907) * @file: file pointer
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 908) * @dentry: dentry or NULL (as returned from ->lookup())
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 909) *
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 910) * This can be used to set the result of a successful lookup in ->atomic_open().
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 911) *
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 912) * NB: unlike finish_open() this function does consume the dentry reference and
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 913) * the caller need not dput() it.
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 914) *
64e1ac4d46f9f (Al Viro 2018-07-09 19:17:52 -0400 915) * Returns "0" which must be the return value of ->atomic_open() after having
0854d450e229e (Miklos Szeredi 2013-09-16 14:51:55 +0200 916) * called this function.
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 917) */
e45198a6ac24b (Al Viro 2012-06-10 06:48:09 -0400 918) int finish_no_open(struct file *file, struct dentry *dentry)
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 919) {
30d904947459c (Al Viro 2012-06-22 12:40:19 +0400 920) file->f_path.dentry = dentry;
64e1ac4d46f9f (Al Viro 2018-07-09 19:17:52 -0400 921) return 0;
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 922) }
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 923) EXPORT_SYMBOL(finish_no_open);
d18e9008c377d (Miklos Szeredi 2012-06-05 15:10:17 +0200 924)
9bf39ab2adafd (Miklos Szeredi 2015-06-19 10:29:13 +0200 925) char *file_path(struct file *filp, char *buf, int buflen)
9bf39ab2adafd (Miklos Szeredi 2015-06-19 10:29:13 +0200 926) {
9bf39ab2adafd (Miklos Szeredi 2015-06-19 10:29:13 +0200 927) return d_path(&filp->f_path, buf, buflen);
9bf39ab2adafd (Miklos Szeredi 2015-06-19 10:29:13 +0200 928) }
9bf39ab2adafd (Miklos Szeredi 2015-06-19 10:29:13 +0200 929) EXPORT_SYMBOL(file_path);
9bf39ab2adafd (Miklos Szeredi 2015-06-19 10:29:13 +0200 930)
4bacc9c9234c7 (David Howells 2015-06-18 14:32:31 +0100 931) /**
4bacc9c9234c7 (David Howells 2015-06-18 14:32:31 +0100 932) * vfs_open - open the file at the given path
4bacc9c9234c7 (David Howells 2015-06-18 14:32:31 +0100 933) * @path: path to open
4bacc9c9234c7 (David Howells 2015-06-18 14:32:31 +0100 934) * @file: newly allocated file with f_flag initialized
4bacc9c9234c7 (David Howells 2015-06-18 14:32:31 +0100 935) * @cred: credentials to use
4bacc9c9234c7 (David Howells 2015-06-18 14:32:31 +0100 936) */
ae2bb293a3e8a (Al Viro 2018-07-10 13:22:28 -0400 937) int vfs_open(const struct path *path, struct file *file)
4bacc9c9234c7 (David Howells 2015-06-18 14:32:31 +0100 938) {
54d5ca871e72f (Miklos Szeredi 2016-05-11 01:16:37 +0200 939) file->f_path = *path;
a6518f73e60e5 (Miklos Szeredi 2018-07-06 23:57:06 +0200 940) return do_dentry_open(file, d_backing_inode(path->dentry), NULL);
4bacc9c9234c7 (David Howells 2015-06-18 14:32:31 +0100 941) }
4bacc9c9234c7 (David Howells 2015-06-18 14:32:31 +0100 942)
765927b2d5087 (Al Viro 2012-06-26 21:58:53 +0400 943) struct file *dentry_open(const struct path *path, int flags,
745ca2475a6ac (David Howells 2008-11-14 10:39:22 +1100 944) const struct cred *cred)
a1a5b3d93ca45 (Peter Staubach 2005-09-13 01:25:12 -0700 945) {
a1a5b3d93ca45 (Peter Staubach 2005-09-13 01:25:12 -0700 946) int error;
a1a5b3d93ca45 (Peter Staubach 2005-09-13 01:25:12 -0700 947) struct file *f;
a1a5b3d93ca45 (Peter Staubach 2005-09-13 01:25:12 -0700 948)
e0e817392b9ac (David Howells 2009-09-02 09:13:40 +0100 949) validate_creds(cred);
e0e817392b9ac (David Howells 2009-09-02 09:13:40 +0100 950)
c212f9aaf9101 (Tetsuo Handa 2011-01-19 21:08:41 +0900 951) /* We must always pass in a valid mount pointer. */
765927b2d5087 (Al Viro 2012-06-26 21:58:53 +0400 952) BUG_ON(!path->mnt);
322ee5b36eac4 (Christoph Hellwig 2008-02-15 14:37:24 -0800 953)
ea73ea7279884 (Al Viro 2018-07-11 15:00:04 -0400 954) f = alloc_empty_file(flags, cred);
af04fadcaa932 (Al Viro 2018-06-02 01:31:02 -0400 955) if (!IS_ERR(f)) {
ae2bb293a3e8a (Al Viro 2018-07-10 13:22:28 -0400 956) error = vfs_open(path, f);
4d27f3266f14e (Al Viro 2018-07-09 11:14:39 -0400 957) if (error) {
4d27f3266f14e (Al Viro 2018-07-09 11:14:39 -0400 958) fput(f);
af04fadcaa932 (Al Viro 2018-06-02 01:31:02 -0400 959) f = ERR_PTR(error);
af04fadcaa932 (Al Viro 2018-06-02 01:31:02 -0400 960) }
2a027e7a18738 (Al Viro 2012-06-10 14:24:38 -0400 961) }
2a027e7a18738 (Al Viro 2012-06-10 14:24:38 -0400 962) return f;
a1a5b3d93ca45 (Peter Staubach 2005-09-13 01:25:12 -0700 963) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 964) EXPORT_SYMBOL(dentry_open);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 965)
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 966) struct file *open_with_fake_path(const struct path *path, int flags,
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 967) struct inode *inode, const struct cred *cred)
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 968) {
d3b1084dfd629 (Miklos Szeredi 2018-07-18 15:44:40 +0200 969) struct file *f = alloc_empty_file_noaccount(flags, cred);
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 970) if (!IS_ERR(f)) {
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 971) int error;
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 972)
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 973) f->f_path = *path;
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 974) error = do_dentry_open(f, inode, NULL);
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 975) if (error) {
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 976) fput(f);
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 977) f = ERR_PTR(error);
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 978) }
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 979) }
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 980) return f;
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 981) }
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 982) EXPORT_SYMBOL(open_with_fake_path);
2abc77af89e17 (Al Viro 2018-07-12 11:18:42 -0400 983)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 984) #define WILL_CREATE(flags) (flags & (O_CREAT | __O_TMPFILE))
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 985) #define O_PATH_FLAGS (O_DIRECTORY | O_NOFOLLOW | O_PATH | O_CLOEXEC)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 986)
35cb6d54c1d5d (Jens Axboe 2019-12-13 11:10:11 -0700 987) inline struct open_how build_open_how(int flags, umode_t mode)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 988) {
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 989) struct open_how how = {
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 990) .flags = flags & VALID_OPEN_FLAGS,
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 991) .mode = mode & S_IALLUGO,
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 992) };
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 993)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 994) /* O_PATH beats everything else. */
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 995) if (how.flags & O_PATH)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 996) how.flags &= O_PATH_FLAGS;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 997) /* Modes should only be set for create-like flags. */
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 998) if (!WILL_CREATE(how.flags))
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 999) how.mode = 0;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1000) return how;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1001) }
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1002)
35cb6d54c1d5d (Jens Axboe 2019-12-13 11:10:11 -0700 1003) inline int build_open_flags(const struct open_how *how, struct open_flags *op)
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1004) {
2b2a31cad66c1 (Christian Brauner 2021-05-28 11:24:16 +0200 1005) u64 flags = how->flags;
2b2a31cad66c1 (Christian Brauner 2021-05-28 11:24:16 +0200 1006) u64 strip = FMODE_NONOTIFY | O_CLOEXEC;
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1007) int lookup_flags = 0;
62fb4a155f745 (Al Viro 2015-12-26 22:33:24 -0500 1008) int acc_mode = ACC_MODE(flags);
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1009)
2b2a31cad66c1 (Christian Brauner 2021-05-28 11:24:16 +0200 1010) BUILD_BUG_ON_MSG(upper_32_bits(VALID_OPEN_FLAGS),
2b2a31cad66c1 (Christian Brauner 2021-05-28 11:24:16 +0200 1011) "struct open_flags doesn't yet handle flags > 32 bits");
2b2a31cad66c1 (Christian Brauner 2021-05-28 11:24:16 +0200 1012)
2b2a31cad66c1 (Christian Brauner 2021-05-28 11:24:16 +0200 1013) /*
2b2a31cad66c1 (Christian Brauner 2021-05-28 11:24:16 +0200 1014) * Strip flags that either shouldn't be set by userspace like
2b2a31cad66c1 (Christian Brauner 2021-05-28 11:24:16 +0200 1015) * FMODE_NONOTIFY or that aren't relevant in determining struct
2b2a31cad66c1 (Christian Brauner 2021-05-28 11:24:16 +0200 1016) * open_flags like O_CLOEXEC.
2b2a31cad66c1 (Christian Brauner 2021-05-28 11:24:16 +0200 1017) */
2b2a31cad66c1 (Christian Brauner 2021-05-28 11:24:16 +0200 1018) flags &= ~strip;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1019)
629e014bb8349 (Christoph Hellwig 2017-04-27 09:42:25 +0200 1020) /*
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1021) * Older syscalls implicitly clear all of the invalid flags or argument
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1022) * values before calling build_open_flags(), but openat2(2) checks all
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1023) * of its arguments.
629e014bb8349 (Christoph Hellwig 2017-04-27 09:42:25 +0200 1024) */
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1025) if (flags & ~VALID_OPEN_FLAGS)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1026) return -EINVAL;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1027) if (how->resolve & ~VALID_RESOLVE_FLAGS)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1028) return -EINVAL;
629e014bb8349 (Christoph Hellwig 2017-04-27 09:42:25 +0200 1029)
398840f8bb935 (Aleksa Sarai 2020-10-28 10:50:43 +1100 1030) /* Scoping flags are mutually exclusive. */
398840f8bb935 (Aleksa Sarai 2020-10-28 10:50:43 +1100 1031) if ((how->resolve & RESOLVE_BENEATH) && (how->resolve & RESOLVE_IN_ROOT))
398840f8bb935 (Aleksa Sarai 2020-10-28 10:50:43 +1100 1032) return -EINVAL;
398840f8bb935 (Aleksa Sarai 2020-10-28 10:50:43 +1100 1033)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1034) /* Deal with the mode. */
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1035) if (WILL_CREATE(flags)) {
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1036) if (how->mode & ~S_IALLUGO)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1037) return -EINVAL;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1038) op->mode = how->mode | S_IFREG;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1039) } else {
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1040) if (how->mode != 0)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1041) return -EINVAL;
e68726ff72cf7 (Miklos Szeredi 2012-08-15 13:01:24 +0200 1042) op->mode = 0;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1043) }
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1044)
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1045) /*
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1046) * In order to ensure programs get explicit errors when trying to use
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1047) * O_TMPFILE on old kernels, O_TMPFILE is implemented such that it
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1048) * looks like (O_DIRECTORY|O_RDWR & ~O_CREAT) to old kernels. But we
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1049) * have to require userspace to explicitly set it.
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1050) */
bb458c644a59d (Al Viro 2013-07-13 13:26:37 +0400 1051) if (flags & __O_TMPFILE) {
bb458c644a59d (Al Viro 2013-07-13 13:26:37 +0400 1052) if ((flags & O_TMPFILE_MASK) != O_TMPFILE)
60545d0d4610b (Al Viro 2013-06-07 01:20:27 -0400 1053) return -EINVAL;
ba57ea64cb182 (Al Viro 2013-07-20 03:11:32 +0400 1054) if (!(acc_mode & MAY_WRITE))
ba57ea64cb182 (Al Viro 2013-07-20 03:11:32 +0400 1055) return -EINVAL;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1056) }
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1057) if (flags & O_PATH) {
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1058) /* O_PATH only permits certain other flags to be set. */
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1059) if (flags & ~O_PATH_FLAGS)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1060) return -EINVAL;
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 1061) acc_mode = 0;
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 1062) }
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1063)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1064) /*
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1065) * O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1066) * check for O_DSYNC if the need any syncing at all we enforce it's
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1067) * always set instead of having to deal with possibly weird behaviour
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1068) * for malicious applications setting only __O_SYNC.
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1069) */
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1070) if (flags & __O_SYNC)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1071) flags |= O_DSYNC;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1072)
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 1073) op->open_flag = flags;
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1074)
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1075) /* O_TRUNC implies we need access checks for write permissions */
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1076) if (flags & O_TRUNC)
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1077) acc_mode |= MAY_WRITE;
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1078)
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1079) /* Allow the LSM permission hook to distinguish append
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1080) access from general write access. */
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1081) if (flags & O_APPEND)
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1082) acc_mode |= MAY_APPEND;
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1083)
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1084) op->acc_mode = acc_mode;
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1085)
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 1086) op->intent = flags & O_PATH ? 0 : LOOKUP_OPEN;
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 1087)
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1088) if (flags & O_CREAT) {
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1089) op->intent |= LOOKUP_CREATE;
31d1726d72500 (Al Viro 2020-01-08 20:19:38 -0500 1090) if (flags & O_EXCL) {
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1091) op->intent |= LOOKUP_EXCL;
31d1726d72500 (Al Viro 2020-01-08 20:19:38 -0500 1092) flags |= O_NOFOLLOW;
31d1726d72500 (Al Viro 2020-01-08 20:19:38 -0500 1093) }
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1094) }
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1095)
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1096) if (flags & O_DIRECTORY)
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1097) lookup_flags |= LOOKUP_DIRECTORY;
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1098) if (!(flags & O_NOFOLLOW))
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1099) lookup_flags |= LOOKUP_FOLLOW;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1100)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1101) if (how->resolve & RESOLVE_NO_XDEV)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1102) lookup_flags |= LOOKUP_NO_XDEV;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1103) if (how->resolve & RESOLVE_NO_MAGICLINKS)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1104) lookup_flags |= LOOKUP_NO_MAGICLINKS;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1105) if (how->resolve & RESOLVE_NO_SYMLINKS)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1106) lookup_flags |= LOOKUP_NO_SYMLINKS;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1107) if (how->resolve & RESOLVE_BENEATH)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1108) lookup_flags |= LOOKUP_BENEATH;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1109) if (how->resolve & RESOLVE_IN_ROOT)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1110) lookup_flags |= LOOKUP_IN_ROOT;
99668f6180628 (Jens Axboe 2020-12-17 09:19:10 -0700 1111) if (how->resolve & RESOLVE_CACHED) {
99668f6180628 (Jens Axboe 2020-12-17 09:19:10 -0700 1112) /* Don't bother even trying for create/truncate/tmpfile open */
99668f6180628 (Jens Axboe 2020-12-17 09:19:10 -0700 1113) if (flags & (O_TRUNC | O_CREAT | O_TMPFILE))
99668f6180628 (Jens Axboe 2020-12-17 09:19:10 -0700 1114) return -EAGAIN;
99668f6180628 (Jens Axboe 2020-12-17 09:19:10 -0700 1115) lookup_flags |= LOOKUP_CACHED;
99668f6180628 (Jens Axboe 2020-12-17 09:19:10 -0700 1116) }
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1117)
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1118) op->lookup_flags = lookup_flags;
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1119) return 0;
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1120) }
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1121)
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1122) /**
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1123) * file_open_name - open file and return file pointer
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1124) *
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1125) * @name: struct filename containing path to open
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1126) * @flags: open flags as per the open(2) second argument
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1127) * @mode: mode for the new file if O_CREAT is set, else ignored
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1128) *
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1129) * This is the helper to open a file from kernelspace if you really
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1130) * have to. But in generally you should not do this, so please move
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1131) * along, nothing to see here..
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1132) */
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1133) struct file *file_open_name(struct filename *name, int flags, umode_t mode)
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1134) {
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1135) struct open_flags op;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1136) struct open_how how = build_open_how(flags, mode);
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1137) int err = build_open_flags(&how, &op);
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1138) if (err)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1139) return ERR_PTR(err);
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1140) return do_filp_open(AT_FDCWD, name, &op);
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1141) }
669abf4e5539c (Jeff Layton 2012-10-10 16:43:10 -0400 1142)
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1143) /**
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1144) * filp_open - open file and return file pointer
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1145) *
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1146) * @filename: path to open
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1147) * @flags: open flags as per the open(2) second argument
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1148) * @mode: mode for the new file if O_CREAT is set, else ignored
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1149) *
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1150) * This is the helper to open a file from kernelspace if you really
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1151) * have to. But in generally you should not do this, so please move
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1152) * along, nothing to see here..
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1153) */
a218d0fdc5f90 (Al Viro 2011-11-21 14:59:34 -0500 1154) struct file *filp_open(const char *filename, int flags, umode_t mode)
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1155) {
5168910413830 (Paul Moore 2015-01-22 00:00:03 -0500 1156) struct filename *name = getname_kernel(filename);
5168910413830 (Paul Moore 2015-01-22 00:00:03 -0500 1157) struct file *file = ERR_CAST(name);
5168910413830 (Paul Moore 2015-01-22 00:00:03 -0500 1158)
5168910413830 (Paul Moore 2015-01-22 00:00:03 -0500 1159) if (!IS_ERR(name)) {
5168910413830 (Paul Moore 2015-01-22 00:00:03 -0500 1160) file = file_open_name(name, flags, mode);
5168910413830 (Paul Moore 2015-01-22 00:00:03 -0500 1161) putname(name);
5168910413830 (Paul Moore 2015-01-22 00:00:03 -0500 1162) }
5168910413830 (Paul Moore 2015-01-22 00:00:03 -0500 1163) return file;
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1164) }
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1165) EXPORT_SYMBOL(filp_open);
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1166)
73d049a40fc62 (Al Viro 2011-03-11 12:08:24 -0500 1167) struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
378c6520e7d29 (Jann Horn 2016-03-22 14:25:36 -0700 1168) const char *filename, int flags, umode_t mode)
73d049a40fc62 (Al Viro 2011-03-11 12:08:24 -0500 1169) {
73d049a40fc62 (Al Viro 2011-03-11 12:08:24 -0500 1170) struct open_flags op;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1171) struct open_how how = build_open_how(flags, mode);
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1172) int err = build_open_flags(&how, &op);
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1173) if (err)
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1174) return ERR_PTR(err);
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1175) return do_file_open_root(dentry, mnt, filename, &op);
73d049a40fc62 (Al Viro 2011-03-11 12:08:24 -0500 1176) }
73d049a40fc62 (Al Viro 2011-03-11 12:08:24 -0500 1177) EXPORT_SYMBOL(file_open_root);
73d049a40fc62 (Al Viro 2011-03-11 12:08:24 -0500 1178)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1179) static long do_sys_openat2(int dfd, const char __user *filename,
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1180) struct open_how *how)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1181) {
47c805dc2d2df (Al Viro 2011-02-23 17:44:09 -0500 1182) struct open_flags op;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1183) int fd = build_open_flags(how, &op);
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1184) struct filename *tmp;
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1185)
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1186) if (fd)
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1187) return fd;
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1188)
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1189) tmp = getname(filename);
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1190) if (IS_ERR(tmp))
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1191) return PTR_ERR(tmp);
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1192)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1193) fd = get_unused_fd_flags(how->flags);
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1194) if (fd >= 0) {
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1195) struct file *f = do_filp_open(dfd, tmp, &op);
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1196) if (IS_ERR(f)) {
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1197) put_unused_fd(fd);
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1198) fd = PTR_ERR(f);
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1199) } else {
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1200) fsnotify_open(f);
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1201) fd_install(fd, f);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1202) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1203) }
f9652e10c12b4 (Al Viro 2013-06-11 08:23:01 +0400 1204) putname(tmp);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1205) return fd;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1206) }
e922efc342d56 (Miklos Szeredi 2005-09-06 15:18:25 -0700 1207)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1208) long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
e922efc342d56 (Miklos Szeredi 2005-09-06 15:18:25 -0700 1209) {
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1210) struct open_how how = build_open_how(flags, mode);
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1211) return do_sys_openat2(dfd, filename, &how);
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1212) }
e922efc342d56 (Miklos Szeredi 2005-09-06 15:18:25 -0700 1213)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1214)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1215) SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1216) {
166e07c37c641 (Christoph Hellwig 2020-06-06 15:03:21 +0200 1217) if (force_o_largefile())
166e07c37c641 (Christoph Hellwig 2020-06-06 15:03:21 +0200 1218) flags |= O_LARGEFILE;
166e07c37c641 (Christoph Hellwig 2020-06-06 15:03:21 +0200 1219) return do_sys_open(AT_FDCWD, filename, flags, mode);
e922efc342d56 (Miklos Szeredi 2005-09-06 15:18:25 -0700 1220) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1221)
6559eed8ca7db (Heiko Carstens 2009-01-14 14:14:32 +0100 1222) SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags,
a218d0fdc5f90 (Al Viro 2011-11-21 14:59:34 -0500 1223) umode_t, mode)
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 1224) {
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 1225) if (force_o_largefile())
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 1226) flags |= O_LARGEFILE;
2cf0966683430 (Al Viro 2013-01-21 15:25:54 -0500 1227) return do_sys_open(dfd, filename, flags, mode);
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 1228) }
5590ff0d5528b (Ulrich Drepper 2006-01-18 17:43:53 -0800 1229)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1230) SYSCALL_DEFINE4(openat2, int, dfd, const char __user *, filename,
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1231) struct open_how __user *, how, size_t, usize)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1232) {
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1233) int err;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1234) struct open_how tmp;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1235)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1236) BUILD_BUG_ON(sizeof(struct open_how) < OPEN_HOW_SIZE_VER0);
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1237) BUILD_BUG_ON(sizeof(struct open_how) != OPEN_HOW_SIZE_LATEST);
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1238)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1239) if (unlikely(usize < OPEN_HOW_SIZE_VER0))
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1240) return -EINVAL;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1241)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1242) err = copy_struct_from_user(&tmp, sizeof(tmp), how, usize);
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1243) if (err)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1244) return err;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1245)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1246) /* O_LARGEFILE is only allowed for non-O_PATH. */
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1247) if (!(tmp.flags & O_PATH) && force_o_largefile())
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1248) tmp.flags |= O_LARGEFILE;
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1249)
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1250) return do_sys_openat2(dfd, filename, &tmp);
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1251) }
fddb5d430ad9f (Aleksa Sarai 2020-01-18 23:07:59 +1100 1252)
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1253) #ifdef CONFIG_COMPAT
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1254) /*
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1255) * Exactly like sys_open(), except that it doesn't set the
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1256) * O_LARGEFILE flag.
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1257) */
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1258) COMPAT_SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1259) {
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1260) return do_sys_open(AT_FDCWD, filename, flags, mode);
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1261) }
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1262)
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1263) /*
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1264) * Exactly like sys_openat(), except that it doesn't set the
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1265) * O_LARGEFILE flag.
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1266) */
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1267) COMPAT_SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, umode_t, mode)
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1268) {
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1269) return do_sys_open(dfd, filename, flags, mode);
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1270) }
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1271) #endif
e35d49f637d5c (Al Viro 2017-04-08 18:15:12 -0400 1272)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1273) #ifndef __alpha__
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1274)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1275) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1276) * For backward compatibility? Maybe this should be moved
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1277) * into arch/i386 instead?
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1278) */
a218d0fdc5f90 (Al Viro 2011-11-21 14:59:34 -0500 1279) SYSCALL_DEFINE2(creat, const char __user *, pathname, umode_t, mode)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1280) {
166e07c37c641 (Christoph Hellwig 2020-06-06 15:03:21 +0200 1281) int flags = O_CREAT | O_WRONLY | O_TRUNC;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1282)
166e07c37c641 (Christoph Hellwig 2020-06-06 15:03:21 +0200 1283) if (force_o_largefile())
166e07c37c641 (Christoph Hellwig 2020-06-06 15:03:21 +0200 1284) flags |= O_LARGEFILE;
166e07c37c641 (Christoph Hellwig 2020-06-06 15:03:21 +0200 1285) return do_sys_open(AT_FDCWD, pathname, flags, mode);
166e07c37c641 (Christoph Hellwig 2020-06-06 15:03:21 +0200 1286) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1287) #endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1288)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1289) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1290) * "id" is the POSIX thread ID. We use the
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1291) * files pointer for this..
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1292) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1293) int filp_close(struct file *filp, fl_owner_t id)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1294) {
45778ca819acc (Christoph Lameter 2005-06-23 00:10:17 -0700 1295) int retval = 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1296)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1297) if (!file_count(filp)) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1298) printk(KERN_ERR "VFS: Close: file count is 0\n");
45778ca819acc (Christoph Lameter 2005-06-23 00:10:17 -0700 1299) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1300) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1301)
72c2d53192004 (Al Viro 2013-09-22 16:27:52 -0400 1302) if (filp->f_op->flush)
75e1fcc0b18df (Miklos Szeredi 2006-06-23 02:05:12 -0700 1303) retval = filp->f_op->flush(filp, id);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1304)
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 1305) if (likely(!(filp->f_mode & FMODE_PATH))) {
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 1306) dnotify_flush(filp, id);
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 1307) locks_remove_posix(filp, id);
1abf0c718f15a (Al Viro 2011-03-13 03:51:11 -0400 1308) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1309) fput(filp);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1310) return retval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1311) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1312)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1313) EXPORT_SYMBOL(filp_close);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1314)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1315) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1316) * Careful here! We test whether the file pointer is NULL before
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1317) * releasing the fd. This ensures that one clone task can't release
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1318) * an fd while another clone is opening it.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1319) */
ca013e945b1ba (Heiko Carstens 2009-01-14 14:14:19 +0100 1320) SYSCALL_DEFINE1(close, unsigned int, fd)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1321) {
8760c909f54a8 (Eric W. Biederman 2020-11-20 17:14:38 -0600 1322) int retval = close_fd(fd);
ee731f4f7880b (Ernie Petrides 2006-09-29 02:00:13 -0700 1323)
ee731f4f7880b (Ernie Petrides 2006-09-29 02:00:13 -0700 1324) /* can't restart close syscall because file table entry was cleared */
ee731f4f7880b (Ernie Petrides 2006-09-29 02:00:13 -0700 1325) if (unlikely(retval == -ERESTARTSYS ||
ee731f4f7880b (Ernie Petrides 2006-09-29 02:00:13 -0700 1326) retval == -ERESTARTNOINTR ||
ee731f4f7880b (Ernie Petrides 2006-09-29 02:00:13 -0700 1327) retval == -ERESTARTNOHAND ||
ee731f4f7880b (Ernie Petrides 2006-09-29 02:00:13 -0700 1328) retval == -ERESTART_RESTARTBLOCK))
ee731f4f7880b (Ernie Petrides 2006-09-29 02:00:13 -0700 1329) retval = -EINTR;
ee731f4f7880b (Ernie Petrides 2006-09-29 02:00:13 -0700 1330)
ee731f4f7880b (Ernie Petrides 2006-09-29 02:00:13 -0700 1331) return retval;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1332) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1333)
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1334) /**
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1335) * close_range() - Close all file descriptors in a given range.
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1336) *
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1337) * @fd: starting file descriptor to close
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1338) * @max_fd: last file descriptor to close
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1339) * @flags: reserved for future extensions
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1340) *
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1341) * This closes a range of file descriptors. All file descriptors
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1342) * from @fd up to and including @max_fd are closed.
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1343) * Currently, errors to close a given file descriptor are ignored.
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1344) */
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1345) SYSCALL_DEFINE3(close_range, unsigned int, fd, unsigned int, max_fd,
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1346) unsigned int, flags)
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1347) {
60997c3d45d9a (Christian Brauner 2020-06-03 21:48:55 +0200 1348) return __close_range(fd, max_fd, flags);
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1349) }
278a5fbaed89d (Christian Brauner 2019-05-24 11:30:34 +0200 1350)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1351) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1352) * This routine simulates a hangup on the tty, to arrange that users
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1353) * are given clean terminals at login time.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1354) */
ca013e945b1ba (Heiko Carstens 2009-01-14 14:14:19 +0100 1355) SYSCALL_DEFINE0(vhangup)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1356) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1357) if (capable(CAP_SYS_TTY_CONFIG)) {
2cb5998b5f0cc (Alan Cox 2008-10-13 10:40:30 +0100 1358) tty_vhangup_self();
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1359) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1360) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1361) return -EPERM;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1362) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1363)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1364) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1365) * Called when an inode is about to be open.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1366) * We use this to disallow opening large files on 32bit systems if
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1367) * the caller didn't specify O_LARGEFILE. On 64bit systems we force
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1368) * on this flag in sys_open.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1369) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1370) int generic_file_open(struct inode * inode, struct file * filp)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1371) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1372) if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
a9c62a18a2914 (Alan Cox 2007-10-16 23:30:22 -0700 1373) return -EOVERFLOW;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1374) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1375) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1376)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1377) EXPORT_SYMBOL(generic_file_open);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1378)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1379) /*
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1380) * This is used by subsystems that don't want seekable
06b1e104b7ea1 (Dmitry Torokhov 2010-08-10 18:01:33 -0700 1381) * file descriptors. The function is not supposed to ever fail, the only
06b1e104b7ea1 (Dmitry Torokhov 2010-08-10 18:01:33 -0700 1382) * reason it returns an 'int' and not 'void' is so that it can be plugged
06b1e104b7ea1 (Dmitry Torokhov 2010-08-10 18:01:33 -0700 1383) * directly into file_operations structure.
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1384) */
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1385) int nonseekable_open(struct inode *inode, struct file *filp)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1386) {
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1387) filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1388) return 0;
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1389) }
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1390)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 1391) EXPORT_SYMBOL(nonseekable_open);
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1392)
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1393) /*
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1394) * stream_open is used by subsystems that want stream-like file descriptors.
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1395) * Such file descriptors are not seekable and don't have notion of position
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 1396) * (file.f_pos is always 0 and ppos passed to .read()/.write() is always NULL).
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 1397) * Contrary to file descriptors of other regular files, .read() and .write()
438ab720c675a (Kirill Smelkov 2019-04-12 12:31:57 +0300 1398) * can run simultaneously.
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1399) *
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1400) * stream_open never fails and is marked to return int so that it could be
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1401) * directly used as file_operations.open .
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1402) */
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1403) int stream_open(struct inode *inode, struct file *filp)
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1404) {
2be7d348fe924 (Linus Torvalds 2019-11-26 11:34:06 -0800 1405) filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE | FMODE_ATOMIC_POS);
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1406) filp->f_mode |= FMODE_STREAM;
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1407) return 0;
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1408) }
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1409)
10dce8af34226 (Kirill Smelkov 2019-03-26 22:20:43 +0000 1410) EXPORT_SYMBOL(stream_open);