@@ -226,7 +226,7 @@ static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint,
}
clear_bit(IMA_DIGSIG, &iint->atomic_flags);
if (xattr_len - sizeof(xattr_value->type) - hash_start >=
- iint->ima_hash->length)
+ iint->ima_hash->length) {
/*
* xattr length may be longer. md5 hash in previous
* version occupied 20 bytes in xattr, instead of 16
@@ -234,6 +234,9 @@ static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint,
rc = memcmp(&xattr_value->data[hash_start],
iint->ima_hash->digest,
iint->ima_hash->length);
+ if (rc)
+ rc = -EINVAL;
+ }
else
rc = -EINVAL;
if (rc) {
@@ -355,7 +358,7 @@ int ima_appraise_measurement(enum ima_hooks func,
struct dentry *dentry = file_dentry(file);
struct inode *inode = d_backing_inode(dentry);
enum integrity_status status = INTEGRITY_UNKNOWN;
- int rc = xattr_len;
+ int rc = -EACCES;
bool try_modsig = iint->flags & IMA_MODSIG_ALLOWED && modsig;
/* If not appraising a modsig, we need an xattr. */
@@ -363,10 +366,7 @@ int ima_appraise_measurement(enum ima_hooks func,
return INTEGRITY_UNKNOWN;
/* If reading the xattr failed and there's no modsig, error out. */
- if (rc <= 0 && !try_modsig) {
- if (rc && rc != -ENODATA)
- goto out;
-
+ if (xattr_len <= 0 && !try_modsig) {
cause = iint->flags & IMA_DIGSIG_REQUIRED ?
"IMA-signature-required" : "missing-hash";
status = INTEGRITY_NOLABEL;
@@ -379,7 +379,8 @@ int ima_appraise_measurement(enum ima_hooks func,
goto out;
}
- status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
+ status = evm_verifyxattr(dentry, XATTR_NAME_IMA,
+ xattr_value, xattr_len, iint);
switch (status) {
case INTEGRITY_PASS:
case INTEGRITY_PASS_IMMUTABLE:
@@ -432,14 +433,17 @@ int ima_appraise_measurement(enum ima_hooks func,
if ((ima_appraise & IMA_APPRAISE_FIX) && !try_modsig &&
(!xattr_value ||
xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
- if (!ima_fix_xattr(dentry, iint))
+ if (!ima_fix_xattr(dentry, iint)) {
status = INTEGRITY_PASS;
+ rc = 0;
+ }
}
/* Permit new files with file signatures, but without data. */
if (inode->i_size == 0 && iint->flags & IMA_NEW_FILE &&
xattr_value && xattr_value->type == EVM_IMA_XATTR_DIGSIG) {
status = INTEGRITY_PASS;
+ rc = 0;
}
integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
@@ -335,10 +335,10 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf,
result = ima_read_policy(data);
} else if (ima_appraise & IMA_APPRAISE_POLICY) {
pr_err("signed policy file (specified as an absolute pathname) required\n");
+ result = -EACCES;
integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
"policy_update", "signed policy required",
- 1, 0);
- result = -EACCES;
+ result, 0);
} else {
result = ima_parse_add_rule(data);
}
@@ -406,6 +406,7 @@ static int ima_open_policy(struct inode *inode, struct file *filp)
static int ima_release_policy(struct inode *inode, struct file *file)
{
const char *cause = valid_policy ? "completed" : "failed";
+ int result = 0;
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
return seq_release(inode, file);
@@ -413,11 +414,12 @@ static int ima_release_policy(struct inode *inode, struct file *file)
if (valid_policy && ima_check_policy() < 0) {
cause = "failed";
valid_policy = 0;
+ result = -EINVAL;
}
pr_info("policy update %s\n", cause);
integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL,
- "policy_update", cause, !valid_policy, 0);
+ "policy_update", cause, result, 0);
if (!valid_policy) {
ima_delete_rules();
The value passed in "result" parameter to integrity_audit_msg() is not an error code in some instances. Update these instances so that "result" parameter always contains an error code. Signed-off-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com> --- security/integrity/ima/ima_appraise.c | 20 ++++++++++++-------- security/integrity/ima/ima_fs.c | 8 +++++--- 2 files changed, 17 insertions(+), 11 deletions(-)