diff options
| -rw-r--r-- | security/integrity/ima/ima_appraise.c | 70 | ||||
| -rw-r--r-- | security/integrity/integrity.h | 1 |
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, | |||
| 63 | { | 63 | { |
| 64 | struct dentry *dentry = file->f_dentry; | 64 | struct dentry *dentry = file->f_dentry; |
| 65 | struct inode *inode = dentry->d_inode; | 65 | struct inode *inode = dentry->d_inode; |
| 66 | struct evm_ima_xattr_data xattr_value; | 66 | struct evm_ima_xattr_data *xattr_value = NULL; |
| 67 | enum integrity_status status = INTEGRITY_UNKNOWN; | 67 | enum integrity_status status = INTEGRITY_UNKNOWN; |
| 68 | const char *op = "appraise_data"; | 68 | const char *op = "appraise_data"; |
| 69 | char *cause = "unknown"; | 69 | char *cause = "unknown"; |
| @@ -77,8 +77,8 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint, | |||
| 77 | if (iint->flags & IMA_APPRAISED) | 77 | if (iint->flags & IMA_APPRAISED) |
| 78 | return iint->ima_status; | 78 | return iint->ima_status; |
| 79 | 79 | ||
| 80 | rc = inode->i_op->getxattr(dentry, XATTR_NAME_IMA, (u8 *)&xattr_value, | 80 | rc = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)&xattr_value, |
| 81 | sizeof xattr_value); | 81 | 0, GFP_NOFS); |
| 82 | if (rc <= 0) { | 82 | if (rc <= 0) { |
| 83 | if (rc && rc != -ENODATA) | 83 | if (rc && rc != -ENODATA) |
| 84 | goto out; | 84 | goto out; |
| @@ -89,8 +89,7 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint, | |||
| 89 | goto out; | 89 | goto out; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | status = evm_verifyxattr(dentry, XATTR_NAME_IMA, (u8 *)&xattr_value, | 92 | status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint); |
| 93 | rc, iint); | ||
| 94 | if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) { | 93 | if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) { |
| 95 | if ((status == INTEGRITY_NOLABEL) | 94 | if ((status == INTEGRITY_NOLABEL) |
| 96 | || (status == INTEGRITY_NOXATTRS)) | 95 | || (status == INTEGRITY_NOXATTRS)) |
| @@ -100,30 +99,58 @@ int ima_appraise_measurement(struct integrity_iint_cache *iint, | |||
| 100 | goto out; | 99 | goto out; |
| 101 | } | 100 | } |
| 102 | 101 | ||
| 103 | rc = memcmp(xattr_value.digest, iint->ima_xattr.digest, | 102 | switch (xattr_value->type) { |
| 104 | IMA_DIGEST_SIZE); | 103 | case IMA_XATTR_DIGEST: |
| 105 | if (rc) { | 104 | rc = memcmp(xattr_value->digest, iint->ima_xattr.digest, |
| 106 | status = INTEGRITY_FAIL; | 105 | IMA_DIGEST_SIZE); |
| 107 | cause = "invalid-hash"; | 106 | if (rc) { |
| 108 | print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE, | 107 | cause = "invalid-hash"; |
| 109 | &xattr_value, sizeof xattr_value); | 108 | status = INTEGRITY_FAIL; |
| 110 | print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE, | 109 | print_hex_dump_bytes("security.ima: ", DUMP_PREFIX_NONE, |
| 111 | (u8 *)&iint->ima_xattr, | 110 | xattr_value, sizeof(*xattr_value)); |
| 112 | sizeof iint->ima_xattr); | 111 | print_hex_dump_bytes("collected: ", DUMP_PREFIX_NONE, |
| 113 | goto out; | 112 | (u8 *)&iint->ima_xattr, |
| 113 | sizeof iint->ima_xattr); | ||
| 114 | break; | ||
| 115 | } | ||
| 116 | status = INTEGRITY_PASS; | ||
| 117 | break; | ||
| 118 | case EVM_IMA_XATTR_DIGSIG: | ||
| 119 | iint->flags |= IMA_DIGSIG; | ||
| 120 | rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, | ||
| 121 | xattr_value->digest, rc - 1, | ||
| 122 | iint->ima_xattr.digest, | ||
| 123 | IMA_DIGEST_SIZE); | ||
| 124 | if (rc == -EOPNOTSUPP) { | ||
| 125 | status = INTEGRITY_UNKNOWN; | ||
| 126 | } else if (rc) { | ||
| 127 | cause = "invalid-signature"; | ||
| 128 | status = INTEGRITY_FAIL; | ||
| 129 | } else { | ||
| 130 | status = INTEGRITY_PASS; | ||
| 131 | } | ||
| 132 | break; | ||
| 133 | default: | ||
| 134 | status = INTEGRITY_UNKNOWN; | ||
| 135 | cause = "unknown-ima-data"; | ||
| 136 | break; | ||
| 114 | } | 137 | } |
| 115 | status = INTEGRITY_PASS; | 138 | |
| 116 | iint->flags |= IMA_APPRAISED; | ||
| 117 | out: | 139 | out: |
| 118 | if (status != INTEGRITY_PASS) { | 140 | if (status != INTEGRITY_PASS) { |
| 119 | if (ima_appraise & IMA_APPRAISE_FIX) { | 141 | if ((ima_appraise & IMA_APPRAISE_FIX) && |
| 142 | (!xattr_value || | ||
| 143 | xattr_value->type != EVM_IMA_XATTR_DIGSIG)) { | ||
| 120 | ima_fix_xattr(dentry, iint); | 144 | ima_fix_xattr(dentry, iint); |
| 121 | status = INTEGRITY_PASS; | 145 | status = INTEGRITY_PASS; |
| 122 | } | 146 | } |
| 123 | integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename, | 147 | integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename, |
| 124 | op, cause, rc, 0); | 148 | op, cause, rc, 0); |
| 149 | } else { | ||
| 150 | iint->flags |= IMA_APPRAISED; | ||
| 125 | } | 151 | } |
| 126 | iint->ima_status = status; | 152 | iint->ima_status = status; |
| 153 | kfree(xattr_value); | ||
| 127 | return status; | 154 | return status; |
| 128 | } | 155 | } |
| 129 | 156 | ||
| @@ -135,9 +162,14 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) | |||
| 135 | struct dentry *dentry = file->f_dentry; | 162 | struct dentry *dentry = file->f_dentry; |
| 136 | int rc = 0; | 163 | int rc = 0; |
| 137 | 164 | ||
| 165 | /* do not collect and update hash for digital signatures */ | ||
| 166 | if (iint->flags & IMA_DIGSIG) | ||
| 167 | return; | ||
| 168 | |||
| 138 | rc = ima_collect_measurement(iint, file); | 169 | rc = ima_collect_measurement(iint, file); |
| 139 | if (rc < 0) | 170 | if (rc < 0) |
| 140 | return; | 171 | return; |
| 172 | |||
| 141 | ima_fix_xattr(dentry, iint); | 173 | ima_fix_xattr(dentry, iint); |
| 142 | } | 174 | } |
| 143 | 175 | ||
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 @@ | |||
| 21 | #define IMA_APPRAISE 0x04 | 21 | #define IMA_APPRAISE 0x04 |
| 22 | #define IMA_APPRAISED 0x08 | 22 | #define IMA_APPRAISED 0x08 |
| 23 | #define IMA_COLLECTED 0x10 | 23 | #define IMA_COLLECTED 0x10 |
| 24 | #define IMA_DIGSIG 0x20 | ||
| 24 | 25 | ||
| 25 | enum evm_ima_xattr_type { | 26 | enum evm_ima_xattr_type { |
| 26 | IMA_XATTR_DIGEST = 0x01, | 27 | IMA_XATTR_DIGEST = 0x01, |
