aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2011-06-26 10:19:28 -0400
committerJames Morris <jmorris@namei.org>2011-06-28 19:31:20 -0400
commit32997144fd9925fc4d506a16990a0c405f766526 (patch)
tree52332d25e9317250a1af1b06008d7eae18717c70 /security
parenteadd99cc85347b4f9eb10122ac90032eb4971b02 (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.c51
-rw-r--r--security/tomoyo/common.h7
-rw-r--r--security/tomoyo/domain.c23
-rw-r--r--security/tomoyo/gc.c16
-rw-r--r--security/tomoyo/memory.c2
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)
918static void tomoyo_set_group(struct tomoyo_io_buffer *head, 924static 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 */
1051static bool tomoyo_read_domain2(struct tomoyo_io_buffer *head, 1060static 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(&param.data, "delete "); 1275 param.is_delete = tomoyo_str_starts(&param.data, "delete ");
1276 if (!param.is_delete && tomoyo_str_starts(&param.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(&param.data, "aggregator ")) 1284 if (tomoyo_str_starts(&param.data, "aggregator "))
1266 return tomoyo_write_aggregator(&param); 1285 return tomoyo_write_aggregator(&param);
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(&param.data, tomoyo_group_name[i])) 1290 if (tomoyo_str_starts(&param.data, tomoyo_group_name[i]))
1272 return tomoyo_write_group(&param, i); 1291 return tomoyo_write_group(&param, i);
1292 if (tomoyo_str_starts(&param.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. */
42enum tomoyo_mode_index { 45enum 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? */
667extern bool tomoyo_policy_loaded; 672extern bool tomoyo_policy_loaded;
668 673
674extern struct list_head tomoyo_acl_group[TOMOYO_MAX_ACL_GROUPS];
675
669/* The kernel's domain. */ 676/* The kernel's domain. */
670extern struct tomoyo_domain_info tomoyo_kernel_domain; 677extern 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. */
16struct list_head tomoyo_acl_group[TOMOYO_MAX_ACL_GROUPS];
17
15/* The initial domain. */ 18/* The initial domain. */
16struct tomoyo_domain_info tomoyo_kernel_domain; 19struct 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 */
128void tomoyo_check_acl(struct tomoyo_request_info *r, 141void 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) { 150retry:
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
268static 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 */
275static 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();