summaryrefslogtreecommitdiffstats
path: root/security/integrity/ima
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-11-13 13:41:25 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-13 13:41:25 -0500
commitb33e3cc5c90b8293599318b68e61b93a89c127bb (patch)
treef61f315118d2b3e60e409c36e09fe06f8b6b6908 /security/integrity/ima
parent55b3a0cb5aeef0961ee18eac058e488f149a0053 (diff)
parente5729f86a2987c9404f9b2fb494b9a6fc4412baf (diff)
Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem integrity updates from James Morris: "There is a mixture of bug fixes, code cleanup, preparatory code for new functionality and new functionality. Commit 26ddabfe96bb ("evm: enable EVM when X509 certificate is loaded") enabled EVM without loading a symmetric key, but was limited to defining the x509 certificate pathname at build. Included in this set of patches is the ability of enabling EVM, without loading the EVM symmetric key, from userspace. New is the ability to prevent the loading of an EVM symmetric key." * 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: ima: Remove redundant conditional operator ima: Fix bool initialization/comparison ima: check signature enforcement against cmdline param instead of CONFIG module: export module signature enforcement status ima: fix hash algorithm initialization EVM: Only complain about a missing HMAC key once EVM: Allow userspace to signal an RSA key has been loaded EVM: Include security.apparmor in EVM measurements ima: call ima_file_free() prior to calling fasync integrity: use kernel_read_file_from_path() to read x509 certs ima: always measure and audit files in policy ima: don't remove the securityfs policy file vfs: fix mounting a filesystem with i_version
Diffstat (limited to 'security/integrity/ima')
-rw-r--r--security/integrity/ima/ima_api.c67
-rw-r--r--security/integrity/ima/ima_appraise.c4
-rw-r--r--security/integrity/ima/ima_crypto.c10
-rw-r--r--security/integrity/ima/ima_fs.c6
-rw-r--r--security/integrity/ima/ima_main.c23
-rw-r--r--security/integrity/ima/ima_policy.c6
6 files changed, 75 insertions, 41 deletions
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index c2edba8de35e..c7e8db0ea4c0 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -199,42 +199,59 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
199 struct inode *inode = file_inode(file); 199 struct inode *inode = file_inode(file);
200 const char *filename = file->f_path.dentry->d_name.name; 200 const char *filename = file->f_path.dentry->d_name.name;
201 int result = 0; 201 int result = 0;
202 int length;
203 void *tmpbuf;
204 u64 i_version;
202 struct { 205 struct {
203 struct ima_digest_data hdr; 206 struct ima_digest_data hdr;
204 char digest[IMA_MAX_DIGEST_SIZE]; 207 char digest[IMA_MAX_DIGEST_SIZE];
205 } hash; 208 } hash;
206 209
207 if (!(iint->flags & IMA_COLLECTED)) { 210 if (iint->flags & IMA_COLLECTED)
208 u64 i_version = file_inode(file)->i_version; 211 goto out;
209 212
210 if (file->f_flags & O_DIRECT) { 213 /*
211 audit_cause = "failed(directio)"; 214 * Dectecting file change is based on i_version. On filesystems
212 result = -EACCES; 215 * which do not support i_version, support is limited to an initial
213 goto out; 216 * measurement/appraisal/audit.
214 } 217 */
218 i_version = file_inode(file)->i_version;
219 hash.hdr.algo = algo;
215 220
216 hash.hdr.algo = algo; 221 /* Initialize hash digest to 0's in case of failure */
217 222 memset(&hash.digest, 0, sizeof(hash.digest));
218 result = (!buf) ? ima_calc_file_hash(file, &hash.hdr) : 223
219 ima_calc_buffer_hash(buf, size, &hash.hdr); 224 if (buf)
220 if (!result) { 225 result = ima_calc_buffer_hash(buf, size, &hash.hdr);
221 int length = sizeof(hash.hdr) + hash.hdr.length; 226 else
222 void *tmpbuf = krealloc(iint->ima_hash, length, 227 result = ima_calc_file_hash(file, &hash.hdr);
223 GFP_NOFS); 228
224 if (tmpbuf) { 229 if (result && result != -EBADF && result != -EINVAL)
225 iint->ima_hash = tmpbuf; 230 goto out;
226 memcpy(iint->ima_hash, &hash, length); 231
227 iint->version = i_version; 232 length = sizeof(hash.hdr) + hash.hdr.length;
228 iint->flags |= IMA_COLLECTED; 233 tmpbuf = krealloc(iint->ima_hash, length, GFP_NOFS);
229 } else 234 if (!tmpbuf) {
230 result = -ENOMEM; 235 result = -ENOMEM;
231 } 236 goto out;
232 } 237 }
238
239 iint->ima_hash = tmpbuf;
240 memcpy(iint->ima_hash, &hash, length);
241 iint->version = i_version;
242
243 /* Possibly temporary failure due to type of read (eg. O_DIRECT) */
244 if (!result)
245 iint->flags |= IMA_COLLECTED;
233out: 246out:
234 if (result) 247 if (result) {
248 if (file->f_flags & O_DIRECT)
249 audit_cause = "failed(directio)";
250
235 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, 251 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
236 filename, "collect_data", audit_cause, 252 filename, "collect_data", audit_cause,
237 result, 0); 253 result, 0);
254 }
238 return result; 255 return result;
239} 256}
240 257
@@ -278,7 +295,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
278 } 295 }
279 296
280 result = ima_store_template(entry, violation, inode, filename, pcr); 297 result = ima_store_template(entry, violation, inode, filename, pcr);
281 if (!result || result == -EEXIST) { 298 if ((!result || result == -EEXIST) && !(file->f_flags & O_DIRECT)) {
282 iint->flags |= IMA_MEASURED; 299 iint->flags |= IMA_MEASURED;
283 iint->measured_pcrs |= (0x1 << pcr); 300 iint->measured_pcrs |= (0x1 << pcr);
284 } 301 }
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 809ba70fbbbf..ec7dfa02c051 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -40,7 +40,7 @@ __setup("ima_appraise=", default_appraise_setup);
40 */ 40 */
41bool is_ima_appraise_enabled(void) 41bool is_ima_appraise_enabled(void)
42{ 42{
43 return (ima_appraise & IMA_APPRAISE_ENFORCE) ? 1 : 0; 43 return ima_appraise & IMA_APPRAISE_ENFORCE;
44} 44}
45 45
46/* 46/*
@@ -405,7 +405,7 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
405 if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST)) 405 if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
406 return -EINVAL; 406 return -EINVAL;
407 ima_reset_appraise_flags(d_backing_inode(dentry), 407 ima_reset_appraise_flags(d_backing_inode(dentry),
408 (xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0); 408 xvalue->type == EVM_IMA_XATTR_DIGSIG);
409 result = 0; 409 result = 0;
410 } 410 }
411 return result; 411 return result;
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 802d5d20f36f..a856d8c9c9f3 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -441,6 +441,16 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
441 loff_t i_size; 441 loff_t i_size;
442 int rc; 442 int rc;
443 443
444 /*
445 * For consistency, fail file's opened with the O_DIRECT flag on
446 * filesystems mounted with/without DAX option.
447 */
448 if (file->f_flags & O_DIRECT) {
449 hash->length = hash_digest_size[ima_hash_algo];
450 hash->algo = ima_hash_algo;
451 return -EINVAL;
452 }
453
444 i_size = i_size_read(file_inode(file)); 454 i_size = i_size_read(file_inode(file));
445 455
446 if (ima_ahash_minsize && i_size >= ima_ahash_minsize) { 456 if (ima_ahash_minsize && i_size >= ima_ahash_minsize) {
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index ad491c51e833..fa540c0469da 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -32,7 +32,7 @@ bool ima_canonical_fmt;
32static int __init default_canonical_fmt_setup(char *str) 32static int __init default_canonical_fmt_setup(char *str)
33{ 33{
34#ifdef __BIG_ENDIAN 34#ifdef __BIG_ENDIAN
35 ima_canonical_fmt = 1; 35 ima_canonical_fmt = true;
36#endif 36#endif
37 return 1; 37 return 1;
38} 38}
@@ -429,10 +429,10 @@ static int ima_release_policy(struct inode *inode, struct file *file)
429 } 429 }
430 430
431 ima_update_policy(); 431 ima_update_policy();
432#ifndef CONFIG_IMA_WRITE_POLICY 432#if !defined(CONFIG_IMA_WRITE_POLICY) && !defined(CONFIG_IMA_READ_POLICY)
433 securityfs_remove(ima_policy); 433 securityfs_remove(ima_policy);
434 ima_policy = NULL; 434 ima_policy = NULL;
435#else 435#elif defined(CONFIG_IMA_WRITE_POLICY)
436 clear_bit(IMA_FS_BUSY, &ima_fs_flags); 436 clear_bit(IMA_FS_BUSY, &ima_fs_flags);
437#endif 437#endif
438 return 0; 438 return 0;
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 2aebb7984437..770654694efc 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -51,6 +51,8 @@ static int __init hash_setup(char *str)
51 ima_hash_algo = HASH_ALGO_SHA1; 51 ima_hash_algo = HASH_ALGO_SHA1;
52 else if (strncmp(str, "md5", 3) == 0) 52 else if (strncmp(str, "md5", 3) == 0)
53 ima_hash_algo = HASH_ALGO_MD5; 53 ima_hash_algo = HASH_ALGO_MD5;
54 else
55 return 1;
54 goto out; 56 goto out;
55 } 57 }
56 58
@@ -60,6 +62,8 @@ static int __init hash_setup(char *str)
60 break; 62 break;
61 } 63 }
62 } 64 }
65 if (i == HASH_ALGO__LAST)
66 return 1;
63out: 67out:
64 hash_setup_done = 1; 68 hash_setup_done = 1;
65 return 1; 69 return 1;
@@ -235,11 +239,8 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
235 hash_algo = ima_get_hash_algo(xattr_value, xattr_len); 239 hash_algo = ima_get_hash_algo(xattr_value, xattr_len);
236 240
237 rc = ima_collect_measurement(iint, file, buf, size, hash_algo); 241 rc = ima_collect_measurement(iint, file, buf, size, hash_algo);
238 if (rc != 0) { 242 if (rc != 0 && rc != -EBADF && rc != -EINVAL)
239 if (file->f_flags & O_DIRECT)
240 rc = (iint->flags & IMA_PERMIT_DIRECTIO) ? 0 : -EACCES;
241 goto out_digsig; 243 goto out_digsig;
242 }
243 244
244 if (!pathbuf) /* ima_rdwr_violation possibly pre-fetched */ 245 if (!pathbuf) /* ima_rdwr_violation possibly pre-fetched */
245 pathname = ima_d_path(&file->f_path, &pathbuf, filename); 246 pathname = ima_d_path(&file->f_path, &pathbuf, filename);
@@ -247,12 +248,14 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
247 if (action & IMA_MEASURE) 248 if (action & IMA_MEASURE)
248 ima_store_measurement(iint, file, pathname, 249 ima_store_measurement(iint, file, pathname,
249 xattr_value, xattr_len, pcr); 250 xattr_value, xattr_len, pcr);
250 if (action & IMA_APPRAISE_SUBMASK) 251 if (rc == 0 && (action & IMA_APPRAISE_SUBMASK))
251 rc = ima_appraise_measurement(func, iint, file, pathname, 252 rc = ima_appraise_measurement(func, iint, file, pathname,
252 xattr_value, xattr_len, opened); 253 xattr_value, xattr_len, opened);
253 if (action & IMA_AUDIT) 254 if (action & IMA_AUDIT)
254 ima_audit_measurement(iint, pathname); 255 ima_audit_measurement(iint, pathname);
255 256
257 if ((file->f_flags & O_DIRECT) && (iint->flags & IMA_PERMIT_DIRECTIO))
258 rc = 0;
256out_digsig: 259out_digsig:
257 if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG) && 260 if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG) &&
258 !(iint->flags & IMA_NEW_FILE)) 261 !(iint->flags & IMA_NEW_FILE))
@@ -359,12 +362,12 @@ void ima_post_path_mknod(struct dentry *dentry)
359 */ 362 */
360int ima_read_file(struct file *file, enum kernel_read_file_id read_id) 363int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
361{ 364{
365 bool sig_enforce = is_module_sig_enforced();
366
362 if (!file && read_id == READING_MODULE) { 367 if (!file && read_id == READING_MODULE) {
363#ifndef CONFIG_MODULE_SIG_FORCE 368 if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES) &&
364 if ((ima_appraise & IMA_APPRAISE_MODULES) &&
365 (ima_appraise & IMA_APPRAISE_ENFORCE)) 369 (ima_appraise & IMA_APPRAISE_ENFORCE))
366 return -EACCES; /* INTEGRITY_UNKNOWN */ 370 return -EACCES; /* INTEGRITY_UNKNOWN */
367#endif
368 return 0; /* We rely on module signature checking */ 371 return 0; /* We rely on module signature checking */
369 } 372 }
370 return 0; 373 return 0;
@@ -406,6 +409,10 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
406 if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */ 409 if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */
407 return 0; 410 return 0;
408 411
412 /* permit signed certs */
413 if (!file && read_id == READING_X509_CERTIFICATE)
414 return 0;
415
409 if (!file || !buf || size == 0) { /* should never happen */ 416 if (!file || !buf || size == 0) { /* should never happen */
410 if (ima_appraise & IMA_APPRAISE_ENFORCE) 417 if (ima_appraise & IMA_APPRAISE_ENFORCE)
411 return -EACCES; 418 return -EACCES;
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 95209a5f8595..ee4613fa5840 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -196,9 +196,9 @@ static int __init policy_setup(char *str)
196 if ((strcmp(p, "tcb") == 0) && !ima_policy) 196 if ((strcmp(p, "tcb") == 0) && !ima_policy)
197 ima_policy = DEFAULT_TCB; 197 ima_policy = DEFAULT_TCB;
198 else if (strcmp(p, "appraise_tcb") == 0) 198 else if (strcmp(p, "appraise_tcb") == 0)
199 ima_use_appraise_tcb = 1; 199 ima_use_appraise_tcb = true;
200 else if (strcmp(p, "secure_boot") == 0) 200 else if (strcmp(p, "secure_boot") == 0)
201 ima_use_secure_boot = 1; 201 ima_use_secure_boot = true;
202 } 202 }
203 203
204 return 1; 204 return 1;
@@ -207,7 +207,7 @@ __setup("ima_policy=", policy_setup);
207 207
208static int __init default_appraise_policy_setup(char *str) 208static int __init default_appraise_policy_setup(char *str)
209{ 209{
210 ima_use_appraise_tcb = 1; 210 ima_use_appraise_tcb = true;
211 return 1; 211 return 1;
212} 212}
213__setup("ima_appraise_tcb", default_appraise_policy_setup); 213__setup("ima_appraise_tcb", default_appraise_policy_setup);