提交 45f147a1 编写于 作者: J Jan Kara 提交者: Al Viro

fs: Call security_ops->inode_killpriv on truncate

Comment in include/linux/security.h says that ->inode_killpriv() should
be called when setuid bit is being removed and that similar security
labels (in fact this applies only to file capabilities) should be
removed at this time as well. However we don't call ->inode_killpriv()
when we remove suid bit on truncate.

We fix the problem by calling ->inode_need_killpriv() and subsequently
->inode_killpriv() on truncate the same way as we do it on file write.

After this patch there's only one user of should_remove_suid() - ocfs2 -
and indeed it's buggy because it doesn't call ->inode_killpriv() on
write. However fixing it is difficult because of special locking
constraints.
Signed-off-by: NJan Kara <jack@suse.cz>
Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
上级 dbfae0cd
...@@ -1678,9 +1678,8 @@ EXPORT_SYMBOL(should_remove_suid); ...@@ -1678,9 +1678,8 @@ EXPORT_SYMBOL(should_remove_suid);
* response to write or truncate. Return 0 if nothing has to be changed. * response to write or truncate. Return 0 if nothing has to be changed.
* Negative value on error (change should be denied). * Negative value on error (change should be denied).
*/ */
int file_needs_remove_privs(struct file *file) int dentry_needs_remove_privs(struct dentry *dentry)
{ {
struct dentry *dentry = file->f_path.dentry;
struct inode *inode = d_inode(dentry); struct inode *inode = d_inode(dentry);
int mask = 0; int mask = 0;
int ret; int ret;
...@@ -1696,7 +1695,7 @@ int file_needs_remove_privs(struct file *file) ...@@ -1696,7 +1695,7 @@ int file_needs_remove_privs(struct file *file)
mask |= ATTR_KILL_PRIV; mask |= ATTR_KILL_PRIV;
return mask; return mask;
} }
EXPORT_SYMBOL(file_needs_remove_privs); EXPORT_SYMBOL(dentry_needs_remove_privs);
static int __remove_privs(struct dentry *dentry, int kill) static int __remove_privs(struct dentry *dentry, int kill)
{ {
......
...@@ -51,8 +51,10 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, ...@@ -51,8 +51,10 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
newattrs.ia_valid |= ATTR_FILE; newattrs.ia_valid |= ATTR_FILE;
} }
/* Remove suid/sgid on truncate too */ /* Remove suid, sgid, and file capabilities on truncate too */
ret = should_remove_suid(dentry); ret = dentry_needs_remove_privs(dentry);
if (ret < 0)
return ret;
if (ret) if (ret)
newattrs.ia_valid |= ret | ATTR_FORCE; newattrs.ia_valid |= ret | ATTR_FORCE;
......
...@@ -2554,7 +2554,11 @@ extern struct inode *new_inode(struct super_block *sb); ...@@ -2554,7 +2554,11 @@ extern struct inode *new_inode(struct super_block *sb);
extern void free_inode_nonrcu(struct inode *inode); extern void free_inode_nonrcu(struct inode *inode);
extern int should_remove_suid(struct dentry *); extern int should_remove_suid(struct dentry *);
extern int file_remove_privs(struct file *); extern int file_remove_privs(struct file *);
extern int file_needs_remove_privs(struct file *file); extern int dentry_needs_remove_privs(struct dentry *dentry);
static inline int file_needs_remove_privs(struct file *file)
{
return dentry_needs_remove_privs(file->f_path.dentry);
}
extern void __insert_inode_hash(struct inode *, unsigned long hashval); extern void __insert_inode_hash(struct inode *, unsigned long hashval);
static inline void insert_inode_hash(struct inode *inode) static inline void insert_inode_hash(struct inode *inode)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册