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.c106
1 files changed, 86 insertions, 20 deletions
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 2d4becab8918..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
@@ -43,19 +44,31 @@ int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func)
43} 44}
44 45
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_xattr.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 (u8 *)&iint->ima_xattr, 51
51 sizeof(iint->ima_xattr), 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 */
55enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, 68enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
56 int func) 69 int func)
57{ 70{
58 switch(func) { 71 switch (func) {
59 case MMAP_CHECK: 72 case MMAP_CHECK:
60 return iint->ima_mmap_status; 73 return iint->ima_mmap_status;
61 case BPRM_CHECK: 74 case BPRM_CHECK:
@@ -71,7 +84,7 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
71static void ima_set_cache_status(struct integrity_iint_cache *iint, 84static void ima_set_cache_status(struct integrity_iint_cache *iint,
72 int func, enum integrity_status status) 85 int func, enum integrity_status status)
73{ 86{
74 switch(func) { 87 switch (func) {
75 case MMAP_CHECK: 88 case MMAP_CHECK:
76 iint->ima_mmap_status = status; 89 iint->ima_mmap_status = status;
77 break; 90 break;
@@ -90,7 +103,7 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint,
90 103
91static void ima_cache_flags(struct integrity_iint_cache *iint, int func) 104static void ima_cache_flags(struct integrity_iint_cache *iint, int func)
92{ 105{
93 switch(func) { 106 switch (func) {
94 case MMAP_CHECK: 107 case MMAP_CHECK:
95 iint->flags |= (IMA_MMAP_APPRAISED | IMA_APPRAISED); 108 iint->flags |= (IMA_MMAP_APPRAISED | IMA_APPRAISED);
96 break; 109 break;
@@ -107,6 +120,50 @@ static void ima_cache_flags(struct integrity_iint_cache *iint, int func)
107 } 120 }
108} 121}
109 122
123void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
124 struct ima_digest_data *hash)
125{
126 struct signature_v2_hdr *sig;
127
128 if (!xattr_value || xattr_len < 2)
129 return;
130
131 switch (xattr_value->type) {
132 case EVM_IMA_XATTR_DIGSIG:
133 sig = (typeof(sig))xattr_value;
134 if (sig->version != 2 || xattr_len <= sizeof(*sig))
135 return;
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 }
153}
154
155int ima_read_xattr(struct dentry *dentry,
156 struct evm_ima_xattr_data **xattr_value)
157{
158 struct inode *inode = dentry->d_inode;
159
160 if (!inode->i_op->getxattr)
161 return 0;
162
163 return vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
164 0, GFP_NOFS);
165}
166
110/* 167/*
111 * ima_appraise_measurement - appraise file measurement 168 * ima_appraise_measurement - appraise file measurement
112 * 169 *
@@ -116,23 +173,22 @@ static void ima_cache_flags(struct integrity_iint_cache *iint, int func)
116 * Return 0 on success, error code otherwise 173 * Return 0 on success, error code otherwise
117 */ 174 */
118int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, 175int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
119 struct file *file, const unsigned char *filename) 176 struct file *file, const unsigned char *filename,
177 struct evm_ima_xattr_data *xattr_value,
178 int xattr_len)
120{ 179{
121 struct dentry *dentry = file->f_dentry; 180 struct dentry *dentry = file->f_dentry;
122 struct inode *inode = dentry->d_inode; 181 struct inode *inode = dentry->d_inode;
123 struct evm_ima_xattr_data *xattr_value = NULL;
124 enum integrity_status status = INTEGRITY_UNKNOWN; 182 enum integrity_status status = INTEGRITY_UNKNOWN;
125 const char *op = "appraise_data"; 183 const char *op = "appraise_data";
126 char *cause = "unknown"; 184 char *cause = "unknown";
127 int rc; 185 int rc = xattr_len, hash_start = 0;
128 186
129 if (!ima_appraise) 187 if (!ima_appraise)
130 return 0; 188 return 0;
131 if (!inode->i_op->getxattr) 189 if (!inode->i_op->getxattr)
132 return INTEGRITY_UNKNOWN; 190 return INTEGRITY_UNKNOWN;
133 191
134 rc = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)&xattr_value,
135 0, GFP_NOFS);
136 if (rc <= 0) { 192 if (rc <= 0) {
137 if (rc && rc != -ENODATA) 193 if (rc && rc != -ENODATA)
138 goto out; 194 goto out;
@@ -153,14 +209,25 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
153 goto out; 209 goto out;
154 } 210 }
155 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;
156 case IMA_XATTR_DIGEST: 215 case IMA_XATTR_DIGEST:
157 if (iint->flags & IMA_DIGSIG_REQUIRED) { 216 if (iint->flags & IMA_DIGSIG_REQUIRED) {
158 cause = "IMA signature required"; 217 cause = "IMA signature required";
159 status = INTEGRITY_FAIL; 218 status = INTEGRITY_FAIL;
160 break; 219 break;
161 } 220 }
162 rc = memcmp(xattr_value->digest, iint->ima_xattr.digest, 221 if (xattr_len - sizeof(xattr_value->type) - hash_start >=
163 IMA_DIGEST_SIZE); 222 iint->ima_hash->length)
223 /* xattr length may be longer. md5 hash in previous
224 version occupied 20 bytes in xattr, instead of 16
225 */
226 rc = memcmp(&xattr_value->digest[hash_start],
227 iint->ima_hash->digest,
228 iint->ima_hash->length);
229 else
230 rc = -EINVAL;
164 if (rc) { 231 if (rc) {
165 cause = "invalid-hash"; 232 cause = "invalid-hash";
166 status = INTEGRITY_FAIL; 233 status = INTEGRITY_FAIL;
@@ -171,9 +238,9 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
171 case EVM_IMA_XATTR_DIGSIG: 238 case EVM_IMA_XATTR_DIGSIG:
172 iint->flags |= IMA_DIGSIG; 239 iint->flags |= IMA_DIGSIG;
173 rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, 240 rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
174 xattr_value->digest, rc - 1, 241 (const char *)xattr_value, rc,
175 iint->ima_xattr.digest, 242 iint->ima_hash->digest,
176 IMA_DIGEST_SIZE); 243 iint->ima_hash->length);
177 if (rc == -EOPNOTSUPP) { 244 if (rc == -EOPNOTSUPP) {
178 status = INTEGRITY_UNKNOWN; 245 status = INTEGRITY_UNKNOWN;
179 } else if (rc) { 246 } else if (rc) {
@@ -203,7 +270,6 @@ out:
203 ima_cache_flags(iint, func); 270 ima_cache_flags(iint, func);
204 } 271 }
205 ima_set_cache_status(iint, func, status); 272 ima_set_cache_status(iint, func, status);
206 kfree(xattr_value);
207 return status; 273 return status;
208} 274}
209 275
@@ -219,7 +285,7 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
219 if (iint->flags & IMA_DIGSIG) 285 if (iint->flags & IMA_DIGSIG)
220 return; 286 return;
221 287
222 rc = ima_collect_measurement(iint, file); 288 rc = ima_collect_measurement(iint, file, NULL, NULL);
223 if (rc < 0) 289 if (rc < 0)
224 return; 290 return;
225 291