aboutsummaryrefslogtreecommitdiffstats
path: root/security/tomoyo
diff options
context:
space:
mode:
Diffstat (limited to 'security/tomoyo')
-rw-r--r--security/tomoyo/Makefile2
-rw-r--r--security/tomoyo/common.c4
-rw-r--r--security/tomoyo/common.h13
-rw-r--r--security/tomoyo/gc.c36
-rw-r--r--security/tomoyo/group.c130
-rw-r--r--security/tomoyo/memory.c44
-rw-r--r--security/tomoyo/number_group.c126
-rw-r--r--security/tomoyo/path_group.c122
-rw-r--r--security/tomoyo/util.c4
9 files changed, 199 insertions, 282 deletions
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile
index 3aa6f076948e..91640e96bd06 100644
--- a/security/tomoyo/Makefile
+++ b/security/tomoyo/Makefile
@@ -1 +1 @@
obj-y = common.o domain.o file.o gc.o load_policy.o memory.o mount.o number_group.o path_group.o realpath.o securityfs_if.o tomoyo.o util.o obj-y = common.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 044115d49033..183fe6513400 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -1186,9 +1186,9 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
1186 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE)) 1186 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE))
1187 return tomoyo_write_no_rewrite_policy(data, is_delete); 1187 return tomoyo_write_no_rewrite_policy(data, is_delete);
1188 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP)) 1188 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP))
1189 return tomoyo_write_path_group_policy(data, is_delete); 1189 return tomoyo_write_group(data, is_delete, TOMOYO_PATH_GROUP);
1190 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NUMBER_GROUP)) 1190 if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NUMBER_GROUP))
1191 return tomoyo_write_number_group_policy(data, is_delete); 1191 return tomoyo_write_group(data, is_delete, TOMOYO_NUMBER_GROUP);
1192 return -EINVAL; 1192 return -EINVAL;
1193} 1193}
1194 1194
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 21eb1e7885b8..ec3ed488ee30 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -838,12 +838,10 @@ int tomoyo_write_mount_policy(char *data, struct tomoyo_domain_info *domain,
838int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); 838int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete);
839/* Create "file_pattern" entry in exception policy. */ 839/* Create "file_pattern" entry in exception policy. */
840int tomoyo_write_pattern_policy(char *data, const bool is_delete); 840int tomoyo_write_pattern_policy(char *data, const bool is_delete);
841/* Create "path_group" entry in exception policy. */ 841/* Create "path_group"/"number_group" entry in exception policy. */
842int tomoyo_write_path_group_policy(char *data, const bool is_delete); 842int tomoyo_write_group(char *data, const bool is_delete, const u8 type);
843int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) 843int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
844 __attribute__ ((format(printf, 2, 3))); 844 __attribute__ ((format(printf, 2, 3)));
845/* Create "number_group" entry in exception policy. */
846int tomoyo_write_number_group_policy(char *data, const bool is_delete);
847/* Find a domain by the given name. */ 845/* Find a domain by the given name. */
848struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); 846struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
849/* Find or create a domain by the given name. */ 847/* Find or create a domain by the given name. */
@@ -851,9 +849,10 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char *
851 domainname, 849 domainname,
852 const u8 profile); 850 const u8 profile);
853struct tomoyo_profile *tomoyo_profile(const u8 profile); 851struct tomoyo_profile *tomoyo_profile(const u8 profile);
854/* Allocate memory for "struct tomoyo_path_group". */ 852/*
855struct tomoyo_group *tomoyo_get_path_group(const char *group_name); 853 * Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
856struct tomoyo_group *tomoyo_get_number_group(const char *group_name); 854 */
855struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 type);
857 856
858/* Check mode for specified functionality. */ 857/* Check mode for specified functionality. */
859unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, 858unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c
index 414e18bd93c7..cf62a4ee79c2 100644
--- a/security/tomoyo/gc.c
+++ b/security/tomoyo/gc.c
@@ -266,33 +266,25 @@ static void tomoyo_collect_entry(void)
266 goto unlock; 266 goto unlock;
267 } 267 }
268 } 268 }
269 { 269 for (i = 0; i < TOMOYO_MAX_GROUP; i++) {
270 struct list_head *list = &tomoyo_group_list[i];
271 int id;
270 struct tomoyo_group *group; 272 struct tomoyo_group *group;
271 list_for_each_entry_rcu(group, 273 switch (i) {
272 &tomoyo_group_list[TOMOYO_PATH_GROUP], 274 case 0:
273 list) { 275 id = TOMOYO_ID_PATH_GROUP;
274 tomoyo_collect_member(&group->member_list, 276 break;
275 TOMOYO_ID_PATH_GROUP); 277 default:
276 if (!list_empty(&group->member_list) || 278 id = TOMOYO_ID_NUMBER_GROUP;
277 atomic_read(&group->users)) 279 break;
278 continue;
279 if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP,
280 &group->list))
281 goto unlock;
282 } 280 }
283 } 281 list_for_each_entry(group, list, list) {
284 { 282 if (!tomoyo_collect_member(&group->member_list, id))
285 struct tomoyo_group *group; 283 goto unlock;
286 list_for_each_entry_rcu(group,
287 &tomoyo_group_list[TOMOYO_NUMBER_GROUP],
288 list) {
289 tomoyo_collect_member(&group->member_list,
290 TOMOYO_ID_NUMBER_GROUP);
291 if (!list_empty(&group->member_list) || 284 if (!list_empty(&group->member_list) ||
292 atomic_read(&group->users)) 285 atomic_read(&group->users))
293 continue; 286 continue;
294 if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, 287 if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, &group->list))
295 &group->list))
296 goto unlock; 288 goto unlock;
297 } 289 }
298 } 290 }
diff --git a/security/tomoyo/group.c b/security/tomoyo/group.c
new file mode 100644
index 000000000000..3f0a2abf65cc
--- /dev/null
+++ b/security/tomoyo/group.c
@@ -0,0 +1,130 @@
1/*
2 * security/tomoyo/group.c
3 *
4 * Copyright (C) 2005-2010 NTT DATA CORPORATION
5 */
6
7#include <linux/slab.h>
8#include "common.h"
9
10static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a,
11 const struct tomoyo_acl_head *b)
12{
13 return container_of(a, struct tomoyo_path_group, head)->member_name ==
14 container_of(b, struct tomoyo_path_group, head)->member_name;
15}
16
17static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
18 const struct tomoyo_acl_head *b)
19{
20 return !memcmp(&container_of(a, struct tomoyo_number_group, head)
21 ->number,
22 &container_of(b, struct tomoyo_number_group, head)
23 ->number,
24 sizeof(container_of(a, struct tomoyo_number_group, head)
25 ->number));
26}
27
28/**
29 * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list.
30 *
31 * @data: String to parse.
32 * @is_delete: True if it is a delete request.
33 * @type: Type of this group.
34 *
35 * Returns 0 on success, negative value otherwise.
36 */
37int tomoyo_write_group(char *data, const bool is_delete, const u8 type)
38{
39 struct tomoyo_group *group;
40 struct list_head *member;
41 char *w[2];
42 int error = -EINVAL;
43 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
44 return -EINVAL;
45 group = tomoyo_get_group(w[0], type);
46 if (!group)
47 return -ENOMEM;
48 member = &group->member_list;
49 if (type == TOMOYO_PATH_GROUP) {
50 struct tomoyo_path_group e = { };
51 e.member_name = tomoyo_get_name(w[1]);
52 if (!e.member_name) {
53 error = -ENOMEM;
54 goto out;
55 }
56 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
57 member, tomoyo_same_path_group);
58 tomoyo_put_name(e.member_name);
59 } else if (type == TOMOYO_NUMBER_GROUP) {
60 struct tomoyo_number_group e = { };
61 if (w[1][0] == '@'
62 || !tomoyo_parse_number_union(w[1], &e.number)
63 || e.number.values[0] > e.number.values[1])
64 goto out;
65 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
66 member, tomoyo_same_number_group);
67 /*
68 * tomoyo_put_number_union() is not needed because
69 * w[1][0] != '@'.
70 */
71 }
72 out:
73 tomoyo_put_group(group);
74 return error;
75}
76
77/**
78 * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group.
79 *
80 * @pathname: The name of pathname.
81 * @group: Pointer to "struct tomoyo_path_group".
82 *
83 * Returns true if @pathname matches pathnames in @group, false otherwise.
84 *
85 * Caller holds tomoyo_read_lock().
86 */
87bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
88 const struct tomoyo_group *group)
89{
90 struct tomoyo_path_group *member;
91 bool matched = false;
92 list_for_each_entry_rcu(member, &group->member_list, head.list) {
93 if (member->head.is_deleted)
94 continue;
95 if (!tomoyo_path_matches_pattern(pathname, member->member_name))
96 continue;
97 matched = true;
98 break;
99 }
100 return matched;
101}
102
103/**
104 * tomoyo_number_matches_group - Check whether the given number matches members of the given number group.
105 *
106 * @min: Min number.
107 * @max: Max number.
108 * @group: Pointer to "struct tomoyo_number_group".
109 *
110 * Returns true if @min and @max partially overlaps @group, false otherwise.
111 *
112 * Caller holds tomoyo_read_lock().
113 */
114bool tomoyo_number_matches_group(const unsigned long min,
115 const unsigned long max,
116 const struct tomoyo_group *group)
117{
118 struct tomoyo_number_group *member;
119 bool matched = false;
120 list_for_each_entry_rcu(member, &group->member_list, head.list) {
121 if (member->head.is_deleted)
122 continue;
123 if (min > member->number.values[1] ||
124 max < member->number.values[0])
125 continue;
126 matched = true;
127 break;
128 }
129 return matched;
130}
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c
index 249835abdf4e..a1d75df93e16 100644
--- a/security/tomoyo/memory.c
+++ b/security/tomoyo/memory.c
@@ -89,6 +89,50 @@ void tomoyo_memory_free(void *ptr)
89 kfree(ptr); 89 kfree(ptr);
90} 90}
91 91
92/**
93 * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
94 *
95 * @group_name: The name of address group.
96 * @idx: Index number.
97 *
98 * Returns pointer to "struct tomoyo_group" on success, NULL otherwise.
99 */
100struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
101{
102 struct tomoyo_group e = { };
103 struct tomoyo_group *group = NULL;
104 bool found = false;
105 if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP)
106 return NULL;
107 e.group_name = tomoyo_get_name(group_name);
108 if (!e.group_name)
109 return NULL;
110 if (mutex_lock_interruptible(&tomoyo_policy_lock))
111 goto out;
112 list_for_each_entry(group, &tomoyo_group_list[idx], list) {
113 if (e.group_name != group->group_name)
114 continue;
115 atomic_inc(&group->users);
116 found = true;
117 break;
118 }
119 if (!found) {
120 struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e));
121 if (entry) {
122 INIT_LIST_HEAD(&entry->member_list);
123 atomic_set(&entry->users, 1);
124 list_add_tail_rcu(&entry->list,
125 &tomoyo_group_list[idx]);
126 group = entry;
127 found = true;
128 }
129 }
130 mutex_unlock(&tomoyo_policy_lock);
131 out:
132 tomoyo_put_name(e.group_name);
133 return found ? group : NULL;
134}
135
92/* 136/*
93 * tomoyo_name_list is used for holding string data used by TOMOYO. 137 * tomoyo_name_list is used for holding string data used by TOMOYO.
94 * Since same string data is likely used for multiple times (e.g. 138 * Since same string data is likely used for multiple times (e.g.
diff --git a/security/tomoyo/number_group.c b/security/tomoyo/number_group.c
deleted file mode 100644
index 5e75f5314bda..000000000000
--- a/security/tomoyo/number_group.c
+++ /dev/null
@@ -1,126 +0,0 @@
1/*
2 * security/tomoyo/number_group.c
3 *
4 * Copyright (C) 2005-2009 NTT DATA CORPORATION
5 */
6
7#include <linux/slab.h>
8#include "common.h"
9
10/**
11 * tomoyo_get_group - Allocate memory for "struct tomoyo_number_group".
12 *
13 * @group_name: The name of number group.
14 *
15 * Returns pointer to "struct tomoyo_number_group" on success,
16 * NULL otherwise.
17 */
18struct tomoyo_group *tomoyo_get_number_group(const char *group_name)
19{
20 struct tomoyo_group *entry = NULL;
21 struct tomoyo_group *group = NULL;
22 const struct tomoyo_path_info *saved_group_name;
23 int error = -ENOMEM;
24 if (!tomoyo_correct_word(group_name))
25 return NULL;
26 saved_group_name = tomoyo_get_name(group_name);
27 if (!saved_group_name)
28 return NULL;
29 entry = kzalloc(sizeof(*entry), GFP_NOFS);
30 if (mutex_lock_interruptible(&tomoyo_policy_lock))
31 goto out;
32 list_for_each_entry_rcu(group, &tomoyo_group_list[TOMOYO_NUMBER_GROUP],
33 list) {
34 if (saved_group_name != group->group_name)
35 continue;
36 atomic_inc(&group->users);
37 error = 0;
38 break;
39 }
40 if (error && tomoyo_memory_ok(entry)) {
41 INIT_LIST_HEAD(&entry->member_list);
42 entry->group_name = saved_group_name;
43 saved_group_name = NULL;
44 atomic_set(&entry->users, 1);
45 list_add_tail_rcu(&entry->list,
46 &tomoyo_group_list[TOMOYO_NUMBER_GROUP]);
47 group = entry;
48 entry = NULL;
49 error = 0;
50 }
51 mutex_unlock(&tomoyo_policy_lock);
52 out:
53 tomoyo_put_name(saved_group_name);
54 kfree(entry);
55 return !error ? group : NULL;
56}
57
58static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
59 const struct tomoyo_acl_head *b)
60{
61 return !memcmp(&container_of(a, struct tomoyo_number_group,
62 head)->number,
63 &container_of(b, struct tomoyo_number_group,
64 head)->number,
65 sizeof(container_of(a,
66 struct tomoyo_number_group,
67 head)->number));
68}
69
70/**
71 * tomoyo_write_number_group_policy - Write "struct tomoyo_number_group" list.
72 *
73 * @data: String to parse.
74 * @is_delete: True if it is a delete request.
75 *
76 * Returns 0 on success, nagative value otherwise.
77 */
78int tomoyo_write_number_group_policy(char *data, const bool is_delete)
79{
80 struct tomoyo_group *group;
81 struct tomoyo_number_group e = { };
82 int error;
83 char *w[2];
84 if (!tomoyo_tokenize(data, w, sizeof(w)))
85 return -EINVAL;
86 if (w[1][0] == '@' || !tomoyo_parse_number_union(w[1], &e.number) ||
87 e.number.values[0] > e.number.values[1])
88 return -EINVAL;
89 group = tomoyo_get_number_group(w[0]);
90 if (!group)
91 return -ENOMEM;
92 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
93 &group->member_list,
94 tomoyo_same_number_group);
95 tomoyo_put_group(group);
96 return error;
97}
98
99/**
100 * tomoyo_number_matches_group - Check whether the given number matches members of the given number group.
101 *
102 * @min: Min number.
103 * @max: Max number.
104 * @group: Pointer to "struct tomoyo_number_group".
105 *
106 * Returns true if @min and @max partially overlaps @group, false otherwise.
107 *
108 * Caller holds tomoyo_read_lock().
109 */
110bool tomoyo_number_matches_group(const unsigned long min,
111 const unsigned long max,
112 const struct tomoyo_group *group)
113{
114 struct tomoyo_number_group *member;
115 bool matched = false;
116 list_for_each_entry_rcu(member, &group->member_list, head.list) {
117 if (member->head.is_deleted)
118 continue;
119 if (min > member->number.values[1] ||
120 max < member->number.values[0])
121 continue;
122 matched = true;
123 break;
124 }
125 return matched;
126}
diff --git a/security/tomoyo/path_group.c b/security/tomoyo/path_group.c
deleted file mode 100644
index 2f9f9240bf5a..000000000000
--- a/security/tomoyo/path_group.c
+++ /dev/null
@@ -1,122 +0,0 @@
1/*
2 * security/tomoyo/path_group.c
3 *
4 * Copyright (C) 2005-2009 NTT DATA CORPORATION
5 */
6
7#include <linux/slab.h>
8#include "common.h"
9
10/**
11 * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group".
12 *
13 * @group_name: The name of pathname group.
14 *
15 * Returns pointer to "struct tomoyo_path_group" on success, NULL otherwise.
16 */
17struct tomoyo_group *tomoyo_get_path_group(const char *group_name)
18{
19 struct tomoyo_group *entry = NULL;
20 struct tomoyo_group *group = NULL;
21 const struct tomoyo_path_info *saved_group_name;
22 int error = -ENOMEM;
23 if (!tomoyo_correct_word(group_name))
24 return NULL;
25 saved_group_name = tomoyo_get_name(group_name);
26 if (!saved_group_name)
27 return NULL;
28 entry = kzalloc(sizeof(*entry), GFP_NOFS);
29 if (mutex_lock_interruptible(&tomoyo_policy_lock))
30 goto out;
31 list_for_each_entry_rcu(group, &tomoyo_group_list[TOMOYO_PATH_GROUP],
32 list) {
33 if (saved_group_name != group->group_name)
34 continue;
35 atomic_inc(&group->users);
36 error = 0;
37 break;
38 }
39 if (error && tomoyo_memory_ok(entry)) {
40 INIT_LIST_HEAD(&entry->member_list);
41 entry->group_name = saved_group_name;
42 saved_group_name = NULL;
43 atomic_set(&entry->users, 1);
44 list_add_tail_rcu(&entry->list,
45 &tomoyo_group_list[TOMOYO_PATH_GROUP]);
46 group = entry;
47 entry = NULL;
48 error = 0;
49 }
50 mutex_unlock(&tomoyo_policy_lock);
51 out:
52 tomoyo_put_name(saved_group_name);
53 kfree(entry);
54 return !error ? group : NULL;
55}
56
57static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a,
58 const struct tomoyo_acl_head *b)
59{
60 return container_of(a, struct tomoyo_path_group, head)
61 ->member_name ==
62 container_of(b, struct tomoyo_path_group, head)
63 ->member_name;
64}
65
66/**
67 * tomoyo_write_path_group_policy - Write "struct tomoyo_path_group" list.
68 *
69 * @data: String to parse.
70 * @is_delete: True if it is a delete request.
71 *
72 * Returns 0 on success, nagative value otherwise.
73 */
74int tomoyo_write_path_group_policy(char *data, const bool is_delete)
75{
76 struct tomoyo_group *group;
77 struct tomoyo_path_group e = { };
78 int error = is_delete ? -ENOENT : -ENOMEM;
79 char *w[2];
80 if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
81 return -EINVAL;
82 group = tomoyo_get_path_group(w[0]);
83 if (!group)
84 return -ENOMEM;
85 e.member_name = tomoyo_get_name(w[1]);
86 if (!e.member_name)
87 goto out;
88 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
89 &group->member_list,
90 tomoyo_same_path_group);
91 out:
92 tomoyo_put_name(e.member_name);
93 tomoyo_put_group(group);
94 return error;
95}
96
97/**
98 * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group.
99 *
100 * @pathname: The name of pathname.
101 * @group: Pointer to "struct tomoyo_path_group".
102 *
103 * Returns true if @pathname matches pathnames in @group, false otherwise.
104 *
105 * Caller holds tomoyo_read_lock().
106 */
107bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
108 const struct tomoyo_group *group)
109{
110 struct tomoyo_path_group *member;
111 bool matched = false;
112 list_for_each_entry_rcu(member, &group->member_list, head.list) {
113 if (member->head.is_deleted)
114 continue;
115 if (!tomoyo_path_matches_pattern(pathname,
116 member->member_name))
117 continue;
118 matched = true;
119 break;
120 }
121 return matched;
122}
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c
index 945eeefbbdfe..20abba22af42 100644
--- a/security/tomoyo/util.c
+++ b/security/tomoyo/util.c
@@ -92,7 +92,7 @@ bool tomoyo_parse_name_union(const char *filename,
92 if (!tomoyo_correct_word(filename)) 92 if (!tomoyo_correct_word(filename))
93 return false; 93 return false;
94 if (filename[0] == '@') { 94 if (filename[0] == '@') {
95 ptr->group = tomoyo_get_path_group(filename + 1); 95 ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP);
96 ptr->is_group = true; 96 ptr->is_group = true;
97 return ptr->group != NULL; 97 return ptr->group != NULL;
98 } 98 }
@@ -117,7 +117,7 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num)
117 if (data[0] == '@') { 117 if (data[0] == '@') {
118 if (!tomoyo_correct_word(data)) 118 if (!tomoyo_correct_word(data))
119 return false; 119 return false;
120 num->group = tomoyo_get_number_group(data + 1); 120 num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP);
121 num->is_group = true; 121 num->is_group = true;
122 return num->group != NULL; 122 return num->group != NULL;
123 } 123 }