vfs: export check_sticky()
It's already duplicated in btrfs and about to be used in overlayfs too. Move the sticky bit check to an inline helper and call the out-of-line helper only in the unlikly case of the sticky bit being set. Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
This commit is contained in:
parent
c771d683a6
commit
cbdf35bcb8
@ -765,23 +765,6 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* copy of check_sticky in fs/namei.c()
|
||||
* It's inline, so penalty for filesystems that don't use sticky bit is
|
||||
* minimal.
|
||||
*/
|
||||
static inline int btrfs_check_sticky(struct inode *dir, struct inode *inode)
|
||||
{
|
||||
kuid_t fsuid = current_fsuid();
|
||||
|
||||
if (!(dir->i_mode & S_ISVTX))
|
||||
return 0;
|
||||
if (uid_eq(inode->i_uid, fsuid))
|
||||
return 0;
|
||||
if (uid_eq(dir->i_uid, fsuid))
|
||||
return 0;
|
||||
return !capable(CAP_FOWNER);
|
||||
}
|
||||
|
||||
/* copy of may_delete in fs/namei.c()
|
||||
* Check whether we can remove a link victim from directory dir, check
|
||||
* whether the type of victim is right.
|
||||
@ -817,8 +800,7 @@ static int btrfs_may_delete(struct inode *dir, struct dentry *victim, int isdir)
|
||||
return error;
|
||||
if (IS_APPEND(dir))
|
||||
return -EPERM;
|
||||
if (btrfs_check_sticky(dir, victim->d_inode)||
|
||||
IS_APPEND(victim->d_inode)||
|
||||
if (check_sticky(dir, victim->d_inode) || IS_APPEND(victim->d_inode) ||
|
||||
IS_IMMUTABLE(victim->d_inode) || IS_SWAPFILE(victim->d_inode))
|
||||
return -EPERM;
|
||||
if (isdir) {
|
||||
|
@ -2384,22 +2384,17 @@ kern_path_mountpoint(int dfd, const char *name, struct path *path,
|
||||
}
|
||||
EXPORT_SYMBOL(kern_path_mountpoint);
|
||||
|
||||
/*
|
||||
* It's inline, so penalty for filesystems that don't use sticky bit is
|
||||
* minimal.
|
||||
*/
|
||||
static inline int check_sticky(struct inode *dir, struct inode *inode)
|
||||
int __check_sticky(struct inode *dir, struct inode *inode)
|
||||
{
|
||||
kuid_t fsuid = current_fsuid();
|
||||
|
||||
if (!(dir->i_mode & S_ISVTX))
|
||||
return 0;
|
||||
if (uid_eq(inode->i_uid, fsuid))
|
||||
return 0;
|
||||
if (uid_eq(dir->i_uid, fsuid))
|
||||
return 0;
|
||||
return !capable_wrt_inode_uidgid(inode, CAP_FOWNER);
|
||||
}
|
||||
EXPORT_SYMBOL(__check_sticky);
|
||||
|
||||
/*
|
||||
* Check whether we can remove a link victim from directory dir, check
|
||||
|
@ -2259,6 +2259,7 @@ extern int notify_change(struct dentry *, struct iattr *, struct inode **);
|
||||
extern int inode_permission(struct inode *, int);
|
||||
extern int __inode_permission(struct inode *, int);
|
||||
extern int generic_permission(struct inode *, int);
|
||||
extern int __check_sticky(struct inode *dir, struct inode *inode);
|
||||
|
||||
static inline bool execute_ok(struct inode *inode)
|
||||
{
|
||||
@ -2745,6 +2746,14 @@ static inline int is_sxid(umode_t mode)
|
||||
return (mode & S_ISUID) || ((mode & S_ISGID) && (mode & S_IXGRP));
|
||||
}
|
||||
|
||||
static inline int check_sticky(struct inode *dir, struct inode *inode)
|
||||
{
|
||||
if (!(dir->i_mode & S_ISVTX))
|
||||
return 0;
|
||||
|
||||
return __check_sticky(dir, inode);
|
||||
}
|
||||
|
||||
static inline void inode_has_no_xattr(struct inode *inode)
|
||||
{
|
||||
if (!is_sxid(inode->i_mode) && (inode->i_sb->s_flags & MS_NOSEC))
|
||||
|
Loading…
Reference in New Issue
Block a user