From 43fc460907dc56a3450654efc6ba1dfbcd4594eb Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Fri, 21 Sep 2018 17:18:07 -0700 Subject: TOMOYO: Abstract use of cred security blob Don't use the cred->security pointer directly. Provide helper functions that provide the security blob pointer. Signed-off-by: Casey Schaufler Reviewed-by: Kees Cook [kees: adjusted for ordered init series] Signed-off-by: Kees Cook --- security/tomoyo/domain.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index f6758dad981f..b7469fdbff01 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -678,6 +678,7 @@ out: */ int tomoyo_find_next_domain(struct linux_binprm *bprm) { + struct tomoyo_domain_info **blob; struct tomoyo_domain_info *old_domain = tomoyo_domain(); struct tomoyo_domain_info *domain = NULL; const char *original_name = bprm->filename; @@ -843,7 +844,8 @@ force_jump_domain: domain = old_domain; /* Update reference count on "struct tomoyo_domain_info". */ atomic_inc(&domain->users); - bprm->cred->security = domain; + blob = tomoyo_cred(bprm->cred); + *blob = domain; kfree(exename.name); if (!retval) { ee->r.domain = domain; -- cgit From 8c6cb983cd52d78ab4e4c0191c73a11dcb60b866 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sat, 19 Jan 2019 23:11:40 +0900 Subject: tomoyo: Swicth from cred->security to task_struct->security. TOMOYO security module is designed to use "struct task_struct"->security in order to allow per "struct task_struct" tracking without being disturbed by unable to update "struct cred"->security due to override mechanism. Now that infrastructure-managed security blob is ready, this patch updates TOMOYO to use "struct task_struct"->security. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/domain.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index b7469fdbff01..39abf3ae6168 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -678,7 +678,6 @@ out: */ int tomoyo_find_next_domain(struct linux_binprm *bprm) { - struct tomoyo_domain_info **blob; struct tomoyo_domain_info *old_domain = tomoyo_domain(); struct tomoyo_domain_info *domain = NULL; const char *original_name = bprm->filename; @@ -843,9 +842,13 @@ force_jump_domain: if (!domain) domain = old_domain; /* Update reference count on "struct tomoyo_domain_info". */ - atomic_inc(&domain->users); - blob = tomoyo_cred(bprm->cred); - *blob = domain; + { + struct tomoyo_task *s = tomoyo_task(current); + + s->old_domain_info = s->domain_info; + s->domain_info = domain; + atomic_inc(&domain->users); + } kfree(exename.name); if (!retval) { ee->r.domain = domain; -- cgit From cdcf6723add57a0ffb37cfde1ca54a00f5715b71 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 24 Jan 2019 18:37:35 +0900 Subject: tomoyo: Coding style fix. Follow many of recommendations by scripts/checkpatch.pl, and follow "lift switch variables out of switches" by Kees Cook. This patch makes no functional change. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/domain.c | 50 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'security/tomoyo/domain.c') diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 39abf3ae6168..bf832b301412 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -30,10 +30,10 @@ struct tomoyo_domain_info tomoyo_kernel_domain; */ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, struct tomoyo_acl_param *param, - bool (*check_duplicate) (const struct tomoyo_acl_head - *, - const struct tomoyo_acl_head - *)) + bool (*check_duplicate)(const struct tomoyo_acl_head + *, + const struct tomoyo_acl_head + *)) { int error = param->is_delete ? -ENOENT : -ENOMEM; struct tomoyo_acl_head *entry; @@ -90,13 +90,13 @@ static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a, */ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, struct tomoyo_acl_param *param, - bool (*check_duplicate) (const struct tomoyo_acl_info - *, - const struct tomoyo_acl_info - *), - bool (*merge_duplicate) (struct tomoyo_acl_info *, - struct tomoyo_acl_info *, - const bool)) + bool (*check_duplicate)(const struct tomoyo_acl_info + *, + const struct tomoyo_acl_info + *), + bool (*merge_duplicate)(struct tomoyo_acl_info *, + struct tomoyo_acl_info *, + const bool)) { const bool is_delete = param->is_delete; int error = is_delete ? -ENOENT : -ENOMEM; @@ -157,8 +157,8 @@ out: * Caller holds tomoyo_read_lock(). */ void tomoyo_check_acl(struct tomoyo_request_info *r, - bool (*check_entry) (struct tomoyo_request_info *, - const struct tomoyo_acl_info *)) + bool (*check_entry)(struct tomoyo_request_info *, + const struct tomoyo_acl_info *)) { const struct tomoyo_domain_info *domain = r->domain; struct tomoyo_acl_info *ptr; @@ -198,6 +198,7 @@ LIST_HEAD(tomoyo_domain_list); static const char *tomoyo_last_word(const char *name) { const char *cp = strrchr(name, ' '); + if (cp) return cp + 1; return name; @@ -220,6 +221,7 @@ static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a, const struct tomoyo_transition_control *p2 = container_of(b, typeof(*p2), head); + return p1->type == p2->type && p1->is_last_name == p2->is_last_name && p1->domainname == p2->domainname && p1->program == p2->program; @@ -240,6 +242,7 @@ int tomoyo_write_transition_control(struct tomoyo_acl_param *param, int error = param->is_delete ? -ENOENT : -ENOMEM; char *program = param->data; char *domainname = strstr(program, " from "); + if (domainname) { *domainname = '\0'; domainname += 6; @@ -293,6 +296,7 @@ static inline bool tomoyo_scan_transition const enum tomoyo_transition_type type) { const struct tomoyo_transition_control *ptr; + list_for_each_entry_rcu(ptr, list, head.list) { if (ptr->head.is_deleted || ptr->type != type) continue; @@ -338,9 +342,11 @@ static enum tomoyo_transition_type tomoyo_transition_type { const char *last_name = tomoyo_last_word(domainname->name); enum tomoyo_transition_type type = TOMOYO_TRANSITION_CONTROL_NO_RESET; + while (type < TOMOYO_MAX_TRANSITION_TYPE) { const struct list_head * const list = &ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL]; + if (!tomoyo_scan_transition(list, domainname, program, last_name, type)) { type++; @@ -375,6 +381,7 @@ static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a, head); const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), head); + return p1->original_name == p2->original_name && p1->aggregated_name == p2->aggregated_name; } @@ -394,6 +401,7 @@ int tomoyo_write_aggregator(struct tomoyo_acl_param *param) int error = param->is_delete ? -ENOENT : -ENOMEM; const char *original_name = tomoyo_read_token(param); const char *aggregated_name = tomoyo_read_token(param); + if (!tomoyo_correct_word(original_name) || !tomoyo_correct_path(aggregated_name)) return -EINVAL; @@ -426,6 +434,7 @@ static struct tomoyo_policy_namespace *tomoyo_find_namespace (const char *name, const unsigned int len) { struct tomoyo_policy_namespace *ns; + list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { if (strncmp(name, ns->name, len) || (name[len] && name[len] != ' ')) @@ -451,6 +460,7 @@ struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname) struct tomoyo_policy_namespace *entry; const char *cp = domainname; unsigned int len = 0; + while (*cp && *cp++ != ' ') len++; ptr = tomoyo_find_namespace(domainname, len); @@ -466,6 +476,7 @@ struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname) ptr = tomoyo_find_namespace(domainname, len); if (!ptr && tomoyo_memory_ok(entry)) { char *name = (char *) (entry + 1); + ptr = entry; memmove(name, domainname, len); name[len] = '\0'; @@ -490,6 +501,7 @@ static bool tomoyo_namespace_jump(const char *domainname) { const char *namespace = tomoyo_current_namespace()->name; const int len = strlen(namespace); + return strncmp(domainname, namespace, len) || (domainname[len] && domainname[len] != ' '); } @@ -510,6 +522,7 @@ struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, struct tomoyo_domain_info e = { }; struct tomoyo_domain_info *entry = tomoyo_find_domain(domainname); bool created = false; + if (entry) { if (transit) { /* @@ -546,6 +559,7 @@ struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, */ if (transit) { const struct tomoyo_domain_info *domain = tomoyo_domain(); + e.profile = domain->profile; e.group = domain->group; } @@ -569,6 +583,7 @@ out: if (entry && transit) { if (created) { struct tomoyo_request_info r; + tomoyo_init_request_info(&r, entry, TOMOYO_MAC_FILE_EXECUTE); r.granted = false; @@ -712,6 +727,7 @@ retry: struct tomoyo_aggregator *ptr; struct list_head *list = &old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR]; + /* Check 'aggregator' directive. */ candidate = &exename; list_for_each_entry_rcu(ptr, list, head.list) { @@ -747,6 +763,7 @@ retry: */ if (ee->transition) { const char *domainname = ee->transition->name; + reject_on_transition_failure = true; if (!strcmp(domainname, "keep")) goto force_keep_domain; @@ -758,6 +775,7 @@ retry: goto force_initialize_domain; if (!strcmp(domainname, "parent")) { char *cp; + strncpy(ee->tmp, old_domain->domainname->name, TOMOYO_EXEC_TMPSIZE - 1); cp = strrchr(ee->tmp, ' '); @@ -822,8 +840,7 @@ force_jump_domain: if (domain) retval = 0; else if (reject_on_transition_failure) { - printk(KERN_WARNING "ERROR: Domain '%s' not ready.\n", - ee->tmp); + pr_warn("ERROR: Domain '%s' not ready.\n", ee->tmp); retval = -ENOMEM; } else if (ee->r.mode == TOMOYO_CONFIG_ENFORCING) retval = -ENOMEM; @@ -834,8 +851,7 @@ force_jump_domain: ee->r.granted = false; tomoyo_write_log(&ee->r, "%s", tomoyo_dif [TOMOYO_DIF_TRANSITION_FAILED]); - printk(KERN_WARNING - "ERROR: Domain '%s' not defined.\n", ee->tmp); + pr_warn("ERROR: Domain '%s' not defined.\n", ee->tmp); } } out: -- cgit From 4b42564181d683d767b495d7041b1f229468042f Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 24 Jan 2019 18:37:36 +0900 Subject: 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 Signed-off-by: James Morris --- security/tomoyo/domain.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'security/tomoyo/domain.c') 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); } } -- cgit