aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity
diff options
context:
space:
mode:
Diffstat (limited to 'security/integrity')
-rw-r--r--security/integrity/ima/ima_appraise.c61
-rw-r--r--security/integrity/integrity.h13
2 files changed, 59 insertions, 15 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
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 5429ca59125b..2fb5e53e927f 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -54,6 +54,7 @@ enum evm_ima_xattr_type {
54 IMA_XATTR_DIGEST = 0x01, 54 IMA_XATTR_DIGEST = 0x01,
55 EVM_XATTR_HMAC, 55 EVM_XATTR_HMAC,
56 EVM_IMA_XATTR_DIGSIG, 56 EVM_IMA_XATTR_DIGSIG,
57 IMA_XATTR_DIGEST_NG,
57}; 58};
58 59
59struct evm_ima_xattr_data { 60struct evm_ima_xattr_data {
@@ -66,7 +67,17 @@ struct evm_ima_xattr_data {
66struct ima_digest_data { 67struct ima_digest_data {
67 u8 algo; 68 u8 algo;
68 u8 length; 69 u8 length;
69 u8 type; 70 union {
71 struct {
72 u8 unused;
73 u8 type;
74 } sha1;
75 struct {
76 u8 type;
77 u8 algo;
78 } ng;
79 u8 data[2];
80 } xattr;
70 u8 digest[0]; 81 u8 digest[0];
71} __packed; 82} __packed;
72 83