提交 01de85e0 编写于 作者: J Jens Axboe 提交者: Jens Axboe

[PATCH] Add lockless helpers for remove_suid()

Right now users have to grab i_mutex before calling remove_suid(), in the
unlikely event that a call to ->setattr() may be needed. Split up the
function in two parts:

- One to check if we need to remove suid
- One to actually remove it

The first we can call lockless.
Signed-off-by: NJens Axboe <jens.axboe@oracle.com>
上级 6da61809
...@@ -1712,6 +1712,8 @@ extern void __iget(struct inode * inode); ...@@ -1712,6 +1712,8 @@ extern void __iget(struct inode * inode);
extern void clear_inode(struct inode *); extern void clear_inode(struct inode *);
extern void destroy_inode(struct inode *); extern void destroy_inode(struct inode *);
extern struct inode *new_inode(struct super_block *); extern struct inode *new_inode(struct super_block *);
extern int __remove_suid(struct dentry *, int);
extern int should_remove_suid(struct dentry *);
extern int remove_suid(struct dentry *); extern int remove_suid(struct dentry *);
extern void remove_dquot_ref(struct super_block *, int, struct list_head *); extern void remove_dquot_ref(struct super_block *, int, struct list_head *);
......
...@@ -1884,11 +1884,10 @@ __grab_cache_page(struct address_space *mapping, unsigned long index, ...@@ -1884,11 +1884,10 @@ __grab_cache_page(struct address_space *mapping, unsigned long index,
* if suid or (sgid and xgrp) * if suid or (sgid and xgrp)
* remove privs * remove privs
*/ */
int remove_suid(struct dentry *dentry) int should_remove_suid(struct dentry *dentry)
{ {
mode_t mode = dentry->d_inode->i_mode; mode_t mode = dentry->d_inode->i_mode;
int kill = 0; int kill = 0;
int result = 0;
/* suid always must be killed */ /* suid always must be killed */
if (unlikely(mode & S_ISUID)) if (unlikely(mode & S_ISUID))
...@@ -1901,13 +1900,28 @@ int remove_suid(struct dentry *dentry) ...@@ -1901,13 +1900,28 @@ int remove_suid(struct dentry *dentry)
if (unlikely((mode & S_ISGID) && (mode & S_IXGRP))) if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
kill |= ATTR_KILL_SGID; kill |= ATTR_KILL_SGID;
if (unlikely(kill && !capable(CAP_FSETID))) { if (unlikely(kill && !capable(CAP_FSETID)))
return kill;
return 0;
}
int __remove_suid(struct dentry *dentry, int kill)
{
struct iattr newattrs; struct iattr newattrs;
newattrs.ia_valid = ATTR_FORCE | kill; newattrs.ia_valid = ATTR_FORCE | kill;
result = notify_change(dentry, &newattrs); return notify_change(dentry, &newattrs);
} }
return result;
int remove_suid(struct dentry *dentry)
{
int kill = should_remove_suid(dentry);
if (unlikely(kill))
return __remove_suid(dentry, kill);
return 0;
} }
EXPORT_SYMBOL(remove_suid); EXPORT_SYMBOL(remove_suid);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册