aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2010-02-28 17:36:31 -0500
committerJames Morris <jmorris@namei.org>2010-02-28 17:36:31 -0500
commitb4ccebdd37ff70d349321a198f416ba737a5e833 (patch)
tree275d717070346722c3aacd8355fb4f743216e03b /security
parent30ff056c42c665b9ea535d8515890857ae382540 (diff)
parentef57471a73b67a7b65fd8708fd55c77cb7c619af (diff)
Merge branch 'next' into for-linus
Diffstat (limited to 'security')
-rw-r--r--security/capability.c4
-rw-r--r--security/commoncap.c9
-rw-r--r--security/security.c49
-rw-r--r--security/selinux/avc.c22
-rw-r--r--security/selinux/hooks.c41
-rw-r--r--security/selinux/include/security.h13
-rw-r--r--security/selinux/selinuxfs.c12
-rw-r--r--security/selinux/ss/context.h12
-rw-r--r--security/selinux/ss/mls.c48
-rw-r--r--security/selinux/ss/mls.h2
-rw-r--r--security/selinux/ss/mls_types.h7
-rw-r--r--security/selinux/ss/policydb.c127
-rw-r--r--security/selinux/ss/policydb.h10
-rw-r--r--security/selinux/ss/services.c273
-rw-r--r--security/smack/smack_lsm.c4
-rw-r--r--security/tomoyo/Makefile2
-rw-r--r--security/tomoyo/common.c374
-rw-r--r--security/tomoyo/common.h530
-rw-r--r--security/tomoyo/domain.c391
-rw-r--r--security/tomoyo/file.c731
-rw-r--r--security/tomoyo/gc.c370
-rw-r--r--security/tomoyo/realpath.c269
-rw-r--r--security/tomoyo/realpath.h66
-rw-r--r--security/tomoyo/tomoyo.c142
-rw-r--r--security/tomoyo/tomoyo.h94
25 files changed, 1937 insertions, 1665 deletions
diff --git a/security/capability.c b/security/capability.c
index 5c700e1a4fd3..4875142b858d 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -906,10 +906,6 @@ static void cap_audit_rule_free(void *lsmrule)
906} 906}
907#endif /* CONFIG_AUDIT */ 907#endif /* CONFIG_AUDIT */
908 908
909struct security_operations default_security_ops = {
910 .name = "default",
911};
912
913#define set_to_cap_if_null(ops, function) \ 909#define set_to_cap_if_null(ops, function) \
914 do { \ 910 do { \
915 if (!ops->function) { \ 911 if (!ops->function) { \
diff --git a/security/commoncap.c b/security/commoncap.c
index f800fdb3de94..61669730da98 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -27,6 +27,7 @@
27#include <linux/sched.h> 27#include <linux/sched.h>
28#include <linux/prctl.h> 28#include <linux/prctl.h>
29#include <linux/securebits.h> 29#include <linux/securebits.h>
30#include <linux/syslog.h>
30 31
31/* 32/*
32 * If a non-root user executes a setuid-root binary in 33 * If a non-root user executes a setuid-root binary in
@@ -888,13 +889,17 @@ error:
888/** 889/**
889 * cap_syslog - Determine whether syslog function is permitted 890 * cap_syslog - Determine whether syslog function is permitted
890 * @type: Function requested 891 * @type: Function requested
892 * @from_file: Whether this request came from an open file (i.e. /proc)
891 * 893 *
892 * Determine whether the current process is permitted to use a particular 894 * Determine whether the current process is permitted to use a particular
893 * syslog function, returning 0 if permission is granted, -ve if not. 895 * syslog function, returning 0 if permission is granted, -ve if not.
894 */ 896 */
895int cap_syslog(int type) 897int cap_syslog(int type, bool from_file)
896{ 898{
897 if ((type != 3 && type != 10) && !capable(CAP_SYS_ADMIN)) 899 if (type != SYSLOG_ACTION_OPEN && from_file)
900 return 0;
901 if ((type != SYSLOG_ACTION_READ_ALL &&
902 type != SYSLOG_ACTION_SIZE_BUFFER) && !capable(CAP_SYS_ADMIN))
898 return -EPERM; 903 return -EPERM;
899 return 0; 904 return 0;
900} 905}
diff --git a/security/security.c b/security/security.c
index 122b748d0f4c..687c6fd14bb6 100644
--- a/security/security.c
+++ b/security/security.c
@@ -23,10 +23,12 @@ static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
23 CONFIG_DEFAULT_SECURITY; 23 CONFIG_DEFAULT_SECURITY;
24 24
25/* things that live in capability.c */ 25/* things that live in capability.c */
26extern struct security_operations default_security_ops;
27extern void security_fixup_ops(struct security_operations *ops); 26extern void security_fixup_ops(struct security_operations *ops);
28 27
29struct security_operations *security_ops; /* Initialized to NULL */ 28static struct security_operations *security_ops;
29static struct security_operations default_security_ops = {
30 .name = "default",
31};
30 32
31static inline int verify(struct security_operations *ops) 33static inline int verify(struct security_operations *ops)
32{ 34{
@@ -63,6 +65,11 @@ int __init security_init(void)
63 return 0; 65 return 0;
64} 66}
65 67
68void reset_security_ops(void)
69{
70 security_ops = &default_security_ops;
71}
72
66/* Save user chosen LSM */ 73/* Save user chosen LSM */
67static int __init choose_lsm(char *str) 74static int __init choose_lsm(char *str)
68{ 75{
@@ -203,9 +210,9 @@ int security_quota_on(struct dentry *dentry)
203 return security_ops->quota_on(dentry); 210 return security_ops->quota_on(dentry);
204} 211}
205 212
206int security_syslog(int type) 213int security_syslog(int type, bool from_file)
207{ 214{
208 return security_ops->syslog(type); 215 return security_ops->syslog(type, from_file);
209} 216}
210 217
211int security_settime(struct timespec *ts, struct timezone *tz) 218int security_settime(struct timespec *ts, struct timezone *tz)
@@ -389,42 +396,42 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
389EXPORT_SYMBOL(security_inode_init_security); 396EXPORT_SYMBOL(security_inode_init_security);
390 397
391#ifdef CONFIG_SECURITY_PATH 398#ifdef CONFIG_SECURITY_PATH
392int security_path_mknod(struct path *path, struct dentry *dentry, int mode, 399int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,
393 unsigned int dev) 400 unsigned int dev)
394{ 401{
395 if (unlikely(IS_PRIVATE(path->dentry->d_inode))) 402 if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
396 return 0; 403 return 0;
397 return security_ops->path_mknod(path, dentry, mode, dev); 404 return security_ops->path_mknod(dir, dentry, mode, dev);
398} 405}
399EXPORT_SYMBOL(security_path_mknod); 406EXPORT_SYMBOL(security_path_mknod);
400 407
401int security_path_mkdir(struct path *path, struct dentry *dentry, int mode) 408int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
402{ 409{
403 if (unlikely(IS_PRIVATE(path->dentry->d_inode))) 410 if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
404 return 0; 411 return 0;
405 return security_ops->path_mkdir(path, dentry, mode); 412 return security_ops->path_mkdir(dir, dentry, mode);
406} 413}
407 414
408int security_path_rmdir(struct path *path, struct dentry *dentry) 415int security_path_rmdir(struct path *dir, struct dentry *dentry)
409{ 416{
410 if (unlikely(IS_PRIVATE(path->dentry->d_inode))) 417 if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
411 return 0; 418 return 0;
412 return security_ops->path_rmdir(path, dentry); 419 return security_ops->path_rmdir(dir, dentry);
413} 420}
414 421
415int security_path_unlink(struct path *path, struct dentry *dentry) 422int security_path_unlink(struct path *dir, struct dentry *dentry)
416{ 423{
417 if (unlikely(IS_PRIVATE(path->dentry->d_inode))) 424 if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
418 return 0; 425 return 0;
419 return security_ops->path_unlink(path, dentry); 426 return security_ops->path_unlink(dir, dentry);
420} 427}
421 428
422int security_path_symlink(struct path *path, struct dentry *dentry, 429int security_path_symlink(struct path *dir, struct dentry *dentry,
423 const char *old_name) 430 const char *old_name)
424{ 431{
425 if (unlikely(IS_PRIVATE(path->dentry->d_inode))) 432 if (unlikely(IS_PRIVATE(dir->dentry->d_inode)))
426 return 0; 433 return 0;
427 return security_ops->path_symlink(path, dentry, old_name); 434 return security_ops->path_symlink(dir, dentry, old_name);
428} 435}
429 436
430int security_path_link(struct dentry *old_dentry, struct path *new_dir, 437int security_path_link(struct dentry *old_dentry, struct path *new_dir,
@@ -630,14 +637,14 @@ int security_inode_killpriv(struct dentry *dentry)
630int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc) 637int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc)
631{ 638{
632 if (unlikely(IS_PRIVATE(inode))) 639 if (unlikely(IS_PRIVATE(inode)))
633 return 0; 640 return -EOPNOTSUPP;
634 return security_ops->inode_getsecurity(inode, name, buffer, alloc); 641 return security_ops->inode_getsecurity(inode, name, buffer, alloc);
635} 642}
636 643
637int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) 644int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
638{ 645{
639 if (unlikely(IS_PRIVATE(inode))) 646 if (unlikely(IS_PRIVATE(inode)))
640 return 0; 647 return -EOPNOTSUPP;
641 return security_ops->inode_setsecurity(inode, name, value, size, flags); 648 return security_ops->inode_setsecurity(inode, name, value, size, flags);
642} 649}
643 650
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index f2dde268165a..db0fd9f33499 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -489,17 +489,14 @@ void avc_audit(u32 ssid, u32 tsid,
489 struct common_audit_data stack_data; 489 struct common_audit_data stack_data;
490 u32 denied, audited; 490 u32 denied, audited;
491 denied = requested & ~avd->allowed; 491 denied = requested & ~avd->allowed;
492 if (denied) { 492 if (denied)
493 audited = denied; 493 audited = denied & avd->auditdeny;
494 if (!(audited & avd->auditdeny)) 494 else if (result)
495 return;
496 } else if (result) {
497 audited = denied = requested; 495 audited = denied = requested;
498 } else { 496 else
499 audited = requested; 497 audited = requested & avd->auditallow;
500 if (!(audited & avd->auditallow)) 498 if (!audited)
501 return; 499 return;
502 }
503 if (!a) { 500 if (!a) {
504 a = &stack_data; 501 a = &stack_data;
505 memset(a, 0, sizeof(*a)); 502 memset(a, 0, sizeof(*a));
@@ -746,9 +743,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
746 else 743 else
747 avd = &avd_entry; 744 avd = &avd_entry;
748 745
749 rc = security_compute_av(ssid, tsid, tclass, requested, avd); 746 security_compute_av(ssid, tsid, tclass, avd);
750 if (rc)
751 goto out;
752 rcu_read_lock(); 747 rcu_read_lock();
753 node = avc_insert(ssid, tsid, tclass, avd); 748 node = avc_insert(ssid, tsid, tclass, avd);
754 } else { 749 } else {
@@ -770,7 +765,6 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
770 } 765 }
771 766
772 rcu_read_unlock(); 767 rcu_read_unlock();
773out:
774 return rc; 768 return rc;
775} 769}
776 770
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9a2ee845e9d4..5feecb41009d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -76,6 +76,7 @@
76#include <linux/selinux.h> 76#include <linux/selinux.h>
77#include <linux/mutex.h> 77#include <linux/mutex.h>
78#include <linux/posix-timers.h> 78#include <linux/posix-timers.h>
79#include <linux/syslog.h>
79 80
80#include "avc.h" 81#include "avc.h"
81#include "objsec.h" 82#include "objsec.h"
@@ -125,13 +126,6 @@ __setup("selinux=", selinux_enabled_setup);
125int selinux_enabled = 1; 126int selinux_enabled = 1;
126#endif 127#endif
127 128
128
129/*
130 * Minimal support for a secondary security module,
131 * just to allow the use of the capability module.
132 */
133static struct security_operations *secondary_ops;
134
135/* Lists of inode and superblock security structures initialized 129/* Lists of inode and superblock security structures initialized
136 before the policy was loaded. */ 130 before the policy was loaded. */
137static LIST_HEAD(superblock_security_head); 131static LIST_HEAD(superblock_security_head);
@@ -2049,29 +2043,30 @@ static int selinux_quota_on(struct dentry *dentry)
2049 return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON); 2043 return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON);
2050} 2044}
2051 2045
2052static int selinux_syslog(int type) 2046static int selinux_syslog(int type, bool from_file)
2053{ 2047{
2054 int rc; 2048 int rc;
2055 2049
2056 rc = cap_syslog(type); 2050 rc = cap_syslog(type, from_file);
2057 if (rc) 2051 if (rc)
2058 return rc; 2052 return rc;
2059 2053
2060 switch (type) { 2054 switch (type) {
2061 case 3: /* Read last kernel messages */ 2055 case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */
2062 case 10: /* Return size of the log buffer */ 2056 case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */
2063 rc = task_has_system(current, SYSTEM__SYSLOG_READ); 2057 rc = task_has_system(current, SYSTEM__SYSLOG_READ);
2064 break; 2058 break;
2065 case 6: /* Disable logging to console */ 2059 case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */
2066 case 7: /* Enable logging to console */ 2060 case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */
2067 case 8: /* Set level of messages printed to console */ 2061 /* Set level of messages printed to console */
2062 case SYSLOG_ACTION_CONSOLE_LEVEL:
2068 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); 2063 rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
2069 break; 2064 break;
2070 case 0: /* Close log */ 2065 case SYSLOG_ACTION_CLOSE: /* Close log */
2071 case 1: /* Open log */ 2066 case SYSLOG_ACTION_OPEN: /* Open log */
2072 case 2: /* Read from log */ 2067 case SYSLOG_ACTION_READ: /* Read from log */
2073 case 4: /* Read/clear last kernel messages */ 2068 case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */
2074 case 5: /* Clear ring buffer */ 2069 case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
2075 default: 2070 default:
2076 rc = task_has_system(current, SYSTEM__SYSLOG_MOD); 2071 rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
2077 break; 2072 break;
@@ -3334,7 +3329,7 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode)
3334 3329
3335 if (ret == 0) 3330 if (ret == 0)
3336 tsec->create_sid = isec->sid; 3331 tsec->create_sid = isec->sid;
3337 return 0; 3332 return ret;
3338} 3333}
3339 3334
3340static int selinux_kernel_module_request(char *kmod_name) 3335static int selinux_kernel_module_request(char *kmod_name)
@@ -5672,9 +5667,6 @@ static __init int selinux_init(void)
5672 0, SLAB_PANIC, NULL); 5667 0, SLAB_PANIC, NULL);
5673 avc_init(); 5668 avc_init();
5674 5669
5675 secondary_ops = security_ops;
5676 if (!secondary_ops)
5677 panic("SELinux: No initial security operations\n");
5678 if (register_security(&selinux_ops)) 5670 if (register_security(&selinux_ops))
5679 panic("SELinux: Unable to register with kernel.\n"); 5671 panic("SELinux: Unable to register with kernel.\n");
5680 5672
@@ -5835,8 +5827,7 @@ int selinux_disable(void)
5835 selinux_disabled = 1; 5827 selinux_disabled = 1;
5836 selinux_enabled = 0; 5828 selinux_enabled = 0;
5837 5829
5838 /* Reset security_ops to the secondary module, dummy or capability. */ 5830 reset_security_ops();
5839 security_ops = secondary_ops;
5840 5831
5841 /* Try to destroy the avc node cache */ 5832 /* Try to destroy the avc node cache */
5842 avc_disable(); 5833 avc_disable();
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 2553266ad793..1f7c2491d3dc 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -57,7 +57,6 @@
57struct netlbl_lsm_secattr; 57struct netlbl_lsm_secattr;
58 58
59extern int selinux_enabled; 59extern int selinux_enabled;
60extern int selinux_mls_enabled;
61 60
62/* Policy capabilities */ 61/* Policy capabilities */
63enum { 62enum {
@@ -80,6 +79,8 @@ extern int selinux_policycap_openperm;
80/* limitation of boundary depth */ 79/* limitation of boundary depth */
81#define POLICYDB_BOUNDS_MAXDEPTH 4 80#define POLICYDB_BOUNDS_MAXDEPTH 4
82 81
82int security_mls_enabled(void);
83
83int security_load_policy(void *data, size_t len); 84int security_load_policy(void *data, size_t len);
84 85
85int security_policycap_supported(unsigned int req_cap); 86int security_policycap_supported(unsigned int req_cap);
@@ -96,13 +97,11 @@ struct av_decision {
96/* definitions of av_decision.flags */ 97/* definitions of av_decision.flags */
97#define AVD_FLAGS_PERMISSIVE 0x0001 98#define AVD_FLAGS_PERMISSIVE 0x0001
98 99
99int security_compute_av(u32 ssid, u32 tsid, 100void security_compute_av(u32 ssid, u32 tsid,
100 u16 tclass, u32 requested, 101 u16 tclass, struct av_decision *avd);
101 struct av_decision *avd);
102 102
103int security_compute_av_user(u32 ssid, u32 tsid, 103void security_compute_av_user(u32 ssid, u32 tsid,
104 u16 tclass, u32 requested, 104 u16 tclass, struct av_decision *avd);
105 struct av_decision *avd);
106 105
107int security_transition_sid(u32 ssid, u32 tsid, 106int security_transition_sid(u32 ssid, u32 tsid,
108 u16 tclass, u32 *out_sid); 107 u16 tclass, u32 *out_sid);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index fab36fdf2769..cd191bbec03c 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -282,7 +282,8 @@ static ssize_t sel_read_mls(struct file *filp, char __user *buf,
282 char tmpbuf[TMPBUFLEN]; 282 char tmpbuf[TMPBUFLEN];
283 ssize_t length; 283 ssize_t length;
284 284
285 length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled); 285 length = scnprintf(tmpbuf, TMPBUFLEN, "%d",
286 security_mls_enabled());
286 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); 287 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
287} 288}
288 289
@@ -494,7 +495,6 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
494 char *scon, *tcon; 495 char *scon, *tcon;
495 u32 ssid, tsid; 496 u32 ssid, tsid;
496 u16 tclass; 497 u16 tclass;
497 u32 req;
498 struct av_decision avd; 498 struct av_decision avd;
499 ssize_t length; 499 ssize_t length;
500 500
@@ -512,7 +512,7 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
512 goto out; 512 goto out;
513 513
514 length = -EINVAL; 514 length = -EINVAL;
515 if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4) 515 if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
516 goto out2; 516 goto out2;
517 517
518 length = security_context_to_sid(scon, strlen(scon)+1, &ssid); 518 length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
@@ -522,9 +522,7 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
522 if (length < 0) 522 if (length < 0)
523 goto out2; 523 goto out2;
524 524
525 length = security_compute_av_user(ssid, tsid, tclass, req, &avd); 525 security_compute_av_user(ssid, tsid, tclass, &avd);
526 if (length < 0)
527 goto out2;
528 526
529 length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, 527 length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
530 "%x %x %x %x %u %x", 528 "%x %x %x %x %u %x",
@@ -979,6 +977,8 @@ static int sel_make_bools(void)
979 u32 sid; 977 u32 sid;
980 978
981 /* remove any existing files */ 979 /* remove any existing files */
980 for (i = 0; i < bool_num; i++)
981 kfree(bool_pending_names[i]);
982 kfree(bool_pending_names); 982 kfree(bool_pending_names);
983 kfree(bool_pending_values); 983 kfree(bool_pending_values);
984 bool_pending_names = NULL; 984 bool_pending_names = NULL;
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h
index d9dd7a2f6a8a..45e8fb0515f8 100644
--- a/security/selinux/ss/context.h
+++ b/security/selinux/ss/context.h
@@ -41,9 +41,6 @@ static inline int mls_context_cpy(struct context *dst, struct context *src)
41{ 41{
42 int rc; 42 int rc;
43 43
44 if (!selinux_mls_enabled)
45 return 0;
46
47 dst->range.level[0].sens = src->range.level[0].sens; 44 dst->range.level[0].sens = src->range.level[0].sens;
48 rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); 45 rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
49 if (rc) 46 if (rc)
@@ -64,9 +61,6 @@ static inline int mls_context_cpy_low(struct context *dst, struct context *src)
64{ 61{
65 int rc; 62 int rc;
66 63
67 if (!selinux_mls_enabled)
68 return 0;
69
70 dst->range.level[0].sens = src->range.level[0].sens; 64 dst->range.level[0].sens = src->range.level[0].sens;
71 rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); 65 rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
72 if (rc) 66 if (rc)
@@ -82,9 +76,6 @@ out:
82 76
83static inline int mls_context_cmp(struct context *c1, struct context *c2) 77static inline int mls_context_cmp(struct context *c1, struct context *c2)
84{ 78{
85 if (!selinux_mls_enabled)
86 return 1;
87
88 return ((c1->range.level[0].sens == c2->range.level[0].sens) && 79 return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
89 ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) && 80 ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) &&
90 (c1->range.level[1].sens == c2->range.level[1].sens) && 81 (c1->range.level[1].sens == c2->range.level[1].sens) &&
@@ -93,9 +84,6 @@ static inline int mls_context_cmp(struct context *c1, struct context *c2)
93 84
94static inline void mls_context_destroy(struct context *c) 85static inline void mls_context_destroy(struct context *c)
95{ 86{
96 if (!selinux_mls_enabled)
97 return;
98
99 ebitmap_destroy(&c->range.level[0].cat); 87 ebitmap_destroy(&c->range.level[0].cat);
100 ebitmap_destroy(&c->range.level[1].cat); 88 ebitmap_destroy(&c->range.level[1].cat);
101 mls_context_init(c); 89 mls_context_init(c);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 3f2b2706b5bb..372b773f8210 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -39,7 +39,7 @@ int mls_compute_context_len(struct context *context)
39 struct ebitmap *e; 39 struct ebitmap *e;
40 struct ebitmap_node *node; 40 struct ebitmap_node *node;
41 41
42 if (!selinux_mls_enabled) 42 if (!policydb.mls_enabled)
43 return 0; 43 return 0;
44 44
45 len = 1; /* for the beginning ":" */ 45 len = 1; /* for the beginning ":" */
@@ -93,7 +93,7 @@ void mls_sid_to_context(struct context *context,
93 struct ebitmap *e; 93 struct ebitmap *e;
94 struct ebitmap_node *node; 94 struct ebitmap_node *node;
95 95
96 if (!selinux_mls_enabled) 96 if (!policydb.mls_enabled)
97 return; 97 return;
98 98
99 scontextp = *scontext; 99 scontextp = *scontext;
@@ -200,7 +200,7 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
200{ 200{
201 struct user_datum *usrdatum; 201 struct user_datum *usrdatum;
202 202
203 if (!selinux_mls_enabled) 203 if (!p->mls_enabled)
204 return 1; 204 return 1;
205 205
206 if (!mls_range_isvalid(p, &c->range)) 206 if (!mls_range_isvalid(p, &c->range))
@@ -253,7 +253,7 @@ int mls_context_to_sid(struct policydb *pol,
253 struct cat_datum *catdatum, *rngdatum; 253 struct cat_datum *catdatum, *rngdatum;
254 int l, rc = -EINVAL; 254 int l, rc = -EINVAL;
255 255
256 if (!selinux_mls_enabled) { 256 if (!pol->mls_enabled) {
257 if (def_sid != SECSID_NULL && oldc) 257 if (def_sid != SECSID_NULL && oldc)
258 *scontext += strlen(*scontext)+1; 258 *scontext += strlen(*scontext)+1;
259 return 0; 259 return 0;
@@ -387,7 +387,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
387 char *tmpstr, *freestr; 387 char *tmpstr, *freestr;
388 int rc; 388 int rc;
389 389
390 if (!selinux_mls_enabled) 390 if (!policydb.mls_enabled)
391 return -EINVAL; 391 return -EINVAL;
392 392
393 /* we need freestr because mls_context_to_sid will change 393 /* we need freestr because mls_context_to_sid will change
@@ -407,7 +407,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
407/* 407/*
408 * Copies the MLS range `range' into `context'. 408 * Copies the MLS range `range' into `context'.
409 */ 409 */
410static inline int mls_range_set(struct context *context, 410int mls_range_set(struct context *context,
411 struct mls_range *range) 411 struct mls_range *range)
412{ 412{
413 int l, rc = 0; 413 int l, rc = 0;
@@ -427,7 +427,7 @@ static inline int mls_range_set(struct context *context,
427int mls_setup_user_range(struct context *fromcon, struct user_datum *user, 427int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
428 struct context *usercon) 428 struct context *usercon)
429{ 429{
430 if (selinux_mls_enabled) { 430 if (policydb.mls_enabled) {
431 struct mls_level *fromcon_sen = &(fromcon->range.level[0]); 431 struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
432 struct mls_level *fromcon_clr = &(fromcon->range.level[1]); 432 struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
433 struct mls_level *user_low = &(user->range.level[0]); 433 struct mls_level *user_low = &(user->range.level[0]);
@@ -477,7 +477,7 @@ int mls_convert_context(struct policydb *oldp,
477 struct ebitmap_node *node; 477 struct ebitmap_node *node;
478 int l, i; 478 int l, i;
479 479
480 if (!selinux_mls_enabled) 480 if (!policydb.mls_enabled)
481 return 0; 481 return 0;
482 482
483 for (l = 0; l < 2; l++) { 483 for (l = 0; l < 2; l++) {
@@ -513,23 +513,21 @@ int mls_compute_sid(struct context *scontext,
513 u32 specified, 513 u32 specified,
514 struct context *newcontext) 514 struct context *newcontext)
515{ 515{
516 struct range_trans *rtr; 516 struct range_trans rtr;
517 struct mls_range *r;
517 518
518 if (!selinux_mls_enabled) 519 if (!policydb.mls_enabled)
519 return 0; 520 return 0;
520 521
521 switch (specified) { 522 switch (specified) {
522 case AVTAB_TRANSITION: 523 case AVTAB_TRANSITION:
523 /* Look for a range transition rule. */ 524 /* Look for a range transition rule. */
524 for (rtr = policydb.range_tr; rtr; rtr = rtr->next) { 525 rtr.source_type = scontext->type;
525 if (rtr->source_type == scontext->type && 526 rtr.target_type = tcontext->type;
526 rtr->target_type == tcontext->type && 527 rtr.target_class = tclass;
527 rtr->target_class == tclass) { 528 r = hashtab_search(policydb.range_tr, &rtr);
528 /* Set the range from the rule */ 529 if (r)
529 return mls_range_set(newcontext, 530 return mls_range_set(newcontext, r);
530 &rtr->target_range);
531 }
532 }
533 /* Fallthrough */ 531 /* Fallthrough */
534 case AVTAB_CHANGE: 532 case AVTAB_CHANGE:
535 if (tclass == policydb.process_class) 533 if (tclass == policydb.process_class)
@@ -541,8 +539,8 @@ int mls_compute_sid(struct context *scontext,
541 case AVTAB_MEMBER: 539 case AVTAB_MEMBER:
542 /* Use the process effective MLS attributes. */ 540 /* Use the process effective MLS attributes. */
543 return mls_context_cpy_low(newcontext, scontext); 541 return mls_context_cpy_low(newcontext, scontext);
544 default: 542
545 return -EINVAL; 543 /* fall through */
546 } 544 }
547 return -EINVAL; 545 return -EINVAL;
548} 546}
@@ -561,7 +559,7 @@ int mls_compute_sid(struct context *scontext,
561void mls_export_netlbl_lvl(struct context *context, 559void mls_export_netlbl_lvl(struct context *context,
562 struct netlbl_lsm_secattr *secattr) 560 struct netlbl_lsm_secattr *secattr)
563{ 561{
564 if (!selinux_mls_enabled) 562 if (!policydb.mls_enabled)
565 return; 563 return;
566 564
567 secattr->attr.mls.lvl = context->range.level[0].sens - 1; 565 secattr->attr.mls.lvl = context->range.level[0].sens - 1;
@@ -581,7 +579,7 @@ void mls_export_netlbl_lvl(struct context *context,
581void mls_import_netlbl_lvl(struct context *context, 579void mls_import_netlbl_lvl(struct context *context,
582 struct netlbl_lsm_secattr *secattr) 580 struct netlbl_lsm_secattr *secattr)
583{ 581{
584 if (!selinux_mls_enabled) 582 if (!policydb.mls_enabled)
585 return; 583 return;
586 584
587 context->range.level[0].sens = secattr->attr.mls.lvl + 1; 585 context->range.level[0].sens = secattr->attr.mls.lvl + 1;
@@ -603,7 +601,7 @@ int mls_export_netlbl_cat(struct context *context,
603{ 601{
604 int rc; 602 int rc;
605 603
606 if (!selinux_mls_enabled) 604 if (!policydb.mls_enabled)
607 return 0; 605 return 0;
608 606
609 rc = ebitmap_netlbl_export(&context->range.level[0].cat, 607 rc = ebitmap_netlbl_export(&context->range.level[0].cat,
@@ -631,7 +629,7 @@ int mls_import_netlbl_cat(struct context *context,
631{ 629{
632 int rc; 630 int rc;
633 631
634 if (!selinux_mls_enabled) 632 if (!policydb.mls_enabled)
635 return 0; 633 return 0;
636 634
637 rc = ebitmap_netlbl_import(&context->range.level[0].cat, 635 rc = ebitmap_netlbl_import(&context->range.level[0].cat,
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index 1276715aaa8b..cd9152632e54 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -39,6 +39,8 @@ int mls_context_to_sid(struct policydb *p,
39 39
40int mls_from_string(char *str, struct context *context, gfp_t gfp_mask); 40int mls_from_string(char *str, struct context *context, gfp_t gfp_mask);
41 41
42int mls_range_set(struct context *context, struct mls_range *range);
43
42int mls_convert_context(struct policydb *oldp, 44int mls_convert_context(struct policydb *oldp,
43 struct policydb *newp, 45 struct policydb *newp,
44 struct context *context); 46 struct context *context);
diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h
index b6e943a21061..03bed52a8052 100644
--- a/security/selinux/ss/mls_types.h
+++ b/security/selinux/ss/mls_types.h
@@ -15,6 +15,7 @@
15#define _SS_MLS_TYPES_H_ 15#define _SS_MLS_TYPES_H_
16 16
17#include "security.h" 17#include "security.h"
18#include "ebitmap.h"
18 19
19struct mls_level { 20struct mls_level {
20 u32 sens; /* sensitivity */ 21 u32 sens; /* sensitivity */
@@ -27,18 +28,12 @@ struct mls_range {
27 28
28static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2) 29static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
29{ 30{
30 if (!selinux_mls_enabled)
31 return 1;
32
33 return ((l1->sens == l2->sens) && 31 return ((l1->sens == l2->sens) &&
34 ebitmap_cmp(&l1->cat, &l2->cat)); 32 ebitmap_cmp(&l1->cat, &l2->cat));
35} 33}
36 34
37static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2) 35static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
38{ 36{
39 if (!selinux_mls_enabled)
40 return 1;
41
42 return ((l1->sens >= l2->sens) && 37 return ((l1->sens >= l2->sens) &&
43 ebitmap_contains(&l1->cat, &l2->cat)); 38 ebitmap_contains(&l1->cat, &l2->cat));
44} 39}
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index f03667213ea8..23c6e53c102c 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -52,8 +52,6 @@ static char *symtab_name[SYM_NUM] = {
52}; 52};
53#endif 53#endif
54 54
55int selinux_mls_enabled;
56
57static unsigned int symtab_sizes[SYM_NUM] = { 55static unsigned int symtab_sizes[SYM_NUM] = {
58 2, 56 2,
59 32, 57 32,
@@ -177,6 +175,21 @@ out_free_role:
177 goto out; 175 goto out;
178} 176}
179 177
178static u32 rangetr_hash(struct hashtab *h, const void *k)
179{
180 const struct range_trans *key = k;
181 return (key->source_type + (key->target_type << 3) +
182 (key->target_class << 5)) & (h->size - 1);
183}
184
185static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
186{
187 const struct range_trans *key1 = k1, *key2 = k2;
188 return (key1->source_type != key2->source_type ||
189 key1->target_type != key2->target_type ||
190 key1->target_class != key2->target_class);
191}
192
180/* 193/*
181 * Initialize a policy database structure. 194 * Initialize a policy database structure.
182 */ 195 */
@@ -204,6 +217,10 @@ static int policydb_init(struct policydb *p)
204 if (rc) 217 if (rc)
205 goto out_free_symtab; 218 goto out_free_symtab;
206 219
220 p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256);
221 if (!p->range_tr)
222 goto out_free_symtab;
223
207 ebitmap_init(&p->policycaps); 224 ebitmap_init(&p->policycaps);
208 ebitmap_init(&p->permissive_map); 225 ebitmap_init(&p->permissive_map);
209 226
@@ -408,6 +425,20 @@ static void symtab_hash_eval(struct symtab *s)
408 info.slots_used, h->size, info.max_chain_len); 425 info.slots_used, h->size, info.max_chain_len);
409 } 426 }
410} 427}
428
429static void rangetr_hash_eval(struct hashtab *h)
430{
431 struct hashtab_info info;
432
433 hashtab_stat(h, &info);
434 printk(KERN_DEBUG "SELinux: rangetr: %d entries and %d/%d buckets used, "
435 "longest chain length %d\n", h->nel,
436 info.slots_used, h->size, info.max_chain_len);
437}
438#else
439static inline void rangetr_hash_eval(struct hashtab *h)
440{
441}
411#endif 442#endif
412 443
413/* 444/*
@@ -422,7 +453,7 @@ static int policydb_index_others(struct policydb *p)
422 453
423 printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools", 454 printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools",
424 p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); 455 p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
425 if (selinux_mls_enabled) 456 if (p->mls_enabled)
426 printk(", %d sens, %d cats", p->p_levels.nprim, 457 printk(", %d sens, %d cats", p->p_levels.nprim,
427 p->p_cats.nprim); 458 p->p_cats.nprim);
428 printk("\n"); 459 printk("\n");
@@ -612,6 +643,17 @@ static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
612 cat_destroy, 643 cat_destroy,
613}; 644};
614 645
646static int range_tr_destroy(void *key, void *datum, void *p)
647{
648 struct mls_range *rt = datum;
649 kfree(key);
650 ebitmap_destroy(&rt->level[0].cat);
651 ebitmap_destroy(&rt->level[1].cat);
652 kfree(datum);
653 cond_resched();
654 return 0;
655}
656
615static void ocontext_destroy(struct ocontext *c, int i) 657static void ocontext_destroy(struct ocontext *c, int i)
616{ 658{
617 context_destroy(&c->context[0]); 659 context_destroy(&c->context[0]);
@@ -632,7 +674,6 @@ void policydb_destroy(struct policydb *p)
632 int i; 674 int i;
633 struct role_allow *ra, *lra = NULL; 675 struct role_allow *ra, *lra = NULL;
634 struct role_trans *tr, *ltr = NULL; 676 struct role_trans *tr, *ltr = NULL;
635 struct range_trans *rt, *lrt = NULL;
636 677
637 for (i = 0; i < SYM_NUM; i++) { 678 for (i = 0; i < SYM_NUM; i++) {
638 cond_resched(); 679 cond_resched();
@@ -693,20 +734,8 @@ void policydb_destroy(struct policydb *p)
693 } 734 }
694 kfree(lra); 735 kfree(lra);
695 736
696 for (rt = p->range_tr; rt; rt = rt->next) { 737 hashtab_map(p->range_tr, range_tr_destroy, NULL);
697 cond_resched(); 738 hashtab_destroy(p->range_tr);
698 if (lrt) {
699 ebitmap_destroy(&lrt->target_range.level[0].cat);
700 ebitmap_destroy(&lrt->target_range.level[1].cat);
701 kfree(lrt);
702 }
703 lrt = rt;
704 }
705 if (lrt) {
706 ebitmap_destroy(&lrt->target_range.level[0].cat);
707 ebitmap_destroy(&lrt->target_range.level[1].cat);
708 kfree(lrt);
709 }
710 739
711 if (p->type_attr_map) { 740 if (p->type_attr_map) {
712 for (i = 0; i < p->p_types.nprim; i++) 741 for (i = 0; i < p->p_types.nprim; i++)
@@ -1686,12 +1715,11 @@ int policydb_read(struct policydb *p, void *fp)
1686 int i, j, rc; 1715 int i, j, rc;
1687 __le32 buf[4]; 1716 __le32 buf[4];
1688 u32 nodebuf[8]; 1717 u32 nodebuf[8];
1689 u32 len, len2, config, nprim, nel, nel2; 1718 u32 len, len2, nprim, nel, nel2;
1690 char *policydb_str; 1719 char *policydb_str;
1691 struct policydb_compat_info *info; 1720 struct policydb_compat_info *info;
1692 struct range_trans *rt, *lrt; 1721 struct range_trans *rt;
1693 1722 struct mls_range *r;
1694 config = 0;
1695 1723
1696 rc = policydb_init(p); 1724 rc = policydb_init(p);
1697 if (rc) 1725 if (rc)
@@ -1740,7 +1768,7 @@ int policydb_read(struct policydb *p, void *fp)
1740 kfree(policydb_str); 1768 kfree(policydb_str);
1741 policydb_str = NULL; 1769 policydb_str = NULL;
1742 1770
1743 /* Read the version, config, and table sizes. */ 1771 /* Read the version and table sizes. */
1744 rc = next_entry(buf, fp, sizeof(u32)*4); 1772 rc = next_entry(buf, fp, sizeof(u32)*4);
1745 if (rc < 0) 1773 if (rc < 0)
1746 goto bad; 1774 goto bad;
@@ -1755,13 +1783,7 @@ int policydb_read(struct policydb *p, void *fp)
1755 } 1783 }
1756 1784
1757 if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { 1785 if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) {
1758 if (ss_initialized && !selinux_mls_enabled) { 1786 p->mls_enabled = 1;
1759 printk(KERN_ERR "SELinux: Cannot switch between non-MLS"
1760 " and MLS policies\n");
1761 goto bad;
1762 }
1763 selinux_mls_enabled = 1;
1764 config |= POLICYDB_CONFIG_MLS;
1765 1787
1766 if (p->policyvers < POLICYDB_VERSION_MLS) { 1788 if (p->policyvers < POLICYDB_VERSION_MLS) {
1767 printk(KERN_ERR "SELinux: security policydb version %d " 1789 printk(KERN_ERR "SELinux: security policydb version %d "
@@ -1769,12 +1791,6 @@ int policydb_read(struct policydb *p, void *fp)
1769 p->policyvers); 1791 p->policyvers);
1770 goto bad; 1792 goto bad;
1771 } 1793 }
1772 } else {
1773 if (ss_initialized && selinux_mls_enabled) {
1774 printk(KERN_ERR "SELinux: Cannot switch between MLS and"
1775 " non-MLS policies\n");
1776 goto bad;
1777 }
1778 } 1794 }
1779 p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); 1795 p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
1780 p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); 1796 p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
@@ -2122,44 +2138,61 @@ int policydb_read(struct policydb *p, void *fp)
2122 if (rc < 0) 2138 if (rc < 0)
2123 goto bad; 2139 goto bad;
2124 nel = le32_to_cpu(buf[0]); 2140 nel = le32_to_cpu(buf[0]);
2125 lrt = NULL;
2126 for (i = 0; i < nel; i++) { 2141 for (i = 0; i < nel; i++) {
2127 rt = kzalloc(sizeof(*rt), GFP_KERNEL); 2142 rt = kzalloc(sizeof(*rt), GFP_KERNEL);
2128 if (!rt) { 2143 if (!rt) {
2129 rc = -ENOMEM; 2144 rc = -ENOMEM;
2130 goto bad; 2145 goto bad;
2131 } 2146 }
2132 if (lrt)
2133 lrt->next = rt;
2134 else
2135 p->range_tr = rt;
2136 rc = next_entry(buf, fp, (sizeof(u32) * 2)); 2147 rc = next_entry(buf, fp, (sizeof(u32) * 2));
2137 if (rc < 0) 2148 if (rc < 0) {
2149 kfree(rt);
2138 goto bad; 2150 goto bad;
2151 }
2139 rt->source_type = le32_to_cpu(buf[0]); 2152 rt->source_type = le32_to_cpu(buf[0]);
2140 rt->target_type = le32_to_cpu(buf[1]); 2153 rt->target_type = le32_to_cpu(buf[1]);
2141 if (new_rangetr) { 2154 if (new_rangetr) {
2142 rc = next_entry(buf, fp, sizeof(u32)); 2155 rc = next_entry(buf, fp, sizeof(u32));
2143 if (rc < 0) 2156 if (rc < 0) {
2157 kfree(rt);
2144 goto bad; 2158 goto bad;
2159 }
2145 rt->target_class = le32_to_cpu(buf[0]); 2160 rt->target_class = le32_to_cpu(buf[0]);
2146 } else 2161 } else
2147 rt->target_class = p->process_class; 2162 rt->target_class = p->process_class;
2148 if (!policydb_type_isvalid(p, rt->source_type) || 2163 if (!policydb_type_isvalid(p, rt->source_type) ||
2149 !policydb_type_isvalid(p, rt->target_type) || 2164 !policydb_type_isvalid(p, rt->target_type) ||
2150 !policydb_class_isvalid(p, rt->target_class)) { 2165 !policydb_class_isvalid(p, rt->target_class)) {
2166 kfree(rt);
2151 rc = -EINVAL; 2167 rc = -EINVAL;
2152 goto bad; 2168 goto bad;
2153 } 2169 }
2154 rc = mls_read_range_helper(&rt->target_range, fp); 2170 r = kzalloc(sizeof(*r), GFP_KERNEL);
2155 if (rc) 2171 if (!r) {
2172 kfree(rt);
2173 rc = -ENOMEM;
2156 goto bad; 2174 goto bad;
2157 if (!mls_range_isvalid(p, &rt->target_range)) { 2175 }
2176 rc = mls_read_range_helper(r, fp);
2177 if (rc) {
2178 kfree(rt);
2179 kfree(r);
2180 goto bad;
2181 }
2182 if (!mls_range_isvalid(p, r)) {
2158 printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); 2183 printk(KERN_WARNING "SELinux: rangetrans: invalid range\n");
2184 kfree(rt);
2185 kfree(r);
2186 goto bad;
2187 }
2188 rc = hashtab_insert(p->range_tr, rt, r);
2189 if (rc) {
2190 kfree(rt);
2191 kfree(r);
2159 goto bad; 2192 goto bad;
2160 } 2193 }
2161 lrt = rt;
2162 } 2194 }
2195 rangetr_hash_eval(p->range_tr);
2163 } 2196 }
2164 2197
2165 p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); 2198 p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL);
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index cdcc5700946f..26d9adf8542b 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -27,6 +27,8 @@
27#include "symtab.h" 27#include "symtab.h"
28#include "avtab.h" 28#include "avtab.h"
29#include "sidtab.h" 29#include "sidtab.h"
30#include "ebitmap.h"
31#include "mls_types.h"
30#include "context.h" 32#include "context.h"
31#include "constraint.h" 33#include "constraint.h"
32 34
@@ -113,8 +115,6 @@ struct range_trans {
113 u32 source_type; 115 u32 source_type;
114 u32 target_type; 116 u32 target_type;
115 u32 target_class; 117 u32 target_class;
116 struct mls_range target_range;
117 struct range_trans *next;
118}; 118};
119 119
120/* Boolean data type */ 120/* Boolean data type */
@@ -187,6 +187,8 @@ struct genfs {
187 187
188/* The policy database */ 188/* The policy database */
189struct policydb { 189struct policydb {
190 int mls_enabled;
191
190 /* symbol tables */ 192 /* symbol tables */
191 struct symtab symtab[SYM_NUM]; 193 struct symtab symtab[SYM_NUM];
192#define p_commons symtab[SYM_COMMONS] 194#define p_commons symtab[SYM_COMMONS]
@@ -240,8 +242,8 @@ struct policydb {
240 fixed labeling behavior. */ 242 fixed labeling behavior. */
241 struct genfs *genfs; 243 struct genfs *genfs;
242 244
243 /* range transitions */ 245 /* range transitions table (range_trans_key -> mls_range) */
244 struct range_trans *range_tr; 246 struct hashtab *range_tr;
245 247
246 /* type -> attribute reverse mapping */ 248 /* type -> attribute reverse mapping */
247 struct ebitmap *type_attr_map; 249 struct ebitmap *type_attr_map;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index b3efae204ac7..cf27b3ee1a95 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -26,6 +26,10 @@
26 * 26 *
27 * Added support for bounds domain and audit messaged on masked permissions 27 * Added support for bounds domain and audit messaged on masked permissions
28 * 28 *
29 * Updated: Guido Trentalancia <guido@trentalancia.com>
30 *
31 * Added support for runtime switching of the policy type
32 *
29 * Copyright (C) 2008, 2009 NEC Corporation 33 * Copyright (C) 2008, 2009 NEC Corporation
30 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. 34 * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
31 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. 35 * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
@@ -87,11 +91,10 @@ static u32 latest_granting;
87static int context_struct_to_string(struct context *context, char **scontext, 91static int context_struct_to_string(struct context *context, char **scontext,
88 u32 *scontext_len); 92 u32 *scontext_len);
89 93
90static int context_struct_compute_av(struct context *scontext, 94static void context_struct_compute_av(struct context *scontext,
91 struct context *tcontext, 95 struct context *tcontext,
92 u16 tclass, 96 u16 tclass,
93 u32 requested, 97 struct av_decision *avd);
94 struct av_decision *avd);
95 98
96struct selinux_mapping { 99struct selinux_mapping {
97 u16 value; /* policy value */ 100 u16 value; /* policy value */
@@ -196,23 +199,6 @@ static u16 unmap_class(u16 tclass)
196 return tclass; 199 return tclass;
197} 200}
198 201
199static u32 unmap_perm(u16 tclass, u32 tperm)
200{
201 if (tclass < current_mapping_size) {
202 unsigned i;
203 u32 kperm = 0;
204
205 for (i = 0; i < current_mapping[tclass].num_perms; i++)
206 if (tperm & (1<<i)) {
207 kperm |= current_mapping[tclass].perms[i];
208 tperm &= ~(1<<i);
209 }
210 return kperm;
211 }
212
213 return tperm;
214}
215
216static void map_decision(u16 tclass, struct av_decision *avd, 202static void map_decision(u16 tclass, struct av_decision *avd,
217 int allow_unknown) 203 int allow_unknown)
218{ 204{
@@ -250,6 +236,10 @@ static void map_decision(u16 tclass, struct av_decision *avd,
250 } 236 }
251} 237}
252 238
239int security_mls_enabled(void)
240{
241 return policydb.mls_enabled;
242}
253 243
254/* 244/*
255 * Return the boolean value of a constraint expression 245 * Return the boolean value of a constraint expression
@@ -465,7 +455,8 @@ static void security_dump_masked_av(struct context *scontext,
465 char *scontext_name = NULL; 455 char *scontext_name = NULL;
466 char *tcontext_name = NULL; 456 char *tcontext_name = NULL;
467 char *permission_names[32]; 457 char *permission_names[32];
468 int index, length; 458 int index;
459 u32 length;
469 bool need_comma = false; 460 bool need_comma = false;
470 461
471 if (!permissions) 462 if (!permissions)
@@ -532,7 +523,6 @@ out:
532static void type_attribute_bounds_av(struct context *scontext, 523static void type_attribute_bounds_av(struct context *scontext,
533 struct context *tcontext, 524 struct context *tcontext,
534 u16 tclass, 525 u16 tclass,
535 u32 requested,
536 struct av_decision *avd) 526 struct av_decision *avd)
537{ 527{
538 struct context lo_scontext; 528 struct context lo_scontext;
@@ -553,7 +543,6 @@ static void type_attribute_bounds_av(struct context *scontext,
553 context_struct_compute_av(&lo_scontext, 543 context_struct_compute_av(&lo_scontext,
554 tcontext, 544 tcontext,
555 tclass, 545 tclass,
556 requested,
557 &lo_avd); 546 &lo_avd);
558 if ((lo_avd.allowed & avd->allowed) == avd->allowed) 547 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
559 return; /* no masked permission */ 548 return; /* no masked permission */
@@ -569,7 +558,6 @@ static void type_attribute_bounds_av(struct context *scontext,
569 context_struct_compute_av(scontext, 558 context_struct_compute_av(scontext,
570 &lo_tcontext, 559 &lo_tcontext,
571 tclass, 560 tclass,
572 requested,
573 &lo_avd); 561 &lo_avd);
574 if ((lo_avd.allowed & avd->allowed) == avd->allowed) 562 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
575 return; /* no masked permission */ 563 return; /* no masked permission */
@@ -586,7 +574,6 @@ static void type_attribute_bounds_av(struct context *scontext,
586 context_struct_compute_av(&lo_scontext, 574 context_struct_compute_av(&lo_scontext,
587 &lo_tcontext, 575 &lo_tcontext,
588 tclass, 576 tclass,
589 requested,
590 &lo_avd); 577 &lo_avd);
591 if ((lo_avd.allowed & avd->allowed) == avd->allowed) 578 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
592 return; /* no masked permission */ 579 return; /* no masked permission */
@@ -607,11 +594,10 @@ static void type_attribute_bounds_av(struct context *scontext,
607 * Compute access vectors based on a context structure pair for 594 * Compute access vectors based on a context structure pair for
608 * the permissions in a particular class. 595 * the permissions in a particular class.
609 */ 596 */
610static int context_struct_compute_av(struct context *scontext, 597static void context_struct_compute_av(struct context *scontext,
611 struct context *tcontext, 598 struct context *tcontext,
612 u16 tclass, 599 u16 tclass,
613 u32 requested, 600 struct av_decision *avd)
614 struct av_decision *avd)
615{ 601{
616 struct constraint_node *constraint; 602 struct constraint_node *constraint;
617 struct role_allow *ra; 603 struct role_allow *ra;
@@ -622,19 +608,14 @@ static int context_struct_compute_av(struct context *scontext,
622 struct ebitmap_node *snode, *tnode; 608 struct ebitmap_node *snode, *tnode;
623 unsigned int i, j; 609 unsigned int i, j;
624 610
625 /*
626 * Initialize the access vectors to the default values.
627 */
628 avd->allowed = 0; 611 avd->allowed = 0;
629 avd->auditallow = 0; 612 avd->auditallow = 0;
630 avd->auditdeny = 0xffffffff; 613 avd->auditdeny = 0xffffffff;
631 avd->seqno = latest_granting;
632 avd->flags = 0;
633 614
634 if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { 615 if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) {
635 if (printk_ratelimit()) 616 if (printk_ratelimit())
636 printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass); 617 printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass);
637 return -EINVAL; 618 return;
638 } 619 }
639 620
640 tclass_datum = policydb.class_val_to_struct[tclass - 1]; 621 tclass_datum = policydb.class_val_to_struct[tclass - 1];
@@ -705,9 +686,7 @@ static int context_struct_compute_av(struct context *scontext,
705 * permission and notice it to userspace via audit. 686 * permission and notice it to userspace via audit.
706 */ 687 */
707 type_attribute_bounds_av(scontext, tcontext, 688 type_attribute_bounds_av(scontext, tcontext,
708 tclass, requested, avd); 689 tclass, avd);
709
710 return 0;
711} 690}
712 691
713static int security_validtrans_handle_fail(struct context *ocontext, 692static int security_validtrans_handle_fail(struct context *ocontext,
@@ -864,7 +843,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
864 if (rc) { 843 if (rc) {
865 char *old_name = NULL; 844 char *old_name = NULL;
866 char *new_name = NULL; 845 char *new_name = NULL;
867 int length; 846 u32 length;
868 847
869 if (!context_struct_to_string(old_context, 848 if (!context_struct_to_string(old_context,
870 &old_name, &length) && 849 &old_name, &length) &&
@@ -886,110 +865,116 @@ out:
886 return rc; 865 return rc;
887} 866}
888 867
889 868static void avd_init(struct av_decision *avd)
890static int security_compute_av_core(u32 ssid,
891 u32 tsid,
892 u16 tclass,
893 u32 requested,
894 struct av_decision *avd)
895{ 869{
896 struct context *scontext = NULL, *tcontext = NULL; 870 avd->allowed = 0;
897 int rc = 0; 871 avd->auditallow = 0;
898 872 avd->auditdeny = 0xffffffff;
899 scontext = sidtab_search(&sidtab, ssid); 873 avd->seqno = latest_granting;
900 if (!scontext) { 874 avd->flags = 0;
901 printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
902 __func__, ssid);
903 return -EINVAL;
904 }
905 tcontext = sidtab_search(&sidtab, tsid);
906 if (!tcontext) {
907 printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
908 __func__, tsid);
909 return -EINVAL;
910 }
911
912 rc = context_struct_compute_av(scontext, tcontext, tclass,
913 requested, avd);
914
915 /* permissive domain? */
916 if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
917 avd->flags |= AVD_FLAGS_PERMISSIVE;
918
919 return rc;
920} 875}
921 876
877
922/** 878/**
923 * security_compute_av - Compute access vector decisions. 879 * security_compute_av - Compute access vector decisions.
924 * @ssid: source security identifier 880 * @ssid: source security identifier
925 * @tsid: target security identifier 881 * @tsid: target security identifier
926 * @tclass: target security class 882 * @tclass: target security class
927 * @requested: requested permissions
928 * @avd: access vector decisions 883 * @avd: access vector decisions
929 * 884 *
930 * Compute a set of access vector decisions based on the 885 * Compute a set of access vector decisions based on the
931 * SID pair (@ssid, @tsid) for the permissions in @tclass. 886 * SID pair (@ssid, @tsid) for the permissions in @tclass.
932 * Return -%EINVAL if any of the parameters are invalid or %0
933 * if the access vector decisions were computed successfully.
934 */ 887 */
935int security_compute_av(u32 ssid, 888void security_compute_av(u32 ssid,
936 u32 tsid, 889 u32 tsid,
937 u16 orig_tclass, 890 u16 orig_tclass,
938 u32 orig_requested, 891 struct av_decision *avd)
939 struct av_decision *avd)
940{ 892{
941 u16 tclass; 893 u16 tclass;
942 u32 requested; 894 struct context *scontext = NULL, *tcontext = NULL;
943 int rc;
944 895
945 read_lock(&policy_rwlock); 896 read_lock(&policy_rwlock);
946 897 avd_init(avd);
947 if (!ss_initialized) 898 if (!ss_initialized)
948 goto allow; 899 goto allow;
949 900
950 requested = unmap_perm(orig_tclass, orig_requested); 901 scontext = sidtab_search(&sidtab, ssid);
902 if (!scontext) {
903 printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
904 __func__, ssid);
905 goto out;
906 }
907
908 /* permissive domain? */
909 if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
910 avd->flags |= AVD_FLAGS_PERMISSIVE;
911
912 tcontext = sidtab_search(&sidtab, tsid);
913 if (!tcontext) {
914 printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
915 __func__, tsid);
916 goto out;
917 }
918
951 tclass = unmap_class(orig_tclass); 919 tclass = unmap_class(orig_tclass);
952 if (unlikely(orig_tclass && !tclass)) { 920 if (unlikely(orig_tclass && !tclass)) {
953 if (policydb.allow_unknown) 921 if (policydb.allow_unknown)
954 goto allow; 922 goto allow;
955 rc = -EINVAL;
956 goto out; 923 goto out;
957 } 924 }
958 rc = security_compute_av_core(ssid, tsid, tclass, requested, avd); 925 context_struct_compute_av(scontext, tcontext, tclass, avd);
959 map_decision(orig_tclass, avd, policydb.allow_unknown); 926 map_decision(orig_tclass, avd, policydb.allow_unknown);
960out: 927out:
961 read_unlock(&policy_rwlock); 928 read_unlock(&policy_rwlock);
962 return rc; 929 return;
963allow: 930allow:
964 avd->allowed = 0xffffffff; 931 avd->allowed = 0xffffffff;
965 avd->auditallow = 0;
966 avd->auditdeny = 0xffffffff;
967 avd->seqno = latest_granting;
968 avd->flags = 0;
969 rc = 0;
970 goto out; 932 goto out;
971} 933}
972 934
973int security_compute_av_user(u32 ssid, 935void security_compute_av_user(u32 ssid,
974 u32 tsid, 936 u32 tsid,
975 u16 tclass, 937 u16 tclass,
976 u32 requested, 938 struct av_decision *avd)
977 struct av_decision *avd)
978{ 939{
979 int rc; 940 struct context *scontext = NULL, *tcontext = NULL;
980 941
981 if (!ss_initialized) { 942 read_lock(&policy_rwlock);
982 avd->allowed = 0xffffffff; 943 avd_init(avd);
983 avd->auditallow = 0; 944 if (!ss_initialized)
984 avd->auditdeny = 0xffffffff; 945 goto allow;
985 avd->seqno = latest_granting; 946
986 return 0; 947 scontext = sidtab_search(&sidtab, ssid);
948 if (!scontext) {
949 printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
950 __func__, ssid);
951 goto out;
987 } 952 }
988 953
989 read_lock(&policy_rwlock); 954 /* permissive domain? */
990 rc = security_compute_av_core(ssid, tsid, tclass, requested, avd); 955 if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
956 avd->flags |= AVD_FLAGS_PERMISSIVE;
957
958 tcontext = sidtab_search(&sidtab, tsid);
959 if (!tcontext) {
960 printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
961 __func__, tsid);
962 goto out;
963 }
964
965 if (unlikely(!tclass)) {
966 if (policydb.allow_unknown)
967 goto allow;
968 goto out;
969 }
970
971 context_struct_compute_av(scontext, tcontext, tclass, avd);
972 out:
991 read_unlock(&policy_rwlock); 973 read_unlock(&policy_rwlock);
992 return rc; 974 return;
975allow:
976 avd->allowed = 0xffffffff;
977 goto out;
993} 978}
994 979
995/* 980/*
@@ -1565,7 +1550,10 @@ static int clone_sid(u32 sid,
1565{ 1550{
1566 struct sidtab *s = arg; 1551 struct sidtab *s = arg;
1567 1552
1568 return sidtab_insert(s, sid, context); 1553 if (sid > SECINITSID_NUM)
1554 return sidtab_insert(s, sid, context);
1555 else
1556 return 0;
1569} 1557}
1570 1558
1571static inline int convert_context_handle_invalid_context(struct context *context) 1559static inline int convert_context_handle_invalid_context(struct context *context)
@@ -1606,12 +1594,17 @@ static int convert_context(u32 key,
1606{ 1594{
1607 struct convert_context_args *args; 1595 struct convert_context_args *args;
1608 struct context oldc; 1596 struct context oldc;
1597 struct ocontext *oc;
1598 struct mls_range *range;
1609 struct role_datum *role; 1599 struct role_datum *role;
1610 struct type_datum *typdatum; 1600 struct type_datum *typdatum;
1611 struct user_datum *usrdatum; 1601 struct user_datum *usrdatum;
1612 char *s; 1602 char *s;
1613 u32 len; 1603 u32 len;
1614 int rc; 1604 int rc = 0;
1605
1606 if (key <= SECINITSID_NUM)
1607 goto out;
1615 1608
1616 args = p; 1609 args = p;
1617 1610
@@ -1673,9 +1666,39 @@ static int convert_context(u32 key,
1673 goto bad; 1666 goto bad;
1674 c->type = typdatum->value; 1667 c->type = typdatum->value;
1675 1668
1676 rc = mls_convert_context(args->oldp, args->newp, c); 1669 /* Convert the MLS fields if dealing with MLS policies */
1677 if (rc) 1670 if (args->oldp->mls_enabled && args->newp->mls_enabled) {
1678 goto bad; 1671 rc = mls_convert_context(args->oldp, args->newp, c);
1672 if (rc)
1673 goto bad;
1674 } else if (args->oldp->mls_enabled && !args->newp->mls_enabled) {
1675 /*
1676 * Switching between MLS and non-MLS policy:
1677 * free any storage used by the MLS fields in the
1678 * context for all existing entries in the sidtab.
1679 */
1680 mls_context_destroy(c);
1681 } else if (!args->oldp->mls_enabled && args->newp->mls_enabled) {
1682 /*
1683 * Switching between non-MLS and MLS policy:
1684 * ensure that the MLS fields of the context for all
1685 * existing entries in the sidtab are filled in with a
1686 * suitable default value, likely taken from one of the
1687 * initial SIDs.
1688 */
1689 oc = args->newp->ocontexts[OCON_ISID];
1690 while (oc && oc->sid[0] != SECINITSID_UNLABELED)
1691 oc = oc->next;
1692 if (!oc) {
1693 printk(KERN_ERR "SELinux: unable to look up"
1694 " the initial SIDs list\n");
1695 goto bad;
1696 }
1697 range = &oc->context[0].range;
1698 rc = mls_range_set(c, range);
1699 if (rc)
1700 goto bad;
1701 }
1679 1702
1680 /* Check the validity of the new context. */ 1703 /* Check the validity of the new context. */
1681 if (!policydb_context_isvalid(args->newp, c)) { 1704 if (!policydb_context_isvalid(args->newp, c)) {
@@ -1771,9 +1794,17 @@ int security_load_policy(void *data, size_t len)
1771 if (policydb_read(&newpolicydb, fp)) 1794 if (policydb_read(&newpolicydb, fp))
1772 return -EINVAL; 1795 return -EINVAL;
1773 1796
1774 if (sidtab_init(&newsidtab)) { 1797 /* If switching between different policy types, log MLS status */
1798 if (policydb.mls_enabled && !newpolicydb.mls_enabled)
1799 printk(KERN_INFO "SELinux: Disabling MLS support...\n");
1800 else if (!policydb.mls_enabled && newpolicydb.mls_enabled)
1801 printk(KERN_INFO "SELinux: Enabling MLS support...\n");
1802
1803 rc = policydb_load_isids(&newpolicydb, &newsidtab);
1804 if (rc) {
1805 printk(KERN_ERR "SELinux: unable to load the initial SIDs\n");
1775 policydb_destroy(&newpolicydb); 1806 policydb_destroy(&newpolicydb);
1776 return -ENOMEM; 1807 return rc;
1777 } 1808 }
1778 1809
1779 if (selinux_set_mapping(&newpolicydb, secclass_map, 1810 if (selinux_set_mapping(&newpolicydb, secclass_map,
@@ -1800,8 +1831,12 @@ int security_load_policy(void *data, size_t len)
1800 args.oldp = &policydb; 1831 args.oldp = &policydb;
1801 args.newp = &newpolicydb; 1832 args.newp = &newpolicydb;
1802 rc = sidtab_map(&newsidtab, convert_context, &args); 1833 rc = sidtab_map(&newsidtab, convert_context, &args);
1803 if (rc) 1834 if (rc) {
1835 printk(KERN_ERR "SELinux: unable to convert the internal"
1836 " representation of contexts in the new SID"
1837 " table\n");
1804 goto err; 1838 goto err;
1839 }
1805 1840
1806 /* Save the old policydb and SID table to free later. */ 1841 /* Save the old policydb and SID table to free later. */
1807 memcpy(&oldpolicydb, &policydb, sizeof policydb); 1842 memcpy(&oldpolicydb, &policydb, sizeof policydb);
@@ -2397,7 +2432,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
2397 u32 len; 2432 u32 len;
2398 int rc = 0; 2433 int rc = 0;
2399 2434
2400 if (!ss_initialized || !selinux_mls_enabled) { 2435 if (!ss_initialized || !policydb.mls_enabled) {
2401 *new_sid = sid; 2436 *new_sid = sid;
2402 goto out; 2437 goto out;
2403 } 2438 }
@@ -2498,7 +2533,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
2498 /* we don't need to check ss_initialized here since the only way both 2533 /* we don't need to check ss_initialized here since the only way both
2499 * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the 2534 * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the
2500 * security server was initialized and ss_initialized was true */ 2535 * security server was initialized and ss_initialized was true */
2501 if (!selinux_mls_enabled) { 2536 if (!policydb.mls_enabled) {
2502 *peer_sid = SECSID_NULL; 2537 *peer_sid = SECSID_NULL;
2503 return 0; 2538 return 0;
2504 } 2539 }
@@ -2555,7 +2590,7 @@ int security_get_classes(char ***classes, int *nclasses)
2555 read_lock(&policy_rwlock); 2590 read_lock(&policy_rwlock);
2556 2591
2557 *nclasses = policydb.p_classes.nprim; 2592 *nclasses = policydb.p_classes.nprim;
2558 *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC); 2593 *classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC);
2559 if (!*classes) 2594 if (!*classes)
2560 goto out; 2595 goto out;
2561 2596
@@ -2602,7 +2637,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
2602 } 2637 }
2603 2638
2604 *nperms = match->permissions.nprim; 2639 *nperms = match->permissions.nprim;
2605 *perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC); 2640 *perms = kcalloc(*nperms, sizeof(**perms), GFP_ATOMIC);
2606 if (!*perms) 2641 if (!*perms)
2607 goto out; 2642 goto out;
2608 2643
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 529c9ca65878..a5721b373f53 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -157,12 +157,12 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
157 * 157 *
158 * Returns 0 on success, error code otherwise. 158 * Returns 0 on success, error code otherwise.
159 */ 159 */
160static int smack_syslog(int type) 160static int smack_syslog(int type, bool from_file)
161{ 161{
162 int rc; 162 int rc;
163 char *sp = current_security(); 163 char *sp = current_security();
164 164
165 rc = cap_syslog(type); 165 rc = cap_syslog(type, from_file);
166 if (rc != 0) 166 if (rc != 0)
167 return rc; 167 return rc;
168 168
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile
index 10ccd686b290..60a9e2002da1 100644
--- a/security/tomoyo/Makefile
+++ b/security/tomoyo/Makefile
@@ -1 +1 @@
obj-y = common.o realpath.o tomoyo.o domain.o file.o obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index e0d0354008b7..ff51f1026b57 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -12,9 +12,10 @@
12#include <linux/uaccess.h> 12#include <linux/uaccess.h>
13#include <linux/security.h> 13#include <linux/security.h>
14#include <linux/hardirq.h> 14#include <linux/hardirq.h>
15#include "realpath.h"
16#include "common.h" 15#include "common.h"
17#include "tomoyo.h" 16
17/* Lock for protecting policy. */
18DEFINE_MUTEX(tomoyo_policy_lock);
18 19
19/* Has loading policy done? */ 20/* Has loading policy done? */
20bool tomoyo_policy_loaded; 21bool tomoyo_policy_loaded;
@@ -178,14 +179,12 @@ static void tomoyo_normalize_line(unsigned char *buffer)
178 * 1 = must / -1 = must not / 0 = don't care 179 * 1 = must / -1 = must not / 0 = don't care
179 * @end_type: Should the pathname end with '/'? 180 * @end_type: Should the pathname end with '/'?
180 * 1 = must / -1 = must not / 0 = don't care 181 * 1 = must / -1 = must not / 0 = don't care
181 * @function: The name of function calling me.
182 * 182 *
183 * Check whether the given filename follows the naming rules. 183 * Check whether the given filename follows the naming rules.
184 * Returns true if @filename follows the naming rules, false otherwise. 184 * Returns true if @filename follows the naming rules, false otherwise.
185 */ 185 */
186bool tomoyo_is_correct_path(const char *filename, const s8 start_type, 186bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
187 const s8 pattern_type, const s8 end_type, 187 const s8 pattern_type, const s8 end_type)
188 const char *function)
189{ 188{
190 const char *const start = filename; 189 const char *const start = filename;
191 bool in_repetition = false; 190 bool in_repetition = false;
@@ -193,7 +192,6 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
193 unsigned char c; 192 unsigned char c;
194 unsigned char d; 193 unsigned char d;
195 unsigned char e; 194 unsigned char e;
196 const char *original_filename = filename;
197 195
198 if (!filename) 196 if (!filename)
199 goto out; 197 goto out;
@@ -282,25 +280,20 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
282 goto out; 280 goto out;
283 return true; 281 return true;
284 out: 282 out:
285 printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,
286 original_filename);
287 return false; 283 return false;
288} 284}
289 285
290/** 286/**
291 * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules. 287 * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules.
292 * @domainname: The domainname to check. 288 * @domainname: The domainname to check.
293 * @function: The name of function calling me.
294 * 289 *
295 * Returns true if @domainname follows the naming rules, false otherwise. 290 * Returns true if @domainname follows the naming rules, false otherwise.
296 */ 291 */
297bool tomoyo_is_correct_domain(const unsigned char *domainname, 292bool tomoyo_is_correct_domain(const unsigned char *domainname)
298 const char *function)
299{ 293{
300 unsigned char c; 294 unsigned char c;
301 unsigned char d; 295 unsigned char d;
302 unsigned char e; 296 unsigned char e;
303 const char *org_domainname = domainname;
304 297
305 if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME, 298 if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME,
306 TOMOYO_ROOT_NAME_LEN)) 299 TOMOYO_ROOT_NAME_LEN))
@@ -343,8 +336,6 @@ bool tomoyo_is_correct_domain(const unsigned char *domainname,
343 } while (*domainname); 336 } while (*domainname);
344 return true; 337 return true;
345 out: 338 out:
346 printk(KERN_DEBUG "%s: Invalid domainname '%s'\n", function,
347 org_domainname);
348 return false; 339 return false;
349} 340}
350 341
@@ -365,10 +356,9 @@ bool tomoyo_is_domain_def(const unsigned char *buffer)
365 * 356 *
366 * @domainname: The domainname to find. 357 * @domainname: The domainname to find.
367 * 358 *
368 * Caller must call down_read(&tomoyo_domain_list_lock); or
369 * down_write(&tomoyo_domain_list_lock); .
370 *
371 * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise. 359 * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
360 *
361 * Caller holds tomoyo_read_lock().
372 */ 362 */
373struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) 363struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
374{ 364{
@@ -377,7 +367,7 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
377 367
378 name.name = domainname; 368 name.name = domainname;
379 tomoyo_fill_path_info(&name); 369 tomoyo_fill_path_info(&name);
380 list_for_each_entry(domain, &tomoyo_domain_list, list) { 370 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
381 if (!domain->is_deleted && 371 if (!domain->is_deleted &&
382 !tomoyo_pathcmp(&name, domain->domainname)) 372 !tomoyo_pathcmp(&name, domain->domainname))
383 return domain; 373 return domain;
@@ -748,7 +738,7 @@ bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
748 * 738 *
749 * Returns the tomoyo_realpath() of current process on success, NULL otherwise. 739 * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
750 * 740 *
751 * This function uses tomoyo_alloc(), so the caller must call tomoyo_free() 741 * This function uses kzalloc(), so the caller must call kfree()
752 * if this function didn't return NULL. 742 * if this function didn't return NULL.
753 */ 743 */
754static const char *tomoyo_get_exe(void) 744static const char *tomoyo_get_exe(void)
@@ -829,6 +819,8 @@ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain)
829 * @domain: Pointer to "struct tomoyo_domain_info". 819 * @domain: Pointer to "struct tomoyo_domain_info".
830 * 820 *
831 * Returns true if the domain is not exceeded quota, false otherwise. 821 * Returns true if the domain is not exceeded quota, false otherwise.
822 *
823 * Caller holds tomoyo_read_lock().
832 */ 824 */
833bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) 825bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
834{ 826{
@@ -837,61 +829,29 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
837 829
838 if (!domain) 830 if (!domain)
839 return true; 831 return true;
840 down_read(&tomoyo_domain_acl_info_list_lock); 832 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
841 list_for_each_entry(ptr, &domain->acl_info_list, list) { 833 switch (ptr->type) {
842 if (ptr->type & TOMOYO_ACL_DELETED) 834 struct tomoyo_path_acl *acl;
843 continue; 835 u32 perm;
844 switch (tomoyo_acl_type2(ptr)) { 836 u8 i;
845 struct tomoyo_single_path_acl_record *acl1; 837 case TOMOYO_TYPE_PATH_ACL:
846 struct tomoyo_double_path_acl_record *acl2; 838 acl = container_of(ptr, struct tomoyo_path_acl, head);
847 u16 perm; 839 perm = acl->perm | (((u32) acl->perm_high) << 16);
848 case TOMOYO_TYPE_SINGLE_PATH_ACL: 840 for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++)
849 acl1 = container_of(ptr, 841 if (perm & (1 << i))
850 struct tomoyo_single_path_acl_record, 842 count++;
851 head); 843 if (perm & (1 << TOMOYO_TYPE_READ_WRITE))
852 perm = acl1->perm; 844 count -= 2;
853 if (perm & (1 << TOMOYO_TYPE_EXECUTE_ACL))
854 count++;
855 if (perm &
856 ((1 << TOMOYO_TYPE_READ_ACL) |
857 (1 << TOMOYO_TYPE_WRITE_ACL)))
858 count++;
859 if (perm & (1 << TOMOYO_TYPE_CREATE_ACL))
860 count++;
861 if (perm & (1 << TOMOYO_TYPE_UNLINK_ACL))
862 count++;
863 if (perm & (1 << TOMOYO_TYPE_MKDIR_ACL))
864 count++;
865 if (perm & (1 << TOMOYO_TYPE_RMDIR_ACL))
866 count++;
867 if (perm & (1 << TOMOYO_TYPE_MKFIFO_ACL))
868 count++;
869 if (perm & (1 << TOMOYO_TYPE_MKSOCK_ACL))
870 count++;
871 if (perm & (1 << TOMOYO_TYPE_MKBLOCK_ACL))
872 count++;
873 if (perm & (1 << TOMOYO_TYPE_MKCHAR_ACL))
874 count++;
875 if (perm & (1 << TOMOYO_TYPE_TRUNCATE_ACL))
876 count++;
877 if (perm & (1 << TOMOYO_TYPE_SYMLINK_ACL))
878 count++;
879 if (perm & (1 << TOMOYO_TYPE_REWRITE_ACL))
880 count++;
881 break; 845 break;
882 case TOMOYO_TYPE_DOUBLE_PATH_ACL: 846 case TOMOYO_TYPE_PATH2_ACL:
883 acl2 = container_of(ptr, 847 perm = container_of(ptr, struct tomoyo_path2_acl, head)
884 struct tomoyo_double_path_acl_record, 848 ->perm;
885 head); 849 for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++)
886 perm = acl2->perm; 850 if (perm & (1 << i))
887 if (perm & (1 << TOMOYO_TYPE_LINK_ACL)) 851 count++;
888 count++;
889 if (perm & (1 << TOMOYO_TYPE_RENAME_ACL))
890 count++;
891 break; 852 break;
892 } 853 }
893 } 854 }
894 up_read(&tomoyo_domain_acl_info_list_lock);
895 if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY)) 855 if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY))
896 return true; 856 return true;
897 if (!domain->quota_warned) { 857 if (!domain->quota_warned) {
@@ -923,9 +883,11 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned
923 ptr = tomoyo_profile_ptr[profile]; 883 ptr = tomoyo_profile_ptr[profile];
924 if (ptr) 884 if (ptr)
925 goto ok; 885 goto ok;
926 ptr = tomoyo_alloc_element(sizeof(*ptr)); 886 ptr = kmalloc(sizeof(*ptr), GFP_KERNEL);
927 if (!ptr) 887 if (!tomoyo_memory_ok(ptr)) {
888 kfree(ptr);
928 goto ok; 889 goto ok;
890 }
929 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) 891 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++)
930 ptr->value[i] = tomoyo_control_array[i].current_value; 892 ptr->value[i] = tomoyo_control_array[i].current_value;
931 mb(); /* Avoid out-of-order execution. */ 893 mb(); /* Avoid out-of-order execution. */
@@ -966,7 +928,9 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
966 return -EINVAL; 928 return -EINVAL;
967 *cp = '\0'; 929 *cp = '\0';
968 if (!strcmp(data, "COMMENT")) { 930 if (!strcmp(data, "COMMENT")) {
969 profile->comment = tomoyo_save_name(cp + 1); 931 const struct tomoyo_path_info *old_comment = profile->comment;
932 profile->comment = tomoyo_get_name(cp + 1);
933 tomoyo_put_name(old_comment);
970 return 0; 934 return 0;
971 } 935 }
972 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) { 936 for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) {
@@ -1061,27 +1025,6 @@ static int tomoyo_read_profile(struct tomoyo_io_buffer *head)
1061} 1025}
1062 1026
1063/* 1027/*
1064 * tomoyo_policy_manager_entry is a structure which is used for holding list of
1065 * domainnames or programs which are permitted to modify configuration via
1066 * /sys/kernel/security/tomoyo/ interface.
1067 * It has following fields.
1068 *
1069 * (1) "list" which is linked to tomoyo_policy_manager_list .
1070 * (2) "manager" is a domainname or a program's pathname.
1071 * (3) "is_domain" is a bool which is true if "manager" is a domainname, false
1072 * otherwise.
1073 * (4) "is_deleted" is a bool which is true if marked as deleted, false
1074 * otherwise.
1075 */
1076struct tomoyo_policy_manager_entry {
1077 struct list_head list;
1078 /* A path to program or a domainname. */
1079 const struct tomoyo_path_info *manager;
1080 bool is_domain; /* True if manager is a domainname. */
1081 bool is_deleted; /* True if this entry is deleted. */
1082};
1083
1084/*
1085 * tomoyo_policy_manager_list is used for holding list of domainnames or 1028 * tomoyo_policy_manager_list is used for holding list of domainnames or
1086 * programs which are permitted to modify configuration via 1029 * programs which are permitted to modify configuration via
1087 * /sys/kernel/security/tomoyo/ interface. 1030 * /sys/kernel/security/tomoyo/ interface.
@@ -1111,8 +1054,7 @@ struct tomoyo_policy_manager_entry {
1111 * 1054 *
1112 * # cat /sys/kernel/security/tomoyo/manager 1055 * # cat /sys/kernel/security/tomoyo/manager
1113 */ 1056 */
1114static LIST_HEAD(tomoyo_policy_manager_list); 1057LIST_HEAD(tomoyo_policy_manager_list);
1115static DECLARE_RWSEM(tomoyo_policy_manager_list_lock);
1116 1058
1117/** 1059/**
1118 * tomoyo_update_manager_entry - Add a manager entry. 1060 * tomoyo_update_manager_entry - Add a manager entry.
@@ -1121,48 +1063,50 @@ static DECLARE_RWSEM(tomoyo_policy_manager_list_lock);
1121 * @is_delete: True if it is a delete request. 1063 * @is_delete: True if it is a delete request.
1122 * 1064 *
1123 * Returns 0 on success, negative value otherwise. 1065 * Returns 0 on success, negative value otherwise.
1066 *
1067 * Caller holds tomoyo_read_lock().
1124 */ 1068 */
1125static int tomoyo_update_manager_entry(const char *manager, 1069static int tomoyo_update_manager_entry(const char *manager,
1126 const bool is_delete) 1070 const bool is_delete)
1127{ 1071{
1128 struct tomoyo_policy_manager_entry *new_entry; 1072 struct tomoyo_policy_manager_entry *entry = NULL;
1129 struct tomoyo_policy_manager_entry *ptr; 1073 struct tomoyo_policy_manager_entry *ptr;
1130 const struct tomoyo_path_info *saved_manager; 1074 const struct tomoyo_path_info *saved_manager;
1131 int error = -ENOMEM; 1075 int error = is_delete ? -ENOENT : -ENOMEM;
1132 bool is_domain = false; 1076 bool is_domain = false;
1133 1077
1134 if (tomoyo_is_domain_def(manager)) { 1078 if (tomoyo_is_domain_def(manager)) {
1135 if (!tomoyo_is_correct_domain(manager, __func__)) 1079 if (!tomoyo_is_correct_domain(manager))
1136 return -EINVAL; 1080 return -EINVAL;
1137 is_domain = true; 1081 is_domain = true;
1138 } else { 1082 } else {
1139 if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__)) 1083 if (!tomoyo_is_correct_path(manager, 1, -1, -1))
1140 return -EINVAL; 1084 return -EINVAL;
1141 } 1085 }
1142 saved_manager = tomoyo_save_name(manager); 1086 saved_manager = tomoyo_get_name(manager);
1143 if (!saved_manager) 1087 if (!saved_manager)
1144 return -ENOMEM; 1088 return -ENOMEM;
1145 down_write(&tomoyo_policy_manager_list_lock); 1089 if (!is_delete)
1146 list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) { 1090 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
1091 mutex_lock(&tomoyo_policy_lock);
1092 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
1147 if (ptr->manager != saved_manager) 1093 if (ptr->manager != saved_manager)
1148 continue; 1094 continue;
1149 ptr->is_deleted = is_delete; 1095 ptr->is_deleted = is_delete;
1150 error = 0; 1096 error = 0;
1151 goto out; 1097 break;
1152 } 1098 }
1153 if (is_delete) { 1099 if (!is_delete && error && tomoyo_memory_ok(entry)) {
1154 error = -ENOENT; 1100 entry->manager = saved_manager;
1155 goto out; 1101 saved_manager = NULL;
1102 entry->is_domain = is_domain;
1103 list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list);
1104 entry = NULL;
1105 error = 0;
1156 } 1106 }
1157 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 1107 mutex_unlock(&tomoyo_policy_lock);
1158 if (!new_entry) 1108 tomoyo_put_name(saved_manager);
1159 goto out; 1109 kfree(entry);
1160 new_entry->manager = saved_manager;
1161 new_entry->is_domain = is_domain;
1162 list_add_tail(&new_entry->list, &tomoyo_policy_manager_list);
1163 error = 0;
1164 out:
1165 up_write(&tomoyo_policy_manager_list_lock);
1166 return error; 1110 return error;
1167} 1111}
1168 1112
@@ -1172,6 +1116,8 @@ static int tomoyo_update_manager_entry(const char *manager,
1172 * @head: Pointer to "struct tomoyo_io_buffer". 1116 * @head: Pointer to "struct tomoyo_io_buffer".
1173 * 1117 *
1174 * Returns 0 on success, negative value otherwise. 1118 * Returns 0 on success, negative value otherwise.
1119 *
1120 * Caller holds tomoyo_read_lock().
1175 */ 1121 */
1176static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) 1122static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head)
1177{ 1123{
@@ -1191,6 +1137,8 @@ static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head)
1191 * @head: Pointer to "struct tomoyo_io_buffer". 1137 * @head: Pointer to "struct tomoyo_io_buffer".
1192 * 1138 *
1193 * Returns 0. 1139 * Returns 0.
1140 *
1141 * Caller holds tomoyo_read_lock().
1194 */ 1142 */
1195static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) 1143static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
1196{ 1144{
@@ -1199,7 +1147,6 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
1199 1147
1200 if (head->read_eof) 1148 if (head->read_eof)
1201 return 0; 1149 return 0;
1202 down_read(&tomoyo_policy_manager_list_lock);
1203 list_for_each_cookie(pos, head->read_var2, 1150 list_for_each_cookie(pos, head->read_var2,
1204 &tomoyo_policy_manager_list) { 1151 &tomoyo_policy_manager_list) {
1205 struct tomoyo_policy_manager_entry *ptr; 1152 struct tomoyo_policy_manager_entry *ptr;
@@ -1211,7 +1158,6 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
1211 if (!done) 1158 if (!done)
1212 break; 1159 break;
1213 } 1160 }
1214 up_read(&tomoyo_policy_manager_list_lock);
1215 head->read_eof = done; 1161 head->read_eof = done;
1216 return 0; 1162 return 0;
1217} 1163}
@@ -1221,6 +1167,8 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
1221 * 1167 *
1222 * Returns true if the current process is permitted to modify policy 1168 * Returns true if the current process is permitted to modify policy
1223 * via /sys/kernel/security/tomoyo/ interface. 1169 * via /sys/kernel/security/tomoyo/ interface.
1170 *
1171 * Caller holds tomoyo_read_lock().
1224 */ 1172 */
1225static bool tomoyo_is_policy_manager(void) 1173static bool tomoyo_is_policy_manager(void)
1226{ 1174{
@@ -1234,29 +1182,25 @@ static bool tomoyo_is_policy_manager(void)
1234 return true; 1182 return true;
1235 if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid)) 1183 if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid))
1236 return false; 1184 return false;
1237 down_read(&tomoyo_policy_manager_list_lock); 1185 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
1238 list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
1239 if (!ptr->is_deleted && ptr->is_domain 1186 if (!ptr->is_deleted && ptr->is_domain
1240 && !tomoyo_pathcmp(domainname, ptr->manager)) { 1187 && !tomoyo_pathcmp(domainname, ptr->manager)) {
1241 found = true; 1188 found = true;
1242 break; 1189 break;
1243 } 1190 }
1244 } 1191 }
1245 up_read(&tomoyo_policy_manager_list_lock);
1246 if (found) 1192 if (found)
1247 return true; 1193 return true;
1248 exe = tomoyo_get_exe(); 1194 exe = tomoyo_get_exe();
1249 if (!exe) 1195 if (!exe)
1250 return false; 1196 return false;
1251 down_read(&tomoyo_policy_manager_list_lock); 1197 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
1252 list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) {
1253 if (!ptr->is_deleted && !ptr->is_domain 1198 if (!ptr->is_deleted && !ptr->is_domain
1254 && !strcmp(exe, ptr->manager->name)) { 1199 && !strcmp(exe, ptr->manager->name)) {
1255 found = true; 1200 found = true;
1256 break; 1201 break;
1257 } 1202 }
1258 } 1203 }
1259 up_read(&tomoyo_policy_manager_list_lock);
1260 if (!found) { /* Reduce error messages. */ 1204 if (!found) { /* Reduce error messages. */
1261 static pid_t last_pid; 1205 static pid_t last_pid;
1262 const pid_t pid = current->pid; 1206 const pid_t pid = current->pid;
@@ -1266,7 +1210,7 @@ static bool tomoyo_is_policy_manager(void)
1266 last_pid = pid; 1210 last_pid = pid;
1267 } 1211 }
1268 } 1212 }
1269 tomoyo_free(exe); 1213 kfree(exe);
1270 return found; 1214 return found;
1271} 1215}
1272 1216
@@ -1277,6 +1221,8 @@ static bool tomoyo_is_policy_manager(void)
1277 * @data: String to parse. 1221 * @data: String to parse.
1278 * 1222 *
1279 * Returns true on success, false otherwise. 1223 * Returns true on success, false otherwise.
1224 *
1225 * Caller holds tomoyo_read_lock().
1280 */ 1226 */
1281static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, 1227static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
1282 const char *data) 1228 const char *data)
@@ -1286,17 +1232,16 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
1286 1232
1287 if (sscanf(data, "pid=%u", &pid) == 1) { 1233 if (sscanf(data, "pid=%u", &pid) == 1) {
1288 struct task_struct *p; 1234 struct task_struct *p;
1235 rcu_read_lock();
1289 read_lock(&tasklist_lock); 1236 read_lock(&tasklist_lock);
1290 p = find_task_by_vpid(pid); 1237 p = find_task_by_vpid(pid);
1291 if (p) 1238 if (p)
1292 domain = tomoyo_real_domain(p); 1239 domain = tomoyo_real_domain(p);
1293 read_unlock(&tasklist_lock); 1240 read_unlock(&tasklist_lock);
1241 rcu_read_unlock();
1294 } else if (!strncmp(data, "domain=", 7)) { 1242 } else if (!strncmp(data, "domain=", 7)) {
1295 if (tomoyo_is_domain_def(data + 7)) { 1243 if (tomoyo_is_domain_def(data + 7))
1296 down_read(&tomoyo_domain_list_lock);
1297 domain = tomoyo_find_domain(data + 7); 1244 domain = tomoyo_find_domain(data + 7);
1298 up_read(&tomoyo_domain_list_lock);
1299 }
1300 } else 1245 } else
1301 return false; 1246 return false;
1302 head->write_var1 = domain; 1247 head->write_var1 = domain;
@@ -1310,13 +1255,11 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
1310 if (domain) { 1255 if (domain) {
1311 struct tomoyo_domain_info *d; 1256 struct tomoyo_domain_info *d;
1312 head->read_var1 = NULL; 1257 head->read_var1 = NULL;
1313 down_read(&tomoyo_domain_list_lock); 1258 list_for_each_entry_rcu(d, &tomoyo_domain_list, list) {
1314 list_for_each_entry(d, &tomoyo_domain_list, list) {
1315 if (d == domain) 1259 if (d == domain)
1316 break; 1260 break;
1317 head->read_var1 = &d->list; 1261 head->read_var1 = &d->list;
1318 } 1262 }
1319 up_read(&tomoyo_domain_list_lock);
1320 head->read_var2 = NULL; 1263 head->read_var2 = NULL;
1321 head->read_bit = 0; 1264 head->read_bit = 0;
1322 head->read_step = 0; 1265 head->read_step = 0;
@@ -1332,6 +1275,8 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
1332 * @domainname: The name of domain. 1275 * @domainname: The name of domain.
1333 * 1276 *
1334 * Returns 0. 1277 * Returns 0.
1278 *
1279 * Caller holds tomoyo_read_lock().
1335 */ 1280 */
1336static int tomoyo_delete_domain(char *domainname) 1281static int tomoyo_delete_domain(char *domainname)
1337{ 1282{
@@ -1340,9 +1285,9 @@ static int tomoyo_delete_domain(char *domainname)
1340 1285
1341 name.name = domainname; 1286 name.name = domainname;
1342 tomoyo_fill_path_info(&name); 1287 tomoyo_fill_path_info(&name);
1343 down_write(&tomoyo_domain_list_lock); 1288 mutex_lock(&tomoyo_policy_lock);
1344 /* Is there an active domain? */ 1289 /* Is there an active domain? */
1345 list_for_each_entry(domain, &tomoyo_domain_list, list) { 1290 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
1346 /* Never delete tomoyo_kernel_domain */ 1291 /* Never delete tomoyo_kernel_domain */
1347 if (domain == &tomoyo_kernel_domain) 1292 if (domain == &tomoyo_kernel_domain)
1348 continue; 1293 continue;
@@ -1352,7 +1297,7 @@ static int tomoyo_delete_domain(char *domainname)
1352 domain->is_deleted = true; 1297 domain->is_deleted = true;
1353 break; 1298 break;
1354 } 1299 }
1355 up_write(&tomoyo_domain_list_lock); 1300 mutex_unlock(&tomoyo_policy_lock);
1356 return 0; 1301 return 0;
1357} 1302}
1358 1303
@@ -1362,6 +1307,8 @@ static int tomoyo_delete_domain(char *domainname)
1362 * @head: Pointer to "struct tomoyo_io_buffer". 1307 * @head: Pointer to "struct tomoyo_io_buffer".
1363 * 1308 *
1364 * Returns 0 on success, negative value otherwise. 1309 * Returns 0 on success, negative value otherwise.
1310 *
1311 * Caller holds tomoyo_read_lock().
1365 */ 1312 */
1366static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) 1313static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
1367{ 1314{
@@ -1384,11 +1331,9 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
1384 domain = NULL; 1331 domain = NULL;
1385 if (is_delete) 1332 if (is_delete)
1386 tomoyo_delete_domain(data); 1333 tomoyo_delete_domain(data);
1387 else if (is_select) { 1334 else if (is_select)
1388 down_read(&tomoyo_domain_list_lock);
1389 domain = tomoyo_find_domain(data); 1335 domain = tomoyo_find_domain(data);
1390 up_read(&tomoyo_domain_list_lock); 1336 else
1391 } else
1392 domain = tomoyo_find_or_assign_new_domain(data, 0); 1337 domain = tomoyo_find_or_assign_new_domain(data, 0);
1393 head->write_var1 = domain; 1338 head->write_var1 = domain;
1394 return 0; 1339 return 0;
@@ -1403,43 +1348,39 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
1403 return 0; 1348 return 0;
1404 } 1349 }
1405 if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) { 1350 if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
1406 tomoyo_set_domain_flag(domain, is_delete, 1351 domain->ignore_global_allow_read = !is_delete;
1407 TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ);
1408 return 0; 1352 return 0;
1409 } 1353 }
1410 return tomoyo_write_file_policy(data, domain, is_delete); 1354 return tomoyo_write_file_policy(data, domain, is_delete);
1411} 1355}
1412 1356
1413/** 1357/**
1414 * tomoyo_print_single_path_acl - Print a single path ACL entry. 1358 * tomoyo_print_path_acl - Print a single path ACL entry.
1415 * 1359 *
1416 * @head: Pointer to "struct tomoyo_io_buffer". 1360 * @head: Pointer to "struct tomoyo_io_buffer".
1417 * @ptr: Pointer to "struct tomoyo_single_path_acl_record". 1361 * @ptr: Pointer to "struct tomoyo_path_acl".
1418 * 1362 *
1419 * Returns true on success, false otherwise. 1363 * Returns true on success, false otherwise.
1420 */ 1364 */
1421static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head, 1365static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head,
1422 struct tomoyo_single_path_acl_record * 1366 struct tomoyo_path_acl *ptr)
1423 ptr)
1424{ 1367{
1425 int pos; 1368 int pos;
1426 u8 bit; 1369 u8 bit;
1427 const char *atmark = ""; 1370 const char *atmark = "";
1428 const char *filename; 1371 const char *filename;
1429 const u16 perm = ptr->perm; 1372 const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16);
1430 1373
1431 filename = ptr->filename->name; 1374 filename = ptr->filename->name;
1432 for (bit = head->read_bit; bit < TOMOYO_MAX_SINGLE_PATH_OPERATION; 1375 for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) {
1433 bit++) {
1434 const char *msg; 1376 const char *msg;
1435 if (!(perm & (1 << bit))) 1377 if (!(perm & (1 << bit)))
1436 continue; 1378 continue;
1437 /* Print "read/write" instead of "read" and "write". */ 1379 /* Print "read/write" instead of "read" and "write". */
1438 if ((bit == TOMOYO_TYPE_READ_ACL || 1380 if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE)
1439 bit == TOMOYO_TYPE_WRITE_ACL) 1381 && (perm & (1 << TOMOYO_TYPE_READ_WRITE)))
1440 && (perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
1441 continue; 1382 continue;
1442 msg = tomoyo_sp2keyword(bit); 1383 msg = tomoyo_path2keyword(bit);
1443 pos = head->read_avail; 1384 pos = head->read_avail;
1444 if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg, 1385 if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg,
1445 atmark, filename)) 1386 atmark, filename))
@@ -1454,16 +1395,15 @@ static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head,
1454} 1395}
1455 1396
1456/** 1397/**
1457 * tomoyo_print_double_path_acl - Print a double path ACL entry. 1398 * tomoyo_print_path2_acl - Print a double path ACL entry.
1458 * 1399 *
1459 * @head: Pointer to "struct tomoyo_io_buffer". 1400 * @head: Pointer to "struct tomoyo_io_buffer".
1460 * @ptr: Pointer to "struct tomoyo_double_path_acl_record". 1401 * @ptr: Pointer to "struct tomoyo_path2_acl".
1461 * 1402 *
1462 * Returns true on success, false otherwise. 1403 * Returns true on success, false otherwise.
1463 */ 1404 */
1464static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head, 1405static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head,
1465 struct tomoyo_double_path_acl_record * 1406 struct tomoyo_path2_acl *ptr)
1466 ptr)
1467{ 1407{
1468 int pos; 1408 int pos;
1469 const char *atmark1 = ""; 1409 const char *atmark1 = "";
@@ -1475,12 +1415,11 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head,
1475 1415
1476 filename1 = ptr->filename1->name; 1416 filename1 = ptr->filename1->name;
1477 filename2 = ptr->filename2->name; 1417 filename2 = ptr->filename2->name;
1478 for (bit = head->read_bit; bit < TOMOYO_MAX_DOUBLE_PATH_OPERATION; 1418 for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) {
1479 bit++) {
1480 const char *msg; 1419 const char *msg;
1481 if (!(perm & (1 << bit))) 1420 if (!(perm & (1 << bit)))
1482 continue; 1421 continue;
1483 msg = tomoyo_dp2keyword(bit); 1422 msg = tomoyo_path22keyword(bit);
1484 pos = head->read_avail; 1423 pos = head->read_avail;
1485 if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg, 1424 if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg,
1486 atmark1, filename1, atmark2, filename2)) 1425 atmark1, filename1, atmark2, filename2))
@@ -1505,23 +1444,17 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head,
1505static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, 1444static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1506 struct tomoyo_acl_info *ptr) 1445 struct tomoyo_acl_info *ptr)
1507{ 1446{
1508 const u8 acl_type = tomoyo_acl_type2(ptr); 1447 const u8 acl_type = ptr->type;
1509 1448
1510 if (acl_type & TOMOYO_ACL_DELETED) 1449 if (acl_type == TOMOYO_TYPE_PATH_ACL) {
1511 return true; 1450 struct tomoyo_path_acl *acl
1512 if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) { 1451 = container_of(ptr, struct tomoyo_path_acl, head);
1513 struct tomoyo_single_path_acl_record *acl 1452 return tomoyo_print_path_acl(head, acl);
1514 = container_of(ptr,
1515 struct tomoyo_single_path_acl_record,
1516 head);
1517 return tomoyo_print_single_path_acl(head, acl);
1518 } 1453 }
1519 if (acl_type == TOMOYO_TYPE_DOUBLE_PATH_ACL) { 1454 if (acl_type == TOMOYO_TYPE_PATH2_ACL) {
1520 struct tomoyo_double_path_acl_record *acl 1455 struct tomoyo_path2_acl *acl
1521 = container_of(ptr, 1456 = container_of(ptr, struct tomoyo_path2_acl, head);
1522 struct tomoyo_double_path_acl_record, 1457 return tomoyo_print_path2_acl(head, acl);
1523 head);
1524 return tomoyo_print_double_path_acl(head, acl);
1525 } 1458 }
1526 BUG(); /* This must not happen. */ 1459 BUG(); /* This must not happen. */
1527 return false; 1460 return false;
@@ -1533,6 +1466,8 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
1533 * @head: Pointer to "struct tomoyo_io_buffer". 1466 * @head: Pointer to "struct tomoyo_io_buffer".
1534 * 1467 *
1535 * Returns 0. 1468 * Returns 0.
1469 *
1470 * Caller holds tomoyo_read_lock().
1536 */ 1471 */
1537static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) 1472static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
1538{ 1473{
@@ -1544,7 +1479,6 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
1544 return 0; 1479 return 0;
1545 if (head->read_step == 0) 1480 if (head->read_step == 0)
1546 head->read_step = 1; 1481 head->read_step = 1;
1547 down_read(&tomoyo_domain_list_lock);
1548 list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) { 1482 list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) {
1549 struct tomoyo_domain_info *domain; 1483 struct tomoyo_domain_info *domain;
1550 const char *quota_exceeded = ""; 1484 const char *quota_exceeded = "";
@@ -1558,10 +1492,9 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
1558 /* Print domainname and flags. */ 1492 /* Print domainname and flags. */
1559 if (domain->quota_warned) 1493 if (domain->quota_warned)
1560 quota_exceeded = "quota_exceeded\n"; 1494 quota_exceeded = "quota_exceeded\n";
1561 if (domain->flags & TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED) 1495 if (domain->transition_failed)
1562 transition_failed = "transition_failed\n"; 1496 transition_failed = "transition_failed\n";
1563 if (domain->flags & 1497 if (domain->ignore_global_allow_read)
1564 TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ)
1565 ignore_global_allow_read 1498 ignore_global_allow_read
1566 = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; 1499 = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
1567 done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE 1500 done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE
@@ -1577,7 +1510,6 @@ acl_loop:
1577 if (head->read_step == 3) 1510 if (head->read_step == 3)
1578 goto tail_mark; 1511 goto tail_mark;
1579 /* Print ACL entries in the domain. */ 1512 /* Print ACL entries in the domain. */
1580 down_read(&tomoyo_domain_acl_info_list_lock);
1581 list_for_each_cookie(apos, head->read_var2, 1513 list_for_each_cookie(apos, head->read_var2,
1582 &domain->acl_info_list) { 1514 &domain->acl_info_list) {
1583 struct tomoyo_acl_info *ptr 1515 struct tomoyo_acl_info *ptr
@@ -1587,7 +1519,6 @@ acl_loop:
1587 if (!done) 1519 if (!done)
1588 break; 1520 break;
1589 } 1521 }
1590 up_read(&tomoyo_domain_acl_info_list_lock);
1591 if (!done) 1522 if (!done)
1592 break; 1523 break;
1593 head->read_step = 3; 1524 head->read_step = 3;
@@ -1599,7 +1530,6 @@ tail_mark:
1599 if (head->read_single_domain) 1530 if (head->read_single_domain)
1600 break; 1531 break;
1601 } 1532 }
1602 up_read(&tomoyo_domain_list_lock);
1603 head->read_eof = done; 1533 head->read_eof = done;
1604 return 0; 1534 return 0;
1605} 1535}
@@ -1615,6 +1545,8 @@ tail_mark:
1615 * 1545 *
1616 * ( echo "select " $domainname; echo "use_profile " $profile ) | 1546 * ( echo "select " $domainname; echo "use_profile " $profile ) |
1617 * /usr/lib/ccs/loadpolicy -d 1547 * /usr/lib/ccs/loadpolicy -d
1548 *
1549 * Caller holds tomoyo_read_lock().
1618 */ 1550 */
1619static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) 1551static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
1620{ 1552{
@@ -1626,9 +1558,7 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
1626 if (!cp) 1558 if (!cp)
1627 return -EINVAL; 1559 return -EINVAL;
1628 *cp = '\0'; 1560 *cp = '\0';
1629 down_read(&tomoyo_domain_list_lock);
1630 domain = tomoyo_find_domain(cp + 1); 1561 domain = tomoyo_find_domain(cp + 1);
1631 up_read(&tomoyo_domain_list_lock);
1632 if (strict_strtoul(data, 10, &profile)) 1562 if (strict_strtoul(data, 10, &profile))
1633 return -EINVAL; 1563 return -EINVAL;
1634 if (domain && profile < TOMOYO_MAX_PROFILES 1564 if (domain && profile < TOMOYO_MAX_PROFILES
@@ -1650,6 +1580,8 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head)
1650 * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" ) 1580 * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
1651 * domainname = $0; } else if ( $1 == "use_profile" ) { 1581 * domainname = $0; } else if ( $1 == "use_profile" ) {
1652 * print $2 " " domainname; domainname = ""; } } ; ' 1582 * print $2 " " domainname; domainname = ""; } } ; '
1583 *
1584 * Caller holds tomoyo_read_lock().
1653 */ 1585 */
1654static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) 1586static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
1655{ 1587{
@@ -1658,7 +1590,6 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
1658 1590
1659 if (head->read_eof) 1591 if (head->read_eof)
1660 return 0; 1592 return 0;
1661 down_read(&tomoyo_domain_list_lock);
1662 list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) { 1593 list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) {
1663 struct tomoyo_domain_info *domain; 1594 struct tomoyo_domain_info *domain;
1664 domain = list_entry(pos, struct tomoyo_domain_info, list); 1595 domain = list_entry(pos, struct tomoyo_domain_info, list);
@@ -1669,7 +1600,6 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
1669 if (!done) 1600 if (!done)
1670 break; 1601 break;
1671 } 1602 }
1672 up_read(&tomoyo_domain_list_lock);
1673 head->read_eof = done; 1603 head->read_eof = done;
1674 return 0; 1604 return 0;
1675} 1605}
@@ -1707,11 +1637,13 @@ static int tomoyo_read_pid(struct tomoyo_io_buffer *head)
1707 const int pid = head->read_step; 1637 const int pid = head->read_step;
1708 struct task_struct *p; 1638 struct task_struct *p;
1709 struct tomoyo_domain_info *domain = NULL; 1639 struct tomoyo_domain_info *domain = NULL;
1640 rcu_read_lock();
1710 read_lock(&tasklist_lock); 1641 read_lock(&tasklist_lock);
1711 p = find_task_by_vpid(pid); 1642 p = find_task_by_vpid(pid);
1712 if (p) 1643 if (p)
1713 domain = tomoyo_real_domain(p); 1644 domain = tomoyo_real_domain(p);
1714 read_unlock(&tasklist_lock); 1645 read_unlock(&tasklist_lock);
1646 rcu_read_unlock();
1715 if (domain) 1647 if (domain)
1716 tomoyo_io_printf(head, "%d %u %s", pid, domain->profile, 1648 tomoyo_io_printf(head, "%d %u %s", pid, domain->profile,
1717 domain->domainname->name); 1649 domain->domainname->name);
@@ -1726,6 +1658,8 @@ static int tomoyo_read_pid(struct tomoyo_io_buffer *head)
1726 * @head: Pointer to "struct tomoyo_io_buffer". 1658 * @head: Pointer to "struct tomoyo_io_buffer".
1727 * 1659 *
1728 * Returns 0 on success, negative value otherwise. 1660 * Returns 0 on success, negative value otherwise.
1661 *
1662 * Caller holds tomoyo_read_lock().
1729 */ 1663 */
1730static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) 1664static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
1731{ 1665{
@@ -1760,6 +1694,8 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
1760 * @head: Pointer to "struct tomoyo_io_buffer". 1694 * @head: Pointer to "struct tomoyo_io_buffer".
1761 * 1695 *
1762 * Returns 0 on success, -EINVAL otherwise. 1696 * Returns 0 on success, -EINVAL otherwise.
1697 *
1698 * Caller holds tomoyo_read_lock().
1763 */ 1699 */
1764static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) 1700static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
1765{ 1701{
@@ -1889,15 +1825,13 @@ void tomoyo_load_policy(const char *filename)
1889 tomoyo_policy_loaded = true; 1825 tomoyo_policy_loaded = true;
1890 { /* Check all profiles currently assigned to domains are defined. */ 1826 { /* Check all profiles currently assigned to domains are defined. */
1891 struct tomoyo_domain_info *domain; 1827 struct tomoyo_domain_info *domain;
1892 down_read(&tomoyo_domain_list_lock); 1828 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
1893 list_for_each_entry(domain, &tomoyo_domain_list, list) {
1894 const u8 profile = domain->profile; 1829 const u8 profile = domain->profile;
1895 if (tomoyo_profile_ptr[profile]) 1830 if (tomoyo_profile_ptr[profile])
1896 continue; 1831 continue;
1897 panic("Profile %u (used by '%s') not defined.\n", 1832 panic("Profile %u (used by '%s') not defined.\n",
1898 profile, domain->domainname->name); 1833 profile, domain->domainname->name);
1899 } 1834 }
1900 up_read(&tomoyo_domain_list_lock);
1901 } 1835 }
1902} 1836}
1903 1837
@@ -1945,10 +1879,12 @@ static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
1945 * @file: Pointer to "struct file". 1879 * @file: Pointer to "struct file".
1946 * 1880 *
1947 * Associates policy handler and returns 0 on success, -ENOMEM otherwise. 1881 * Associates policy handler and returns 0 on success, -ENOMEM otherwise.
1882 *
1883 * Caller acquires tomoyo_read_lock().
1948 */ 1884 */
1949static int tomoyo_open_control(const u8 type, struct file *file) 1885static int tomoyo_open_control(const u8 type, struct file *file)
1950{ 1886{
1951 struct tomoyo_io_buffer *head = tomoyo_alloc(sizeof(*head)); 1887 struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL);
1952 1888
1953 if (!head) 1889 if (!head)
1954 return -ENOMEM; 1890 return -ENOMEM;
@@ -2009,9 +1945,9 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2009 } else { 1945 } else {
2010 if (!head->readbuf_size) 1946 if (!head->readbuf_size)
2011 head->readbuf_size = 4096 * 2; 1947 head->readbuf_size = 4096 * 2;
2012 head->read_buf = tomoyo_alloc(head->readbuf_size); 1948 head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);
2013 if (!head->read_buf) { 1949 if (!head->read_buf) {
2014 tomoyo_free(head); 1950 kfree(head);
2015 return -ENOMEM; 1951 return -ENOMEM;
2016 } 1952 }
2017 } 1953 }
@@ -2023,13 +1959,14 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2023 head->write = NULL; 1959 head->write = NULL;
2024 } else if (head->write) { 1960 } else if (head->write) {
2025 head->writebuf_size = 4096 * 2; 1961 head->writebuf_size = 4096 * 2;
2026 head->write_buf = tomoyo_alloc(head->writebuf_size); 1962 head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);
2027 if (!head->write_buf) { 1963 if (!head->write_buf) {
2028 tomoyo_free(head->read_buf); 1964 kfree(head->read_buf);
2029 tomoyo_free(head); 1965 kfree(head);
2030 return -ENOMEM; 1966 return -ENOMEM;
2031 } 1967 }
2032 } 1968 }
1969 head->reader_idx = tomoyo_read_lock();
2033 file->private_data = head; 1970 file->private_data = head;
2034 /* 1971 /*
2035 * Call the handler now if the file is 1972 * Call the handler now if the file is
@@ -2051,6 +1988,8 @@ static int tomoyo_open_control(const u8 type, struct file *file)
2051 * @buffer_len: Size of @buffer. 1988 * @buffer_len: Size of @buffer.
2052 * 1989 *
2053 * Returns bytes read on success, negative value otherwise. 1990 * Returns bytes read on success, negative value otherwise.
1991 *
1992 * Caller holds tomoyo_read_lock().
2054 */ 1993 */
2055static int tomoyo_read_control(struct file *file, char __user *buffer, 1994static int tomoyo_read_control(struct file *file, char __user *buffer,
2056 const int buffer_len) 1995 const int buffer_len)
@@ -2094,6 +2033,8 @@ static int tomoyo_read_control(struct file *file, char __user *buffer,
2094 * @buffer_len: Size of @buffer. 2033 * @buffer_len: Size of @buffer.
2095 * 2034 *
2096 * Returns @buffer_len on success, negative value otherwise. 2035 * Returns @buffer_len on success, negative value otherwise.
2036 *
2037 * Caller holds tomoyo_read_lock().
2097 */ 2038 */
2098static int tomoyo_write_control(struct file *file, const char __user *buffer, 2039static int tomoyo_write_control(struct file *file, const char __user *buffer,
2099 const int buffer_len) 2040 const int buffer_len)
@@ -2144,52 +2085,29 @@ static int tomoyo_write_control(struct file *file, const char __user *buffer,
2144 * @file: Pointer to "struct file". 2085 * @file: Pointer to "struct file".
2145 * 2086 *
2146 * Releases memory and returns 0. 2087 * Releases memory and returns 0.
2088 *
2089 * Caller looses tomoyo_read_lock().
2147 */ 2090 */
2148static int tomoyo_close_control(struct file *file) 2091static int tomoyo_close_control(struct file *file)
2149{ 2092{
2150 struct tomoyo_io_buffer *head = file->private_data; 2093 struct tomoyo_io_buffer *head = file->private_data;
2094 const bool is_write = !!head->write_buf;
2151 2095
2096 tomoyo_read_unlock(head->reader_idx);
2152 /* Release memory used for policy I/O. */ 2097 /* Release memory used for policy I/O. */
2153 tomoyo_free(head->read_buf); 2098 kfree(head->read_buf);
2154 head->read_buf = NULL; 2099 head->read_buf = NULL;
2155 tomoyo_free(head->write_buf); 2100 kfree(head->write_buf);
2156 head->write_buf = NULL; 2101 head->write_buf = NULL;
2157 tomoyo_free(head); 2102 kfree(head);
2158 head = NULL; 2103 head = NULL;
2159 file->private_data = NULL; 2104 file->private_data = NULL;
2105 if (is_write)
2106 tomoyo_run_gc();
2160 return 0; 2107 return 0;
2161} 2108}
2162 2109
2163/** 2110/**
2164 * tomoyo_alloc_acl_element - Allocate permanent memory for ACL entry.
2165 *
2166 * @acl_type: Type of ACL entry.
2167 *
2168 * Returns pointer to the ACL entry on success, NULL otherwise.
2169 */
2170void *tomoyo_alloc_acl_element(const u8 acl_type)
2171{
2172 int len;
2173 struct tomoyo_acl_info *ptr;
2174
2175 switch (acl_type) {
2176 case TOMOYO_TYPE_SINGLE_PATH_ACL:
2177 len = sizeof(struct tomoyo_single_path_acl_record);
2178 break;
2179 case TOMOYO_TYPE_DOUBLE_PATH_ACL:
2180 len = sizeof(struct tomoyo_double_path_acl_record);
2181 break;
2182 default:
2183 return NULL;
2184 }
2185 ptr = tomoyo_alloc_element(len);
2186 if (!ptr)
2187 return NULL;
2188 ptr->type = acl_type;
2189 return ptr;
2190}
2191
2192/**
2193 * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface. 2111 * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface.
2194 * 2112 *
2195 * @inode: Pointer to "struct inode". 2113 * @inode: Pointer to "struct inode".
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 92169d29b2db..67bd22dd3e68 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -1,12 +1,9 @@
1/* 1/*
2 * security/tomoyo/common.h 2 * security/tomoyo/common.h
3 * 3 *
4 * Common functions for TOMOYO. 4 * Header file for TOMOYO.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0 2009/04/01
9 * 5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
10 */ 7 */
11 8
12#ifndef _SECURITY_TOMOYO_COMMON_H 9#ifndef _SECURITY_TOMOYO_COMMON_H
@@ -22,9 +19,119 @@
22#include <linux/namei.h> 19#include <linux/namei.h>
23#include <linux/mount.h> 20#include <linux/mount.h>
24#include <linux/list.h> 21#include <linux/list.h>
22#include <linux/cred.h>
23struct linux_binprm;
24
25/********** Constants definitions. **********/
26
27/*
28 * TOMOYO uses this hash only when appending a string into the string
29 * table. Frequency of appending strings is very low. So we don't need
30 * large (e.g. 64k) hash size. 256 will be sufficient.
31 */
32#define TOMOYO_HASH_BITS 8
33#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS)
34
35/*
36 * This is the max length of a token.
37 *
38 * A token consists of only ASCII printable characters.
39 * Non printable characters in a token is represented in \ooo style
40 * octal string. Thus, \ itself is represented as \\.
41 */
42#define TOMOYO_MAX_PATHNAME_LEN 4000
43
44/* Profile number is an integer between 0 and 255. */
45#define TOMOYO_MAX_PROFILES 256
46
47/* Keywords for ACLs. */
48#define TOMOYO_KEYWORD_ALIAS "alias "
49#define TOMOYO_KEYWORD_ALLOW_READ "allow_read "
50#define TOMOYO_KEYWORD_DELETE "delete "
51#define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite "
52#define TOMOYO_KEYWORD_FILE_PATTERN "file_pattern "
53#define TOMOYO_KEYWORD_INITIALIZE_DOMAIN "initialize_domain "
54#define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain "
55#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain "
56#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain "
57#define TOMOYO_KEYWORD_SELECT "select "
58#define TOMOYO_KEYWORD_USE_PROFILE "use_profile "
59#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read"
60/* A domain definition starts with <kernel>. */
61#define TOMOYO_ROOT_NAME "<kernel>"
62#define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1)
63
64/* Index numbers for Access Controls. */
65enum tomoyo_mac_index {
66 TOMOYO_MAC_FOR_FILE, /* domain_policy.conf */
67 TOMOYO_MAX_ACCEPT_ENTRY,
68 TOMOYO_VERBOSE,
69 TOMOYO_MAX_CONTROL_INDEX
70};
71
72/* Index numbers for Access Controls. */
73enum tomoyo_acl_entry_type_index {
74 TOMOYO_TYPE_PATH_ACL,
75 TOMOYO_TYPE_PATH2_ACL,
76};
77
78/* Index numbers for File Controls. */
79
80/*
81 * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set
82 * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and
83 * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set.
84 * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or
85 * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are
86 * automatically cleared if TYPE_READ_WRITE_ACL is cleared.
87 */
88
89enum tomoyo_path_acl_index {
90 TOMOYO_TYPE_READ_WRITE,
91 TOMOYO_TYPE_EXECUTE,
92 TOMOYO_TYPE_READ,
93 TOMOYO_TYPE_WRITE,
94 TOMOYO_TYPE_CREATE,
95 TOMOYO_TYPE_UNLINK,
96 TOMOYO_TYPE_MKDIR,
97 TOMOYO_TYPE_RMDIR,
98 TOMOYO_TYPE_MKFIFO,
99 TOMOYO_TYPE_MKSOCK,
100 TOMOYO_TYPE_MKBLOCK,
101 TOMOYO_TYPE_MKCHAR,
102 TOMOYO_TYPE_TRUNCATE,
103 TOMOYO_TYPE_SYMLINK,
104 TOMOYO_TYPE_REWRITE,
105 TOMOYO_TYPE_IOCTL,
106 TOMOYO_TYPE_CHMOD,
107 TOMOYO_TYPE_CHOWN,
108 TOMOYO_TYPE_CHGRP,
109 TOMOYO_TYPE_CHROOT,
110 TOMOYO_TYPE_MOUNT,
111 TOMOYO_TYPE_UMOUNT,
112 TOMOYO_MAX_PATH_OPERATION
113};
25 114
26struct dentry; 115enum tomoyo_path2_acl_index {
27struct vfsmount; 116 TOMOYO_TYPE_LINK,
117 TOMOYO_TYPE_RENAME,
118 TOMOYO_TYPE_PIVOT_ROOT,
119 TOMOYO_MAX_PATH2_OPERATION
120};
121
122enum tomoyo_securityfs_interface_index {
123 TOMOYO_DOMAINPOLICY,
124 TOMOYO_EXCEPTIONPOLICY,
125 TOMOYO_DOMAIN_STATUS,
126 TOMOYO_PROCESS_STATUS,
127 TOMOYO_MEMINFO,
128 TOMOYO_SELFDOMAIN,
129 TOMOYO_VERSION,
130 TOMOYO_PROFILE,
131 TOMOYO_MANAGER
132};
133
134/********** Structure definitions. **********/
28 135
29/* 136/*
30 * tomoyo_page_buffer is a structure which is used for holding a pathname 137 * tomoyo_page_buffer is a structure which is used for holding a pathname
@@ -66,13 +173,14 @@ struct tomoyo_path_info {
66}; 173};
67 174
68/* 175/*
69 * This is the max length of a token. 176 * tomoyo_name_entry is a structure which is used for linking
70 * 177 * "struct tomoyo_path_info" into tomoyo_name_list .
71 * A token consists of only ASCII printable characters.
72 * Non printable characters in a token is represented in \ooo style
73 * octal string. Thus, \ itself is represented as \\.
74 */ 178 */
75#define TOMOYO_MAX_PATHNAME_LEN 4000 179struct tomoyo_name_entry {
180 struct list_head list;
181 atomic_t users;
182 struct tomoyo_path_info entry;
183};
76 184
77/* 185/*
78 * tomoyo_path_info_with_data is a structure which is used for holding a 186 * tomoyo_path_info_with_data is a structure which is used for holding a
@@ -89,7 +197,7 @@ struct tomoyo_path_info {
89 * "struct tomoyo_path_info_with_data". 197 * "struct tomoyo_path_info_with_data".
90 */ 198 */
91struct tomoyo_path_info_with_data { 199struct tomoyo_path_info_with_data {
92 /* Keep "head" first, for this pointer is passed to tomoyo_free(). */ 200 /* Keep "head" first, for this pointer is passed to kfree(). */
93 struct tomoyo_path_info head; 201 struct tomoyo_path_info head;
94 char barrier1[16]; /* Safeguard for overrun. */ 202 char barrier1[16]; /* Safeguard for overrun. */
95 char body[TOMOYO_MAX_PATHNAME_LEN]; 203 char body[TOMOYO_MAX_PATHNAME_LEN];
@@ -101,30 +209,19 @@ struct tomoyo_path_info_with_data {
101 * 209 *
102 * (1) "list" which is linked to the ->acl_info_list of 210 * (1) "list" which is linked to the ->acl_info_list of
103 * "struct tomoyo_domain_info" 211 * "struct tomoyo_domain_info"
104 * (2) "type" which tells 212 * (2) "type" which tells type of the entry (either
105 * (a) type & 0x7F : type of the entry (either 213 * "struct tomoyo_path_acl" or "struct tomoyo_path2_acl").
106 * "struct tomoyo_single_path_acl_record" or
107 * "struct tomoyo_double_path_acl_record")
108 * (b) type & 0x80 : whether the entry is marked as "deleted".
109 * 214 *
110 * Packing "struct tomoyo_acl_info" allows 215 * Packing "struct tomoyo_acl_info" allows
111 * "struct tomoyo_single_path_acl_record" to embed "u16" and 216 * "struct tomoyo_path_acl" to embed "u8" + "u16" and
112 * "struct tomoyo_double_path_acl_record" to embed "u8" 217 * "struct tomoyo_path2_acl" to embed "u8"
113 * without enlarging their structure size. 218 * without enlarging their structure size.
114 */ 219 */
115struct tomoyo_acl_info { 220struct tomoyo_acl_info {
116 struct list_head list; 221 struct list_head list;
117 /*
118 * Type of this ACL entry.
119 *
120 * MSB is is_deleted flag.
121 */
122 u8 type; 222 u8 type;
123} __packed; 223} __packed;
124 224
125/* This ACL entry is deleted. */
126#define TOMOYO_ACL_DELETED 0x80
127
128/* 225/*
129 * tomoyo_domain_info is a structure which is used for holding permissions 226 * tomoyo_domain_info is a structure which is used for holding permissions
130 * (e.g. "allow_read /lib/libc-2.5.so") given to each domain. 227 * (e.g. "allow_read /lib/libc-2.5.so") given to each domain.
@@ -138,7 +235,17 @@ struct tomoyo_acl_info {
138 * "deleted", false otherwise. 235 * "deleted", false otherwise.
139 * (6) "quota_warned" is a bool which is used for suppressing warning message 236 * (6) "quota_warned" is a bool which is used for suppressing warning message
140 * when learning mode learned too much entries. 237 * when learning mode learned too much entries.
141 * (7) "flags" which remembers this domain's attributes. 238 * (7) "ignore_global_allow_read" is a bool which is true if this domain
239 * should ignore "allow_read" directive in exception policy.
240 * (8) "transition_failed" is a bool which is set to true when this domain was
241 * unable to create a new domain at tomoyo_find_next_domain() because the
242 * name of the domain to be created was too long or it could not allocate
243 * memory. If set to true, more than one process continued execve()
244 * without domain transition.
245 * (9) "users" is an atomic_t that holds how many "struct cred"->security
246 * are referring this "struct tomoyo_domain_info". If is_deleted == true
247 * and users == 0, this struct will be kfree()d upon next garbage
248 * collection.
142 * 249 *
143 * A domain's lifecycle is an analogy of files on / directory. 250 * A domain's lifecycle is an analogy of files on / directory.
144 * Multiple domains with the same domainname cannot be created (as with 251 * Multiple domains with the same domainname cannot be created (as with
@@ -155,25 +262,13 @@ struct tomoyo_domain_info {
155 u8 profile; /* Profile number to use. */ 262 u8 profile; /* Profile number to use. */
156 bool is_deleted; /* Delete flag. */ 263 bool is_deleted; /* Delete flag. */
157 bool quota_warned; /* Quota warnning flag. */ 264 bool quota_warned; /* Quota warnning flag. */
158 /* DOMAIN_FLAGS_*. Use tomoyo_set_domain_flag() to modify. */ 265 bool ignore_global_allow_read; /* Ignore "allow_read" flag. */
159 u8 flags; 266 bool transition_failed; /* Domain transition failed flag. */
267 atomic_t users; /* Number of referring credentials. */
160}; 268};
161 269
162/* Profile number is an integer between 0 and 255. */
163#define TOMOYO_MAX_PROFILES 256
164
165/* Ignore "allow_read" directive in exception policy. */
166#define TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ 1
167/*
168 * This domain was unable to create a new domain at tomoyo_find_next_domain()
169 * because the name of the domain to be created was too long or
170 * it could not allocate memory.
171 * More than one process continued execve() without domain transition.
172 */
173#define TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED 2
174
175/* 270/*
176 * tomoyo_single_path_acl_record is a structure which is used for holding an 271 * tomoyo_path_acl is a structure which is used for holding an
177 * entry with one pathname operation (e.g. open(), mkdir()). 272 * entry with one pathname operation (e.g. open(), mkdir()).
178 * It has following fields. 273 * It has following fields.
179 * 274 *
@@ -184,18 +279,21 @@ struct tomoyo_domain_info {
184 * Directives held by this structure are "allow_read/write", "allow_execute", 279 * Directives held by this structure are "allow_read/write", "allow_execute",
185 * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", 280 * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir",
186 * "allow_rmdir", "allow_mkfifo", "allow_mksock", "allow_mkblock", 281 * "allow_rmdir", "allow_mkfifo", "allow_mksock", "allow_mkblock",
187 * "allow_mkchar", "allow_truncate", "allow_symlink" and "allow_rewrite". 282 * "allow_mkchar", "allow_truncate", "allow_symlink", "allow_rewrite",
283 * "allow_chmod", "allow_chown", "allow_chgrp", "allow_chroot", "allow_mount"
284 * and "allow_unmount".
188 */ 285 */
189struct tomoyo_single_path_acl_record { 286struct tomoyo_path_acl {
190 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_SINGLE_PATH_ACL */ 287 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */
288 u8 perm_high;
191 u16 perm; 289 u16 perm;
192 /* Pointer to single pathname. */ 290 /* Pointer to single pathname. */
193 const struct tomoyo_path_info *filename; 291 const struct tomoyo_path_info *filename;
194}; 292};
195 293
196/* 294/*
197 * tomoyo_double_path_acl_record is a structure which is used for holding an 295 * tomoyo_path2_acl is a structure which is used for holding an
198 * entry with two pathnames operation (i.e. link() and rename()). 296 * entry with two pathnames operation (i.e. link(), rename() and pivot_root()).
199 * It has following fields. 297 * It has following fields.
200 * 298 *
201 * (1) "head" which is a "struct tomoyo_acl_info". 299 * (1) "head" which is a "struct tomoyo_acl_info".
@@ -203,10 +301,11 @@ struct tomoyo_single_path_acl_record {
203 * (3) "filename1" is the source/old pathname. 301 * (3) "filename1" is the source/old pathname.
204 * (4) "filename2" is the destination/new pathname. 302 * (4) "filename2" is the destination/new pathname.
205 * 303 *
206 * Directives held by this structure are "allow_rename" and "allow_link". 304 * Directives held by this structure are "allow_rename", "allow_link" and
305 * "allow_pivot_root".
207 */ 306 */
208struct tomoyo_double_path_acl_record { 307struct tomoyo_path2_acl {
209 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_DOUBLE_PATH_ACL */ 308 struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */
210 u8 perm; 309 u8 perm;
211 /* Pointer to single pathname. */ 310 /* Pointer to single pathname. */
212 const struct tomoyo_path_info *filename1; 311 const struct tomoyo_path_info *filename1;
@@ -214,29 +313,6 @@ struct tomoyo_double_path_acl_record {
214 const struct tomoyo_path_info *filename2; 313 const struct tomoyo_path_info *filename2;
215}; 314};
216 315
217/* Keywords for ACLs. */
218#define TOMOYO_KEYWORD_ALIAS "alias "
219#define TOMOYO_KEYWORD_ALLOW_READ "allow_read "
220#define TOMOYO_KEYWORD_DELETE "delete "
221#define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite "
222#define TOMOYO_KEYWORD_FILE_PATTERN "file_pattern "
223#define TOMOYO_KEYWORD_INITIALIZE_DOMAIN "initialize_domain "
224#define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain "
225#define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain "
226#define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain "
227#define TOMOYO_KEYWORD_SELECT "select "
228#define TOMOYO_KEYWORD_USE_PROFILE "use_profile "
229#define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read"
230/* A domain definition starts with <kernel>. */
231#define TOMOYO_ROOT_NAME "<kernel>"
232#define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1)
233
234/* Index numbers for Access Controls. */
235#define TOMOYO_MAC_FOR_FILE 0 /* domain_policy.conf */
236#define TOMOYO_MAX_ACCEPT_ENTRY 1
237#define TOMOYO_VERBOSE 2
238#define TOMOYO_MAX_CONTROL_INDEX 3
239
240/* 316/*
241 * tomoyo_io_buffer is a structure which is used for reading and modifying 317 * tomoyo_io_buffer is a structure which is used for reading and modifying
242 * configuration via /sys/kernel/security/tomoyo/ interface. 318 * configuration via /sys/kernel/security/tomoyo/ interface.
@@ -265,6 +341,8 @@ struct tomoyo_io_buffer {
265 int (*write) (struct tomoyo_io_buffer *); 341 int (*write) (struct tomoyo_io_buffer *);
266 /* Exclusive lock for this structure. */ 342 /* Exclusive lock for this structure. */
267 struct mutex io_sem; 343 struct mutex io_sem;
344 /* Index returned by tomoyo_read_lock(). */
345 int reader_idx;
268 /* The position currently reading from. */ 346 /* The position currently reading from. */
269 struct list_head *read_var1; 347 struct list_head *read_var1;
270 /* Extra variables for reading. */ 348 /* Extra variables for reading. */
@@ -293,18 +371,159 @@ struct tomoyo_io_buffer {
293 int writebuf_size; 371 int writebuf_size;
294}; 372};
295 373
374/*
375 * tomoyo_globally_readable_file_entry is a structure which is used for holding
376 * "allow_read" entries.
377 * It has following fields.
378 *
379 * (1) "list" which is linked to tomoyo_globally_readable_list .
380 * (2) "filename" is a pathname which is allowed to open(O_RDONLY).
381 * (3) "is_deleted" is a bool which is true if marked as deleted, false
382 * otherwise.
383 */
384struct tomoyo_globally_readable_file_entry {
385 struct list_head list;
386 const struct tomoyo_path_info *filename;
387 bool is_deleted;
388};
389
390/*
391 * tomoyo_pattern_entry is a structure which is used for holding
392 * "tomoyo_pattern_list" entries.
393 * It has following fields.
394 *
395 * (1) "list" which is linked to tomoyo_pattern_list .
396 * (2) "pattern" is a pathname pattern which is used for converting pathnames
397 * to pathname patterns during learning mode.
398 * (3) "is_deleted" is a bool which is true if marked as deleted, false
399 * otherwise.
400 */
401struct tomoyo_pattern_entry {
402 struct list_head list;
403 const struct tomoyo_path_info *pattern;
404 bool is_deleted;
405};
406
407/*
408 * tomoyo_no_rewrite_entry is a structure which is used for holding
409 * "deny_rewrite" entries.
410 * It has following fields.
411 *
412 * (1) "list" which is linked to tomoyo_no_rewrite_list .
413 * (2) "pattern" is a pathname which is by default not permitted to modify
414 * already existing content.
415 * (3) "is_deleted" is a bool which is true if marked as deleted, false
416 * otherwise.
417 */
418struct tomoyo_no_rewrite_entry {
419 struct list_head list;
420 const struct tomoyo_path_info *pattern;
421 bool is_deleted;
422};
423
424/*
425 * tomoyo_domain_initializer_entry is a structure which is used for holding
426 * "initialize_domain" and "no_initialize_domain" entries.
427 * It has following fields.
428 *
429 * (1) "list" which is linked to tomoyo_domain_initializer_list .
430 * (2) "domainname" which is "a domainname" or "the last component of a
431 * domainname". This field is NULL if "from" clause is not specified.
432 * (3) "program" which is a program's pathname.
433 * (4) "is_deleted" is a bool which is true if marked as deleted, false
434 * otherwise.
435 * (5) "is_not" is a bool which is true if "no_initialize_domain", false
436 * otherwise.
437 * (6) "is_last_name" is a bool which is true if "domainname" is "the last
438 * component of a domainname", false otherwise.
439 */
440struct tomoyo_domain_initializer_entry {
441 struct list_head list;
442 const struct tomoyo_path_info *domainname; /* This may be NULL */
443 const struct tomoyo_path_info *program;
444 bool is_deleted;
445 bool is_not; /* True if this entry is "no_initialize_domain". */
446 /* True if the domainname is tomoyo_get_last_name(). */
447 bool is_last_name;
448};
449
450/*
451 * tomoyo_domain_keeper_entry is a structure which is used for holding
452 * "keep_domain" and "no_keep_domain" entries.
453 * It has following fields.
454 *
455 * (1) "list" which is linked to tomoyo_domain_keeper_list .
456 * (2) "domainname" which is "a domainname" or "the last component of a
457 * domainname".
458 * (3) "program" which is a program's pathname.
459 * This field is NULL if "from" clause is not specified.
460 * (4) "is_deleted" is a bool which is true if marked as deleted, false
461 * otherwise.
462 * (5) "is_not" is a bool which is true if "no_initialize_domain", false
463 * otherwise.
464 * (6) "is_last_name" is a bool which is true if "domainname" is "the last
465 * component of a domainname", false otherwise.
466 */
467struct tomoyo_domain_keeper_entry {
468 struct list_head list;
469 const struct tomoyo_path_info *domainname;
470 const struct tomoyo_path_info *program; /* This may be NULL */
471 bool is_deleted;
472 bool is_not; /* True if this entry is "no_keep_domain". */
473 /* True if the domainname is tomoyo_get_last_name(). */
474 bool is_last_name;
475};
476
477/*
478 * tomoyo_alias_entry is a structure which is used for holding "alias" entries.
479 * It has following fields.
480 *
481 * (1) "list" which is linked to tomoyo_alias_list .
482 * (2) "original_name" which is a dereferenced pathname.
483 * (3) "aliased_name" which is a symlink's pathname.
484 * (4) "is_deleted" is a bool which is true if marked as deleted, false
485 * otherwise.
486 */
487struct tomoyo_alias_entry {
488 struct list_head list;
489 const struct tomoyo_path_info *original_name;
490 const struct tomoyo_path_info *aliased_name;
491 bool is_deleted;
492};
493
494/*
495 * tomoyo_policy_manager_entry is a structure which is used for holding list of
496 * domainnames or programs which are permitted to modify configuration via
497 * /sys/kernel/security/tomoyo/ interface.
498 * It has following fields.
499 *
500 * (1) "list" which is linked to tomoyo_policy_manager_list .
501 * (2) "manager" is a domainname or a program's pathname.
502 * (3) "is_domain" is a bool which is true if "manager" is a domainname, false
503 * otherwise.
504 * (4) "is_deleted" is a bool which is true if marked as deleted, false
505 * otherwise.
506 */
507struct tomoyo_policy_manager_entry {
508 struct list_head list;
509 /* A path to program or a domainname. */
510 const struct tomoyo_path_info *manager;
511 bool is_domain; /* True if manager is a domainname. */
512 bool is_deleted; /* True if this entry is deleted. */
513};
514
515/********** Function prototypes. **********/
516
296/* Check whether the domain has too many ACL entries to hold. */ 517/* Check whether the domain has too many ACL entries to hold. */
297bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); 518bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain);
298/* Transactional sprintf() for policy dump. */ 519/* Transactional sprintf() for policy dump. */
299bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) 520bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
300 __attribute__ ((format(printf, 2, 3))); 521 __attribute__ ((format(printf, 2, 3)));
301/* Check whether the domainname is correct. */ 522/* Check whether the domainname is correct. */
302bool tomoyo_is_correct_domain(const unsigned char *domainname, 523bool tomoyo_is_correct_domain(const unsigned char *domainname);
303 const char *function);
304/* Check whether the token is correct. */ 524/* Check whether the token is correct. */
305bool tomoyo_is_correct_path(const char *filename, const s8 start_type, 525bool tomoyo_is_correct_path(const char *filename, const s8 start_type,
306 const s8 pattern_type, const s8 end_type, 526 const s8 pattern_type, const s8 end_type);
307 const char *function);
308/* Check whether the token can be a domainname. */ 527/* Check whether the token can be a domainname. */
309bool tomoyo_is_domain_def(const unsigned char *buffer); 528bool tomoyo_is_domain_def(const unsigned char *buffer);
310/* Check whether the given filename matches the given pattern. */ 529/* Check whether the given filename matches the given pattern. */
@@ -328,13 +547,13 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head);
328/* Write domain policy violation warning message to console? */ 547/* Write domain policy violation warning message to console? */
329bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); 548bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain);
330/* Convert double path operation to operation name. */ 549/* Convert double path operation to operation name. */
331const char *tomoyo_dp2keyword(const u8 operation); 550const char *tomoyo_path22keyword(const u8 operation);
332/* Get the last component of the given domainname. */ 551/* Get the last component of the given domainname. */
333const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); 552const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain);
334/* Get warning message. */ 553/* Get warning message. */
335const char *tomoyo_get_msg(const bool is_enforce); 554const char *tomoyo_get_msg(const bool is_enforce);
336/* Convert single path operation to operation name. */ 555/* Convert single path operation to operation name. */
337const char *tomoyo_sp2keyword(const u8 operation); 556const char *tomoyo_path2keyword(const u8 operation);
338/* Create "alias" entry in exception policy. */ 557/* Create "alias" entry in exception policy. */
339int tomoyo_write_alias_policy(char *data, const bool is_delete); 558int tomoyo_write_alias_policy(char *data, const bool is_delete);
340/* 559/*
@@ -370,33 +589,107 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
370/* Check mode for specified functionality. */ 589/* Check mode for specified functionality. */
371unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, 590unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
372 const u8 index); 591 const u8 index);
373/* Allocate memory for structures. */
374void *tomoyo_alloc_acl_element(const u8 acl_type);
375/* Fill in "struct tomoyo_path_info" members. */ 592/* Fill in "struct tomoyo_path_info" members. */
376void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); 593void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
377/* Run policy loader when /sbin/init starts. */ 594/* Run policy loader when /sbin/init starts. */
378void tomoyo_load_policy(const char *filename); 595void tomoyo_load_policy(const char *filename);
379/* Change "struct tomoyo_domain_info"->flags. */
380void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
381 const bool is_delete, const u8 flags);
382 596
383/* strcmp() for "struct tomoyo_path_info" structure. */ 597/* Convert binary string to ascii string. */
384static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, 598int tomoyo_encode(char *buffer, int buflen, const char *str);
385 const struct tomoyo_path_info *b) 599
600/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
601int tomoyo_realpath_from_path2(struct path *path, char *newname,
602 int newname_len);
603
604/*
605 * Returns realpath(3) of the given pathname but ignores chroot'ed root.
606 * These functions use kzalloc(), so the caller must call kfree()
607 * if these functions didn't return NULL.
608 */
609char *tomoyo_realpath(const char *pathname);
610/*
611 * Same with tomoyo_realpath() except that it doesn't follow the final symlink.
612 */
613char *tomoyo_realpath_nofollow(const char *pathname);
614/* Same with tomoyo_realpath() except that the pathname is already solved. */
615char *tomoyo_realpath_from_path(struct path *path);
616
617/* Check memory quota. */
618bool tomoyo_memory_ok(void *ptr);
619
620/*
621 * Keep the given name on the RAM.
622 * The RAM is shared, so NEVER try to modify or kfree() the returned name.
623 */
624const struct tomoyo_path_info *tomoyo_get_name(const char *name);
625
626/* Check for memory usage. */
627int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head);
628
629/* Set memory quota. */
630int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head);
631
632/* Initialize realpath related code. */
633void __init tomoyo_realpath_init(void);
634int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
635 const struct tomoyo_path_info *filename);
636int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
637 struct path *path, const int flag);
638int tomoyo_path_perm(const u8 operation, struct path *path);
639int tomoyo_path2_perm(const u8 operation, struct path *path1,
640 struct path *path2);
641int tomoyo_check_rewrite_permission(struct file *filp);
642int tomoyo_find_next_domain(struct linux_binprm *bprm);
643
644/* Run garbage collector. */
645void tomoyo_run_gc(void);
646
647void tomoyo_memory_free(void *ptr);
648
649/********** External variable definitions. **********/
650
651/* Lock for GC. */
652extern struct srcu_struct tomoyo_ss;
653
654/* The list for "struct tomoyo_domain_info". */
655extern struct list_head tomoyo_domain_list;
656
657extern struct list_head tomoyo_domain_initializer_list;
658extern struct list_head tomoyo_domain_keeper_list;
659extern struct list_head tomoyo_alias_list;
660extern struct list_head tomoyo_globally_readable_list;
661extern struct list_head tomoyo_pattern_list;
662extern struct list_head tomoyo_no_rewrite_list;
663extern struct list_head tomoyo_policy_manager_list;
664extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
665extern struct mutex tomoyo_name_list_lock;
666
667/* Lock for protecting policy. */
668extern struct mutex tomoyo_policy_lock;
669
670/* Has /sbin/init started? */
671extern bool tomoyo_policy_loaded;
672
673/* The kernel's domain. */
674extern struct tomoyo_domain_info tomoyo_kernel_domain;
675
676/********** Inlined functions. **********/
677
678static inline int tomoyo_read_lock(void)
386{ 679{
387 return a->hash != b->hash || strcmp(a->name, b->name); 680 return srcu_read_lock(&tomoyo_ss);
388} 681}
389 682
390/* Get type of an ACL entry. */ 683static inline void tomoyo_read_unlock(int idx)
391static inline u8 tomoyo_acl_type1(struct tomoyo_acl_info *ptr)
392{ 684{
393 return ptr->type & ~TOMOYO_ACL_DELETED; 685 srcu_read_unlock(&tomoyo_ss, idx);
394} 686}
395 687
396/* Get type of an ACL entry. */ 688/* strcmp() for "struct tomoyo_path_info" structure. */
397static inline u8 tomoyo_acl_type2(struct tomoyo_acl_info *ptr) 689static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a,
690 const struct tomoyo_path_info *b)
398{ 691{
399 return ptr->type; 692 return a->hash != b->hash || strcmp(a->name, b->name);
400} 693}
401 694
402/** 695/**
@@ -423,18 +716,25 @@ static inline bool tomoyo_is_invalid(const unsigned char c)
423 return c && (c <= ' ' || c >= 127); 716 return c && (c <= ' ' || c >= 127);
424} 717}
425 718
426/* The list for "struct tomoyo_domain_info". */ 719static inline void tomoyo_put_name(const struct tomoyo_path_info *name)
427extern struct list_head tomoyo_domain_list; 720{
428extern struct rw_semaphore tomoyo_domain_list_lock; 721 if (name) {
429 722 struct tomoyo_name_entry *ptr =
430/* Lock for domain->acl_info_list. */ 723 container_of(name, struct tomoyo_name_entry, entry);
431extern struct rw_semaphore tomoyo_domain_acl_info_list_lock; 724 atomic_dec(&ptr->users);
725 }
726}
432 727
433/* Has /sbin/init started? */ 728static inline struct tomoyo_domain_info *tomoyo_domain(void)
434extern bool tomoyo_policy_loaded; 729{
730 return current_cred()->security;
731}
435 732
436/* The kernel's domain. */ 733static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
437extern struct tomoyo_domain_info tomoyo_kernel_domain; 734 *task)
735{
736 return task_cred_xxx(task, security);
737}
438 738
439/** 739/**
440 * list_for_each_cookie - iterate over a list with cookie. 740 * list_for_each_cookie - iterate over a list with cookie.
@@ -442,16 +742,16 @@ extern struct tomoyo_domain_info tomoyo_kernel_domain;
442 * @cookie: the &struct list_head to use as a cookie. 742 * @cookie: the &struct list_head to use as a cookie.
443 * @head: the head for your list. 743 * @head: the head for your list.
444 * 744 *
445 * Same with list_for_each() except that this primitive uses @cookie 745 * Same with list_for_each_rcu() except that this primitive uses @cookie
446 * so that we can continue iteration. 746 * so that we can continue iteration.
447 * @cookie must be NULL when iteration starts, and @cookie will become 747 * @cookie must be NULL when iteration starts, and @cookie will become
448 * NULL when iteration finishes. 748 * NULL when iteration finishes.
449 */ 749 */
450#define list_for_each_cookie(pos, cookie, head) \ 750#define list_for_each_cookie(pos, cookie, head) \
451 for (({ if (!cookie) \ 751 for (({ if (!cookie) \
452 cookie = head; }), \ 752 cookie = head; }), \
453 pos = (cookie)->next; \ 753 pos = rcu_dereference((cookie)->next); \
454 prefetch(pos->next), pos != (head) || ((cookie) = NULL); \ 754 prefetch(pos->next), pos != (head) || ((cookie) = NULL); \
455 (cookie) = pos, pos = pos->next) 755 (cookie) = pos, pos = rcu_dereference(pos->next))
456 756
457#endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ 757#endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index fcf52accce2b..66caaa1b842a 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -10,8 +10,6 @@
10 */ 10 */
11 11
12#include "common.h" 12#include "common.h"
13#include "tomoyo.h"
14#include "realpath.h"
15#include <linux/binfmts.h> 13#include <linux/binfmts.h>
16 14
17/* Variables definitions.*/ 15/* Variables definitions.*/
@@ -58,99 +56,6 @@ struct tomoyo_domain_info tomoyo_kernel_domain;
58 * exceptions. 56 * exceptions.
59 */ 57 */
60LIST_HEAD(tomoyo_domain_list); 58LIST_HEAD(tomoyo_domain_list);
61DECLARE_RWSEM(tomoyo_domain_list_lock);
62
63/*
64 * tomoyo_domain_initializer_entry is a structure which is used for holding
65 * "initialize_domain" and "no_initialize_domain" entries.
66 * It has following fields.
67 *
68 * (1) "list" which is linked to tomoyo_domain_initializer_list .
69 * (2) "domainname" which is "a domainname" or "the last component of a
70 * domainname". This field is NULL if "from" clause is not specified.
71 * (3) "program" which is a program's pathname.
72 * (4) "is_deleted" is a bool which is true if marked as deleted, false
73 * otherwise.
74 * (5) "is_not" is a bool which is true if "no_initialize_domain", false
75 * otherwise.
76 * (6) "is_last_name" is a bool which is true if "domainname" is "the last
77 * component of a domainname", false otherwise.
78 */
79struct tomoyo_domain_initializer_entry {
80 struct list_head list;
81 const struct tomoyo_path_info *domainname; /* This may be NULL */
82 const struct tomoyo_path_info *program;
83 bool is_deleted;
84 bool is_not; /* True if this entry is "no_initialize_domain". */
85 /* True if the domainname is tomoyo_get_last_name(). */
86 bool is_last_name;
87};
88
89/*
90 * tomoyo_domain_keeper_entry is a structure which is used for holding
91 * "keep_domain" and "no_keep_domain" entries.
92 * It has following fields.
93 *
94 * (1) "list" which is linked to tomoyo_domain_keeper_list .
95 * (2) "domainname" which is "a domainname" or "the last component of a
96 * domainname".
97 * (3) "program" which is a program's pathname.
98 * This field is NULL if "from" clause is not specified.
99 * (4) "is_deleted" is a bool which is true if marked as deleted, false
100 * otherwise.
101 * (5) "is_not" is a bool which is true if "no_initialize_domain", false
102 * otherwise.
103 * (6) "is_last_name" is a bool which is true if "domainname" is "the last
104 * component of a domainname", false otherwise.
105 */
106struct tomoyo_domain_keeper_entry {
107 struct list_head list;
108 const struct tomoyo_path_info *domainname;
109 const struct tomoyo_path_info *program; /* This may be NULL */
110 bool is_deleted;
111 bool is_not; /* True if this entry is "no_keep_domain". */
112 /* True if the domainname is tomoyo_get_last_name(). */
113 bool is_last_name;
114};
115
116/*
117 * tomoyo_alias_entry is a structure which is used for holding "alias" entries.
118 * It has following fields.
119 *
120 * (1) "list" which is linked to tomoyo_alias_list .
121 * (2) "original_name" which is a dereferenced pathname.
122 * (3) "aliased_name" which is a symlink's pathname.
123 * (4) "is_deleted" is a bool which is true if marked as deleted, false
124 * otherwise.
125 */
126struct tomoyo_alias_entry {
127 struct list_head list;
128 const struct tomoyo_path_info *original_name;
129 const struct tomoyo_path_info *aliased_name;
130 bool is_deleted;
131};
132
133/**
134 * tomoyo_set_domain_flag - Set or clear domain's attribute flags.
135 *
136 * @domain: Pointer to "struct tomoyo_domain_info".
137 * @is_delete: True if it is a delete request.
138 * @flags: Flags to set or clear.
139 *
140 * Returns nothing.
141 */
142void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain,
143 const bool is_delete, const u8 flags)
144{
145 /* We need to serialize because this is bitfield operation. */
146 static DEFINE_SPINLOCK(lock);
147 spin_lock(&lock);
148 if (!is_delete)
149 domain->flags |= flags;
150 else
151 domain->flags &= ~flags;
152 spin_unlock(&lock);
153}
154 59
155/** 60/**
156 * tomoyo_get_last_name - Get last component of a domainname. 61 * tomoyo_get_last_name - Get last component of a domainname.
@@ -205,8 +110,7 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
205 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain 110 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain
206 * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain. 111 * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain.
207 */ 112 */
208static LIST_HEAD(tomoyo_domain_initializer_list); 113LIST_HEAD(tomoyo_domain_initializer_list);
209static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock);
210 114
211/** 115/**
212 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. 116 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
@@ -217,59 +121,65 @@ static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock);
217 * @is_delete: True if it is a delete request. 121 * @is_delete: True if it is a delete request.
218 * 122 *
219 * Returns 0 on success, negative value otherwise. 123 * Returns 0 on success, negative value otherwise.
124 *
125 * Caller holds tomoyo_read_lock().
220 */ 126 */
221static int tomoyo_update_domain_initializer_entry(const char *domainname, 127static int tomoyo_update_domain_initializer_entry(const char *domainname,
222 const char *program, 128 const char *program,
223 const bool is_not, 129 const bool is_not,
224 const bool is_delete) 130 const bool is_delete)
225{ 131{
226 struct tomoyo_domain_initializer_entry *new_entry; 132 struct tomoyo_domain_initializer_entry *entry = NULL;
227 struct tomoyo_domain_initializer_entry *ptr; 133 struct tomoyo_domain_initializer_entry *ptr;
228 const struct tomoyo_path_info *saved_program; 134 const struct tomoyo_path_info *saved_program = NULL;
229 const struct tomoyo_path_info *saved_domainname = NULL; 135 const struct tomoyo_path_info *saved_domainname = NULL;
230 int error = -ENOMEM; 136 int error = is_delete ? -ENOENT : -ENOMEM;
231 bool is_last_name = false; 137 bool is_last_name = false;
232 138
233 if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) 139 if (!tomoyo_is_correct_path(program, 1, -1, -1))
234 return -EINVAL; /* No patterns allowed. */ 140 return -EINVAL; /* No patterns allowed. */
235 if (domainname) { 141 if (domainname) {
236 if (!tomoyo_is_domain_def(domainname) && 142 if (!tomoyo_is_domain_def(domainname) &&
237 tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) 143 tomoyo_is_correct_path(domainname, 1, -1, -1))
238 is_last_name = true; 144 is_last_name = true;
239 else if (!tomoyo_is_correct_domain(domainname, __func__)) 145 else if (!tomoyo_is_correct_domain(domainname))
240 return -EINVAL; 146 return -EINVAL;
241 saved_domainname = tomoyo_save_name(domainname); 147 saved_domainname = tomoyo_get_name(domainname);
242 if (!saved_domainname) 148 if (!saved_domainname)
243 return -ENOMEM; 149 goto out;
244 } 150 }
245 saved_program = tomoyo_save_name(program); 151 saved_program = tomoyo_get_name(program);
246 if (!saved_program) 152 if (!saved_program)
247 return -ENOMEM; 153 goto out;
248 down_write(&tomoyo_domain_initializer_list_lock); 154 if (!is_delete)
249 list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { 155 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
156 mutex_lock(&tomoyo_policy_lock);
157 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
250 if (ptr->is_not != is_not || 158 if (ptr->is_not != is_not ||
251 ptr->domainname != saved_domainname || 159 ptr->domainname != saved_domainname ||
252 ptr->program != saved_program) 160 ptr->program != saved_program)
253 continue; 161 continue;
254 ptr->is_deleted = is_delete; 162 ptr->is_deleted = is_delete;
255 error = 0; 163 error = 0;
256 goto out; 164 break;
257 } 165 }
258 if (is_delete) { 166 if (!is_delete && error && tomoyo_memory_ok(entry)) {
259 error = -ENOENT; 167 entry->domainname = saved_domainname;
260 goto out; 168 saved_domainname = NULL;
169 entry->program = saved_program;
170 saved_program = NULL;
171 entry->is_not = is_not;
172 entry->is_last_name = is_last_name;
173 list_add_tail_rcu(&entry->list,
174 &tomoyo_domain_initializer_list);
175 entry = NULL;
176 error = 0;
261 } 177 }
262 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 178 mutex_unlock(&tomoyo_policy_lock);
263 if (!new_entry)
264 goto out;
265 new_entry->domainname = saved_domainname;
266 new_entry->program = saved_program;
267 new_entry->is_not = is_not;
268 new_entry->is_last_name = is_last_name;
269 list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list);
270 error = 0;
271 out: 179 out:
272 up_write(&tomoyo_domain_initializer_list_lock); 180 tomoyo_put_name(saved_domainname);
181 tomoyo_put_name(saved_program);
182 kfree(entry);
273 return error; 183 return error;
274} 184}
275 185
@@ -279,13 +189,14 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
279 * @head: Pointer to "struct tomoyo_io_buffer". 189 * @head: Pointer to "struct tomoyo_io_buffer".
280 * 190 *
281 * Returns true on success, false otherwise. 191 * Returns true on success, false otherwise.
192 *
193 * Caller holds tomoyo_read_lock().
282 */ 194 */
283bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) 195bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
284{ 196{
285 struct list_head *pos; 197 struct list_head *pos;
286 bool done = true; 198 bool done = true;
287 199
288 down_read(&tomoyo_domain_initializer_list_lock);
289 list_for_each_cookie(pos, head->read_var2, 200 list_for_each_cookie(pos, head->read_var2,
290 &tomoyo_domain_initializer_list) { 201 &tomoyo_domain_initializer_list) {
291 const char *no; 202 const char *no;
@@ -308,7 +219,6 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
308 if (!done) 219 if (!done)
309 break; 220 break;
310 } 221 }
311 up_read(&tomoyo_domain_initializer_list_lock);
312 return done; 222 return done;
313} 223}
314 224
@@ -320,6 +230,8 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head)
320 * @is_delete: True if it is a delete request. 230 * @is_delete: True if it is a delete request.
321 * 231 *
322 * Returns 0 on success, negative value otherwise. 232 * Returns 0 on success, negative value otherwise.
233 *
234 * Caller holds tomoyo_read_lock().
323 */ 235 */
324int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, 236int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
325 const bool is_delete) 237 const bool is_delete)
@@ -345,6 +257,8 @@ int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
345 * 257 *
346 * Returns true if executing @program reinitializes domain transition, 258 * Returns true if executing @program reinitializes domain transition,
347 * false otherwise. 259 * false otherwise.
260 *
261 * Caller holds tomoyo_read_lock().
348 */ 262 */
349static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * 263static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
350 domainname, 264 domainname,
@@ -355,8 +269,7 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
355 struct tomoyo_domain_initializer_entry *ptr; 269 struct tomoyo_domain_initializer_entry *ptr;
356 bool flag = false; 270 bool flag = false;
357 271
358 down_read(&tomoyo_domain_initializer_list_lock); 272 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
359 list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) {
360 if (ptr->is_deleted) 273 if (ptr->is_deleted)
361 continue; 274 continue;
362 if (ptr->domainname) { 275 if (ptr->domainname) {
@@ -376,7 +289,6 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
376 } 289 }
377 flag = true; 290 flag = true;
378 } 291 }
379 up_read(&tomoyo_domain_initializer_list_lock);
380 return flag; 292 return flag;
381} 293}
382 294
@@ -418,8 +330,7 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info *
418 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless 330 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless
419 * explicitly specified by "initialize_domain". 331 * explicitly specified by "initialize_domain".
420 */ 332 */
421static LIST_HEAD(tomoyo_domain_keeper_list); 333LIST_HEAD(tomoyo_domain_keeper_list);
422static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock);
423 334
424/** 335/**
425 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. 336 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
@@ -430,59 +341,64 @@ static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock);
430 * @is_delete: True if it is a delete request. 341 * @is_delete: True if it is a delete request.
431 * 342 *
432 * Returns 0 on success, negative value otherwise. 343 * Returns 0 on success, negative value otherwise.
344 *
345 * Caller holds tomoyo_read_lock().
433 */ 346 */
434static int tomoyo_update_domain_keeper_entry(const char *domainname, 347static int tomoyo_update_domain_keeper_entry(const char *domainname,
435 const char *program, 348 const char *program,
436 const bool is_not, 349 const bool is_not,
437 const bool is_delete) 350 const bool is_delete)
438{ 351{
439 struct tomoyo_domain_keeper_entry *new_entry; 352 struct tomoyo_domain_keeper_entry *entry = NULL;
440 struct tomoyo_domain_keeper_entry *ptr; 353 struct tomoyo_domain_keeper_entry *ptr;
441 const struct tomoyo_path_info *saved_domainname; 354 const struct tomoyo_path_info *saved_domainname = NULL;
442 const struct tomoyo_path_info *saved_program = NULL; 355 const struct tomoyo_path_info *saved_program = NULL;
443 int error = -ENOMEM; 356 int error = is_delete ? -ENOENT : -ENOMEM;
444 bool is_last_name = false; 357 bool is_last_name = false;
445 358
446 if (!tomoyo_is_domain_def(domainname) && 359 if (!tomoyo_is_domain_def(domainname) &&
447 tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) 360 tomoyo_is_correct_path(domainname, 1, -1, -1))
448 is_last_name = true; 361 is_last_name = true;
449 else if (!tomoyo_is_correct_domain(domainname, __func__)) 362 else if (!tomoyo_is_correct_domain(domainname))
450 return -EINVAL; 363 return -EINVAL;
451 if (program) { 364 if (program) {
452 if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) 365 if (!tomoyo_is_correct_path(program, 1, -1, -1))
453 return -EINVAL; 366 return -EINVAL;
454 saved_program = tomoyo_save_name(program); 367 saved_program = tomoyo_get_name(program);
455 if (!saved_program) 368 if (!saved_program)
456 return -ENOMEM; 369 goto out;
457 } 370 }
458 saved_domainname = tomoyo_save_name(domainname); 371 saved_domainname = tomoyo_get_name(domainname);
459 if (!saved_domainname) 372 if (!saved_domainname)
460 return -ENOMEM; 373 goto out;
461 down_write(&tomoyo_domain_keeper_list_lock); 374 if (!is_delete)
462 list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { 375 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
376 mutex_lock(&tomoyo_policy_lock);
377 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
463 if (ptr->is_not != is_not || 378 if (ptr->is_not != is_not ||
464 ptr->domainname != saved_domainname || 379 ptr->domainname != saved_domainname ||
465 ptr->program != saved_program) 380 ptr->program != saved_program)
466 continue; 381 continue;
467 ptr->is_deleted = is_delete; 382 ptr->is_deleted = is_delete;
468 error = 0; 383 error = 0;
469 goto out; 384 break;
470 } 385 }
471 if (is_delete) { 386 if (!is_delete && error && tomoyo_memory_ok(entry)) {
472 error = -ENOENT; 387 entry->domainname = saved_domainname;
473 goto out; 388 saved_domainname = NULL;
389 entry->program = saved_program;
390 saved_program = NULL;
391 entry->is_not = is_not;
392 entry->is_last_name = is_last_name;
393 list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list);
394 entry = NULL;
395 error = 0;
474 } 396 }
475 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 397 mutex_unlock(&tomoyo_policy_lock);
476 if (!new_entry)
477 goto out;
478 new_entry->domainname = saved_domainname;
479 new_entry->program = saved_program;
480 new_entry->is_not = is_not;
481 new_entry->is_last_name = is_last_name;
482 list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list);
483 error = 0;
484 out: 398 out:
485 up_write(&tomoyo_domain_keeper_list_lock); 399 tomoyo_put_name(saved_domainname);
400 tomoyo_put_name(saved_program);
401 kfree(entry);
486 return error; 402 return error;
487} 403}
488 404
@@ -493,6 +409,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
493 * @is_not: True if it is "no_keep_domain" entry. 409 * @is_not: True if it is "no_keep_domain" entry.
494 * @is_delete: True if it is a delete request. 410 * @is_delete: True if it is a delete request.
495 * 411 *
412 * Caller holds tomoyo_read_lock().
496 */ 413 */
497int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, 414int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
498 const bool is_delete) 415 const bool is_delete)
@@ -513,13 +430,14 @@ int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
513 * @head: Pointer to "struct tomoyo_io_buffer". 430 * @head: Pointer to "struct tomoyo_io_buffer".
514 * 431 *
515 * Returns true on success, false otherwise. 432 * Returns true on success, false otherwise.
433 *
434 * Caller holds tomoyo_read_lock().
516 */ 435 */
517bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) 436bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
518{ 437{
519 struct list_head *pos; 438 struct list_head *pos;
520 bool done = true; 439 bool done = true;
521 440
522 down_read(&tomoyo_domain_keeper_list_lock);
523 list_for_each_cookie(pos, head->read_var2, 441 list_for_each_cookie(pos, head->read_var2,
524 &tomoyo_domain_keeper_list) { 442 &tomoyo_domain_keeper_list) {
525 struct tomoyo_domain_keeper_entry *ptr; 443 struct tomoyo_domain_keeper_entry *ptr;
@@ -542,7 +460,6 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
542 if (!done) 460 if (!done)
543 break; 461 break;
544 } 462 }
545 up_read(&tomoyo_domain_keeper_list_lock);
546 return done; 463 return done;
547} 464}
548 465
@@ -555,6 +472,8 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head)
555 * 472 *
556 * Returns true if executing @program supresses domain transition, 473 * Returns true if executing @program supresses domain transition,
557 * false otherwise. 474 * false otherwise.
475 *
476 * Caller holds tomoyo_read_lock().
558 */ 477 */
559static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, 478static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
560 const struct tomoyo_path_info *program, 479 const struct tomoyo_path_info *program,
@@ -563,8 +482,7 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
563 struct tomoyo_domain_keeper_entry *ptr; 482 struct tomoyo_domain_keeper_entry *ptr;
564 bool flag = false; 483 bool flag = false;
565 484
566 down_read(&tomoyo_domain_keeper_list_lock); 485 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
567 list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) {
568 if (ptr->is_deleted) 486 if (ptr->is_deleted)
569 continue; 487 continue;
570 if (!ptr->is_last_name) { 488 if (!ptr->is_last_name) {
@@ -582,7 +500,6 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
582 } 500 }
583 flag = true; 501 flag = true;
584 } 502 }
585 up_read(&tomoyo_domain_keeper_list_lock);
586 return flag; 503 return flag;
587} 504}
588 505
@@ -616,8 +533,7 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname,
616 * /bin/busybox and domainname which the current process will belong to after 533 * /bin/busybox and domainname which the current process will belong to after
617 * execve() succeeds is calculated using /bin/cat rather than /bin/busybox . 534 * execve() succeeds is calculated using /bin/cat rather than /bin/busybox .
618 */ 535 */
619static LIST_HEAD(tomoyo_alias_list); 536LIST_HEAD(tomoyo_alias_list);
620static DECLARE_RWSEM(tomoyo_alias_list_lock);
621 537
622/** 538/**
623 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. 539 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list.
@@ -627,46 +543,51 @@ static DECLARE_RWSEM(tomoyo_alias_list_lock);
627 * @is_delete: True if it is a delete request. 543 * @is_delete: True if it is a delete request.
628 * 544 *
629 * Returns 0 on success, negative value otherwise. 545 * Returns 0 on success, negative value otherwise.
546 *
547 * Caller holds tomoyo_read_lock().
630 */ 548 */
631static int tomoyo_update_alias_entry(const char *original_name, 549static int tomoyo_update_alias_entry(const char *original_name,
632 const char *aliased_name, 550 const char *aliased_name,
633 const bool is_delete) 551 const bool is_delete)
634{ 552{
635 struct tomoyo_alias_entry *new_entry; 553 struct tomoyo_alias_entry *entry = NULL;
636 struct tomoyo_alias_entry *ptr; 554 struct tomoyo_alias_entry *ptr;
637 const struct tomoyo_path_info *saved_original_name; 555 const struct tomoyo_path_info *saved_original_name;
638 const struct tomoyo_path_info *saved_aliased_name; 556 const struct tomoyo_path_info *saved_aliased_name;
639 int error = -ENOMEM; 557 int error = is_delete ? -ENOENT : -ENOMEM;
640 558
641 if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || 559 if (!tomoyo_is_correct_path(original_name, 1, -1, -1) ||
642 !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) 560 !tomoyo_is_correct_path(aliased_name, 1, -1, -1))
643 return -EINVAL; /* No patterns allowed. */ 561 return -EINVAL; /* No patterns allowed. */
644 saved_original_name = tomoyo_save_name(original_name); 562 saved_original_name = tomoyo_get_name(original_name);
645 saved_aliased_name = tomoyo_save_name(aliased_name); 563 saved_aliased_name = tomoyo_get_name(aliased_name);
646 if (!saved_original_name || !saved_aliased_name) 564 if (!saved_original_name || !saved_aliased_name)
647 return -ENOMEM; 565 goto out;
648 down_write(&tomoyo_alias_list_lock); 566 if (!is_delete)
649 list_for_each_entry(ptr, &tomoyo_alias_list, list) { 567 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
568 mutex_lock(&tomoyo_policy_lock);
569 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
650 if (ptr->original_name != saved_original_name || 570 if (ptr->original_name != saved_original_name ||
651 ptr->aliased_name != saved_aliased_name) 571 ptr->aliased_name != saved_aliased_name)
652 continue; 572 continue;
653 ptr->is_deleted = is_delete; 573 ptr->is_deleted = is_delete;
654 error = 0; 574 error = 0;
655 goto out; 575 break;
656 } 576 }
657 if (is_delete) { 577 if (!is_delete && error && tomoyo_memory_ok(entry)) {
658 error = -ENOENT; 578 entry->original_name = saved_original_name;
659 goto out; 579 saved_original_name = NULL;
580 entry->aliased_name = saved_aliased_name;
581 saved_aliased_name = NULL;
582 list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
583 entry = NULL;
584 error = 0;
660 } 585 }
661 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 586 mutex_unlock(&tomoyo_policy_lock);
662 if (!new_entry)
663 goto out;
664 new_entry->original_name = saved_original_name;
665 new_entry->aliased_name = saved_aliased_name;
666 list_add_tail(&new_entry->list, &tomoyo_alias_list);
667 error = 0;
668 out: 587 out:
669 up_write(&tomoyo_alias_list_lock); 588 tomoyo_put_name(saved_original_name);
589 tomoyo_put_name(saved_aliased_name);
590 kfree(entry);
670 return error; 591 return error;
671} 592}
672 593
@@ -676,13 +597,14 @@ static int tomoyo_update_alias_entry(const char *original_name,
676 * @head: Pointer to "struct tomoyo_io_buffer". 597 * @head: Pointer to "struct tomoyo_io_buffer".
677 * 598 *
678 * Returns true on success, false otherwise. 599 * Returns true on success, false otherwise.
600 *
601 * Caller holds tomoyo_read_lock().
679 */ 602 */
680bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) 603bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
681{ 604{
682 struct list_head *pos; 605 struct list_head *pos;
683 bool done = true; 606 bool done = true;
684 607
685 down_read(&tomoyo_alias_list_lock);
686 list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { 608 list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) {
687 struct tomoyo_alias_entry *ptr; 609 struct tomoyo_alias_entry *ptr;
688 610
@@ -695,7 +617,6 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
695 if (!done) 617 if (!done)
696 break; 618 break;
697 } 619 }
698 up_read(&tomoyo_alias_list_lock);
699 return done; 620 return done;
700} 621}
701 622
@@ -706,6 +627,8 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head)
706 * @is_delete: True if it is a delete request. 627 * @is_delete: True if it is a delete request.
707 * 628 *
708 * Returns 0 on success, negative value otherwise. 629 * Returns 0 on success, negative value otherwise.
630 *
631 * Caller holds tomoyo_read_lock().
709 */ 632 */
710int tomoyo_write_alias_policy(char *data, const bool is_delete) 633int tomoyo_write_alias_policy(char *data, const bool is_delete)
711{ 634{
@@ -724,63 +647,46 @@ int tomoyo_write_alias_policy(char *data, const bool is_delete)
724 * @profile: Profile number to assign if the domain was newly created. 647 * @profile: Profile number to assign if the domain was newly created.
725 * 648 *
726 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. 649 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise.
650 *
651 * Caller holds tomoyo_read_lock().
727 */ 652 */
728struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 653struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
729 domainname, 654 domainname,
730 const u8 profile) 655 const u8 profile)
731{ 656{
732 struct tomoyo_domain_info *domain = NULL; 657 struct tomoyo_domain_info *entry;
658 struct tomoyo_domain_info *domain;
733 const struct tomoyo_path_info *saved_domainname; 659 const struct tomoyo_path_info *saved_domainname;
660 bool found = false;
734 661
735 down_write(&tomoyo_domain_list_lock); 662 if (!tomoyo_is_correct_domain(domainname))
736 domain = tomoyo_find_domain(domainname); 663 return NULL;
737 if (domain) 664 saved_domainname = tomoyo_get_name(domainname);
738 goto out;
739 if (!tomoyo_is_correct_domain(domainname, __func__))
740 goto out;
741 saved_domainname = tomoyo_save_name(domainname);
742 if (!saved_domainname) 665 if (!saved_domainname)
743 goto out; 666 return NULL;
744 /* Can I reuse memory of deleted domain? */ 667 entry = kzalloc(sizeof(*entry), GFP_KERNEL);
745 list_for_each_entry(domain, &tomoyo_domain_list, list) { 668 mutex_lock(&tomoyo_policy_lock);
746 struct task_struct *p; 669 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
747 struct tomoyo_acl_info *ptr; 670 if (domain->is_deleted ||
748 bool flag; 671 tomoyo_pathcmp(saved_domainname, domain->domainname))
749 if (!domain->is_deleted ||
750 domain->domainname != saved_domainname)
751 continue; 672 continue;
752 flag = false; 673 found = true;
753 read_lock(&tasklist_lock); 674 break;
754 for_each_process(p) {
755 if (tomoyo_real_domain(p) != domain)
756 continue;
757 flag = true;
758 break;
759 }
760 read_unlock(&tasklist_lock);
761 if (flag)
762 continue;
763 list_for_each_entry(ptr, &domain->acl_info_list, list) {
764 ptr->type |= TOMOYO_ACL_DELETED;
765 }
766 tomoyo_set_domain_flag(domain, true, domain->flags);
767 domain->profile = profile;
768 domain->quota_warned = false;
769 mb(); /* Avoid out-of-order execution. */
770 domain->is_deleted = false;
771 goto out;
772 } 675 }
773 /* No memory reusable. Create using new memory. */ 676 if (!found && tomoyo_memory_ok(entry)) {
774 domain = tomoyo_alloc_element(sizeof(*domain)); 677 INIT_LIST_HEAD(&entry->acl_info_list);
775 if (domain) { 678 entry->domainname = saved_domainname;
776 INIT_LIST_HEAD(&domain->acl_info_list); 679 saved_domainname = NULL;
777 domain->domainname = saved_domainname; 680 entry->profile = profile;
778 domain->profile = profile; 681 list_add_tail_rcu(&entry->list, &tomoyo_domain_list);
779 list_add_tail(&domain->list, &tomoyo_domain_list); 682 domain = entry;
683 entry = NULL;
684 found = true;
780 } 685 }
781 out: 686 mutex_unlock(&tomoyo_policy_lock);
782 up_write(&tomoyo_domain_list_lock); 687 tomoyo_put_name(saved_domainname);
783 return domain; 688 kfree(entry);
689 return found ? domain : NULL;
784} 690}
785 691
786/** 692/**
@@ -789,6 +695,8 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
789 * @bprm: Pointer to "struct linux_binprm". 695 * @bprm: Pointer to "struct linux_binprm".
790 * 696 *
791 * Returns 0 on success, negative value otherwise. 697 * Returns 0 on success, negative value otherwise.
698 *
699 * Caller holds tomoyo_read_lock().
792 */ 700 */
793int tomoyo_find_next_domain(struct linux_binprm *bprm) 701int tomoyo_find_next_domain(struct linux_binprm *bprm)
794{ 702{
@@ -796,7 +704,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
796 * This function assumes that the size of buffer returned by 704 * This function assumes that the size of buffer returned by
797 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. 705 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN.
798 */ 706 */
799 struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp)); 707 struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
800 struct tomoyo_domain_info *old_domain = tomoyo_domain(); 708 struct tomoyo_domain_info *old_domain = tomoyo_domain();
801 struct tomoyo_domain_info *domain = NULL; 709 struct tomoyo_domain_info *domain = NULL;
802 const char *old_domain_name = old_domain->domainname->name; 710 const char *old_domain_name = old_domain->domainname->name;
@@ -849,8 +757,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
849 if (tomoyo_pathcmp(&r, &s)) { 757 if (tomoyo_pathcmp(&r, &s)) {
850 struct tomoyo_alias_entry *ptr; 758 struct tomoyo_alias_entry *ptr;
851 /* Is this program allowed to be called via symbolic links? */ 759 /* Is this program allowed to be called via symbolic links? */
852 down_read(&tomoyo_alias_list_lock); 760 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
853 list_for_each_entry(ptr, &tomoyo_alias_list, list) {
854 if (ptr->is_deleted || 761 if (ptr->is_deleted ||
855 tomoyo_pathcmp(&r, ptr->original_name) || 762 tomoyo_pathcmp(&r, ptr->original_name) ||
856 tomoyo_pathcmp(&s, ptr->aliased_name)) 763 tomoyo_pathcmp(&s, ptr->aliased_name))
@@ -861,7 +768,6 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
861 tomoyo_fill_path_info(&r); 768 tomoyo_fill_path_info(&r);
862 break; 769 break;
863 } 770 }
864 up_read(&tomoyo_alias_list_lock);
865 } 771 }
866 772
867 /* Check execute permission. */ 773 /* Check execute permission. */
@@ -892,9 +798,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
892 } 798 }
893 if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) 799 if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN)
894 goto done; 800 goto done;
895 down_read(&tomoyo_domain_list_lock);
896 domain = tomoyo_find_domain(new_domain_name); 801 domain = tomoyo_find_domain(new_domain_name);
897 up_read(&tomoyo_domain_list_lock);
898 if (domain) 802 if (domain)
899 goto done; 803 goto done;
900 if (is_enforce) 804 if (is_enforce)
@@ -909,14 +813,15 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
909 if (is_enforce) 813 if (is_enforce)
910 retval = -EPERM; 814 retval = -EPERM;
911 else 815 else
912 tomoyo_set_domain_flag(old_domain, false, 816 old_domain->transition_failed = true;
913 TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED);
914 out: 817 out:
915 if (!domain) 818 if (!domain)
916 domain = old_domain; 819 domain = old_domain;
820 /* Update reference count on "struct tomoyo_domain_info". */
821 atomic_inc(&domain->users);
917 bprm->cred->security = domain; 822 bprm->cred->security = domain;
918 tomoyo_free(real_program_name); 823 kfree(real_program_name);
919 tomoyo_free(symlink_program_name); 824 kfree(symlink_program_name);
920 tomoyo_free(tmp); 825 kfree(tmp);
921 return retval; 826 return retval;
922} 827}
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c
index 9a6c58881c0a..1b24304edb7d 100644
--- a/security/tomoyo/file.c
+++ b/security/tomoyo/file.c
@@ -10,108 +10,64 @@
10 */ 10 */
11 11
12#include "common.h" 12#include "common.h"
13#include "tomoyo.h"
14#include "realpath.h"
15
16/*
17 * tomoyo_globally_readable_file_entry is a structure which is used for holding
18 * "allow_read" entries.
19 * It has following fields.
20 *
21 * (1) "list" which is linked to tomoyo_globally_readable_list .
22 * (2) "filename" is a pathname which is allowed to open(O_RDONLY).
23 * (3) "is_deleted" is a bool which is true if marked as deleted, false
24 * otherwise.
25 */
26struct tomoyo_globally_readable_file_entry {
27 struct list_head list;
28 const struct tomoyo_path_info *filename;
29 bool is_deleted;
30};
31
32/*
33 * tomoyo_pattern_entry is a structure which is used for holding
34 * "tomoyo_pattern_list" entries.
35 * It has following fields.
36 *
37 * (1) "list" which is linked to tomoyo_pattern_list .
38 * (2) "pattern" is a pathname pattern which is used for converting pathnames
39 * to pathname patterns during learning mode.
40 * (3) "is_deleted" is a bool which is true if marked as deleted, false
41 * otherwise.
42 */
43struct tomoyo_pattern_entry {
44 struct list_head list;
45 const struct tomoyo_path_info *pattern;
46 bool is_deleted;
47};
48
49/*
50 * tomoyo_no_rewrite_entry is a structure which is used for holding
51 * "deny_rewrite" entries.
52 * It has following fields.
53 *
54 * (1) "list" which is linked to tomoyo_no_rewrite_list .
55 * (2) "pattern" is a pathname which is by default not permitted to modify
56 * already existing content.
57 * (3) "is_deleted" is a bool which is true if marked as deleted, false
58 * otherwise.
59 */
60struct tomoyo_no_rewrite_entry {
61 struct list_head list;
62 const struct tomoyo_path_info *pattern;
63 bool is_deleted;
64};
65 13
66/* Keyword array for single path operations. */ 14/* Keyword array for single path operations. */
67static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = { 15static const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = {
68 [TOMOYO_TYPE_READ_WRITE_ACL] = "read/write", 16 [TOMOYO_TYPE_READ_WRITE] = "read/write",
69 [TOMOYO_TYPE_EXECUTE_ACL] = "execute", 17 [TOMOYO_TYPE_EXECUTE] = "execute",
70 [TOMOYO_TYPE_READ_ACL] = "read", 18 [TOMOYO_TYPE_READ] = "read",
71 [TOMOYO_TYPE_WRITE_ACL] = "write", 19 [TOMOYO_TYPE_WRITE] = "write",
72 [TOMOYO_TYPE_CREATE_ACL] = "create", 20 [TOMOYO_TYPE_CREATE] = "create",
73 [TOMOYO_TYPE_UNLINK_ACL] = "unlink", 21 [TOMOYO_TYPE_UNLINK] = "unlink",
74 [TOMOYO_TYPE_MKDIR_ACL] = "mkdir", 22 [TOMOYO_TYPE_MKDIR] = "mkdir",
75 [TOMOYO_TYPE_RMDIR_ACL] = "rmdir", 23 [TOMOYO_TYPE_RMDIR] = "rmdir",
76 [TOMOYO_TYPE_MKFIFO_ACL] = "mkfifo", 24 [TOMOYO_TYPE_MKFIFO] = "mkfifo",
77 [TOMOYO_TYPE_MKSOCK_ACL] = "mksock", 25 [TOMOYO_TYPE_MKSOCK] = "mksock",
78 [TOMOYO_TYPE_MKBLOCK_ACL] = "mkblock", 26 [TOMOYO_TYPE_MKBLOCK] = "mkblock",
79 [TOMOYO_TYPE_MKCHAR_ACL] = "mkchar", 27 [TOMOYO_TYPE_MKCHAR] = "mkchar",
80 [TOMOYO_TYPE_TRUNCATE_ACL] = "truncate", 28 [TOMOYO_TYPE_TRUNCATE] = "truncate",
81 [TOMOYO_TYPE_SYMLINK_ACL] = "symlink", 29 [TOMOYO_TYPE_SYMLINK] = "symlink",
82 [TOMOYO_TYPE_REWRITE_ACL] = "rewrite", 30 [TOMOYO_TYPE_REWRITE] = "rewrite",
31 [TOMOYO_TYPE_IOCTL] = "ioctl",
32 [TOMOYO_TYPE_CHMOD] = "chmod",
33 [TOMOYO_TYPE_CHOWN] = "chown",
34 [TOMOYO_TYPE_CHGRP] = "chgrp",
35 [TOMOYO_TYPE_CHROOT] = "chroot",
36 [TOMOYO_TYPE_MOUNT] = "mount",
37 [TOMOYO_TYPE_UMOUNT] = "unmount",
83}; 38};
84 39
85/* Keyword array for double path operations. */ 40/* Keyword array for double path operations. */
86static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = { 41static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = {
87 [TOMOYO_TYPE_LINK_ACL] = "link", 42 [TOMOYO_TYPE_LINK] = "link",
88 [TOMOYO_TYPE_RENAME_ACL] = "rename", 43 [TOMOYO_TYPE_RENAME] = "rename",
44 [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root",
89}; 45};
90 46
91/** 47/**
92 * tomoyo_sp2keyword - Get the name of single path operation. 48 * tomoyo_path2keyword - Get the name of single path operation.
93 * 49 *
94 * @operation: Type of operation. 50 * @operation: Type of operation.
95 * 51 *
96 * Returns the name of single path operation. 52 * Returns the name of single path operation.
97 */ 53 */
98const char *tomoyo_sp2keyword(const u8 operation) 54const char *tomoyo_path2keyword(const u8 operation)
99{ 55{
100 return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION) 56 return (operation < TOMOYO_MAX_PATH_OPERATION)
101 ? tomoyo_sp_keyword[operation] : NULL; 57 ? tomoyo_path_keyword[operation] : NULL;
102} 58}
103 59
104/** 60/**
105 * tomoyo_dp2keyword - Get the name of double path operation. 61 * tomoyo_path22keyword - Get the name of double path operation.
106 * 62 *
107 * @operation: Type of operation. 63 * @operation: Type of operation.
108 * 64 *
109 * Returns the name of double path operation. 65 * Returns the name of double path operation.
110 */ 66 */
111const char *tomoyo_dp2keyword(const u8 operation) 67const char *tomoyo_path22keyword(const u8 operation)
112{ 68{
113 return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION) 69 return (operation < TOMOYO_MAX_PATH2_OPERATION)
114 ? tomoyo_dp_keyword[operation] : NULL; 70 ? tomoyo_path2_keyword[operation] : NULL;
115} 71}
116 72
117/** 73/**
@@ -142,7 +98,8 @@ static bool tomoyo_strendswith(const char *name, const char *tail)
142static struct tomoyo_path_info *tomoyo_get_path(struct path *path) 98static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
143{ 99{
144 int error; 100 int error;
145 struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf)); 101 struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf),
102 GFP_KERNEL);
146 103
147 if (!buf) 104 if (!buf)
148 return NULL; 105 return NULL;
@@ -154,20 +111,17 @@ static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
154 tomoyo_fill_path_info(&buf->head); 111 tomoyo_fill_path_info(&buf->head);
155 return &buf->head; 112 return &buf->head;
156 } 113 }
157 tomoyo_free(buf); 114 kfree(buf);
158 return NULL; 115 return NULL;
159} 116}
160 117
161/* Lock for domain->acl_info_list. */ 118static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
162DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock); 119 const char *filename2,
163 120 struct tomoyo_domain_info *const domain,
164static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, 121 const bool is_delete);
165 const char *filename2, 122static int tomoyo_update_path_acl(const u8 type, const char *filename,
166 struct tomoyo_domain_info * 123 struct tomoyo_domain_info *const domain,
167 const domain, const bool is_delete); 124 const bool is_delete);
168static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
169 struct tomoyo_domain_info *
170 const domain, const bool is_delete);
171 125
172/* 126/*
173 * tomoyo_globally_readable_list is used for holding list of pathnames which 127 * tomoyo_globally_readable_list is used for holding list of pathnames which
@@ -194,8 +148,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
194 * given "allow_read /lib/libc-2.5.so" to the domain which current process 148 * given "allow_read /lib/libc-2.5.so" to the domain which current process
195 * belongs to. 149 * belongs to.
196 */ 150 */
197static LIST_HEAD(tomoyo_globally_readable_list); 151LIST_HEAD(tomoyo_globally_readable_list);
198static DECLARE_RWSEM(tomoyo_globally_readable_list_lock);
199 152
200/** 153/**
201 * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list. 154 * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list.
@@ -204,40 +157,42 @@ static DECLARE_RWSEM(tomoyo_globally_readable_list_lock);
204 * @is_delete: True if it is a delete request. 157 * @is_delete: True if it is a delete request.
205 * 158 *
206 * Returns 0 on success, negative value otherwise. 159 * Returns 0 on success, negative value otherwise.
160 *
161 * Caller holds tomoyo_read_lock().
207 */ 162 */
208static int tomoyo_update_globally_readable_entry(const char *filename, 163static int tomoyo_update_globally_readable_entry(const char *filename,
209 const bool is_delete) 164 const bool is_delete)
210{ 165{
211 struct tomoyo_globally_readable_file_entry *new_entry; 166 struct tomoyo_globally_readable_file_entry *entry = NULL;
212 struct tomoyo_globally_readable_file_entry *ptr; 167 struct tomoyo_globally_readable_file_entry *ptr;
213 const struct tomoyo_path_info *saved_filename; 168 const struct tomoyo_path_info *saved_filename;
214 int error = -ENOMEM; 169 int error = is_delete ? -ENOENT : -ENOMEM;
215 170
216 if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__)) 171 if (!tomoyo_is_correct_path(filename, 1, 0, -1))
217 return -EINVAL; 172 return -EINVAL;
218 saved_filename = tomoyo_save_name(filename); 173 saved_filename = tomoyo_get_name(filename);
219 if (!saved_filename) 174 if (!saved_filename)
220 return -ENOMEM; 175 return -ENOMEM;
221 down_write(&tomoyo_globally_readable_list_lock); 176 if (!is_delete)
222 list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) { 177 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
178 mutex_lock(&tomoyo_policy_lock);
179 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
223 if (ptr->filename != saved_filename) 180 if (ptr->filename != saved_filename)
224 continue; 181 continue;
225 ptr->is_deleted = is_delete; 182 ptr->is_deleted = is_delete;
226 error = 0; 183 error = 0;
227 goto out; 184 break;
228 } 185 }
229 if (is_delete) { 186 if (!is_delete && error && tomoyo_memory_ok(entry)) {
230 error = -ENOENT; 187 entry->filename = saved_filename;
231 goto out; 188 saved_filename = NULL;
189 list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list);
190 entry = NULL;
191 error = 0;
232 } 192 }
233 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 193 mutex_unlock(&tomoyo_policy_lock);
234 if (!new_entry) 194 tomoyo_put_name(saved_filename);
235 goto out; 195 kfree(entry);
236 new_entry->filename = saved_filename;
237 list_add_tail(&new_entry->list, &tomoyo_globally_readable_list);
238 error = 0;
239 out:
240 up_write(&tomoyo_globally_readable_list_lock);
241 return error; 196 return error;
242} 197}
243 198
@@ -247,21 +202,22 @@ static int tomoyo_update_globally_readable_entry(const char *filename,
247 * @filename: The filename to check. 202 * @filename: The filename to check.
248 * 203 *
249 * Returns true if any domain can open @filename for reading, false otherwise. 204 * Returns true if any domain can open @filename for reading, false otherwise.
205 *
206 * Caller holds tomoyo_read_lock().
250 */ 207 */
251static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * 208static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
252 filename) 209 filename)
253{ 210{
254 struct tomoyo_globally_readable_file_entry *ptr; 211 struct tomoyo_globally_readable_file_entry *ptr;
255 bool found = false; 212 bool found = false;
256 down_read(&tomoyo_globally_readable_list_lock); 213
257 list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) { 214 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
258 if (!ptr->is_deleted && 215 if (!ptr->is_deleted &&
259 tomoyo_path_matches_pattern(filename, ptr->filename)) { 216 tomoyo_path_matches_pattern(filename, ptr->filename)) {
260 found = true; 217 found = true;
261 break; 218 break;
262 } 219 }
263 } 220 }
264 up_read(&tomoyo_globally_readable_list_lock);
265 return found; 221 return found;
266} 222}
267 223
@@ -272,6 +228,8 @@ static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
272 * @is_delete: True if it is a delete request. 228 * @is_delete: True if it is a delete request.
273 * 229 *
274 * Returns 0 on success, negative value otherwise. 230 * Returns 0 on success, negative value otherwise.
231 *
232 * Caller holds tomoyo_read_lock().
275 */ 233 */
276int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) 234int tomoyo_write_globally_readable_policy(char *data, const bool is_delete)
277{ 235{
@@ -284,13 +242,14 @@ int tomoyo_write_globally_readable_policy(char *data, const bool is_delete)
284 * @head: Pointer to "struct tomoyo_io_buffer". 242 * @head: Pointer to "struct tomoyo_io_buffer".
285 * 243 *
286 * Returns true on success, false otherwise. 244 * Returns true on success, false otherwise.
245 *
246 * Caller holds tomoyo_read_lock().
287 */ 247 */
288bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) 248bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
289{ 249{
290 struct list_head *pos; 250 struct list_head *pos;
291 bool done = true; 251 bool done = true;
292 252
293 down_read(&tomoyo_globally_readable_list_lock);
294 list_for_each_cookie(pos, head->read_var2, 253 list_for_each_cookie(pos, head->read_var2,
295 &tomoyo_globally_readable_list) { 254 &tomoyo_globally_readable_list) {
296 struct tomoyo_globally_readable_file_entry *ptr; 255 struct tomoyo_globally_readable_file_entry *ptr;
@@ -304,7 +263,6 @@ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
304 if (!done) 263 if (!done)
305 break; 264 break;
306 } 265 }
307 up_read(&tomoyo_globally_readable_list_lock);
308 return done; 266 return done;
309} 267}
310 268
@@ -337,8 +295,7 @@ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
337 * which pretends as if /proc/self/ is not a symlink; so that we can forbid 295 * which pretends as if /proc/self/ is not a symlink; so that we can forbid
338 * current process from accessing other process's information. 296 * current process from accessing other process's information.
339 */ 297 */
340static LIST_HEAD(tomoyo_pattern_list); 298LIST_HEAD(tomoyo_pattern_list);
341static DECLARE_RWSEM(tomoyo_pattern_list_lock);
342 299
343/** 300/**
344 * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. 301 * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list.
@@ -347,40 +304,43 @@ static DECLARE_RWSEM(tomoyo_pattern_list_lock);
347 * @is_delete: True if it is a delete request. 304 * @is_delete: True if it is a delete request.
348 * 305 *
349 * Returns 0 on success, negative value otherwise. 306 * Returns 0 on success, negative value otherwise.
307 *
308 * Caller holds tomoyo_read_lock().
350 */ 309 */
351static int tomoyo_update_file_pattern_entry(const char *pattern, 310static int tomoyo_update_file_pattern_entry(const char *pattern,
352 const bool is_delete) 311 const bool is_delete)
353{ 312{
354 struct tomoyo_pattern_entry *new_entry; 313 struct tomoyo_pattern_entry *entry = NULL;
355 struct tomoyo_pattern_entry *ptr; 314 struct tomoyo_pattern_entry *ptr;
356 const struct tomoyo_path_info *saved_pattern; 315 const struct tomoyo_path_info *saved_pattern;
357 int error = -ENOMEM; 316 int error = is_delete ? -ENOENT : -ENOMEM;
358 317
359 if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__)) 318 saved_pattern = tomoyo_get_name(pattern);
360 return -EINVAL;
361 saved_pattern = tomoyo_save_name(pattern);
362 if (!saved_pattern) 319 if (!saved_pattern)
363 return -ENOMEM; 320 return error;
364 down_write(&tomoyo_pattern_list_lock); 321 if (!saved_pattern->is_patterned)
365 list_for_each_entry(ptr, &tomoyo_pattern_list, list) { 322 goto out;
323 if (!is_delete)
324 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
325 mutex_lock(&tomoyo_policy_lock);
326 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
366 if (saved_pattern != ptr->pattern) 327 if (saved_pattern != ptr->pattern)
367 continue; 328 continue;
368 ptr->is_deleted = is_delete; 329 ptr->is_deleted = is_delete;
369 error = 0; 330 error = 0;
370 goto out; 331 break;
371 } 332 }
372 if (is_delete) { 333 if (!is_delete && error && tomoyo_memory_ok(entry)) {
373 error = -ENOENT; 334 entry->pattern = saved_pattern;
374 goto out; 335 saved_pattern = NULL;
336 list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
337 entry = NULL;
338 error = 0;
375 } 339 }
376 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 340 mutex_unlock(&tomoyo_policy_lock);
377 if (!new_entry)
378 goto out;
379 new_entry->pattern = saved_pattern;
380 list_add_tail(&new_entry->list, &tomoyo_pattern_list);
381 error = 0;
382 out: 341 out:
383 up_write(&tomoyo_pattern_list_lock); 342 kfree(entry);
343 tomoyo_put_name(saved_pattern);
384 return error; 344 return error;
385} 345}
386 346
@@ -390,6 +350,8 @@ static int tomoyo_update_file_pattern_entry(const char *pattern,
390 * @filename: The filename to find patterned pathname. 350 * @filename: The filename to find patterned pathname.
391 * 351 *
392 * Returns pointer to pathname pattern if matched, @filename otherwise. 352 * Returns pointer to pathname pattern if matched, @filename otherwise.
353 *
354 * Caller holds tomoyo_read_lock().
393 */ 355 */
394static const struct tomoyo_path_info * 356static const struct tomoyo_path_info *
395tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) 357tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
@@ -397,8 +359,7 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
397 struct tomoyo_pattern_entry *ptr; 359 struct tomoyo_pattern_entry *ptr;
398 const struct tomoyo_path_info *pattern = NULL; 360 const struct tomoyo_path_info *pattern = NULL;
399 361
400 down_read(&tomoyo_pattern_list_lock); 362 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
401 list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
402 if (ptr->is_deleted) 363 if (ptr->is_deleted)
403 continue; 364 continue;
404 if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) 365 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
@@ -411,7 +372,6 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
411 break; 372 break;
412 } 373 }
413 } 374 }
414 up_read(&tomoyo_pattern_list_lock);
415 if (pattern) 375 if (pattern)
416 filename = pattern; 376 filename = pattern;
417 return filename; 377 return filename;
@@ -424,6 +384,8 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
424 * @is_delete: True if it is a delete request. 384 * @is_delete: True if it is a delete request.
425 * 385 *
426 * Returns 0 on success, negative value otherwise. 386 * Returns 0 on success, negative value otherwise.
387 *
388 * Caller holds tomoyo_read_lock().
427 */ 389 */
428int tomoyo_write_pattern_policy(char *data, const bool is_delete) 390int tomoyo_write_pattern_policy(char *data, const bool is_delete)
429{ 391{
@@ -436,13 +398,14 @@ int tomoyo_write_pattern_policy(char *data, const bool is_delete)
436 * @head: Pointer to "struct tomoyo_io_buffer". 398 * @head: Pointer to "struct tomoyo_io_buffer".
437 * 399 *
438 * Returns true on success, false otherwise. 400 * Returns true on success, false otherwise.
401 *
402 * Caller holds tomoyo_read_lock().
439 */ 403 */
440bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) 404bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
441{ 405{
442 struct list_head *pos; 406 struct list_head *pos;
443 bool done = true; 407 bool done = true;
444 408
445 down_read(&tomoyo_pattern_list_lock);
446 list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) { 409 list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) {
447 struct tomoyo_pattern_entry *ptr; 410 struct tomoyo_pattern_entry *ptr;
448 ptr = list_entry(pos, struct tomoyo_pattern_entry, list); 411 ptr = list_entry(pos, struct tomoyo_pattern_entry, list);
@@ -453,7 +416,6 @@ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
453 if (!done) 416 if (!done)
454 break; 417 break;
455 } 418 }
456 up_read(&tomoyo_pattern_list_lock);
457 return done; 419 return done;
458} 420}
459 421
@@ -486,8 +448,7 @@ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
486 * " (deleted)" suffix if the file is already unlink()ed; so that we don't 448 * " (deleted)" suffix if the file is already unlink()ed; so that we don't
487 * need to worry whether the file is already unlink()ed or not. 449 * need to worry whether the file is already unlink()ed or not.
488 */ 450 */
489static LIST_HEAD(tomoyo_no_rewrite_list); 451LIST_HEAD(tomoyo_no_rewrite_list);
490static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock);
491 452
492/** 453/**
493 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list. 454 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
@@ -496,39 +457,42 @@ static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock);
496 * @is_delete: True if it is a delete request. 457 * @is_delete: True if it is a delete request.
497 * 458 *
498 * Returns 0 on success, negative value otherwise. 459 * Returns 0 on success, negative value otherwise.
460 *
461 * Caller holds tomoyo_read_lock().
499 */ 462 */
500static int tomoyo_update_no_rewrite_entry(const char *pattern, 463static int tomoyo_update_no_rewrite_entry(const char *pattern,
501 const bool is_delete) 464 const bool is_delete)
502{ 465{
503 struct tomoyo_no_rewrite_entry *new_entry, *ptr; 466 struct tomoyo_no_rewrite_entry *entry = NULL;
467 struct tomoyo_no_rewrite_entry *ptr;
504 const struct tomoyo_path_info *saved_pattern; 468 const struct tomoyo_path_info *saved_pattern;
505 int error = -ENOMEM; 469 int error = is_delete ? -ENOENT : -ENOMEM;
506 470
507 if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) 471 if (!tomoyo_is_correct_path(pattern, 0, 0, 0))
508 return -EINVAL; 472 return -EINVAL;
509 saved_pattern = tomoyo_save_name(pattern); 473 saved_pattern = tomoyo_get_name(pattern);
510 if (!saved_pattern) 474 if (!saved_pattern)
511 return -ENOMEM; 475 return error;
512 down_write(&tomoyo_no_rewrite_list_lock); 476 if (!is_delete)
513 list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) { 477 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
478 mutex_lock(&tomoyo_policy_lock);
479 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
514 if (ptr->pattern != saved_pattern) 480 if (ptr->pattern != saved_pattern)
515 continue; 481 continue;
516 ptr->is_deleted = is_delete; 482 ptr->is_deleted = is_delete;
517 error = 0; 483 error = 0;
518 goto out; 484 break;
519 } 485 }
520 if (is_delete) { 486 if (!is_delete && error && tomoyo_memory_ok(entry)) {
521 error = -ENOENT; 487 entry->pattern = saved_pattern;
522 goto out; 488 saved_pattern = NULL;
489 list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list);
490 entry = NULL;
491 error = 0;
523 } 492 }
524 new_entry = tomoyo_alloc_element(sizeof(*new_entry)); 493 mutex_unlock(&tomoyo_policy_lock);
525 if (!new_entry) 494 tomoyo_put_name(saved_pattern);
526 goto out; 495 kfree(entry);
527 new_entry->pattern = saved_pattern;
528 list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list);
529 error = 0;
530 out:
531 up_write(&tomoyo_no_rewrite_list_lock);
532 return error; 496 return error;
533} 497}
534 498
@@ -539,14 +503,15 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern,
539 * 503 *
540 * Returns true if @filename is specified by "deny_rewrite" directive, 504 * Returns true if @filename is specified by "deny_rewrite" directive,
541 * false otherwise. 505 * false otherwise.
506 *
507 * Caller holds tomoyo_read_lock().
542 */ 508 */
543static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) 509static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
544{ 510{
545 struct tomoyo_no_rewrite_entry *ptr; 511 struct tomoyo_no_rewrite_entry *ptr;
546 bool found = false; 512 bool found = false;
547 513
548 down_read(&tomoyo_no_rewrite_list_lock); 514 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
549 list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
550 if (ptr->is_deleted) 515 if (ptr->is_deleted)
551 continue; 516 continue;
552 if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) 517 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
@@ -554,7 +519,6 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
554 found = true; 519 found = true;
555 break; 520 break;
556 } 521 }
557 up_read(&tomoyo_no_rewrite_list_lock);
558 return found; 522 return found;
559} 523}
560 524
@@ -565,6 +529,8 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
565 * @is_delete: True if it is a delete request. 529 * @is_delete: True if it is a delete request.
566 * 530 *
567 * Returns 0 on success, negative value otherwise. 531 * Returns 0 on success, negative value otherwise.
532 *
533 * Caller holds tomoyo_read_lock().
568 */ 534 */
569int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) 535int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
570{ 536{
@@ -577,13 +543,14 @@ int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
577 * @head: Pointer to "struct tomoyo_io_buffer". 543 * @head: Pointer to "struct tomoyo_io_buffer".
578 * 544 *
579 * Returns true on success, false otherwise. 545 * Returns true on success, false otherwise.
546 *
547 * Caller holds tomoyo_read_lock().
580 */ 548 */
581bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) 549bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
582{ 550{
583 struct list_head *pos; 551 struct list_head *pos;
584 bool done = true; 552 bool done = true;
585 553
586 down_read(&tomoyo_no_rewrite_list_lock);
587 list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) { 554 list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) {
588 struct tomoyo_no_rewrite_entry *ptr; 555 struct tomoyo_no_rewrite_entry *ptr;
589 ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list); 556 ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list);
@@ -594,7 +561,6 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
594 if (!done) 561 if (!done)
595 break; 562 break;
596 } 563 }
597 up_read(&tomoyo_no_rewrite_list_lock);
598 return done; 564 return done;
599} 565}
600 566
@@ -612,6 +578,8 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
612 * Current policy syntax uses "allow_read/write" instead of "6", 578 * Current policy syntax uses "allow_read/write" instead of "6",
613 * "allow_read" instead of "4", "allow_write" instead of "2", 579 * "allow_read" instead of "4", "allow_write" instead of "2",
614 * "allow_execute" instead of "1". 580 * "allow_execute" instead of "1".
581 *
582 * Caller holds tomoyo_read_lock().
615 */ 583 */
616static int tomoyo_update_file_acl(const char *filename, u8 perm, 584static int tomoyo_update_file_acl(const char *filename, u8 perm,
617 struct tomoyo_domain_info * const domain, 585 struct tomoyo_domain_info * const domain,
@@ -629,19 +597,19 @@ static int tomoyo_update_file_acl(const char *filename, u8 perm,
629 */ 597 */
630 return 0; 598 return 0;
631 if (perm & 4) 599 if (perm & 4)
632 tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename, 600 tomoyo_update_path_acl(TOMOYO_TYPE_READ, filename, domain,
633 domain, is_delete); 601 is_delete);
634 if (perm & 2) 602 if (perm & 2)
635 tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename, 603 tomoyo_update_path_acl(TOMOYO_TYPE_WRITE, filename, domain,
636 domain, is_delete); 604 is_delete);
637 if (perm & 1) 605 if (perm & 1)
638 tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL, 606 tomoyo_update_path_acl(TOMOYO_TYPE_EXECUTE, filename, domain,
639 filename, domain, is_delete); 607 is_delete);
640 return 0; 608 return 0;
641} 609}
642 610
643/** 611/**
644 * tomoyo_check_single_path_acl2 - Check permission for single path operation. 612 * tomoyo_path_acl2 - Check permission for single path operation.
645 * 613 *
646 * @domain: Pointer to "struct tomoyo_domain_info". 614 * @domain: Pointer to "struct tomoyo_domain_info".
647 * @filename: Filename to check. 615 * @filename: Filename to check.
@@ -649,26 +617,28 @@ static int tomoyo_update_file_acl(const char *filename, u8 perm,
649 * @may_use_pattern: True if patterned ACL is permitted. 617 * @may_use_pattern: True if patterned ACL is permitted.
650 * 618 *
651 * Returns 0 on success, -EPERM otherwise. 619 * Returns 0 on success, -EPERM otherwise.
620 *
621 * Caller holds tomoyo_read_lock().
652 */ 622 */
653static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * 623static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain,
654 domain, 624 const struct tomoyo_path_info *filename,
655 const struct tomoyo_path_info * 625 const u32 perm, const bool may_use_pattern)
656 filename,
657 const u16 perm,
658 const bool may_use_pattern)
659{ 626{
660 struct tomoyo_acl_info *ptr; 627 struct tomoyo_acl_info *ptr;
661 int error = -EPERM; 628 int error = -EPERM;
662 629
663 down_read(&tomoyo_domain_acl_info_list_lock); 630 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
664 list_for_each_entry(ptr, &domain->acl_info_list, list) { 631 struct tomoyo_path_acl *acl;
665 struct tomoyo_single_path_acl_record *acl; 632 if (ptr->type != TOMOYO_TYPE_PATH_ACL)
666 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
667 continue;
668 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
669 head);
670 if (!(acl->perm & perm))
671 continue; 633 continue;
634 acl = container_of(ptr, struct tomoyo_path_acl, head);
635 if (perm <= 0xFFFF) {
636 if (!(acl->perm & perm))
637 continue;
638 } else {
639 if (!(acl->perm_high & (perm >> 16)))
640 continue;
641 }
672 if (may_use_pattern || !acl->filename->is_patterned) { 642 if (may_use_pattern || !acl->filename->is_patterned) {
673 if (!tomoyo_path_matches_pattern(filename, 643 if (!tomoyo_path_matches_pattern(filename,
674 acl->filename)) 644 acl->filename))
@@ -679,7 +649,6 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
679 error = 0; 649 error = 0;
680 break; 650 break;
681 } 651 }
682 up_read(&tomoyo_domain_acl_info_list_lock);
683 return error; 652 return error;
684} 653}
685 654
@@ -691,27 +660,28 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
691 * @operation: Mode ("read" or "write" or "read/write" or "execute"). 660 * @operation: Mode ("read" or "write" or "read/write" or "execute").
692 * 661 *
693 * Returns 0 on success, -EPERM otherwise. 662 * Returns 0 on success, -EPERM otherwise.
663 *
664 * Caller holds tomoyo_read_lock().
694 */ 665 */
695static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, 666static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
696 const struct tomoyo_path_info *filename, 667 const struct tomoyo_path_info *filename,
697 const u8 operation) 668 const u8 operation)
698{ 669{
699 u16 perm = 0; 670 u32 perm = 0;
700 671
701 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) 672 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
702 return 0; 673 return 0;
703 if (operation == 6) 674 if (operation == 6)
704 perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL; 675 perm = 1 << TOMOYO_TYPE_READ_WRITE;
705 else if (operation == 4) 676 else if (operation == 4)
706 perm = 1 << TOMOYO_TYPE_READ_ACL; 677 perm = 1 << TOMOYO_TYPE_READ;
707 else if (operation == 2) 678 else if (operation == 2)
708 perm = 1 << TOMOYO_TYPE_WRITE_ACL; 679 perm = 1 << TOMOYO_TYPE_WRITE;
709 else if (operation == 1) 680 else if (operation == 1)
710 perm = 1 << TOMOYO_TYPE_EXECUTE_ACL; 681 perm = 1 << TOMOYO_TYPE_EXECUTE;
711 else 682 else
712 BUG(); 683 BUG();
713 return tomoyo_check_single_path_acl2(domain, filename, perm, 684 return tomoyo_path_acl2(domain, filename, perm, operation != 1);
714 operation != 1);
715} 685}
716 686
717/** 687/**
@@ -724,6 +694,8 @@ static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
724 * @mode: Access control mode. 694 * @mode: Access control mode.
725 * 695 *
726 * Returns 0 on success, negative value otherwise. 696 * Returns 0 on success, negative value otherwise.
697 *
698 * Caller holds tomoyo_read_lock().
727 */ 699 */
728static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, 700static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
729 const struct tomoyo_path_info *filename, 701 const struct tomoyo_path_info *filename,
@@ -737,18 +709,17 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
737 if (!filename) 709 if (!filename)
738 return 0; 710 return 0;
739 error = tomoyo_check_file_acl(domain, filename, perm); 711 error = tomoyo_check_file_acl(domain, filename, perm);
740 if (error && perm == 4 && 712 if (error && perm == 4 && !domain->ignore_global_allow_read
741 (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0
742 && tomoyo_is_globally_readable_file(filename)) 713 && tomoyo_is_globally_readable_file(filename))
743 error = 0; 714 error = 0;
744 if (perm == 6) 715 if (perm == 6)
745 msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL); 716 msg = tomoyo_path2keyword(TOMOYO_TYPE_READ_WRITE);
746 else if (perm == 4) 717 else if (perm == 4)
747 msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL); 718 msg = tomoyo_path2keyword(TOMOYO_TYPE_READ);
748 else if (perm == 2) 719 else if (perm == 2)
749 msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL); 720 msg = tomoyo_path2keyword(TOMOYO_TYPE_WRITE);
750 else if (perm == 1) 721 else if (perm == 1)
751 msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL); 722 msg = tomoyo_path2keyword(TOMOYO_TYPE_EXECUTE);
752 else 723 else
753 BUG(); 724 BUG();
754 if (!error) 725 if (!error)
@@ -777,6 +748,8 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
777 * @is_delete: True if it is a delete request. 748 * @is_delete: True if it is a delete request.
778 * 749 *
779 * Returns 0 on success, negative value otherwise. 750 * Returns 0 on success, negative value otherwise.
751 *
752 * Caller holds tomoyo_read_lock().
780 */ 753 */
781int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, 754int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
782 const bool is_delete) 755 const bool is_delete)
@@ -795,28 +768,28 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
795 if (strncmp(data, "allow_", 6)) 768 if (strncmp(data, "allow_", 6))
796 goto out; 769 goto out;
797 data += 6; 770 data += 6;
798 for (type = 0; type < TOMOYO_MAX_SINGLE_PATH_OPERATION; type++) { 771 for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) {
799 if (strcmp(data, tomoyo_sp_keyword[type])) 772 if (strcmp(data, tomoyo_path_keyword[type]))
800 continue; 773 continue;
801 return tomoyo_update_single_path_acl(type, filename, 774 return tomoyo_update_path_acl(type, filename, domain,
802 domain, is_delete); 775 is_delete);
803 } 776 }
804 filename2 = strchr(filename, ' '); 777 filename2 = strchr(filename, ' ');
805 if (!filename2) 778 if (!filename2)
806 goto out; 779 goto out;
807 *filename2++ = '\0'; 780 *filename2++ = '\0';
808 for (type = 0; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION; type++) { 781 for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) {
809 if (strcmp(data, tomoyo_dp_keyword[type])) 782 if (strcmp(data, tomoyo_path2_keyword[type]))
810 continue; 783 continue;
811 return tomoyo_update_double_path_acl(type, filename, filename2, 784 return tomoyo_update_path2_acl(type, filename, filename2,
812 domain, is_delete); 785 domain, is_delete);
813 } 786 }
814 out: 787 out:
815 return -EINVAL; 788 return -EINVAL;
816} 789}
817 790
818/** 791/**
819 * tomoyo_update_single_path_acl - Update "struct tomoyo_single_path_acl_record" list. 792 * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
820 * 793 *
821 * @type: Type of operation. 794 * @type: Type of operation.
822 * @filename: Filename. 795 * @filename: Filename.
@@ -824,85 +797,82 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
824 * @is_delete: True if it is a delete request. 797 * @is_delete: True if it is a delete request.
825 * 798 *
826 * Returns 0 on success, negative value otherwise. 799 * Returns 0 on success, negative value otherwise.
800 *
801 * Caller holds tomoyo_read_lock().
827 */ 802 */
828static int tomoyo_update_single_path_acl(const u8 type, const char *filename, 803static int tomoyo_update_path_acl(const u8 type, const char *filename,
829 struct tomoyo_domain_info * 804 struct tomoyo_domain_info *const domain,
830 const domain, const bool is_delete) 805 const bool is_delete)
831{ 806{
832 static const u16 rw_mask = 807 static const u32 rw_mask =
833 (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL); 808 (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE);
834 const struct tomoyo_path_info *saved_filename; 809 const struct tomoyo_path_info *saved_filename;
835 struct tomoyo_acl_info *ptr; 810 struct tomoyo_acl_info *ptr;
836 struct tomoyo_single_path_acl_record *acl; 811 struct tomoyo_path_acl *entry = NULL;
837 int error = -ENOMEM; 812 int error = is_delete ? -ENOENT : -ENOMEM;
838 const u16 perm = 1 << type; 813 const u32 perm = 1 << type;
839 814
840 if (!domain) 815 if (!domain)
841 return -EINVAL; 816 return -EINVAL;
842 if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__)) 817 if (!tomoyo_is_correct_path(filename, 0, 0, 0))
843 return -EINVAL; 818 return -EINVAL;
844 saved_filename = tomoyo_save_name(filename); 819 saved_filename = tomoyo_get_name(filename);
845 if (!saved_filename) 820 if (!saved_filename)
846 return -ENOMEM; 821 return -ENOMEM;
847 down_write(&tomoyo_domain_acl_info_list_lock); 822 if (!is_delete)
848 if (is_delete) 823 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
849 goto delete; 824 mutex_lock(&tomoyo_policy_lock);
850 list_for_each_entry(ptr, &domain->acl_info_list, list) { 825 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
851 if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) 826 struct tomoyo_path_acl *acl =
827 container_of(ptr, struct tomoyo_path_acl, head);
828 if (ptr->type != TOMOYO_TYPE_PATH_ACL)
852 continue; 829 continue;
853 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
854 head);
855 if (acl->filename != saved_filename) 830 if (acl->filename != saved_filename)
856 continue; 831 continue;
857 /* Special case. Clear all bits if marked as deleted. */ 832 if (is_delete) {
858 if (ptr->type & TOMOYO_ACL_DELETED) 833 if (perm <= 0xFFFF)
859 acl->perm = 0; 834 acl->perm &= ~perm;
860 acl->perm |= perm; 835 else
861 if ((acl->perm & rw_mask) == rw_mask) 836 acl->perm_high &= ~(perm >> 16);
862 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL; 837 if ((acl->perm & rw_mask) != rw_mask)
863 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) 838 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
864 acl->perm |= rw_mask; 839 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)))
865 ptr->type &= ~TOMOYO_ACL_DELETED; 840 acl->perm &= ~rw_mask;
841 } else {
842 if (perm <= 0xFFFF)
843 acl->perm |= perm;
844 else
845 acl->perm_high |= (perm >> 16);
846 if ((acl->perm & rw_mask) == rw_mask)
847 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE;
848 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))
849 acl->perm |= rw_mask;
850 }
866 error = 0; 851 error = 0;
867 goto out; 852 break;
868 } 853 }
869 /* Not found. Append it to the tail. */ 854 if (!is_delete && error && tomoyo_memory_ok(entry)) {
870 acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL); 855 entry->head.type = TOMOYO_TYPE_PATH_ACL;
871 if (!acl) 856 if (perm <= 0xFFFF)
872 goto out; 857 entry->perm = perm;
873 acl->perm = perm; 858 else
874 if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) 859 entry->perm_high = (perm >> 16);
875 acl->perm |= rw_mask; 860 if (perm == (1 << TOMOYO_TYPE_READ_WRITE))
876 acl->filename = saved_filename; 861 entry->perm |= rw_mask;
877 list_add_tail(&acl->head.list, &domain->acl_info_list); 862 entry->filename = saved_filename;
878 error = 0; 863 saved_filename = NULL;
879 goto out; 864 list_add_tail_rcu(&entry->head.list, &domain->acl_info_list);
880 delete: 865 entry = NULL;
881 error = -ENOENT;
882 list_for_each_entry(ptr, &domain->acl_info_list, list) {
883 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
884 continue;
885 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
886 head);
887 if (acl->filename != saved_filename)
888 continue;
889 acl->perm &= ~perm;
890 if ((acl->perm & rw_mask) != rw_mask)
891 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
892 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
893 acl->perm &= ~rw_mask;
894 if (!acl->perm)
895 ptr->type |= TOMOYO_ACL_DELETED;
896 error = 0; 866 error = 0;
897 break;
898 } 867 }
899 out: 868 mutex_unlock(&tomoyo_policy_lock);
900 up_write(&tomoyo_domain_acl_info_list_lock); 869 kfree(entry);
870 tomoyo_put_name(saved_filename);
901 return error; 871 return error;
902} 872}
903 873
904/** 874/**
905 * tomoyo_update_double_path_acl - Update "struct tomoyo_double_path_acl_record" list. 875 * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
906 * 876 *
907 * @type: Type of operation. 877 * @type: Type of operation.
908 * @filename1: First filename. 878 * @filename1: First filename.
@@ -911,98 +881,88 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
911 * @is_delete: True if it is a delete request. 881 * @is_delete: True if it is a delete request.
912 * 882 *
913 * Returns 0 on success, negative value otherwise. 883 * Returns 0 on success, negative value otherwise.
884 *
885 * Caller holds tomoyo_read_lock().
914 */ 886 */
915static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, 887static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
916 const char *filename2, 888 const char *filename2,
917 struct tomoyo_domain_info * 889 struct tomoyo_domain_info *const domain,
918 const domain, const bool is_delete) 890 const bool is_delete)
919{ 891{
920 const struct tomoyo_path_info *saved_filename1; 892 const struct tomoyo_path_info *saved_filename1;
921 const struct tomoyo_path_info *saved_filename2; 893 const struct tomoyo_path_info *saved_filename2;
922 struct tomoyo_acl_info *ptr; 894 struct tomoyo_acl_info *ptr;
923 struct tomoyo_double_path_acl_record *acl; 895 struct tomoyo_path2_acl *entry = NULL;
924 int error = -ENOMEM; 896 int error = is_delete ? -ENOENT : -ENOMEM;
925 const u8 perm = 1 << type; 897 const u8 perm = 1 << type;
926 898
927 if (!domain) 899 if (!domain)
928 return -EINVAL; 900 return -EINVAL;
929 if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) || 901 if (!tomoyo_is_correct_path(filename1, 0, 0, 0) ||
930 !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__)) 902 !tomoyo_is_correct_path(filename2, 0, 0, 0))
931 return -EINVAL; 903 return -EINVAL;
932 saved_filename1 = tomoyo_save_name(filename1); 904 saved_filename1 = tomoyo_get_name(filename1);
933 saved_filename2 = tomoyo_save_name(filename2); 905 saved_filename2 = tomoyo_get_name(filename2);
934 if (!saved_filename1 || !saved_filename2) 906 if (!saved_filename1 || !saved_filename2)
935 return -ENOMEM;
936 down_write(&tomoyo_domain_acl_info_list_lock);
937 if (is_delete)
938 goto delete;
939 list_for_each_entry(ptr, &domain->acl_info_list, list) {
940 if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
941 continue;
942 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
943 head);
944 if (acl->filename1 != saved_filename1 ||
945 acl->filename2 != saved_filename2)
946 continue;
947 /* Special case. Clear all bits if marked as deleted. */
948 if (ptr->type & TOMOYO_ACL_DELETED)
949 acl->perm = 0;
950 acl->perm |= perm;
951 ptr->type &= ~TOMOYO_ACL_DELETED;
952 error = 0;
953 goto out; 907 goto out;
954 } 908 if (!is_delete)
955 /* Not found. Append it to the tail. */ 909 entry = kmalloc(sizeof(*entry), GFP_KERNEL);
956 acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL); 910 mutex_lock(&tomoyo_policy_lock);
957 if (!acl) 911 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
958 goto out; 912 struct tomoyo_path2_acl *acl =
959 acl->perm = perm; 913 container_of(ptr, struct tomoyo_path2_acl, head);
960 acl->filename1 = saved_filename1; 914 if (ptr->type != TOMOYO_TYPE_PATH2_ACL)
961 acl->filename2 = saved_filename2;
962 list_add_tail(&acl->head.list, &domain->acl_info_list);
963 error = 0;
964 goto out;
965 delete:
966 error = -ENOENT;
967 list_for_each_entry(ptr, &domain->acl_info_list, list) {
968 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
969 continue; 915 continue;
970 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
971 head);
972 if (acl->filename1 != saved_filename1 || 916 if (acl->filename1 != saved_filename1 ||
973 acl->filename2 != saved_filename2) 917 acl->filename2 != saved_filename2)
974 continue; 918 continue;
975 acl->perm &= ~perm; 919 if (is_delete)
976 if (!acl->perm) 920 acl->perm &= ~perm;
977 ptr->type |= TOMOYO_ACL_DELETED; 921 else
922 acl->perm |= perm;
978 error = 0; 923 error = 0;
979 break; 924 break;
980 } 925 }
926 if (!is_delete && error && tomoyo_memory_ok(entry)) {
927 entry->head.type = TOMOYO_TYPE_PATH2_ACL;
928 entry->perm = perm;
929 entry->filename1 = saved_filename1;
930 saved_filename1 = NULL;
931 entry->filename2 = saved_filename2;
932 saved_filename2 = NULL;
933 list_add_tail_rcu(&entry->head.list, &domain->acl_info_list);
934 entry = NULL;
935 error = 0;
936 }
937 mutex_unlock(&tomoyo_policy_lock);
981 out: 938 out:
982 up_write(&tomoyo_domain_acl_info_list_lock); 939 tomoyo_put_name(saved_filename1);
940 tomoyo_put_name(saved_filename2);
941 kfree(entry);
983 return error; 942 return error;
984} 943}
985 944
986/** 945/**
987 * tomoyo_check_single_path_acl - Check permission for single path operation. 946 * tomoyo_path_acl - Check permission for single path operation.
988 * 947 *
989 * @domain: Pointer to "struct tomoyo_domain_info". 948 * @domain: Pointer to "struct tomoyo_domain_info".
990 * @type: Type of operation. 949 * @type: Type of operation.
991 * @filename: Filename to check. 950 * @filename: Filename to check.
992 * 951 *
993 * Returns 0 on success, negative value otherwise. 952 * Returns 0 on success, negative value otherwise.
953 *
954 * Caller holds tomoyo_read_lock().
994 */ 955 */
995static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain, 956static int tomoyo_path_acl(struct tomoyo_domain_info *domain, const u8 type,
996 const u8 type, 957 const struct tomoyo_path_info *filename)
997 const struct tomoyo_path_info *filename)
998{ 958{
999 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) 959 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
1000 return 0; 960 return 0;
1001 return tomoyo_check_single_path_acl2(domain, filename, 1 << type, 1); 961 return tomoyo_path_acl2(domain, filename, 1 << type, 1);
1002} 962}
1003 963
1004/** 964/**
1005 * tomoyo_check_double_path_acl - Check permission for double path operation. 965 * tomoyo_path2_acl - Check permission for double path operation.
1006 * 966 *
1007 * @domain: Pointer to "struct tomoyo_domain_info". 967 * @domain: Pointer to "struct tomoyo_domain_info".
1008 * @type: Type of operation. 968 * @type: Type of operation.
@@ -1010,13 +970,13 @@ static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain,
1010 * @filename2: Second filename to check. 970 * @filename2: Second filename to check.
1011 * 971 *
1012 * Returns 0 on success, -EPERM otherwise. 972 * Returns 0 on success, -EPERM otherwise.
973 *
974 * Caller holds tomoyo_read_lock().
1013 */ 975 */
1014static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, 976static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain,
1015 const u8 type, 977 const u8 type,
1016 const struct tomoyo_path_info * 978 const struct tomoyo_path_info *filename1,
1017 filename1, 979 const struct tomoyo_path_info *filename2)
1018 const struct tomoyo_path_info *
1019 filename2)
1020{ 980{
1021 struct tomoyo_acl_info *ptr; 981 struct tomoyo_acl_info *ptr;
1022 const u8 perm = 1 << type; 982 const u8 perm = 1 << type;
@@ -1024,13 +984,11 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
1024 984
1025 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) 985 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
1026 return 0; 986 return 0;
1027 down_read(&tomoyo_domain_acl_info_list_lock); 987 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
1028 list_for_each_entry(ptr, &domain->acl_info_list, list) { 988 struct tomoyo_path2_acl *acl;
1029 struct tomoyo_double_path_acl_record *acl; 989 if (ptr->type != TOMOYO_TYPE_PATH2_ACL)
1030 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
1031 continue; 990 continue;
1032 acl = container_of(ptr, struct tomoyo_double_path_acl_record, 991 acl = container_of(ptr, struct tomoyo_path2_acl, head);
1033 head);
1034 if (!(acl->perm & perm)) 992 if (!(acl->perm & perm))
1035 continue; 993 continue;
1036 if (!tomoyo_path_matches_pattern(filename1, acl->filename1)) 994 if (!tomoyo_path_matches_pattern(filename1, acl->filename1))
@@ -1040,12 +998,11 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
1040 error = 0; 998 error = 0;
1041 break; 999 break;
1042 } 1000 }
1043 up_read(&tomoyo_domain_acl_info_list_lock);
1044 return error; 1001 return error;
1045} 1002}
1046 1003
1047/** 1004/**
1048 * tomoyo_check_single_path_permission2 - Check permission for single path operation. 1005 * tomoyo_path_permission2 - Check permission for single path operation.
1049 * 1006 *
1050 * @domain: Pointer to "struct tomoyo_domain_info". 1007 * @domain: Pointer to "struct tomoyo_domain_info".
1051 * @operation: Type of operation. 1008 * @operation: Type of operation.
@@ -1053,11 +1010,13 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
1053 * @mode: Access control mode. 1010 * @mode: Access control mode.
1054 * 1011 *
1055 * Returns 0 on success, negative value otherwise. 1012 * Returns 0 on success, negative value otherwise.
1013 *
1014 * Caller holds tomoyo_read_lock().
1056 */ 1015 */
1057static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * 1016static int tomoyo_path_permission2(struct tomoyo_domain_info *const domain,
1058 const domain, u8 operation, 1017 u8 operation,
1059 const struct tomoyo_path_info * 1018 const struct tomoyo_path_info *filename,
1060 filename, const u8 mode) 1019 const u8 mode)
1061{ 1020{
1062 const char *msg; 1021 const char *msg;
1063 int error; 1022 int error;
@@ -1066,8 +1025,8 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
1066 if (!mode) 1025 if (!mode)
1067 return 0; 1026 return 0;
1068 next: 1027 next:
1069 error = tomoyo_check_single_path_acl(domain, operation, filename); 1028 error = tomoyo_path_acl(domain, operation, filename);
1070 msg = tomoyo_sp2keyword(operation); 1029 msg = tomoyo_path2keyword(operation);
1071 if (!error) 1030 if (!error)
1072 goto ok; 1031 goto ok;
1073 if (tomoyo_verbose_mode(domain)) 1032 if (tomoyo_verbose_mode(domain))
@@ -1076,7 +1035,7 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
1076 tomoyo_get_last_name(domain)); 1035 tomoyo_get_last_name(domain));
1077 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { 1036 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
1078 const char *name = tomoyo_get_file_pattern(filename)->name; 1037 const char *name = tomoyo_get_file_pattern(filename)->name;
1079 tomoyo_update_single_path_acl(operation, name, domain, false); 1038 tomoyo_update_path_acl(operation, name, domain, false);
1080 } 1039 }
1081 if (!is_enforce) 1040 if (!is_enforce)
1082 error = 0; 1041 error = 0;
@@ -1086,9 +1045,9 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
1086 * we need to check "allow_rewrite" permission if the filename is 1045 * we need to check "allow_rewrite" permission if the filename is
1087 * specified by "deny_rewrite" keyword. 1046 * specified by "deny_rewrite" keyword.
1088 */ 1047 */
1089 if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL && 1048 if (!error && operation == TOMOYO_TYPE_TRUNCATE &&
1090 tomoyo_is_no_rewrite_file(filename)) { 1049 tomoyo_is_no_rewrite_file(filename)) {
1091 operation = TOMOYO_TYPE_REWRITE_ACL; 1050 operation = TOMOYO_TYPE_REWRITE;
1092 goto next; 1051 goto next;
1093 } 1052 }
1094 return error; 1053 return error;
@@ -1101,6 +1060,8 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
1101 * @filename: Check permission for "execute". 1060 * @filename: Check permission for "execute".
1102 * 1061 *
1103 * Returns 0 on success, negativevalue otherwise. 1062 * Returns 0 on success, negativevalue otherwise.
1063 *
1064 * Caller holds tomoyo_read_lock().
1104 */ 1065 */
1105int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, 1066int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
1106 const struct tomoyo_path_info *filename) 1067 const struct tomoyo_path_info *filename)
@@ -1129,6 +1090,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1129 struct tomoyo_path_info *buf; 1090 struct tomoyo_path_info *buf;
1130 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 1091 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1131 const bool is_enforce = (mode == 3); 1092 const bool is_enforce = (mode == 3);
1093 int idx;
1132 1094
1133 if (!mode || !path->mnt) 1095 if (!mode || !path->mnt)
1134 return 0; 1096 return 0;
@@ -1140,6 +1102,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1140 * don't call me. 1102 * don't call me.
1141 */ 1103 */
1142 return 0; 1104 return 0;
1105 idx = tomoyo_read_lock();
1143 buf = tomoyo_get_path(path); 1106 buf = tomoyo_get_path(path);
1144 if (!buf) 1107 if (!buf)
1145 goto out; 1108 goto out;
@@ -1152,49 +1115,50 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1152 if ((acc_mode & MAY_WRITE) && 1115 if ((acc_mode & MAY_WRITE) &&
1153 ((flag & O_TRUNC) || !(flag & O_APPEND)) && 1116 ((flag & O_TRUNC) || !(flag & O_APPEND)) &&
1154 (tomoyo_is_no_rewrite_file(buf))) { 1117 (tomoyo_is_no_rewrite_file(buf))) {
1155 error = tomoyo_check_single_path_permission2(domain, 1118 error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE,
1156 TOMOYO_TYPE_REWRITE_ACL, 1119 buf, mode);
1157 buf, mode);
1158 } 1120 }
1159 if (!error) 1121 if (!error)
1160 error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open", 1122 error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open",
1161 mode); 1123 mode);
1162 if (!error && (flag & O_TRUNC)) 1124 if (!error && (flag & O_TRUNC))
1163 error = tomoyo_check_single_path_permission2(domain, 1125 error = tomoyo_path_permission2(domain, TOMOYO_TYPE_TRUNCATE,
1164 TOMOYO_TYPE_TRUNCATE_ACL, 1126 buf, mode);
1165 buf, mode);
1166 out: 1127 out:
1167 tomoyo_free(buf); 1128 kfree(buf);
1129 tomoyo_read_unlock(idx);
1168 if (!is_enforce) 1130 if (!is_enforce)
1169 error = 0; 1131 error = 0;
1170 return error; 1132 return error;
1171} 1133}
1172 1134
1173/** 1135/**
1174 * tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink". 1136 * tomoyo_path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate", "symlink", "ioctl", "chmod", "chown", "chgrp", "chroot", "mount" and "unmount".
1175 * 1137 *
1176 * @domain: Pointer to "struct tomoyo_domain_info".
1177 * @operation: Type of operation. 1138 * @operation: Type of operation.
1178 * @path: Pointer to "struct path". 1139 * @path: Pointer to "struct path".
1179 * 1140 *
1180 * Returns 0 on success, negative value otherwise. 1141 * Returns 0 on success, negative value otherwise.
1181 */ 1142 */
1182int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, 1143int tomoyo_path_perm(const u8 operation, struct path *path)
1183 const u8 operation, struct path *path)
1184{ 1144{
1185 int error = -ENOMEM; 1145 int error = -ENOMEM;
1186 struct tomoyo_path_info *buf; 1146 struct tomoyo_path_info *buf;
1147 struct tomoyo_domain_info *domain = tomoyo_domain();
1187 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 1148 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1188 const bool is_enforce = (mode == 3); 1149 const bool is_enforce = (mode == 3);
1150 int idx;
1189 1151
1190 if (!mode || !path->mnt) 1152 if (!mode || !path->mnt)
1191 return 0; 1153 return 0;
1154 idx = tomoyo_read_lock();
1192 buf = tomoyo_get_path(path); 1155 buf = tomoyo_get_path(path);
1193 if (!buf) 1156 if (!buf)
1194 goto out; 1157 goto out;
1195 switch (operation) { 1158 switch (operation) {
1196 case TOMOYO_TYPE_MKDIR_ACL: 1159 case TOMOYO_TYPE_MKDIR:
1197 case TOMOYO_TYPE_RMDIR_ACL: 1160 case TOMOYO_TYPE_RMDIR:
1161 case TOMOYO_TYPE_CHROOT:
1198 if (!buf->is_dir) { 1162 if (!buf->is_dir) {
1199 /* 1163 /*
1200 * tomoyo_get_path() reserves space for appending "/." 1164 * tomoyo_get_path() reserves space for appending "/."
@@ -1203,10 +1167,10 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
1203 tomoyo_fill_path_info(buf); 1167 tomoyo_fill_path_info(buf);
1204 } 1168 }
1205 } 1169 }
1206 error = tomoyo_check_single_path_permission2(domain, operation, buf, 1170 error = tomoyo_path_permission2(domain, operation, buf, mode);
1207 mode);
1208 out: 1171 out:
1209 tomoyo_free(buf); 1172 kfree(buf);
1173 tomoyo_read_unlock(idx);
1210 if (!is_enforce) 1174 if (!is_enforce)
1211 error = 0; 1175 error = 0;
1212 return error; 1176 return error;
@@ -1215,21 +1179,23 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
1215/** 1179/**
1216 * tomoyo_check_rewrite_permission - Check permission for "rewrite". 1180 * tomoyo_check_rewrite_permission - Check permission for "rewrite".
1217 * 1181 *
1218 * @domain: Pointer to "struct tomoyo_domain_info".
1219 * @filp: Pointer to "struct file". 1182 * @filp: Pointer to "struct file".
1220 * 1183 *
1221 * Returns 0 on success, negative value otherwise. 1184 * Returns 0 on success, negative value otherwise.
1222 */ 1185 */
1223int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, 1186int tomoyo_check_rewrite_permission(struct file *filp)
1224 struct file *filp)
1225{ 1187{
1226 int error = -ENOMEM; 1188 int error = -ENOMEM;
1189 struct tomoyo_domain_info *domain = tomoyo_domain();
1227 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 1190 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1228 const bool is_enforce = (mode == 3); 1191 const bool is_enforce = (mode == 3);
1229 struct tomoyo_path_info *buf; 1192 struct tomoyo_path_info *buf;
1193 int idx;
1230 1194
1231 if (!mode || !filp->f_path.mnt) 1195 if (!mode || !filp->f_path.mnt)
1232 return 0; 1196 return 0;
1197
1198 idx = tomoyo_read_lock();
1233 buf = tomoyo_get_path(&filp->f_path); 1199 buf = tomoyo_get_path(&filp->f_path);
1234 if (!buf) 1200 if (!buf)
1235 goto out; 1201 goto out;
@@ -1237,38 +1203,38 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
1237 error = 0; 1203 error = 0;
1238 goto out; 1204 goto out;
1239 } 1205 }
1240 error = tomoyo_check_single_path_permission2(domain, 1206 error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, buf, mode);
1241 TOMOYO_TYPE_REWRITE_ACL,
1242 buf, mode);
1243 out: 1207 out:
1244 tomoyo_free(buf); 1208 kfree(buf);
1209 tomoyo_read_unlock(idx);
1245 if (!is_enforce) 1210 if (!is_enforce)
1246 error = 0; 1211 error = 0;
1247 return error; 1212 return error;
1248} 1213}
1249 1214
1250/** 1215/**
1251 * tomoyo_check_2path_perm - Check permission for "rename" and "link". 1216 * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root".
1252 * 1217 *
1253 * @domain: Pointer to "struct tomoyo_domain_info".
1254 * @operation: Type of operation. 1218 * @operation: Type of operation.
1255 * @path1: Pointer to "struct path". 1219 * @path1: Pointer to "struct path".
1256 * @path2: Pointer to "struct path". 1220 * @path2: Pointer to "struct path".
1257 * 1221 *
1258 * Returns 0 on success, negative value otherwise. 1222 * Returns 0 on success, negative value otherwise.
1259 */ 1223 */
1260int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, 1224int tomoyo_path2_perm(const u8 operation, struct path *path1,
1261 const u8 operation, struct path *path1, 1225 struct path *path2)
1262 struct path *path2)
1263{ 1226{
1264 int error = -ENOMEM; 1227 int error = -ENOMEM;
1265 struct tomoyo_path_info *buf1, *buf2; 1228 struct tomoyo_path_info *buf1, *buf2;
1229 struct tomoyo_domain_info *domain = tomoyo_domain();
1266 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); 1230 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1267 const bool is_enforce = (mode == 3); 1231 const bool is_enforce = (mode == 3);
1268 const char *msg; 1232 const char *msg;
1233 int idx;
1269 1234
1270 if (!mode || !path1->mnt || !path2->mnt) 1235 if (!mode || !path1->mnt || !path2->mnt)
1271 return 0; 1236 return 0;
1237 idx = tomoyo_read_lock();
1272 buf1 = tomoyo_get_path(path1); 1238 buf1 = tomoyo_get_path(path1);
1273 buf2 = tomoyo_get_path(path2); 1239 buf2 = tomoyo_get_path(path2);
1274 if (!buf1 || !buf2) 1240 if (!buf1 || !buf2)
@@ -1289,8 +1255,8 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain,
1289 } 1255 }
1290 } 1256 }
1291 } 1257 }
1292 error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2); 1258 error = tomoyo_path2_acl(domain, operation, buf1, buf2);
1293 msg = tomoyo_dp2keyword(operation); 1259 msg = tomoyo_path22keyword(operation);
1294 if (!error) 1260 if (!error)
1295 goto out; 1261 goto out;
1296 if (tomoyo_verbose_mode(domain)) 1262 if (tomoyo_verbose_mode(domain))
@@ -1301,12 +1267,13 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain,
1301 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { 1267 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
1302 const char *name1 = tomoyo_get_file_pattern(buf1)->name; 1268 const char *name1 = tomoyo_get_file_pattern(buf1)->name;
1303 const char *name2 = tomoyo_get_file_pattern(buf2)->name; 1269 const char *name2 = tomoyo_get_file_pattern(buf2)->name;
1304 tomoyo_update_double_path_acl(operation, name1, name2, domain, 1270 tomoyo_update_path2_acl(operation, name1, name2, domain,
1305 false); 1271 false);
1306 } 1272 }
1307 out: 1273 out:
1308 tomoyo_free(buf1); 1274 kfree(buf1);
1309 tomoyo_free(buf2); 1275 kfree(buf2);
1276 tomoyo_read_unlock(idx);
1310 if (!is_enforce) 1277 if (!is_enforce)
1311 error = 0; 1278 error = 0;
1312 return error; 1279 return error;
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c
new file mode 100644
index 000000000000..9645525ccdd4
--- /dev/null
+++ b/security/tomoyo/gc.c
@@ -0,0 +1,370 @@
1/*
2 * security/tomoyo/gc.c
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
7 *
8 */
9
10#include "common.h"
11#include <linux/kthread.h>
12
13enum tomoyo_gc_id {
14 TOMOYO_ID_DOMAIN_INITIALIZER,
15 TOMOYO_ID_DOMAIN_KEEPER,
16 TOMOYO_ID_ALIAS,
17 TOMOYO_ID_GLOBALLY_READABLE,
18 TOMOYO_ID_PATTERN,
19 TOMOYO_ID_NO_REWRITE,
20 TOMOYO_ID_MANAGER,
21 TOMOYO_ID_NAME,
22 TOMOYO_ID_ACL,
23 TOMOYO_ID_DOMAIN
24};
25
26struct tomoyo_gc_entry {
27 struct list_head list;
28 int type;
29 void *element;
30};
31static LIST_HEAD(tomoyo_gc_queue);
32static DEFINE_MUTEX(tomoyo_gc_mutex);
33
34/* Caller holds tomoyo_policy_lock mutex. */
35static bool tomoyo_add_to_gc(const int type, void *element)
36{
37 struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
38 if (!entry)
39 return false;
40 entry->type = type;
41 entry->element = element;
42 list_add(&entry->list, &tomoyo_gc_queue);
43 return true;
44}
45
46static void tomoyo_del_allow_read
47(struct tomoyo_globally_readable_file_entry *ptr)
48{
49 tomoyo_put_name(ptr->filename);
50}
51
52static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr)
53{
54 tomoyo_put_name(ptr->pattern);
55}
56
57static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr)
58{
59 tomoyo_put_name(ptr->pattern);
60}
61
62static void tomoyo_del_domain_initializer
63(struct tomoyo_domain_initializer_entry *ptr)
64{
65 tomoyo_put_name(ptr->domainname);
66 tomoyo_put_name(ptr->program);
67}
68
69static void tomoyo_del_domain_keeper(struct tomoyo_domain_keeper_entry *ptr)
70{
71 tomoyo_put_name(ptr->domainname);
72 tomoyo_put_name(ptr->program);
73}
74
75static void tomoyo_del_alias(struct tomoyo_alias_entry *ptr)
76{
77 tomoyo_put_name(ptr->original_name);
78 tomoyo_put_name(ptr->aliased_name);
79}
80
81static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr)
82{
83 tomoyo_put_name(ptr->manager);
84}
85
86static void tomoyo_del_acl(struct tomoyo_acl_info *acl)
87{
88 switch (acl->type) {
89 case TOMOYO_TYPE_PATH_ACL:
90 {
91 struct tomoyo_path_acl *entry
92 = container_of(acl, typeof(*entry), head);
93 tomoyo_put_name(entry->filename);
94 }
95 break;
96 case TOMOYO_TYPE_PATH2_ACL:
97 {
98 struct tomoyo_path2_acl *entry
99 = container_of(acl, typeof(*entry), head);
100 tomoyo_put_name(entry->filename1);
101 tomoyo_put_name(entry->filename2);
102 }
103 break;
104 default:
105 printk(KERN_WARNING "Unknown type\n");
106 break;
107 }
108}
109
110static bool tomoyo_del_domain(struct tomoyo_domain_info *domain)
111{
112 struct tomoyo_acl_info *acl;
113 struct tomoyo_acl_info *tmp;
114 /*
115 * Since we don't protect whole execve() operation using SRCU,
116 * we need to recheck domain->users at this point.
117 *
118 * (1) Reader starts SRCU section upon execve().
119 * (2) Reader traverses tomoyo_domain_list and finds this domain.
120 * (3) Writer marks this domain as deleted.
121 * (4) Garbage collector removes this domain from tomoyo_domain_list
122 * because this domain is marked as deleted and used by nobody.
123 * (5) Reader saves reference to this domain into
124 * "struct linux_binprm"->cred->security .
125 * (6) Reader finishes SRCU section, although execve() operation has
126 * not finished yet.
127 * (7) Garbage collector waits for SRCU synchronization.
128 * (8) Garbage collector kfree() this domain because this domain is
129 * used by nobody.
130 * (9) Reader finishes execve() operation and restores this domain from
131 * "struct linux_binprm"->cred->security.
132 *
133 * By updating domain->users at (5), we can solve this race problem
134 * by rechecking domain->users at (8).
135 */
136 if (atomic_read(&domain->users))
137 return false;
138 list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
139 tomoyo_del_acl(acl);
140 tomoyo_memory_free(acl);
141 }
142 tomoyo_put_name(domain->domainname);
143 return true;
144}
145
146
147static void tomoyo_del_name(const struct tomoyo_name_entry *ptr)
148{
149}
150
151static void tomoyo_collect_entry(void)
152{
153 mutex_lock(&tomoyo_policy_lock);
154 {
155 struct tomoyo_globally_readable_file_entry *ptr;
156 list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list,
157 list) {
158 if (!ptr->is_deleted)
159 continue;
160 if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr))
161 list_del_rcu(&ptr->list);
162 else
163 break;
164 }
165 }
166 {
167 struct tomoyo_pattern_entry *ptr;
168 list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
169 if (!ptr->is_deleted)
170 continue;
171 if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr))
172 list_del_rcu(&ptr->list);
173 else
174 break;
175 }
176 }
177 {
178 struct tomoyo_no_rewrite_entry *ptr;
179 list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
180 if (!ptr->is_deleted)
181 continue;
182 if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr))
183 list_del_rcu(&ptr->list);
184 else
185 break;
186 }
187 }
188 {
189 struct tomoyo_domain_initializer_entry *ptr;
190 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list,
191 list) {
192 if (!ptr->is_deleted)
193 continue;
194 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr))
195 list_del_rcu(&ptr->list);
196 else
197 break;
198 }
199 }
200 {
201 struct tomoyo_domain_keeper_entry *ptr;
202 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
203 if (!ptr->is_deleted)
204 continue;
205 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr))
206 list_del_rcu(&ptr->list);
207 else
208 break;
209 }
210 }
211 {
212 struct tomoyo_alias_entry *ptr;
213 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
214 if (!ptr->is_deleted)
215 continue;
216 if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr))
217 list_del_rcu(&ptr->list);
218 else
219 break;
220 }
221 }
222 {
223 struct tomoyo_policy_manager_entry *ptr;
224 list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list,
225 list) {
226 if (!ptr->is_deleted)
227 continue;
228 if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr))
229 list_del_rcu(&ptr->list);
230 else
231 break;
232 }
233 }
234 {
235 struct tomoyo_domain_info *domain;
236 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
237 struct tomoyo_acl_info *acl;
238 list_for_each_entry_rcu(acl, &domain->acl_info_list,
239 list) {
240 switch (acl->type) {
241 case TOMOYO_TYPE_PATH_ACL:
242 if (container_of(acl,
243 struct tomoyo_path_acl,
244 head)->perm ||
245 container_of(acl,
246 struct tomoyo_path_acl,
247 head)->perm_high)
248 continue;
249 break;
250 case TOMOYO_TYPE_PATH2_ACL:
251 if (container_of(acl,
252 struct tomoyo_path2_acl,
253 head)->perm)
254 continue;
255 break;
256 default:
257 continue;
258 }
259 if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl))
260 list_del_rcu(&acl->list);
261 else
262 break;
263 }
264 if (!domain->is_deleted || atomic_read(&domain->users))
265 continue;
266 /*
267 * Nobody is referring this domain. But somebody may
268 * refer this domain after successful execve().
269 * We recheck domain->users after SRCU synchronization.
270 */
271 if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain))
272 list_del_rcu(&domain->list);
273 else
274 break;
275 }
276 }
277 mutex_unlock(&tomoyo_policy_lock);
278 mutex_lock(&tomoyo_name_list_lock);
279 {
280 int i;
281 for (i = 0; i < TOMOYO_MAX_HASH; i++) {
282 struct tomoyo_name_entry *ptr;
283 list_for_each_entry_rcu(ptr, &tomoyo_name_list[i],
284 list) {
285 if (atomic_read(&ptr->users))
286 continue;
287 if (tomoyo_add_to_gc(TOMOYO_ID_NAME, ptr))
288 list_del_rcu(&ptr->list);
289 else {
290 i = TOMOYO_MAX_HASH;
291 break;
292 }
293 }
294 }
295 }
296 mutex_unlock(&tomoyo_name_list_lock);
297}
298
299static void tomoyo_kfree_entry(void)
300{
301 struct tomoyo_gc_entry *p;
302 struct tomoyo_gc_entry *tmp;
303
304 list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) {
305 switch (p->type) {
306 case TOMOYO_ID_DOMAIN_INITIALIZER:
307 tomoyo_del_domain_initializer(p->element);
308 break;
309 case TOMOYO_ID_DOMAIN_KEEPER:
310 tomoyo_del_domain_keeper(p->element);
311 break;
312 case TOMOYO_ID_ALIAS:
313 tomoyo_del_alias(p->element);
314 break;
315 case TOMOYO_ID_GLOBALLY_READABLE:
316 tomoyo_del_allow_read(p->element);
317 break;
318 case TOMOYO_ID_PATTERN:
319 tomoyo_del_file_pattern(p->element);
320 break;
321 case TOMOYO_ID_NO_REWRITE:
322 tomoyo_del_no_rewrite(p->element);
323 break;
324 case TOMOYO_ID_MANAGER:
325 tomoyo_del_manager(p->element);
326 break;
327 case TOMOYO_ID_NAME:
328 tomoyo_del_name(p->element);
329 break;
330 case TOMOYO_ID_ACL:
331 tomoyo_del_acl(p->element);
332 break;
333 case TOMOYO_ID_DOMAIN:
334 if (!tomoyo_del_domain(p->element))
335 continue;
336 break;
337 default:
338 printk(KERN_WARNING "Unknown type\n");
339 break;
340 }
341 tomoyo_memory_free(p->element);
342 list_del(&p->list);
343 kfree(p);
344 }
345}
346
347static int tomoyo_gc_thread(void *unused)
348{
349 daemonize("GC for TOMOYO");
350 if (mutex_trylock(&tomoyo_gc_mutex)) {
351 int i;
352 for (i = 0; i < 10; i++) {
353 tomoyo_collect_entry();
354 if (list_empty(&tomoyo_gc_queue))
355 break;
356 synchronize_srcu(&tomoyo_ss);
357 tomoyo_kfree_entry();
358 }
359 mutex_unlock(&tomoyo_gc_mutex);
360 }
361 do_exit(0);
362}
363
364void tomoyo_run_gc(void)
365{
366 struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL,
367 "GC for TOMOYO");
368 if (!IS_ERR(task))
369 wake_up_process(task);
370}
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index 18369d497eb8..c00df45c7ede 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -14,9 +14,8 @@
14#include <linux/mnt_namespace.h> 14#include <linux/mnt_namespace.h>
15#include <linux/fs_struct.h> 15#include <linux/fs_struct.h>
16#include <linux/hash.h> 16#include <linux/hash.h>
17 17#include <linux/magic.h>
18#include "common.h" 18#include "common.h"
19#include "realpath.h"
20 19
21/** 20/**
22 * tomoyo_encode: Convert binary string to ascii string. 21 * tomoyo_encode: Convert binary string to ascii string.
@@ -112,7 +111,7 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname,
112 path_put(&ns_root); 111 path_put(&ns_root);
113 /* Prepend "/proc" prefix if using internal proc vfs mount. */ 112 /* Prepend "/proc" prefix if using internal proc vfs mount. */
114 if (!IS_ERR(sp) && (path->mnt->mnt_parent == path->mnt) && 113 if (!IS_ERR(sp) && (path->mnt->mnt_parent == path->mnt) &&
115 (strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0)) { 114 (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
116 sp -= 5; 115 sp -= 5;
117 if (sp >= newname) 116 if (sp >= newname)
118 memcpy(sp, "/proc", 5); 117 memcpy(sp, "/proc", 5);
@@ -149,12 +148,12 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname,
149 * 148 *
150 * Returns the realpath of the given @path on success, NULL otherwise. 149 * Returns the realpath of the given @path on success, NULL otherwise.
151 * 150 *
152 * These functions use tomoyo_alloc(), so the caller must call tomoyo_free() 151 * These functions use kzalloc(), so the caller must call kfree()
153 * if these functions didn't return NULL. 152 * if these functions didn't return NULL.
154 */ 153 */
155char *tomoyo_realpath_from_path(struct path *path) 154char *tomoyo_realpath_from_path(struct path *path)
156{ 155{
157 char *buf = tomoyo_alloc(sizeof(struct tomoyo_page_buffer)); 156 char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_KERNEL);
158 157
159 BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer) 158 BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer)
160 <= TOMOYO_MAX_PATHNAME_LEN - 1); 159 <= TOMOYO_MAX_PATHNAME_LEN - 1);
@@ -163,7 +162,7 @@ char *tomoyo_realpath_from_path(struct path *path)
163 if (tomoyo_realpath_from_path2(path, buf, 162 if (tomoyo_realpath_from_path2(path, buf,
164 TOMOYO_MAX_PATHNAME_LEN - 1) == 0) 163 TOMOYO_MAX_PATHNAME_LEN - 1) == 0)
165 return buf; 164 return buf;
166 tomoyo_free(buf); 165 kfree(buf);
167 return NULL; 166 return NULL;
168} 167}
169 168
@@ -206,98 +205,47 @@ char *tomoyo_realpath_nofollow(const char *pathname)
206} 205}
207 206
208/* Memory allocated for non-string data. */ 207/* Memory allocated for non-string data. */
209static unsigned int tomoyo_allocated_memory_for_elements; 208static atomic_t tomoyo_policy_memory_size;
210/* Quota for holding non-string data. */ 209/* Quota for holding policy. */
211static unsigned int tomoyo_quota_for_elements; 210static unsigned int tomoyo_quota_for_policy;
212 211
213/** 212/**
214 * tomoyo_alloc_element - Allocate permanent memory for structures. 213 * tomoyo_memory_ok - Check memory quota.
215 * 214 *
216 * @size: Size in bytes. 215 * @ptr: Pointer to allocated memory.
217 * 216 *
218 * Returns pointer to allocated memory on success, NULL otherwise. 217 * Returns true on success, false otherwise.
219 * 218 *
220 * Memory has to be zeroed. 219 * Caller holds tomoyo_policy_lock.
221 * The RAM is chunked, so NEVER try to kfree() the returned pointer. 220 * Memory pointed by @ptr will be zeroed on success.
222 */ 221 */
223void *tomoyo_alloc_element(const unsigned int size) 222bool tomoyo_memory_ok(void *ptr)
224{ 223{
225 static char *buf; 224 int allocated_len = ptr ? ksize(ptr) : 0;
226 static DEFINE_MUTEX(lock); 225 atomic_add(allocated_len, &tomoyo_policy_memory_size);
227 static unsigned int buf_used_len = PATH_MAX; 226 if (ptr && (!tomoyo_quota_for_policy ||
228 char *ptr = NULL; 227 atomic_read(&tomoyo_policy_memory_size)
229 /*Assumes sizeof(void *) >= sizeof(long) is true. */ 228 <= tomoyo_quota_for_policy)) {
230 const unsigned int word_aligned_size 229 memset(ptr, 0, allocated_len);
231 = roundup(size, max(sizeof(void *), sizeof(long))); 230 return true;
232 if (word_aligned_size > PATH_MAX)
233 return NULL;
234 mutex_lock(&lock);
235 if (buf_used_len + word_aligned_size > PATH_MAX) {
236 if (!tomoyo_quota_for_elements ||
237 tomoyo_allocated_memory_for_elements
238 + PATH_MAX <= tomoyo_quota_for_elements)
239 ptr = kzalloc(PATH_MAX, GFP_KERNEL);
240 if (!ptr) {
241 printk(KERN_WARNING "ERROR: Out of memory "
242 "for tomoyo_alloc_element().\n");
243 if (!tomoyo_policy_loaded)
244 panic("MAC Initialization failed.\n");
245 } else {
246 buf = ptr;
247 tomoyo_allocated_memory_for_elements += PATH_MAX;
248 buf_used_len = word_aligned_size;
249 ptr = buf;
250 }
251 } else if (word_aligned_size) {
252 int i;
253 ptr = buf + buf_used_len;
254 buf_used_len += word_aligned_size;
255 for (i = 0; i < word_aligned_size; i++) {
256 if (!ptr[i])
257 continue;
258 printk(KERN_ERR "WARNING: Reserved memory was tainted! "
259 "The system might go wrong.\n");
260 ptr[i] = '\0';
261 }
262 } 231 }
263 mutex_unlock(&lock); 232 printk(KERN_WARNING "ERROR: Out of memory "
264 return ptr; 233 "for tomoyo_alloc_element().\n");
234 if (!tomoyo_policy_loaded)
235 panic("MAC Initialization failed.\n");
236 return false;
265} 237}
266 238
267/* Memory allocated for string data in bytes. */ 239/**
268static unsigned int tomoyo_allocated_memory_for_savename; 240 * tomoyo_memory_free - Free memory for elements.
269/* Quota for holding string data in bytes. */
270static unsigned int tomoyo_quota_for_savename;
271
272/*
273 * TOMOYO uses this hash only when appending a string into the string
274 * table. Frequency of appending strings is very low. So we don't need
275 * large (e.g. 64k) hash size. 256 will be sufficient.
276 */
277#define TOMOYO_HASH_BITS 8
278#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS)
279
280/*
281 * tomoyo_name_entry is a structure which is used for linking
282 * "struct tomoyo_path_info" into tomoyo_name_list .
283 * 241 *
284 * Since tomoyo_name_list manages a list of strings which are shared by 242 * @ptr: Pointer to allocated memory.
285 * multiple processes (whereas "struct tomoyo_path_info" inside
286 * "struct tomoyo_path_info_with_data" is not shared), a reference counter will
287 * be added to "struct tomoyo_name_entry" rather than "struct tomoyo_path_info"
288 * when TOMOYO starts supporting garbage collector.
289 */ 243 */
290struct tomoyo_name_entry { 244void tomoyo_memory_free(void *ptr)
291 struct list_head list; 245{
292 struct tomoyo_path_info entry; 246 atomic_sub(ksize(ptr), &tomoyo_policy_memory_size);
293}; 247 kfree(ptr);
294 248}
295/* Structure for available memory region. */
296struct tomoyo_free_memory_block_list {
297 struct list_head list;
298 char *ptr; /* Pointer to a free area. */
299 int len; /* Length of the area. */
300};
301 249
302/* 250/*
303 * tomoyo_name_list is used for holding string data used by TOMOYO. 251 * tomoyo_name_list is used for holding string data used by TOMOYO.
@@ -305,87 +253,58 @@ struct tomoyo_free_memory_block_list {
305 * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of 253 * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of
306 * "const struct tomoyo_path_info *". 254 * "const struct tomoyo_path_info *".
307 */ 255 */
308static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; 256struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
257/* Lock for protecting tomoyo_name_list . */
258DEFINE_MUTEX(tomoyo_name_list_lock);
309 259
310/** 260/**
311 * tomoyo_save_name - Allocate permanent memory for string data. 261 * tomoyo_get_name - Allocate permanent memory for string data.
312 * 262 *
313 * @name: The string to store into the permernent memory. 263 * @name: The string to store into the permernent memory.
314 * 264 *
315 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. 265 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
316 *
317 * The RAM is shared, so NEVER try to modify or kfree() the returned name.
318 */ 266 */
319const struct tomoyo_path_info *tomoyo_save_name(const char *name) 267const struct tomoyo_path_info *tomoyo_get_name(const char *name)
320{ 268{
321 static LIST_HEAD(fmb_list);
322 static DEFINE_MUTEX(lock);
323 struct tomoyo_name_entry *ptr; 269 struct tomoyo_name_entry *ptr;
324 unsigned int hash; 270 unsigned int hash;
325 /* fmb contains available size in bytes.
326 fmb is removed from the fmb_list when fmb->len becomes 0. */
327 struct tomoyo_free_memory_block_list *fmb;
328 int len; 271 int len;
329 char *cp; 272 int allocated_len;
330 struct list_head *head; 273 struct list_head *head;
331 274
332 if (!name) 275 if (!name)
333 return NULL; 276 return NULL;
334 len = strlen(name) + 1; 277 len = strlen(name) + 1;
335 if (len > TOMOYO_MAX_PATHNAME_LEN) {
336 printk(KERN_WARNING "ERROR: Name too long "
337 "for tomoyo_save_name().\n");
338 return NULL;
339 }
340 hash = full_name_hash((const unsigned char *) name, len - 1); 278 hash = full_name_hash((const unsigned char *) name, len - 1);
341 head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; 279 head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
342 280 mutex_lock(&tomoyo_name_list_lock);
343 mutex_lock(&lock);
344 list_for_each_entry(ptr, head, list) { 281 list_for_each_entry(ptr, head, list) {
345 if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name)) 282 if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
346 goto out; 283 continue;
347 } 284 atomic_inc(&ptr->users);
348 list_for_each_entry(fmb, &fmb_list, list) { 285 goto out;
349 if (len <= fmb->len)
350 goto ready;
351 } 286 }
352 if (!tomoyo_quota_for_savename || 287 ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL);
353 tomoyo_allocated_memory_for_savename + PATH_MAX 288 allocated_len = ptr ? ksize(ptr) : 0;
354 <= tomoyo_quota_for_savename) 289 if (!ptr || (tomoyo_quota_for_policy &&
355 cp = kzalloc(PATH_MAX, GFP_KERNEL); 290 atomic_read(&tomoyo_policy_memory_size) + allocated_len
356 else 291 > tomoyo_quota_for_policy)) {
357 cp = NULL; 292 kfree(ptr);
358 fmb = kzalloc(sizeof(*fmb), GFP_KERNEL);
359 if (!cp || !fmb) {
360 kfree(cp);
361 kfree(fmb);
362 printk(KERN_WARNING "ERROR: Out of memory " 293 printk(KERN_WARNING "ERROR: Out of memory "
363 "for tomoyo_save_name().\n"); 294 "for tomoyo_get_name().\n");
364 if (!tomoyo_policy_loaded) 295 if (!tomoyo_policy_loaded)
365 panic("MAC Initialization failed.\n"); 296 panic("MAC Initialization failed.\n");
366 ptr = NULL; 297 ptr = NULL;
367 goto out; 298 goto out;
368 } 299 }
369 tomoyo_allocated_memory_for_savename += PATH_MAX; 300 atomic_add(allocated_len, &tomoyo_policy_memory_size);
370 list_add(&fmb->list, &fmb_list); 301 ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
371 fmb->ptr = cp; 302 memmove((char *) ptr->entry.name, name, len);
372 fmb->len = PATH_MAX; 303 atomic_set(&ptr->users, 1);
373 ready:
374 ptr = tomoyo_alloc_element(sizeof(*ptr));
375 if (!ptr)
376 goto out;
377 ptr->entry.name = fmb->ptr;
378 memmove(fmb->ptr, name, len);
379 tomoyo_fill_path_info(&ptr->entry); 304 tomoyo_fill_path_info(&ptr->entry);
380 fmb->ptr += len;
381 fmb->len -= len;
382 list_add_tail(&ptr->list, head); 305 list_add_tail(&ptr->list, head);
383 if (fmb->len == 0) {
384 list_del(&fmb->list);
385 kfree(fmb);
386 }
387 out: 306 out:
388 mutex_unlock(&lock); 307 mutex_unlock(&tomoyo_name_list_lock);
389 return ptr ? &ptr->entry : NULL; 308 return ptr ? &ptr->entry : NULL;
390} 309}
391 310
@@ -400,45 +319,14 @@ void __init tomoyo_realpath_init(void)
400 for (i = 0; i < TOMOYO_MAX_HASH; i++) 319 for (i = 0; i < TOMOYO_MAX_HASH; i++)
401 INIT_LIST_HEAD(&tomoyo_name_list[i]); 320 INIT_LIST_HEAD(&tomoyo_name_list[i]);
402 INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); 321 INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
403 tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME); 322 tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME);
404 list_add_tail(&tomoyo_kernel_domain.list, &tomoyo_domain_list); 323 /*
405 down_read(&tomoyo_domain_list_lock); 324 * tomoyo_read_lock() is not needed because this function is
325 * called before the first "delete" request.
326 */
327 list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
406 if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) 328 if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
407 panic("Can't register tomoyo_kernel_domain"); 329 panic("Can't register tomoyo_kernel_domain");
408 up_read(&tomoyo_domain_list_lock);
409}
410
411/* Memory allocated for temporary purpose. */
412static atomic_t tomoyo_dynamic_memory_size;
413
414/**
415 * tomoyo_alloc - Allocate memory for temporary purpose.
416 *
417 * @size: Size in bytes.
418 *
419 * Returns pointer to allocated memory on success, NULL otherwise.
420 */
421void *tomoyo_alloc(const size_t size)
422{
423 void *p = kzalloc(size, GFP_KERNEL);
424 if (p)
425 atomic_add(ksize(p), &tomoyo_dynamic_memory_size);
426 return p;
427}
428
429/**
430 * tomoyo_free - Release memory allocated by tomoyo_alloc().
431 *
432 * @p: Pointer returned by tomoyo_alloc(). May be NULL.
433 *
434 * Returns nothing.
435 */
436void tomoyo_free(const void *p)
437{
438 if (p) {
439 atomic_sub(ksize(p), &tomoyo_dynamic_memory_size);
440 kfree(p);
441 }
442} 330}
443 331
444/** 332/**
@@ -451,32 +339,19 @@ void tomoyo_free(const void *p)
451int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) 339int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
452{ 340{
453 if (!head->read_eof) { 341 if (!head->read_eof) {
454 const unsigned int shared 342 const unsigned int policy
455 = tomoyo_allocated_memory_for_savename; 343 = atomic_read(&tomoyo_policy_memory_size);
456 const unsigned int private
457 = tomoyo_allocated_memory_for_elements;
458 const unsigned int dynamic
459 = atomic_read(&tomoyo_dynamic_memory_size);
460 char buffer[64]; 344 char buffer[64];
461 345
462 memset(buffer, 0, sizeof(buffer)); 346 memset(buffer, 0, sizeof(buffer));
463 if (tomoyo_quota_for_savename) 347 if (tomoyo_quota_for_policy)
464 snprintf(buffer, sizeof(buffer) - 1,
465 " (Quota: %10u)",
466 tomoyo_quota_for_savename);
467 else
468 buffer[0] = '\0';
469 tomoyo_io_printf(head, "Shared: %10u%s\n", shared, buffer);
470 if (tomoyo_quota_for_elements)
471 snprintf(buffer, sizeof(buffer) - 1, 348 snprintf(buffer, sizeof(buffer) - 1,
472 " (Quota: %10u)", 349 " (Quota: %10u)",
473 tomoyo_quota_for_elements); 350 tomoyo_quota_for_policy);
474 else 351 else
475 buffer[0] = '\0'; 352 buffer[0] = '\0';
476 tomoyo_io_printf(head, "Private: %10u%s\n", private, buffer); 353 tomoyo_io_printf(head, "Policy: %10u%s\n", policy, buffer);
477 tomoyo_io_printf(head, "Dynamic: %10u\n", dynamic); 354 tomoyo_io_printf(head, "Total: %10u\n", policy);
478 tomoyo_io_printf(head, "Total: %10u\n",
479 shared + private + dynamic);
480 head->read_eof = true; 355 head->read_eof = true;
481 } 356 }
482 return 0; 357 return 0;
@@ -494,9 +369,7 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
494 char *data = head->write_buf; 369 char *data = head->write_buf;
495 unsigned int size; 370 unsigned int size;
496 371
497 if (sscanf(data, "Shared: %u", &size) == 1) 372 if (sscanf(data, "Policy: %u", &size) == 1)
498 tomoyo_quota_for_savename = size; 373 tomoyo_quota_for_policy = size;
499 else if (sscanf(data, "Private: %u", &size) == 1)
500 tomoyo_quota_for_elements = size;
501 return 0; 374 return 0;
502} 375}
diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h
deleted file mode 100644
index 78217a37960b..000000000000
--- a/security/tomoyo/realpath.h
+++ /dev/null
@@ -1,66 +0,0 @@
1/*
2 * security/tomoyo/realpath.h
3 *
4 * Get the canonicalized absolute pathnames. The basis for TOMOYO.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0 2009/04/01
9 *
10 */
11
12#ifndef _SECURITY_TOMOYO_REALPATH_H
13#define _SECURITY_TOMOYO_REALPATH_H
14
15struct path;
16struct tomoyo_path_info;
17struct tomoyo_io_buffer;
18
19/* Convert binary string to ascii string. */
20int tomoyo_encode(char *buffer, int buflen, const char *str);
21
22/* Returns realpath(3) of the given pathname but ignores chroot'ed root. */
23int tomoyo_realpath_from_path2(struct path *path, char *newname,
24 int newname_len);
25
26/*
27 * Returns realpath(3) of the given pathname but ignores chroot'ed root.
28 * These functions use tomoyo_alloc(), so the caller must call tomoyo_free()
29 * if these functions didn't return NULL.
30 */
31char *tomoyo_realpath(const char *pathname);
32/*
33 * Same with tomoyo_realpath() except that it doesn't follow the final symlink.
34 */
35char *tomoyo_realpath_nofollow(const char *pathname);
36/* Same with tomoyo_realpath() except that the pathname is already solved. */
37char *tomoyo_realpath_from_path(struct path *path);
38
39/*
40 * Allocate memory for ACL entry.
41 * The RAM is chunked, so NEVER try to kfree() the returned pointer.
42 */
43void *tomoyo_alloc_element(const unsigned int size);
44
45/*
46 * Keep the given name on the RAM.
47 * The RAM is shared, so NEVER try to modify or kfree() the returned name.
48 */
49const struct tomoyo_path_info *tomoyo_save_name(const char *name);
50
51/* Allocate memory for temporary use (e.g. permission checks). */
52void *tomoyo_alloc(const size_t size);
53
54/* Free memory allocated by tomoyo_alloc(). */
55void tomoyo_free(const void *p);
56
57/* Check for memory usage. */
58int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head);
59
60/* Set memory quota. */
61int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head);
62
63/* Initialize realpath related code. */
64void __init tomoyo_realpath_init(void);
65
66#endif /* !defined(_SECURITY_TOMOYO_REALPATH_H) */
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index 2aceebf5f354..dedd97d0c163 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -11,8 +11,6 @@
11 11
12#include <linux/security.h> 12#include <linux/security.h>
13#include "common.h" 13#include "common.h"
14#include "tomoyo.h"
15#include "realpath.h"
16 14
17static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) 15static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp)
18{ 16{
@@ -23,21 +21,23 @@ static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp)
23static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, 21static int tomoyo_cred_prepare(struct cred *new, const struct cred *old,
24 gfp_t gfp) 22 gfp_t gfp)
25{ 23{
26 /* 24 struct tomoyo_domain_info *domain = old->security;
27 * Since "struct tomoyo_domain_info *" is a sharable pointer, 25 new->security = domain;
28 * we don't need to duplicate. 26 if (domain)
29 */ 27 atomic_inc(&domain->users);
30 new->security = old->security;
31 return 0; 28 return 0;
32} 29}
33 30
34static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) 31static void tomoyo_cred_transfer(struct cred *new, const struct cred *old)
35{ 32{
36 /* 33 tomoyo_cred_prepare(new, old, 0);
37 * Since "struct tomoyo_domain_info *" is a sharable pointer, 34}
38 * we don't need to duplicate. 35
39 */ 36static void tomoyo_cred_free(struct cred *cred)
40 new->security = old->security; 37{
38 struct tomoyo_domain_info *domain = cred->security;
39 if (domain)
40 atomic_dec(&domain->users);
41} 41}
42 42
43static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) 43static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
@@ -61,6 +61,14 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
61 if (!tomoyo_policy_loaded) 61 if (!tomoyo_policy_loaded)
62 tomoyo_load_policy(bprm->filename); 62 tomoyo_load_policy(bprm->filename);
63 /* 63 /*
64 * Release reference to "struct tomoyo_domain_info" stored inside
65 * "bprm->cred->security". New reference to "struct tomoyo_domain_info"
66 * stored inside "bprm->cred->security" will be acquired later inside
67 * tomoyo_find_next_domain().
68 */
69 atomic_dec(&((struct tomoyo_domain_info *)
70 bprm->cred->security)->users);
71 /*
64 * Tell tomoyo_bprm_check_security() is called for the first time of an 72 * Tell tomoyo_bprm_check_security() is called for the first time of an
65 * execve operation. 73 * execve operation.
66 */ 74 */
@@ -76,8 +84,12 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
76 * Execute permission is checked against pathname passed to do_execve() 84 * Execute permission is checked against pathname passed to do_execve()
77 * using current domain. 85 * using current domain.
78 */ 86 */
79 if (!domain) 87 if (!domain) {
80 return tomoyo_find_next_domain(bprm); 88 const int idx = tomoyo_read_lock();
89 const int err = tomoyo_find_next_domain(bprm);
90 tomoyo_read_unlock(idx);
91 return err;
92 }
81 /* 93 /*
82 * Read permission is checked against interpreters using next domain. 94 * Read permission is checked against interpreters using next domain.
83 */ 95 */
@@ -87,67 +99,56 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
87static int tomoyo_path_truncate(struct path *path, loff_t length, 99static int tomoyo_path_truncate(struct path *path, loff_t length,
88 unsigned int time_attrs) 100 unsigned int time_attrs)
89{ 101{
90 return tomoyo_check_1path_perm(tomoyo_domain(), 102 return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path);
91 TOMOYO_TYPE_TRUNCATE_ACL,
92 path);
93} 103}
94 104
95static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) 105static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry)
96{ 106{
97 struct path path = { parent->mnt, dentry }; 107 struct path path = { parent->mnt, dentry };
98 return tomoyo_check_1path_perm(tomoyo_domain(), 108 return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path);
99 TOMOYO_TYPE_UNLINK_ACL,
100 &path);
101} 109}
102 110
103static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, 111static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
104 int mode) 112 int mode)
105{ 113{
106 struct path path = { parent->mnt, dentry }; 114 struct path path = { parent->mnt, dentry };
107 return tomoyo_check_1path_perm(tomoyo_domain(), 115 return tomoyo_path_perm(TOMOYO_TYPE_MKDIR, &path);
108 TOMOYO_TYPE_MKDIR_ACL,
109 &path);
110} 116}
111 117
112static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) 118static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry)
113{ 119{
114 struct path path = { parent->mnt, dentry }; 120 struct path path = { parent->mnt, dentry };
115 return tomoyo_check_1path_perm(tomoyo_domain(), 121 return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path);
116 TOMOYO_TYPE_RMDIR_ACL,
117 &path);
118} 122}
119 123
120static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, 124static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry,
121 const char *old_name) 125 const char *old_name)
122{ 126{
123 struct path path = { parent->mnt, dentry }; 127 struct path path = { parent->mnt, dentry };
124 return tomoyo_check_1path_perm(tomoyo_domain(), 128 return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path);
125 TOMOYO_TYPE_SYMLINK_ACL,
126 &path);
127} 129}
128 130
129static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, 131static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
130 int mode, unsigned int dev) 132 int mode, unsigned int dev)
131{ 133{
132 struct path path = { parent->mnt, dentry }; 134 struct path path = { parent->mnt, dentry };
133 int type = TOMOYO_TYPE_CREATE_ACL; 135 int type = TOMOYO_TYPE_CREATE;
134 136
135 switch (mode & S_IFMT) { 137 switch (mode & S_IFMT) {
136 case S_IFCHR: 138 case S_IFCHR:
137 type = TOMOYO_TYPE_MKCHAR_ACL; 139 type = TOMOYO_TYPE_MKCHAR;
138 break; 140 break;
139 case S_IFBLK: 141 case S_IFBLK:
140 type = TOMOYO_TYPE_MKBLOCK_ACL; 142 type = TOMOYO_TYPE_MKBLOCK;
141 break; 143 break;
142 case S_IFIFO: 144 case S_IFIFO:
143 type = TOMOYO_TYPE_MKFIFO_ACL; 145 type = TOMOYO_TYPE_MKFIFO;
144 break; 146 break;
145 case S_IFSOCK: 147 case S_IFSOCK:
146 type = TOMOYO_TYPE_MKSOCK_ACL; 148 type = TOMOYO_TYPE_MKSOCK;
147 break; 149 break;
148 } 150 }
149 return tomoyo_check_1path_perm(tomoyo_domain(), 151 return tomoyo_path_perm(type, &path);
150 type, &path);
151} 152}
152 153
153static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, 154static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir,
@@ -155,9 +156,7 @@ static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir,
155{ 156{
156 struct path path1 = { new_dir->mnt, old_dentry }; 157 struct path path1 = { new_dir->mnt, old_dentry };
157 struct path path2 = { new_dir->mnt, new_dentry }; 158 struct path path2 = { new_dir->mnt, new_dentry };
158 return tomoyo_check_2path_perm(tomoyo_domain(), 159 return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2);
159 TOMOYO_TYPE_LINK_ACL,
160 &path1, &path2);
161} 160}
162 161
163static int tomoyo_path_rename(struct path *old_parent, 162static int tomoyo_path_rename(struct path *old_parent,
@@ -167,16 +166,14 @@ static int tomoyo_path_rename(struct path *old_parent,
167{ 166{
168 struct path path1 = { old_parent->mnt, old_dentry }; 167 struct path path1 = { old_parent->mnt, old_dentry };
169 struct path path2 = { new_parent->mnt, new_dentry }; 168 struct path path2 = { new_parent->mnt, new_dentry };
170 return tomoyo_check_2path_perm(tomoyo_domain(), 169 return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2);
171 TOMOYO_TYPE_RENAME_ACL,
172 &path1, &path2);
173} 170}
174 171
175static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, 172static int tomoyo_file_fcntl(struct file *file, unsigned int cmd,
176 unsigned long arg) 173 unsigned long arg)
177{ 174{
178 if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) 175 if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))
179 return tomoyo_check_rewrite_permission(tomoyo_domain(), file); 176 return tomoyo_check_rewrite_permission(file);
180 return 0; 177 return 0;
181} 178}
182 179
@@ -189,6 +186,51 @@ static int tomoyo_dentry_open(struct file *f, const struct cred *cred)
189 return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); 186 return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags);
190} 187}
191 188
189static int tomoyo_file_ioctl(struct file *file, unsigned int cmd,
190 unsigned long arg)
191{
192 return tomoyo_path_perm(TOMOYO_TYPE_IOCTL, &file->f_path);
193}
194
195static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
196 mode_t mode)
197{
198 struct path path = { mnt, dentry };
199 return tomoyo_path_perm(TOMOYO_TYPE_CHMOD, &path);
200}
201
202static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid)
203{
204 int error = 0;
205 if (uid != (uid_t) -1)
206 error = tomoyo_path_perm(TOMOYO_TYPE_CHOWN, path);
207 if (!error && gid != (gid_t) -1)
208 error = tomoyo_path_perm(TOMOYO_TYPE_CHGRP, path);
209 return error;
210}
211
212static int tomoyo_path_chroot(struct path *path)
213{
214 return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path);
215}
216
217static int tomoyo_sb_mount(char *dev_name, struct path *path,
218 char *type, unsigned long flags, void *data)
219{
220 return tomoyo_path_perm(TOMOYO_TYPE_MOUNT, path);
221}
222
223static int tomoyo_sb_umount(struct vfsmount *mnt, int flags)
224{
225 struct path path = { mnt, mnt->mnt_root };
226 return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path);
227}
228
229static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path)
230{
231 return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path);
232}
233
192/* 234/*
193 * tomoyo_security_ops is a "struct security_operations" which is used for 235 * tomoyo_security_ops is a "struct security_operations" which is used for
194 * registering TOMOYO. 236 * registering TOMOYO.
@@ -198,6 +240,7 @@ static struct security_operations tomoyo_security_ops = {
198 .cred_alloc_blank = tomoyo_cred_alloc_blank, 240 .cred_alloc_blank = tomoyo_cred_alloc_blank,
199 .cred_prepare = tomoyo_cred_prepare, 241 .cred_prepare = tomoyo_cred_prepare,
200 .cred_transfer = tomoyo_cred_transfer, 242 .cred_transfer = tomoyo_cred_transfer,
243 .cred_free = tomoyo_cred_free,
201 .bprm_set_creds = tomoyo_bprm_set_creds, 244 .bprm_set_creds = tomoyo_bprm_set_creds,
202 .bprm_check_security = tomoyo_bprm_check_security, 245 .bprm_check_security = tomoyo_bprm_check_security,
203 .file_fcntl = tomoyo_file_fcntl, 246 .file_fcntl = tomoyo_file_fcntl,
@@ -210,8 +253,18 @@ static struct security_operations tomoyo_security_ops = {
210 .path_mknod = tomoyo_path_mknod, 253 .path_mknod = tomoyo_path_mknod,
211 .path_link = tomoyo_path_link, 254 .path_link = tomoyo_path_link,
212 .path_rename = tomoyo_path_rename, 255 .path_rename = tomoyo_path_rename,
256 .file_ioctl = tomoyo_file_ioctl,
257 .path_chmod = tomoyo_path_chmod,
258 .path_chown = tomoyo_path_chown,
259 .path_chroot = tomoyo_path_chroot,
260 .sb_mount = tomoyo_sb_mount,
261 .sb_umount = tomoyo_sb_umount,
262 .sb_pivotroot = tomoyo_sb_pivotroot,
213}; 263};
214 264
265/* Lock for GC. */
266struct srcu_struct tomoyo_ss;
267
215static int __init tomoyo_init(void) 268static int __init tomoyo_init(void)
216{ 269{
217 struct cred *cred = (struct cred *) current_cred(); 270 struct cred *cred = (struct cred *) current_cred();
@@ -219,7 +272,8 @@ static int __init tomoyo_init(void)
219 if (!security_module_enable(&tomoyo_security_ops)) 272 if (!security_module_enable(&tomoyo_security_ops))
220 return 0; 273 return 0;
221 /* register ourselves with the security framework */ 274 /* register ourselves with the security framework */
222 if (register_security(&tomoyo_security_ops)) 275 if (register_security(&tomoyo_security_ops) ||
276 init_srcu_struct(&tomoyo_ss))
223 panic("Failure registering TOMOYO Linux"); 277 panic("Failure registering TOMOYO Linux");
224 printk(KERN_INFO "TOMOYO Linux initialized\n"); 278 printk(KERN_INFO "TOMOYO Linux initialized\n");
225 cred->security = &tomoyo_kernel_domain; 279 cred->security = &tomoyo_kernel_domain;
diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h
deleted file mode 100644
index ed758325b1ae..000000000000
--- a/security/tomoyo/tomoyo.h
+++ /dev/null
@@ -1,94 +0,0 @@
1/*
2 * security/tomoyo/tomoyo.h
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 2.2.0 2009/04/01
9 *
10 */
11
12#ifndef _SECURITY_TOMOYO_TOMOYO_H
13#define _SECURITY_TOMOYO_TOMOYO_H
14
15struct tomoyo_path_info;
16struct path;
17struct inode;
18struct linux_binprm;
19struct pt_regs;
20
21int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
22 const struct tomoyo_path_info *filename);
23int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
24 struct path *path, const int flag);
25int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
26 const u8 operation, struct path *path);
27int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain,
28 const u8 operation, struct path *path1,
29 struct path *path2);
30int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
31 struct file *filp);
32int tomoyo_find_next_domain(struct linux_binprm *bprm);
33
34/* Index numbers for Access Controls. */
35
36#define TOMOYO_TYPE_SINGLE_PATH_ACL 0
37#define TOMOYO_TYPE_DOUBLE_PATH_ACL 1
38
39/* Index numbers for File Controls. */
40
41/*
42 * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set
43 * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and
44 * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set.
45 * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or
46 * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are
47 * automatically cleared if TYPE_READ_WRITE_ACL is cleared.
48 */
49
50#define TOMOYO_TYPE_READ_WRITE_ACL 0
51#define TOMOYO_TYPE_EXECUTE_ACL 1
52#define TOMOYO_TYPE_READ_ACL 2
53#define TOMOYO_TYPE_WRITE_ACL 3
54#define TOMOYO_TYPE_CREATE_ACL 4
55#define TOMOYO_TYPE_UNLINK_ACL 5
56#define TOMOYO_TYPE_MKDIR_ACL 6
57#define TOMOYO_TYPE_RMDIR_ACL 7
58#define TOMOYO_TYPE_MKFIFO_ACL 8
59#define TOMOYO_TYPE_MKSOCK_ACL 9
60#define TOMOYO_TYPE_MKBLOCK_ACL 10
61#define TOMOYO_TYPE_MKCHAR_ACL 11
62#define TOMOYO_TYPE_TRUNCATE_ACL 12
63#define TOMOYO_TYPE_SYMLINK_ACL 13
64#define TOMOYO_TYPE_REWRITE_ACL 14
65#define TOMOYO_MAX_SINGLE_PATH_OPERATION 15
66
67#define TOMOYO_TYPE_LINK_ACL 0
68#define TOMOYO_TYPE_RENAME_ACL 1
69#define TOMOYO_MAX_DOUBLE_PATH_OPERATION 2
70
71#define TOMOYO_DOMAINPOLICY 0
72#define TOMOYO_EXCEPTIONPOLICY 1
73#define TOMOYO_DOMAIN_STATUS 2
74#define TOMOYO_PROCESS_STATUS 3
75#define TOMOYO_MEMINFO 4
76#define TOMOYO_SELFDOMAIN 5
77#define TOMOYO_VERSION 6
78#define TOMOYO_PROFILE 7
79#define TOMOYO_MANAGER 8
80
81extern struct tomoyo_domain_info tomoyo_kernel_domain;
82
83static inline struct tomoyo_domain_info *tomoyo_domain(void)
84{
85 return current_cred()->security;
86}
87
88static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
89 *task)
90{
91 return task_cred_xxx(task, security);
92}
93
94#endif /* !defined(_SECURITY_TOMOYO_TOMOYO_H) */