diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2011-06-26 10:19:28 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-06-28 19:31:20 -0400 |
commit | 32997144fd9925fc4d506a16990a0c405f766526 (patch) | |
tree | 52332d25e9317250a1af1b06008d7eae18717c70 /security | |
parent | eadd99cc85347b4f9eb10122ac90032eb4971b02 (diff) |
TOMOYO: Add ACL group support.
ACL group allows administrator to globally grant not only "file read"
permission but also other permissions.
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
-rw-r--r-- | security/tomoyo/common.c | 51 | ||||
-rw-r--r-- | security/tomoyo/common.h | 7 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 23 | ||||
-rw-r--r-- | security/tomoyo/gc.c | 16 | ||||
-rw-r--r-- | security/tomoyo/memory.c | 2 |
5 files changed, 88 insertions, 11 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 6580ef35074..507ebf01e43 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -896,6 +896,12 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) | |||
896 | domain->profile = (u8) profile; | 896 | domain->profile = (u8) profile; |
897 | return 0; | 897 | return 0; |
898 | } | 898 | } |
899 | if (sscanf(data, "use_group %u\n", &profile) == 1 | ||
900 | && profile < TOMOYO_MAX_ACL_GROUPS) { | ||
901 | if (!is_delete) | ||
902 | domain->group = (u8) profile; | ||
903 | return 0; | ||
904 | } | ||
899 | if (!strcmp(data, "quota_exceeded")) { | 905 | if (!strcmp(data, "quota_exceeded")) { |
900 | domain->quota_warned = !is_delete; | 906 | domain->quota_warned = !is_delete; |
901 | return 0; | 907 | return 0; |
@@ -908,7 +914,7 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) | |||
908 | } | 914 | } |
909 | 915 | ||
910 | /** | 916 | /** |
911 | * tomoyo_set_group - Print category name. | 917 | * tomoyo_set_group - Print "acl_group " header keyword and category name. |
912 | * | 918 | * |
913 | * @head: Pointer to "struct tomoyo_io_buffer". | 919 | * @head: Pointer to "struct tomoyo_io_buffer". |
914 | * @category: Category name. | 920 | * @category: Category name. |
@@ -918,6 +924,9 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) | |||
918 | static void tomoyo_set_group(struct tomoyo_io_buffer *head, | 924 | static void tomoyo_set_group(struct tomoyo_io_buffer *head, |
919 | const char *category) | 925 | const char *category) |
920 | { | 926 | { |
927 | if (head->type == TOMOYO_EXCEPTIONPOLICY) | ||
928 | tomoyo_io_printf(head, "acl_group %u ", | ||
929 | head->r.acl_group_index); | ||
921 | tomoyo_set_string(head, category); | 930 | tomoyo_set_string(head, category); |
922 | } | 931 | } |
923 | 932 | ||
@@ -1041,17 +1050,17 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
1041 | /** | 1050 | /** |
1042 | * tomoyo_read_domain2 - Read domain policy. | 1051 | * tomoyo_read_domain2 - Read domain policy. |
1043 | * | 1052 | * |
1044 | * @head: Pointer to "struct tomoyo_io_buffer". | 1053 | * @head: Pointer to "struct tomoyo_io_buffer". |
1045 | * @domain: Pointer to "struct tomoyo_domain_info". | 1054 | * @list: Pointer to "struct list_head". |
1046 | * | 1055 | * |
1047 | * Caller holds tomoyo_read_lock(). | 1056 | * Caller holds tomoyo_read_lock(). |
1048 | * | 1057 | * |
1049 | * Returns true on success, false otherwise. | 1058 | * Returns true on success, false otherwise. |
1050 | */ | 1059 | */ |
1051 | static bool tomoyo_read_domain2(struct tomoyo_io_buffer *head, | 1060 | static bool tomoyo_read_domain2(struct tomoyo_io_buffer *head, |
1052 | struct tomoyo_domain_info *domain) | 1061 | struct list_head *list) |
1053 | { | 1062 | { |
1054 | list_for_each_cookie(head->r.acl, &domain->acl_info_list) { | 1063 | list_for_each_cookie(head->r.acl, list) { |
1055 | struct tomoyo_acl_info *ptr = | 1064 | struct tomoyo_acl_info *ptr = |
1056 | list_entry(head->r.acl, typeof(*ptr), list); | 1065 | list_entry(head->r.acl, typeof(*ptr), list); |
1057 | if (!tomoyo_print_entry(head, ptr)) | 1066 | if (!tomoyo_print_entry(head, ptr)) |
@@ -1085,6 +1094,8 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head) | |||
1085 | tomoyo_set_lf(head); | 1094 | tomoyo_set_lf(head); |
1086 | tomoyo_io_printf(head, "use_profile %u\n", | 1095 | tomoyo_io_printf(head, "use_profile %u\n", |
1087 | domain->profile); | 1096 | domain->profile); |
1097 | tomoyo_io_printf(head, "use_group %u\n", | ||
1098 | domain->group); | ||
1088 | if (domain->quota_warned) | 1099 | if (domain->quota_warned) |
1089 | tomoyo_set_string(head, "quota_exceeded\n"); | 1100 | tomoyo_set_string(head, "quota_exceeded\n"); |
1090 | if (domain->transition_failed) | 1101 | if (domain->transition_failed) |
@@ -1093,7 +1104,7 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head) | |||
1093 | tomoyo_set_lf(head); | 1104 | tomoyo_set_lf(head); |
1094 | /* fall through */ | 1105 | /* fall through */ |
1095 | case 1: | 1106 | case 1: |
1096 | if (!tomoyo_read_domain2(head, domain)) | 1107 | if (!tomoyo_read_domain2(head, &domain->acl_info_list)) |
1097 | return; | 1108 | return; |
1098 | head->r.step++; | 1109 | head->r.step++; |
1099 | if (!tomoyo_set_lf(head)) | 1110 | if (!tomoyo_set_lf(head)) |
@@ -1262,6 +1273,14 @@ static int tomoyo_write_exception(struct tomoyo_io_buffer *head) | |||
1262 | }; | 1273 | }; |
1263 | u8 i; | 1274 | u8 i; |
1264 | param.is_delete = tomoyo_str_starts(¶m.data, "delete "); | 1275 | param.is_delete = tomoyo_str_starts(¶m.data, "delete "); |
1276 | if (!param.is_delete && tomoyo_str_starts(¶m.data, "select ") && | ||
1277 | !strcmp(param.data, "execute_only")) { | ||
1278 | head->r.print_execute_only = true; | ||
1279 | return 0; | ||
1280 | } | ||
1281 | /* Don't allow updating policies by non manager programs. */ | ||
1282 | if (!tomoyo_manager()) | ||
1283 | return -EPERM; | ||
1265 | if (tomoyo_str_starts(¶m.data, "aggregator ")) | 1284 | if (tomoyo_str_starts(¶m.data, "aggregator ")) |
1266 | return tomoyo_write_aggregator(¶m); | 1285 | return tomoyo_write_aggregator(¶m); |
1267 | for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) | 1286 | for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) |
@@ -1270,6 +1289,14 @@ static int tomoyo_write_exception(struct tomoyo_io_buffer *head) | |||
1270 | for (i = 0; i < TOMOYO_MAX_GROUP; i++) | 1289 | for (i = 0; i < TOMOYO_MAX_GROUP; i++) |
1271 | if (tomoyo_str_starts(¶m.data, tomoyo_group_name[i])) | 1290 | if (tomoyo_str_starts(¶m.data, tomoyo_group_name[i])) |
1272 | return tomoyo_write_group(¶m, i); | 1291 | return tomoyo_write_group(¶m, i); |
1292 | if (tomoyo_str_starts(¶m.data, "acl_group ")) { | ||
1293 | unsigned int group; | ||
1294 | char *data; | ||
1295 | group = simple_strtoul(param.data, &data, 10); | ||
1296 | if (group < TOMOYO_MAX_ACL_GROUPS && *data++ == ' ') | ||
1297 | return tomoyo_write_domain2(&tomoyo_acl_group[group], | ||
1298 | data, param.is_delete); | ||
1299 | } | ||
1273 | return -EINVAL; | 1300 | return -EINVAL; |
1274 | } | 1301 | } |
1275 | 1302 | ||
@@ -1392,6 +1419,15 @@ static void tomoyo_read_exception(struct tomoyo_io_buffer *head) | |||
1392 | head->r.step++; | 1419 | head->r.step++; |
1393 | if (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP) | 1420 | if (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP) |
1394 | return; | 1421 | return; |
1422 | while (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP | ||
1423 | + TOMOYO_MAX_ACL_GROUPS) { | ||
1424 | head->r.acl_group_index = head->r.step - TOMOYO_MAX_POLICY | ||
1425 | - TOMOYO_MAX_GROUP; | ||
1426 | if (!tomoyo_read_domain2(head, &tomoyo_acl_group | ||
1427 | [head->r.acl_group_index])) | ||
1428 | return; | ||
1429 | head->r.step++; | ||
1430 | } | ||
1395 | head->r.eof = true; | 1431 | head->r.eof = true; |
1396 | } | 1432 | } |
1397 | 1433 | ||
@@ -1914,7 +1950,8 @@ int tomoyo_write_control(struct tomoyo_io_buffer *head, | |||
1914 | return -EFAULT; | 1950 | return -EFAULT; |
1915 | /* Don't allow updating policies by non manager programs. */ | 1951 | /* Don't allow updating policies by non manager programs. */ |
1916 | if (head->write != tomoyo_write_pid && | 1952 | if (head->write != tomoyo_write_pid && |
1917 | head->write != tomoyo_write_domain && !tomoyo_manager()) | 1953 | head->write != tomoyo_write_domain && |
1954 | head->write != tomoyo_write_exception && !tomoyo_manager()) | ||
1918 | return -EPERM; | 1955 | return -EPERM; |
1919 | if (mutex_lock_interruptible(&head->io_sem)) | 1956 | if (mutex_lock_interruptible(&head->io_sem)) |
1920 | return -EINTR; | 1957 | return -EINTR; |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index f40ec1fcbc5..4bc3975516c 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -38,6 +38,9 @@ struct linux_binprm; | |||
38 | /* Profile number is an integer between 0 and 255. */ | 38 | /* Profile number is an integer between 0 and 255. */ |
39 | #define TOMOYO_MAX_PROFILES 256 | 39 | #define TOMOYO_MAX_PROFILES 256 |
40 | 40 | ||
41 | /* Group number is an integer between 0 and 255. */ | ||
42 | #define TOMOYO_MAX_ACL_GROUPS 256 | ||
43 | |||
41 | /* Index numbers for operation mode. */ | 44 | /* Index numbers for operation mode. */ |
42 | enum tomoyo_mode_index { | 45 | enum tomoyo_mode_index { |
43 | TOMOYO_CONFIG_DISABLED, | 46 | TOMOYO_CONFIG_DISABLED, |
@@ -357,6 +360,7 @@ struct tomoyo_domain_info { | |||
357 | /* Name of this domain. Never NULL. */ | 360 | /* Name of this domain. Never NULL. */ |
358 | const struct tomoyo_path_info *domainname; | 361 | const struct tomoyo_path_info *domainname; |
359 | u8 profile; /* Profile number to use. */ | 362 | u8 profile; /* Profile number to use. */ |
363 | u8 group; /* Group number to use. */ | ||
360 | bool is_deleted; /* Delete flag. */ | 364 | bool is_deleted; /* Delete flag. */ |
361 | bool quota_warned; /* Quota warnning flag. */ | 365 | bool quota_warned; /* Quota warnning flag. */ |
362 | bool transition_failed; /* Domain transition failed flag. */ | 366 | bool transition_failed; /* Domain transition failed flag. */ |
@@ -446,6 +450,7 @@ struct tomoyo_io_buffer { | |||
446 | int step; | 450 | int step; |
447 | int query_index; | 451 | int query_index; |
448 | u16 index; | 452 | u16 index; |
453 | u8 acl_group_index; | ||
449 | u8 bit; | 454 | u8 bit; |
450 | u8 w_pos; | 455 | u8 w_pos; |
451 | bool eof; | 456 | bool eof; |
@@ -666,6 +671,8 @@ extern struct mutex tomoyo_policy_lock; | |||
666 | /* Has /sbin/init started? */ | 671 | /* Has /sbin/init started? */ |
667 | extern bool tomoyo_policy_loaded; | 672 | extern bool tomoyo_policy_loaded; |
668 | 673 | ||
674 | extern struct list_head tomoyo_acl_group[TOMOYO_MAX_ACL_GROUPS]; | ||
675 | |||
669 | /* The kernel's domain. */ | 676 | /* The kernel's domain. */ |
670 | extern struct tomoyo_domain_info tomoyo_kernel_domain; | 677 | extern struct tomoyo_domain_info tomoyo_kernel_domain; |
671 | 678 | ||
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index cb5d2b05c24..af5f325e2f3 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -12,6 +12,9 @@ | |||
12 | 12 | ||
13 | /* Variables definitions.*/ | 13 | /* Variables definitions.*/ |
14 | 14 | ||
15 | /* The global ACL referred by "use_group" keyword. */ | ||
16 | struct list_head tomoyo_acl_group[TOMOYO_MAX_ACL_GROUPS]; | ||
17 | |||
15 | /* The initial domain. */ | 18 | /* The initial domain. */ |
16 | struct tomoyo_domain_info tomoyo_kernel_domain; | 19 | struct tomoyo_domain_info tomoyo_kernel_domain; |
17 | 20 | ||
@@ -125,14 +128,27 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, | |||
125 | return error; | 128 | return error; |
126 | } | 129 | } |
127 | 130 | ||
131 | /** | ||
132 | * tomoyo_check_acl - Do permission check. | ||
133 | * | ||
134 | * @r: Pointer to "struct tomoyo_request_info". | ||
135 | * @check_entry: Callback function to check type specific parameters. | ||
136 | * | ||
137 | * Returns 0 on success, negative value otherwise. | ||
138 | * | ||
139 | * Caller holds tomoyo_read_lock(). | ||
140 | */ | ||
128 | void tomoyo_check_acl(struct tomoyo_request_info *r, | 141 | void tomoyo_check_acl(struct tomoyo_request_info *r, |
129 | bool (*check_entry) (struct tomoyo_request_info *, | 142 | bool (*check_entry) (struct tomoyo_request_info *, |
130 | const struct tomoyo_acl_info *)) | 143 | const struct tomoyo_acl_info *)) |
131 | { | 144 | { |
132 | const struct tomoyo_domain_info *domain = r->domain; | 145 | const struct tomoyo_domain_info *domain = r->domain; |
133 | struct tomoyo_acl_info *ptr; | 146 | struct tomoyo_acl_info *ptr; |
147 | bool retried = false; | ||
148 | const struct list_head *list = &domain->acl_info_list; | ||
134 | 149 | ||
135 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 150 | retry: |
151 | list_for_each_entry_rcu(ptr, list, list) { | ||
136 | if (ptr->is_deleted || ptr->type != r->param_type) | 152 | if (ptr->is_deleted || ptr->type != r->param_type) |
137 | continue; | 153 | continue; |
138 | if (check_entry(r, ptr)) { | 154 | if (check_entry(r, ptr)) { |
@@ -140,6 +156,11 @@ void tomoyo_check_acl(struct tomoyo_request_info *r, | |||
140 | return; | 156 | return; |
141 | } | 157 | } |
142 | } | 158 | } |
159 | if (!retried) { | ||
160 | retried = true; | ||
161 | list = &tomoyo_acl_group[domain->group]; | ||
162 | goto retry; | ||
163 | } | ||
143 | r->granted = false; | 164 | r->granted = false; |
144 | } | 165 | } |
145 | 166 | ||
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index de14030823c..412ee8309c2 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c | |||
@@ -265,10 +265,17 @@ static bool tomoyo_collect_member(const enum tomoyo_policy_id id, | |||
265 | return true; | 265 | return true; |
266 | } | 266 | } |
267 | 267 | ||
268 | static bool tomoyo_collect_acl(struct tomoyo_domain_info *domain) | 268 | /** |
269 | * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info". | ||
270 | * | ||
271 | * @list: Pointer to "struct list_head". | ||
272 | * | ||
273 | * Returns true if some elements are deleted, false otherwise. | ||
274 | */ | ||
275 | static bool tomoyo_collect_acl(struct list_head *list) | ||
269 | { | 276 | { |
270 | struct tomoyo_acl_info *acl; | 277 | struct tomoyo_acl_info *acl; |
271 | list_for_each_entry(acl, &domain->acl_info_list, list) { | 278 | list_for_each_entry(acl, list, list) { |
272 | if (!acl->is_deleted) | 279 | if (!acl->is_deleted) |
273 | continue; | 280 | continue; |
274 | if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list)) | 281 | if (!tomoyo_add_to_gc(TOMOYO_ID_ACL, &acl->list)) |
@@ -291,10 +298,13 @@ static void tomoyo_collect_entry(void) | |||
291 | if (!tomoyo_collect_member(i, &tomoyo_policy_list[i])) | 298 | if (!tomoyo_collect_member(i, &tomoyo_policy_list[i])) |
292 | goto unlock; | 299 | goto unlock; |
293 | } | 300 | } |
301 | for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++) | ||
302 | if (!tomoyo_collect_acl(&tomoyo_acl_group[i])) | ||
303 | goto unlock; | ||
294 | { | 304 | { |
295 | struct tomoyo_domain_info *domain; | 305 | struct tomoyo_domain_info *domain; |
296 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { | 306 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
297 | if (!tomoyo_collect_acl(domain)) | 307 | if (!tomoyo_collect_acl(&domain->acl_info_list)) |
298 | goto unlock; | 308 | goto unlock; |
299 | if (!domain->is_deleted || atomic_read(&domain->users)) | 309 | if (!domain->is_deleted || atomic_read(&domain->users)) |
300 | continue; | 310 | continue; |
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c index 598282cd0bd..7a0493943d6 100644 --- a/security/tomoyo/memory.c +++ b/security/tomoyo/memory.c | |||
@@ -213,6 +213,8 @@ void __init tomoyo_mm_init(void) | |||
213 | for (idx = 0; idx < TOMOYO_MAX_HASH; idx++) | 213 | for (idx = 0; idx < TOMOYO_MAX_HASH; idx++) |
214 | INIT_LIST_HEAD(&tomoyo_name_list[idx]); | 214 | INIT_LIST_HEAD(&tomoyo_name_list[idx]); |
215 | INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); | 215 | INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); |
216 | for (idx = 0; idx < TOMOYO_MAX_ACL_GROUPS; idx++) | ||
217 | INIT_LIST_HEAD(&tomoyo_acl_group[idx]); | ||
216 | tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME); | 218 | tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME); |
217 | list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list); | 219 | list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list); |
218 | idx = tomoyo_read_lock(); | 220 | idx = tomoyo_read_lock(); |