From dab741e0e02bd3c4f5e2e97be74b39df2523fc6e Mon Sep 17 00:00:00 2001 From: Mattias Nissler Date: Thu, 27 Aug 2020 11:09:46 -0600 Subject: Add a "nosymfollow" mount option. For mounts that have the new "nosymfollow" option, don't follow symlinks when resolving paths. The new option is similar in spirit to the existing "nodev", "noexec", and "nosuid" options, as well as to the LOOKUP_NO_SYMLINKS resolve flag in the openat2(2) syscall. Various BSD variants have been supporting the "nosymfollow" mount option for a long time with equivalent implementations. Note that symlinks may still be created on file systems mounted with the "nosymfollow" option present. readlink() remains functional, so user space code that is aware of symlinks can still choose to follow them explicitly. Setting the "nosymfollow" mount option helps prevent privileged writers from modifying files unintentionally in case there is an unexpected link along the accessed path. The "nosymfollow" option is thus useful as a defensive measure for systems that need to deal with untrusted file systems in privileged contexts. More information on the history and motivation for this patch can be found here: https://sites.google.com/a/chromium.org/dev/chromium-os/chromiumos-design-docs/hardening-against-malicious-stateful-data#TOC-Restricting-symlink-traversal Signed-off-by: Mattias Nissler Signed-off-by: Ross Zwisler Reviewed-by: Aleksa Sarai Signed-off-by: Al Viro --- include/linux/mount.h | 3 ++- include/linux/statfs.h | 1 + include/uapi/linux/mount.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/mount.h b/include/linux/mount.h index de657bd211fa..aaf343b38671 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -30,6 +30,7 @@ struct fs_context; #define MNT_NODIRATIME 0x10 #define MNT_RELATIME 0x20 #define MNT_READONLY 0x40 /* does the user want this to be r/o? */ +#define MNT_NOSYMFOLLOW 0x80 #define MNT_SHRINKABLE 0x100 #define MNT_WRITE_HOLD 0x200 @@ -46,7 +47,7 @@ struct fs_context; #define MNT_SHARED_MASK (MNT_UNBINDABLE) #define MNT_USER_SETTABLE_MASK (MNT_NOSUID | MNT_NODEV | MNT_NOEXEC \ | MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME \ - | MNT_READONLY) + | MNT_READONLY | MNT_NOSYMFOLLOW) #define MNT_ATIME_MASK (MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME ) #define MNT_INTERNAL_FLAGS (MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | \ diff --git a/include/linux/statfs.h b/include/linux/statfs.h index 9bc69edb8f18..fac4356ea1bf 100644 --- a/include/linux/statfs.h +++ b/include/linux/statfs.h @@ -40,6 +40,7 @@ struct kstatfs { #define ST_NOATIME 0x0400 /* do not update access times */ #define ST_NODIRATIME 0x0800 /* do not update directory access times */ #define ST_RELATIME 0x1000 /* update atime relative to mtime/ctime */ +#define ST_NOSYMFOLLOW 0x2000 /* do not follow symlinks */ struct dentry; extern int vfs_get_fsid(struct dentry *dentry, __kernel_fsid_t *fsid); diff --git a/include/uapi/linux/mount.h b/include/uapi/linux/mount.h index 96a0240f23fe..dd8306ea336c 100644 --- a/include/uapi/linux/mount.h +++ b/include/uapi/linux/mount.h @@ -16,6 +16,7 @@ #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ #define MS_DIRSYNC 128 /* Directory modifications are synchronous */ +#define MS_NOSYMFOLLOW 256 /* Do not follow symlinks */ #define MS_NOATIME 1024 /* Do not update access times. */ #define MS_NODIRATIME 2048 /* Do not update directory access times */ #define MS_BIND 4096 -- cgit v1.2.3 From aabf59432c51be174994ecfe280f75ac139b5550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Wilczy=C5=84ski?= Date: Sun, 6 Sep 2020 22:39:49 +0000 Subject: fs: Remove duplicated flag O_NDELAY occurring twice in VALID_OPEN_FLAGS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The O_NDELAY flag occurs twice in the VALID_OPEN_FLAGS definition, this change removes the duplicate. There is no change to the functionality. Note, that the flags O_NONBLOCK and O_NDELAY are not duplicates, as values of these flags are platform dependent, and on platforms like Sparc O_NONBLOCK and O_NDELAY are not the same. This has been done that way to maintain the ABI compatibility with Solaris since the Sparc port was first introduced. This change resolves the following Coccinelle warning: include/linux/fcntl.h:11:13-21: duplicated argument to & or | Signed-off-by: Krzysztof WilczyƄski Signed-off-by: Al Viro --- include/linux/fcntl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h index 7bcdcf4f6ab2..921e750843e6 100644 --- a/include/linux/fcntl.h +++ b/include/linux/fcntl.h @@ -8,7 +8,7 @@ /* List of all valid flags for the open/openat flags argument: */ #define VALID_OPEN_FLAGS \ (O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | \ - O_APPEND | O_NDELAY | O_NONBLOCK | O_NDELAY | __O_SYNC | O_DSYNC | \ + O_APPEND | O_NDELAY | O_NONBLOCK | __O_SYNC | O_DSYNC | \ FASYNC | O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \ O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE) -- cgit v1.2.3 From 6d1349c769ea28543bdde20a658cbc93c3bc936d Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 18 Sep 2020 16:45:50 -0400 Subject: [PATCH] reduce boilerplate in fsid handling Get rid of boilerplate in most of ->statfs() instances... Signed-off-by: Al Viro --- include/linux/statfs.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/statfs.h b/include/linux/statfs.h index fac4356ea1bf..20f695b90aab 100644 --- a/include/linux/statfs.h +++ b/include/linux/statfs.h @@ -45,4 +45,9 @@ struct kstatfs { struct dentry; extern int vfs_get_fsid(struct dentry *dentry, __kernel_fsid_t *fsid); +static inline __kernel_fsid_t u64_to_fsid(u64 v) +{ + return (__kernel_fsid_t){.val = {(u32)v, (u32)(v>>32)}}; +} + #endif -- cgit v1.2.3 From da9aa5d96bfe49e903ce2bc01cfb8a776c2619e9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 26 Sep 2020 09:03:57 +0200 Subject: fs: remove vfs_statx_fd vfs_statx_fd is only used to implement vfs_fstat. Remove vfs_statx_fd and just implement vfs_fstat directly. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- include/linux/fs.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'include') diff --git a/include/linux/fs.h b/include/linux/fs.h index e019ea2f1347..f100d9f711a3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3163,7 +3163,7 @@ extern const struct inode_operations simple_symlink_inode_operations; extern int iterate_dir(struct file *, struct dir_context *); extern int vfs_statx(int, const char __user *, int, struct kstat *, u32); -extern int vfs_statx_fd(unsigned int, struct kstat *, u32, unsigned int); +int vfs_fstat(int fd, struct kstat *stat); static inline int vfs_stat(const char __user *filename, struct kstat *stat) { @@ -3181,11 +3181,6 @@ static inline int vfs_fstatat(int dfd, const char __user *filename, return vfs_statx(dfd, filename, flags | AT_NO_AUTOMOUNT, stat, STATX_BASIC_STATS); } -static inline int vfs_fstat(int fd, struct kstat *stat) -{ - return vfs_statx_fd(fd, stat, STATX_BASIC_STATS, 0); -} - extern const char *vfs_get_link(struct dentry *, struct delayed_call *); extern int vfs_readlink(struct dentry *, char __user *, int); -- cgit v1.2.3 From 0b2c6693b4220595e9cff95d829d5d5bc5d544dc Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 26 Sep 2020 09:03:58 +0200 Subject: fs: implement vfs_stat and vfs_lstat in terms of vfs_fstatat Go through vfs_fstatat instead of duplicating the *stat to statx mapping three times. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- include/linux/fs.h | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/linux/fs.h b/include/linux/fs.h index f100d9f711a3..b43c9ad7c3c2 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3165,21 +3165,19 @@ extern int iterate_dir(struct file *, struct dir_context *); extern int vfs_statx(int, const char __user *, int, struct kstat *, u32); int vfs_fstat(int fd, struct kstat *stat); -static inline int vfs_stat(const char __user *filename, struct kstat *stat) +static inline int vfs_fstatat(int dfd, const char __user *filename, + struct kstat *stat, int flags) { - return vfs_statx(AT_FDCWD, filename, AT_NO_AUTOMOUNT, + return vfs_statx(dfd, filename, flags | AT_NO_AUTOMOUNT, stat, STATX_BASIC_STATS); } -static inline int vfs_lstat(const char __user *name, struct kstat *stat) +static inline int vfs_stat(const char __user *filename, struct kstat *stat) { - return vfs_statx(AT_FDCWD, name, AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, - stat, STATX_BASIC_STATS); + return vfs_fstatat(AT_FDCWD, filename, stat, 0); } -static inline int vfs_fstatat(int dfd, const char __user *filename, - struct kstat *stat, int flags) +static inline int vfs_lstat(const char __user *name, struct kstat *stat) { - return vfs_statx(dfd, filename, flags | AT_NO_AUTOMOUNT, - stat, STATX_BASIC_STATS); + return vfs_fstatat(AT_FDCWD, name, stat, AT_SYMLINK_NOFOLLOW); } extern const char *vfs_get_link(struct dentry *, struct delayed_call *); -- cgit v1.2.3 From 09f1bde4017e9c34749da2918b3926799c77bce8 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 26 Sep 2020 09:03:59 +0200 Subject: fs: move vfs_fstatat out of line This allows to keep vfs_statx static in fs/stat.c to prepare for the following changes. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- include/linux/fs.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/include/linux/fs.h b/include/linux/fs.h index b43c9ad7c3c2..1ac68236bc09 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3162,15 +3162,10 @@ extern const struct inode_operations simple_symlink_inode_operations; extern int iterate_dir(struct file *, struct dir_context *); -extern int vfs_statx(int, const char __user *, int, struct kstat *, u32); +int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, + int flags); int vfs_fstat(int fd, struct kstat *stat); -static inline int vfs_fstatat(int dfd, const char __user *filename, - struct kstat *stat, int flags) -{ - return vfs_statx(dfd, filename, flags | AT_NO_AUTOMOUNT, - stat, STATX_BASIC_STATS); -} static inline int vfs_stat(const char __user *filename, struct kstat *stat) { return vfs_fstatat(AT_FDCWD, filename, stat, 0); -- cgit v1.2.3 From f2d077ff1b5c17008cff5dc27e7356a694e55462 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Sat, 26 Sep 2020 09:04:01 +0200 Subject: fs: remove KSTAT_QUERY_FLAGS KSTAT_QUERY_FLAGS expands to AT_STATX_SYNC_TYPE, which itself already is a mask. Remove the double name, especially given that the prefix is a little confusing vs the normal AT_* flags. Signed-off-by: Christoph Hellwig Signed-off-by: Al Viro --- include/linux/stat.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/linux/stat.h b/include/linux/stat.h index 56614af83d4a..fff27e603814 100644 --- a/include/linux/stat.h +++ b/include/linux/stat.h @@ -19,8 +19,6 @@ #include #include -#define KSTAT_QUERY_FLAGS (AT_STATX_SYNC_TYPE) - struct kstat { u32 result_mask; /* What fields the user got */ umode_t mode; -- cgit v1.2.3