aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-13 10:39:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-13 10:39:39 -0400
commitaa569fa0ea32d1c24fb801a07d2d9174cbbdde23 (patch)
tree54c211a790684e0a93d6139634251152c703bbc2 /security
parent6d87c225f5d82d29243dc124f1ffcbb0e14ec358 (diff)
parent0430e49b6e7c6b5e076be8fefdee089958c9adad (diff)
Merge branch 'serge-next-2' of git://git.kernel.org/pub/scm/linux/kernel/git/sergeh/linux-security
Pull more security layer updates from Serge Hallyn: "A few more commits had previously failed to make it through security-next into linux-next but this week made it into linux-next. At least commit "ima: introduce ima_kernel_read()" was deemed critical by Mimi to make this merge window. This is a temporary tree just for this request. Mimi has pointed me to some previous threads about keeping maintainer trees at the previous release, which I'll certainly do for anything long-term, after talking with James" * 'serge-next-2' of git://git.kernel.org/pub/scm/linux/kernel/git/sergeh/linux-security: ima: introduce ima_kernel_read() evm: prohibit userspace writing 'security.evm' HMAC value ima: check inode integrity cache in violation check ima: prevent unnecessary policy checking evm: provide option to protect additional SMACK xattrs evm: replace HMAC version with attribute mask ima: prevent new digsig xattr from being replaced
Diffstat (limited to 'security')
-rw-r--r--security/integrity/evm/Kconfig42
-rw-r--r--security/integrity/evm/evm.h5
-rw-r--r--security/integrity/evm/evm_crypto.c2
-rw-r--r--security/integrity/evm/evm_main.c29
-rw-r--r--security/integrity/ima/ima_appraise.c10
-rw-r--r--security/integrity/ima/ima_crypto.c32
-rw-r--r--security/integrity/ima/ima_main.c22
7 files changed, 114 insertions, 28 deletions
diff --git a/security/integrity/evm/Kconfig b/security/integrity/evm/Kconfig
index d35b4915b00d..d606f3d12d6b 100644
--- a/security/integrity/evm/Kconfig
+++ b/security/integrity/evm/Kconfig
@@ -12,15 +12,41 @@ config EVM
12 12
13 If you are unsure how to answer this question, answer N. 13 If you are unsure how to answer this question, answer N.
14 14
15config EVM_HMAC_VERSION 15if EVM
16 int "EVM HMAC version" 16
17menu "EVM options"
18
19config EVM_ATTR_FSUUID
20 bool "FSUUID (version 2)"
21 default y
17 depends on EVM 22 depends on EVM
18 default 2
19 help 23 help
20 This options adds EVM HMAC version support. 24 Include filesystem UUID for HMAC calculation.
21 1 - original version 25
22 2 - add per filesystem unique identifier (UUID) (default) 26 Default value is 'selected', which is former version 2.
27 if 'not selected', it is former version 1
23 28
24 WARNING: changing the HMAC calculation method or adding 29 WARNING: changing the HMAC calculation method or adding
25 additional info to the calculation, requires existing EVM 30 additional info to the calculation, requires existing EVM
26 labeled file systems to be relabeled. 31 labeled file systems to be relabeled.
32
33config EVM_EXTRA_SMACK_XATTRS
34 bool "Additional SMACK xattrs"
35 depends on EVM && SECURITY_SMACK
36 default n
37 help
38 Include additional SMACK xattrs for HMAC calculation.
39
40 In addition to the original security xattrs (eg. security.selinux,
41 security.SMACK64, security.capability, and security.ima) included
42 in the HMAC calculation, enabling this option includes newly defined
43 Smack xattrs: security.SMACK64EXEC, security.SMACK64TRANSMUTE and
44 security.SMACK64MMAP.
45
46 WARNING: changing the HMAC calculation method or adding
47 additional info to the calculation, requires existing EVM
48 labeled file systems to be relabeled.
49
50endmenu
51
52endif
diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h
index 37c88ddb3cfe..88bfe77efa1c 100644
--- a/security/integrity/evm/evm.h
+++ b/security/integrity/evm/evm.h
@@ -24,7 +24,10 @@
24extern int evm_initialized; 24extern int evm_initialized;
25extern char *evm_hmac; 25extern char *evm_hmac;
26extern char *evm_hash; 26extern char *evm_hash;
27extern int evm_hmac_version; 27
28#define EVM_ATTR_FSUUID 0x0001
29
30extern int evm_hmac_attrs;
28 31
29extern struct crypto_shash *hmac_tfm; 32extern struct crypto_shash *hmac_tfm;
30extern struct crypto_shash *hash_tfm; 33extern struct crypto_shash *hash_tfm;
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index 6b540f1822e0..5e9687f02e1b 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -112,7 +112,7 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
112 hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid); 112 hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid);
113 hmac_misc.mode = inode->i_mode; 113 hmac_misc.mode = inode->i_mode;
114 crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof(hmac_misc)); 114 crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof(hmac_misc));
115 if (evm_hmac_version > 1) 115 if (evm_hmac_attrs & EVM_ATTR_FSUUID)
116 crypto_shash_update(desc, inode->i_sb->s_uuid, 116 crypto_shash_update(desc, inode->i_sb->s_uuid,
117 sizeof(inode->i_sb->s_uuid)); 117 sizeof(inode->i_sb->s_uuid));
118 crypto_shash_final(desc, digest); 118 crypto_shash_final(desc, digest);
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 6e0bd933b6a9..3bcb80df4d01 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -32,7 +32,7 @@ static char *integrity_status_msg[] = {
32}; 32};
33char *evm_hmac = "hmac(sha1)"; 33char *evm_hmac = "hmac(sha1)";
34char *evm_hash = "sha1"; 34char *evm_hash = "sha1";
35int evm_hmac_version = CONFIG_EVM_HMAC_VERSION; 35int evm_hmac_attrs;
36 36
37char *evm_config_xattrnames[] = { 37char *evm_config_xattrnames[] = {
38#ifdef CONFIG_SECURITY_SELINUX 38#ifdef CONFIG_SECURITY_SELINUX
@@ -40,6 +40,11 @@ char *evm_config_xattrnames[] = {
40#endif 40#endif
41#ifdef CONFIG_SECURITY_SMACK 41#ifdef CONFIG_SECURITY_SMACK
42 XATTR_NAME_SMACK, 42 XATTR_NAME_SMACK,
43#ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
44 XATTR_NAME_SMACKEXEC,
45 XATTR_NAME_SMACKTRANSMUTE,
46 XATTR_NAME_SMACKMMAP,
47#endif
43#endif 48#endif
44#ifdef CONFIG_IMA_APPRAISE 49#ifdef CONFIG_IMA_APPRAISE
45 XATTR_NAME_IMA, 50 XATTR_NAME_IMA,
@@ -57,6 +62,14 @@ static int __init evm_set_fixmode(char *str)
57} 62}
58__setup("evm=", evm_set_fixmode); 63__setup("evm=", evm_set_fixmode);
59 64
65static void __init evm_init_config(void)
66{
67#ifdef CONFIG_EVM_ATTR_FSUUID
68 evm_hmac_attrs |= EVM_ATTR_FSUUID;
69#endif
70 pr_info("HMAC attrs: 0x%x\n", evm_hmac_attrs);
71}
72
60static int evm_find_protected_xattrs(struct dentry *dentry) 73static int evm_find_protected_xattrs(struct dentry *dentry)
61{ 74{
62 struct inode *inode = dentry->d_inode; 75 struct inode *inode = dentry->d_inode;
@@ -287,12 +300,20 @@ out:
287 * @xattr_value: pointer to the new extended attribute value 300 * @xattr_value: pointer to the new extended attribute value
288 * @xattr_value_len: pointer to the new extended attribute value length 301 * @xattr_value_len: pointer to the new extended attribute value length
289 * 302 *
290 * Updating 'security.evm' requires CAP_SYS_ADMIN privileges and that 303 * Before allowing the 'security.evm' protected xattr to be updated,
291 * the current value is valid. 304 * verify the existing value is valid. As only the kernel should have
305 * access to the EVM encrypted key needed to calculate the HMAC, prevent
306 * userspace from writing HMAC value. Writing 'security.evm' requires
307 * requires CAP_SYS_ADMIN privileges.
292 */ 308 */
293int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name, 309int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,
294 const void *xattr_value, size_t xattr_value_len) 310 const void *xattr_value, size_t xattr_value_len)
295{ 311{
312 const struct evm_ima_xattr_data *xattr_data = xattr_value;
313
314 if ((strcmp(xattr_name, XATTR_NAME_EVM) == 0)
315 && (xattr_data->type == EVM_XATTR_HMAC))
316 return -EPERM;
296 return evm_protect_xattr(dentry, xattr_name, xattr_value, 317 return evm_protect_xattr(dentry, xattr_name, xattr_value,
297 xattr_value_len); 318 xattr_value_len);
298} 319}
@@ -432,6 +453,8 @@ static int __init init_evm(void)
432{ 453{
433 int error; 454 int error;
434 455
456 evm_init_config();
457
435 error = evm_init_secfs(); 458 error = evm_init_secfs();
436 if (error < 0) { 459 if (error < 0) {
437 pr_info("Error registering secfs\n"); 460 pr_info("Error registering secfs\n");
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 291bf0f3a46d..d3113d4aaa3c 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -341,7 +341,7 @@ static int ima_protect_xattr(struct dentry *dentry, const char *xattr_name,
341 return 0; 341 return 0;
342} 342}
343 343
344static void ima_reset_appraise_flags(struct inode *inode) 344static void ima_reset_appraise_flags(struct inode *inode, int digsig)
345{ 345{
346 struct integrity_iint_cache *iint; 346 struct integrity_iint_cache *iint;
347 347
@@ -353,18 +353,22 @@ static void ima_reset_appraise_flags(struct inode *inode)
353 return; 353 return;
354 354
355 iint->flags &= ~IMA_DONE_MASK; 355 iint->flags &= ~IMA_DONE_MASK;
356 if (digsig)
357 iint->flags |= IMA_DIGSIG;
356 return; 358 return;
357} 359}
358 360
359int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name, 361int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
360 const void *xattr_value, size_t xattr_value_len) 362 const void *xattr_value, size_t xattr_value_len)
361{ 363{
364 const struct evm_ima_xattr_data *xvalue = xattr_value;
362 int result; 365 int result;
363 366
364 result = ima_protect_xattr(dentry, xattr_name, xattr_value, 367 result = ima_protect_xattr(dentry, xattr_name, xattr_value,
365 xattr_value_len); 368 xattr_value_len);
366 if (result == 1) { 369 if (result == 1) {
367 ima_reset_appraise_flags(dentry->d_inode); 370 ima_reset_appraise_flags(dentry->d_inode,
371 (xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0);
368 result = 0; 372 result = 0;
369 } 373 }
370 return result; 374 return result;
@@ -376,7 +380,7 @@ int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)
376 380
377 result = ima_protect_xattr(dentry, xattr_name, NULL, 0); 381 result = ima_protect_xattr(dentry, xattr_name, NULL, 0);
378 if (result == 1) { 382 if (result == 1) {
379 ima_reset_appraise_flags(dentry->d_inode); 383 ima_reset_appraise_flags(dentry->d_inode, 0);
380 result = 0; 384 result = 0;
381 } 385 }
382 return result; 386 return result;
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 1bde8e627766..ccd0ac8fa9a0 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -27,6 +27,36 @@
27 27
28static struct crypto_shash *ima_shash_tfm; 28static struct crypto_shash *ima_shash_tfm;
29 29
30/**
31 * ima_kernel_read - read file content
32 *
33 * This is a function for reading file content instead of kernel_read().
34 * It does not perform locking checks to ensure it cannot be blocked.
35 * It does not perform security checks because it is irrelevant for IMA.
36 *
37 */
38static int ima_kernel_read(struct file *file, loff_t offset,
39 char *addr, unsigned long count)
40{
41 mm_segment_t old_fs;
42 char __user *buf = addr;
43 ssize_t ret;
44
45 if (!(file->f_mode & FMODE_READ))
46 return -EBADF;
47 if (!file->f_op->read && !file->f_op->aio_read)
48 return -EINVAL;
49
50 old_fs = get_fs();
51 set_fs(get_ds());
52 if (file->f_op->read)
53 ret = file->f_op->read(file, buf, count, &offset);
54 else
55 ret = do_sync_read(file, buf, count, &offset);
56 set_fs(old_fs);
57 return ret;
58}
59
30int ima_init_crypto(void) 60int ima_init_crypto(void)
31{ 61{
32 long rc; 62 long rc;
@@ -104,7 +134,7 @@ static int ima_calc_file_hash_tfm(struct file *file,
104 while (offset < i_size) { 134 while (offset < i_size) {
105 int rbuf_len; 135 int rbuf_len;
106 136
107 rbuf_len = kernel_read(file, offset, rbuf, PAGE_SIZE); 137 rbuf_len = ima_kernel_read(file, offset, rbuf, PAGE_SIZE);
108 if (rbuf_len < 0) { 138 if (rbuf_len < 0) {
109 rc = rbuf_len; 139 rc = rbuf_len;
110 break; 140 break;
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index dcc98cf542d8..09baa335ebc7 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -81,7 +81,6 @@ static void ima_rdwr_violation_check(struct file *file)
81{ 81{
82 struct inode *inode = file_inode(file); 82 struct inode *inode = file_inode(file);
83 fmode_t mode = file->f_mode; 83 fmode_t mode = file->f_mode;
84 int must_measure;
85 bool send_tomtou = false, send_writers = false; 84 bool send_tomtou = false, send_writers = false;
86 char *pathbuf = NULL; 85 char *pathbuf = NULL;
87 const char *pathname; 86 const char *pathname;
@@ -92,18 +91,19 @@ static void ima_rdwr_violation_check(struct file *file)
92 mutex_lock(&inode->i_mutex); /* file metadata: permissions, xattr */ 91 mutex_lock(&inode->i_mutex); /* file metadata: permissions, xattr */
93 92
94 if (mode & FMODE_WRITE) { 93 if (mode & FMODE_WRITE) {
95 if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) 94 if (atomic_read(&inode->i_readcount) && IS_IMA(inode)) {
96 send_tomtou = true; 95 struct integrity_iint_cache *iint;
97 goto out; 96 iint = integrity_iint_find(inode);
97 /* IMA_MEASURE is set from reader side */
98 if (iint && (iint->flags & IMA_MEASURE))
99 send_tomtou = true;
100 }
101 } else {
102 if ((atomic_read(&inode->i_writecount) > 0) &&
103 ima_must_measure(inode, MAY_READ, FILE_CHECK))
104 send_writers = true;
98 } 105 }
99 106
100 must_measure = ima_must_measure(inode, MAY_READ, FILE_CHECK);
101 if (!must_measure)
102 goto out;
103
104 if (atomic_read(&inode->i_writecount) > 0)
105 send_writers = true;
106out:
107 mutex_unlock(&inode->i_mutex); 107 mutex_unlock(&inode->i_mutex);
108 108
109 if (!send_tomtou && !send_writers) 109 if (!send_tomtou && !send_writers)