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>
This commit is contained in:
parent
1fa7b6a29c
commit
9e1f1de02c
|
@ -819,7 +819,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
|
|||
} else {
|
||||
char b[BDEVNAME_SIZE];
|
||||
|
||||
s->s_flags = flags;
|
||||
s->s_flags = flags | MS_NOSEC;
|
||||
strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
|
||||
error = btrfs_fill_super(s, fs_devices, data,
|
||||
flags & MS_SILENT ? 1 : 0);
|
||||
|
|
|
@ -921,6 +921,8 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
|
|||
if (sb->s_flags & MS_MANDLOCK)
|
||||
goto err;
|
||||
|
||||
sb->s_flags &= ~MS_NOSEC;
|
||||
|
||||
if (!parse_fuse_opt((char *) data, &d, is_bdev))
|
||||
goto err;
|
||||
|
||||
|
|
|
@ -1072,7 +1072,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
|
|||
|
||||
sb->s_magic = OCFS2_SUPER_MAGIC;
|
||||
|
||||
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
|
||||
sb->s_flags = (sb->s_flags & ~(MS_POSIXACL | MS_NOSEC)) |
|
||||
((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
|
||||
|
||||
/* Hard readonly mode only if: bdev_read_only, MS_RDONLY,
|
||||
|
|
|
@ -822,7 +822,7 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
|
|||
} else {
|
||||
char b[BDEVNAME_SIZE];
|
||||
|
||||
s->s_flags = flags;
|
||||
s->s_flags = flags | MS_NOSEC;
|
||||
s->s_mode = mode;
|
||||
strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
|
||||
sb_set_blocksize(s, block_size(bdev));
|
||||
|
|
|
@ -208,6 +208,7 @@ struct inodes_stat_t {
|
|||
#define MS_KERNMOUNT (1<<22) /* this is a kern_mount call */
|
||||
#define MS_I_VERSION (1<<23) /* Update inode I_version field */
|
||||
#define MS_STRICTATIME (1<<24) /* Always perform atime updates */
|
||||
#define MS_NOSEC (1<<28)
|
||||
#define MS_BORN (1<<29)
|
||||
#define MS_ACTIVE (1<<30)
|
||||
#define MS_NOUSER (1<<31)
|
||||
|
@ -2591,7 +2592,7 @@ static inline int is_sxid(mode_t mode)
|
|||
|
||||
static inline void inode_has_no_xattr(struct inode *inode)
|
||||
{
|
||||
if (!is_sxid(inode->i_mode))
|
||||
if (!is_sxid(inode->i_mode) && (inode->i_sb->s_flags & MS_NOSEC))
|
||||
inode->i_flags |= S_NOSEC;
|
||||
}
|
||||
|
||||
|
|
|
@ -2000,7 +2000,7 @@ int file_remove_suid(struct file *file)
|
|||
error = security_inode_killpriv(dentry);
|
||||
if (!error && killsuid)
|
||||
error = __remove_suid(dentry, killsuid);
|
||||
if (!error)
|
||||
if (!error && (inode->i_sb->s_flags & MS_NOSEC))
|
||||
inode->i_flags |= S_NOSEC;
|
||||
|
||||
return error;
|
||||
|
|
Loading…
Reference in New Issue