aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Kasatkin <d.kasatkin@samsung.com>2013-04-25 03:44:04 -0400
committerMimi Zohar <zohar@linux.vnet.ibm.com>2013-10-25 17:17:00 -0400
commita35c3fb6490cc1d3446e4781693408100113c4fb (patch)
tree03234f8b7ebaf3cb98bf77f999b8a5284d4dadbc
parentb1aaab22e263d0cca1effe319b7d2bf895444219 (diff)
ima: use dynamically allocated hash storage
For each inode in the IMA policy, an iint is allocated. To support larger hash digests, the iint digest size changed from 20 bytes to the maximum supported hash digest size. Instead of allocating the maximum size, which most likely is not needed, this patch dynamically allocates the needed hash storage. Changelog: - fix krealloc bug Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
-rw-r--r--security/integrity/iint.c2
-rw-r--r--security/integrity/ima/ima_api.c57
-rw-r--r--security/integrity/ima/ima_appraise.c16
-rw-r--r--security/integrity/integrity.h4
4 files changed, 49 insertions, 30 deletions
diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index 74522dbd10a6..c49d3f14cbec 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -70,6 +70,8 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode)
70 70
71static void iint_free(struct integrity_iint_cache *iint) 71static void iint_free(struct integrity_iint_cache *iint)
72{ 72{
73 kfree(iint->ima_hash);
74 iint->ima_hash = NULL;
73 iint->version = 0; 75 iint->version = 0;
74 iint->flags = 0UL; 76 iint->flags = 0UL;
75 iint->ima_file_status = INTEGRITY_UNKNOWN; 77 iint->ima_file_status = INTEGRITY_UNKNOWN;
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 1dba98e2d7e9..5a7942e20814 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -44,7 +44,10 @@ int ima_store_template(struct ima_template_entry *entry,
44 const char *op = "add_template_measure"; 44 const char *op = "add_template_measure";
45 const char *audit_cause = "hashing_error"; 45 const char *audit_cause = "hashing_error";
46 int result; 46 int result;
47 struct ima_digest_data hash; 47 struct {
48 struct ima_digest_data hdr;
49 char digest[IMA_MAX_DIGEST_SIZE];
50 } hash;
48 51
49 memset(entry->digest, 0, sizeof(entry->digest)); 52 memset(entry->digest, 0, sizeof(entry->digest));
50 entry->template_name = IMA_TEMPLATE_NAME; 53 entry->template_name = IMA_TEMPLATE_NAME;
@@ -52,14 +55,14 @@ int ima_store_template(struct ima_template_entry *entry,
52 55
53 if (!violation) { 56 if (!violation) {
54 result = ima_calc_buffer_hash(&entry->template, 57 result = ima_calc_buffer_hash(&entry->template,
55 entry->template_len, &hash); 58 entry->template_len, &hash.hdr);
56 if (result < 0) { 59 if (result < 0) {
57 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, 60 integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
58 entry->template_name, op, 61 entry->template_name, op,
59 audit_cause, result, 0); 62 audit_cause, result, 0);
60 return result; 63 return result;
61 } 64 }
62 memcpy(entry->digest, hash.digest, hash.length); 65 memcpy(entry->digest, hash.hdr.digest, hash.hdr.length);
63 } 66 }
64 result = ima_add_template_entry(entry, violation, op, inode); 67 result = ima_add_template_entry(entry, violation, op, inode);
65 return result; 68 return result;
@@ -146,6 +149,10 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
146 struct inode *inode = file_inode(file); 149 struct inode *inode = file_inode(file);
147 const char *filename = file->f_dentry->d_name.name; 150 const char *filename = file->f_dentry->d_name.name;
148 int result = 0; 151 int result = 0;
152 struct {
153 struct ima_digest_data hdr;
154 char digest[IMA_MAX_DIGEST_SIZE];
155 } hash;
149 156
150 if (xattr_value) 157 if (xattr_value)
151 *xattr_len = ima_read_xattr(file->f_dentry, xattr_value); 158 *xattr_len = ima_read_xattr(file->f_dentry, xattr_value);
@@ -154,16 +161,23 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
154 u64 i_version = file_inode(file)->i_version; 161 u64 i_version = file_inode(file)->i_version;
155 162
156 /* use default hash algorithm */ 163 /* use default hash algorithm */
157 iint->ima_hash.algo = ima_hash_algo; 164 hash.hdr.algo = ima_hash_algo;
158 165
159 if (xattr_value) 166 if (xattr_value)
160 ima_get_hash_algo(*xattr_value, *xattr_len, 167 ima_get_hash_algo(*xattr_value, *xattr_len, &hash.hdr);
161 &iint->ima_hash);
162 168
163 result = ima_calc_file_hash(file, &iint->ima_hash); 169 result = ima_calc_file_hash(file, &hash.hdr);
164 if (!result) { 170 if (!result) {
165 iint->version = i_version; 171 int length = sizeof(hash.hdr) + hash.hdr.length;
166 iint->flags |= IMA_COLLECTED; 172 void *tmpbuf = krealloc(iint->ima_hash, length,
173 GFP_NOFS);
174 if (tmpbuf) {
175 iint->ima_hash = tmpbuf;
176 memcpy(iint->ima_hash, &hash, length);
177 iint->version = i_version;
178 iint->flags |= IMA_COLLECTED;
179 } else
180 result = -ENOMEM;
167 } 181 }
168 } 182 }
169 if (result) 183 if (result)
@@ -208,21 +222,24 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
208 return; 222 return;
209 } 223 }
210 memset(&entry->template, 0, sizeof(entry->template)); 224 memset(&entry->template, 0, sizeof(entry->template));
211 if (iint->ima_hash.algo != ima_hash_algo) { 225 if (iint->ima_hash->algo != ima_hash_algo) {
212 struct ima_digest_data hash; 226 struct {
227 struct ima_digest_data hdr;
228 char digest[IMA_MAX_DIGEST_SIZE];
229 } hash;
213 230
214 hash.algo = ima_hash_algo; 231 hash.hdr.algo = ima_hash_algo;
215 result = ima_calc_file_hash(file, &hash); 232 result = ima_calc_file_hash(file, &hash.hdr);
216 if (result) 233 if (result)
217 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, 234 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
218 filename, "collect_data", "failed", 235 filename, "collect_data", "failed",
219 result, 0); 236 result, 0);
220 else 237 else
221 memcpy(entry->template.digest, hash.digest, 238 memcpy(entry->template.digest, hash.hdr.digest,
222 hash.length); 239 hash.hdr.length);
223 } else 240 } else
224 memcpy(entry->template.digest, iint->ima_hash.digest, 241 memcpy(entry->template.digest, iint->ima_hash->digest,
225 iint->ima_hash.length); 242 iint->ima_hash->length);
226 strcpy(entry->template.file_name, 243 strcpy(entry->template.file_name,
227 (strlen(filename) > IMA_EVENT_NAME_LEN_MAX) ? 244 (strlen(filename) > IMA_EVENT_NAME_LEN_MAX) ?
228 file->f_dentry->d_name.name : filename); 245 file->f_dentry->d_name.name : filename);
@@ -238,14 +255,14 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
238 const unsigned char *filename) 255 const unsigned char *filename)
239{ 256{
240 struct audit_buffer *ab; 257 struct audit_buffer *ab;
241 char hash[(iint->ima_hash.length * 2) + 1]; 258 char hash[(iint->ima_hash->length * 2) + 1];
242 int i; 259 int i;
243 260
244 if (iint->flags & IMA_AUDITED) 261 if (iint->flags & IMA_AUDITED)
245 return; 262 return;
246 263
247 for (i = 0; i < iint->ima_hash.length; i++) 264 for (i = 0; i < iint->ima_hash->length; i++)
248 hex_byte_pack(hash + (i * 2), iint->ima_hash.digest[i]); 265 hex_byte_pack(hash + (i * 2), iint->ima_hash->digest[i]);
249 hash[i * 2] = '\0'; 266 hash[i * 2] = '\0';
250 267
251 ab = audit_log_start(current->audit_context, GFP_KERNEL, 268 ab = audit_log_start(current->audit_context, GFP_KERNEL,
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index e1865a6e80ec..116630ca5ff3 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -45,10 +45,10 @@ int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func)
45static int ima_fix_xattr(struct dentry *dentry, 45static int ima_fix_xattr(struct dentry *dentry,
46 struct integrity_iint_cache *iint) 46 struct integrity_iint_cache *iint)
47{ 47{
48 iint->ima_hash.type = IMA_XATTR_DIGEST; 48 iint->ima_hash->type = IMA_XATTR_DIGEST;
49 return __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA, 49 return __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA,
50 &iint->ima_hash.type, 50 &iint->ima_hash->type,
51 1 + iint->ima_hash.length, 0); 51 1 + iint->ima_hash->length, 0);
52} 52}
53 53
54/* Return specific func appraised cached result */ 54/* Return specific func appraised cached result */
@@ -186,13 +186,13 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
186 status = INTEGRITY_FAIL; 186 status = INTEGRITY_FAIL;
187 break; 187 break;
188 } 188 }
189 if (xattr_len - 1 >= iint->ima_hash.length) 189 if (xattr_len - 1 >= iint->ima_hash->length)
190 /* xattr length may be longer. md5 hash in previous 190 /* xattr length may be longer. md5 hash in previous
191 version occupied 20 bytes in xattr, instead of 16 191 version occupied 20 bytes in xattr, instead of 16
192 */ 192 */
193 rc = memcmp(xattr_value->digest, 193 rc = memcmp(xattr_value->digest,
194 iint->ima_hash.digest, 194 iint->ima_hash->digest,
195 iint->ima_hash.length); 195 iint->ima_hash->length);
196 else 196 else
197 rc = -EINVAL; 197 rc = -EINVAL;
198 if (rc) { 198 if (rc) {
@@ -206,8 +206,8 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
206 iint->flags |= IMA_DIGSIG; 206 iint->flags |= IMA_DIGSIG;
207 rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, 207 rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
208 (const char *)xattr_value, rc, 208 (const char *)xattr_value, rc,
209 iint->ima_hash.digest, 209 iint->ima_hash->digest,
210 iint->ima_hash.length); 210 iint->ima_hash->length);
211 if (rc == -EOPNOTSUPP) { 211 if (rc == -EOPNOTSUPP) {
212 status = INTEGRITY_UNKNOWN; 212 status = INTEGRITY_UNKNOWN;
213 } else if (rc) { 213 } else if (rc) {
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index aead6b2b5488..5429ca59125b 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -67,7 +67,7 @@ struct ima_digest_data {
67 u8 algo; 67 u8 algo;
68 u8 length; 68 u8 length;
69 u8 type; 69 u8 type;
70 u8 digest[IMA_MAX_DIGEST_SIZE]; 70 u8 digest[0];
71} __packed; 71} __packed;
72 72
73/* 73/*
@@ -93,7 +93,7 @@ struct integrity_iint_cache {
93 enum integrity_status ima_bprm_status:4; 93 enum integrity_status ima_bprm_status:4;
94 enum integrity_status ima_module_status:4; 94 enum integrity_status ima_module_status:4;
95 enum integrity_status evm_status:4; 95 enum integrity_status evm_status:4;
96 struct ima_digest_data ima_hash; 96 struct ima_digest_data *ima_hash;
97}; 97};
98 98
99/* rbtree tree calls to lookup, insert, delete 99/* rbtree tree calls to lookup, insert, delete