aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/ima/ima_appraise.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/integrity/ima/ima_appraise.c')
-rw-r--r--security/integrity/ima/ima_appraise.c61
1 files changed, 47 insertions, 14 deletions
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 116630ca5ff3..734e9468aca0 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -15,6 +15,7 @@
15#include <linux/magic.h> 15#include <linux/magic.h>
16#include <linux/ima.h> 16#include <linux/ima.h>
17#include <linux/evm.h> 17#include <linux/evm.h>
18#include <crypto/hash_info.h>
18 19
19#include "ima.h" 20#include "ima.h"
20 21
@@ -45,10 +46,22 @@ int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func)
45static int ima_fix_xattr(struct dentry *dentry, 46static int ima_fix_xattr(struct dentry *dentry,
46 struct integrity_iint_cache *iint) 47 struct integrity_iint_cache *iint)
47{ 48{
48 iint->ima_hash->type = IMA_XATTR_DIGEST; 49 int rc, offset;
49 return __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA, 50 u8 algo = iint->ima_hash->algo;
50 &iint->ima_hash->type, 51
51 1 + iint->ima_hash->length, 0); 52 if (algo <= HASH_ALGO_SHA1) {
53 offset = 1;
54 iint->ima_hash->xattr.sha1.type = IMA_XATTR_DIGEST;
55 } else {
56 offset = 0;
57 iint->ima_hash->xattr.ng.type = IMA_XATTR_DIGEST_NG;
58 iint->ima_hash->xattr.ng.algo = algo;
59 }
60 rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA,
61 &iint->ima_hash->xattr.data[offset],
62 (sizeof(iint->ima_hash->xattr) - offset) +
63 iint->ima_hash->length, 0);
64 return rc;
52} 65}
53 66
54/* Return specific func appraised cached result */ 67/* Return specific func appraised cached result */
@@ -112,15 +125,31 @@ void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
112{ 125{
113 struct signature_v2_hdr *sig; 126 struct signature_v2_hdr *sig;
114 127
115 if (!xattr_value || xattr_len < 0 || xattr_len <= 1 + sizeof(*sig)) 128 if (!xattr_value || xattr_len < 2)
116 return; 129 return;
117 130
118 sig = (typeof(sig)) xattr_value->digest; 131 switch (xattr_value->type) {
119 132 case EVM_IMA_XATTR_DIGSIG:
120 if (xattr_value->type != EVM_IMA_XATTR_DIGSIG || sig->version != 2) 133 sig = (typeof(sig))xattr_value;
121 return; 134 if (sig->version != 2 || xattr_len <= sizeof(*sig))
122 135 return;
123 hash->algo = sig->hash_algo; 136 hash->algo = sig->hash_algo;
137 break;
138 case IMA_XATTR_DIGEST_NG:
139 hash->algo = xattr_value->digest[0];
140 break;
141 case IMA_XATTR_DIGEST:
142 /* this is for backward compatibility */
143 if (xattr_len == 21) {
144 unsigned int zero = 0;
145 if (!memcmp(&xattr_value->digest[16], &zero, 4))
146 hash->algo = HASH_ALGO_MD5;
147 else
148 hash->algo = HASH_ALGO_SHA1;
149 } else if (xattr_len == 17)
150 hash->algo = HASH_ALGO_MD5;
151 break;
152 }
124} 153}
125 154
126int ima_read_xattr(struct dentry *dentry, 155int ima_read_xattr(struct dentry *dentry,
@@ -153,7 +182,7 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
153 enum integrity_status status = INTEGRITY_UNKNOWN; 182 enum integrity_status status = INTEGRITY_UNKNOWN;
154 const char *op = "appraise_data"; 183 const char *op = "appraise_data";
155 char *cause = "unknown"; 184 char *cause = "unknown";
156 int rc = xattr_len; 185 int rc = xattr_len, hash_start = 0;
157 186
158 if (!ima_appraise) 187 if (!ima_appraise)
159 return 0; 188 return 0;
@@ -180,17 +209,21 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
180 goto out; 209 goto out;
181 } 210 }
182 switch (xattr_value->type) { 211 switch (xattr_value->type) {
212 case IMA_XATTR_DIGEST_NG:
213 /* first byte contains algorithm id */
214 hash_start = 1;
183 case IMA_XATTR_DIGEST: 215 case IMA_XATTR_DIGEST:
184 if (iint->flags & IMA_DIGSIG_REQUIRED) { 216 if (iint->flags & IMA_DIGSIG_REQUIRED) {
185 cause = "IMA signature required"; 217 cause = "IMA signature required";
186 status = INTEGRITY_FAIL; 218 status = INTEGRITY_FAIL;
187 break; 219 break;
188 } 220 }
189 if (xattr_len - 1 >= iint->ima_hash->length) 221 if (xattr_len - sizeof(xattr_value->type) - hash_start >=
222 iint->ima_hash->length)
190 /* xattr length may be longer. md5 hash in previous 223 /* xattr length may be longer. md5 hash in previous
191 version occupied 20 bytes in xattr, instead of 16 224 version occupied 20 bytes in xattr, instead of 16
192 */ 225 */
193 rc = memcmp(xattr_value->digest, 226 rc = memcmp(&xattr_value->digest[hash_start],
194 iint->ima_hash->digest, 227 iint->ima_hash->digest,
195 iint->ima_hash->length); 228 iint->ima_hash->length);
196 else 229 else