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

evm: Return -EAGAIN to ignore verification failures

hulk inclusion
category: feature
feature: digest-lists

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

By default, EVM maintains the same behavior as before hooks were moved
outside the LSM infrastructure. When EVM returns -EPERM, callers stop their
execution and return the error to user space.

This patch introduces a new mode, called ignore, that changes the return
value of the pre hooks from -EPERM to -EAGAIN. It also modifies the callers
of pre and post hooks to continue the execution if -EAGAIN is returned. The
error is then handled by the post hooks.

The only error that is not ignored is when user space is trying to modify
immutable metadata. Once that signature has been validated with the current
values of metadata, there is no valid reason to change them.

From user space perspective, operations on corrupted metadata are
successfully performed but post hooks didn't update the HMAC. At the next
IMA verification, when evm_verifyxattr() is called, corruption will be
detected and access will be denied.
Signed-off-by: NRoberto Sassu <roberto.sassu@huawei.com>
Acked-by: NHanjun Guo <guohanjun@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 dcf1b463
...@@ -327,7 +327,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de ...@@ -327,7 +327,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
if (error) if (error)
return error; return error;
evm_error = evm_inode_setattr(dentry, attr); evm_error = evm_inode_setattr(dentry, attr);
if (evm_error) if (evm_error && evm_error != -EAGAIN)
return evm_error; return evm_error;
error = try_break_deleg(inode, delegated_inode); error = try_break_deleg(inode, delegated_inode);
if (error) if (error)
......
...@@ -240,7 +240,7 @@ __vfs_setxattr_locked(struct dentry *dentry, const char *name, ...@@ -240,7 +240,7 @@ __vfs_setxattr_locked(struct dentry *dentry, const char *name,
goto out; goto out;
evm_error = evm_inode_setxattr(dentry, name, value, size); evm_error = evm_inode_setxattr(dentry, name, value, size);
if (evm_error) { if (evm_error && evm_error != -EAGAIN) {
error = evm_error; error = evm_error;
goto out; goto out;
} }
...@@ -454,7 +454,7 @@ __vfs_removexattr_locked(struct dentry *dentry, const char *name, ...@@ -454,7 +454,7 @@ __vfs_removexattr_locked(struct dentry *dentry, const char *name,
goto out; goto out;
evm_error = evm_inode_removexattr(dentry, name); evm_error = evm_inode_removexattr(dentry, name);
if (evm_error) { if (evm_error && evm_error != -EAGAIN) {
error = evm_error; error = evm_error;
goto out; goto out;
} }
......
...@@ -61,7 +61,7 @@ static struct xattr_list evm_config_default_xattrnames[] = { ...@@ -61,7 +61,7 @@ static struct xattr_list evm_config_default_xattrnames[] = {
LIST_HEAD(evm_config_xattrnames); LIST_HEAD(evm_config_xattrnames);
static int evm_fixmode; static int evm_fixmode, evm_ignoremode __ro_after_init;
static int __init evm_set_param(char *str) static int __init evm_set_param(char *str)
{ {
if (strncmp(str, "fix", 3) == 0) if (strncmp(str, "fix", 3) == 0)
...@@ -70,6 +70,8 @@ static int __init evm_set_param(char *str) ...@@ -70,6 +70,8 @@ static int __init evm_set_param(char *str)
evm_initialized |= EVM_INIT_X509; evm_initialized |= EVM_INIT_X509;
else if (strncmp(str, "allow_metadata_writes", 21) == 0) else if (strncmp(str, "allow_metadata_writes", 21) == 0)
evm_initialized |= EVM_ALLOW_METADATA_WRITES; evm_initialized |= EVM_ALLOW_METADATA_WRITES;
else if (strncmp(str, "ignore", 6) == 0)
evm_ignoremode = 1;
return 0; return 0;
} }
__setup("evm=", evm_set_param); __setup("evm=", evm_set_param);
...@@ -450,6 +452,7 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, ...@@ -450,6 +452,7 @@ static int evm_protect_xattr(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)
{ {
enum integrity_status evm_status; enum integrity_status evm_status;
int rc = -EPERM;
if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) { if (strcmp(xattr_name, XATTR_NAME_EVM) == 0) {
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
...@@ -494,12 +497,17 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name, ...@@ -494,12 +497,17 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
!evm_xattr_change(dentry, xattr_name, xattr_value, xattr_value_len)) !evm_xattr_change(dentry, xattr_name, xattr_value, xattr_value_len))
return 0; return 0;
if (evm_status != INTEGRITY_PASS) if (evm_status != INTEGRITY_PASS) {
if (evm_ignoremode && evm_status != INTEGRITY_PASS_IMMUTABLE)
rc = -EAGAIN;
integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry), integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
dentry->d_name.name, "appraise_metadata", dentry->d_name.name, "appraise_metadata",
integrity_status_msg[evm_status], integrity_status_msg[evm_status],
-EPERM, 0); rc, 0);
return evm_status == INTEGRITY_PASS ? 0 : -EPERM; }
return evm_status == INTEGRITY_PASS ? 0 : rc;
} }
/** /**
...@@ -659,6 +667,7 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -659,6 +667,7 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
{ {
unsigned int ia_valid = attr->ia_valid; unsigned int ia_valid = attr->ia_valid;
enum integrity_status evm_status; enum integrity_status evm_status;
int rc = -EPERM;
/* Policy permits modification of the protected attrs even though /* Policy permits modification of the protected attrs even though
* there's no HMAC key loaded * there's no HMAC key loaded
...@@ -681,10 +690,13 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr) ...@@ -681,10 +690,13 @@ int evm_inode_setattr(struct dentry *dentry, struct iattr *attr)
!evm_attr_change(dentry, attr)) !evm_attr_change(dentry, attr))
return 0; return 0;
if (evm_ignoremode && evm_status != INTEGRITY_PASS_IMMUTABLE)
rc = -EAGAIN;
integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry), integrity_audit_msg(AUDIT_INTEGRITY_METADATA, d_backing_inode(dentry),
dentry->d_name.name, "appraise_metadata", dentry->d_name.name, "appraise_metadata",
integrity_status_msg[evm_status], -EPERM, 0); integrity_status_msg[evm_status], rc, 0);
return -EPERM; return rc;
} }
/** /**
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册