summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2019-01-24 10:37:36 +0100
committerJames Morris <james.morris@microsoft.com>2019-01-24 23:50:27 +0100
commit4b42564181d683d767b495d7041b1f229468042f (patch)
tree8f100d312c522aa2a0d3cfbb118293919826702d
parenttomoyo: Coding style fix. (diff)
downloadlinux-4b42564181d683d767b495d7041b1f229468042f.tar.xz
linux-4b42564181d683d767b495d7041b1f229468042f.zip
tomoyo: Allow multiple use_group lines.
Being able to specify multiple "use_group" lines makes it easier to write whitelisted policies. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <james.morris@microsoft.com>
-rw-r--r--security/tomoyo/common.c44
-rw-r--r--security/tomoyo/common.h3
-rw-r--r--security/tomoyo/domain.c17
3 files changed, 42 insertions, 22 deletions
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++;
- tomoyo_set_lf(head);
/* 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 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);
}
}