diff options
Diffstat (limited to 'security')
-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, |