From 7c2ea22e3c5463627ca98924cd65cb9e480dc29c Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 17 Jun 2010 16:55:58 +0900 Subject: TOMOYO: Merge path_group and number_group. Use common code for "path_group" and "number_group". Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/group.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 security/tomoyo/group.c (limited to 'security/tomoyo/group.c') diff --git a/security/tomoyo/group.c b/security/tomoyo/group.c new file mode 100644 index 00000000000..3f0a2abf65c --- /dev/null +++ b/security/tomoyo/group.c @@ -0,0 +1,130 @@ +/* + * security/tomoyo/group.c + * + * Copyright (C) 2005-2010 NTT DATA CORPORATION + */ + +#include +#include "common.h" + +static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a, + const struct tomoyo_acl_head *b) +{ + return container_of(a, struct tomoyo_path_group, head)->member_name == + container_of(b, struct tomoyo_path_group, head)->member_name; +} + +static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a, + const struct tomoyo_acl_head *b) +{ + return !memcmp(&container_of(a, struct tomoyo_number_group, head) + ->number, + &container_of(b, struct tomoyo_number_group, head) + ->number, + sizeof(container_of(a, struct tomoyo_number_group, head) + ->number)); +} + +/** + * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list. + * + * @data: String to parse. + * @is_delete: True if it is a delete request. + * @type: Type of this group. + * + * Returns 0 on success, negative value otherwise. + */ +int tomoyo_write_group(char *data, const bool is_delete, const u8 type) +{ + struct tomoyo_group *group; + struct list_head *member; + char *w[2]; + int error = -EINVAL; + if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) + return -EINVAL; + group = tomoyo_get_group(w[0], type); + if (!group) + return -ENOMEM; + member = &group->member_list; + if (type == TOMOYO_PATH_GROUP) { + struct tomoyo_path_group e = { }; + e.member_name = tomoyo_get_name(w[1]); + if (!e.member_name) { + error = -ENOMEM; + goto out; + } + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, + member, tomoyo_same_path_group); + tomoyo_put_name(e.member_name); + } else if (type == TOMOYO_NUMBER_GROUP) { + struct tomoyo_number_group e = { }; + if (w[1][0] == '@' + || !tomoyo_parse_number_union(w[1], &e.number) + || e.number.values[0] > e.number.values[1]) + goto out; + error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, + member, tomoyo_same_number_group); + /* + * tomoyo_put_number_union() is not needed because + * w[1][0] != '@'. + */ + } + out: + tomoyo_put_group(group); + return error; +} + +/** + * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group. + * + * @pathname: The name of pathname. + * @group: Pointer to "struct tomoyo_path_group". + * + * Returns true if @pathname matches pathnames in @group, false otherwise. + * + * Caller holds tomoyo_read_lock(). + */ +bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, + const struct tomoyo_group *group) +{ + struct tomoyo_path_group *member; + bool matched = false; + list_for_each_entry_rcu(member, &group->member_list, head.list) { + if (member->head.is_deleted) + continue; + if (!tomoyo_path_matches_pattern(pathname, member->member_name)) + continue; + matched = true; + break; + } + return matched; +} + +/** + * tomoyo_number_matches_group - Check whether the given number matches members of the given number group. + * + * @min: Min number. + * @max: Max number. + * @group: Pointer to "struct tomoyo_number_group". + * + * Returns true if @min and @max partially overlaps @group, false otherwise. + * + * Caller holds tomoyo_read_lock(). + */ +bool tomoyo_number_matches_group(const unsigned long min, + const unsigned long max, + const struct tomoyo_group *group) +{ + struct tomoyo_number_group *member; + bool matched = false; + list_for_each_entry_rcu(member, &group->member_list, head.list) { + if (member->head.is_deleted) + continue; + if (min > member->number.values[1] || + max < member->number.values[0]) + continue; + matched = true; + break; + } + return matched; +} -- cgit v1.2.3-70-g09d2 From 484ca79c653121d3c79fffb86e1deea724f2e20b Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 29 Jul 2010 14:29:55 +0900 Subject: TOMOYO: Use pathname specified by policy rather than execve() Commit c9e69318 "TOMOYO: Allow wildcard for execute permission." changed execute permission and domainname to accept wildcards. But tomoyo_find_next_domain() was using pathname passed to execve() rather than pathname specified by the execute permission. As a result, processes were not able to transit to domains which contain wildcards in their domainnames. This patch passes pathname specified by the execute permission back to tomoyo_find_next_domain() so that processes can transit to domains which contain wildcards in their domainnames. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.h | 14 +++++++++----- security/tomoyo/domain.c | 15 ++++++++++++++- security/tomoyo/file.c | 26 +++++++++++++++++--------- security/tomoyo/group.c | 14 +++++++------- security/tomoyo/mount.c | 2 +- 5 files changed, 48 insertions(+), 23 deletions(-) (limited to 'security/tomoyo/group.c') diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 2ffad613855..04454cb7b24 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -246,6 +246,8 @@ struct tomoyo_request_info { union { struct { const struct tomoyo_path_info *filename; + /* For using wildcards at tomoyo_find_next_domain(). */ + const struct tomoyo_path_info *matched_path; u8 operation; } path; struct { @@ -718,8 +720,9 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); /* Print out of memory warning message. */ void tomoyo_warn_oom(const char *function); /* Check whether the given name matches the given name_union. */ -bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, - const struct tomoyo_name_union *ptr); +const struct tomoyo_path_info * +tomoyo_compare_name_union(const struct tomoyo_path_info *name, + const struct tomoyo_name_union *ptr); /* Check whether the given number matches the given number_union. */ bool tomoyo_compare_number_union(const unsigned long value, const struct tomoyo_number_union *ptr); @@ -736,8 +739,9 @@ bool tomoyo_domain_def(const unsigned char *buffer); bool tomoyo_parse_name_union(const char *filename, struct tomoyo_name_union *ptr); /* Check whether the given filename matches the given path_group. */ -bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, - const struct tomoyo_group *group); +const struct tomoyo_path_info * +tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, + const struct tomoyo_group *group); /* Check whether the given value matches the given number_group. */ bool tomoyo_number_matches_group(const unsigned long min, const unsigned long max, @@ -879,7 +883,7 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, const struct tomoyo_acl_head *)); void tomoyo_check_acl(struct tomoyo_request_info *r, - bool (*check_entry) (const struct tomoyo_request_info *, + bool (*check_entry) (struct tomoyo_request_info *, const struct tomoyo_acl_info *)); /********** External variable definitions. **********/ diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 4e0101b0041..35388408e47 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -110,7 +110,7 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, } void tomoyo_check_acl(struct tomoyo_request_info *r, - bool (*check_entry) (const struct tomoyo_request_info *, + bool (*check_entry) (struct tomoyo_request_info *, const struct tomoyo_acl_info *)) { const struct tomoyo_domain_info *domain = r->domain; @@ -465,6 +465,19 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) goto retry; if (retval < 0) goto out; + /* + * To be able to specify domainnames with wildcards, use the + * pathname specified in the policy (which may contain + * wildcard) rather than the pathname passed to execve() + * (which never contains wildcard). + */ + if (r.param.path.matched_path) { + if (need_kfree) + kfree(rn.name); + need_kfree = false; + /* This is OK because it is read only. */ + rn = *r.param.path.matched_path; + } /* Calculate domain to transit to. */ switch (tomoyo_transition_type(old_domain->domainname, &rn)) { diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index f7877fa80f1..9d32f182301 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -95,12 +95,15 @@ void tomoyo_put_name_union(struct tomoyo_name_union *ptr) tomoyo_put_name(ptr->filename); } -bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, - const struct tomoyo_name_union *ptr) +const struct tomoyo_path_info * +tomoyo_compare_name_union(const struct tomoyo_path_info *name, + const struct tomoyo_name_union *ptr) { if (ptr->is_group) return tomoyo_path_matches_group(name, ptr->group); - return tomoyo_path_matches_pattern(name, ptr->filename); + if (tomoyo_path_matches_pattern(name, ptr->filename)) + return ptr->filename; + return NULL; } void tomoyo_put_number_union(struct tomoyo_number_union *ptr) @@ -504,16 +507,21 @@ int tomoyo_write_no_rewrite(char *data, const bool is_delete) return tomoyo_update_no_rewrite_entry(data, is_delete); } -static bool tomoyo_check_path_acl(const struct tomoyo_request_info *r, +static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, const struct tomoyo_acl_info *ptr) { const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl), head); - return (acl->perm & (1 << r->param.path.operation)) && - tomoyo_compare_name_union(r->param.path.filename, &acl->name); + if (acl->perm & (1 << r->param.path.operation)) { + r->param.path.matched_path = + tomoyo_compare_name_union(r->param.path.filename, + &acl->name); + return r->param.path.matched_path != NULL; + } + return false; } -static bool tomoyo_check_path_number_acl(const struct tomoyo_request_info *r, +static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r, const struct tomoyo_acl_info *ptr) { const struct tomoyo_path_number_acl *acl = @@ -525,7 +533,7 @@ static bool tomoyo_check_path_number_acl(const struct tomoyo_request_info *r, &acl->name); } -static bool tomoyo_check_path2_acl(const struct tomoyo_request_info *r, +static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r, const struct tomoyo_acl_info *ptr) { const struct tomoyo_path2_acl *acl = @@ -536,7 +544,7 @@ static bool tomoyo_check_path2_acl(const struct tomoyo_request_info *r, &acl->name2); } -static bool tomoyo_check_mkdev_acl(const struct tomoyo_request_info *r, +static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, const struct tomoyo_acl_info *ptr) { const struct tomoyo_mkdev_acl *acl = diff --git a/security/tomoyo/group.c b/security/tomoyo/group.c index 3f0a2abf65c..e94352ce723 100644 --- a/security/tomoyo/group.c +++ b/security/tomoyo/group.c @@ -80,24 +80,24 @@ int tomoyo_write_group(char *data, const bool is_delete, const u8 type) * @pathname: The name of pathname. * @group: Pointer to "struct tomoyo_path_group". * - * Returns true if @pathname matches pathnames in @group, false otherwise. + * Returns matched member's pathname if @pathname matches pathnames in @group, + * NULL otherwise. * * Caller holds tomoyo_read_lock(). */ -bool tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, - const struct tomoyo_group *group) +const struct tomoyo_path_info * +tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, + const struct tomoyo_group *group) { struct tomoyo_path_group *member; - bool matched = false; list_for_each_entry_rcu(member, &group->member_list, head.list) { if (member->head.is_deleted) continue; if (!tomoyo_path_matches_pattern(pathname, member->member_name)) continue; - matched = true; - break; + return member->member_name; } - return matched; + return NULL; } /** diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index cfeff871908..82bf8c2390b 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -60,7 +60,7 @@ static int tomoyo_audit_mount_log(struct tomoyo_request_info *r) flags); } -static bool tomoyo_check_mount_acl(const struct tomoyo_request_info *r, +static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r, const struct tomoyo_acl_info *ptr) { const struct tomoyo_mount_acl *acl = -- cgit v1.2.3-70-g09d2