提交 dcf1b463 编写于 作者: R Roberto Sassu 提交者: Yang Yingliang

evm: Extend API of post hooks to pass the result of pre hooks

hulk inclusion
category: feature
feature: digest-lists

---------------------------

This patch extends the API of post hooks to pass the result returned by the
pre hooks. Given that now this information is available, post hooks can
stop before updating the HMAC if the result of the pre hook is not zero.

They still reset the result of the last verification, stored in the
integrity_iint_cache, to ensure that file metadata are re-evaluated after
update.
Signed-off-by: NRoberto Sassu <roberto.sassu@huawei.com>
Acked-by: NHanjun Guo <guohanjun@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 ab884109
...@@ -341,7 +341,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de ...@@ -341,7 +341,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
if (!error) { if (!error) {
fsnotify_change(dentry, ia_valid); fsnotify_change(dentry, ia_valid);
ima_inode_post_setattr(dentry); ima_inode_post_setattr(dentry);
evm_inode_post_setattr(dentry, ia_valid); evm_inode_post_setattr(dentry, ia_valid, evm_error);
} }
return error; return error;
......
...@@ -150,24 +150,8 @@ __vfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name, ...@@ -150,24 +150,8 @@ __vfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
} }
EXPORT_SYMBOL(__vfs_setxattr); EXPORT_SYMBOL(__vfs_setxattr);
/** static int __vfs_setxattr_noperm_evm(struct dentry *dentry, const char *name,
* __vfs_setxattr_noperm - perform setxattr operation without performing const void *value, size_t size, int flags, int evm_error)
* permission checks.
*
* @dentry - object to perform setxattr on
* @name - xattr name to set
* @value - value to set @name to
* @size - size of @value
* @flags - flags to pass into filesystem operations
*
* returns the result of the internal setxattr or setsecurity operations.
*
* This function requires the caller to lock the inode's i_mutex before it
* is executed. It also assumes that the caller will make the appropriate
* permission checks.
*/
int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{ {
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
int error = -EAGAIN; int error = -EAGAIN;
...@@ -182,7 +166,8 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name, ...@@ -182,7 +166,8 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
fsnotify_xattr(dentry); fsnotify_xattr(dentry);
security_inode_post_setxattr(dentry, name, value, security_inode_post_setxattr(dentry, name, value,
size, flags); size, flags);
evm_inode_post_setxattr(dentry, name, value, size); evm_inode_post_setxattr(dentry, name, value, size,
evm_error);
} }
} else { } else {
if (unlikely(is_bad_inode(inode))) if (unlikely(is_bad_inode(inode)))
...@@ -204,6 +189,28 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name, ...@@ -204,6 +189,28 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
return error; return error;
} }
/**
* __vfs_setxattr_noperm - perform setxattr operation without performing
* permission checks.
*
* @dentry - object to perform setxattr on
* @name - xattr name to set
* @value - value to set @name to
* @size - size of @value
* @flags - flags to pass into filesystem operations
*
* returns the result of the internal setxattr or setsecurity operations.
*
* This function requires the caller to lock the inode's i_mutex before it
* is executed. It also assumes that the caller will make the appropriate
* permission checks.
*/
int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
return __vfs_setxattr_noperm_evm(dentry, name, value, size, flags, 0);
}
/** /**
* __vfs_setxattr_locked: set an extended attribute while holding the inode * __vfs_setxattr_locked: set an extended attribute while holding the inode
* lock * lock
...@@ -242,7 +249,8 @@ __vfs_setxattr_locked(struct dentry *dentry, const char *name, ...@@ -242,7 +249,8 @@ __vfs_setxattr_locked(struct dentry *dentry, const char *name,
if (error) if (error)
goto out; goto out;
error = __vfs_setxattr_noperm(dentry, name, value, size, flags); error = __vfs_setxattr_noperm_evm(dentry, name, value, size, flags,
evm_error);
out: out:
return error; return error;
...@@ -459,7 +467,7 @@ __vfs_removexattr_locked(struct dentry *dentry, const char *name, ...@@ -459,7 +467,7 @@ __vfs_removexattr_locked(struct dentry *dentry, const char *name,
if (!error) { if (!error) {
fsnotify_xattr(dentry); fsnotify_xattr(dentry);
evm_inode_post_removexattr(dentry, name); evm_inode_post_removexattr(dentry, name, evm_error);
} }
out: out:
......
...@@ -22,16 +22,19 @@ extern enum integrity_status evm_verifyxattr(struct dentry *dentry, ...@@ -22,16 +22,19 @@ extern enum integrity_status evm_verifyxattr(struct dentry *dentry,
size_t xattr_value_len, size_t xattr_value_len,
struct integrity_iint_cache *iint); struct integrity_iint_cache *iint);
extern int evm_inode_setattr(struct dentry *dentry, struct iattr *attr); extern int evm_inode_setattr(struct dentry *dentry, struct iattr *attr);
extern void evm_inode_post_setattr(struct dentry *dentry, int ia_valid); extern void evm_inode_post_setattr(struct dentry *dentry, int ia_valid,
int evm_pre_error);
extern int evm_inode_setxattr(struct dentry *dentry, const char *name, extern int evm_inode_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size); const void *value, size_t size);
extern void evm_inode_post_setxattr(struct dentry *dentry, extern void evm_inode_post_setxattr(struct dentry *dentry,
const char *xattr_name, const char *xattr_name,
const void *xattr_value, const void *xattr_value,
size_t xattr_value_len); size_t xattr_value_len,
int evm_pre_error);
extern int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name); extern int evm_inode_removexattr(struct dentry *dentry, const char *xattr_name);
extern void evm_inode_post_removexattr(struct dentry *dentry, extern void evm_inode_post_removexattr(struct dentry *dentry,
const char *xattr_name); const char *xattr_name,
int evm_pre_error);
extern int evm_inode_init_security(struct inode *inode, extern int evm_inode_init_security(struct inode *inode,
const struct xattr *xattr_array, const struct xattr *xattr_array,
struct xattr *evm); struct xattr *evm);
...@@ -66,7 +69,8 @@ static inline int evm_inode_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -66,7 +69,8 @@ static inline int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
return 0; return 0;
} }
static inline void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) static inline void evm_inode_post_setattr(struct dentry *dentry, int ia_valid,
int evm_pre_error)
{ {
return; return;
} }
...@@ -80,7 +84,8 @@ static inline int evm_inode_setxattr(struct dentry *dentry, const char *name, ...@@ -80,7 +84,8 @@ static inline int evm_inode_setxattr(struct dentry *dentry, const char *name,
static inline void evm_inode_post_setxattr(struct dentry *dentry, static inline void evm_inode_post_setxattr(struct dentry *dentry,
const char *xattr_name, const char *xattr_name,
const void *xattr_value, const void *xattr_value,
size_t xattr_value_len) size_t xattr_value_len,
int evm_pre_error)
{ {
return; return;
} }
...@@ -92,7 +97,8 @@ static inline int evm_inode_removexattr(struct dentry *dentry, ...@@ -92,7 +97,8 @@ static inline int evm_inode_removexattr(struct dentry *dentry,
} }
static inline void evm_inode_post_removexattr(struct dentry *dentry, static inline void evm_inode_post_removexattr(struct dentry *dentry,
const char *xattr_name) const char *xattr_name,
int evm_pre_error)
{ {
return; return;
} }
......
...@@ -576,6 +576,7 @@ static void evm_reset_status(struct inode *inode, int bit) ...@@ -576,6 +576,7 @@ static void evm_reset_status(struct inode *inode, int bit)
* @xattr_name: pointer to the affected extended attribute name * @xattr_name: pointer to the affected extended attribute name
* @xattr_value: pointer to the new extended attribute value * @xattr_value: pointer to the new extended attribute value
* @xattr_value_len: pointer to the new extended attribute value length * @xattr_value_len: pointer to the new extended attribute value length
* @evm_pre_error: error returned by evm_inode_setxattr()
* *
* Update the HMAC stored in 'security.evm' to reflect the change. * Update the HMAC stored in 'security.evm' to reflect the change.
* *
...@@ -584,7 +585,8 @@ static void evm_reset_status(struct inode *inode, int bit) ...@@ -584,7 +585,8 @@ static void evm_reset_status(struct inode *inode, int bit)
* i_mutex lock. * i_mutex lock.
*/ */
void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
const void *xattr_value, size_t xattr_value_len) const void *xattr_value, size_t xattr_value_len,
int evm_pre_error)
{ {
int is_evm = !strcmp(xattr_name, XATTR_NAME_EVM); int is_evm = !strcmp(xattr_name, XATTR_NAME_EVM);
...@@ -597,6 +599,9 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, ...@@ -597,6 +599,9 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
if (is_evm) if (is_evm)
return; return;
if (evm_pre_error)
return;
evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len); evm_update_evmxattr(dentry, xattr_name, xattr_value, xattr_value_len);
} }
...@@ -604,13 +609,15 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name, ...@@ -604,13 +609,15 @@ void evm_inode_post_setxattr(struct dentry *dentry, const char *xattr_name,
* evm_inode_post_removexattr - update 'security.evm' after removing the xattr * evm_inode_post_removexattr - update 'security.evm' after removing the xattr
* @dentry: pointer to the affected dentry * @dentry: pointer to the affected dentry
* @xattr_name: pointer to the affected extended attribute name * @xattr_name: pointer to the affected extended attribute name
* @evm_pre_error: error returned by evm_inode_removexattr()
* *
* Update the HMAC stored in 'security.evm' to reflect removal of the xattr. * 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 * No need to take the i_mutex lock here, as this function is called from
* vfs_removexattr() which takes the i_mutex. * vfs_removexattr() which takes the i_mutex.
*/ */
void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name,
int evm_pre_error)
{ {
int is_evm = !strcmp(xattr_name, XATTR_NAME_EVM); int is_evm = !strcmp(xattr_name, XATTR_NAME_EVM);
...@@ -622,6 +629,9 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name) ...@@ -622,6 +629,9 @@ void evm_inode_post_removexattr(struct dentry *dentry, const char *xattr_name)
if (is_evm) if (is_evm)
return; return;
if (evm_pre_error)
return;
evm_update_evmxattr(dentry, xattr_name, NULL, 0); evm_update_evmxattr(dentry, xattr_name, NULL, 0);
} }
...@@ -681,6 +691,7 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -681,6 +691,7 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
* evm_inode_post_setattr - update 'security.evm' after modifying metadata * evm_inode_post_setattr - update 'security.evm' after modifying metadata
* @dentry: pointer to the affected dentry * @dentry: pointer to the affected dentry
* @ia_valid: for the UID and GID status * @ia_valid: for the UID and GID status
* @evm_pre_error: error returned by evm_inode_setattr()
* *
* For now, update the HMAC stored in 'security.evm' to reflect UID/GID * For now, update the HMAC stored in 'security.evm' to reflect UID/GID
* changes. * changes.
...@@ -688,13 +699,17 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -688,13 +699,17 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
* This function is called from notify_change(), which expects the caller * This function is called from notify_change(), which expects the caller
* to lock the inode's i_mutex. * to lock the inode's i_mutex.
*/ */
void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) void evm_inode_post_setattr(struct dentry *dentry, int ia_valid,
int evm_pre_error)
{ {
if (!evm_key_loaded()) if (!evm_key_loaded())
return; return;
evm_reset_status(dentry->d_inode, IMA_CHANGE_ATTR); evm_reset_status(dentry->d_inode, IMA_CHANGE_ATTR);
if (evm_pre_error)
return;
if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID))
evm_update_evmxattr(dentry, NULL, NULL, 0); evm_update_evmxattr(dentry, NULL, NULL, 0);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册