diff options
Diffstat (limited to 'security/integrity/ima/ima_appraise.c')
-rw-r--r-- | security/integrity/ima/ima_appraise.c | 61 |
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) | |||
45 | static int ima_fix_xattr(struct dentry *dentry, | 46 | static 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 | ||
126 | int ima_read_xattr(struct dentry *dentry, | 155 | int 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 |