From: Tetsuo Handa on 10 Jun 2010 08:10 This patch allows users to check caller task's UID/GID etc. for each request. For example, allow_read /tmp/file if task.uid=0 will allow opening /tmp/file for reading only if the caller task's UID is 0. Signed-off-by: Tetsuo Handa <penguin-kernel(a)I-love.SAKURA.ne.jp> --- security/tomoyo/Makefile | 2 security/tomoyo/common.c | 199 ++++++++++++++++++++---- security/tomoyo/common.h | 98 +++++++++++ security/tomoyo/condition.c | 364 ++++++++++++++++++++++++++++++++++++++++++++ security/tomoyo/domain.c | 17 +- security/tomoyo/file.c | 62 +++++-- security/tomoyo/gc.c | 43 +++++ security/tomoyo/memory.c | 4 security/tomoyo/mount.c | 13 + 9 files changed, 733 insertions(+), 69 deletions(-) --- security-testing-2.6.orig/security/tomoyo/Makefile +++ security-testing-2.6/security/tomoyo/Makefile @@ -1 +1 @@ -obj-y = common.o domain.o file.o gc.o load_policy.o memory.o mount.o number_group.o path_group.o realpath.o securityfs_if.o tomoyo.o util.o +obj-y = condition.o common.o domain.o file.o gc.o load_policy.o memory.o mount.o number_group.o path_group.o realpath.o securityfs_if.o tomoyo.o util.o --- security-testing-2.6.orig/security/tomoyo/common.c +++ security-testing-2.6/security/tomoyo/common.c @@ -85,7 +85,7 @@ static const char *tomoyo_yesno(const un * Returns true on success, false otherwise. */ static bool tomoyo_print_name_union(struct tomoyo_io_buffer *head, - const struct tomoyo_name_union *ptr) + const struct tomoyo_name_union *ptr) { int pos = head->read_avail; if (pos && head->read_buf[pos - 1] == ' ') @@ -97,25 +97,27 @@ static bool tomoyo_print_name_union(stru } /** - * tomoyo_print_number_union - Print a tomoyo_number_union. + * tomoyo_print_number_union_common - Print a tomoyo_number_union. * * @head: Pointer to "struct tomoyo_io_buffer". * @ptr: Pointer to "struct tomoyo_number_union". + * @need_space: True if a space character is needed. * * Returns true on success, false otherwise. */ -bool tomoyo_print_number_union(struct tomoyo_io_buffer *head, - const struct tomoyo_number_union *ptr) +static bool tomoyo_print_number_union_common(struct tomoyo_io_buffer *head, + const struct tomoyo_number_union *ptr, + const bool need_space) { unsigned long min; unsigned long max; u8 min_type; u8 max_type; - if (!tomoyo_io_printf(head, " ")) + if (need_space && !tomoyo_io_printf(head, " ")) return false; if (ptr->is_group) return tomoyo_io_printf(head, "@%s", - ptr->group->group_name->name); + ptr->group->group_name->name); min_type = ptr->min_type; max_type = ptr->max_type; min = ptr->values[0]; @@ -147,6 +149,35 @@ bool tomoyo_print_number_union(struct to } /** + * tomoyo_print_number_union - Print a tomoyo_number_union. + * + * @head: Pointer to "struct tomoyo_io_buffer". + * @ptr: Pointer to "struct tomoyo_number_union". + * + * Returns true on success, false otherwise. + */ +bool tomoyo_print_number_union(struct tomoyo_io_buffer *head, + const struct tomoyo_number_union *ptr) +{ + return tomoyo_print_number_union_common(head, ptr, true); +} + +/** + * tomoyo_print_number_union_nospace - Print a tomoyo_number_union without a space character. + * + * @head: Pointer to "struct tomoyo_io_buffer". + * @ptr: Pointer to "struct tomoyo_number_union". + * + * Returns true on success, false otherwise. + */ +static bool tomoyo_print_number_union_nospace(struct tomoyo_io_buffer *head, + const struct tomoyo_number_union + *ptr) +{ + return tomoyo_print_number_union_common(head, ptr, false); +} + +/** * tomoyo_io_printf - Transactional printf() to "struct tomoyo_io_buffer" structure. * * @head: Pointer to "struct tomoyo_io_buffer". @@ -729,11 +760,39 @@ static int tomoyo_delete_domain(char *do */ static int tomoyo_write_domain_policy2(char *data, struct tomoyo_domain_info *domain, + struct tomoyo_condition *cond, const bool is_delete) { if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_MOUNT)) - return tomoyo_write_mount_policy(data, domain, is_delete); - return tomoyo_write_file_policy(data, domain, is_delete); + return tomoyo_write_mount_policy(data, domain, cond, is_delete); + return tomoyo_write_file_policy(data, domain, cond, is_delete); +} + +/** + * tomoyo_find_condition_part - Find condition part from the statement. + * + * @data: String to parse. + * + * Returns pointer to the condition part if it was found in the statement, + * NULL otherwise. + */ +static char *tomoyo_find_condition_part(char *data) +{ + char *cp = strstr(data, " if "); + if (cp) { + while (1) { + char *cp2 = strstr(cp + 3, " if "); + if (!cp2) + break; + cp = cp2; + } + *cp++ = '\0'; + } else { + cp = strstr(data, " ; set "); + if (cp) + *cp++ = '\0'; + } + return cp; } /** @@ -752,6 +811,9 @@ static int tomoyo_write_domain_policy(st bool is_delete = false; bool is_select = false; unsigned int profile; + struct tomoyo_condition *cond = NULL; + char *cp; + int error; if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE)) is_delete = true; @@ -794,7 +856,82 @@ static int tomoyo_write_domain_policy(st domain->transition_failed = !is_delete; return 0; } - return tomoyo_write_domain_policy2(data, domain, is_delete); + cp = tomoyo_find_condition_part(data); + if (cp) { + cond = tomoyo_get_condition(cp); + if (!cond) + return -EINVAL; + } + error = tomoyo_write_domain_policy2(data, domain, cond, is_delete); + if (cond) + tomoyo_put_condition(cond); + return error; +} + +/** + * tomoyo_print_condition - Print condition part. + * + * @head: Pointer to "struct tomoyo_io_buffer". + * @cond: Pointer to "struct tomoyo_condition". May be NULL. + * + * Returns true on success, false otherwise. + */ +static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, + const struct tomoyo_condition *cond) +{ + const struct tomoyo_condition_element *condp; + const struct tomoyo_number_union *numbers_p; + u16 condc; + u16 i; + char buffer[32]; + if (!cond) + goto no_condition; + condc = cond->condc; + condp = (const struct tomoyo_condition_element *) (cond + 1); + numbers_p = (const struct tomoyo_number_union *) (condp + condc); + memset(buffer, 0, sizeof(buffer)); + if (condc && !tomoyo_io_printf(head, "%s", " if")) + goto out; + for (i = 0; i < condc; i++) { + const u8 match = condp->equals; + const u8 left = condp->left; + const u8 right = condp->right; + condp++; + switch (left) { + case TOMOYO_NUMBER_UNION: + if (!tomoyo_print_number_union(head, numbers_p++)) + goto out; + break; + default: + if (left >= TOMOYO_MAX_CONDITION_KEYWORD) + goto out; + if (!tomoyo_io_printf(head, " %s", + tomoyo_condition_keyword[left])) + goto out; + break; + } + if (!tomoyo_io_printf(head, "%s", match ? "=" : "!=")) + goto out; + switch (right) { + case TOMOYO_NUMBER_UNION: + if (!tomoyo_print_number_union_nospace(head, + numbers_p++)) + goto out; + break; + default: + if (right >= TOMOYO_MAX_CONDITION_KEYWORD) + goto out; + if (!tomoyo_io_printf(head, "%s", + tomoyo_condition_keyword[right])) + goto out; + break; + } + } + no_condition: + if (tomoyo_io_printf(head, "\n")) + return true; + out: + return false; } /** @@ -802,11 +939,13 @@ static int tomoyo_write_domain_policy(st * * @head: Pointer to "struct tomoyo_io_buffer". * @ptr: Pointer to "struct tomoyo_path_acl". + * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. * * Returns true on success, false otherwise. */ static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head, - struct tomoyo_path_acl *ptr) + struct tomoyo_path_acl *ptr, + const struct tomoyo_condition *cond) { int pos; u8 bit; @@ -823,7 +962,7 @@ static bool tomoyo_print_path_acl(struct if (!tomoyo_io_printf(head, "allow_%s ", tomoyo_path2keyword(bit)) || !tomoyo_print_name_union(head, &ptr->name) || - !tomoyo_io_printf(head, "\n")) + !tomoyo_print_condition(head, cond)) goto out; } head->read_bit = 0; @@ -839,11 +978,13 @@ static bool tomoyo_print_path_acl(struct * * @head: Pointer to "struct tomoyo_io_buffer". * @ptr: Pointer to "struct tomoyo_path2_acl". + * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. * * Returns true on success, false otherwise. */ static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head, - struct tomoyo_path2_acl *ptr) + struct tomoyo_path2_acl *ptr, + const struct tomoyo_condition *cond) { int pos; const u8 perm = ptr->perm; @@ -857,7 +998,7 @@ static bool tomoyo_print_path2_acl(struc tomoyo_path22keyword(bit)) || !tomoyo_print_name_union(head, &ptr->name1) || !tomoyo_print_name_union(head, &ptr->name2) || - !tomoyo_io_printf(head, "\n")) + !tomoyo_print_condition(head, cond)) goto out; } head->read_bit = 0; @@ -873,11 +1014,13 @@ static bool tomoyo_print_path2_acl(struc * * @head: Pointer to "struct tomoyo_io_buffer". * @ptr: Pointer to "struct tomoyo_path_number_acl". + * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. * * Returns true on success, false otherwise. */ static bool tomoyo_print_path_number_acl(struct tomoyo_io_buffer *head, - struct tomoyo_path_number_acl *ptr) + struct tomoyo_path_number_acl *ptr, + const struct tomoyo_condition *cond) { int pos; u8 bit; @@ -891,7 +1034,7 @@ static bool tomoyo_print_path_number_acl tomoyo_path_number2keyword(bit)) || !tomoyo_print_name_union(head, &ptr->name) || !tomoyo_print_number_union(head, &ptr->number) || - !tomoyo_io_printf(head, "\n")) + !tomoyo_print_condition(head, cond)) goto out; } head->read_bit = 0; @@ -907,11 +1050,13 @@ static bool tomoyo_print_path_number_acl * * @head: Pointer to "struct tomoyo_io_buffer". * @ptr: Pointer to "struct tomoyo_path_number3_acl". + * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. * * Returns true on success, false otherwise. */ static bool tomoyo_print_path_number3_acl(struct tomoyo_io_buffer *head, - struct tomoyo_path_number3_acl *ptr) + struct tomoyo_path_number3_acl *ptr, + const struct tomoyo_condition *cond) { int pos; u8 bit; @@ -927,7 +1072,7 @@ static bool tomoyo_print_path_number3_ac !tomoyo_print_number_union(head, &ptr->mode) || !tomoyo_print_number_union(head, &ptr->major) || !tomoyo_print_number_union(head, &ptr->minor) || - !tomoyo_io_printf(head, "\n")) + !tomoyo_print_condition(head, cond)) goto out; } head->read_bit = 0; @@ -943,11 +1088,13 @@ static bool tomoyo_print_path_number3_ac * * @head: Pointer to "struct tomoyo_io_buffer". * @ptr: Pointer to "struct tomoyo_mount_acl". + * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. * * Returns true on success, false otherwise. */ static bool tomoyo_print_mount_acl(struct tomoyo_io_buffer *head, - struct tomoyo_mount_acl *ptr) + struct tomoyo_mount_acl *ptr, + const struct tomoyo_condition *cond) { const int pos = head->read_avail; if (ptr->is_deleted) @@ -957,7 +1104,7 @@ static bool tomoyo_print_mount_acl(struc !tomoyo_print_name_union(head, &ptr->dir_name) || !tomoyo_print_name_union(head, &ptr->fs_type) || !tomoyo_print_number_union(head, &ptr->flags) || - !tomoyo_io_printf(head, "\n")) { + !tomoyo_print_condition(head, cond)) { head->read_avail = pos; return false; } @@ -975,34 +1122,35 @@ static bool tomoyo_print_mount_acl(struc static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, struct tomoyo_acl_info *ptr) { + const struct tomoyo_condition *cond = ptr->cond; const u8 acl_type = ptr->type; if (acl_type == TOMOYO_TYPE_PATH_ACL) { struct tomoyo_path_acl *acl = container_of(ptr, struct tomoyo_path_acl, head); - return tomoyo_print_path_acl(head, acl); + return tomoyo_print_path_acl(head, acl, cond); } if (acl_type == TOMOYO_TYPE_PATH2_ACL) { struct tomoyo_path2_acl *acl = container_of(ptr, struct tomoyo_path2_acl, head); - return tomoyo_print_path2_acl(head, acl); + return tomoyo_print_path2_acl(head, acl, cond); } if (acl_type == TOMOYO_TYPE_PATH_NUMBER_ACL) { struct tomoyo_path_number_acl *acl = container_of(ptr, struct tomoyo_path_number_acl, head); - return tomoyo_print_path_number_acl(head, acl); + return tomoyo_print_path_number_acl(head, acl, cond); } if (acl_type == TOMOYO_TYPE_PATH_NUMBER3_ACL) { struct tomoyo_path_number3_acl *acl = container_of(ptr, struct tomoyo_path_number3_acl, head); - return tomoyo_print_path_number3_acl(head, acl); + return tomoyo_print_path_number3_acl(head, acl, cond); } if (acl_type == TOMOYO_TYPE_MOUNT_ACL) { struct tomoyo_mount_acl *acl = container_of(ptr, struct tomoyo_mount_acl, head); - return tomoyo_print_mount_acl(head, acl); + return tomoyo_print_mount_acl(head, acl, cond); } BUG(); /* This must not happen. */ return false; @@ -1445,8 +1593,7 @@ int tomoyo_supervisor(struct tomoyo_requ vsnprintf(buffer, len - 1, fmt, args); va_end(args); tomoyo_normalize_line(buffer); - tomoyo_write_domain_policy2(buffer, r->domain, false); - kfree(buffer); + tomoyo_write_domain_policy2(buffer, r->domain, NULL, false); /* fall through */ case TOMOYO_CONFIG_PERMISSIVE: return 0; --- security-testing-2.6.orig/security/tomoyo/common.h +++ security-testing-2.6/security/tomoyo/common.h @@ -21,7 +21,7 @@ #include <linux/list.h> #include <linux/cred.h> #include <linux/poll.h> -struct linux_binprm; +#include <linux/binfmts.h> /********** Constants definitions. **********/ @@ -182,20 +182,65 @@ enum tomoyo_mac_category_index { TOMOYO_MAX_MAC_CATEGORY_INDEX }; +enum tomoyo_conditions_index { + TOMOYO_TASK_UID, /* current_uid() */ + TOMOYO_TASK_EUID, /* current_euid() */ + TOMOYO_TASK_SUID, /* current_suid() */ + TOMOYO_TASK_FSUID, /* current_fsuid() */ + TOMOYO_TASK_GID, /* current_gid() */ + TOMOYO_TASK_EGID, /* current_egid() */ + TOMOYO_TASK_SGID, /* current_sgid() */ + TOMOYO_TASK_FSGID, /* current_fsgid() */ + TOMOYO_TASK_PID, /* sys_getpid() */ + TOMOYO_TASK_PPID, /* sys_getppid() */ + TOMOYO_MAX_CONDITION_KEYWORD, + TOMOYO_NUMBER_UNION, +}; + #define TOMOYO_RETRY_REQUEST 1 /* Retry this request. */ /********** Structure definitions. **********/ +struct tomoyo_condition_element { + /* Left hand operand. */ + u8 left; + /* + * Right hand operand. A "struct tomoyo_number_union" for + * TOMOYO_NUMBER_UNION is attached to the tail of the array of this + * struct. + */ + u8 right; + /* Equation operator. true if equals or overlaps, false otherwise. */ + bool equals; +}; + +/* Structure for " if " part. */ +struct tomoyo_condition { + struct list_head list; + atomic_t users; + u32 size; + u16 condc; + u16 numbers_count; + /* + * struct tomoyo_condition_element condition[condc]; + * struct tomoyo_number_union values[numbers_count]; + */ +}; + +struct tomoyo_execve_entry; + /* * tomoyo_request_info is a structure which is used for holding * * (1) Domain information of current process. - * (2) How many retries are made for this request. - * (3) Profile number used for this request. - * (4) Access control mode of the profile. + * (2) Parameters specific to execve() request. NULL if not for execve(). + * (3) How many retries are made for this request. + * (4) Profile number used for this request. + * (5) Access control mode of the profile. */ struct tomoyo_request_info { struct tomoyo_domain_info *domain; + struct tomoyo_execve_entry *ee; u8 retry; u8 profile; u8 mode; /* One of tomoyo_mode_index . */ @@ -284,12 +329,21 @@ struct tomoyo_number_group_member { struct tomoyo_number_union number; }; +/* Structure for execve() operation. */ +struct tomoyo_execve_entry { + struct tomoyo_request_info r; + int reader_idx; + /* For temporary use. */ + char *tmp; /* Size is TOMOYO_EXEC_TMPSIZE bytes */ +}; + /* * tomoyo_acl_info is a structure which is used for holding * * (1) "list" which is linked to the ->acl_info_list of * "struct tomoyo_domain_info" - * (2) "type" which tells type of the entry (either + * (2) "cond" which tells optional conditions for this entry. Maybe NULL. + * (3) "type" which tells type of the entry (either * "struct tomoyo_path_acl" or "struct tomoyo_path2_acl"). * * Packing "struct tomoyo_acl_info" allows @@ -299,6 +353,7 @@ struct tomoyo_number_group_member { */ struct tomoyo_acl_info { struct list_head list; + struct tomoyo_condition *cond; u8 type; } __packed; @@ -697,6 +752,11 @@ struct tomoyo_profile { extern asmlinkage long sys_getpid(void); extern asmlinkage long sys_getppid(void); +bool tomoyo_condition(struct tomoyo_request_info *r, + const struct tomoyo_acl_info *acl); +u8 tomoyo_parse_ulong(unsigned long *result, char **str); +struct tomoyo_condition *tomoyo_get_condition(char * const condition); +void tomoyo_del_condition(struct tomoyo_condition *cond); /* Check whether the given string starts with the given keyword. */ bool tomoyo_str_starts(char **src, const char *find); /* Get tomoyo_realpath() of current process. */ @@ -817,11 +877,13 @@ int tomoyo_write_domain_keeper_policy(ch * "allow_link" entry in domain policy. */ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, + struct tomoyo_condition *cond, const bool is_delete); /* Create "allow_read" entry in exception policy. */ int tomoyo_write_globally_readable_policy(char *data, const bool is_delete); /* Create "allow_mount" entry in domain policy. */ int tomoyo_write_mount_policy(char *data, struct tomoyo_domain_info *domain, + struct tomoyo_condition *cond, const bool is_delete); /* Create "deny_rewrite" entry in exception policy. */ int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); @@ -932,6 +994,7 @@ extern struct list_head tomoyo_globally_ extern struct list_head tomoyo_pattern_list; extern struct list_head tomoyo_no_rewrite_list; extern struct list_head tomoyo_policy_manager_list; +extern struct list_head tomoyo_condition_list; extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; /* Lock for protecting policy. */ @@ -943,6 +1006,7 @@ extern bool tomoyo_policy_loaded; /* The kernel's domain. */ extern struct tomoyo_domain_info tomoyo_kernel_domain; +extern const char *tomoyo_condition_keyword[TOMOYO_MAX_CONDITION_KEYWORD]; extern unsigned int tomoyo_quota_for_query; extern unsigned int tomoyo_query_memory_size; @@ -989,6 +1053,12 @@ static inline bool tomoyo_is_invalid(con return c && (c <= ' ' || c >= 127); } +static inline void tomoyo_put_condition(struct tomoyo_condition *cond) +{ + if (cond) + atomic_dec(&cond->users); +} + static inline void tomoyo_put_name(const struct tomoyo_path_info *name) { if (name) { @@ -1010,6 +1080,14 @@ static inline void tomoyo_put_number_gro atomic_dec(&group->users); } +static inline void tomoyo_add_domain_acl(struct tomoyo_domain_info *domain, + struct tomoyo_acl_info *acl) +{ + if (acl->cond) + atomic_inc(&acl->cond->users); + list_add_tail_rcu(&acl->list, &domain->acl_info_list); +} + static inline struct tomoyo_domain_info *tomoyo_domain(void) { return current_cred()->security; @@ -1024,7 +1102,7 @@ static inline struct tomoyo_domain_info static inline bool tomoyo_is_same_acl_head(const struct tomoyo_acl_info *p1, const struct tomoyo_acl_info *p2) { - return p1->type == p2->type; + return p1->type == p2->type && p1->cond == p2->cond; } static inline bool tomoyo_is_same_name_union @@ -1114,6 +1192,14 @@ static inline bool tomoyo_is_same_aggreg p1->aggregated_name == p2->aggregated_name; } +static inline bool tomoyo_is_same_condition(const struct tomoyo_condition *p1, + const struct tomoyo_condition *p2) +{ + return p1->size == p2->size && p1->condc == p2->condc && + p1->numbers_count == p2->numbers_count && + !memcmp(p1 + 1, p2 + 1, p1->size - sizeof(*p1)); +} + static inline bool tomoyo_is_same_alias_entry (const struct tomoyo_alias_entry *p1, const struct tomoyo_alias_entry *p2) { --- /dev/null +++ security-testing-2.6/security/tomoyo/condition.c @@ -0,0 +1,364 @@ +/* + * security/tomoyo/condition.c + * + * Copyright (C) 2005-2010 NTT DATA CORPORATION + */ + +#include "common.h" +#include <linux/slab.h> + +/* The list for "struct tomoyo_condition". */ +LIST_HEAD(tomoyo_condition_list); + +const char *tomoyo_condition_keyword[TOMOYO_MAX_CONDITION_KEYWORD] = { + [TOMOYO_TASK_UID] = "task.uid", + [TOMOYO_TASK_EUID] = "task.euid", + [TOMOYO_TASK_SUID] = "task.suid", + [TOMOYO_TASK_FSUID] = "task.fsuid", + [TOMOYO_TASK_GID] = "task.gid", + [TOMOYO_TASK_EGID] = "task.egid", + [TOMOYO_TASK_SGID] = "task.sgid", + [TOMOYO_TASK_FSGID] = "task.fsgid", + [TOMOYO_TASK_PID] = "task.pid", + [TOMOYO_TASK_PPID] = "task.ppid", +}; + +/* #define DEBUG_CONDITION */ + +#ifdef DEBUG_CONDITION +#define dprintk printk +#else +#define dprintk(...) do { } while (0) +#endif + +/** + * tomoyo_get_condition - Parse condition part. + * + * @condition: Pointer to string to parse. + * + * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise. + */ +struct tomoyo_condition *tomoyo_get_condition(char * const condition) +{ + char *start = condition; + struct tomoyo_condition *entry = NULL; + struct tomoyo_condition *ptr; + struct tomoyo_condition_element *condp; + struct tomoyo_number_union *numbers_p; + u32 size; + bool found = false; + u16 condc = 0; + u16 numbers_count = 0; + char *end_of_string; + start = condition; + if (!strncmp(start, "if ", 3)) + start += 3; + else if (*start) + return NULL; + end_of_string = start + strlen(start); + while (1) { + u8 left; + u8 right; + char *word = start; + char *cp; + char *eq; + bool is_not = false; + if (!*word) + break; + cp = strchr(start, ' '); + if (cp) { + *cp = '\0'; + start = cp + 1; + } else { + start = ""; + } + dprintk(KERN_WARNING "%u: <%s>\n", __LINE__, word); + eq = strchr(word, '='); + if (!eq) + goto out; + if (eq > word && *(eq - 1) == '!') { + is_not = true; + eq--; + } + *eq = '\0'; + for (left = 0; left < TOMOYO_MAX_CONDITION_KEYWORD; left++) { + if (strcmp(word, tomoyo_condition_keyword[left])) + continue; + break; + } + dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, + word, left); + if (left == TOMOYO_MAX_CONDITION_KEYWORD) + numbers_count++; + *eq = is_not ? '!' : '='; + word = eq + 1; + if (is_not) + word++; + condc++; + dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, + word, left); + for (right = 0; right < TOMOYO_MAX_CONDITION_KEYWORD; right++) { + if (strcmp(word, tomoyo_condition_keyword[right])) + continue; + break; + } + dprintk(KERN_WARNING "%u: <%s> right=%u\n", __LINE__, + word, right); + if (right == TOMOYO_MAX_CONDITION_KEYWORD) + numbers_count++; + } + dprintk(KERN_DEBUG "%u: cond=%u numbers=%u\n", __LINE__, + condc, numbers_count); + size = sizeof(*entry) + + condc * sizeof(struct tomoyo_condition_element) + + numbers_count * sizeof(struct tomoyo_number_union); + entry = kzalloc(size, GFP_NOFS); + if (!entry) + return NULL; + INIT_LIST_HEAD(&entry->list); + entry->condc = condc; + entry->numbers_count = numbers_count; + condp = (struct tomoyo_condition_element *) (entry + 1); + numbers_p = (struct tomoyo_number_union *) (condp + condc); + for (start = condition; start < end_of_string; start++) + if (!*start) + *start = ' '; + start = condition; + if (!strncmp(start, "if ", 3)) + start += 3; + else if (*start) + goto out; + while (1) { + u8 left; + u8 right; + char *word = start; + char *cp; + char *eq; + bool is_not = false; + if (!*word) + break; + cp = strchr(start, ' '); + if (cp) { + *cp = '\0'; + start = cp + 1; + } else { + start = ""; + } + dprintk(KERN_WARNING "%u: <%s>\n", __LINE__, word); + eq = strchr(word, '='); + if (!eq) { + dprintk(KERN_WARNING "%u: No operator.\n", + __LINE__); + goto out; + } + if (eq > word && *(eq - 1) == '!') { + is_not = true; + eq--; + } + *eq = '\0'; + for (left = 0; left < TOMOYO_MAX_CONDITION_KEYWORD; left++) { + if (strcmp(word, tomoyo_condition_keyword[left])) + continue; + break; + } + dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, + word, left); + if (left == TOMOYO_MAX_CONDITION_KEYWORD) { + left = TOMOYO_NUMBER_UNION; + if (!tomoyo_parse_number_union(word, numbers_p)) + goto out; + if (numbers_p->is_group) + goto out; + numbers_p++; + numbers_count--; + } + *eq = is_not ? '!' : '='; + word = eq + 1; + if (is_not) + word++; + condc--; + dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, + word, left); + for (right = 0; right < TOMOYO_MAX_CONDITION_KEYWORD; right++) { + if (strcmp(word, tomoyo_condition_keyword[right])) + continue; + break; + } + if (right == TOMOYO_MAX_CONDITION_KEYWORD) { + right = TOMOYO_NUMBER_UNION; + if (!tomoyo_parse_number_union(word, numbers_p++)) + goto out; + numbers_count--; + } + condp->left = left; + condp->right = right; + condp->equals = !is_not; + dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n", + __LINE__, condp->left, condp->right, + condp->equals); + condp++; + } +#ifdef DEBUG_CONFITION + for (start = condition; start < end_of_string; start++) + if (!*start) + *start = ' '; + dprintk(KERN_DEBUG "%u: <%s> cond=%u numbers=%u\n", + __LINE__, condition, condc, numbers_count); + BUG_ON(numbers_count); + BUG_ON(condc); +#else + BUG_ON(numbers_count | condc); +#endif + entry->size = size; + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; + list_for_each_entry_rcu(ptr, &tomoyo_condition_list, list) { + if (!tomoyo_is_same_condition(ptr, entry)) + continue; + /* Same entry found. Share this entry. */ + atomic_inc(&ptr->users); + found = true; + break; + } + if (!found) { + if (tomoyo_memory_ok(entry)) { + atomic_set(&entry->users, 1); + list_add_rcu(&entry->list, &tomoyo_condition_list); + } else { + found = true; + ptr = NULL; + } + } + mutex_unlock(&tomoyo_policy_lock); + if (found) { + tomoyo_del_condition(entry); + kfree(entry); + entry = ptr; + } + return entry; + out: + dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__); + if (entry) { + tomoyo_del_condition(entry); + kfree(entry); + } + return NULL; +} + +/** + * tomoyo_condition - Check condition part. + * + * @r: Pointer to "struct tomoyo_request_info". + * @acl: Pointer to "struct tomoyo_acl_info". + * + * Returns true on success, false otherwise. + * + * Caller holds tomoyo_read_lock(). + */ +bool tomoyo_condition(struct tomoyo_request_info *r, + const struct tomoyo_acl_info *acl) +{ + u32 i; + unsigned long left_min = 0; + unsigned long left_max = 0; + unsigned long right_min = 0; + unsigned long right_max = 0; + const struct tomoyo_condition_element *condp; + const struct tomoyo_number_union *numbers_p; + u16 condc; + const struct tomoyo_condition *cond = acl->cond; + if (!cond) + return true; + condc = cond->condc; + condp = (struct tomoyo_condition_element *) (cond + 1); + numbers_p = (const struct tomoyo_number_union *) (condp + condc); + for (i = 0; i < condc; i++) { + const bool match = condp->equals; + const u8 left = condp->left; + const u8 right = condp->right; + u8 j; + condp++; + /* Check numeric or bit-op expressions. */ + for (j = 0; j < 2; j++) { + const u8 index = j ? right : left; + unsigned long value = 0; + switch (index) { + case TOMOYO_TASK_UID: + value = current_uid(); + break; + case TOMOYO_TASK_EUID: + value = current_euid(); + break; + case TOMOYO_TASK_SUID: + value = current_suid(); + break; + case TOMOYO_TASK_FSUID: + value = current_fsuid(); + break; + case TOMOYO_TASK_GID: + value = current_gid(); + break; + case TOMOYO_TASK_EGID: + value = current_egid(); + break; + case TOMOYO_TASK_SGID: + value = current_sgid(); + break; + case TOMOYO_TASK_FSGID: + value = current_fsgid(); + break; + case TOMOYO_TASK_PID: + value = sys_getpid(); + break; + case TOMOYO_TASK_PPID: + value = sys_getppid(); + break; + case TOMOYO_NUMBER_UNION: + /* Fetch values later. */ + break; + default: + goto out; + } + value = value; + if (j) { + right_max = value; + right_min = value; + } else { + left_max = value; + left_min = value; + } + } + if (left == TOMOYO_NUMBER_UNION) { + /* Fetch values now. */ + const struct tomoyo_number_union *ptr = numbers_p++; + left_min = ptr->values[0]; + left_max = ptr->values[1]; + } + if (right == TOMOYO_NUMBER_UNION) { + /* Fetch values now. */ + const struct tomoyo_number_union *ptr = numbers_p++; + if (ptr->is_group) { + if (tomoyo_number_matches_group(left_min, + left_max, + ptr->group) + == match) + continue; + } else { + if ((left_min <= ptr->values[1] && + left_max >= ptr->values[0]) == match) + continue; + } + goto out; + } + if (match) { + if (left_min <= right_max && left_max >= right_min) + continue; + } else { + if (left_min > right_max || left_max < right_min) + continue; + } + out: + return false; + } + return true; +} --- security-testing-2.6.orig/security/tomoyo/domain.c +++ security-testing-2.6/security/tomoyo/domain.c @@ -9,6 +9,7 @@ #include "common.h" #include <linux/binfmts.h> #include <linux/slab.h> +#include <linux/highmem.h> /* Variables definitions.*/ @@ -806,13 +807,12 @@ struct tomoyo_domain_info *tomoyo_find_o */ int tomoyo_find_next_domain(struct linux_binprm *bprm) { + char *tmp = kmalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); struct tomoyo_request_info r; - char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); struct tomoyo_domain_info *old_domain = tomoyo_domain(); struct tomoyo_domain_info *domain = NULL; const char *old_domain_name = old_domain->domainname->name; const char *original_name = bprm->filename; - u8 mode; bool is_enforce; int retval = -ENOMEM; bool need_kfree = false; @@ -820,13 +820,13 @@ int tomoyo_find_next_domain(struct linux struct tomoyo_path_info sn = { }; /* symlink name */ struct tomoyo_path_info ln; /* last name */ - ln.name = tomoyo_get_last_name(old_domain); - tomoyo_fill_path_info(&ln); - mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE); - is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); if (!tmp) - goto out; + return -ENOMEM; + tomoyo_init_request_info(&r, NULL, TOMOYO_TYPE_EXECUTE); + is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING); + ln.name = tomoyo_get_last_name(old_domain); + tomoyo_fill_path_info(&ln); retry: if (need_kfree) { kfree(rn.name); @@ -924,7 +924,8 @@ int tomoyo_find_next_domain(struct linux done: if (domain) goto out; - printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp); + printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", + tmp); if (is_enforce) retval = -EPERM; else --- security-testing-2.6.orig/security/tomoyo/file.c +++ security-testing-2.6/security/tomoyo/file.c @@ -221,9 +221,11 @@ static bool tomoyo_get_realpath(struct t static int tomoyo_update_path2_acl(const u8 type, const char *filename1, const char *filename2, struct tomoyo_domain_info *const domain, + struct tomoyo_condition *cond, const bool is_delete); static int tomoyo_update_path_acl(const u8 type, const char *filename, struct tomoyo_domain_info *const domain, + struct tomoyo_condition *cond, const bool is_delete); /* @@ -670,6 +672,7 @@ bool tomoyo_read_no_rewrite_policy(struc * @perm: Permission (between 1 to 7). * @filename: Filename. * @domain: Pointer to "struct tomoyo_domain_info". + * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. @@ -683,6 +686,7 @@ bool tomoyo_read_no_rewrite_policy(struc */ static int tomoyo_update_file_acl(u8 perm, const char *filename, struct tomoyo_domain_info * const domain, + struct tomoyo_condition *cond, const bool is_delete) { if (perm > 7 || !perm) { @@ -698,13 +702,13 @@ static int tomoyo_update_file_acl(u8 per return 0; if (perm & 4) tomoyo_update_path_acl(TOMOYO_TYPE_READ, filename, domain, - is_delete); + cond, is_delete); if (perm & 2) tomoyo_update_path_acl(TOMOYO_TYPE_WRITE, filename, domain, - is_delete); + cond, is_delete); if (perm & 1) tomoyo_update_path_acl(TOMOYO_TYPE_EXECUTE, filename, domain, - is_delete); + cond, is_delete); return 0; } @@ -719,7 +723,7 @@ static int tomoyo_update_file_acl(u8 per * * Caller holds tomoyo_read_lock(). */ -static int tomoyo_path_acl(const struct tomoyo_request_info *r, +static int tomoyo_path_acl(struct tomoyo_request_info *r, const struct tomoyo_path_info *filename, const u32 perm) { @@ -733,7 +737,8 @@ static int tomoyo_path_acl(const struct continue; acl = container_of(ptr, struct tomoyo_path_acl, head); if (!(acl->perm & perm) || - !tomoyo_compare_name_union(filename, &acl->name)) + !tomoyo_compare_name_union(filename, &acl->name) || + !tomoyo_condition(r, ptr)) continue; error = 0; break; @@ -803,6 +808,7 @@ static int tomoyo_file_perm(struct tomoy * @type: Type of operation. * @filename: Filename. * @domain: Pointer to "struct tomoyo_domain_info". + * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. @@ -811,6 +817,7 @@ static int tomoyo_file_perm(struct tomoy */ static int tomoyo_update_path_acl(const u8 type, const char *filename, struct tomoyo_domain_info *const domain, + struct tomoyo_condition *cond, const bool is_delete) { static const u16 tomoyo_rw_mask = @@ -819,6 +826,7 @@ static int tomoyo_update_path_acl(const struct tomoyo_acl_info *ptr; struct tomoyo_path_acl e = { .head.type = TOMOYO_TYPE_PATH_ACL, + .head.cond = cond, .perm = perm }; int error = is_delete ? -ENOENT : -ENOMEM; @@ -856,8 +864,7 @@ static int tomoyo_update_path_acl(const struct tomoyo_path_acl *entry = tomoyo_commit_ok(&e, sizeof(e)); if (entry) { - list_add_tail_rcu(&entry->head.list, - &domain->acl_info_list); + tomoyo_add_domain_acl(domain, &entry->head); error = 0; } } @@ -876,6 +883,7 @@ static int tomoyo_update_path_acl(const * @major: Device major number. * @minor: Device minor number. * @domain: Pointer to "struct tomoyo_domain_info". + * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. @@ -886,12 +894,14 @@ static inline int tomoyo_update_path_num char *major, char *minor, struct tomoyo_domain_info * const domain, + struct tomoyo_condition *cond, const bool is_delete) { const u8 perm = 1 << type; struct tomoyo_acl_info *ptr; struct tomoyo_path_number3_acl e = { .head.type = TOMOYO_TYPE_PATH_NUMBER3_ACL, + .head.cond = cond, .perm = perm }; int error = is_delete ? -ENOENT : -ENOMEM; @@ -918,8 +928,7 @@ static inline int tomoyo_update_path_num struct tomoyo_path_number3_acl *entry = tomoyo_commit_ok(&e, sizeof(e)); if (entry) { - list_add_tail_rcu(&entry->head.list, - &domain->acl_info_list); + tomoyo_add_domain_acl(domain, &entry->head); error = 0; } } @@ -939,6 +948,7 @@ static inline int tomoyo_update_path_num * @filename1: First filename. * @filename2: Second filename. * @domain: Pointer to "struct tomoyo_domain_info". + * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. @@ -948,11 +958,13 @@ static inline int tomoyo_update_path_num static int tomoyo_update_path2_acl(const u8 type, const char *filename1, const char *filename2, struct tomoyo_domain_info *const domain, + struct tomoyo_condition *cond, const bool is_delete) { const u8 perm = 1 << type; struct tomoyo_path2_acl e = { .head.type = TOMOYO_TYPE_PATH2_ACL, + .head.cond = cond, .perm = perm }; struct tomoyo_acl_info *ptr; @@ -981,8 +993,7 @@ static int tomoyo_update_path2_acl(const struct tomoyo_path2_acl *entry = tomoyo_commit_ok(&e, sizeof(e)); if (entry) { - list_add_tail_rcu(&entry->head.list, - &domain->acl_info_list); + tomoyo_add_domain_acl(domain, &entry->head); error = 0; } } @@ -1031,6 +1042,8 @@ static int tomoyo_path_number3_acl(struc continue; if (!tomoyo_compare_name_union(filename, &acl->name)) continue; + if (!tomoyo_condition(r, ptr)) + continue; error = 0; break; } @@ -1049,7 +1062,7 @@ static int tomoyo_path_number3_acl(struc * * Caller holds tomoyo_read_lock(). */ -static int tomoyo_path2_acl(const struct tomoyo_request_info *r, const u8 type, +static int tomoyo_path2_acl(struct tomoyo_request_info *r, const u8 type, const struct tomoyo_path_info *filename1, const struct tomoyo_path_info *filename2) { @@ -1069,6 +1082,8 @@ static int tomoyo_path2_acl(const struct continue; if (!tomoyo_compare_name_union(filename2, &acl->name2)) continue; + if (!tomoyo_condition(r, ptr)) + continue; error = 0; break; } @@ -1149,7 +1164,8 @@ static int tomoyo_path_number_acl(struct head); if (!(acl->perm & perm) || !tomoyo_compare_number_union(number, &acl->number) || - !tomoyo_compare_name_union(filename, &acl->name)) + !tomoyo_compare_name_union(filename, &acl->name) || + !tomoyo_condition(r, ptr)) continue; error = 0; break; @@ -1164,6 +1180,7 @@ static int tomoyo_path_number_acl(struct * @filename: Filename. * @number: Number. * @domain: Pointer to "struct tomoyo_domain_info". + * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. @@ -1173,12 +1190,14 @@ static inline int tomoyo_update_path_num char *number, struct tomoyo_domain_info * const domain, + struct tomoyo_condition *cond, const bool is_delete) { const u8 perm = 1 << type; struct tomoyo_acl_info *ptr; struct tomoyo_path_number_acl e = { .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, + .head.cond = cond, .perm = perm }; int error = is_delete ? -ENOENT : -ENOMEM; @@ -1206,8 +1225,7 @@ static inline int tomoyo_update_path_num struct tomoyo_path_number_acl *entry = tomoyo_commit_ok(&e, sizeof(e)); if (entry) { - list_add_tail_rcu(&entry->head.list, - &domain->acl_info_list); + tomoyo_add_domain_acl(domain, &entry->head); error = 0; } } @@ -1572,6 +1590,7 @@ int tomoyo_path2_perm(const u8 operation * * @data: String to parse. * @domain: Pointer to "struct tomoyo_domain_info". + * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. @@ -1579,6 +1598,7 @@ int tomoyo_path2_perm(const u8 operation * Caller holds tomoyo_read_lock(). */ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, + struct tomoyo_condition *cond, const bool is_delete) { char *w[5]; @@ -1589,14 +1609,15 @@ int tomoyo_write_file_policy(char *data, unsigned int perm; if (sscanf(w[0], "%u", &perm) == 1) return tomoyo_update_file_acl((u8) perm, w[1], domain, - is_delete); + cond, is_delete); goto out; } w[0] += 6; for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { if (strcmp(w[0], tomoyo_path_keyword[type])) continue; - return tomoyo_update_path_acl(type, w[1], domain, is_delete); + return tomoyo_update_path_acl(type, w[1], domain, cond, + is_delete); } if (!w[2][0]) goto out; @@ -1604,13 +1625,13 @@ int tomoyo_write_file_policy(char *data, if (strcmp(w[0], tomoyo_path2_keyword[type])) continue; return tomoyo_update_path2_acl(type, w[1], w[2], domain, - is_delete); + cond, is_delete); } for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) { if (strcmp(w[0], tomoyo_path_number_keyword[type])) continue; return tomoyo_update_path_number_acl(type, w[1], w[2], domain, - is_delete); + cond, is_delete); } if (!w[3][0] || !w[4][0]) goto out; @@ -1618,7 +1639,8 @@ int tomoyo_write_file_policy(char *data, if (strcmp(w[0], tomoyo_path_number3_keyword[type])) continue; return tomoyo_update_path_number3_acl(type, w[1], w[2], w[3], - w[4], domain, is_delete); + w[4], domain, cond, + is_delete); } out: return -EINVAL; --- security-testing-2.6.orig/security/tomoyo/gc.c +++ security-testing-2.6/security/tomoyo/gc.c @@ -24,6 +24,7 @@ enum tomoyo_gc_id { TOMOYO_ID_PATTERN, TOMOYO_ID_NO_REWRITE, TOMOYO_ID_MANAGER, + TOMOYO_ID_CONDITION, TOMOYO_ID_NAME, TOMOYO_ID_ACL, TOMOYO_ID_DOMAIN @@ -97,6 +98,7 @@ static void tomoyo_del_manager(struct to static void tomoyo_del_acl(struct tomoyo_acl_info *acl) { + tomoyo_put_condition(acl->cond); switch (acl->type) { case TOMOYO_TYPE_PATH_ACL: { @@ -183,6 +185,23 @@ static bool tomoyo_del_domain(struct tom return true; } +/** + * tomoyo_del_condition - Delete members in "struct tomoyo_condition". + * + * @cond: Pointer to "struct tomoyo_condition". + */ +void tomoyo_del_condition(struct tomoyo_condition *cond) +{ + const u16 condc = cond->condc; + const u16 numbers_count = cond->numbers_count; + unsigned int i; + const struct tomoyo_condition_element *condp + = (const struct tomoyo_condition_element *) (cond + 1); + struct tomoyo_number_union *numbers_p + = (struct tomoyo_number_union *) (condp + condc); + for (i = 0; i < numbers_count; i++) + tomoyo_put_number_union(numbers_p++); +} static void tomoyo_del_name(const struct tomoyo_name_entry *ptr) { @@ -335,8 +354,14 @@ static void tomoyo_collect_entry(void) head)->perm) continue; break; + case TOMOYO_TYPE_MOUNT_ACL: + if (!container_of(acl, + struct tomoyo_mount_acl, + head)->is_deleted) + continue; + break; default: - continue; + continue; } if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl)) list_del_rcu(&acl->list); @@ -357,6 +382,17 @@ static void tomoyo_collect_entry(void) } } { + struct tomoyo_condition *ptr; + list_for_each_entry_rcu(ptr, &tomoyo_condition_list, list) { + if (atomic_read(&ptr->users)) + continue; + if (tomoyo_add_to_gc(TOMOYO_ID_CONDITION, ptr)) + list_del_rcu(&ptr->list); + else + break; + } + } + { int i; for (i = 0; i < TOMOYO_MAX_HASH; i++) { struct tomoyo_name_entry *ptr; @@ -453,6 +489,11 @@ static void tomoyo_kfree_entry(void) case TOMOYO_ID_MANAGER: tomoyo_del_manager(p->element); break; + case TOMOYO_ID_CONDITION: + tomoyo_del_condition(container_of(p->element, struct + tomoyo_condition, + list)); + break; case TOMOYO_ID_NAME: tomoyo_del_name(p->element); break; --- security-testing-2.6.orig/security/tomoyo/memory.c +++ security-testing-2.6/security/tomoyo/memory.c @@ -49,10 +49,8 @@ bool tomoyo_memory_ok(void *ptr) atomic_add(s, &tomoyo_policy_memory_size); if (ptr && (!tomoyo_quota_for_policy || atomic_read(&tomoyo_policy_memory_size) - <= tomoyo_quota_for_policy)) { - memset(ptr, 0, s); + <= tomoyo_quota_for_policy)) return true; - } atomic_sub(s, &tomoyo_policy_memory_size); tomoyo_warn_oom(__func__); return false; --- security-testing-2.6.orig/security/tomoyo/mount.c +++ security-testing-2.6/security/tomoyo/mount.c @@ -122,7 +122,8 @@ static int tomoyo_mount_acl2(struct tomo !tomoyo_compare_name_union(&rtype, &acl->fs_type) || !tomoyo_compare_name_union(&rdir, &acl->dir_name) || (need_dev && - !tomoyo_compare_name_union(&rdev, &acl->dev_name))) + !tomoyo_compare_name_union(&rdev, &acl->dev_name)) || + !tomoyo_condition(r, ptr)) continue; error = 0; break; @@ -264,15 +265,20 @@ int tomoyo_mount_permission(char *dev_na * * @data: String to parse. * @domain: Pointer to "struct tomoyo_domain_info". + * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. */ int tomoyo_write_mount_policy(char *data, struct tomoyo_domain_info *domain, + struct tomoyo_condition *cond, const bool is_delete) { struct tomoyo_acl_info *ptr; - struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; + struct tomoyo_mount_acl e = { + .head.type = TOMOYO_TYPE_MOUNT_ACL, + .head.cond = cond + }; int error = is_delete ? -ENOENT : -ENOMEM; char *w[4]; if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[3][0]) @@ -297,8 +303,7 @@ int tomoyo_write_mount_policy(char *data struct tomoyo_mount_acl *entry = tomoyo_commit_ok(&e, sizeof(e)); if (entry) { - list_add_tail_rcu(&entry->head.list, - &domain->acl_info_list); + tomoyo_add_domain_acl(domain, &entry->head); error = 0; } } -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo(a)vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
|
Pages: 1 Prev: [PATCH 0/4] TOMOYO: Add conditional ACL support. Next: jump label v9: x86 support |