diff options
author | Dmitry Kasatkin <d.kasatkin@samsung.com> | 2014-11-20 16:31:01 +0200 |
---|---|---|
committer | Mimi Zohar <zohar@linux.vnet.ibm.com> | 2015-05-21 13:28:47 -0400 |
commit | 7c51bb00c40e5608fb2cdac5230f51aeb56a28df (patch) | |
tree | ea228d622a60f43812b50ce7e27b2abbb466f04b | |
parent | 5101a1850bb7ccbf107929dee9af0cd2f400940f (diff) |
evm: fix potential race when removing xattrs
EVM needs to be atomically updated when removing xattrs.
Otherwise concurrent EVM verification may fail in between.
This patch fixes by moving i_mutex unlocking after calling
EVM hook. fsnotify_xattr() is also now called while locked
the same way as it is done in __vfs_setxattr_noperm.
Changelog:
- remove unused 'inode' variable.
Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com>
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
-rw-r--r-- | fs/xattr.c | 10 | ||||
-rw-r--r-- | security/integrity/evm/evm_main.c | 7 |
2 files changed, 8 insertions, 9 deletions
diff --git a/fs/xattr.c b/fs/xattr.c index 4ef698549e31..072fee1258dd 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -298,18 +298,18 @@ vfs_removexattr(struct dentry *dentry, const char *name) mutex_lock(&inode->i_mutex); error = security_inode_removexattr(dentry, name); - if (error) { - mutex_unlock(&inode->i_mutex); - return error; - } + if (error) + goto out; error = inode->i_op->removexattr(dentry, name); - mutex_unlock(&inode->i_mutex); if (!error) { fsnotify_xattr(dentry); evm_inode_post_removexattr(dentry, name); } + +out: + mutex_unlock(&inode->i_mutex); return error; } EXPORT_SYMBOL_GPL(vfs_removexattr); diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 582091498819..1334e02ae8f4 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -387,17 +387,16 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, * @xattr_name: pointer to the affected extended attribute name * * Update the HMAC stored in 'security.evm' to reflect removal of the xattr. + * + * No need to take the i_mutex lock here, as this function is called from + * vfs_removexattr() which takes the i_mutex. */ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) { - struct inode *inode = d_backing_inode(dentry); - if (!evm_initialized || !evm_protected_xattr(xattr_name)) return; - mutex_lock(&inode->i_mutex); evm_update_evmxattr(dentry, xattr_name, NULL, 0); - mutex_unlock(&inode->i_mutex); } /** |