diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 0f8079b65e23..148ad50a1f94 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -1174,7 +1174,7 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) struct tomoyo_domain_info *domain = head->w.domain; const bool is_delete = head->w.is_delete; bool is_select = !is_delete && tomoyo_str_starts(&data, "select "); - unsigned int profile; + unsigned int idx; if (*data == '<') { int ret = 0; @@ -1192,24 +1192,27 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) if (!domain) return -EINVAL; ns = domain->ns; - if (sscanf(data, "use_profile %u", &profile) == 1 - && profile < TOMOYO_MAX_PROFILES) { - if (!tomoyo_policy_loaded || ns->profile_ptr[profile]) - domain->profile = (u8) profile; + if (sscanf(data, "use_profile %u", &idx) == 1 + && idx < TOMOYO_MAX_PROFILES) { + if (!tomoyo_policy_loaded || ns->profile_ptr[idx]) + if (!is_delete) + domain->profile = (u8) idx; return 0; } - if (sscanf(data, "use_group %u\n", &profile) == 1 - && profile < TOMOYO_MAX_ACL_GROUPS) { + if (sscanf(data, "use_group %u\n", &idx) == 1 + && idx < TOMOYO_MAX_ACL_GROUPS) { if (!is_delete) - domain->group = (u8) profile; + set_bit(idx, domain->group); + else + clear_bit(idx, domain->group); return 0; } - for (profile = 0; profile < TOMOYO_MAX_DOMAIN_INFO_FLAGS; profile++) { - const char *cp = tomoyo_dif[profile]; + for (idx = 0; idx < TOMOYO_MAX_DOMAIN_INFO_FLAGS; idx++) { + const char *cp = tomoyo_dif[idx]; if (strncmp(data, cp, strlen(cp) - 1)) continue; - domain->flags[profile] = !is_delete; + domain->flags[idx] = !is_delete; return 0; } return tomoyo_write_domain2(ns, &domain->acl_info_list, data, @@ -1629,22 +1632,33 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head) tomoyo_set_lf(head); tomoyo_io_printf(head, "use_profile %u\n", domain->profile); - tomoyo_io_printf(head, "use_group %u\n", - domain->group); for (i = 0; i < TOMOYO_MAX_DOMAIN_INFO_FLAGS; i++) if (domain->flags[i]) tomoyo_set_string(head, tomoyo_dif[i]); + head->r.index = 0; + head->r.step++; + /* fall through */ + case 1: + while (head->r.index < TOMOYO_MAX_ACL_GROUPS) { + i = head->r.index++; + if (!test_bit(i, domain->group)) + continue; + tomoyo_io_printf(head, "use_group %u\n", i); + if (!tomoyo_flush(head)) + return; + } + head->r.index = 0; head->r.step++; tomoyo_set_lf(head); /* fall through */ - case 1: + case 2: if (!tomoyo_read_domain2(head, &domain->acl_info_list)) return; head->r.step++; if (!tomoyo_set_lf(head)) return; /* fall through */ - case 2: + case 3: head->r.step = 0; if (head->r.print_this_domain_only) goto done; diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index f2c458ab9942..74dbd3bdc64e 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -684,8 +684,9 @@ struct tomoyo_domain_info { const struct tomoyo_path_info *domainname; /* Namespace for this domain. Never NULL. */ struct tomoyo_policy_namespace *ns; + /* Group numbers to use. */ + unsigned long group[TOMOYO_MAX_ACL_GROUPS / BITS_PER_LONG]; u8 profile; /* Profile number to use. */ - u8 group; /* Group number to use. */ bool is_deleted; /* Delete flag. */ bool flags[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; atomic_t users; /* Number of referring tasks. */ diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index bf832b301412..8526a0a74023 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -162,8 +162,8 @@ void tomoyo_check_acl(struct tomoyo_request_info *r, { const struct tomoyo_domain_info *domain = r->domain; struct tomoyo_acl_info *ptr; - bool retried = false; const struct list_head *list = &domain->acl_info_list; + u16 i = 0; retry: list_for_each_entry_rcu(ptr, list, list) { @@ -177,9 +177,10 @@ retry: r->granted = true; return; } - if (!retried) { - retried = true; - list = &domain->ns->acl_group[domain->group]; + for (; i < TOMOYO_MAX_ACL_GROUPS; i++) { + if (!test_bit(i, domain->group)) + continue; + list = &domain->ns->acl_group[i++]; goto retry; } r->granted = false; @@ -561,7 +562,7 @@ struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, const struct tomoyo_domain_info *domain = tomoyo_domain(); e.profile = domain->profile; - e.group = domain->group; + memcpy(e.group, domain->group, sizeof(e.group)); } e.domainname = tomoyo_get_name(domainname); if (!e.domainname) @@ -583,13 +584,17 @@ out: if (entry && transit) { if (created) { struct tomoyo_request_info r; + int i; tomoyo_init_request_info(&r, entry, TOMOYO_MAC_FILE_EXECUTE); r.granted = false; tomoyo_write_log(&r, "use_profile %u\n", entry->profile); - tomoyo_write_log(&r, "use_group %u\n", entry->group); + for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++) + if (test_bit(i, entry->group)) + tomoyo_write_log(&r, "use_group %u\n", + i); tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES); } }