Commit 9e1f1de02c2275d7172e18dc4e7c2065777611bf
1 parent
1fa7b6a29c
Exists in
master
and in
4 other branches
more conservative S_NOSEC handling
Caching "we have already removed suid/caps" was overenthusiastic as merged. On network filesystems we might have had suid/caps set on another client, silently picked by this client on revalidate, all of that *without* clearing the S_NOSEC flag. AFAICS, the only reasonably sane way to deal with that is * new superblock flag; unless set, S_NOSEC is not going to be set. * local block filesystems set it in their ->mount() (more accurately, mount_bdev() does, so does btrfs ->mount(), users of mount_bdev() other than local block ones clear it) * if any network filesystem (or a cluster one) wants to use S_NOSEC, it'll need to set MS_NOSEC in sb->s_flags *AND* take care to clear S_NOSEC when inode attribute changes are picked from other clients. It's not an earth-shattering hole (anybody that can set suid on another client will almost certainly be able to write to the file before doing that anyway), but it's a bug that needs fixing. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 6 changed files with 8 additions and 5 deletions Side-by-side Diff
fs/btrfs/super.c
fs/fuse/inode.c
fs/ocfs2/super.c
... | ... | @@ -1072,7 +1072,7 @@ |
1072 | 1072 | |
1073 | 1073 | sb->s_magic = OCFS2_SUPER_MAGIC; |
1074 | 1074 | |
1075 | - sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | | |
1075 | + sb->s_flags = (sb->s_flags & ~(MS_POSIXACL | MS_NOSEC)) | | |
1076 | 1076 | ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0); |
1077 | 1077 | |
1078 | 1078 | /* Hard readonly mode only if: bdev_read_only, MS_RDONLY, |
fs/super.c
include/linux/fs.h
... | ... | @@ -208,6 +208,7 @@ |
208 | 208 | #define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */ |
209 | 209 | #define MS_I_VERSION (1<<23) /* Update inode I_version field */ |
210 | 210 | #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ |
211 | +#define MS_NOSEC (1<<28) | |
211 | 212 | #define MS_BORN (1<<29) |
212 | 213 | #define MS_ACTIVE (1<<30) |
213 | 214 | #define MS_NOUSER (1<<31) |
... | ... | @@ -2591,7 +2592,7 @@ |
2591 | 2592 | |
2592 | 2593 | static inline void inode_has_no_xattr(struct inode *inode) |
2593 | 2594 | { |
2594 | - if (!is_sxid(inode->i_mode)) | |
2595 | + if (!is_sxid(inode->i_mode) && (inode->i_sb->s_flags & MS_NOSEC)) | |
2595 | 2596 | inode->i_flags |= S_NOSEC; |
2596 | 2597 | } |
2597 | 2598 |
mm/filemap.c
... | ... | @@ -2000,7 +2000,7 @@ |
2000 | 2000 | error = security_inode_killpriv(dentry); |
2001 | 2001 | if (!error && killsuid) |
2002 | 2002 | error = __remove_suid(dentry, killsuid); |
2003 | - if (!error) | |
2003 | + if (!error && (inode->i_sb->s_flags & MS_NOSEC)) | |
2004 | 2004 | inode->i_flags |= S_NOSEC; |
2005 | 2005 | |
2006 | 2006 | return error; |