aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2014-07-16 12:10:27 -0400
committerJames Morris <james.l.morris@oracle.com>2014-07-16 12:10:27 -0400
commitbd89bb78f35fd175db7a9cfc504d789b6ca0f7b0 (patch)
treedee9f8b31f3d6d2fb141541da88e1cc1329b017e /security
parentf01387d2693813eb5271a3448e6a082322c7d75d (diff)
parent1795cd9b3a91d4b5473c97f491d63892442212ab (diff)
Sync with the changes pushed by Serge in the last merge window.
Diffstat (limited to 'security')
-rw-r--r--security/device_cgroup.c33
-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_api.c10
-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.c27
-rw-r--r--security/integrity/ima/ima_policy.c6
-rw-r--r--security/integrity/integrity.h1
-rw-r--r--security/selinux/include/classmap.h2
12 files changed, 147 insertions, 52 deletions
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 9134dbf70d3e..d9d69e6930ed 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -182,7 +182,7 @@ static inline bool is_devcg_online(const struct dev_cgroup *devcg)
182static int devcgroup_online(struct cgroup_subsys_state *css) 182static int devcgroup_online(struct cgroup_subsys_state *css)
183{ 183{
184 struct dev_cgroup *dev_cgroup = css_to_devcgroup(css); 184 struct dev_cgroup *dev_cgroup = css_to_devcgroup(css);
185 struct dev_cgroup *parent_dev_cgroup = css_to_devcgroup(css_parent(css)); 185 struct dev_cgroup *parent_dev_cgroup = css_to_devcgroup(css->parent);
186 int ret = 0; 186 int ret = 0;
187 187
188 mutex_lock(&devcgroup_mutex); 188 mutex_lock(&devcgroup_mutex);
@@ -455,7 +455,7 @@ static bool verify_new_ex(struct dev_cgroup *dev_cgroup,
455static int parent_has_perm(struct dev_cgroup *childcg, 455static int parent_has_perm(struct dev_cgroup *childcg,
456 struct dev_exception_item *ex) 456 struct dev_exception_item *ex)
457{ 457{
458 struct dev_cgroup *parent = css_to_devcgroup(css_parent(&childcg->css)); 458 struct dev_cgroup *parent = css_to_devcgroup(childcg->css.parent);
459 459
460 if (!parent) 460 if (!parent)
461 return 1; 461 return 1;
@@ -476,7 +476,7 @@ static int parent_has_perm(struct dev_cgroup *childcg,
476static bool parent_allows_removal(struct dev_cgroup *childcg, 476static bool parent_allows_removal(struct dev_cgroup *childcg,
477 struct dev_exception_item *ex) 477 struct dev_exception_item *ex)
478{ 478{
479 struct dev_cgroup *parent = css_to_devcgroup(css_parent(&childcg->css)); 479 struct dev_cgroup *parent = css_to_devcgroup(childcg->css.parent);
480 480
481 if (!parent) 481 if (!parent)
482 return true; 482 return true;
@@ -587,13 +587,6 @@ static int propagate_exception(struct dev_cgroup *devcg_root,
587 return rc; 587 return rc;
588} 588}
589 589
590static inline bool has_children(struct dev_cgroup *devcgroup)
591{
592 struct cgroup *cgrp = devcgroup->css.cgroup;
593
594 return !list_empty(&cgrp->children);
595}
596
597/* 590/*
598 * Modify the exception list using allow/deny rules. 591 * Modify the exception list using allow/deny rules.
599 * CAP_SYS_ADMIN is needed for this. It's at least separate from CAP_MKNOD 592 * CAP_SYS_ADMIN is needed for this. It's at least separate from CAP_MKNOD
@@ -614,7 +607,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
614 char temp[12]; /* 11 + 1 characters needed for a u32 */ 607 char temp[12]; /* 11 + 1 characters needed for a u32 */
615 int count, rc = 0; 608 int count, rc = 0;
616 struct dev_exception_item ex; 609 struct dev_exception_item ex;
617 struct dev_cgroup *parent = css_to_devcgroup(css_parent(&devcgroup->css)); 610 struct dev_cgroup *parent = css_to_devcgroup(devcgroup->css.parent);
618 611
619 if (!capable(CAP_SYS_ADMIN)) 612 if (!capable(CAP_SYS_ADMIN))
620 return -EPERM; 613 return -EPERM;
@@ -626,7 +619,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
626 case 'a': 619 case 'a':
627 switch (filetype) { 620 switch (filetype) {
628 case DEVCG_ALLOW: 621 case DEVCG_ALLOW:
629 if (has_children(devcgroup)) 622 if (css_has_online_children(&devcgroup->css))
630 return -EINVAL; 623 return -EINVAL;
631 624
632 if (!may_allow_all(parent)) 625 if (!may_allow_all(parent))
@@ -642,7 +635,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
642 return rc; 635 return rc;
643 break; 636 break;
644 case DEVCG_DENY: 637 case DEVCG_DENY:
645 if (has_children(devcgroup)) 638 if (css_has_online_children(&devcgroup->css))
646 return -EINVAL; 639 return -EINVAL;
647 640
648 dev_exception_clean(devcgroup); 641 dev_exception_clean(devcgroup);
@@ -767,27 +760,27 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
767 return rc; 760 return rc;
768} 761}
769 762
770static int devcgroup_access_write(struct cgroup_subsys_state *css, 763static ssize_t devcgroup_access_write(struct kernfs_open_file *of,
771 struct cftype *cft, char *buffer) 764 char *buf, size_t nbytes, loff_t off)
772{ 765{
773 int retval; 766 int retval;
774 767
775 mutex_lock(&devcgroup_mutex); 768 mutex_lock(&devcgroup_mutex);
776 retval = devcgroup_update_access(css_to_devcgroup(css), 769 retval = devcgroup_update_access(css_to_devcgroup(of_css(of)),
777 cft->private, buffer); 770 of_cft(of)->private, strstrip(buf));
778 mutex_unlock(&devcgroup_mutex); 771 mutex_unlock(&devcgroup_mutex);
779 return retval; 772 return retval ?: nbytes;
780} 773}
781 774
782static struct cftype dev_cgroup_files[] = { 775static struct cftype dev_cgroup_files[] = {
783 { 776 {
784 .name = "allow", 777 .name = "allow",
785 .write_string = devcgroup_access_write, 778 .write = devcgroup_access_write,
786 .private = DEVCG_ALLOW, 779 .private = DEVCG_ALLOW,
787 }, 780 },
788 { 781 {
789 .name = "deny", 782 .name = "deny",
790 .write_string = devcgroup_access_write, 783 .write = devcgroup_access_write,
791 .private = DEVCG_DENY, 784 .private = DEVCG_DENY,
792 }, 785 },
793 { 786 {
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_api.c b/security/integrity/ima/ima_api.c
index ba9e4d792dd5..d9cd5ce14d2b 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -199,6 +199,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
199 struct evm_ima_xattr_data **xattr_value, 199 struct evm_ima_xattr_data **xattr_value,
200 int *xattr_len) 200 int *xattr_len)
201{ 201{
202 const char *audit_cause = "failed";
202 struct inode *inode = file_inode(file); 203 struct inode *inode = file_inode(file);
203 const char *filename = file->f_dentry->d_name.name; 204 const char *filename = file->f_dentry->d_name.name;
204 int result = 0; 205 int result = 0;
@@ -213,6 +214,12 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
213 if (!(iint->flags & IMA_COLLECTED)) { 214 if (!(iint->flags & IMA_COLLECTED)) {
214 u64 i_version = file_inode(file)->i_version; 215 u64 i_version = file_inode(file)->i_version;
215 216
217 if (file->f_flags & O_DIRECT) {
218 audit_cause = "failed(directio)";
219 result = -EACCES;
220 goto out;
221 }
222
216 /* use default hash algorithm */ 223 /* use default hash algorithm */
217 hash.hdr.algo = ima_hash_algo; 224 hash.hdr.algo = ima_hash_algo;
218 225
@@ -233,9 +240,10 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
233 result = -ENOMEM; 240 result = -ENOMEM;
234 } 241 }
235 } 242 }
243out:
236 if (result) 244 if (result)
237 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, 245 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
238 filename, "collect_data", "failed", 246 filename, "collect_data", audit_cause,
239 result, 0); 247 result, 0);
240 return result; 248 return result;
241} 249}
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 52ac6cf41f88..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)
@@ -214,8 +214,11 @@ static int process_measurement(struct file *file, const char *filename,
214 xattr_ptr = &xattr_value; 214 xattr_ptr = &xattr_value;
215 215
216 rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len); 216 rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len);
217 if (rc != 0) 217 if (rc != 0) {
218 if (file->f_flags & O_DIRECT)
219 rc = (iint->flags & IMA_PERMIT_DIRECTIO) ? 0 : -EACCES;
218 goto out_digsig; 220 goto out_digsig;
221 }
219 222
220 pathname = filename ?: ima_d_path(&file->f_path, &pathbuf); 223 pathname = filename ?: ima_d_path(&file->f_path, &pathbuf);
221 224
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 93873a450ff7..40a7488f6721 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -353,7 +353,7 @@ enum {
353 Opt_obj_user, Opt_obj_role, Opt_obj_type, 353 Opt_obj_user, Opt_obj_role, Opt_obj_type,
354 Opt_subj_user, Opt_subj_role, Opt_subj_type, 354 Opt_subj_user, Opt_subj_role, Opt_subj_type,
355 Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner, 355 Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner,
356 Opt_appraise_type, Opt_fsuuid 356 Opt_appraise_type, Opt_fsuuid, Opt_permit_directio
357}; 357};
358 358
359static match_table_t policy_tokens = { 359static match_table_t policy_tokens = {
@@ -375,6 +375,7 @@ static match_table_t policy_tokens = {
375 {Opt_uid, "uid=%s"}, 375 {Opt_uid, "uid=%s"},
376 {Opt_fowner, "fowner=%s"}, 376 {Opt_fowner, "fowner=%s"},
377 {Opt_appraise_type, "appraise_type=%s"}, 377 {Opt_appraise_type, "appraise_type=%s"},
378 {Opt_permit_directio, "permit_directio"},
378 {Opt_err, NULL} 379 {Opt_err, NULL}
379}; 380};
380 381
@@ -622,6 +623,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
622 else 623 else
623 result = -EINVAL; 624 result = -EINVAL;
624 break; 625 break;
626 case Opt_permit_directio:
627 entry->flags |= IMA_PERMIT_DIRECTIO;
628 break;
625 case Opt_err: 629 case Opt_err:
626 ima_log_string(ab, "UNKNOWN", p); 630 ima_log_string(ab, "UNKNOWN", p);
627 result = -EINVAL; 631 result = -EINVAL;
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 2fb5e53e927f..33c0a70f6b15 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -30,6 +30,7 @@
30#define IMA_ACTION_FLAGS 0xff000000 30#define IMA_ACTION_FLAGS 0xff000000
31#define IMA_DIGSIG 0x01000000 31#define IMA_DIGSIG 0x01000000
32#define IMA_DIGSIG_REQUIRED 0x02000000 32#define IMA_DIGSIG_REQUIRED 0x02000000
33#define IMA_PERMIT_DIRECTIO 0x04000000
33 34
34#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ 35#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \
35 IMA_APPRAISE_SUBMASK) 36 IMA_APPRAISE_SUBMASK)
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index 14d04e63b1f0..be491a74c1ed 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -147,7 +147,7 @@ struct security_class_mapping secclass_map[] = {
147 { "peer", { "recv", NULL } }, 147 { "peer", { "recv", NULL } },
148 { "capability2", 148 { "capability2",
149 { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend", 149 { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend",
150 NULL } }, 150 "audit_read", NULL } },
151 { "kernel_service", { "use_as_override", "create_files_as", NULL } }, 151 { "kernel_service", { "use_as_override", "create_files_as", NULL } },
152 { "tun_socket", 152 { "tun_socket",
153 { COMMON_SOCK_PERMS, "attach_queue", NULL } }, 153 { COMMON_SOCK_PERMS, "attach_queue", NULL } },