summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--security/integrity/ima/ima_appraise.c70
-rw-r--r--security/integrity/integrity.h1
2 files changed, 52 insertions, 19 deletions
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index f9979976aa5d..4cdf36ad884a 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -63,7 +63,7 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
{
struct dentry *dentry = file->f_dentry;
struct inode *inode = dentry->d_inode;
- struct evm_ima_xattr_data xattr_value;
+ struct evm_ima_xattr_data *xattr_value = NULL;
enum integrity_status status = INTEGRITY_UNKNOWN;
const char *op = "appraise_data";
char *cause = "unknown";
@@ -77,8 +77,8 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
if (iint->flags & IMA_APPRAISED)
return iint->ima_status;
- rc = inode->i_op->getxattr(dentry, XATTR_NAME_IMA, (u8 *)&xattr_value,
- sizeof xattr_value);
+ rc = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)&xattr_value,
+ 0, GFP_NOFS);
if (rc <= 0) {
if (rc && rc != -ENODATA)
goto out;
@@ -89,8 +89,7 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
goto out;
}
- status = evm_verifyxattr(dentry, XATTR_NAME_IMA, (u8 *)&xattr_value,
- rc, iint);
+ status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
if ((status == INTEGRITY_NOLABEL)
|| (status == INTEGRITY_NOXATTRS))
@@ -100,30 +99,58 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint,
goto out;
}
- rc = memcmp(xattr_value.digest, iint->ima_xattr.digest,
- IMA_DIGEST_SIZE);
- if (rc) {
- status = INTEGRITY_FAIL;
- cause = "invalid-hash";
- print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE,
- &xattr_value, sizeof xattr_value);
- print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE,
- (u8 *)&iint->ima_xattr,
- sizeof iint->ima_xattr);
- goto out;
+ switch (xattr_value->type) {
+ case IMA_XATTR_DIGEST:
+ rc = memcmp(xattr_value->digest, iint->ima_xattr.digest,
+ IMA_DIGEST_SIZE);
+ if (rc) {
+ cause = "invalid-hash";
+ status = INTEGRITY_FAIL;
+ print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE,
+ xattr_value, sizeof(*xattr_value));
+ print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE,
+ (u8 *)&iint->ima_xattr,
+ sizeof iint->ima_xattr);
+ break;
+ }
+ status = INTEGRITY_PASS;
+ break;
+ case EVM_IMA_XATTR_DIGSIG:
+ iint->flags |= IMA_DIGSIG;
+ rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
+ xattr_value->digest, rc - 1,
+ iint->ima_xattr.digest,
+ IMA_DIGEST_SIZE);
+ if (rc == -EOPNOTSUPP) {
+ status = INTEGRITY_UNKNOWN;
+ } else if (rc) {
+ cause = "invalid-signature";
+ status = INTEGRITY_FAIL;
+ } else {
+ status = INTEGRITY_PASS;
+ }
+ break;
+ default:
+ status = INTEGRITY_UNKNOWN;
+ cause = "unknown-ima-data";
+ break;
}
- status = INTEGRITY_PASS;
- iint->flags |= IMA_APPRAISED;
+
out:
if (status != INTEGRITY_PASS) {
- if (ima_appraise & IMA_APPRAISE_FIX) {
+ if ((ima_appraise & IMA_APPRAISE_FIX) &&
+ (!xattr_value ||
+ xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
ima_fix_xattr(dentry, iint);
status = INTEGRITY_PASS;
}
integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
op, cause, rc, 0);
+ } else {
+ iint->flags |= IMA_APPRAISED;
}
iint->ima_status = status;
+ kfree(xattr_value);
return status;
}
@@ -135,9 +162,14 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
struct dentry *dentry = file->f_dentry;
int rc = 0;
+ /* do not collect and update hash for digital signatures */
+ if (iint->flags & IMA_DIGSIG)
+ return;
+
rc = ima_collect_measurement(iint, file);
if (rc < 0)
return;
+
ima_fix_xattr(dentry, iint);
}
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 91ccef1c704b..4eec1b14193e 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -21,6 +21,7 @@
#define IMA_APPRAISE 0x04
#define IMA_APPRAISED 0x08
#define IMA_COLLECTED 0x10
+#define IMA_DIGSIG 0x20
enum evm_ima_xattr_type {
IMA_XATTR_DIGEST = 0x01,