From 2106ccd972dcd9fda7df9b181505fac1741b3508 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 17 May 2010 10:10:31 +0900 Subject: TOMOYO: Add mount restriction. mount(2) has three string and one numeric parameters. Split mount restriction code from security/tomoyo/file.c . Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/mount.c | 366 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 366 insertions(+) create mode 100644 security/tomoyo/mount.c (limited to 'security/tomoyo/mount.c') diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c new file mode 100644 index 000000000000..507be09e93a9 --- /dev/null +++ b/security/tomoyo/mount.c @@ -0,0 +1,366 @@ +/* + * security/tomoyo/mount.c + * + * Copyright (C) 2005-2010 NTT DATA CORPORATION + */ + +#include +#include "common.h" + +/* Keywords for mount restrictions. */ + +/* Allow to call 'mount --bind /source_dir /dest_dir' */ +#define TOMOYO_MOUNT_BIND_KEYWORD "--bind" +/* Allow to call 'mount --move /old_dir /new_dir ' */ +#define TOMOYO_MOUNT_MOVE_KEYWORD "--move" +/* Allow to call 'mount -o remount /dir ' */ +#define TOMOYO_MOUNT_REMOUNT_KEYWORD "--remount" +/* Allow to call 'mount --make-unbindable /dir' */ +#define TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD "--make-unbindable" +/* Allow to call 'mount --make-private /dir' */ +#define TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD "--make-private" +/* Allow to call 'mount --make-slave /dir' */ +#define TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD "--make-slave" +/* Allow to call 'mount --make-shared /dir' */ +#define TOMOYO_MOUNT_MAKE_SHARED_KEYWORD "--make-shared" + +/** + * tomoyo_encode2: Encode binary string to ascii string. + * + * @str: String in binary format. + * + * Returns pointer to @str in ascii format on success, NULL otherwise. + * + * This function uses kzalloc(), so caller must kfree() if this function + * didn't return NULL. + */ +static char *tomoyo_encode2(const char *str) +{ + int len = 0; + const char *p = str; + char *cp; + char *cp0; + if (!p) + return NULL; + while (*p) { + const unsigned char c = *p++; + if (c == '\\') + len += 2; + else if (c > ' ' && c < 127) + len++; + else + len += 4; + } + len++; + /* Reserve space for appending "/". */ + cp = kzalloc(len + 10, GFP_NOFS); + if (!cp) + return NULL; + cp0 = cp; + p = str; + while (*p) { + const unsigned char c = *p++; + if (c == '\\') { + *cp++ = '\\'; + *cp++ = '\\'; + } else if (c > ' ' && c < 127) { + *cp++ = c; + } else { + *cp++ = '\\'; + *cp++ = (c >> 6) + '0'; + *cp++ = ((c >> 3) & 7) + '0'; + *cp++ = (c & 7) + '0'; + } + } + return cp0; +} + +/** + * tomoyo_mount_acl2 - Check permission for mount() operation. + * + * @r: Pointer to "struct tomoyo_request_info". + * @dev_name: Name of device file. + * @dir: Pointer to "struct path". + * @type: Name of filesystem type. + * @flags: Mount options. + * + * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). + */ +static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name, + struct path *dir, char *type, unsigned long flags) +{ + struct path path; + struct tomoyo_acl_info *ptr; + struct file_system_type *fstype = NULL; + const char *requested_type = NULL; + const char *requested_dir_name = NULL; + const char *requested_dev_name = NULL; + struct tomoyo_path_info rtype; + struct tomoyo_path_info rdev; + struct tomoyo_path_info rdir; + int need_dev = 0; + int error = -ENOMEM; + + /* Get fstype. */ + requested_type = tomoyo_encode2(type); + if (!requested_type) + goto out; + rtype.name = requested_type; + tomoyo_fill_path_info(&rtype); + + /* Get mount point. */ + requested_dir_name = tomoyo_realpath_from_path(dir); + if (!requested_dir_name) { + error = -ENOMEM; + goto out; + } + rdir.name = requested_dir_name; + tomoyo_fill_path_info(&rdir); + + /* Compare fs name. */ + if (!strcmp(type, TOMOYO_MOUNT_REMOUNT_KEYWORD)) { + /* dev_name is ignored. */ + } else if (!strcmp(type, TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD) || + !strcmp(type, TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD) || + !strcmp(type, TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD) || + !strcmp(type, TOMOYO_MOUNT_MAKE_SHARED_KEYWORD)) { + /* dev_name is ignored. */ + } else if (!strcmp(type, TOMOYO_MOUNT_BIND_KEYWORD) || + !strcmp(type, TOMOYO_MOUNT_MOVE_KEYWORD)) { + need_dev = -1; /* dev_name is a directory */ + } else { + fstype = get_fs_type(type); + if (!fstype) { + error = -ENODEV; + goto out; + } + if (fstype->fs_flags & FS_REQUIRES_DEV) + /* dev_name is a block device file. */ + need_dev = 1; + } + if (need_dev) { + /* Get mount point or device file. */ + if (kern_path(dev_name, LOOKUP_FOLLOW, &path)) { + error = -ENOENT; + goto out; + } + requested_dev_name = tomoyo_realpath_from_path(&path); + if (!requested_dev_name) { + error = -ENOENT; + goto out; + } + } else { + /* Map dev_name to "" if no dev_name given. */ + if (!dev_name) + dev_name = ""; + requested_dev_name = tomoyo_encode2(dev_name); + if (!requested_dev_name) { + error = -ENOMEM; + goto out; + } + } + rdev.name = requested_dev_name; + tomoyo_fill_path_info(&rdev); + list_for_each_entry_rcu(ptr, &r->domain->acl_info_list, list) { + struct tomoyo_mount_acl *acl; + if (ptr->type != TOMOYO_TYPE_MOUNT_ACL) + continue; + acl = container_of(ptr, struct tomoyo_mount_acl, head); + if (acl->is_deleted || + !tomoyo_compare_number_union(flags, &acl->flags) || + !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))) + continue; + error = 0; + break; + } + if (error) { + const char *dev = tomoyo_get_file_pattern(&rdev)->name; + const char *dir = tomoyo_get_file_pattern(&rdir)->name; + int len = strlen(dev) + strlen(dir) + strlen(requested_type) + + 64; + char *buf = kzalloc(len, GFP_NOFS); + if (buf) { + snprintf(buf, len - 1, "%s %s %s 0x%lX", + dev, dir, requested_type, flags); + tomoyo_write_mount_policy(buf, r->domain, false); + kfree(buf); + } + } + out: + kfree(requested_dev_name); + kfree(requested_dir_name); + if (fstype) + put_filesystem(fstype); + kfree(requested_type); + return error; +} + +/** + * tomoyo_mount_acl - Check permission for mount() operation. + * + * @r: Pointer to "struct tomoyo_request_info". + * @dev_name: Name of device file. + * @dir: Pointer to "struct path". + * @type: Name of filesystem type. + * @flags: Mount options. + * + * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). + */ +static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, + struct path *dir, char *type, unsigned long flags) +{ + int error; + error = -EPERM; + if ((flags & MS_MGC_MSK) == MS_MGC_VAL) + flags &= ~MS_MGC_MSK; + switch (flags & (MS_REMOUNT | MS_MOVE | MS_BIND)) { + case MS_REMOUNT: + case MS_MOVE: + case MS_BIND: + case 0: + break; + default: + printk(KERN_WARNING "ERROR: " + "%s%s%sare given for single mount operation.\n", + flags & MS_REMOUNT ? "'remount' " : "", + flags & MS_MOVE ? "'move' " : "", + flags & MS_BIND ? "'bind' " : ""); + return -EINVAL; + } + switch (flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED)) { + case MS_UNBINDABLE: + case MS_PRIVATE: + case MS_SLAVE: + case MS_SHARED: + case 0: + break; + default: + printk(KERN_WARNING "ERROR: " + "%s%s%s%sare given for single mount operation.\n", + flags & MS_UNBINDABLE ? "'unbindable' " : "", + flags & MS_PRIVATE ? "'private' " : "", + flags & MS_SLAVE ? "'slave' " : "", + flags & MS_SHARED ? "'shared' " : ""); + return -EINVAL; + } + if (flags & MS_REMOUNT) + error = tomoyo_mount_acl(r, dev_name, dir, + TOMOYO_MOUNT_REMOUNT_KEYWORD, + flags & ~MS_REMOUNT); + else if (flags & MS_MOVE) + error = tomoyo_mount_acl(r, dev_name, dir, + TOMOYO_MOUNT_MOVE_KEYWORD, + flags & ~MS_MOVE); + else if (flags & MS_BIND) + error = tomoyo_mount_acl(r, dev_name, dir, + TOMOYO_MOUNT_BIND_KEYWORD, + flags & ~MS_BIND); + else if (flags & MS_UNBINDABLE) + error = tomoyo_mount_acl(r, dev_name, dir, + TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD, + flags & ~MS_UNBINDABLE); + else if (flags & MS_PRIVATE) + error = tomoyo_mount_acl(r, dev_name, dir, + TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD, + flags & ~MS_PRIVATE); + else if (flags & MS_SLAVE) + error = tomoyo_mount_acl(r, dev_name, dir, + TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD, + flags & ~MS_SLAVE); + else if (flags & MS_SHARED) + error = tomoyo_mount_acl(r, dev_name, dir, + TOMOYO_MOUNT_MAKE_SHARED_KEYWORD, + flags & ~MS_SHARED); + else + error = tomoyo_mount_acl2(r, dev_name, dir, type, flags); + if (r->mode != TOMOYO_CONFIG_ENFORCING) + error = 0; + return error; +} + +/** + * tomoyo_mount_permission - Check permission for mount() operation. + * + * @dev_name: Name of device file. + * @path: Pointer to "struct path". + * @type: Name of filesystem type. May be NULL. + * @flags: Mount options. + * @data_page: Optional data. May be NULL. + * + * Returns 0 on success, negative value otherwise. + */ +int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, + unsigned long flags, void *data_page) +{ + struct tomoyo_request_info r; + int error; + int idx; + + if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED) + return 0; + if (!type) + type = ""; + idx = tomoyo_read_lock(); + error = tomoyo_mount_acl(&r, dev_name, path, type, flags); + tomoyo_read_unlock(idx); + return error; +} + +/** + * tomoyo_write_mount_policy - Write "struct tomoyo_mount_acl" list. + * + * @data: String to parse. + * @domain: Pointer to "struct tomoyo_domain_info". + * @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, + const bool is_delete) +{ + struct tomoyo_acl_info *ptr; + struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; + int error = is_delete ? -ENOENT : -ENOMEM; + char *w[4]; + if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[3][0]) + return -EINVAL; + if (!tomoyo_parse_name_union(w[0], &e.dev_name) || + !tomoyo_parse_name_union(w[1], &e.dir_name) || + !tomoyo_parse_name_union(w[2], &e.fs_type) || + !tomoyo_parse_number_union(w[3], &e.flags)) + goto out; + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { + struct tomoyo_mount_acl *acl = + container_of(ptr, struct tomoyo_mount_acl, head); + if (!tomoyo_is_same_mount_acl(acl, &e)) + continue; + acl->is_deleted = is_delete; + error = 0; + break; + } + if (!is_delete && error) { + struct tomoyo_mount_acl *entry = + tomoyo_commit_ok(&e, sizeof(e)); + if (entry) { + list_add_tail_rcu(&entry->head.list, + &domain->acl_info_list); + error = 0; + } + } + mutex_unlock(&tomoyo_policy_lock); + out: + tomoyo_put_name_union(&e.dev_name); + tomoyo_put_name_union(&e.dir_name); + tomoyo_put_name_union(&e.fs_type); + tomoyo_put_number_union(&e.flags); + return error; +} -- cgit v1.2.3 From 17fcfbd9d45b57f38d40e31f9d28db53f4af5c88 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 17 May 2010 10:11:36 +0900 Subject: TOMOYO: Add interactive enforcing mode. Since the behavior of the system is restricted by policy, we may need to update policy when you update packages. We need to update policy in the following cases. * The pathname of files has changed. * The dependency of files has changed. * The access permissions required has increased. The ideal way to update policy is to rebuild from the scratch using learning mode. But it is not desirable to change from enforcing mode to other mode if the system has once entered in production state. Suppose MAC could support per-application enforcing mode, the MAC becomes useless if an application that is not running in enforcing mode was cracked. For example, the whole system becomes vulnerable if only HTTP server application is running in learning mode to rebuild policy for the application. So, in TOMOYO Linux, updating policy is done while the system is running in enforcing mode. This patch implements "interactive enforcing mode" which allows administrators to judge whether to accept policy violation in enforcing mode or not. A demo movie is available at http://www.youtube.com/watch?v=b9q1Jo25LPA . Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 426 ++++++++++++++++++++++++++++++++++++++++++++- security/tomoyo/common.h | 28 ++- security/tomoyo/domain.c | 47 +++-- security/tomoyo/file.c | 140 +++++++-------- security/tomoyo/mount.c | 24 ++- security/tomoyo/realpath.c | 19 +- 6 files changed, 564 insertions(+), 120 deletions(-) (limited to 'security/tomoyo/mount.c') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 0c6f9a5c37a5..ee46aaa3566f 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -74,6 +74,8 @@ static int tomoyo_read_control(struct file *file, char __user *buffer, /* Write operation for /sys/kernel/security/tomoyo/ interface. */ static int tomoyo_write_control(struct file *file, const char __user *buffer, const int buffer_len); +/* Check whether the domain has too many ACL entries to hold. */ +static bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); /** * tomoyo_parse_name_union - Parse a tomoyo_name_union. @@ -1031,7 +1033,7 @@ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain) * * Caller holds tomoyo_read_lock(). */ -bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) +static bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) { unsigned int count = 0; struct tomoyo_domain_info *domain = r->domain; @@ -1530,6 +1532,24 @@ static int tomoyo_delete_domain(char *domainname) return 0; } +/** + * tomoyo_write_domain_policy2 - Write domain policy. + * + * @head: Pointer to "struct tomoyo_io_buffer". + * + * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). + */ +static int tomoyo_write_domain_policy2(char *data, + struct tomoyo_domain_info *domain, + 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); +} + /** * tomoyo_write_domain_policy - Write domain policy. * @@ -1580,9 +1600,7 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) domain->ignore_global_allow_read = !is_delete; return 0; } - 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_domain_policy2(data, domain, is_delete); } /** @@ -2185,6 +2203,357 @@ void tomoyo_load_policy(const char *filename) } } +/** + * tomoyo_print_header - Get header line of audit log. + * + * @r: Pointer to "struct tomoyo_request_info". + * + * Returns string representation. + * + * This function uses kmalloc(), so caller must kfree() if this function + * didn't return NULL. + */ +static char *tomoyo_print_header(struct tomoyo_request_info *r) +{ + static const char *tomoyo_mode_4[4] = { + "disabled", "learning", "permissive", "enforcing" + }; + struct timeval tv; + const pid_t gpid = task_pid_nr(current); + static const int tomoyo_buffer_len = 4096; + char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); + if (!buffer) + return NULL; + do_gettimeofday(&tv); + snprintf(buffer, tomoyo_buffer_len - 1, + "#timestamp=%lu profile=%u mode=%s (global-pid=%u)" + " task={ pid=%u ppid=%u uid=%u gid=%u euid=%u" + " egid=%u suid=%u sgid=%u fsuid=%u fsgid=%u }", + tv.tv_sec, r->profile, tomoyo_mode_4[r->mode], gpid, + (pid_t) sys_getpid(), (pid_t) sys_getppid(), + current_uid(), current_gid(), current_euid(), + current_egid(), current_suid(), current_sgid(), + current_fsuid(), current_fsgid()); + return buffer; +} + +/** + * tomoyo_init_audit_log - Allocate buffer for audit logs. + * + * @len: Required size. + * @r: Pointer to "struct tomoyo_request_info". + * + * Returns pointer to allocated memory. + * + * The @len is updated to add the header lines' size on success. + * + * This function uses kzalloc(), so caller must kfree() if this function + * didn't return NULL. + */ +static char *tomoyo_init_audit_log(int *len, struct tomoyo_request_info *r) +{ + char *buf = NULL; + const char *header; + const char *domainname; + if (!r->domain) + r->domain = tomoyo_domain(); + domainname = r->domain->domainname->name; + header = tomoyo_print_header(r); + if (!header) + return NULL; + *len += strlen(domainname) + strlen(header) + 10; + buf = kzalloc(*len, GFP_NOFS); + if (buf) + snprintf(buf, (*len) - 1, "%s\n%s\n", header, domainname); + kfree(header); + return buf; +} + +/* Wait queue for tomoyo_query_list. */ +static DECLARE_WAIT_QUEUE_HEAD(tomoyo_query_wait); + +/* Lock for manipulating tomoyo_query_list. */ +static DEFINE_SPINLOCK(tomoyo_query_list_lock); + +/* Structure for query. */ +struct tomoyo_query_entry { + struct list_head list; + char *query; + int query_len; + unsigned int serial; + int timer; + int answer; +}; + +/* The list for "struct tomoyo_query_entry". */ +static LIST_HEAD(tomoyo_query_list); + +/* + * Number of "struct file" referring /sys/kernel/security/tomoyo/query + * interface. + */ +static atomic_t tomoyo_query_observers = ATOMIC_INIT(0); + +/** + * tomoyo_supervisor - Ask for the supervisor's decision. + * + * @r: Pointer to "struct tomoyo_request_info". + * @fmt: The printf()'s format string, followed by parameters. + * + * Returns 0 if the supervisor decided to permit the access request which + * violated the policy in enforcing mode, TOMOYO_RETRY_REQUEST if the + * supervisor decided to retry the access request which violated the policy in + * enforcing mode, 0 if it is not in enforcing mode, -EPERM otherwise. + */ +int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) +{ + va_list args; + int error = -EPERM; + int pos; + int len; + static unsigned int tomoyo_serial; + struct tomoyo_query_entry *tomoyo_query_entry = NULL; + bool quota_exceeded = false; + char *header; + switch (r->mode) { + char *buffer; + case TOMOYO_CONFIG_LEARNING: + if (!tomoyo_domain_quota_is_ok(r)) + return 0; + va_start(args, fmt); + len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4; + va_end(args); + buffer = kmalloc(len, GFP_NOFS); + if (!buffer) + return 0; + va_start(args, fmt); + vsnprintf(buffer, len - 1, fmt, args); + va_end(args); + tomoyo_normalize_line(buffer); + tomoyo_write_domain_policy2(buffer, r->domain, false); + kfree(buffer); + /* fall through */ + case TOMOYO_CONFIG_PERMISSIVE: + return 0; + } + if (!r->domain) + r->domain = tomoyo_domain(); + if (!atomic_read(&tomoyo_query_observers)) + return -EPERM; + va_start(args, fmt); + len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32; + va_end(args); + header = tomoyo_init_audit_log(&len, r); + if (!header) + goto out; + tomoyo_query_entry = kzalloc(sizeof(*tomoyo_query_entry), GFP_NOFS); + if (!tomoyo_query_entry) + goto out; + tomoyo_query_entry->query = kzalloc(len, GFP_NOFS); + if (!tomoyo_query_entry->query) + goto out; + len = ksize(tomoyo_query_entry->query); + INIT_LIST_HEAD(&tomoyo_query_entry->list); + spin_lock(&tomoyo_query_list_lock); + if (tomoyo_quota_for_query && tomoyo_query_memory_size + len + + sizeof(*tomoyo_query_entry) >= tomoyo_quota_for_query) { + quota_exceeded = true; + } else { + tomoyo_query_memory_size += len + sizeof(*tomoyo_query_entry); + tomoyo_query_entry->serial = tomoyo_serial++; + } + spin_unlock(&tomoyo_query_list_lock); + if (quota_exceeded) + goto out; + pos = snprintf(tomoyo_query_entry->query, len - 1, "Q%u-%hu\n%s", + tomoyo_query_entry->serial, r->retry, header); + kfree(header); + header = NULL; + va_start(args, fmt); + vsnprintf(tomoyo_query_entry->query + pos, len - 1 - pos, fmt, args); + tomoyo_query_entry->query_len = strlen(tomoyo_query_entry->query) + 1; + va_end(args); + spin_lock(&tomoyo_query_list_lock); + list_add_tail(&tomoyo_query_entry->list, &tomoyo_query_list); + spin_unlock(&tomoyo_query_list_lock); + /* Give 10 seconds for supervisor's opinion. */ + for (tomoyo_query_entry->timer = 0; + atomic_read(&tomoyo_query_observers) && tomoyo_query_entry->timer < 100; + tomoyo_query_entry->timer++) { + wake_up(&tomoyo_query_wait); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ / 10); + if (tomoyo_query_entry->answer) + break; + } + spin_lock(&tomoyo_query_list_lock); + list_del(&tomoyo_query_entry->list); + tomoyo_query_memory_size -= len + sizeof(*tomoyo_query_entry); + spin_unlock(&tomoyo_query_list_lock); + switch (tomoyo_query_entry->answer) { + case 3: /* Asked to retry by administrator. */ + error = TOMOYO_RETRY_REQUEST; + r->retry++; + break; + case 1: + /* Granted by administrator. */ + error = 0; + break; + case 0: + /* Timed out. */ + break; + default: + /* Rejected by administrator. */ + break; + } + out: + if (tomoyo_query_entry) + kfree(tomoyo_query_entry->query); + kfree(tomoyo_query_entry); + kfree(header); + return error; +} + +/** + * tomoyo_poll_query - poll() for /sys/kernel/security/tomoyo/query. + * + * @file: Pointer to "struct file". + * @wait: Pointer to "poll_table". + * + * Returns POLLIN | POLLRDNORM when ready to read, 0 otherwise. + * + * Waits for access requests which violated policy in enforcing mode. + */ +static int tomoyo_poll_query(struct file *file, poll_table *wait) +{ + struct list_head *tmp; + bool found = false; + u8 i; + for (i = 0; i < 2; i++) { + spin_lock(&tomoyo_query_list_lock); + list_for_each(tmp, &tomoyo_query_list) { + struct tomoyo_query_entry *ptr + = list_entry(tmp, struct tomoyo_query_entry, + list); + if (ptr->answer) + continue; + found = true; + break; + } + spin_unlock(&tomoyo_query_list_lock); + if (found) + return POLLIN | POLLRDNORM; + if (i) + break; + poll_wait(file, &tomoyo_query_wait, wait); + } + return 0; +} + +/** + * tomoyo_read_query - Read access requests which violated policy in enforcing mode. + * + * @head: Pointer to "struct tomoyo_io_buffer". + * + * Returns 0. + */ +static int tomoyo_read_query(struct tomoyo_io_buffer *head) +{ + struct list_head *tmp; + int pos = 0; + int len = 0; + char *buf; + if (head->read_avail) + return 0; + if (head->read_buf) { + kfree(head->read_buf); + head->read_buf = NULL; + head->readbuf_size = 0; + } + spin_lock(&tomoyo_query_list_lock); + list_for_each(tmp, &tomoyo_query_list) { + struct tomoyo_query_entry *ptr + = list_entry(tmp, struct tomoyo_query_entry, list); + if (ptr->answer) + continue; + if (pos++ != head->read_step) + continue; + len = ptr->query_len; + break; + } + spin_unlock(&tomoyo_query_list_lock); + if (!len) { + head->read_step = 0; + return 0; + } + buf = kzalloc(len, GFP_NOFS); + if (!buf) + return 0; + pos = 0; + spin_lock(&tomoyo_query_list_lock); + list_for_each(tmp, &tomoyo_query_list) { + struct tomoyo_query_entry *ptr + = list_entry(tmp, struct tomoyo_query_entry, list); + if (ptr->answer) + continue; + if (pos++ != head->read_step) + continue; + /* + * Some query can be skipped because tomoyo_query_list + * can change, but I don't care. + */ + if (len == ptr->query_len) + memmove(buf, ptr->query, len); + break; + } + spin_unlock(&tomoyo_query_list_lock); + if (buf[0]) { + head->read_avail = len; + head->readbuf_size = head->read_avail; + head->read_buf = buf; + head->read_step++; + } else { + kfree(buf); + } + return 0; +} + +/** + * tomoyo_write_answer - Write the supervisor's decision. + * + * @head: Pointer to "struct tomoyo_io_buffer". + * + * Returns 0 on success, -EINVAL otherwise. + */ +static int tomoyo_write_answer(struct tomoyo_io_buffer *head) +{ + char *data = head->write_buf; + struct list_head *tmp; + unsigned int serial; + unsigned int answer; + spin_lock(&tomoyo_query_list_lock); + list_for_each(tmp, &tomoyo_query_list) { + struct tomoyo_query_entry *ptr + = list_entry(tmp, struct tomoyo_query_entry, list); + ptr->timer = 0; + } + spin_unlock(&tomoyo_query_list_lock); + if (sscanf(data, "A%u=%u", &serial, &answer) != 2) + return -EINVAL; + spin_lock(&tomoyo_query_list_lock); + list_for_each(tmp, &tomoyo_query_list) { + struct tomoyo_query_entry *ptr + = list_entry(tmp, struct tomoyo_query_entry, list); + if (ptr->serial != serial) + continue; + if (!ptr->answer) + ptr->answer = answer; + break; + } + spin_unlock(&tomoyo_query_list_lock); + return 0; +} + /** * tomoyo_read_version: Get version. * @@ -2239,6 +2608,7 @@ static int tomoyo_open_control(const u8 type, struct file *file) if (!head) return -ENOMEM; mutex_init(&head->io_sem); + head->type = type; switch (type) { case TOMOYO_DOMAINPOLICY: /* /sys/kernel/security/tomoyo/domain_policy */ @@ -2280,6 +2650,11 @@ static int tomoyo_open_control(const u8 type, struct file *file) head->write = tomoyo_write_profile; head->read = tomoyo_read_profile; break; + case TOMOYO_QUERY: /* /sys/kernel/security/tomoyo/query */ + head->poll = tomoyo_poll_query; + head->write = tomoyo_write_answer; + head->read = tomoyo_read_query; + break; case TOMOYO_MANAGER: /* /sys/kernel/security/tomoyo/manager */ head->write = tomoyo_write_manager_policy; @@ -2292,7 +2667,9 @@ static int tomoyo_open_control(const u8 type, struct file *file) * for reading. */ head->read = NULL; - } else { + head->poll = NULL; + } else if (!head->poll) { + /* Don't allocate read_buf for poll() access. */ if (!head->readbuf_size) head->readbuf_size = 4096 * 2; head->read_buf = kzalloc(head->readbuf_size, GFP_NOFS); @@ -2316,7 +2693,8 @@ static int tomoyo_open_control(const u8 type, struct file *file) return -ENOMEM; } } - head->reader_idx = tomoyo_read_lock(); + if (type != TOMOYO_QUERY) + head->reader_idx = tomoyo_read_lock(); file->private_data = head; /* * Call the handler now if the file is @@ -2327,9 +2705,34 @@ static int tomoyo_open_control(const u8 type, struct file *file) */ if (type == TOMOYO_SELFDOMAIN) tomoyo_read_control(file, NULL, 0); + /* + * If the file is /sys/kernel/security/tomoyo/query , increment the + * observer counter. + * The obserber counter is used by tomoyo_supervisor() to see if + * there is some process monitoring /sys/kernel/security/tomoyo/query. + */ + else if (type == TOMOYO_QUERY) + atomic_inc(&tomoyo_query_observers); return 0; } +/** + * tomoyo_poll_control - poll() for /sys/kernel/security/tomoyo/ interface. + * + * @file: Pointer to "struct file". + * @wait: Pointer to "poll_table". + * + * Waits for read readiness. + * /sys/kernel/security/tomoyo/query is handled by /usr/sbin/tomoyo-queryd . + */ +int tomoyo_poll_control(struct file *file, poll_table *wait) +{ + struct tomoyo_io_buffer *head = file->private_data; + if (!head->poll) + return -ENOSYS; + return head->poll(file, wait); +} + /** * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface. * @@ -2443,7 +2846,14 @@ static int tomoyo_close_control(struct file *file) struct tomoyo_io_buffer *head = file->private_data; const bool is_write = !!head->write_buf; - tomoyo_read_unlock(head->reader_idx); + /* + * If the file is /sys/kernel/security/tomoyo/query , decrement the + * observer counter. + */ + if (head->type == TOMOYO_QUERY) + atomic_dec(&tomoyo_query_observers); + else + tomoyo_read_unlock(head->reader_idx); /* Release memory used for policy I/O. */ kfree(head->read_buf); head->read_buf = NULL; @@ -2562,6 +2972,8 @@ static int __init tomoyo_initerface_init(void) return 0; tomoyo_dir = securityfs_create_dir("tomoyo", NULL); + tomoyo_create_entry("query", 0600, tomoyo_dir, + TOMOYO_QUERY); tomoyo_create_entry("domain_policy", 0600, tomoyo_dir, TOMOYO_DOMAINPOLICY); tomoyo_create_entry("exception_policy", 0600, tomoyo_dir, diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 3d819b139165..dc5f98f52f61 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -20,6 +20,7 @@ #include #include #include +#include struct linux_binprm; /********** Constants definitions. **********/ @@ -156,9 +157,12 @@ enum tomoyo_securityfs_interface_index { TOMOYO_SELFDOMAIN, TOMOYO_VERSION, TOMOYO_PROFILE, + TOMOYO_QUERY, TOMOYO_MANAGER }; +#define TOMOYO_RETRY_REQUEST 1 /* Retry this request. */ + /********** Structure definitions. **********/ /* @@ -176,10 +180,14 @@ struct tomoyo_page_buffer { * tomoyo_request_info is a structure which is used for holding * * (1) Domain information of current process. - * (2) Access control mode of the profile. + * (2) How many retries are made for this request. + * (3) Profile number used for this request. + * (4) Access control mode of the profile. */ struct tomoyo_request_info { struct tomoyo_domain_info *domain; + u8 retry; + u8 profile; u8 mode; /* One of tomoyo_mode_index . */ }; @@ -484,6 +492,7 @@ struct tomoyo_mount_acl { struct tomoyo_io_buffer { int (*read) (struct tomoyo_io_buffer *); int (*write) (struct tomoyo_io_buffer *); + int (*poll) (struct file *file, poll_table *wait); /* Exclusive lock for this structure. */ struct mutex io_sem; /* Index returned by tomoyo_read_lock(). */ @@ -514,6 +523,8 @@ struct tomoyo_io_buffer { int write_avail; /* Size of write buffer. */ int writebuf_size; + /* Type of this interface. */ + u8 type; }; /* @@ -659,14 +670,15 @@ struct tomoyo_policy_manager_entry { /********** Function prototypes. **********/ +extern asmlinkage long sys_getpid(void); +extern asmlinkage long sys_getppid(void); + /* 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); /* 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); -/* Check whether the domain has too many ACL entries to hold. */ -bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); /* Transactional sprintf() for policy dump. */ bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); @@ -763,6 +775,8 @@ int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); int tomoyo_write_pattern_policy(char *data, const bool is_delete); /* Create "path_group" entry in exception policy. */ int tomoyo_write_path_group_policy(char *data, const bool is_delete); +int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) + __attribute__ ((format(printf, 2, 3))); /* Create "number_group" entry in exception policy. */ int tomoyo_write_number_group_policy(char *data, const bool is_delete); /* Find a domain by the given name. */ @@ -771,9 +785,6 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * domainname, const u8 profile); -/* Get patterned pathname. */ -const struct tomoyo_path_info * -tomoyo_get_file_pattern(const struct tomoyo_path_info *filename); /* Allocate memory for "struct tomoyo_path_group". */ struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name); @@ -807,6 +818,8 @@ char *tomoyo_realpath(const char *pathname); char *tomoyo_realpath_nofollow(const char *pathname); /* Same with tomoyo_realpath() except that the pathname is already solved. */ char *tomoyo_realpath_from_path(struct path *path); +/* Get patterned pathname. */ +const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename); /* Check memory quota. */ bool tomoyo_memory_ok(void *ptr); @@ -878,6 +891,9 @@ extern bool tomoyo_policy_loaded; /* The kernel's domain. */ extern struct tomoyo_domain_info tomoyo_kernel_domain; +extern unsigned int tomoyo_quota_for_query; +extern unsigned int tomoyo_query_memory_size; + /********** Inlined functions. **********/ static inline int tomoyo_read_lock(void) diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index afdf26128bfe..7e242d27da5a 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -678,6 +678,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * */ int tomoyo_find_next_domain(struct linux_binprm *bprm) { + struct tomoyo_request_info r; /* * This function assumes that the size of buffer returned by * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. @@ -693,11 +694,12 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE); const bool is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); int retval = -ENOMEM; - struct tomoyo_path_info r; /* real name */ - struct tomoyo_path_info s; /* symlink name */ - struct tomoyo_path_info l; /* last name */ + struct tomoyo_path_info rn; /* real name */ + struct tomoyo_path_info sn; /* symlink name */ + struct tomoyo_path_info ln; /* last name */ static bool initialized; + tomoyo_init_request_info(&r, NULL); if (!tmp) goto out; @@ -713,6 +715,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) initialized = true; } + retry: /* Get tomoyo_realpath of program. */ retval = -ENOENT; /* I hope tomoyo_realpath() won't fail with -ENOMEM. */ @@ -724,37 +727,39 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) if (!symlink_program_name) goto out; - r.name = real_program_name; - tomoyo_fill_path_info(&r); - s.name = symlink_program_name; - tomoyo_fill_path_info(&s); - l.name = tomoyo_get_last_name(old_domain); - tomoyo_fill_path_info(&l); + rn.name = real_program_name; + tomoyo_fill_path_info(&rn); + sn.name = symlink_program_name; + tomoyo_fill_path_info(&sn); + ln.name = tomoyo_get_last_name(old_domain); + tomoyo_fill_path_info(&ln); /* Check 'alias' directive. */ - if (tomoyo_pathcmp(&r, &s)) { + if (tomoyo_pathcmp(&rn, &sn)) { struct tomoyo_alias_entry *ptr; /* Is this program allowed to be called via symbolic links? */ list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { if (ptr->is_deleted || - tomoyo_pathcmp(&r, ptr->original_name) || - tomoyo_pathcmp(&s, ptr->aliased_name)) + tomoyo_pathcmp(&rn, ptr->original_name) || + tomoyo_pathcmp(&sn, ptr->aliased_name)) continue; memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN); strncpy(real_program_name, ptr->aliased_name->name, TOMOYO_MAX_PATHNAME_LEN - 1); - tomoyo_fill_path_info(&r); + tomoyo_fill_path_info(&rn); break; } } /* Check execute permission. */ - retval = tomoyo_check_exec_perm(old_domain, &r); + retval = tomoyo_check_exec_perm(old_domain, &rn); + if (retval == TOMOYO_RETRY_REQUEST) + goto retry; if (retval < 0) goto out; new_domain_name = tmp->buffer; - if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) { + if (tomoyo_is_domain_initializer(old_domain->domainname, &rn, &ln)) { /* Transit to the child of tomoyo_kernel_domain domain. */ snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, TOMOYO_ROOT_NAME " " "%s", real_program_name); @@ -766,7 +771,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) * initializers because they might start before /sbin/init. */ domain = old_domain; - } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) { + } else if (tomoyo_is_domain_keeper(old_domain->domainname, &rn, &ln)) { /* Keep current domain. */ domain = old_domain; } else { @@ -779,8 +784,14 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) domain = tomoyo_find_domain(new_domain_name); if (domain) goto done; - if (is_enforce) - goto done; + if (is_enforce) { + int error = tomoyo_supervisor(&r, "# wants to create domain\n" + "%s\n", new_domain_name); + if (error == TOMOYO_RETRY_REQUEST) + goto retry; + if (error < 0) + goto done; + } domain = tomoyo_find_or_assign_new_domain(new_domain_name, old_domain->profile); done: diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index ae32cab8ec7e..c629cb4e2c66 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -478,7 +478,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, } /** - * tomoyo_get_file_pattern - Get patterned pathname. + * tomoyo_file_pattern - Get patterned pathname. * * @filename: The filename to find patterned pathname. * @@ -486,8 +486,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, * * Caller holds tomoyo_read_lock(). */ -const struct tomoyo_path_info * -tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) +const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename) { struct tomoyo_pattern_entry *ptr; const struct tomoyo_path_info *pattern = NULL; @@ -507,7 +506,7 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) } if (pattern) filename = pattern; - return filename; + return filename->name; } /** @@ -812,23 +811,25 @@ static int tomoyo_file_perm(struct tomoyo_request_info *r, perm = 1 << TOMOYO_TYPE_EXECUTE; } else BUG(); - error = tomoyo_path_acl(r, filename, perm, mode != 1); - if (error && mode == 4 && !r->domain->ignore_global_allow_read - && tomoyo_is_globally_readable_file(filename)) + do { + error = tomoyo_path_acl(r, filename, perm, mode != 1); + if (error && mode == 4 && !r->domain->ignore_global_allow_read + && tomoyo_is_globally_readable_file(filename)) + error = 0; + if (!error) + break; + tomoyo_warn_log(r, "%s %s", msg, filename->name); + error = tomoyo_supervisor(r, "allow_%s %s\n", msg, + mode == 1 ? filename->name : + tomoyo_file_pattern(filename)); + /* + * Do not retry for execute request, for alias may have + * changed. + */ + } while (error == TOMOYO_RETRY_REQUEST && mode != 1); + if (r->mode != TOMOYO_CONFIG_ENFORCING) error = 0; - if (!error) - return 0; - tomoyo_warn_log(r, "%s %s", msg, filename->name); - if (r->mode == TOMOYO_CONFIG_ENFORCING) - return error; - if (tomoyo_domain_quota_is_ok(r)) { - /* Don't use patterns for execute permission. */ - const struct tomoyo_path_info *patterned_file = (mode != 1) ? - tomoyo_get_file_pattern(filename) : filename; - tomoyo_update_file_acl(mode, patterned_file->name, r->domain, - false); - } - return 0; + return error; } /** @@ -1123,21 +1124,21 @@ static int tomoyo_path2_acl(const struct tomoyo_request_info *r, const u8 type, static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, const struct tomoyo_path_info *filename) { + const char *msg; int error; next: - error = tomoyo_path_acl(r, filename, 1 << operation, 1); - if (!error) - goto ok; - tomoyo_warn_log(r, "%s %s", tomoyo_path2keyword(operation), - filename->name); - if (tomoyo_domain_quota_is_ok(r)) { - const char *name = tomoyo_get_file_pattern(filename)->name; - tomoyo_update_path_acl(operation, name, r->domain, false); - } + do { + error = tomoyo_path_acl(r, filename, 1 << operation, 1); + if (!error) + break; + msg = tomoyo_path2keyword(operation); + tomoyo_warn_log(r, "%s %s", msg, filename->name); + error = tomoyo_supervisor(r, "allow_%s %s\n", msg, + tomoyo_file_pattern(filename)); + } while (error == TOMOYO_RETRY_REQUEST); if (r->mode != TOMOYO_CONFIG_ENFORCING) error = 0; - ok: /* * Since "allow_truncate" doesn't imply "allow_rewrite" permission, * we need to check "allow_rewrite" permission if the filename is @@ -1267,6 +1268,7 @@ static int tomoyo_path_number_perm2(struct tomoyo_request_info *r, char buffer[64]; int error; u8 radix; + const char *msg; if (!filename) return 0; @@ -1286,15 +1288,16 @@ static int tomoyo_path_number_perm2(struct tomoyo_request_info *r, break; } tomoyo_print_ulong(buffer, sizeof(buffer), number, radix); - error = tomoyo_path_number_acl(r, type, filename, number); - if (!error) - return 0; - tomoyo_warn_log(r, "%s %s %s", tomoyo_path_number2keyword(type), - filename->name, buffer); - if (tomoyo_domain_quota_is_ok(r)) - tomoyo_update_path_number_acl(type, - tomoyo_get_file_pattern(filename) - ->name, buffer, r->domain, false); + do { + error = tomoyo_path_number_acl(r, type, filename, number); + if (!error) + break; + msg = tomoyo_path_number2keyword(type); + tomoyo_warn_log(r, "%s %s %s", msg, filename->name, buffer); + error = tomoyo_supervisor(r, "allow_%s %s %s\n", msg, + tomoyo_file_pattern(filename), + buffer); + } while (error == TOMOYO_RETRY_REQUEST); if (r->mode != TOMOYO_CONFIG_ENFORCING) error = 0; return error; @@ -1484,32 +1487,23 @@ static int tomoyo_path_number3_perm2(struct tomoyo_request_info *r, const unsigned int dev) { int error; + const char *msg; const unsigned int major = MAJOR(dev); const unsigned int minor = MINOR(dev); - error = tomoyo_path_number3_acl(r, filename, 1 << operation, mode, - major, minor); - if (!error) - return 0; - tomoyo_warn_log(r, "%s %s 0%o %u %u", - tomoyo_path_number32keyword(operation), - filename->name, mode, major, minor); - if (tomoyo_domain_quota_is_ok(r)) { - char mode_buf[64]; - char major_buf[64]; - char minor_buf[64]; - memset(mode_buf, 0, sizeof(mode_buf)); - memset(major_buf, 0, sizeof(major_buf)); - memset(minor_buf, 0, sizeof(minor_buf)); - snprintf(mode_buf, sizeof(mode_buf) - 1, "0%o", mode); - snprintf(major_buf, sizeof(major_buf) - 1, "%u", major); - snprintf(minor_buf, sizeof(minor_buf) - 1, "%u", minor); - tomoyo_update_path_number3_acl(operation, - tomoyo_get_file_pattern(filename) - ->name, mode_buf, major_buf, - minor_buf, r->domain, false); - } - if (r->mode != TOMOYO_CONFIG_ENFORCING) + do { + error = tomoyo_path_number3_acl(r, filename, 1 << operation, + mode, major, minor); + if (!error) + break; + msg = tomoyo_path_number32keyword(operation); + tomoyo_warn_log(r, "%s %s 0%o %u %u", msg, filename->name, + mode, major, minor); + error = tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", msg, + tomoyo_file_pattern(filename), mode, + major, minor); + } while (error == TOMOYO_RETRY_REQUEST); + if (r->mode != TOMOYO_CONFIG_ENFORCING) error = 0; return error; } @@ -1562,6 +1556,7 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, struct path *path2) { int error = -ENOMEM; + const char *msg; struct tomoyo_path_info *buf1; struct tomoyo_path_info *buf2; struct tomoyo_request_info r; @@ -1591,17 +1586,16 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, } } } - error = tomoyo_path2_acl(&r, operation, buf1, buf2); - if (!error) - goto out; - tomoyo_warn_log(&r, "%s %s %s", tomoyo_path22keyword(operation), - buf1->name, buf2->name); - if (tomoyo_domain_quota_is_ok(&r)) { - const char *name1 = tomoyo_get_file_pattern(buf1)->name; - const char *name2 = tomoyo_get_file_pattern(buf2)->name; - tomoyo_update_path2_acl(operation, name1, name2, r.domain, - false); - } + do { + error = tomoyo_path2_acl(&r, operation, buf1, buf2); + if (!error) + break; + msg = tomoyo_path22keyword(operation); + tomoyo_warn_log(&r, "%s %s %s", msg, buf1->name, buf2->name); + error = tomoyo_supervisor(&r, "allow_%s %s %s\n", msg, + tomoyo_file_pattern(buf1), + tomoyo_file_pattern(buf2)); + } while (error == TOMOYO_RETRY_REQUEST); out: kfree(buf1); kfree(buf2); diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 507be09e93a9..aeac619f787d 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -178,19 +178,12 @@ static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name, error = 0; break; } - if (error) { - const char *dev = tomoyo_get_file_pattern(&rdev)->name; - const char *dir = tomoyo_get_file_pattern(&rdir)->name; - int len = strlen(dev) + strlen(dir) + strlen(requested_type) - + 64; - char *buf = kzalloc(len, GFP_NOFS); - if (buf) { - snprintf(buf, len - 1, "%s %s %s 0x%lX", - dev, dir, requested_type, flags); - tomoyo_write_mount_policy(buf, r->domain, false); - kfree(buf); - } - } + if (error) + error = tomoyo_supervisor(r, TOMOYO_KEYWORD_ALLOW_MOUNT + "%s %s %s 0x%lX\n", + tomoyo_file_pattern(&rdev), + tomoyo_file_pattern(&rdir), + requested_type, flags); out: kfree(requested_dev_name); kfree(requested_dir_name); @@ -279,7 +272,10 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, TOMOYO_MOUNT_MAKE_SHARED_KEYWORD, flags & ~MS_SHARED); else - error = tomoyo_mount_acl2(r, dev_name, dir, type, flags); + do { + error = tomoyo_mount_acl2(r, dev_name, dir, type, + flags); + } while (error == TOMOYO_RETRY_REQUEST); if (r->mode != TOMOYO_CONFIG_ENFORCING) error = 0; return error; diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index d1b96f019621..3ceb1724c92d 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -333,6 +333,9 @@ void __init tomoyo_realpath_init(void) panic("Can't register tomoyo_kernel_domain"); } +unsigned int tomoyo_quota_for_query; +unsigned int tomoyo_query_memory_size; + /** * tomoyo_read_memory_counter - Check for memory usage in bytes. * @@ -345,6 +348,7 @@ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) if (!head->read_eof) { const unsigned int policy = atomic_read(&tomoyo_policy_memory_size); + const unsigned int query = tomoyo_query_memory_size; char buffer[64]; memset(buffer, 0, sizeof(buffer)); @@ -354,8 +358,17 @@ int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) tomoyo_quota_for_policy); else buffer[0] = '\0'; - tomoyo_io_printf(head, "Policy: %10u%s\n", policy, buffer); - tomoyo_io_printf(head, "Total: %10u\n", policy); + tomoyo_io_printf(head, "Policy: %10u%s\n", policy, + buffer); + if (tomoyo_quota_for_query) + snprintf(buffer, sizeof(buffer) - 1, + " (Quota: %10u)", + tomoyo_quota_for_query); + else + buffer[0] = '\0'; + tomoyo_io_printf(head, "Query lists: %10u%s\n", query, + buffer); + tomoyo_io_printf(head, "Total: %10u\n", policy + query); head->read_eof = true; } return 0; @@ -375,5 +388,7 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head) if (sscanf(data, "Policy: %u", &size) == 1) tomoyo_quota_for_policy = size; + else if (sscanf(data, "Query lists: %u", &size) == 1) + tomoyo_quota_for_query = size; return 0; } -- cgit v1.2.3 From c8c57e842720d8cc92ac8607f2d1c16d92314573 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 3 Jun 2010 20:36:43 +0900 Subject: TOMOYO: Support longer pathname. Allow pathnames longer than 4000 bytes. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.h | 48 +--------- security/tomoyo/domain.c | 72 +++++++-------- security/tomoyo/file.c | 136 ++++++++++++---------------- security/tomoyo/memory.c | 1 - security/tomoyo/mount.c | 55 +----------- security/tomoyo/realpath.c | 214 ++++++++++++++++++++++++--------------------- 6 files changed, 208 insertions(+), 318 deletions(-) (limited to 'security/tomoyo/mount.c') diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 6270a530c4d8..f4a8aa244af5 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -33,14 +33,7 @@ struct linux_binprm; #define TOMOYO_HASH_BITS 8 #define TOMOYO_MAX_HASH (1u<domainname->name; const char *original_name = bprm->filename; - char *new_domain_name = NULL; - char *real_program_name = NULL; - char *symlink_program_name = NULL; const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE); const bool is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); int retval = -ENOMEM; - struct tomoyo_path_info rn; /* real name */ - struct tomoyo_path_info sn; /* symlink name */ + bool need_kfree = false; + struct tomoyo_path_info rn = { }; /* real name */ + 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); tomoyo_init_request_info(&r, NULL); if (!tmp) goto out; retry: + if (need_kfree) { + kfree(rn.name); + need_kfree = false; + } /* Get tomoyo_realpath of program. */ retval = -ENOENT; - /* I hope tomoyo_realpath() won't fail with -ENOMEM. */ - real_program_name = tomoyo_realpath(original_name); - if (!real_program_name) + rn.name = tomoyo_realpath(original_name); + if (!rn.name) goto out; + tomoyo_fill_path_info(&rn); + need_kfree = true; + /* Get tomoyo_realpath of symbolic link. */ - symlink_program_name = tomoyo_realpath_nofollow(original_name); - if (!symlink_program_name) + sn.name = tomoyo_realpath_nofollow(original_name); + if (!sn.name) goto out; - - rn.name = real_program_name; - tomoyo_fill_path_info(&rn); - sn.name = symlink_program_name; tomoyo_fill_path_info(&sn); - ln.name = tomoyo_get_last_name(old_domain); - tomoyo_fill_path_info(&ln); /* Check 'alias' directive. */ if (tomoyo_pathcmp(&rn, &sn)) { @@ -727,10 +723,10 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) tomoyo_pathcmp(&rn, ptr->original_name) || tomoyo_pathcmp(&sn, ptr->aliased_name)) continue; - memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN); - strncpy(real_program_name, ptr->aliased_name->name, - TOMOYO_MAX_PATHNAME_LEN - 1); - tomoyo_fill_path_info(&rn); + kfree(rn.name); + need_kfree = false; + /* This is OK because it is read only. */ + rn = *ptr->aliased_name; break; } } @@ -742,11 +738,10 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) if (retval < 0) goto out; - new_domain_name = tmp->buffer; if (tomoyo_is_domain_initializer(old_domain->domainname, &rn, &ln)) { /* Transit to the child of tomoyo_kernel_domain domain. */ - snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, - TOMOYO_ROOT_NAME " " "%s", real_program_name); + snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, + TOMOYO_ROOT_NAME " " "%s", rn.name); } else if (old_domain == &tomoyo_kernel_domain && !tomoyo_policy_loaded) { /* @@ -760,29 +755,27 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) domain = old_domain; } else { /* Normal domain transition. */ - snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, - "%s %s", old_domain_name, real_program_name); + snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, + "%s %s", old_domain_name, rn.name); } - if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) + if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10) goto done; - domain = tomoyo_find_domain(new_domain_name); + domain = tomoyo_find_domain(tmp); if (domain) goto done; if (is_enforce) { int error = tomoyo_supervisor(&r, "# wants to create domain\n" - "%s\n", new_domain_name); + "%s\n", tmp); if (error == TOMOYO_RETRY_REQUEST) goto retry; if (error < 0) goto done; } - domain = tomoyo_find_or_assign_new_domain(new_domain_name, - old_domain->profile); + domain = tomoyo_find_or_assign_new_domain(tmp, old_domain->profile); done: if (domain) goto out; - printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", - new_domain_name); + printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp); if (is_enforce) retval = -EPERM; else @@ -793,8 +786,9 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) /* Update reference count on "struct tomoyo_domain_info". */ atomic_inc(&domain->users); bprm->cred->security = domain; - kfree(real_program_name); - kfree(symlink_program_name); + if (need_kfree) + kfree(rn.name); + kfree(sn.name); kfree(tmp); return retval; } diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index c13806937dc6..cef685415df1 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -148,6 +148,17 @@ const char *tomoyo_path_number2keyword(const u8 operation) ? tomoyo_path_number_keyword[operation] : NULL; } +static void tomoyo_add_slash(struct tomoyo_path_info *buf) +{ + if (buf->is_dir) + return; + /* + * This is OK because tomoyo_encode() reserves space for appending "/". + */ + strcat((char *) buf->name, "/"); + tomoyo_fill_path_info(buf); +} + /** * tomoyo_strendswith - Check whether the token ends with the given token. * @@ -167,30 +178,21 @@ static bool tomoyo_strendswith(const char *name, const char *tail) } /** - * tomoyo_get_path - Get realpath. + * tomoyo_get_realpath - Get realpath. * + * @buf: Pointer to "struct tomoyo_path_info". * @path: Pointer to "struct path". * - * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. + * Returns true on success, false otherwise. */ -static struct tomoyo_path_info *tomoyo_get_path(struct path *path) +static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path) { - int error; - struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf), - GFP_NOFS); - - if (!buf) - return NULL; - /* Reserve one byte for appending "/". */ - error = tomoyo_realpath_from_path2(path, buf->body, - sizeof(buf->body) - 2); - if (!error) { - buf->head.name = buf->body; - tomoyo_fill_path_info(&buf->head); - return &buf->head; + buf->name = tomoyo_realpath_from_path(path); + if (buf->name) { + tomoyo_fill_path_info(buf); + return true; } - kfree(buf); - return NULL; + return false; } static int tomoyo_update_path2_acl(const u8 type, const char *filename1, @@ -1259,26 +1261,20 @@ int tomoyo_path_number_perm(const u8 type, struct path *path, { struct tomoyo_request_info r; int error = -ENOMEM; - struct tomoyo_path_info *buf; + struct tomoyo_path_info buf; int idx; if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry) return 0; idx = tomoyo_read_lock(); - buf = tomoyo_get_path(path); - if (!buf) + if (!tomoyo_get_realpath(&buf, path)) goto out; - if (type == TOMOYO_TYPE_MKDIR && !buf->is_dir) { - /* - * tomoyo_get_path() reserves space for appending "/." - */ - strcat((char *) buf->name, "/"); - tomoyo_fill_path_info(buf); - } - error = tomoyo_path_number_perm2(&r, type, buf, number); + if (type == TOMOYO_TYPE_MKDIR) + tomoyo_add_slash(&buf); + error = tomoyo_path_number_perm2(&r, type, &buf, number); out: - kfree(buf); + kfree(buf.name); tomoyo_read_unlock(idx); if (r.mode != TOMOYO_CONFIG_ENFORCING) error = 0; @@ -1319,7 +1315,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, { const u8 acc_mode = ACC_MODE(flag); int error = -ENOMEM; - struct tomoyo_path_info *buf; + struct tomoyo_path_info buf; struct tomoyo_request_info r; int idx; @@ -1335,8 +1331,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, */ return 0; idx = tomoyo_read_lock(); - buf = tomoyo_get_path(path); - if (!buf) + if (!tomoyo_get_realpath(&buf, path)) goto out; error = 0; /* @@ -1346,15 +1341,15 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, */ if ((acc_mode & MAY_WRITE) && ((flag & O_TRUNC) || !(flag & O_APPEND)) && - (tomoyo_is_no_rewrite_file(buf))) { - error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, buf); + (tomoyo_is_no_rewrite_file(&buf))) { + error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, &buf); } if (!error) - error = tomoyo_file_perm(&r, buf, acc_mode); + error = tomoyo_file_perm(&r, &buf, acc_mode); if (!error && (flag & O_TRUNC)) - error = tomoyo_path_permission(&r, TOMOYO_TYPE_TRUNCATE, buf); + error = tomoyo_path_permission(&r, TOMOYO_TYPE_TRUNCATE, &buf); out: - kfree(buf); + kfree(buf.name); tomoyo_read_unlock(idx); if (r.mode != TOMOYO_CONFIG_ENFORCING) error = 0; @@ -1372,7 +1367,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, int tomoyo_path_perm(const u8 operation, struct path *path) { int error = -ENOMEM; - struct tomoyo_path_info *buf; + struct tomoyo_path_info buf; struct tomoyo_request_info r; int idx; @@ -1380,29 +1375,23 @@ int tomoyo_path_perm(const u8 operation, struct path *path) !path->mnt) return 0; idx = tomoyo_read_lock(); - buf = tomoyo_get_path(path); - if (!buf) + if (!tomoyo_get_realpath(&buf, path)) goto out; switch (operation) { case TOMOYO_TYPE_REWRITE: - if (!tomoyo_is_no_rewrite_file(buf)) { + if (!tomoyo_is_no_rewrite_file(&buf)) { error = 0; goto out; } break; case TOMOYO_TYPE_RMDIR: case TOMOYO_TYPE_CHROOT: - if (!buf->is_dir) { - /* - * tomoyo_get_path() reserves space for appending "/." - */ - strcat((char *) buf->name, "/"); - tomoyo_fill_path_info(buf); - } + tomoyo_add_slash(&buf); + break; } - error = tomoyo_path_permission(&r, operation, buf); + error = tomoyo_path_permission(&r, operation, &buf); out: - kfree(buf); + kfree(buf.name); tomoyo_read_unlock(idx); if (r.mode != TOMOYO_CONFIG_ENFORCING) error = 0; @@ -1465,7 +1454,7 @@ int tomoyo_path_number3_perm(const u8 operation, struct path *path, { struct tomoyo_request_info r; int error = -ENOMEM; - struct tomoyo_path_info *buf; + struct tomoyo_path_info buf; int idx; if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || @@ -1473,11 +1462,10 @@ int tomoyo_path_number3_perm(const u8 operation, struct path *path, return 0; idx = tomoyo_read_lock(); error = -ENOMEM; - buf = tomoyo_get_path(path); - if (buf) { - error = tomoyo_path_number3_perm2(&r, operation, buf, mode, + if (tomoyo_get_realpath(&buf, path)) { + error = tomoyo_path_number3_perm2(&r, operation, &buf, mode, new_decode_dev(dev)); - kfree(buf); + kfree(buf.name); } tomoyo_read_unlock(idx); if (r.mode != TOMOYO_CONFIG_ENFORCING) @@ -1499,48 +1487,40 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, { int error = -ENOMEM; const char *msg; - struct tomoyo_path_info *buf1; - struct tomoyo_path_info *buf2; + struct tomoyo_path_info buf1; + struct tomoyo_path_info buf2; struct tomoyo_request_info r; int idx; if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || !path1->mnt || !path2->mnt) return 0; + buf1.name = NULL; + buf2.name = NULL; idx = tomoyo_read_lock(); - buf1 = tomoyo_get_path(path1); - buf2 = tomoyo_get_path(path2); - if (!buf1 || !buf2) + if (!tomoyo_get_realpath(&buf1, path1) || + !tomoyo_get_realpath(&buf2, path2)) goto out; { struct dentry *dentry = path1->dentry; if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) { - /* - * tomoyo_get_path() reserves space for appending "/." - */ - if (!buf1->is_dir) { - strcat((char *) buf1->name, "/"); - tomoyo_fill_path_info(buf1); - } - if (!buf2->is_dir) { - strcat((char *) buf2->name, "/"); - tomoyo_fill_path_info(buf2); - } + tomoyo_add_slash(&buf1); + tomoyo_add_slash(&buf2); } } do { - error = tomoyo_path2_acl(&r, operation, buf1, buf2); + error = tomoyo_path2_acl(&r, operation, &buf1, &buf2); if (!error) break; msg = tomoyo_path22keyword(operation); - tomoyo_warn_log(&r, "%s %s %s", msg, buf1->name, buf2->name); + tomoyo_warn_log(&r, "%s %s %s", msg, buf1.name, buf2.name); error = tomoyo_supervisor(&r, "allow_%s %s %s\n", msg, - tomoyo_file_pattern(buf1), - tomoyo_file_pattern(buf2)); + tomoyo_file_pattern(&buf1), + tomoyo_file_pattern(&buf2)); } while (error == TOMOYO_RETRY_REQUEST); out: - kfree(buf1); - kfree(buf2); + kfree(buf1.name); + kfree(buf2.name); tomoyo_read_unlock(idx); if (r.mode != TOMOYO_CONFIG_ENFORCING) error = 0; diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c index 8fb73ff5cb63..4809febc1acb 100644 --- a/security/tomoyo/memory.c +++ b/security/tomoyo/memory.c @@ -153,7 +153,6 @@ void __init tomoyo_mm_init(void) { int idx; - BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX); for (idx = 0; idx < TOMOYO_MAX_HASH; idx++) INIT_LIST_HEAD(&tomoyo_name_list[idx]); INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index aeac619f787d..7c1c7fdd3681 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -24,57 +24,6 @@ /* Allow to call 'mount --make-shared /dir' */ #define TOMOYO_MOUNT_MAKE_SHARED_KEYWORD "--make-shared" -/** - * tomoyo_encode2: Encode binary string to ascii string. - * - * @str: String in binary format. - * - * Returns pointer to @str in ascii format on success, NULL otherwise. - * - * This function uses kzalloc(), so caller must kfree() if this function - * didn't return NULL. - */ -static char *tomoyo_encode2(const char *str) -{ - int len = 0; - const char *p = str; - char *cp; - char *cp0; - if (!p) - return NULL; - while (*p) { - const unsigned char c = *p++; - if (c == '\\') - len += 2; - else if (c > ' ' && c < 127) - len++; - else - len += 4; - } - len++; - /* Reserve space for appending "/". */ - cp = kzalloc(len + 10, GFP_NOFS); - if (!cp) - return NULL; - cp0 = cp; - p = str; - while (*p) { - const unsigned char c = *p++; - if (c == '\\') { - *cp++ = '\\'; - *cp++ = '\\'; - } else if (c > ' ' && c < 127) { - *cp++ = c; - } else { - *cp++ = '\\'; - *cp++ = (c >> 6) + '0'; - *cp++ = ((c >> 3) & 7) + '0'; - *cp++ = (c & 7) + '0'; - } - } - return cp0; -} - /** * tomoyo_mount_acl2 - Check permission for mount() operation. * @@ -104,7 +53,7 @@ static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name, int error = -ENOMEM; /* Get fstype. */ - requested_type = tomoyo_encode2(type); + requested_type = tomoyo_encode(type); if (!requested_type) goto out; rtype.name = requested_type; @@ -155,7 +104,7 @@ static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name, /* Map dev_name to "" if no dev_name given. */ if (!dev_name) dev_name = ""; - requested_dev_name = tomoyo_encode2(dev_name); + requested_dev_name = tomoyo_encode(dev_name); if (!requested_dev_name) { error = -ENOMEM; goto out; diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 1fd685a94ad1..153fa23a05cc 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -12,141 +12,153 @@ #include #include #include +#include #include "common.h" /** * tomoyo_encode: Convert binary string to ascii string. * - * @buffer: Buffer for ASCII string. - * @buflen: Size of @buffer. - * @str: Binary string. + * @str: String in binary format. * - * Returns 0 on success, -ENOMEM otherwise. + * Returns pointer to @str in ascii format on success, NULL otherwise. + * + * This function uses kzalloc(), so caller must kfree() if this function + * didn't return NULL. */ -int tomoyo_encode(char *buffer, int buflen, const char *str) +char *tomoyo_encode(const char *str) { - while (1) { - const unsigned char c = *(unsigned char *) str++; + int len = 0; + const char *p = str; + char *cp; + char *cp0; - if (tomoyo_is_valid(c)) { - if (--buflen <= 0) - break; - *buffer++ = (char) c; - if (c != '\\') - continue; - if (--buflen <= 0) - break; - *buffer++ = (char) c; - continue; - } - if (!c) { - if (--buflen <= 0) - break; - *buffer = '\0'; - return 0; + if (!p) + return NULL; + while (*p) { + const unsigned char c = *p++; + if (c == '\\') + len += 2; + else if (c > ' ' && c < 127) + len++; + else + len += 4; + } + len++; + /* Reserve space for appending "/". */ + cp = kzalloc(len + 10, GFP_NOFS); + if (!cp) + return NULL; + cp0 = cp; + p = str; + while (*p) { + const unsigned char c = *p++; + + if (c == '\\') { + *cp++ = '\\'; + *cp++ = '\\'; + } else if (c > ' ' && c < 127) { + *cp++ = c; + } else { + *cp++ = '\\'; + *cp++ = (c >> 6) + '0'; + *cp++ = ((c >> 3) & 7) + '0'; + *cp++ = (c & 7) + '0'; } - buflen -= 4; - if (buflen <= 0) - break; - *buffer++ = '\\'; - *buffer++ = (c >> 6) + '0'; - *buffer++ = ((c >> 3) & 7) + '0'; - *buffer++ = (c & 7) + '0'; } - return -ENOMEM; + return cp0; } /** - * tomoyo_realpath_from_path2 - Returns realpath(3) of the given dentry but ignores chroot'ed root. + * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root. * - * @path: Pointer to "struct path". - * @newname: Pointer to buffer to return value in. - * @newname_len: Size of @newname. + * @path: Pointer to "struct path". * - * Returns 0 on success, negative value otherwise. + * Returns the realpath of the given @path on success, NULL otherwise. * * If dentry is a directory, trailing '/' is appended. * Characters out of 0x20 < c < 0x7F range are converted to * \ooo style octal string. * Character \ is converted to \\ string. + * + * These functions use kzalloc(), so the caller must call kfree() + * if these functions didn't return NULL. */ -int tomoyo_realpath_from_path2(struct path *path, char *newname, - int newname_len) +char *tomoyo_realpath_from_path(struct path *path) { - int error = -ENOMEM; + char *buf = NULL; + char *name = NULL; + unsigned int buf_len = PAGE_SIZE / 2; struct dentry *dentry = path->dentry; - char *sp; - - if (!dentry || !path->mnt || !newname || newname_len <= 2048) - return -EINVAL; - if (dentry->d_op && dentry->d_op->d_dname) { + bool is_dir; + if (!dentry) + return NULL; + is_dir = dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode); + while (1) { + struct path ns_root = { .mnt = NULL, .dentry = NULL }; + char *pos; + buf_len <<= 1; + kfree(buf); + buf = kmalloc(buf_len, GFP_NOFS); + if (!buf) + break; + /* Get better name for socket. */ + if (dentry->d_sb && dentry->d_sb->s_magic == SOCKFS_MAGIC) { + struct inode *inode = dentry->d_inode; + struct socket *sock = inode ? SOCKET_I(inode) : NULL; + struct sock *sk = sock ? sock->sk : NULL; + if (sk) { + snprintf(buf, buf_len - 1, "socket:[family=%u:" + "type=%u:protocol=%u]", sk->sk_family, + sk->sk_type, sk->sk_protocol); + } else { + snprintf(buf, buf_len - 1, "socket:[unknown]"); + } + name = tomoyo_encode(buf); + break; + } /* For "socket:[\$]" and "pipe:[\$]". */ - static const int offset = 1536; - sp = dentry->d_op->d_dname(dentry, newname + offset, - newname_len - offset); - } else { - struct path ns_root = {.mnt = NULL, .dentry = NULL}; - + if (dentry->d_op && dentry->d_op->d_dname) { + pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1); + if (IS_ERR(pos)) + continue; + name = tomoyo_encode(pos); + break; + } + /* If we don't have a vfsmount, we can't calculate. */ + if (!path->mnt) + break; spin_lock(&dcache_lock); /* go to whatever namespace root we are under */ - sp = __d_path(path, &ns_root, newname, newname_len); + pos = __d_path(path, &ns_root, buf, buf_len); spin_unlock(&dcache_lock); /* Prepend "/proc" prefix if using internal proc vfs mount. */ - if (!IS_ERR(sp) && (path->mnt->mnt_flags & MNT_INTERNAL) && + if (!IS_ERR(pos) && (path->mnt->mnt_flags & MNT_INTERNAL) && (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) { - sp -= 5; - if (sp >= newname) - memcpy(sp, "/proc", 5); + pos -= 5; + if (pos >= buf) + memcpy(pos, "/proc", 5); else - sp = ERR_PTR(-ENOMEM); - } - } - if (IS_ERR(sp)) - error = PTR_ERR(sp); - else - error = tomoyo_encode(newname, sp - newname, sp); - /* Append trailing '/' if dentry is a directory. */ - if (!error && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode) - && *newname) { - sp = newname + strlen(newname); - if (*(sp - 1) != '/') { - if (sp < newname + newname_len - 4) { - *sp++ = '/'; - *sp = '\0'; - } else { - error = -ENOMEM; - } + pos = ERR_PTR(-ENOMEM); } + if (IS_ERR(pos)) + continue; + name = tomoyo_encode(pos); + break; } - if (error) - tomoyo_warn_oom(__func__); - return error; -} - -/** - * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root. - * - * @path: Pointer to "struct path". - * - * Returns the realpath of the given @path on success, NULL otherwise. - * - * These functions use kzalloc(), so the caller must call kfree() - * if these functions didn't return NULL. - */ -char *tomoyo_realpath_from_path(struct path *path) -{ - char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_NOFS); - - BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX); - BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer) - <= TOMOYO_MAX_PATHNAME_LEN - 1); - if (!buf) - return NULL; - if (tomoyo_realpath_from_path2(path, buf, - TOMOYO_MAX_PATHNAME_LEN - 1) == 0) - return buf; kfree(buf); - return NULL; + if (!name) + tomoyo_warn_oom(__func__); + else if (is_dir && *name) { + /* Append trailing '/' if dentry is a directory. */ + char *pos = name + strlen(name) - 1; + if (*pos != '/') + /* + * This is OK because tomoyo_encode() reserves space + * for appending "/". + */ + *++pos = '/'; + } + return name; } /** -- cgit v1.2.3 From 57c2590fb7fd38bd52708ff2716a577d0c2b3c5a Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Thu, 3 Jun 2010 20:38:44 +0900 Subject: TOMOYO: Update profile structure. This patch allows users to change access control mode for per-operation basis. This feature comes from non LSM version of TOMOYO which is designed for permitting users to use SELinux and TOMOYO at the same time. SELinux does not care filename in a directory whereas TOMOYO does. Change of filename can change how the file is used. For example, renaming index.txt to .htaccess will change how the file is used. Thus, letting SELinux to enforce read()/write()/mmap() etc. restriction and letting TOMOYO to enforce rename() restriction is an example usage of this feature. What is unfortunate for me is that currently LSM does not allow users to use SELinux and LSM version of TOMOYO at the same time... Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 431 ++++++++++++++++++++++++++++------------------- security/tomoyo/common.h | 68 ++++++-- security/tomoyo/domain.c | 9 +- security/tomoyo/file.c | 131 +++++++++----- security/tomoyo/mount.c | 3 +- security/tomoyo/util.c | 92 +++++++--- 6 files changed, 486 insertions(+), 248 deletions(-) (limited to 'security/tomoyo/mount.c') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index bdf1ed7ca45b..811adb5e9fea 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -9,52 +9,73 @@ #include #include #include -#include #include "common.h" +static struct tomoyo_profile tomoyo_default_profile = { + .learning = &tomoyo_default_profile.preference, + .permissive = &tomoyo_default_profile.preference, + .enforcing = &tomoyo_default_profile.preference, + .preference.enforcing_verbose = true, + .preference.learning_max_entry = 2048, + .preference.learning_verbose = false, + .preference.permissive_verbose = true +}; + +/* Profile version. Currently only 20090903 is defined. */ +static unsigned int tomoyo_profile_version; + +/* Profile table. Memory is allocated as needed. */ +static struct tomoyo_profile *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES]; + /* String table for functionality that takes 4 modes. */ static const char *tomoyo_mode_4[4] = { "disabled", "learning", "permissive", "enforcing" }; -/* String table for functionality that takes 2 modes. */ -static const char *tomoyo_mode_2[4] = { - "disabled", "enabled", "enabled", "enabled" -}; -/* - * tomoyo_control_array is a static data which contains - * - * (1) functionality name used by /sys/kernel/security/tomoyo/profile . - * (2) initial values for "struct tomoyo_profile". - * (3) max values for "struct tomoyo_profile". - */ -static struct { - const char *keyword; - unsigned int current_value; - const unsigned int max_value; -} tomoyo_control_array[TOMOYO_MAX_CONTROL_INDEX] = { - [TOMOYO_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 }, - [TOMOYO_MAX_ACCEPT_ENTRY] = { "MAX_ACCEPT_ENTRY", 2048, INT_MAX }, - [TOMOYO_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 }, +/* String table for /sys/kernel/security/tomoyo/profile */ +static const char *tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX + + TOMOYO_MAX_MAC_CATEGORY_INDEX] = { + [TOMOYO_MAC_FILE_EXECUTE] = "file::execute", + [TOMOYO_MAC_FILE_OPEN] = "file::open", + [TOMOYO_MAC_FILE_CREATE] = "file::create", + [TOMOYO_MAC_FILE_UNLINK] = "file::unlink", + [TOMOYO_MAC_FILE_MKDIR] = "file::mkdir", + [TOMOYO_MAC_FILE_RMDIR] = "file::rmdir", + [TOMOYO_MAC_FILE_MKFIFO] = "file::mkfifo", + [TOMOYO_MAC_FILE_MKSOCK] = "file::mksock", + [TOMOYO_MAC_FILE_TRUNCATE] = "file::truncate", + [TOMOYO_MAC_FILE_SYMLINK] = "file::symlink", + [TOMOYO_MAC_FILE_REWRITE] = "file::rewrite", + [TOMOYO_MAC_FILE_MKBLOCK] = "file::mkblock", + [TOMOYO_MAC_FILE_MKCHAR] = "file::mkchar", + [TOMOYO_MAC_FILE_LINK] = "file::link", + [TOMOYO_MAC_FILE_RENAME] = "file::rename", + [TOMOYO_MAC_FILE_CHMOD] = "file::chmod", + [TOMOYO_MAC_FILE_CHOWN] = "file::chown", + [TOMOYO_MAC_FILE_CHGRP] = "file::chgrp", + [TOMOYO_MAC_FILE_IOCTL] = "file::ioctl", + [TOMOYO_MAC_FILE_CHROOT] = "file::chroot", + [TOMOYO_MAC_FILE_MOUNT] = "file::mount", + [TOMOYO_MAC_FILE_UMOUNT] = "file::umount", + [TOMOYO_MAC_FILE_PIVOT_ROOT] = "file::pivot_root", + [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file", }; -/* - * tomoyo_profile is a structure which is used for holding the mode of access - * controls. TOMOYO has 4 modes: disabled, learning, permissive, enforcing. - * An administrator can define up to 256 profiles. - * The ->profile of "struct tomoyo_domain_info" is used for remembering - * the profile's number (0 - 255) assigned to that domain. - */ -static struct tomoyo_profile { - unsigned int value[TOMOYO_MAX_CONTROL_INDEX]; - const struct tomoyo_path_info *comment; -} *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES]; - /* Permit policy management by non-root user? */ static bool tomoyo_manage_by_non_root; /* Utility functions. */ +/** + * tomoyo_yesno - Return "yes" or "no". + * + * @value: Bool value. + */ +static const char *tomoyo_yesno(const unsigned int value) +{ + return value ? "yes" : "no"; +} + /** * tomoyo_print_name_union - Print a tomoyo_name_union. * @@ -153,44 +174,6 @@ bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) return true; } -/** - * tomoyo_check_flags - Check mode for specified functionality. - * - * @domain: Pointer to "struct tomoyo_domain_info". - * @index: The functionality to check mode. - * - * TOMOYO checks only process context. - * This code disables TOMOYO's enforcement in case the function is called from - * interrupt context. - */ -unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, - const u8 index) -{ - const u8 profile = domain->profile; - - if (WARN_ON(in_interrupt())) - return 0; - return tomoyo_policy_loaded && index < TOMOYO_MAX_CONTROL_INDEX -#if TOMOYO_MAX_PROFILES != 256 - && profile < TOMOYO_MAX_PROFILES -#endif - && tomoyo_profile_ptr[profile] ? - tomoyo_profile_ptr[profile]->value[index] : 0; -} - -/** - * tomoyo_verbose_mode - Check whether TOMOYO is verbose mode. - * - * @domain: Pointer to "struct tomoyo_domain_info". - * - * Returns true if domain policy violation warning should be printed to - * console. - */ -bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain) -{ - return tomoyo_check_flags(domain, TOMOYO_VERBOSE) != 0; -} - /** * tomoyo_find_or_assign_new_profile - Create a new profile. * @@ -198,36 +181,56 @@ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain) * * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise. */ -static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned - int profile) +static struct tomoyo_profile *tomoyo_find_or_assign_new_profile +(const unsigned int profile) { - struct tomoyo_profile *ptr = NULL; - int i; - + struct tomoyo_profile *ptr; + struct tomoyo_profile *entry; if (profile >= TOMOYO_MAX_PROFILES) return NULL; - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - return NULL; ptr = tomoyo_profile_ptr[profile]; if (ptr) - goto ok; - ptr = kmalloc(sizeof(*ptr), GFP_NOFS); - if (!tomoyo_memory_ok(ptr)) { - kfree(ptr); - ptr = NULL; - goto ok; + return ptr; + entry = kzalloc(sizeof(*entry), GFP_NOFS); + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + goto out; + ptr = tomoyo_profile_ptr[profile]; + if (!ptr && tomoyo_memory_ok(entry)) { + ptr = entry; + ptr->learning = &tomoyo_default_profile.preference; + ptr->permissive = &tomoyo_default_profile.preference; + ptr->enforcing = &tomoyo_default_profile.preference; + ptr->default_config = TOMOYO_CONFIG_DISABLED; + memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT, + sizeof(ptr->config)); + mb(); /* Avoid out-of-order execution. */ + tomoyo_profile_ptr[profile] = ptr; + entry = NULL; } - for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) - ptr->value[i] = tomoyo_control_array[i].current_value; - mb(); /* Avoid out-of-order execution. */ - tomoyo_profile_ptr[profile] = ptr; - ok: mutex_unlock(&tomoyo_policy_lock); + out: + kfree(entry); return ptr; } /** - * tomoyo_write_profile - Write to profile table. + * tomoyo_profile - Find a profile. + * + * @profile: Profile number to find. + * + * Returns pointer to "struct tomoyo_profile". + */ +struct tomoyo_profile *tomoyo_profile(const u8 profile) +{ + struct tomoyo_profile *ptr = tomoyo_profile_ptr[profile]; + if (!tomoyo_policy_loaded) + return &tomoyo_default_profile; + BUG_ON(!ptr); + return ptr; +} + +/** + * tomoyo_write_profile - Write profile table. * * @head: Pointer to "struct tomoyo_io_buffer". * @@ -237,64 +240,116 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) { char *data = head->write_buf; unsigned int i; - unsigned int value; + int value; + int mode; + u8 config; + bool use_default = false; char *cp; struct tomoyo_profile *profile; - unsigned long num; - - cp = strchr(data, '-'); - if (cp) - *cp = '\0'; - if (strict_strtoul(data, 10, &num)) - return -EINVAL; - if (cp) + if (sscanf(data, "PROFILE_VERSION=%u", &tomoyo_profile_version) == 1) + return 0; + i = simple_strtoul(data, &cp, 10); + if (data == cp) { + profile = &tomoyo_default_profile; + } else { + if (*cp != '-') + return -EINVAL; data = cp + 1; - profile = tomoyo_find_or_assign_new_profile(num); - if (!profile) - return -EINVAL; + profile = tomoyo_find_or_assign_new_profile(i); + if (!profile) + return -EINVAL; + } cp = strchr(data, '='); if (!cp) return -EINVAL; - *cp = '\0'; + *cp++ = '\0'; + if (profile != &tomoyo_default_profile) + use_default = strstr(cp, "use_default") != NULL; + if (strstr(cp, "verbose=yes")) + value = 1; + else if (strstr(cp, "verbose=no")) + value = 0; + else + value = -1; + if (!strcmp(data, "PREFERENCE::enforcing")) { + if (use_default) { + profile->enforcing = &tomoyo_default_profile.preference; + return 0; + } + profile->enforcing = &profile->preference; + if (value >= 0) + profile->preference.enforcing_verbose = value; + return 0; + } + if (!strcmp(data, "PREFERENCE::permissive")) { + if (use_default) { + profile->permissive = &tomoyo_default_profile.preference; + return 0; + } + profile->permissive = &profile->preference; + if (value >= 0) + profile->preference.permissive_verbose = value; + return 0; + } + if (!strcmp(data, "PREFERENCE::learning")) { + char *cp2; + if (use_default) { + profile->learning = &tomoyo_default_profile.preference; + return 0; + } + profile->learning = &profile->preference; + if (value >= 0) + profile->preference.learning_verbose = value; + cp2 = strstr(cp, "max_entry="); + if (cp2) + sscanf(cp2 + 10, "%u", + &profile->preference.learning_max_entry); + return 0; + } + if (profile == &tomoyo_default_profile) + return -EINVAL; if (!strcmp(data, "COMMENT")) { const struct tomoyo_path_info *old_comment = profile->comment; - profile->comment = tomoyo_get_name(cp + 1); + profile->comment = tomoyo_get_name(cp); tomoyo_put_name(old_comment); return 0; } - for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) { - if (strcmp(data, tomoyo_control_array[i].keyword)) - continue; - if (sscanf(cp + 1, "%u", &value) != 1) { - int j; - const char **modes; - switch (i) { - case TOMOYO_VERBOSE: - modes = tomoyo_mode_2; - break; - default: - modes = tomoyo_mode_4; - break; - } - for (j = 0; j < 4; j++) { - if (strcmp(cp + 1, modes[j])) - continue; - value = j; - break; - } - if (j == 4) - return -EINVAL; - } else if (value > tomoyo_control_array[i].max_value) { - value = tomoyo_control_array[i].max_value; + if (!strcmp(data, "CONFIG")) { + i = TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX; + config = profile->default_config; + } else if (tomoyo_str_starts(&data, "CONFIG::")) { + config = 0; + for (i = 0; i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) { + if (strcmp(data, tomoyo_mac_keywords[i])) + continue; + config = profile->config[i]; + break; } - profile->value[i] = value; - return 0; + if (i == TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX) + return -EINVAL; + } else { + return -EINVAL; } - return -EINVAL; + if (use_default) { + config = TOMOYO_CONFIG_USE_DEFAULT; + } else { + for (mode = 3; mode >= 0; mode--) + if (strstr(cp, tomoyo_mode_4[mode])) + /* + * Update lower 3 bits in order to distinguish + * 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'. + */ + config = (config & ~7) | mode; + } + if (i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX) + profile->config[i] = config; + else if (config != TOMOYO_CONFIG_USE_DEFAULT) + profile->default_config = config; + return 0; } /** - * tomoyo_read_profile - Read from profile table. + * tomoyo_read_profile - Read profile table. * * @head: Pointer to "struct tomoyo_io_buffer". * @@ -302,53 +357,82 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) */ static int tomoyo_read_profile(struct tomoyo_io_buffer *head) { - static const int total = TOMOYO_MAX_CONTROL_INDEX + 1; - int step; - + int index; if (head->read_eof) return 0; - for (step = head->read_step; step < TOMOYO_MAX_PROFILES * total; - step++) { - const u8 index = step / total; - u8 type = step % total; + if (head->read_bit) + goto body; + tomoyo_io_printf(head, "PROFILE_VERSION=%s\n", "20090903"); + tomoyo_io_printf(head, "PREFERENCE::learning={ verbose=%s " + "max_entry=%u }\n", + tomoyo_yesno(tomoyo_default_profile.preference. + learning_verbose), + tomoyo_default_profile.preference.learning_max_entry); + tomoyo_io_printf(head, "PREFERENCE::permissive={ verbose=%s }\n", + tomoyo_yesno(tomoyo_default_profile.preference. + permissive_verbose)); + tomoyo_io_printf(head, "PREFERENCE::enforcing={ verbose=%s }\n", + tomoyo_yesno(tomoyo_default_profile.preference. + enforcing_verbose)); + head->read_bit = 1; + body: + for (index = head->read_step; index < TOMOYO_MAX_PROFILES; index++) { + bool done; + u8 config; + int i; + int pos; const struct tomoyo_profile *profile = tomoyo_profile_ptr[index]; - head->read_step = step; + const struct tomoyo_path_info *comment; + head->read_step = index; if (!profile) continue; - if (!type) { /* Print profile' comment tag. */ - if (!tomoyo_io_printf(head, "%u-COMMENT=%s\n", - index, profile->comment ? - profile->comment->name : "")) - break; - continue; - } - type--; - if (type < TOMOYO_MAX_CONTROL_INDEX) { - const unsigned int value = profile->value[type]; - const char **modes = NULL; - const char *keyword - = tomoyo_control_array[type].keyword; - switch (tomoyo_control_array[type].max_value) { - case 3: - modes = tomoyo_mode_4; - break; - case 1: - modes = tomoyo_mode_2; - break; - } - if (modes) { - if (!tomoyo_io_printf(head, "%u-%s=%s\n", index, - keyword, modes[value])) - break; - } else { - if (!tomoyo_io_printf(head, "%u-%s=%u\n", index, - keyword, value)) - break; - } + pos = head->read_avail; + comment = profile->comment; + done = tomoyo_io_printf(head, "%u-COMMENT=%s\n", index, + comment ? comment->name : ""); + if (!done) + goto out; + config = profile->default_config; + if (!tomoyo_io_printf(head, "%u-CONFIG={ mode=%s }\n", index, + tomoyo_mode_4[config & 3])) + goto out; + for (i = 0; i < TOMOYO_MAX_MAC_INDEX + + TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) { + config = profile->config[i]; + if (config == TOMOYO_CONFIG_USE_DEFAULT) + continue; + if (!tomoyo_io_printf(head, + "%u-CONFIG::%s={ mode=%s }\n", + index, tomoyo_mac_keywords[i], + tomoyo_mode_4[config & 3])) + goto out; } + if (profile->learning != &tomoyo_default_profile.preference && + !tomoyo_io_printf(head, "%u-PREFERENCE::learning={ " + "verbose=%s max_entry=%u }\n", index, + tomoyo_yesno(profile->preference. + learning_verbose), + profile->preference.learning_max_entry)) + goto out; + if (profile->permissive != &tomoyo_default_profile.preference + && !tomoyo_io_printf(head, "%u-PREFERENCE::permissive={ " + "verbose=%s }\n", index, + tomoyo_yesno(profile->preference. + permissive_verbose))) + goto out; + if (profile->enforcing != &tomoyo_default_profile.preference && + !tomoyo_io_printf(head, "%u-PREFERENCE::enforcing={ " + "verbose=%s }\n", index, + tomoyo_yesno(profile->preference. + enforcing_verbose))) + goto out; + continue; + out: + head->read_avail = pos; + break; } - if (step == TOMOYO_MAX_PROFILES * total) + if (index == TOMOYO_MAX_PROFILES) head->read_eof = true; return 0; } @@ -1595,7 +1679,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head) static int tomoyo_read_version(struct tomoyo_io_buffer *head) { if (!head->read_eof) { - tomoyo_io_printf(head, "2.2.0"); + tomoyo_io_printf(head, "2.3.0-pre"); head->read_eof = true; } return 0; @@ -1915,6 +1999,9 @@ void tomoyo_check_profile(void) profile, domain->domainname->name); } tomoyo_read_unlock(idx); - printk(KERN_INFO "TOMOYO: 2.2.0 2009/04/01\n"); + if (tomoyo_profile_version != 20090903) + panic("Profile version %u is not supported.\n", + tomoyo_profile_version); + printk(KERN_INFO "TOMOYO: 2.3.0-pre 2010/06/03\n"); printk(KERN_INFO "Mandatory Access Control activated.\n"); } diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 54db39aa339b..c777c594a00b 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -42,7 +42,8 @@ enum tomoyo_mode_index { TOMOYO_CONFIG_DISABLED, TOMOYO_CONFIG_LEARNING, TOMOYO_CONFIG_PERMISSIVE, - TOMOYO_CONFIG_ENFORCING + TOMOYO_CONFIG_ENFORCING, + TOMOYO_CONFIG_USE_DEFAULT = 255 }; /* Keywords for ACLs. */ @@ -74,14 +75,6 @@ enum tomoyo_mode_index { #define TOMOYO_VALUE_TYPE_OCTAL 2 #define TOMOYO_VALUE_TYPE_HEXADECIMAL 3 -/* Index numbers for Access Controls. */ -enum tomoyo_mac_index { - TOMOYO_MAC_FOR_FILE, /* domain_policy.conf */ - TOMOYO_MAX_ACCEPT_ENTRY, - TOMOYO_VERBOSE, - TOMOYO_MAX_CONTROL_INDEX -}; - /* Index numbers for Access Controls. */ enum tomoyo_acl_entry_type_index { TOMOYO_TYPE_PATH_ACL, @@ -157,6 +150,38 @@ enum tomoyo_securityfs_interface_index { TOMOYO_MANAGER }; +enum tomoyo_mac_index { + TOMOYO_MAC_FILE_EXECUTE, + TOMOYO_MAC_FILE_OPEN, + TOMOYO_MAC_FILE_CREATE, + TOMOYO_MAC_FILE_UNLINK, + TOMOYO_MAC_FILE_MKDIR, + TOMOYO_MAC_FILE_RMDIR, + TOMOYO_MAC_FILE_MKFIFO, + TOMOYO_MAC_FILE_MKSOCK, + TOMOYO_MAC_FILE_TRUNCATE, + TOMOYO_MAC_FILE_SYMLINK, + TOMOYO_MAC_FILE_REWRITE, + TOMOYO_MAC_FILE_MKBLOCK, + TOMOYO_MAC_FILE_MKCHAR, + TOMOYO_MAC_FILE_LINK, + TOMOYO_MAC_FILE_RENAME, + TOMOYO_MAC_FILE_CHMOD, + TOMOYO_MAC_FILE_CHOWN, + TOMOYO_MAC_FILE_CHGRP, + TOMOYO_MAC_FILE_IOCTL, + TOMOYO_MAC_FILE_CHROOT, + TOMOYO_MAC_FILE_MOUNT, + TOMOYO_MAC_FILE_UMOUNT, + TOMOYO_MAC_FILE_PIVOT_ROOT, + TOMOYO_MAX_MAC_INDEX +}; + +enum tomoyo_mac_category_index { + TOMOYO_MAC_CATEGORY_FILE, + TOMOYO_MAX_MAC_CATEGORY_INDEX +}; + #define TOMOYO_RETRY_REQUEST 1 /* Retry this request. */ /********** Structure definitions. **********/ @@ -174,6 +199,7 @@ struct tomoyo_request_info { u8 retry; u8 profile; u8 mode; /* One of tomoyo_mode_index . */ + u8 type; }; /* @@ -649,6 +675,23 @@ struct tomoyo_policy_manager_entry { bool is_deleted; /* True if this entry is deleted. */ }; +struct tomoyo_preference { + unsigned int learning_max_entry; + bool enforcing_verbose; + bool learning_verbose; + bool permissive_verbose; +}; + +struct tomoyo_profile { + const struct tomoyo_path_info *comment; + struct tomoyo_preference *learning; + struct tomoyo_preference *permissive; + struct tomoyo_preference *enforcing; + struct tomoyo_preference preference; + u8 default_config; + u8 config[TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX]; +}; + /********** Function prototypes. **********/ extern asmlinkage long sys_getpid(void); @@ -685,6 +728,7 @@ bool tomoyo_compare_name_union(const struct tomoyo_path_info *name, /* 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); +int tomoyo_get_mode(const u8 profile, const u8 index); /* Transactional sprintf() for policy dump. */ bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); @@ -747,7 +791,8 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); const char *tomoyo_path2keyword(const u8 operation); /* Fill "struct tomoyo_request_info". */ int tomoyo_init_request_info(struct tomoyo_request_info *r, - struct tomoyo_domain_info *domain); + struct tomoyo_domain_info *domain, + const u8 index); /* Check permission for mount operation. */ int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, unsigned long flags, void *data_page); @@ -794,6 +839,7 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * domainname, const u8 profile); +struct tomoyo_profile *tomoyo_profile(const u8 profile); /* Allocate memory for "struct tomoyo_path_group". */ struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name); struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name); @@ -844,7 +890,7 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head); /* Initialize mm related code. */ void __init tomoyo_mm_init(void); -int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, +int tomoyo_check_exec_perm(struct tomoyo_request_info *r, const struct tomoyo_path_info *filename); int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, struct path *path, const int flag); diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index a07ca6dc1a08..09ec37c12a9c 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -812,8 +812,8 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) struct tomoyo_domain_info *domain = NULL; const char *old_domain_name = old_domain->domainname->name; const char *original_name = bprm->filename; - const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE); - const bool is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); + u8 mode; + bool is_enforce; int retval = -ENOMEM; bool need_kfree = false; struct tomoyo_path_info rn = { }; /* real name */ @@ -822,7 +822,8 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) ln.name = tomoyo_get_last_name(old_domain); tomoyo_fill_path_info(&ln); - tomoyo_init_request_info(&r, NULL); + mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE); + is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); if (!tmp) goto out; @@ -880,7 +881,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) } /* Check execute permission. */ - retval = tomoyo_check_exec_perm(old_domain, &rn); + retval = tomoyo_check_exec_perm(&r, &rn); if (retval == TOMOYO_RETRY_REQUEST) goto retry; if (retval < 0) diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 83fa17a1113a..8e51348d022e 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -51,6 +51,42 @@ static const char *tomoyo_path_number_keyword [TOMOYO_TYPE_CHGRP] = "chgrp", }; +static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { + [TOMOYO_TYPE_READ_WRITE] = TOMOYO_MAC_FILE_OPEN, + [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, + [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, + [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN, + [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK, + [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR, + [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE, + [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK, + [TOMOYO_TYPE_REWRITE] = TOMOYO_MAC_FILE_REWRITE, + [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT, + [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, +}; + +static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_PATH_NUMBER3_OPERATION] = { + [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, + [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR, +}; + +static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = { + [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK, + [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME, + [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT, +}; + +static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { + [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE, + [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR, + [TOMOYO_TYPE_MKFIFO] = TOMOYO_MAC_FILE_MKFIFO, + [TOMOYO_TYPE_MKSOCK] = TOMOYO_MAC_FILE_MKSOCK, + [TOMOYO_TYPE_IOCTL] = TOMOYO_MAC_FILE_IOCTL, + [TOMOYO_TYPE_CHMOD] = TOMOYO_MAC_FILE_CHMOD, + [TOMOYO_TYPE_CHOWN] = TOMOYO_MAC_FILE_CHOWN, + [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP, +}; + void tomoyo_put_name_union(struct tomoyo_name_union *ptr) { if (!ptr) @@ -1057,6 +1093,10 @@ static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, int error; next: + r->type = tomoyo_p2mac[operation]; + r->mode = tomoyo_get_mode(r->profile, r->type); + if (r->mode == TOMOYO_CONFIG_DISABLED) + return 0; do { error = tomoyo_path_acl(r, filename, 1 << operation); if (!error) @@ -1249,8 +1289,8 @@ int tomoyo_path_number_perm(const u8 type, struct path *path, struct tomoyo_path_info buf; int idx; - if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || - !path->mnt || !path->dentry) + if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type]) + == TOMOYO_CONFIG_DISABLED || !path->mnt || !path->dentry) return 0; idx = tomoyo_read_lock(); if (!tomoyo_get_realpath(&buf, path)) @@ -1269,21 +1309,19 @@ int tomoyo_path_number_perm(const u8 type, struct path *path, /** * tomoyo_check_exec_perm - Check permission for "execute". * - * @domain: Pointer to "struct tomoyo_domain_info". + * @r: Pointer to "struct tomoyo_request_info". * @filename: Check permission for "execute". * * Returns 0 on success, negativevalue otherwise. * * Caller holds tomoyo_read_lock(). */ -int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, +int tomoyo_check_exec_perm(struct tomoyo_request_info *r, const struct tomoyo_path_info *filename) { - struct tomoyo_request_info r; - - if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED) + if (r->mode == TOMOYO_CONFIG_DISABLED) return 0; - return tomoyo_file_perm(&r, filename, 1); + return tomoyo_file_perm(r, filename, 1); } /** @@ -1304,17 +1342,11 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, struct tomoyo_request_info r; int idx; - if (tomoyo_init_request_info(&r, domain) == TOMOYO_CONFIG_DISABLED || - !path->mnt) - return 0; - if (acc_mode == 0) - return 0; - if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode)) - /* - * I don't check directories here because mkdir() and rmdir() - * don't call me. - */ + if (!path->mnt || + (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))) return 0; + buf.name = NULL; + r.mode = TOMOYO_CONFIG_DISABLED; idx = tomoyo_read_lock(); if (!tomoyo_get_realpath(&buf, path)) goto out; @@ -1324,15 +1356,26 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, * we need to check "allow_rewrite" permission when the filename is not * opened for append mode or the filename is truncated at open time. */ - if ((acc_mode & MAY_WRITE) && - ((flag & O_TRUNC) || !(flag & O_APPEND)) && - (tomoyo_is_no_rewrite_file(&buf))) { - error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, &buf); + if ((acc_mode & MAY_WRITE) && !(flag & O_APPEND) + && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_REWRITE) + != TOMOYO_CONFIG_DISABLED) { + if (!tomoyo_get_realpath(&buf, path)) { + error = -ENOMEM; + goto out; + } + if (tomoyo_is_no_rewrite_file(&buf)) + error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, + &buf); } - if (!error) + if (!error && acc_mode && + tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) + != TOMOYO_CONFIG_DISABLED) { + if (!buf.name && !tomoyo_get_realpath(&buf, path)) { + error = -ENOMEM; + goto out; + } error = tomoyo_file_perm(&r, &buf, acc_mode); - if (!error && (flag & O_TRUNC)) - error = tomoyo_path_permission(&r, TOMOYO_TYPE_TRUNCATE, &buf); + } out: kfree(buf.name); tomoyo_read_unlock(idx); @@ -1356,9 +1399,12 @@ int tomoyo_path_perm(const u8 operation, struct path *path) struct tomoyo_request_info r; int idx; - if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || - !path->mnt) + if (!path->mnt) + return 0; + if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) + == TOMOYO_CONFIG_DISABLED) return 0; + buf.name = NULL; idx = tomoyo_read_lock(); if (!tomoyo_get_realpath(&buf, path)) goto out; @@ -1371,6 +1417,7 @@ int tomoyo_path_perm(const u8 operation, struct path *path) break; case TOMOYO_TYPE_RMDIR: case TOMOYO_TYPE_CHROOT: + case TOMOYO_TYPE_UMOUNT: tomoyo_add_slash(&buf); break; } @@ -1442,8 +1489,9 @@ int tomoyo_path_number3_perm(const u8 operation, struct path *path, struct tomoyo_path_info buf; int idx; - if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || - !path->mnt) + if (!path->mnt || + tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation]) + == TOMOYO_CONFIG_DISABLED) return 0; idx = tomoyo_read_lock(); error = -ENOMEM; @@ -1477,8 +1525,9 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, struct tomoyo_request_info r; int idx; - if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED || - !path1->mnt || !path2->mnt) + if (!path1->mnt || !path2->mnt || + tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation]) + == TOMOYO_CONFIG_DISABLED) return 0; buf1.name = NULL; buf2.name = NULL; @@ -1486,13 +1535,19 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, if (!tomoyo_get_realpath(&buf1, path1) || !tomoyo_get_realpath(&buf2, path2)) goto out; - { - struct dentry *dentry = path1->dentry; - if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) { - tomoyo_add_slash(&buf1); - tomoyo_add_slash(&buf2); - } - } + switch (operation) { + struct dentry *dentry; + case TOMOYO_TYPE_RENAME: + case TOMOYO_TYPE_LINK: + dentry = path1->dentry; + if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode)) + break; + /* fall through */ + case TOMOYO_TYPE_PIVOT_ROOT: + tomoyo_add_slash(&buf1); + tomoyo_add_slash(&buf2); + break; + } do { error = tomoyo_path2_acl(&r, operation, &buf1, &buf2); if (!error) diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 7c1c7fdd3681..77ee8bf41948 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -248,7 +248,8 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, int error; int idx; - if (tomoyo_init_request_info(&r, NULL) == TOMOYO_CONFIG_DISABLED) + if (tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_MOUNT) + == TOMOYO_CONFIG_DISABLED) return 0; if (!type) type = ""; diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 592b76a2bce8..307793ed6075 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c @@ -791,25 +791,67 @@ const char *tomoyo_get_exe(void) return cp; } +/** + * tomoyo_get_mode - Get MAC mode. + * + * @profile: Profile number. + * @index: Index number of functionality. + * + * Returns mode. + */ +int tomoyo_get_mode(const u8 profile, const u8 index) +{ + u8 mode; + const u8 category = TOMOYO_MAC_CATEGORY_FILE; + if (!tomoyo_policy_loaded) + return TOMOYO_CONFIG_DISABLED; + mode = tomoyo_profile(profile)->config[index]; + if (mode == TOMOYO_CONFIG_USE_DEFAULT) + mode = tomoyo_profile(profile)->config[category]; + if (mode == TOMOYO_CONFIG_USE_DEFAULT) + mode = tomoyo_profile(profile)->default_config; + return mode & 3; +} + /** * tomoyo_init_request_info - Initialize "struct tomoyo_request_info" members. * * @r: Pointer to "struct tomoyo_request_info" to initialize. * @domain: Pointer to "struct tomoyo_domain_info". NULL for tomoyo_domain(). + * @index: Index number of functionality. * * Returns mode. */ int tomoyo_init_request_info(struct tomoyo_request_info *r, - struct tomoyo_domain_info *domain) + struct tomoyo_domain_info *domain, const u8 index) { + u8 profile; memset(r, 0, sizeof(*r)); if (!domain) domain = tomoyo_domain(); r->domain = domain; - r->mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); + profile = domain->profile; + r->profile = profile; + r->type = index; + r->mode = tomoyo_get_mode(profile, index); return r->mode; } +/** + * tomoyo_last_word - Get last component of a line. + * + * @line: A line. + * + * Returns the last word of a line. + */ +static const char *tomoyo_last_word(const char *name) +{ + const char *cp = strrchr(name, ' '); + if (cp) + return cp + 1; + return name; +} + /** * tomoyo_warn_log - Print warning or error message on console. * @@ -818,29 +860,34 @@ int tomoyo_init_request_info(struct tomoyo_request_info *r, */ void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...) { - int len = PAGE_SIZE; va_list args; char *buffer; - if (!tomoyo_verbose_mode(r->domain)) - return; - while (1) { - int len2; - buffer = kmalloc(len, GFP_NOFS); - if (!buffer) + const struct tomoyo_domain_info * const domain = r->domain; + const struct tomoyo_profile *profile = tomoyo_profile(domain->profile); + switch (r->mode) { + case TOMOYO_CONFIG_ENFORCING: + if (!profile->enforcing->enforcing_verbose) return; - va_start(args, fmt); - len2 = vsnprintf(buffer, len - 1, fmt, args); - va_end(args); - if (len2 <= len - 1) { - buffer[len2] = '\0'; - break; - } - len = len2 + 1; - kfree(buffer); + break; + case TOMOYO_CONFIG_PERMISSIVE: + if (!profile->permissive->permissive_verbose) + return; + break; + case TOMOYO_CONFIG_LEARNING: + if (!profile->learning->learning_verbose) + return; + break; } - printk(KERN_WARNING "TOMOYO-%s: Access %s denied for %s\n", - r->mode == TOMOYO_CONFIG_ENFORCING ? "ERROR" : "WARNING", - buffer, tomoyo_get_last_name(r->domain)); + buffer = kmalloc(4096, GFP_NOFS); + if (!buffer) + return; + va_start(args, fmt); + vsnprintf(buffer, 4095, fmt, args); + va_end(args); + buffer[4095] = '\0'; + printk(KERN_WARNING "%s: Access %s denied for %s\n", + r->mode == TOMOYO_CONFIG_ENFORCING ? "ERROR" : "WARNING", buffer, + tomoyo_last_word(domain->domainname->name)); kfree(buffer); } @@ -903,7 +950,8 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) count++; } } - if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY)) + if (count < tomoyo_profile(domain->profile)->learning-> + learning_max_entry) return true; if (!domain->quota_warned) { domain->quota_warned = true; -- cgit v1.2.3 From 237ab459f12cb98eadd3fe7b85343e183a1076a4 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sat, 12 Jun 2010 20:46:22 +0900 Subject: TOMOYO: Use callback for updating entries. Use common "struct list_head" + "bool" + "u8" structure and use common code for elements using that structure. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 4 +- security/tomoyo/common.h | 82 ++++------- security/tomoyo/domain.c | 51 +++++++ security/tomoyo/file.c | 349 +++++++++++++++++++++-------------------------- security/tomoyo/gc.c | 28 +--- security/tomoyo/mount.c | 43 +++--- security/tomoyo/util.c | 8 +- 7 files changed, 253 insertions(+), 312 deletions(-) (limited to 'security/tomoyo/mount.c') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 811adb5e9fea..6556e5d27d74 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -950,8 +950,6 @@ static bool tomoyo_print_mount_acl(struct tomoyo_io_buffer *head, struct tomoyo_mount_acl *ptr) { const int pos = head->read_avail; - if (ptr->is_deleted) - return true; if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_MOUNT) || !tomoyo_print_name_union(head, &ptr->dev_name) || !tomoyo_print_name_union(head, &ptr->dir_name) || @@ -977,6 +975,8 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, { const u8 acl_type = ptr->type; + if (ptr->is_deleted) + return true; if (acl_type == TOMOYO_TYPE_PATH_ACL) { struct tomoyo_path_acl *acl = container_of(ptr, struct tomoyo_path_acl, head); diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index c777c594a00b..539b9a28b739 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -112,6 +112,8 @@ enum tomoyo_path_acl_index { TOMOYO_MAX_PATH_OPERATION }; +#define TOMOYO_RW_MASK ((1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE)) + enum tomoyo_path_number3_acl_index { TOMOYO_TYPE_MKBLOCK, TOMOYO_TYPE_MKCHAR, @@ -289,17 +291,19 @@ struct tomoyo_number_group_member { * * (1) "list" which is linked to the ->acl_info_list of * "struct tomoyo_domain_info" - * (2) "type" which tells type of the entry (either - * "struct tomoyo_path_acl" or "struct tomoyo_path2_acl"). + * (2) "is_deleted" is a bool which is true if this domain is marked as + * "deleted", false otherwise. + * (3) "type" which tells type of the entry. * * Packing "struct tomoyo_acl_info" allows - * "struct tomoyo_path_acl" to embed "u8" + "u16" and - * "struct tomoyo_path2_acl" to embed "u8" - * without enlarging their structure size. + * "struct tomoyo_path_acl" to embed "u16" and "struct tomoyo_path2_acl" + * "struct tomoyo_path_number_acl" "struct tomoyo_path_number3_acl" to embed + * "u8" without enlarging their structure size. */ struct tomoyo_acl_info { struct list_head list; - u8 type; + bool is_deleted; + u8 type; /* = one of values in "enum tomoyo_acl_entry_type_index". */ } __packed; /* @@ -438,17 +442,15 @@ struct tomoyo_path2_acl { * It has following fields. * * (1) "head" which is a "struct tomoyo_acl_info". - * (2) "is_deleted" is boolean. - * (3) "dev_name" is the device name. - * (4) "dir_name" is the mount point. + * (2) "dev_name" is the device name. + * (3) "dir_name" is the mount point. + * (4) "fs_type" is the filesystem type. * (5) "flags" is the mount flags. * - * Directives held by this structure are "allow_rename", "allow_link" and - * "allow_pivot_root". + * Directive held by this structure is "allow_mount". */ struct tomoyo_mount_acl { struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MOUNT_ACL */ - bool is_deleted; struct tomoyo_name_union dev_name; struct tomoyo_name_union dir_name; struct tomoyo_name_union fs_type; @@ -914,6 +916,16 @@ void tomoyo_run_gc(void); void tomoyo_memory_free(void *ptr); +int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, + bool is_delete, struct tomoyo_domain_info *domain, + 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)); + /********** External variable definitions. **********/ /* Lock for GC. */ @@ -1042,52 +1054,6 @@ static inline bool tomoyo_is_same_number_union p1->max_type == p2->max_type && p1->is_group == p2->is_group; } -static inline bool tomoyo_is_same_path_acl(const struct tomoyo_path_acl *p1, - const struct tomoyo_path_acl *p2) -{ - return tomoyo_is_same_acl_head(&p1->head, &p2->head) && - tomoyo_is_same_name_union(&p1->name, &p2->name); -} - -static inline bool tomoyo_is_same_path_number3_acl -(const struct tomoyo_path_number3_acl *p1, - const struct tomoyo_path_number3_acl *p2) -{ - return tomoyo_is_same_acl_head(&p1->head, &p2->head) - && tomoyo_is_same_name_union(&p1->name, &p2->name) - && tomoyo_is_same_number_union(&p1->mode, &p2->mode) - && tomoyo_is_same_number_union(&p1->major, &p2->major) - && tomoyo_is_same_number_union(&p1->minor, &p2->minor); -} - - -static inline bool tomoyo_is_same_path2_acl(const struct tomoyo_path2_acl *p1, - const struct tomoyo_path2_acl *p2) -{ - return tomoyo_is_same_acl_head(&p1->head, &p2->head) && - tomoyo_is_same_name_union(&p1->name1, &p2->name1) && - tomoyo_is_same_name_union(&p1->name2, &p2->name2); -} - -static inline bool tomoyo_is_same_path_number_acl -(const struct tomoyo_path_number_acl *p1, - const struct tomoyo_path_number_acl *p2) -{ - return tomoyo_is_same_acl_head(&p1->head, &p2->head) - && tomoyo_is_same_name_union(&p1->name, &p2->name) - && tomoyo_is_same_number_union(&p1->number, &p2->number); -} - -static inline bool tomoyo_is_same_mount_acl(const struct tomoyo_mount_acl *p1, - const struct tomoyo_mount_acl *p2) -{ - return tomoyo_is_same_acl_head(&p1->head, &p2->head) && - tomoyo_is_same_name_union(&p1->dev_name, &p2->dev_name) && - tomoyo_is_same_name_union(&p1->dir_name, &p2->dir_name) && - tomoyo_is_same_name_union(&p1->fs_type, &p2->fs_type) && - tomoyo_is_same_number_union(&p1->flags, &p2->flags); -} - static inline bool tomoyo_is_same_domain_initializer_entry (const struct tomoyo_domain_initializer_entry *p1, const struct tomoyo_domain_initializer_entry *p2) diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 09ec37c12a9c..f774e73e0022 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -15,6 +15,57 @@ /* The initial domain. */ struct tomoyo_domain_info tomoyo_kernel_domain; +/** + * tomoyo_update_domain - Update an entry for domain policy. + * + * @new_entry: Pointer to "struct tomoyo_acl_info". + * @size: Size of @new_entry in bytes. + * @is_delete: True if it is a delete request. + * @domain: Pointer to "struct tomoyo_domain_info". + * @check_duplicate: Callback function to find duplicated entry. + * @merge_duplicate: Callback function to merge duplicated entry. + * + * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). + */ +int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, + bool is_delete, struct tomoyo_domain_info *domain, + 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)) +{ + int error = is_delete ? -ENOENT : -ENOMEM; + struct tomoyo_acl_info *entry; + + if (mutex_lock_interruptible(&tomoyo_policy_lock)) + return error; + list_for_each_entry_rcu(entry, &domain->acl_info_list, list) { + if (!check_duplicate(entry, new_entry)) + continue; + if (merge_duplicate) + entry->is_deleted = merge_duplicate(entry, new_entry, + is_delete); + else + entry->is_deleted = is_delete; + error = 0; + break; + } + if (error && !is_delete) { + entry = tomoyo_commit_ok(new_entry, size); + if (entry) { + list_add_tail_rcu(&entry->list, &domain->acl_info_list); + error = 0; + } + } + mutex_unlock(&tomoyo_policy_lock); + return error; +} + /* * tomoyo_domain_list is used for holding list of domains. * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 8e51348d022e..b826058c72e9 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -664,50 +664,6 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) return done; } -/** - * tomoyo_update_file_acl - Update file's read/write/execute ACL. - * - * @perm: Permission (between 1 to 7). - * @filename: Filename. - * @domain: Pointer to "struct tomoyo_domain_info". - * @is_delete: True if it is a delete request. - * - * Returns 0 on success, negative value otherwise. - * - * This is legacy support interface for older policy syntax. - * Current policy syntax uses "allow_read/write" instead of "6", - * "allow_read" instead of "4", "allow_write" instead of "2", - * "allow_execute" instead of "1". - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_update_file_acl(u8 perm, const char *filename, - struct tomoyo_domain_info * const domain, - const bool is_delete) -{ - if (perm > 7 || !perm) { - printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n", - __func__, perm, filename); - return -EINVAL; - } - if (filename[0] != '@' && tomoyo_strendswith(filename, "/")) - /* - * Only 'allow_mkdir' and 'allow_rmdir' are valid for - * directory permissions. - */ - return 0; - if (perm & 4) - tomoyo_update_path_acl(TOMOYO_TYPE_READ, filename, domain, - is_delete); - if (perm & 2) - tomoyo_update_path_acl(TOMOYO_TYPE_WRITE, filename, domain, - is_delete); - if (perm & 1) - tomoyo_update_path_acl(TOMOYO_TYPE_EXECUTE, filename, domain, - is_delete); - return 0; -} - /** * tomoyo_path_acl - Check permission for single path operation. * @@ -797,6 +753,40 @@ static int tomoyo_file_perm(struct tomoyo_request_info *r, return error; } +static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, + const struct tomoyo_acl_info *b) +{ + const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); + const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); + return tomoyo_is_same_acl_head(&p1->head, &p2->head) && + tomoyo_is_same_name_union(&p1->name, &p2->name); +} + +static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, + struct tomoyo_acl_info *b, + const bool is_delete) +{ + u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head) + ->perm; + u16 perm = *a_perm; + const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; + if (is_delete) { + perm &= ~b_perm; + if ((perm & TOMOYO_RW_MASK) != TOMOYO_RW_MASK) + perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); + else if (!(perm & (1 << TOMOYO_TYPE_READ_WRITE))) + perm &= ~TOMOYO_RW_MASK; + } else { + perm |= b_perm; + if ((perm & TOMOYO_RW_MASK) == TOMOYO_RW_MASK) + perm |= (1 << TOMOYO_TYPE_READ_WRITE); + else if (perm & (1 << TOMOYO_TYPE_READ_WRITE)) + perm |= TOMOYO_RW_MASK; + } + *a_perm = perm; + return !perm; +} + /** * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. * @@ -810,63 +800,56 @@ static int tomoyo_file_perm(struct tomoyo_request_info *r, * Caller holds tomoyo_read_lock(). */ static int tomoyo_update_path_acl(const u8 type, const char *filename, - struct tomoyo_domain_info *const domain, + struct tomoyo_domain_info * const domain, const bool is_delete) { - static const u16 tomoyo_rw_mask = - (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); - const u16 perm = 1 << type; - struct tomoyo_acl_info *ptr; struct tomoyo_path_acl e = { .head.type = TOMOYO_TYPE_PATH_ACL, - .perm = perm + .perm = 1 << type }; - int error = is_delete ? -ENOENT : -ENOMEM; - - if (type == TOMOYO_TYPE_READ_WRITE) - e.perm |= tomoyo_rw_mask; - if (!domain) - return -EINVAL; + int error; + if (e.perm == (1 << TOMOYO_TYPE_READ_WRITE)) + e.perm |= TOMOYO_RW_MASK; if (!tomoyo_parse_name_union(filename, &e.name)) return -EINVAL; - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - goto out; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - struct tomoyo_path_acl *acl = - container_of(ptr, struct tomoyo_path_acl, head); - if (!tomoyo_is_same_path_acl(acl, &e)) - continue; - if (is_delete) { - acl->perm &= ~perm; - if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask) - acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); - else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))) - acl->perm &= ~tomoyo_rw_mask; - } else { - acl->perm |= perm; - if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask) - acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE; - else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)) - acl->perm |= tomoyo_rw_mask; - } - error = 0; - break; - } - if (!is_delete && error) { - struct tomoyo_path_acl *entry = - tomoyo_commit_ok(&e, sizeof(e)); - if (entry) { - list_add_tail_rcu(&entry->head.list, - &domain->acl_info_list); - error = 0; - } - } - mutex_unlock(&tomoyo_policy_lock); - out: + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, + tomoyo_same_path_acl, + tomoyo_merge_path_acl); tomoyo_put_name_union(&e.name); return error; } +static bool tomoyo_same_path_number3_acl(const struct tomoyo_acl_info *a, + const struct tomoyo_acl_info *b) +{ + const struct tomoyo_path_number3_acl *p1 = container_of(a, typeof(*p1), + head); + const struct tomoyo_path_number3_acl *p2 = container_of(b, typeof(*p2), + head); + return tomoyo_is_same_acl_head(&p1->head, &p2->head) + && tomoyo_is_same_name_union(&p1->name, &p2->name) + && tomoyo_is_same_number_union(&p1->mode, &p2->mode) + && tomoyo_is_same_number_union(&p1->major, &p2->major) + && tomoyo_is_same_number_union(&p1->minor, &p2->minor); +} + +static bool tomoyo_merge_path_number3_acl(struct tomoyo_acl_info *a, + struct tomoyo_acl_info *b, + const bool is_delete) +{ + u8 *const a_perm = &container_of(a, struct tomoyo_path_number3_acl, + head)->perm; + u8 perm = *a_perm; + const u8 b_perm = container_of(b, struct tomoyo_path_number3_acl, head) + ->perm; + if (is_delete) + perm &= ~b_perm; + else + perm |= b_perm; + *a_perm = perm; + return !perm; +} + /** * tomoyo_update_path_number3_acl - Update "struct tomoyo_path_number3_acl" list. * @@ -879,20 +862,17 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ -static inline int tomoyo_update_path_number3_acl(const u8 type, - const char *filename, - char *mode, - char *major, char *minor, - struct tomoyo_domain_info * - const domain, - const bool is_delete) +static int tomoyo_update_path_number3_acl(const u8 type, const char *filename, + char *mode, char *major, char *minor, + struct tomoyo_domain_info * const + domain, 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, - .perm = perm + .perm = 1 << type }; int error = is_delete ? -ENOENT : -ENOMEM; if (!tomoyo_parse_name_union(filename, &e.name) || @@ -900,30 +880,9 @@ static inline int tomoyo_update_path_number3_acl(const u8 type, !tomoyo_parse_number_union(major, &e.major) || !tomoyo_parse_number_union(minor, &e.minor)) goto out; - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - goto out; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - struct tomoyo_path_number3_acl *acl = - container_of(ptr, struct tomoyo_path_number3_acl, head); - if (!tomoyo_is_same_path_number3_acl(acl, &e)) - continue; - if (is_delete) - acl->perm &= ~perm; - else - acl->perm |= perm; - error = 0; - break; - } - if (!is_delete && error) { - 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); - error = 0; - } - } - mutex_unlock(&tomoyo_policy_lock); + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, + tomoyo_same_path_number3_acl, + tomoyo_merge_path_number3_acl); out: tomoyo_put_name_union(&e.name); tomoyo_put_number_union(&e.mode); @@ -932,6 +891,32 @@ static inline int tomoyo_update_path_number3_acl(const u8 type, return error; } +static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a, + const struct tomoyo_acl_info *b) +{ + const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); + const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); + return tomoyo_is_same_acl_head(&p1->head, &p2->head) + && tomoyo_is_same_name_union(&p1->name1, &p2->name1) + && tomoyo_is_same_name_union(&p1->name2, &p2->name2); +} + +static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, + struct tomoyo_acl_info *b, + const bool is_delete) +{ + u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head) + ->perm; + u8 perm = *a_perm; + const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm; + if (is_delete) + perm &= ~b_perm; + else + perm |= b_perm; + *a_perm = perm; + return !perm; +} + /** * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. * @@ -947,46 +932,20 @@ static inline int tomoyo_update_path_number3_acl(const u8 type, */ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, const char *filename2, - struct tomoyo_domain_info *const domain, + struct tomoyo_domain_info * const domain, const bool is_delete) { - const u8 perm = 1 << type; struct tomoyo_path2_acl e = { .head.type = TOMOYO_TYPE_PATH2_ACL, - .perm = perm + .perm = 1 << type }; - struct tomoyo_acl_info *ptr; int error = is_delete ? -ENOENT : -ENOMEM; - - if (!domain) - return -EINVAL; if (!tomoyo_parse_name_union(filename1, &e.name1) || !tomoyo_parse_name_union(filename2, &e.name2)) goto out; - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - goto out; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - struct tomoyo_path2_acl *acl = - container_of(ptr, struct tomoyo_path2_acl, head); - if (!tomoyo_is_same_path2_acl(acl, &e)) - continue; - if (is_delete) - acl->perm &= ~perm; - else - acl->perm |= perm; - error = 0; - break; - } - if (!is_delete && error) { - struct tomoyo_path2_acl *entry = - tomoyo_commit_ok(&e, sizeof(e)); - if (entry) { - list_add_tail_rcu(&entry->head.list, - &domain->acl_info_list); - error = 0; - } - } - mutex_unlock(&tomoyo_policy_lock); + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, + tomoyo_same_path2_acl, + tomoyo_merge_path2_acl); out: tomoyo_put_name_union(&e.name1); tomoyo_put_name_union(&e.name2); @@ -1157,6 +1116,35 @@ static int tomoyo_path_number_acl(struct tomoyo_request_info *r, const u8 type, return error; } +static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, + const struct tomoyo_acl_info *b) +{ + const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1), + head); + const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), + head); + return tomoyo_is_same_acl_head(&p1->head, &p2->head) + && tomoyo_is_same_name_union(&p1->name, &p2->name) + && tomoyo_is_same_number_union(&p1->number, &p2->number); +} + +static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, + struct tomoyo_acl_info *b, + const bool is_delete) +{ + u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl, + head)->perm; + u8 perm = *a_perm; + const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head) + ->perm; + if (is_delete) + perm &= ~b_perm; + else + perm |= b_perm; + *a_perm = perm; + return !perm; +} + /** * tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL. * @@ -1168,50 +1156,24 @@ static int tomoyo_path_number_acl(struct tomoyo_request_info *r, const u8 type, * * Returns 0 on success, negative value otherwise. */ -static inline int tomoyo_update_path_number_acl(const u8 type, - const char *filename, - char *number, - struct tomoyo_domain_info * - const domain, - const bool is_delete) +static int tomoyo_update_path_number_acl(const u8 type, const char *filename, + char *number, + struct tomoyo_domain_info * const + domain, + 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, - .perm = perm + .perm = 1 << type }; int error = is_delete ? -ENOENT : -ENOMEM; - if (!domain) - return -EINVAL; if (!tomoyo_parse_name_union(filename, &e.name)) return -EINVAL; if (!tomoyo_parse_number_union(number, &e.number)) goto out; - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - goto out; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - struct tomoyo_path_number_acl *acl = - container_of(ptr, struct tomoyo_path_number_acl, head); - if (!tomoyo_is_same_path_number_acl(acl, &e)) - continue; - if (is_delete) - acl->perm &= ~perm; - else - acl->perm |= perm; - error = 0; - break; - } - if (!is_delete && error) { - 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); - error = 0; - } - } - mutex_unlock(&tomoyo_policy_lock); + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, + tomoyo_same_path_number_acl, + tomoyo_merge_path_number_acl); out: tomoyo_put_name_union(&e.name); tomoyo_put_number_union(&e.number); @@ -1585,13 +1547,8 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, u8 type; if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0]) return -EINVAL; - if (strncmp(w[0], "allow_", 6)) { - unsigned int perm; - if (sscanf(w[0], "%u", &perm) == 1) - return tomoyo_update_file_acl((u8) perm, w[1], domain, - is_delete); + if (strncmp(w[0], "allow_", 6)) goto out; - } w[0] += 6; for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { if (strcmp(w[0], tomoyo_path_keyword[type])) diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 8a31f0c628b2..aed7ddd0de84 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c @@ -310,34 +310,8 @@ static void tomoyo_collect_entry(void) struct tomoyo_acl_info *acl; list_for_each_entry_rcu(acl, &domain->acl_info_list, list) { - switch (acl->type) { - case TOMOYO_TYPE_PATH_ACL: - if (container_of(acl, - struct tomoyo_path_acl, - head)->perm) - continue; - break; - case TOMOYO_TYPE_PATH2_ACL: - if (container_of(acl, - struct tomoyo_path2_acl, - head)->perm) - continue; - break; - case TOMOYO_TYPE_PATH_NUMBER_ACL: - if (container_of(acl, - struct tomoyo_path_number_acl, - head)->perm) - continue; - break; - case TOMOYO_TYPE_PATH_NUMBER3_ACL: - if (container_of(acl, - struct tomoyo_path_number3_acl, - head)->perm) - continue; - break; - default: + if (!acl->is_deleted) continue; - } if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl)) list_del_rcu(&acl->list); else diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 77ee8bf41948..c170b41c3833 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -114,11 +114,10 @@ static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name, tomoyo_fill_path_info(&rdev); list_for_each_entry_rcu(ptr, &r->domain->acl_info_list, list) { struct tomoyo_mount_acl *acl; - if (ptr->type != TOMOYO_TYPE_MOUNT_ACL) + if (ptr->is_deleted || ptr->type != TOMOYO_TYPE_MOUNT_ACL) continue; acl = container_of(ptr, struct tomoyo_mount_acl, head); - if (acl->is_deleted || - !tomoyo_compare_number_union(flags, &acl->flags) || + if (!tomoyo_compare_number_union(flags, &acl->flags) || !tomoyo_compare_name_union(&rtype, &acl->fs_type) || !tomoyo_compare_name_union(&rdir, &acl->dir_name) || (need_dev && @@ -259,6 +258,18 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, return error; } +static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, + const struct tomoyo_acl_info *b) +{ + const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); + const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); + return tomoyo_is_same_acl_head(&p1->head, &p2->head) && + tomoyo_is_same_name_union(&p1->dev_name, &p2->dev_name) && + tomoyo_is_same_name_union(&p1->dir_name, &p2->dir_name) && + tomoyo_is_same_name_union(&p1->fs_type, &p2->fs_type) && + tomoyo_is_same_number_union(&p1->flags, &p2->flags); +} + /** * tomoyo_write_mount_policy - Write "struct tomoyo_mount_acl" list. * @@ -267,11 +278,12 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, * @is_delete: True if it is a delete request. * * Returns 0 on success, negative value otherwise. + * + * Caller holds tomoyo_read_lock(). */ int tomoyo_write_mount_policy(char *data, struct tomoyo_domain_info *domain, const bool is_delete) { - struct tomoyo_acl_info *ptr; struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; int error = is_delete ? -ENOENT : -ENOMEM; char *w[4]; @@ -282,27 +294,8 @@ int tomoyo_write_mount_policy(char *data, struct tomoyo_domain_info *domain, !tomoyo_parse_name_union(w[2], &e.fs_type) || !tomoyo_parse_number_union(w[3], &e.flags)) goto out; - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - goto out; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - struct tomoyo_mount_acl *acl = - container_of(ptr, struct tomoyo_mount_acl, head); - if (!tomoyo_is_same_mount_acl(acl, &e)) - continue; - acl->is_deleted = is_delete; - error = 0; - break; - } - if (!is_delete && error) { - struct tomoyo_mount_acl *entry = - tomoyo_commit_ok(&e, sizeof(e)); - if (entry) { - list_add_tail_rcu(&entry->head.list, - &domain->acl_info_list); - error = 0; - } - } - mutex_unlock(&tomoyo_policy_lock); + error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, + tomoyo_same_mount_acl, NULL); out: tomoyo_put_name_union(&e.dev_name); tomoyo_put_name_union(&e.dir_name); diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 307793ed6075..e5931686ca33 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c @@ -911,6 +911,8 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) if (!domain) return true; list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { + if (!ptr->is_deleted) + continue; switch (ptr->type) { u16 perm; u8 i; @@ -944,10 +946,8 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) if (perm & (1 << i)) count++; break; - case TOMOYO_TYPE_MOUNT_ACL: - if (!container_of(ptr, struct tomoyo_mount_acl, head)-> - is_deleted) - count++; + default: + count++; } } if (count < tomoyo_profile(domain->profile)->learning-> -- cgit v1.2.3 From cf6e9a6468ec82a94cbc707b607452ec4454182c Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Wed, 16 Jun 2010 16:21:36 +0900 Subject: TOMOYO: Pass parameters via structure. To make it possible to use callback function, pass parameters via "struct tomoyo_request_info". Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.h | 33 +++++++++++++++++++++++++++++++++ security/tomoyo/file.c | 20 +++++++++++++++++++- security/tomoyo/mount.c | 6 ++++++ 3 files changed, 58 insertions(+), 1 deletion(-) (limited to 'security/tomoyo/mount.c') diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 203454025410..f055e273ec02 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -212,6 +212,39 @@ struct tomoyo_acl_head { */ struct tomoyo_request_info { struct tomoyo_domain_info *domain; + /* For holding parameters. */ + union { + struct { + const struct tomoyo_path_info *filename; + u8 operation; + } path; + struct { + const struct tomoyo_path_info *filename1; + const struct tomoyo_path_info *filename2; + u8 operation; + } path2; + struct { + const struct tomoyo_path_info *filename; + unsigned int mode; + unsigned int major; + unsigned int minor; + u8 operation; + } mkdev; + struct { + const struct tomoyo_path_info *filename; + unsigned long number; + u8 operation; + } path_number; + struct { + const struct tomoyo_path_info *type; + const struct tomoyo_path_info *dir; + const struct tomoyo_path_info *dev; + unsigned long flags; + int need_dev; + } mount; + } param; + u8 param_type; + bool granted; u8 retry; u8 profile; u8 mode; /* One of tomoyo_mode_index . */ diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 50875d7e8603..32661df10e85 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -973,6 +973,9 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, r->mode = tomoyo_get_mode(r->profile, r->type); if (r->mode == TOMOYO_CONFIG_DISABLED) return 0; + r->param_type = TOMOYO_TYPE_PATH_ACL; + r->param.path.filename = filename; + r->param.path.operation = operation; do { error = tomoyo_path_acl(r, filename, 1 << operation); if (error && operation == TOMOYO_TYPE_READ && @@ -1143,6 +1146,10 @@ static int tomoyo_path_number_perm2(struct tomoyo_request_info *r, break; } tomoyo_print_ulong(buffer, sizeof(buffer), number, radix); + r->param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; + r->param.path_number.operation = type; + r->param.path_number.filename = filename; + r->param.path_number.number = number; do { error = tomoyo_path_number_acl(r, type, filename, number); if (!error) @@ -1369,8 +1376,15 @@ int tomoyo_path_number3_perm(const u8 operation, struct path *path, idx = tomoyo_read_lock(); error = -ENOMEM; if (tomoyo_get_realpath(&buf, path)) { + dev = new_decode_dev(dev); + r.param_type = TOMOYO_TYPE_PATH_NUMBER3_ACL; + r.param.mkdev.filename = &buf; + r.param.mkdev.operation = operation; + r.param.mkdev.mode = mode; + r.param.mkdev.major = MAJOR(dev); + r.param.mkdev.minor = MINOR(dev); error = tomoyo_path_number3_perm2(&r, operation, &buf, mode, - new_decode_dev(dev)); + dev); kfree(buf.name); } tomoyo_read_unlock(idx); @@ -1421,6 +1435,10 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, tomoyo_add_slash(&buf2); break; } + r.param_type = TOMOYO_TYPE_PATH2_ACL; + r.param.path2.operation = operation; + r.param.path2.filename1 = &buf1; + r.param.path2.filename2 = &buf2; do { error = tomoyo_path2_acl(&r, operation, &buf1, &buf2); if (!error) diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index c170b41c3833..554de173152c 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -112,6 +112,12 @@ static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name, } rdev.name = requested_dev_name; tomoyo_fill_path_info(&rdev); + r->param_type = TOMOYO_TYPE_MOUNT_ACL; + r->param.mount.need_dev = need_dev; + r->param.mount.dev = &rdev; + r->param.mount.dir = &rdir; + r->param.mount.type = &rtype; + r->param.mount.flags = flags; list_for_each_entry_rcu(ptr, &r->domain->acl_info_list, list) { struct tomoyo_mount_acl *acl; if (ptr->is_deleted || ptr->type != TOMOYO_TYPE_MOUNT_ACL) -- cgit v1.2.3 From 99a852596beb26cc449ca1a79834c107ef4080e1 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Wed, 16 Jun 2010 16:22:51 +0900 Subject: TOMOYO: Use callback for permission check. We can use callback function since parameters are passed via "const struct tomoyo_request_info". Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.h | 3 + security/tomoyo/domain.c | 18 +++ security/tomoyo/file.c | 394 +++++++++++++++++++---------------------------- security/tomoyo/mount.c | 73 ++++++--- 4 files changed, 230 insertions(+), 258 deletions(-) (limited to 'security/tomoyo/mount.c') diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index f055e273ec02..36b027460ea6 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -952,6 +952,9 @@ 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 *, + const struct tomoyo_acl_info *)); /********** External variable definitions. **********/ diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 35317e783f34..13f4f39baf8f 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -109,6 +109,24 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, return error; } +void tomoyo_check_acl(struct tomoyo_request_info *r, + bool (*check_entry) (const struct tomoyo_request_info *, + const struct tomoyo_acl_info *)) +{ + const struct tomoyo_domain_info *domain = r->domain; + struct tomoyo_acl_info *ptr; + + list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { + if (ptr->is_deleted || ptr->type != r->param_type) + continue; + if (check_entry(r, ptr)) { + r->granted = true; + return; + } + } + r->granted = false; +} + /* * tomoyo_domain_list is used for holding list of domains. * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 32661df10e85..18969e77f5e8 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -218,6 +218,108 @@ static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path) return false; } +/** + * tomoyo_audit_path_log - Audit path request log. + * + * @r: Pointer to "struct tomoyo_request_info". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_audit_path_log(struct tomoyo_request_info *r) +{ + const char *operation = tomoyo_path_keyword[r->param.path.operation]; + const struct tomoyo_path_info *filename = r->param.path.filename; + if (r->granted) + return 0; + tomoyo_warn_log(r, "%s %s", operation, filename->name); + return tomoyo_supervisor(r, "allow_%s %s\n", operation, + tomoyo_file_pattern(filename)); +} + +/** + * tomoyo_audit_path2_log - Audit path/path request log. + * + * @r: Pointer to "struct tomoyo_request_info". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) +{ + const char *operation = tomoyo_path2_keyword[r->param.path2.operation]; + const struct tomoyo_path_info *filename1 = r->param.path2.filename1; + const struct tomoyo_path_info *filename2 = r->param.path2.filename2; + if (r->granted) + return 0; + tomoyo_warn_log(r, "%s %s %s", operation, filename1->name, + filename2->name); + return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, + tomoyo_file_pattern(filename1), + tomoyo_file_pattern(filename2)); +} + +/** + * tomoyo_audit_mkdev_log - Audit path/number/number/number request log. + * + * @r: Pointer to "struct tomoyo_request_info". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r) +{ + const char *operation = tomoyo_path_number32keyword(r->param.mkdev. + operation); + const struct tomoyo_path_info *filename = r->param.mkdev.filename; + const unsigned int major = r->param.mkdev.major; + const unsigned int minor = r->param.mkdev.minor; + const unsigned int mode = r->param.mkdev.mode; + if (r->granted) + return 0; + tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode, + major, minor); + return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation, + tomoyo_file_pattern(filename), mode, major, + minor); +} + +/** + * tomoyo_audit_path_number_log - Audit path/number request log. + * + * @r: Pointer to "struct tomoyo_request_info". + * @error: Error code. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) +{ + const u8 type = r->param.path_number.operation; + u8 radix; + const struct tomoyo_path_info *filename = r->param.path_number.filename; + const char *operation = tomoyo_path_number_keyword[type]; + char buffer[64]; + if (r->granted) + return 0; + switch (type) { + case TOMOYO_TYPE_CREATE: + case TOMOYO_TYPE_MKDIR: + case TOMOYO_TYPE_MKFIFO: + case TOMOYO_TYPE_MKSOCK: + case TOMOYO_TYPE_CHMOD: + radix = TOMOYO_VALUE_TYPE_OCTAL; + break; + case TOMOYO_TYPE_IOCTL: + radix = TOMOYO_VALUE_TYPE_HEXADECIMAL; + break; + default: + radix = TOMOYO_VALUE_TYPE_DECIMAL; + break; + } + tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number, + radix); + tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer); + return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, + tomoyo_file_pattern(filename), buffer); +} + static int tomoyo_update_path2_acl(const u8 type, const char *filename1, const char *filename2, struct tomoyo_domain_info *const domain, @@ -637,37 +739,52 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) return done; } -/** - * tomoyo_path_acl - Check permission for single path operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @filename: Filename to check. - * @perm: Permission. - * - * Returns 0 on success, -EPERM otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_path_acl(const struct tomoyo_request_info *r, - const struct tomoyo_path_info *filename, - const u32 perm) +static bool tomoyo_check_path_acl(const struct tomoyo_request_info *r, + const struct tomoyo_acl_info *ptr) { - struct tomoyo_domain_info *domain = r->domain; - struct tomoyo_acl_info *ptr; - int error = -EPERM; + 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); +} - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - struct tomoyo_path_acl *acl; - if (ptr->type != TOMOYO_TYPE_PATH_ACL) - continue; - acl = container_of(ptr, struct tomoyo_path_acl, head); - if (!(acl->perm & perm) || - !tomoyo_compare_name_union(filename, &acl->name)) - continue; - error = 0; - break; - } - return error; +static bool tomoyo_check_path_number_acl(const struct tomoyo_request_info *r, + const struct tomoyo_acl_info *ptr) +{ + const struct tomoyo_path_number_acl *acl = + container_of(ptr, typeof(*acl), head); + return (acl->perm & (1 << r->param.path_number.operation)) && + tomoyo_compare_number_union(r->param.path_number.number, + &acl->number) && + tomoyo_compare_name_union(r->param.path_number.filename, + &acl->name); +} + +static bool tomoyo_check_path2_acl(const struct tomoyo_request_info *r, + const struct tomoyo_acl_info *ptr) +{ + const struct tomoyo_path2_acl *acl = + container_of(ptr, typeof(*acl), head); + return (acl->perm & (1 << r->param.path2.operation)) && + tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1) + && tomoyo_compare_name_union(r->param.path2.filename2, + &acl->name2); +} + +static bool tomoyo_check_mkdev_acl(const struct tomoyo_request_info *r, + const struct tomoyo_acl_info *ptr) +{ + const struct tomoyo_path_number3_acl *acl = + container_of(ptr, typeof(*acl), head); + return (acl->perm & (1 << r->param.mkdev.operation)) && + tomoyo_compare_number_union(r->param.mkdev.mode, + &acl->mode) && + tomoyo_compare_number_union(r->param.mkdev.major, + &acl->major) && + tomoyo_compare_number_union(r->param.mkdev.minor, + &acl->minor) && + tomoyo_compare_name_union(r->param.mkdev.filename, + &acl->name); } static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, @@ -869,88 +986,6 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1, return error; } -/** - * tomoyo_path_number3_acl - Check permission for path/number/number/number operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @filename: Filename to check. - * @perm: Permission. - * @mode: Create mode. - * @major: Device major number. - * @minor: Device minor number. - * - * Returns 0 on success, -EPERM otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_path_number3_acl(struct tomoyo_request_info *r, - const struct tomoyo_path_info *filename, - const u16 perm, const unsigned int mode, - const unsigned int major, - const unsigned int minor) -{ - struct tomoyo_domain_info *domain = r->domain; - struct tomoyo_acl_info *ptr; - int error = -EPERM; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - struct tomoyo_path_number3_acl *acl; - if (ptr->type != TOMOYO_TYPE_PATH_NUMBER3_ACL) - continue; - acl = container_of(ptr, struct tomoyo_path_number3_acl, head); - if (!tomoyo_compare_number_union(mode, &acl->mode)) - continue; - if (!tomoyo_compare_number_union(major, &acl->major)) - continue; - if (!tomoyo_compare_number_union(minor, &acl->minor)) - continue; - if (!(acl->perm & perm)) - continue; - if (!tomoyo_compare_name_union(filename, &acl->name)) - continue; - error = 0; - break; - } - return error; -} - -/** - * tomoyo_path2_acl - Check permission for double path operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @type: Type of operation. - * @filename1: First filename to check. - * @filename2: Second filename to check. - * - * Returns 0 on success, -EPERM otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_path2_acl(const struct tomoyo_request_info *r, const u8 type, - const struct tomoyo_path_info *filename1, - const struct tomoyo_path_info *filename2) -{ - const struct tomoyo_domain_info *domain = r->domain; - struct tomoyo_acl_info *ptr; - const u8 perm = 1 << type; - int error = -EPERM; - - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - struct tomoyo_path2_acl *acl; - if (ptr->type != TOMOYO_TYPE_PATH2_ACL) - continue; - acl = container_of(ptr, struct tomoyo_path2_acl, head); - if (!(acl->perm & perm)) - continue; - if (!tomoyo_compare_name_union(filename1, &acl->name1)) - continue; - if (!tomoyo_compare_name_union(filename2, &acl->name2)) - continue; - error = 0; - break; - } - return error; -} - /** * tomoyo_path_permission - Check permission for single path operation. * @@ -965,7 +1000,6 @@ static int tomoyo_path2_acl(const struct tomoyo_request_info *r, const u8 type, int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, const struct tomoyo_path_info *filename) { - const char *msg; int error; next: @@ -977,17 +1011,12 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, r->param.path.filename = filename; r->param.path.operation = operation; do { - error = tomoyo_path_acl(r, filename, 1 << operation); - if (error && operation == TOMOYO_TYPE_READ && + tomoyo_check_acl(r, tomoyo_check_path_acl); + if (!r->granted && operation == TOMOYO_TYPE_READ && !r->domain->ignore_global_allow_read && tomoyo_is_globally_readable_file(filename)) - error = 0; - if (!error) - break; - msg = tomoyo_path2keyword(operation); - tomoyo_warn_log(r, "%s %s", msg, filename->name); - error = tomoyo_supervisor(r, "allow_%s %s\n", msg, - tomoyo_file_pattern(filename)); + r->granted = true; + error = tomoyo_audit_path_log(r); /* * Do not retry for execute request, for alias may have * changed. @@ -1007,42 +1036,6 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, return error; } -/** - * tomoyo_path_number_acl - Check permission for ioctl/chmod/chown/chgrp operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @type: Operation. - * @filename: Filename to check. - * @number: Number. - * - * Returns 0 on success, -EPERM otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_path_number_acl(struct tomoyo_request_info *r, const u8 type, - const struct tomoyo_path_info *filename, - const unsigned long number) -{ - struct tomoyo_domain_info *domain = r->domain; - struct tomoyo_acl_info *ptr; - const u8 perm = 1 << type; - int error = -EPERM; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - struct tomoyo_path_number_acl *acl; - if (ptr->type != TOMOYO_TYPE_PATH_NUMBER_ACL) - continue; - acl = container_of(ptr, struct tomoyo_path_number_acl, - head); - if (!(acl->perm & perm) || - !tomoyo_compare_number_union(number, &acl->number) || - !tomoyo_compare_name_union(filename, &acl->name)) - continue; - error = 0; - break; - } - return error; -} - static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, const struct tomoyo_acl_info *b) { @@ -1123,42 +1116,17 @@ static int tomoyo_path_number_perm2(struct tomoyo_request_info *r, const struct tomoyo_path_info *filename, const unsigned long number) { - char buffer[64]; int error; - u8 radix; - const char *msg; if (!filename) return 0; - switch (type) { - case TOMOYO_TYPE_CREATE: - case TOMOYO_TYPE_MKDIR: - case TOMOYO_TYPE_MKFIFO: - case TOMOYO_TYPE_MKSOCK: - case TOMOYO_TYPE_CHMOD: - radix = TOMOYO_VALUE_TYPE_OCTAL; - break; - case TOMOYO_TYPE_IOCTL: - radix = TOMOYO_VALUE_TYPE_HEXADECIMAL; - break; - default: - radix = TOMOYO_VALUE_TYPE_DECIMAL; - break; - } - tomoyo_print_ulong(buffer, sizeof(buffer), number, radix); r->param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; r->param.path_number.operation = type; r->param.path_number.filename = filename; r->param.path_number.number = number; do { - error = tomoyo_path_number_acl(r, type, filename, number); - if (!error) - break; - msg = tomoyo_path_number2keyword(type); - tomoyo_warn_log(r, "%s %s %s", msg, filename->name, buffer); - error = tomoyo_supervisor(r, "allow_%s %s %s\n", msg, - tomoyo_file_pattern(filename), - buffer); + tomoyo_check_acl(r, tomoyo_check_path_number_acl); + error = tomoyo_audit_path_number_log(r); } while (error == TOMOYO_RETRY_REQUEST); return error; } @@ -1310,47 +1278,6 @@ int tomoyo_path_perm(const u8 operation, struct path *path) return error; } -/** - * tomoyo_path_number3_perm2 - Check permission for path/number/number/number operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @operation: Type of operation. - * @filename: Filename to check. - * @mode: Create mode. - * @dev: Device number. - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_path_number3_perm2(struct tomoyo_request_info *r, - const u8 operation, - const struct tomoyo_path_info *filename, - const unsigned int mode, - const unsigned int dev) -{ - int error; - const char *msg; - const unsigned int major = MAJOR(dev); - const unsigned int minor = MINOR(dev); - - do { - error = tomoyo_path_number3_acl(r, filename, 1 << operation, - mode, major, minor); - if (!error) - break; - msg = tomoyo_path_number32keyword(operation); - tomoyo_warn_log(r, "%s %s 0%o %u %u", msg, filename->name, - mode, major, minor); - error = tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", msg, - tomoyo_file_pattern(filename), mode, - major, minor); - } while (error == TOMOYO_RETRY_REQUEST); - if (r->mode != TOMOYO_CONFIG_ENFORCING) - error = 0; - return error; -} - /** * tomoyo_path_number3_perm - Check permission for "mkblock" and "mkchar". * @@ -1383,8 +1310,8 @@ int tomoyo_path_number3_perm(const u8 operation, struct path *path, r.param.mkdev.mode = mode; r.param.mkdev.major = MAJOR(dev); r.param.mkdev.minor = MINOR(dev); - error = tomoyo_path_number3_perm2(&r, operation, &buf, mode, - dev); + tomoyo_check_acl(&r, tomoyo_check_mkdev_acl); + error = tomoyo_audit_mkdev_log(&r); kfree(buf.name); } tomoyo_read_unlock(idx); @@ -1406,7 +1333,6 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, struct path *path2) { int error = -ENOMEM; - const char *msg; struct tomoyo_path_info buf1; struct tomoyo_path_info buf2; struct tomoyo_request_info r; @@ -1440,15 +1366,9 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, r.param.path2.filename1 = &buf1; r.param.path2.filename2 = &buf2; do { - error = tomoyo_path2_acl(&r, operation, &buf1, &buf2); - if (!error) - break; - msg = tomoyo_path22keyword(operation); - tomoyo_warn_log(&r, "%s %s %s", msg, buf1.name, buf2.name); - error = tomoyo_supervisor(&r, "allow_%s %s %s\n", msg, - tomoyo_file_pattern(&buf1), - tomoyo_file_pattern(&buf2)); - } while (error == TOMOYO_RETRY_REQUEST); + tomoyo_check_acl(&r, tomoyo_check_path2_acl); + error = tomoyo_audit_path2_log(&r); + } while (error == TOMOYO_RETRY_REQUEST); out: kfree(buf1.name); kfree(buf2.name); diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 554de173152c..8f3ac251c571 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -24,6 +24,54 @@ /* Allow to call 'mount --make-shared /dir' */ #define TOMOYO_MOUNT_MAKE_SHARED_KEYWORD "--make-shared" +/** + * tomoyo_audit_mount_log - Audit mount log. + * + * @r: Pointer to "struct tomoyo_request_info". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_audit_mount_log(struct tomoyo_request_info *r) +{ + const char *dev = r->param.mount.dev->name; + const char *dir = r->param.mount.dir->name; + const char *type = r->param.mount.type->name; + const unsigned long flags = r->param.mount.flags; + if (r->granted) + return 0; + if (!strcmp(type, TOMOYO_MOUNT_REMOUNT_KEYWORD)) + tomoyo_warn_log(r, "mount -o remount %s 0x%lX", dir, flags); + else if (!strcmp(type, TOMOYO_MOUNT_BIND_KEYWORD) + || !strcmp(type, TOMOYO_MOUNT_MOVE_KEYWORD)) + tomoyo_warn_log(r, "mount %s %s %s 0x%lX", type, dev, dir, + flags); + else if (!strcmp(type, TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD) || + !strcmp(type, TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD) || + !strcmp(type, TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD) || + !strcmp(type, TOMOYO_MOUNT_MAKE_SHARED_KEYWORD)) + tomoyo_warn_log(r, "mount %s %s 0x%lX", type, dir, flags); + else + tomoyo_warn_log(r, "mount -t %s %s %s 0x%lX", type, dev, dir, + flags); + return tomoyo_supervisor(r, + TOMOYO_KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n", + tomoyo_file_pattern(r->param.mount.dev), + tomoyo_file_pattern(r->param.mount.dir), type, + flags); +} + +static bool tomoyo_check_mount_acl(const struct tomoyo_request_info *r, + const struct tomoyo_acl_info *ptr) +{ + const struct tomoyo_mount_acl *acl = + container_of(ptr, typeof(*acl), head); + return tomoyo_compare_number_union(r->param.mount.flags, &acl->flags) && + tomoyo_compare_name_union(r->param.mount.type, &acl->fs_type) && + tomoyo_compare_name_union(r->param.mount.dir, &acl->dir_name) && + (!r->param.mount.need_dev || + tomoyo_compare_name_union(r->param.mount.dev, &acl->dev_name)); +} + /** * tomoyo_mount_acl2 - Check permission for mount() operation. * @@ -41,7 +89,6 @@ static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name, struct path *dir, char *type, unsigned long flags) { struct path path; - struct tomoyo_acl_info *ptr; struct file_system_type *fstype = NULL; const char *requested_type = NULL; const char *requested_dir_name = NULL; @@ -118,26 +165,10 @@ static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name, r->param.mount.dir = &rdir; r->param.mount.type = &rtype; r->param.mount.flags = flags; - list_for_each_entry_rcu(ptr, &r->domain->acl_info_list, list) { - struct tomoyo_mount_acl *acl; - if (ptr->is_deleted || ptr->type != TOMOYO_TYPE_MOUNT_ACL) - continue; - acl = container_of(ptr, struct tomoyo_mount_acl, head); - if (!tomoyo_compare_number_union(flags, &acl->flags) || - !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))) - continue; - error = 0; - break; - } - if (error) - error = tomoyo_supervisor(r, TOMOYO_KEYWORD_ALLOW_MOUNT - "%s %s %s 0x%lX\n", - tomoyo_file_pattern(&rdev), - tomoyo_file_pattern(&rdir), - requested_type, flags); + do { + tomoyo_check_acl(r, tomoyo_check_mount_acl); + error = tomoyo_audit_mount_log(r); + } while (error == TOMOYO_RETRY_REQUEST); out: kfree(requested_dev_name); kfree(requested_dir_name); -- cgit v1.2.3 From 75093152a97ee0ec281895b4f6229ff3c481fd64 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Wed, 16 Jun 2010 16:23:55 +0900 Subject: TOMOYO: Rename symbols. Use shorter name in order to make it easier to fix 80 columns limit. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 44 ++++++++--------- security/tomoyo/common.h | 42 ++++++++--------- security/tomoyo/domain.c | 38 +++++++-------- security/tomoyo/file.c | 104 ++++++++++++++++++++--------------------- security/tomoyo/gc.c | 4 +- security/tomoyo/mount.c | 10 ++-- security/tomoyo/number_group.c | 2 +- security/tomoyo/path_group.c | 2 +- security/tomoyo/tomoyo.c | 2 +- security/tomoyo/util.c | 66 +++++++++++++------------- 10 files changed, 157 insertions(+), 157 deletions(-) (limited to 'security/tomoyo/mount.c') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 4ee47af0917d..1a22fff89e70 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -494,12 +494,12 @@ static int tomoyo_update_manager_entry(const char *manager, struct tomoyo_policy_manager_entry e = { }; int error; - if (tomoyo_is_domain_def(manager)) { - if (!tomoyo_is_correct_domain(manager)) + if (tomoyo_domain_def(manager)) { + if (!tomoyo_correct_domain(manager)) return -EINVAL; e.is_domain = true; } else { - if (!tomoyo_is_correct_path(manager)) + if (!tomoyo_correct_path(manager)) return -EINVAL; } e.manager = tomoyo_get_name(manager); @@ -565,14 +565,14 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) } /** - * tomoyo_is_policy_manager - Check whether the current process is a policy manager. + * tomoyo_policy_manager - Check whether the current process is a policy manager. * * Returns true if the current process is permitted to modify policy * via /sys/kernel/security/tomoyo/ interface. * * Caller holds tomoyo_read_lock(). */ -static bool tomoyo_is_policy_manager(void) +static bool tomoyo_policy_manager(void) { struct tomoyo_policy_manager_entry *ptr; const char *exe; @@ -617,7 +617,7 @@ static bool tomoyo_is_policy_manager(void) } /** - * tomoyo_is_select_one - Parse select command. + * tomoyo_select_one - Parse select command. * * @head: Pointer to "struct tomoyo_io_buffer". * @data: String to parse. @@ -626,7 +626,7 @@ static bool tomoyo_is_policy_manager(void) * * Caller holds tomoyo_read_lock(). */ -static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, +static bool tomoyo_select_one(struct tomoyo_io_buffer *head, const char *data) { unsigned int pid; @@ -647,7 +647,7 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, read_unlock(&tasklist_lock); rcu_read_unlock(); } else if (!strncmp(data, "domain=", 7)) { - if (tomoyo_is_domain_def(data + 7)) + if (tomoyo_domain_def(data + 7)) domain = tomoyo_find_domain(data + 7); } else return false; @@ -748,12 +748,12 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) is_delete = true; else if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_SELECT)) is_select = true; - if (is_select && tomoyo_is_select_one(head, data)) + if (is_select && tomoyo_select_one(head, data)) return 0; /* Don't allow updating policies by non manager programs. */ - if (!tomoyo_is_policy_manager()) + if (!tomoyo_policy_manager()) return -EPERM; - if (tomoyo_is_domain_def(data)) { + if (tomoyo_domain_def(data)) { domain = NULL; if (is_delete) tomoyo_delete_domain(data); @@ -894,26 +894,26 @@ static bool tomoyo_print_path_number_acl(struct tomoyo_io_buffer *head, } /** - * tomoyo_print_path_number3_acl - Print a path_number3 ACL entry. + * tomoyo_print_mkdev_acl - Print a mkdev ACL entry. * * @head: Pointer to "struct tomoyo_io_buffer". - * @ptr: Pointer to "struct tomoyo_path_number3_acl". + * @ptr: Pointer to "struct tomoyo_mkdev_acl". * * Returns true on success, false otherwise. */ -static bool tomoyo_print_path_number3_acl(struct tomoyo_io_buffer *head, - struct tomoyo_path_number3_acl *ptr) +static bool tomoyo_print_mkdev_acl(struct tomoyo_io_buffer *head, + struct tomoyo_mkdev_acl *ptr) { int pos; u8 bit; const u16 perm = ptr->perm; - for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_NUMBER3_OPERATION; + for (bit = head->read_bit; bit < TOMOYO_MAX_MKDEV_OPERATION; bit++) { if (!(perm & (1 << bit))) continue; pos = head->read_avail; if (!tomoyo_io_printf(head, "allow_%s", - tomoyo_path_number32keyword(bit)) || + tomoyo_mkdev2keyword(bit)) || !tomoyo_print_name_union(head, &ptr->name) || !tomoyo_print_number_union(head, &ptr->mode) || !tomoyo_print_number_union(head, &ptr->major) || @@ -984,11 +984,11 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, head); return tomoyo_print_path_number_acl(head, acl); } - if (acl_type == TOMOYO_TYPE_PATH_NUMBER3_ACL) { - struct tomoyo_path_number3_acl *acl - = container_of(ptr, struct tomoyo_path_number3_acl, + if (acl_type == TOMOYO_TYPE_MKDEV_ACL) { + struct tomoyo_mkdev_acl *acl + = container_of(ptr, struct tomoyo_mkdev_acl, head); - return tomoyo_print_path_number3_acl(head, acl); + return tomoyo_print_mkdev_acl(head, acl); } if (acl_type == TOMOYO_TYPE_MOUNT_ACL) { struct tomoyo_mount_acl *acl @@ -1910,7 +1910,7 @@ int tomoyo_write_control(struct file *file, const char __user *buffer, /* Don't allow updating policies by non manager programs. */ if (head->write != tomoyo_write_pid && head->write != tomoyo_write_domain_policy && - !tomoyo_is_policy_manager()) + !tomoyo_policy_manager()) return -EPERM; if (mutex_lock_interruptible(&head->io_sem)) return -EINTR; diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 36b027460ea6..9b106e9adbec 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -80,7 +80,7 @@ enum tomoyo_acl_entry_type_index { TOMOYO_TYPE_PATH_ACL, TOMOYO_TYPE_PATH2_ACL, TOMOYO_TYPE_PATH_NUMBER_ACL, - TOMOYO_TYPE_PATH_NUMBER3_ACL, + TOMOYO_TYPE_MKDEV_ACL, TOMOYO_TYPE_MOUNT_ACL, }; @@ -114,10 +114,10 @@ enum tomoyo_path_acl_index { #define TOMOYO_RW_MASK ((1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE)) -enum tomoyo_path_number3_acl_index { +enum tomoyo_mkdev_acl_index { TOMOYO_TYPE_MKBLOCK, TOMOYO_TYPE_MKCHAR, - TOMOYO_MAX_PATH_NUMBER3_OPERATION + TOMOYO_MAX_MKDEV_OPERATION }; enum tomoyo_path2_acl_index { @@ -342,7 +342,7 @@ struct tomoyo_number_group_member { * * Packing "struct tomoyo_acl_info" allows * "struct tomoyo_path_acl" to embed "u16" and "struct tomoyo_path2_acl" - * "struct tomoyo_path_number_acl" "struct tomoyo_path_number3_acl" to embed + * "struct tomoyo_path_number_acl" "struct tomoyo_mkdev_acl" to embed * "u8" without enlarging their structure size. */ struct tomoyo_acl_info { @@ -439,7 +439,7 @@ struct tomoyo_path_number_acl { }; /* - * tomoyo_path_number3_acl is a structure which is used for holding an + * tomoyo_mkdev_acl is a structure which is used for holding an * entry with one pathname and three numbers operation. * It has following fields. * @@ -452,8 +452,8 @@ struct tomoyo_path_number_acl { * Directives held by this structure are "allow_mkchar", "allow_mkblock". * */ -struct tomoyo_path_number3_acl { - struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_NUMBER3_ACL */ +struct tomoyo_mkdev_acl { + struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MKDEV_ACL */ u8 perm; struct tomoyo_name_union name; struct tomoyo_number_union mode; @@ -756,12 +756,12 @@ int tomoyo_get_mode(const u8 profile, const u8 index); bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); /* Check whether the domainname is correct. */ -bool tomoyo_is_correct_domain(const unsigned char *domainname); +bool tomoyo_correct_domain(const unsigned char *domainname); /* Check whether the token is correct. */ -bool tomoyo_is_correct_path(const char *filename); -bool tomoyo_is_correct_word(const char *string); +bool tomoyo_correct_path(const char *filename); +bool tomoyo_correct_word(const char *string); /* Check whether the token can be a domainname. */ -bool tomoyo_is_domain_def(const unsigned char *buffer); +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. */ @@ -807,7 +807,7 @@ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); /* Convert double path operation to operation name. */ const char *tomoyo_path22keyword(const u8 operation); const char *tomoyo_path_number2keyword(const u8 operation); -const char *tomoyo_path_number32keyword(const u8 operation); +const char *tomoyo_mkdev2keyword(const u8 operation); /* Get the last component of the given domainname. */ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); /* Convert single path operation to operation name. */ @@ -919,8 +919,8 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, struct path *path, const int flag); int tomoyo_path_number_perm(const u8 operation, struct path *path, unsigned long number); -int tomoyo_path_number3_perm(const u8 operation, struct path *path, - const unsigned int mode, unsigned int dev); +int tomoyo_mkdev_perm(const u8 operation, struct path *path, + const unsigned int mode, unsigned int dev); int tomoyo_path_perm(const u8 operation, struct path *path); int tomoyo_path2_perm(const u8 operation, struct path *path1, struct path *path2); @@ -1008,25 +1008,25 @@ static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, } /** - * tomoyo_is_valid - Check whether the character is a valid char. + * tomoyo_valid - Check whether the character is a valid char. * * @c: The character to check. * * Returns true if @c is a valid character, false otherwise. */ -static inline bool tomoyo_is_valid(const unsigned char c) +static inline bool tomoyo_valid(const unsigned char c) { return c > ' ' && c < 127; } /** - * tomoyo_is_invalid - Check whether the character is an invalid char. + * tomoyo_invalid - Check whether the character is an invalid char. * * @c: The character to check. * * Returns true if @c is an invalid character, false otherwise. */ -static inline bool tomoyo_is_invalid(const unsigned char c) +static inline bool tomoyo_invalid(const unsigned char c) { return c && (c <= ' ' || c >= 127); } @@ -1063,20 +1063,20 @@ static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct return task_cred_xxx(task, security); } -static inline bool tomoyo_is_same_acl_head(const struct tomoyo_acl_info *p1, +static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *p1, const struct tomoyo_acl_info *p2) { return p1->type == p2->type; } -static inline bool tomoyo_is_same_name_union +static inline bool tomoyo_same_name_union (const struct tomoyo_name_union *p1, const struct tomoyo_name_union *p2) { return p1->filename == p2->filename && p1->group == p2->group && p1->is_group == p2->is_group; } -static inline bool tomoyo_is_same_number_union +static inline bool tomoyo_same_number_union (const struct tomoyo_number_union *p1, const struct tomoyo_number_union *p2) { return p1->values[0] == p2->values[0] && p1->values[1] == p2->values[1] diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 13f4f39baf8f..1a122974240f 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -256,13 +256,13 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, struct tomoyo_domain_initializer_entry e = { .is_not = is_not }; int error = is_delete ? -ENOENT : -ENOMEM; - if (!tomoyo_is_correct_path(program)) + if (!tomoyo_correct_path(program)) return -EINVAL; if (domainname) { - if (!tomoyo_is_domain_def(domainname) && - tomoyo_is_correct_path(domainname)) + if (!tomoyo_domain_def(domainname) && + tomoyo_correct_path(domainname)) e.is_last_name = true; - else if (!tomoyo_is_correct_domain(domainname)) + else if (!tomoyo_correct_domain(domainname)) return -EINVAL; e.domainname = tomoyo_get_name(domainname); if (!e.domainname) @@ -346,7 +346,7 @@ int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, } /** - * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization. + * tomoyo_domain_initializer - Check whether the given program causes domainname reinitialization. * * @domainname: The name of domain. * @program: The name of program. @@ -357,7 +357,7 @@ int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, * * Caller holds tomoyo_read_lock(). */ -static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * +static bool tomoyo_domain_initializer(const struct tomoyo_path_info * domainname, const struct tomoyo_path_info *program, const struct tomoyo_path_info * @@ -462,13 +462,13 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, struct tomoyo_domain_keeper_entry e = { .is_not = is_not }; int error = is_delete ? -ENOENT : -ENOMEM; - if (!tomoyo_is_domain_def(domainname) && - tomoyo_is_correct_path(domainname)) + if (!tomoyo_domain_def(domainname) && + tomoyo_correct_path(domainname)) e.is_last_name = true; - else if (!tomoyo_is_correct_domain(domainname)) + else if (!tomoyo_correct_domain(domainname)) return -EINVAL; if (program) { - if (!tomoyo_is_correct_path(program)) + if (!tomoyo_correct_path(program)) return -EINVAL; e.program = tomoyo_get_name(program); if (!e.program) @@ -549,7 +549,7 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) } /** - * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression. + * tomoyo_domain_keeper - Check whether the given program causes domain transition suppression. * * @domainname: The name of domain. * @program: The name of program. @@ -560,7 +560,7 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) * * Caller holds tomoyo_read_lock(). */ -static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, +static bool tomoyo_domain_keeper(const struct tomoyo_path_info *domainname, const struct tomoyo_path_info *program, const struct tomoyo_path_info *last_name) { @@ -646,8 +646,8 @@ static int tomoyo_update_aggregator_entry(const char *original_name, struct tomoyo_aggregator_entry e = { }; int error = is_delete ? -ENOENT : -ENOMEM; - if (!tomoyo_is_correct_path(original_name) || - !tomoyo_is_correct_path(aggregated_name)) + if (!tomoyo_correct_path(original_name) || + !tomoyo_correct_path(aggregated_name)) return -EINVAL; e.original_name = tomoyo_get_name(original_name); e.aggregated_name = tomoyo_get_name(aggregated_name); @@ -774,8 +774,8 @@ static int tomoyo_update_alias_entry(const char *original_name, struct tomoyo_alias_entry e = { }; int error = is_delete ? -ENOENT : -ENOMEM; - if (!tomoyo_is_correct_path(original_name) || - !tomoyo_is_correct_path(aliased_name)) + if (!tomoyo_correct_path(original_name) || + !tomoyo_correct_path(aliased_name)) return -EINVAL; e.original_name = tomoyo_get_name(original_name); e.aliased_name = tomoyo_get_name(aliased_name); @@ -859,7 +859,7 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * const struct tomoyo_path_info *saved_domainname; bool found = false; - if (!tomoyo_is_correct_domain(domainname)) + if (!tomoyo_correct_domain(domainname)) return NULL; saved_domainname = tomoyo_get_name(domainname); if (!saved_domainname) @@ -984,7 +984,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) if (retval < 0) goto out; - if (tomoyo_is_domain_initializer(old_domain->domainname, &rn, &ln)) { + if (tomoyo_domain_initializer(old_domain->domainname, &rn, &ln)) { /* Transit to the child of tomoyo_kernel_domain domain. */ snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, TOMOYO_ROOT_NAME " " "%s", rn.name); @@ -996,7 +996,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) * initializers because they might start before /sbin/init. */ domain = old_domain; - } else if (tomoyo_is_domain_keeper(old_domain->domainname, &rn, &ln)) { + } else if (tomoyo_domain_keeper(old_domain->domainname, &rn, &ln)) { /* Keep current domain. */ domain = old_domain; } else { diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 18969e77f5e8..94e1493ab6b6 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -25,8 +25,8 @@ static const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { }; /* Keyword array for operations with one pathname and three numbers. */ -static const char *tomoyo_path_number3_keyword -[TOMOYO_MAX_PATH_NUMBER3_OPERATION] = { +static const char *tomoyo_mkdev_keyword +[TOMOYO_MAX_MKDEV_OPERATION] = { [TOMOYO_TYPE_MKBLOCK] = "mkblock", [TOMOYO_TYPE_MKCHAR] = "mkchar", }; @@ -65,7 +65,7 @@ static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, }; -static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_PATH_NUMBER3_OPERATION] = { +static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = { [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR, }; @@ -133,16 +133,16 @@ const char *tomoyo_path2keyword(const u8 operation) } /** - * tomoyo_path_number32keyword - Get the name of path/number/number/number operations. + * tomoyo_mkdev2keyword - Get the name of path/number/number/number operations. * * @operation: Type of operation. * * Returns the name of path/number/number/number operation. */ -const char *tomoyo_path_number32keyword(const u8 operation) +const char *tomoyo_mkdev2keyword(const u8 operation) { - return (operation < TOMOYO_MAX_PATH_NUMBER3_OPERATION) - ? tomoyo_path_number3_keyword[operation] : NULL; + return (operation < TOMOYO_MAX_MKDEV_OPERATION) + ? tomoyo_mkdev_keyword[operation] : NULL; } /** @@ -266,7 +266,7 @@ static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) */ static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r) { - const char *operation = tomoyo_path_number32keyword(r->param.mkdev. + const char *operation = tomoyo_mkdev2keyword(r->param.mkdev. operation); const struct tomoyo_path_info *filename = r->param.mkdev.filename; const unsigned int major = r->param.mkdev.major; @@ -380,7 +380,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, struct tomoyo_globally_readable_file_entry e = { }; int error; - if (!tomoyo_is_correct_word(filename)) + if (!tomoyo_correct_word(filename)) return -EINVAL; e.filename = tomoyo_get_name(filename); if (!e.filename) @@ -393,7 +393,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, } /** - * tomoyo_is_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading. + * tomoyo_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading. * * @filename: The filename to check. * @@ -401,7 +401,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, * * Caller holds tomoyo_read_lock(). */ -static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * +static bool tomoyo_globally_readable_file(const struct tomoyo_path_info * filename) { struct tomoyo_globally_readable_file_entry *ptr; @@ -517,7 +517,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, struct tomoyo_pattern_entry e = { }; int error; - if (!tomoyo_is_correct_word(pattern)) + if (!tomoyo_correct_word(pattern)) return -EINVAL; e.pattern = tomoyo_get_name(pattern); if (!e.pattern) @@ -658,7 +658,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, struct tomoyo_no_rewrite_entry e = { }; int error; - if (!tomoyo_is_correct_word(pattern)) + if (!tomoyo_correct_word(pattern)) return -EINVAL; e.pattern = tomoyo_get_name(pattern); if (!e.pattern) @@ -671,7 +671,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, } /** - * tomoyo_is_no_rewrite_file - Check if the given pathname is not permitted to be rewrited. + * tomoyo_no_rewrite_file - Check if the given pathname is not permitted to be rewrited. * * @filename: Filename to check. * @@ -680,7 +680,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, * * Caller holds tomoyo_read_lock(). */ -static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) +static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename) { struct tomoyo_no_rewrite_entry *ptr; bool found = false; @@ -774,7 +774,7 @@ static bool tomoyo_check_path2_acl(const struct tomoyo_request_info *r, static bool tomoyo_check_mkdev_acl(const struct tomoyo_request_info *r, const struct tomoyo_acl_info *ptr) { - const struct tomoyo_path_number3_acl *acl = + const struct tomoyo_mkdev_acl *acl = container_of(ptr, typeof(*acl), head); return (acl->perm & (1 << r->param.mkdev.operation)) && tomoyo_compare_number_union(r->param.mkdev.mode, @@ -792,8 +792,8 @@ static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, { const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); - return tomoyo_is_same_acl_head(&p1->head, &p2->head) && - tomoyo_is_same_name_union(&p1->name, &p2->name); + return tomoyo_same_acl_head(&p1->head, &p2->head) && + tomoyo_same_name_union(&p1->name, &p2->name); } static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, @@ -853,28 +853,28 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, return error; } -static bool tomoyo_same_path_number3_acl(const struct tomoyo_acl_info *a, +static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a, const struct tomoyo_acl_info *b) { - const struct tomoyo_path_number3_acl *p1 = container_of(a, typeof(*p1), + const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head); - const struct tomoyo_path_number3_acl *p2 = container_of(b, typeof(*p2), + const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head); - return tomoyo_is_same_acl_head(&p1->head, &p2->head) - && tomoyo_is_same_name_union(&p1->name, &p2->name) - && tomoyo_is_same_number_union(&p1->mode, &p2->mode) - && tomoyo_is_same_number_union(&p1->major, &p2->major) - && tomoyo_is_same_number_union(&p1->minor, &p2->minor); + return tomoyo_same_acl_head(&p1->head, &p2->head) + && tomoyo_same_name_union(&p1->name, &p2->name) + && tomoyo_same_number_union(&p1->mode, &p2->mode) + && tomoyo_same_number_union(&p1->major, &p2->major) + && tomoyo_same_number_union(&p1->minor, &p2->minor); } -static bool tomoyo_merge_path_number3_acl(struct tomoyo_acl_info *a, +static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, struct tomoyo_acl_info *b, const bool is_delete) { - u8 *const a_perm = &container_of(a, struct tomoyo_path_number3_acl, + u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl, head)->perm; u8 perm = *a_perm; - const u8 b_perm = container_of(b, struct tomoyo_path_number3_acl, head) + const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head) ->perm; if (is_delete) perm &= ~b_perm; @@ -885,7 +885,7 @@ static bool tomoyo_merge_path_number3_acl(struct tomoyo_acl_info *a, } /** - * tomoyo_update_path_number3_acl - Update "struct tomoyo_path_number3_acl" list. + * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list. * * @type: Type of operation. * @filename: Filename. @@ -899,13 +899,13 @@ static bool tomoyo_merge_path_number3_acl(struct tomoyo_acl_info *a, * * Caller holds tomoyo_read_lock(). */ -static int tomoyo_update_path_number3_acl(const u8 type, const char *filename, +static int tomoyo_update_mkdev_acl(const u8 type, const char *filename, char *mode, char *major, char *minor, struct tomoyo_domain_info * const domain, const bool is_delete) { - struct tomoyo_path_number3_acl e = { - .head.type = TOMOYO_TYPE_PATH_NUMBER3_ACL, + struct tomoyo_mkdev_acl e = { + .head.type = TOMOYO_TYPE_MKDEV_ACL, .perm = 1 << type }; int error = is_delete ? -ENOENT : -ENOMEM; @@ -915,8 +915,8 @@ static int tomoyo_update_path_number3_acl(const u8 type, const char *filename, !tomoyo_parse_number_union(minor, &e.minor)) goto out; error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, - tomoyo_same_path_number3_acl, - tomoyo_merge_path_number3_acl); + tomoyo_same_mkdev_acl, + tomoyo_merge_mkdev_acl); out: tomoyo_put_name_union(&e.name); tomoyo_put_number_union(&e.mode); @@ -930,9 +930,9 @@ static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a, { const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); - return tomoyo_is_same_acl_head(&p1->head, &p2->head) - && tomoyo_is_same_name_union(&p1->name1, &p2->name1) - && tomoyo_is_same_name_union(&p1->name2, &p2->name2); + return tomoyo_same_acl_head(&p1->head, &p2->head) + && tomoyo_same_name_union(&p1->name1, &p2->name1) + && tomoyo_same_name_union(&p1->name2, &p2->name2); } static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, @@ -1014,7 +1014,7 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, tomoyo_check_acl(r, tomoyo_check_path_acl); if (!r->granted && operation == TOMOYO_TYPE_READ && !r->domain->ignore_global_allow_read && - tomoyo_is_globally_readable_file(filename)) + tomoyo_globally_readable_file(filename)) r->granted = true; error = tomoyo_audit_path_log(r); /* @@ -1029,7 +1029,7 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, * specified by "deny_rewrite" keyword. */ if (!error && operation == TOMOYO_TYPE_TRUNCATE && - tomoyo_is_no_rewrite_file(filename)) { + tomoyo_no_rewrite_file(filename)) { operation = TOMOYO_TYPE_REWRITE; goto next; } @@ -1043,9 +1043,9 @@ static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, head); const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), head); - return tomoyo_is_same_acl_head(&p1->head, &p2->head) - && tomoyo_is_same_name_union(&p1->name, &p2->name) - && tomoyo_is_same_number_union(&p1->number, &p2->number); + return tomoyo_same_acl_head(&p1->head, &p2->head) + && tomoyo_same_name_union(&p1->name, &p2->name) + && tomoyo_same_number_union(&p1->number, &p2->number); } static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, @@ -1204,7 +1204,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, error = -ENOMEM; goto out; } - if (tomoyo_is_no_rewrite_file(&buf)) + if (tomoyo_no_rewrite_file(&buf)) error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, &buf); } @@ -1258,7 +1258,7 @@ int tomoyo_path_perm(const u8 operation, struct path *path) goto out; switch (operation) { case TOMOYO_TYPE_REWRITE: - if (!tomoyo_is_no_rewrite_file(&buf)) { + if (!tomoyo_no_rewrite_file(&buf)) { error = 0; goto out; } @@ -1279,7 +1279,7 @@ int tomoyo_path_perm(const u8 operation, struct path *path) } /** - * tomoyo_path_number3_perm - Check permission for "mkblock" and "mkchar". + * tomoyo_mkdev_perm - Check permission for "mkblock" and "mkchar". * * @operation: Type of operation. (TOMOYO_TYPE_MKCHAR or TOMOYO_TYPE_MKBLOCK) * @path: Pointer to "struct path". @@ -1288,7 +1288,7 @@ int tomoyo_path_perm(const u8 operation, struct path *path) * * Returns 0 on success, negative value otherwise. */ -int tomoyo_path_number3_perm(const u8 operation, struct path *path, +int tomoyo_mkdev_perm(const u8 operation, struct path *path, const unsigned int mode, unsigned int dev) { struct tomoyo_request_info r; @@ -1304,7 +1304,7 @@ int tomoyo_path_number3_perm(const u8 operation, struct path *path, error = -ENOMEM; if (tomoyo_get_realpath(&buf, path)) { dev = new_decode_dev(dev); - r.param_type = TOMOYO_TYPE_PATH_NUMBER3_ACL; + r.param_type = TOMOYO_TYPE_MKDEV_ACL; r.param.mkdev.filename = &buf; r.param.mkdev.operation = operation; r.param.mkdev.mode = mode; @@ -1420,11 +1420,11 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, } if (!w[3][0] || !w[4][0]) goto out; - for (type = 0; type < TOMOYO_MAX_PATH_NUMBER3_OPERATION; type++) { - if (strcmp(w[0], tomoyo_path_number3_keyword[type])) + for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) { + if (strcmp(w[0], tomoyo_mkdev_keyword[type])) continue; - return tomoyo_update_path_number3_acl(type, w[1], w[2], w[3], - w[4], domain, is_delete); + return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3], + w[4], domain, is_delete); } out: return -EINVAL; diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 4290e519eaa8..d129317ca481 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c @@ -122,9 +122,9 @@ static void tomoyo_del_acl(struct tomoyo_acl_info *acl) tomoyo_put_number_union(&entry->number); } break; - case TOMOYO_TYPE_PATH_NUMBER3_ACL: + case TOMOYO_TYPE_MKDEV_ACL: { - struct tomoyo_path_number3_acl *entry + struct tomoyo_mkdev_acl *entry = container_of(acl, typeof(*entry), head); tomoyo_put_name_union(&entry->name); tomoyo_put_number_union(&entry->mode); diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 8f3ac251c571..54015b9964dc 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -300,11 +300,11 @@ static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, { const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); - return tomoyo_is_same_acl_head(&p1->head, &p2->head) && - tomoyo_is_same_name_union(&p1->dev_name, &p2->dev_name) && - tomoyo_is_same_name_union(&p1->dir_name, &p2->dir_name) && - tomoyo_is_same_name_union(&p1->fs_type, &p2->fs_type) && - tomoyo_is_same_number_union(&p1->flags, &p2->flags); + return tomoyo_same_acl_head(&p1->head, &p2->head) && + tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) && + tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) && + tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) && + tomoyo_same_number_union(&p1->flags, &p2->flags); } /** diff --git a/security/tomoyo/number_group.c b/security/tomoyo/number_group.c index 7266a7462c45..8779309c5b44 100644 --- a/security/tomoyo/number_group.c +++ b/security/tomoyo/number_group.c @@ -24,7 +24,7 @@ struct tomoyo_number_group *tomoyo_get_number_group(const char *group_name) struct tomoyo_number_group *group = NULL; const struct tomoyo_path_info *saved_group_name; int error = -ENOMEM; - if (!tomoyo_is_correct_word(group_name)) + if (!tomoyo_correct_word(group_name)) return NULL; saved_group_name = tomoyo_get_name(group_name); if (!saved_group_name) diff --git a/security/tomoyo/path_group.c b/security/tomoyo/path_group.c index 5b71d8868453..c78c57cd94ee 100644 --- a/security/tomoyo/path_group.c +++ b/security/tomoyo/path_group.c @@ -22,7 +22,7 @@ struct tomoyo_path_group *tomoyo_get_path_group(const char *group_name) struct tomoyo_path_group *group = NULL; const struct tomoyo_path_info *saved_group_name; int error = -ENOMEM; - if (!tomoyo_is_correct_word(group_name)) + if (!tomoyo_correct_word(group_name)) return NULL; saved_group_name = tomoyo_get_name(group_name); if (!saved_group_name) diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 7be732cadd47..95d3f9572237 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c @@ -142,7 +142,7 @@ static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, default: goto no_dev; } - return tomoyo_path_number3_perm(type, &path, perm, dev); + return tomoyo_mkdev_perm(type, &path, perm, dev); no_dev: switch (mode & S_IFMT) { case S_IFIFO: diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index e5931686ca33..945eeefbbdfe 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c @@ -89,7 +89,7 @@ void tomoyo_print_ulong(char *buffer, const int buffer_len, bool tomoyo_parse_name_union(const char *filename, struct tomoyo_name_union *ptr) { - if (!tomoyo_is_correct_word(filename)) + if (!tomoyo_correct_word(filename)) return false; if (filename[0] == '@') { ptr->group = tomoyo_get_path_group(filename + 1); @@ -115,7 +115,7 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num) unsigned long v; memset(num, 0, sizeof(*num)); if (data[0] == '@') { - if (!tomoyo_is_correct_word(data)) + if (!tomoyo_correct_word(data)) return false; num->group = tomoyo_get_number_group(data + 1); num->is_group = true; @@ -142,7 +142,7 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num) } /** - * tomoyo_is_byte_range - Check whether the string is a \ooo style octal value. + * tomoyo_byte_range - Check whether the string is a \ooo style octal value. * * @str: Pointer to the string. * @@ -151,7 +151,7 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num) * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF. * This function verifies that \ooo is in valid range. */ -static inline bool tomoyo_is_byte_range(const char *str) +static inline bool tomoyo_byte_range(const char *str) { return *str >= '0' && *str++ <= '3' && *str >= '0' && *str++ <= '7' && @@ -159,13 +159,13 @@ static inline bool tomoyo_is_byte_range(const char *str) } /** - * tomoyo_is_alphabet_char - Check whether the character is an alphabet. + * tomoyo_alphabet_char - Check whether the character is an alphabet. * * @c: The character to check. * * Returns true if @c is an alphabet character, false otherwise. */ -static inline bool tomoyo_is_alphabet_char(const char c) +static inline bool tomoyo_alphabet_char(const char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); } @@ -223,15 +223,15 @@ void tomoyo_normalize_line(unsigned char *buffer) unsigned char *dp = buffer; bool first = true; - while (tomoyo_is_invalid(*sp)) + while (tomoyo_invalid(*sp)) sp++; while (*sp) { if (!first) *dp++ = ' '; first = false; - while (tomoyo_is_valid(*sp)) + while (tomoyo_valid(*sp)) *dp++ = *sp++; - while (tomoyo_is_invalid(*sp)) + while (tomoyo_invalid(*sp)) sp++; } *dp = '\0'; @@ -265,7 +265,7 @@ bool tomoyo_tokenize(char *buffer, char *w[], size_t size) } /** - * tomoyo_is_correct_word2 - Validate a string. + * tomoyo_correct_word2 - Validate a string. * * @string: The string to check. May be non-'\0'-terminated. * @len: Length of @string. @@ -273,7 +273,7 @@ bool tomoyo_tokenize(char *buffer, char *w[], size_t size) * Check whether the given string follows the naming rules. * Returns true if @string follows the naming rules, false otherwise. */ -static bool tomoyo_is_correct_word2(const char *string, size_t len) +static bool tomoyo_correct_word2(const char *string, size_t len) { const char *const start = string; bool in_repetition = false; @@ -325,13 +325,13 @@ static bool tomoyo_is_correct_word2(const char *string, size_t len) if (d < '0' || d > '7' || e < '0' || e > '7') break; c = tomoyo_make_byte(c, d, e); - if (tomoyo_is_invalid(c)) + if (tomoyo_invalid(c)) continue; /* pattern is not \000 */ } goto out; } else if (in_repetition && c == '/') { goto out; - } else if (tomoyo_is_invalid(c)) { + } else if (tomoyo_invalid(c)) { goto out; } } @@ -343,39 +343,39 @@ static bool tomoyo_is_correct_word2(const char *string, size_t len) } /** - * tomoyo_is_correct_word - Validate a string. + * tomoyo_correct_word - Validate a string. * * @string: The string to check. * * Check whether the given string follows the naming rules. * Returns true if @string follows the naming rules, false otherwise. */ -bool tomoyo_is_correct_word(const char *string) +bool tomoyo_correct_word(const char *string) { - return tomoyo_is_correct_word2(string, strlen(string)); + return tomoyo_correct_word2(string, strlen(string)); } /** - * tomoyo_is_correct_path - Validate a pathname. + * tomoyo_correct_path - Validate a pathname. * * @filename: The pathname to check. * * Check whether the given pathname follows the naming rules. * Returns true if @filename follows the naming rules, false otherwise. */ -bool tomoyo_is_correct_path(const char *filename) +bool tomoyo_correct_path(const char *filename) { - return *filename == '/' && tomoyo_is_correct_word(filename); + return *filename == '/' && tomoyo_correct_word(filename); } /** - * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules. + * tomoyo_correct_domain - Check whether the given domainname follows the naming rules. * * @domainname: The domainname to check. * * Returns true if @domainname follows the naming rules, false otherwise. */ -bool tomoyo_is_correct_domain(const unsigned char *domainname) +bool tomoyo_correct_domain(const unsigned char *domainname) { if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN)) @@ -390,23 +390,23 @@ bool tomoyo_is_correct_domain(const unsigned char *domainname) if (!cp) break; if (*domainname != '/' || - !tomoyo_is_correct_word2(domainname, cp - domainname - 1)) + !tomoyo_correct_word2(domainname, cp - domainname - 1)) goto out; domainname = cp + 1; } - return tomoyo_is_correct_path(domainname); + return tomoyo_correct_path(domainname); out: return false; } /** - * tomoyo_is_domain_def - Check whether the given token can be a domainname. + * tomoyo_domain_def - Check whether the given token can be a domainname. * * @buffer: The token to check. * * Returns true if @buffer possibly be a domainname, false otherwise. */ -bool tomoyo_is_domain_def(const unsigned char *buffer) +bool tomoyo_domain_def(const unsigned char *buffer) { return !strncmp(buffer, TOMOYO_ROOT_NAME, TOMOYO_ROOT_NAME_LEN); } @@ -528,7 +528,7 @@ static bool tomoyo_file_matches_pattern2(const char *filename, } else if (c == '\\') { if (filename[1] == '\\') filename++; - else if (tomoyo_is_byte_range(filename + 1)) + else if (tomoyo_byte_range(filename + 1)) filename += 3; else return false; @@ -549,14 +549,14 @@ static bool tomoyo_file_matches_pattern2(const char *filename, return false; break; case 'a': - if (!tomoyo_is_alphabet_char(c)) + if (!tomoyo_alphabet_char(c)) return false; break; case '0': case '1': case '2': case '3': - if (c == '\\' && tomoyo_is_byte_range(filename + 1) + if (c == '\\' && tomoyo_byte_range(filename + 1) && strncmp(filename + 1, pattern, 3) == 0) { filename += 3; pattern += 2; @@ -577,7 +577,7 @@ static bool tomoyo_file_matches_pattern2(const char *filename, continue; if (filename[i + 1] == '\\') i++; - else if (tomoyo_is_byte_range(filename + i + 1)) + else if (tomoyo_byte_range(filename + i + 1)) i += 3; else break; /* Bad pattern. */ @@ -593,7 +593,7 @@ static bool tomoyo_file_matches_pattern2(const char *filename, while (isxdigit(filename[j])) j++; } else if (c == 'A') { - while (tomoyo_is_alphabet_char(filename[j])) + while (tomoyo_alphabet_char(filename[j])) j++; } for (i = 1; i <= j; i++) { @@ -939,10 +939,10 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) if (perm & (1 << i)) count++; break; - case TOMOYO_TYPE_PATH_NUMBER3_ACL: - perm = container_of(ptr, struct tomoyo_path_number3_acl, + case TOMOYO_TYPE_MKDEV_ACL: + perm = container_of(ptr, struct tomoyo_mkdev_acl, head)->perm; - for (i = 0; i < TOMOYO_MAX_PATH_NUMBER3_OPERATION; i++) + for (i = 0; i < TOMOYO_MAX_MKDEV_OPERATION; i++) if (perm & (1 << i)) count++; break; -- cgit v1.2.3 From d795ef9e751b72c94600c91e31bdaef55987a9f6 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Wed, 16 Jun 2010 16:24:58 +0900 Subject: TOMOYO: Loosen parameter check for mount operation. If invalid combination of mount flags are given, it will be rejected later. Thus, no need for TOMOYO to reject invalid combination of mount flags. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/mount.c | 124 +++++++++++++----------------------------------- 1 file changed, 33 insertions(+), 91 deletions(-) (limited to 'security/tomoyo/mount.c') diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 54015b9964dc..7872226f72ee 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -73,7 +73,7 @@ static bool tomoyo_check_mount_acl(const struct tomoyo_request_info *r, } /** - * tomoyo_mount_acl2 - Check permission for mount() operation. + * tomoyo_mount_acl - Check permission for mount() operation. * * @r: Pointer to "struct tomoyo_request_info". * @dev_name: Name of device file. @@ -85,8 +85,8 @@ static bool tomoyo_check_mount_acl(const struct tomoyo_request_info *r, * * Caller holds tomoyo_read_lock(). */ -static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name, - struct path *dir, char *type, unsigned long flags) +static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, + struct path *dir, char *type, unsigned long flags) { struct path path; struct file_system_type *fstype = NULL; @@ -178,94 +178,6 @@ static int tomoyo_mount_acl2(struct tomoyo_request_info *r, char *dev_name, return error; } -/** - * tomoyo_mount_acl - Check permission for mount() operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @dev_name: Name of device file. - * @dir: Pointer to "struct path". - * @type: Name of filesystem type. - * @flags: Mount options. - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, - struct path *dir, char *type, unsigned long flags) -{ - int error; - error = -EPERM; - if ((flags & MS_MGC_MSK) == MS_MGC_VAL) - flags &= ~MS_MGC_MSK; - switch (flags & (MS_REMOUNT | MS_MOVE | MS_BIND)) { - case MS_REMOUNT: - case MS_MOVE: - case MS_BIND: - case 0: - break; - default: - printk(KERN_WARNING "ERROR: " - "%s%s%sare given for single mount operation.\n", - flags & MS_REMOUNT ? "'remount' " : "", - flags & MS_MOVE ? "'move' " : "", - flags & MS_BIND ? "'bind' " : ""); - return -EINVAL; - } - switch (flags & (MS_UNBINDABLE | MS_PRIVATE | MS_SLAVE | MS_SHARED)) { - case MS_UNBINDABLE: - case MS_PRIVATE: - case MS_SLAVE: - case MS_SHARED: - case 0: - break; - default: - printk(KERN_WARNING "ERROR: " - "%s%s%s%sare given for single mount operation.\n", - flags & MS_UNBINDABLE ? "'unbindable' " : "", - flags & MS_PRIVATE ? "'private' " : "", - flags & MS_SLAVE ? "'slave' " : "", - flags & MS_SHARED ? "'shared' " : ""); - return -EINVAL; - } - if (flags & MS_REMOUNT) - error = tomoyo_mount_acl(r, dev_name, dir, - TOMOYO_MOUNT_REMOUNT_KEYWORD, - flags & ~MS_REMOUNT); - else if (flags & MS_MOVE) - error = tomoyo_mount_acl(r, dev_name, dir, - TOMOYO_MOUNT_MOVE_KEYWORD, - flags & ~MS_MOVE); - else if (flags & MS_BIND) - error = tomoyo_mount_acl(r, dev_name, dir, - TOMOYO_MOUNT_BIND_KEYWORD, - flags & ~MS_BIND); - else if (flags & MS_UNBINDABLE) - error = tomoyo_mount_acl(r, dev_name, dir, - TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD, - flags & ~MS_UNBINDABLE); - else if (flags & MS_PRIVATE) - error = tomoyo_mount_acl(r, dev_name, dir, - TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD, - flags & ~MS_PRIVATE); - else if (flags & MS_SLAVE) - error = tomoyo_mount_acl(r, dev_name, dir, - TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD, - flags & ~MS_SLAVE); - else if (flags & MS_SHARED) - error = tomoyo_mount_acl(r, dev_name, dir, - TOMOYO_MOUNT_MAKE_SHARED_KEYWORD, - flags & ~MS_SHARED); - else - do { - error = tomoyo_mount_acl2(r, dev_name, dir, type, - flags); - } while (error == TOMOYO_RETRY_REQUEST); - if (r->mode != TOMOYO_CONFIG_ENFORCING) - error = 0; - return error; -} - /** * tomoyo_mount_permission - Check permission for mount() operation. * @@ -287,6 +199,36 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, if (tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_MOUNT) == TOMOYO_CONFIG_DISABLED) return 0; + if ((flags & MS_MGC_MSK) == MS_MGC_VAL) + flags &= ~MS_MGC_MSK; + if (flags & MS_REMOUNT) { + type = TOMOYO_MOUNT_REMOUNT_KEYWORD; + flags &= ~MS_REMOUNT; + } + if (flags & MS_MOVE) { + type = TOMOYO_MOUNT_MOVE_KEYWORD; + flags &= ~MS_MOVE; + } + if (flags & MS_BIND) { + type = TOMOYO_MOUNT_BIND_KEYWORD; + flags &= ~MS_BIND; + } + if (flags & MS_UNBINDABLE) { + type = TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD; + flags &= ~MS_UNBINDABLE; + } + if (flags & MS_PRIVATE) { + type = TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD; + flags &= ~MS_PRIVATE; + } + if (flags & MS_SLAVE) { + type = TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD; + flags &= ~MS_SLAVE; + } + if (flags & MS_SHARED) { + type = TOMOYO_MOUNT_MAKE_SHARED_KEYWORD; + flags &= ~MS_SHARED; + } if (!type) type = ""; idx = tomoyo_read_lock(); -- cgit v1.2.3 From e2bf69077acefee5247bb661faac2552d29ba7ba Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Fri, 25 Jun 2010 11:16:00 +0900 Subject: TOMOYO: Rename symbols. Use shorter name in order to make it easier to fit 80 columns limit. Signed-off-by: Tetsuo Handa Signed-off-by: James Morris --- security/tomoyo/common.c | 226 +++++++++++++++++++++-------------------------- security/tomoyo/common.h | 54 ++++++----- security/tomoyo/domain.c | 60 ++++++------- security/tomoyo/file.c | 63 +++++++------ security/tomoyo/gc.c | 22 ++--- security/tomoyo/memory.c | 2 +- security/tomoyo/mount.c | 10 +-- security/tomoyo/util.c | 2 +- 8 files changed, 199 insertions(+), 240 deletions(-) (limited to 'security/tomoyo/mount.c') diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 30e4b08905e3..65c18af3ffe5 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -248,14 +248,13 @@ static void tomoyo_print_number_union(struct tomoyo_io_buffer *head, } /** - * tomoyo_find_or_assign_new_profile - Create a new profile. + * tomoyo_assign_profile - Create a new profile. * * @profile: Profile number to create. * * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise. */ -static struct tomoyo_profile *tomoyo_find_or_assign_new_profile -(const unsigned int profile) +static struct tomoyo_profile *tomoyo_assign_profile(const unsigned int profile) { struct tomoyo_profile *ptr; struct tomoyo_profile *entry; @@ -443,7 +442,7 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) if (*cp != '-') return -EINVAL; data = cp + 1; - profile = tomoyo_find_or_assign_new_profile(i); + profile = tomoyo_assign_profile(i); if (!profile) return -EINVAL; } @@ -584,13 +583,11 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head) goto next; } -static bool tomoyo_same_manager_entry(const struct tomoyo_acl_head *a, - const struct tomoyo_acl_head *b) +static bool tomoyo_same_manager(const struct tomoyo_acl_head *a, + const struct tomoyo_acl_head *b) { - return container_of(a, struct tomoyo_policy_manager_entry, head) - ->manager == - container_of(b, struct tomoyo_policy_manager_entry, head) - ->manager; + return container_of(a, struct tomoyo_manager, head)->manager == + container_of(b, struct tomoyo_manager, head)->manager; } /** @@ -606,7 +603,7 @@ static bool tomoyo_same_manager_entry(const struct tomoyo_acl_head *a, static int tomoyo_update_manager_entry(const char *manager, const bool is_delete) { - struct tomoyo_policy_manager_entry e = { }; + struct tomoyo_manager e = { }; int error; if (tomoyo_domain_def(manager)) { @@ -622,13 +619,13 @@ static int tomoyo_update_manager_entry(const char *manager, return -ENOMEM; error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, &tomoyo_policy_list[TOMOYO_ID_MANAGER], - tomoyo_same_manager_entry); + tomoyo_same_manager); tomoyo_put_name(e.manager); return error; } /** - * tomoyo_write_manager_policy - Write manager policy. + * tomoyo_write_manager - Write manager policy. * * @head: Pointer to "struct tomoyo_io_buffer". * @@ -636,7 +633,7 @@ static int tomoyo_update_manager_entry(const char *manager, * * Caller holds tomoyo_read_lock(). */ -static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) +static int tomoyo_write_manager(struct tomoyo_io_buffer *head) { char *data = head->write_buf; bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE); @@ -649,19 +646,19 @@ static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) } /** - * tomoyo_read_manager_policy - Read manager policy. + * tomoyo_read_manager - Read manager policy. * * @head: Pointer to "struct tomoyo_io_buffer". * * Caller holds tomoyo_read_lock(). */ -static void tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) +static void tomoyo_read_manager(struct tomoyo_io_buffer *head) { if (head->r.eof) return; list_for_each_cookie(head->r.acl, &tomoyo_policy_list[TOMOYO_ID_MANAGER]) { - struct tomoyo_policy_manager_entry *ptr = + struct tomoyo_manager *ptr = list_entry(head->r.acl, typeof(*ptr), head.list); if (ptr->head.is_deleted) continue; @@ -674,16 +671,16 @@ static void tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) } /** - * tomoyo_policy_manager - Check whether the current process is a policy manager. + * tomoyo_manager - Check whether the current process is a policy manager. * * Returns true if the current process is permitted to modify policy * via /sys/kernel/security/tomoyo/ interface. * * Caller holds tomoyo_read_lock(). */ -static bool tomoyo_policy_manager(void) +static bool tomoyo_manager(void) { - struct tomoyo_policy_manager_entry *ptr; + struct tomoyo_manager *ptr; const char *exe; const struct task_struct *task = current; const struct tomoyo_path_info *domainname = tomoyo_domain()->domainname; @@ -813,7 +810,7 @@ static int tomoyo_delete_domain(char *domainname) } /** - * tomoyo_write_domain_policy2 - Write domain policy. + * tomoyo_write_domain2 - Write domain policy. * * @head: Pointer to "struct tomoyo_io_buffer". * @@ -821,17 +818,16 @@ static int tomoyo_delete_domain(char *domainname) * * Caller holds tomoyo_read_lock(). */ -static int tomoyo_write_domain_policy2(char *data, - struct tomoyo_domain_info *domain, - const bool is_delete) +static int tomoyo_write_domain2(char *data, struct tomoyo_domain_info *domain, + 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(data, domain, is_delete); + return tomoyo_write_file(data, domain, is_delete); } /** - * tomoyo_write_domain_policy - Write domain policy. + * tomoyo_write_domain - Write domain policy. * * @head: Pointer to "struct tomoyo_io_buffer". * @@ -839,7 +835,7 @@ static int tomoyo_write_domain_policy2(char *data, * * Caller holds tomoyo_read_lock(). */ -static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) +static int tomoyo_write_domain(struct tomoyo_io_buffer *head) { char *data = head->write_buf; struct tomoyo_domain_info *domain = head->write_var1; @@ -854,7 +850,7 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) if (is_select && tomoyo_select_one(head, data)) return 0; /* Don't allow updating policies by non manager programs. */ - if (!tomoyo_policy_manager()) + if (!tomoyo_manager()) return -EPERM; if (tomoyo_domain_def(data)) { domain = NULL; @@ -863,7 +859,7 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) else if (is_select) domain = tomoyo_find_domain(data); else - domain = tomoyo_find_or_assign_new_domain(data, 0); + domain = tomoyo_assign_domain(data, 0); head->write_var1 = domain; return 0; } @@ -888,7 +884,7 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) domain->transition_failed = !is_delete; return 0; } - return tomoyo_write_domain_policy2(data, domain, is_delete); + return tomoyo_write_domain2(data, domain, is_delete); } /** @@ -1022,13 +1018,13 @@ static bool tomoyo_read_domain2(struct tomoyo_io_buffer *head, } /** - * tomoyo_read_domain_policy - Read domain policy. + * tomoyo_read_domain - Read domain policy. * * @head: Pointer to "struct tomoyo_io_buffer". * * Caller holds tomoyo_read_lock(). */ -static void tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) +static void tomoyo_read_domain(struct tomoyo_io_buffer *head) { if (head->r.eof) return; @@ -1208,8 +1204,13 @@ static const char *tomoyo_transition_type[TOMOYO_MAX_TRANSITION_TYPE] = { [TOMOYO_TRANSITION_CONTROL_KEEP] = TOMOYO_KEYWORD_KEEP_DOMAIN }; +static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = { + [TOMOYO_PATH_GROUP] = TOMOYO_KEYWORD_PATH_GROUP, + [TOMOYO_NUMBER_GROUP] = TOMOYO_KEYWORD_NUMBER_GROUP +}; + /** - * tomoyo_write_exception_policy - Write exception policy. + * tomoyo_write_exception - Write exception policy. * * @head: Pointer to "struct tomoyo_io_buffer". * @@ -1217,37 +1218,34 @@ static const char *tomoyo_transition_type[TOMOYO_MAX_TRANSITION_TYPE] = { * * Caller holds tomoyo_read_lock(). */ -static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) +static int tomoyo_write_exception(struct tomoyo_io_buffer *head) { char *data = head->write_buf; bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE); u8 i; - - for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) { + static const struct { + const char *keyword; + int (*write) (char *, const bool); + } tomoyo_callback[4] = { + { TOMOYO_KEYWORD_AGGREGATOR, tomoyo_write_aggregator }, + { TOMOYO_KEYWORD_FILE_PATTERN, tomoyo_write_pattern }, + { TOMOYO_KEYWORD_DENY_REWRITE, tomoyo_write_no_rewrite }, + { TOMOYO_KEYWORD_ALLOW_READ, tomoyo_write_globally_readable }, + }; + + for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) if (tomoyo_str_starts(&data, tomoyo_transition_type[i])) return tomoyo_write_transition_control(data, is_delete, i); - } - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_AGGREGATOR)) - return tomoyo_write_aggregator_policy(data, is_delete); - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_READ)) - return tomoyo_write_globally_readable_policy(data, is_delete); - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_FILE_PATTERN)) - return tomoyo_write_pattern_policy(data, is_delete); - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE)) - return tomoyo_write_no_rewrite_policy(data, is_delete); - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP)) - return tomoyo_write_group(data, is_delete, TOMOYO_PATH_GROUP); - if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NUMBER_GROUP)) - return tomoyo_write_group(data, is_delete, TOMOYO_NUMBER_GROUP); + for (i = 0; i < 4; i++) + if (tomoyo_str_starts(&data, tomoyo_callback[i].keyword)) + return tomoyo_callback[i].write(data, is_delete); + for (i = 0; i < TOMOYO_MAX_GROUP; i++) + if (tomoyo_str_starts(&data, tomoyo_group_name[i])) + return tomoyo_write_group(data, is_delete, i); return -EINVAL; } -static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = { - [TOMOYO_PATH_GROUP] = TOMOYO_KEYWORD_PATH_GROUP, - [TOMOYO_NUMBER_GROUP] = TOMOYO_KEYWORD_NUMBER_GROUP -}; - /** * tomoyo_read_group - Read "struct tomoyo_path_group"/"struct tomoyo_number_group" list. * @@ -1331,8 +1329,8 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) break; case TOMOYO_ID_GLOBALLY_READABLE: { - struct tomoyo_globally_readable_file_entry *ptr - = container_of(acl, typeof(*ptr), head); + struct tomoyo_readable_file *ptr = + container_of(acl, typeof(*ptr), head); tomoyo_set_string(head, TOMOYO_KEYWORD_ALLOW_READ); tomoyo_set_string(head, ptr->filename->name); @@ -1340,7 +1338,7 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) break; case TOMOYO_ID_AGGREGATOR: { - struct tomoyo_aggregator_entry *ptr = + struct tomoyo_aggregator *ptr = container_of(acl, typeof(*ptr), head); tomoyo_set_string(head, TOMOYO_KEYWORD_AGGREGATOR); @@ -1353,7 +1351,7 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) break; case TOMOYO_ID_PATTERN: { - struct tomoyo_pattern_entry *ptr = + struct tomoyo_no_pattern *ptr = container_of(acl, typeof(*ptr), head); tomoyo_set_string(head, TOMOYO_KEYWORD_FILE_PATTERN); @@ -1362,7 +1360,7 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) break; case TOMOYO_ID_NO_REWRITE: { - struct tomoyo_no_rewrite_entry *ptr = + struct tomoyo_no_rewrite *ptr = container_of(acl, typeof(*ptr), head); tomoyo_set_string(head, TOMOYO_KEYWORD_DENY_REWRITE); @@ -1379,13 +1377,13 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) } /** - * tomoyo_read_exception_policy - Read exception policy. + * tomoyo_read_exception - Read exception policy. * * @head: Pointer to "struct tomoyo_io_buffer". * * Caller holds tomoyo_read_lock(). */ -static void tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) +static void tomoyo_read_exception(struct tomoyo_io_buffer *head) { if (head->r.eof) return; @@ -1472,7 +1470,7 @@ static DECLARE_WAIT_QUEUE_HEAD(tomoyo_query_wait); static DEFINE_SPINLOCK(tomoyo_query_list_lock); /* Structure for query. */ -struct tomoyo_query_entry { +struct tomoyo_query { struct list_head list; char *query; int query_len; @@ -1481,7 +1479,7 @@ struct tomoyo_query_entry { int answer; }; -/* The list for "struct tomoyo_query_entry". */ +/* The list for "struct tomoyo_query". */ static LIST_HEAD(tomoyo_query_list); /* @@ -1508,7 +1506,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) int pos; int len; static unsigned int tomoyo_serial; - struct tomoyo_query_entry *tomoyo_query_entry = NULL; + struct tomoyo_query *entry = NULL; bool quota_exceeded = false; char *header; switch (r->mode) { @@ -1526,7 +1524,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) vsnprintf(buffer, len - 1, fmt, args); va_end(args); tomoyo_normalize_line(buffer); - tomoyo_write_domain_policy2(buffer, r->domain, false); + tomoyo_write_domain2(buffer, r->domain, false); kfree(buffer); /* fall through */ case TOMOYO_CONFIG_PERMISSIVE: @@ -1542,51 +1540,50 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) header = tomoyo_init_audit_log(&len, r); if (!header) goto out; - tomoyo_query_entry = kzalloc(sizeof(*tomoyo_query_entry), GFP_NOFS); - if (!tomoyo_query_entry) + entry = kzalloc(sizeof(*entry), GFP_NOFS); + if (!entry) goto out; - tomoyo_query_entry->query = kzalloc(len, GFP_NOFS); - if (!tomoyo_query_entry->query) + entry->query = kzalloc(len, GFP_NOFS); + if (!entry->query) goto out; - len = ksize(tomoyo_query_entry->query); - INIT_LIST_HEAD(&tomoyo_query_entry->list); + len = ksize(entry->query); spin_lock(&tomoyo_query_list_lock); if (tomoyo_quota_for_query && tomoyo_query_memory_size + len + - sizeof(*tomoyo_query_entry) >= tomoyo_quota_for_query) { + sizeof(*entry) >= tomoyo_quota_for_query) { quota_exceeded = true; } else { - tomoyo_query_memory_size += len + sizeof(*tomoyo_query_entry); - tomoyo_query_entry->serial = tomoyo_serial++; + tomoyo_query_memory_size += len + sizeof(*entry); + entry->serial = tomoyo_serial++; } spin_unlock(&tomoyo_query_list_lock); if (quota_exceeded) goto out; - pos = snprintf(tomoyo_query_entry->query, len - 1, "Q%u-%hu\n%s", - tomoyo_query_entry->serial, r->retry, header); + pos = snprintf(entry->query, len - 1, "Q%u-%hu\n%s", + entry->serial, r->retry, header); kfree(header); header = NULL; va_start(args, fmt); - vsnprintf(tomoyo_query_entry->query + pos, len - 1 - pos, fmt, args); - tomoyo_query_entry->query_len = strlen(tomoyo_query_entry->query) + 1; + vsnprintf(entry->query + pos, len - 1 - pos, fmt, args); + entry->query_len = strlen(entry->query) + 1; va_end(args); spin_lock(&tomoyo_query_list_lock); - list_add_tail(&tomoyo_query_entry->list, &tomoyo_query_list); + list_add_tail(&entry->list, &tomoyo_query_list); spin_unlock(&tomoyo_query_list_lock); /* Give 10 seconds for supervisor's opinion. */ - for (tomoyo_query_entry->timer = 0; - atomic_read(&tomoyo_query_observers) && tomoyo_query_entry->timer < 100; - tomoyo_query_entry->timer++) { + for (entry->timer = 0; + atomic_read(&tomoyo_query_observers) && entry->timer < 100; + entry->timer++) { wake_up(&tomoyo_query_wait); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 10); - if (tomoyo_query_entry->answer) + if (entry->answer) break; } spin_lock(&tomoyo_query_list_lock); - list_del(&tomoyo_query_entry->list); - tomoyo_query_memory_size -= len + sizeof(*tomoyo_query_entry); + list_del(&entry->list); + tomoyo_query_memory_size -= len + sizeof(*entry); spin_unlock(&tomoyo_query_list_lock); - switch (tomoyo_query_entry->answer) { + switch (entry->answer) { case 3: /* Asked to retry by administrator. */ error = TOMOYO_RETRY_REQUEST; r->retry++; @@ -1603,9 +1600,9 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) break; } out: - if (tomoyo_query_entry) - kfree(tomoyo_query_entry->query); - kfree(tomoyo_query_entry); + if (entry) + kfree(entry->query); + kfree(entry); kfree(header); return error; } @@ -1628,9 +1625,8 @@ static int tomoyo_poll_query(struct file *file, poll_table *wait) for (i = 0; i < 2; i++) { spin_lock(&tomoyo_query_list_lock); list_for_each(tmp, &tomoyo_query_list) { - struct tomoyo_query_entry *ptr - = list_entry(tmp, struct tomoyo_query_entry, - list); + struct tomoyo_query *ptr = + list_entry(tmp, typeof(*ptr), list); if (ptr->answer) continue; found = true; @@ -1665,8 +1661,7 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head) } spin_lock(&tomoyo_query_list_lock); list_for_each(tmp, &tomoyo_query_list) { - struct tomoyo_query_entry *ptr = - list_entry(tmp, typeof(*ptr), list); + struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); if (ptr->answer) continue; if (pos++ != head->r.query_index) @@ -1685,8 +1680,7 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head) pos = 0; spin_lock(&tomoyo_query_list_lock); list_for_each(tmp, &tomoyo_query_list) { - struct tomoyo_query_entry *ptr = - list_entry(tmp, typeof(*ptr), list); + struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); if (ptr->answer) continue; if (pos++ != head->r.query_index) @@ -1724,8 +1718,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head) unsigned int answer; spin_lock(&tomoyo_query_list_lock); list_for_each(tmp, &tomoyo_query_list) { - struct tomoyo_query_entry *ptr - = list_entry(tmp, struct tomoyo_query_entry, list); + struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); ptr->timer = 0; } spin_unlock(&tomoyo_query_list_lock); @@ -1733,8 +1726,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head) return -EINVAL; spin_lock(&tomoyo_query_list_lock); list_for_each(tmp, &tomoyo_query_list) { - struct tomoyo_query_entry *ptr - = list_entry(tmp, struct tomoyo_query_entry, list); + struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); if (ptr->serial != serial) continue; if (!ptr->answer) @@ -1801,13 +1793,13 @@ int tomoyo_open_control(const u8 type, struct file *file) switch (type) { case TOMOYO_DOMAINPOLICY: /* /sys/kernel/security/tomoyo/domain_policy */ - head->write = tomoyo_write_domain_policy; - head->read = tomoyo_read_domain_policy; + head->write = tomoyo_write_domain; + head->read = tomoyo_read_domain; break; case TOMOYO_EXCEPTIONPOLICY: /* /sys/kernel/security/tomoyo/exception_policy */ - head->write = tomoyo_write_exception_policy; - head->read = tomoyo_read_exception_policy; + head->write = tomoyo_write_exception; + head->read = tomoyo_read_exception; break; case TOMOYO_SELFDOMAIN: /* /sys/kernel/security/tomoyo/self_domain */ @@ -1846,8 +1838,8 @@ int tomoyo_open_control(const u8 type, struct file *file) break; case TOMOYO_MANAGER: /* /sys/kernel/security/tomoyo/manager */ - head->write = tomoyo_write_manager_policy; - head->read = tomoyo_read_manager_policy; + head->write = tomoyo_write_manager; + head->read = tomoyo_read_manager; break; } if (!(file->f_mode & FMODE_READ)) { @@ -1905,23 +1897,6 @@ int tomoyo_open_control(const u8 type, struct file *file) return 0; } -/** - * tomoyo_poll_control - poll() for /sys/kernel/security/tomoyo/ interface. - * - * @file: Pointer to "struct file". - * @wait: Pointer to "poll_table". - * - * Waits for read readiness. - * /sys/kernel/security/tomoyo/query is handled by /usr/sbin/tomoyo-queryd . - */ -int tomoyo_poll_control(struct file *file, poll_table *wait) -{ - struct tomoyo_io_buffer *head = file->private_data; - if (!head->poll) - return -ENOSYS; - return head->poll(file, wait); -} - /** * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface. * @@ -1979,8 +1954,7 @@ int tomoyo_write_control(struct file *file, const char __user *buffer, return -EFAULT; /* Don't allow updating policies by non manager programs. */ if (head->write != tomoyo_write_pid && - head->write != tomoyo_write_domain_policy && - !tomoyo_policy_manager()) + head->write != tomoyo_write_domain && !tomoyo_manager()) return -EPERM; if (mutex_lock_interruptible(&head->io_sem)) return -EINTR; diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index ef8fecddb65a..b8b2dac656f1 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -310,10 +310,10 @@ struct tomoyo_path_info { }; /* - * tomoyo_name_entry is a structure which is used for linking + * tomoyo_name is a structure which is used for linking * "struct tomoyo_path_info" into tomoyo_name_list . */ -struct tomoyo_name_entry { +struct tomoyo_name { struct list_head list; atomic_t users; struct tomoyo_path_info entry; @@ -572,20 +572,20 @@ struct tomoyo_io_buffer { }; /* - * tomoyo_globally_readable_file_entry is a structure which is used for holding + * tomoyo_readable_file is a structure which is used for holding * "allow_read" entries. * It has following fields. * * (1) "head" is "struct tomoyo_acl_head". * (2) "filename" is a pathname which is allowed to open(O_RDONLY). */ -struct tomoyo_globally_readable_file_entry { +struct tomoyo_readable_file { struct tomoyo_acl_head head; const struct tomoyo_path_info *filename; }; /* - * tomoyo_pattern_entry is a structure which is used for holding + * tomoyo_no_pattern is a structure which is used for holding * "file_pattern" entries. * It has following fields. * @@ -593,13 +593,13 @@ struct tomoyo_globally_readable_file_entry { * (2) "pattern" is a pathname pattern which is used for converting pathnames * to pathname patterns during learning mode. */ -struct tomoyo_pattern_entry { +struct tomoyo_no_pattern { struct tomoyo_acl_head head; const struct tomoyo_path_info *pattern; }; /* - * tomoyo_no_rewrite_entry is a structure which is used for holding + * tomoyo_no_rewrite is a structure which is used for holding * "deny_rewrite" entries. * It has following fields. * @@ -607,7 +607,7 @@ struct tomoyo_pattern_entry { * (2) "pattern" is a pathname which is by default not permitted to modify * already existing content. */ -struct tomoyo_no_rewrite_entry { +struct tomoyo_no_rewrite { struct tomoyo_acl_head head; const struct tomoyo_path_info *pattern; }; @@ -636,7 +636,7 @@ struct tomoyo_transition_control { }; /* - * tomoyo_aggregator_entry is a structure which is used for holding + * tomoyo_aggregator is a structure which is used for holding * "aggregator" entries. * It has following fields. * @@ -644,14 +644,14 @@ struct tomoyo_transition_control { * (2) "original_name" which is originally requested name. * (3) "aggregated_name" which is name to rewrite. */ -struct tomoyo_aggregator_entry { +struct tomoyo_aggregator { struct tomoyo_acl_head head; const struct tomoyo_path_info *original_name; const struct tomoyo_path_info *aggregated_name; }; /* - * tomoyo_policy_manager_entry is a structure which is used for holding list of + * tomoyo_manager is a structure which is used for holding list of * domainnames or programs which are permitted to modify configuration via * /sys/kernel/security/tomoyo/ interface. * It has following fields. @@ -661,7 +661,7 @@ struct tomoyo_aggregator_entry { * otherwise. * (3) "manager" is a domainname or a program's pathname. */ -struct tomoyo_policy_manager_entry { +struct tomoyo_manager { struct tomoyo_acl_head head; bool is_domain; /* True if manager is a domainname. */ /* A path to program or a domainname. */ @@ -749,8 +749,6 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num); bool tomoyo_tokenize(char *buffer, char *w[], size_t size); /* Write domain policy violation warning message to console? */ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); -/* Get the last component of the given domainname. */ -const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); /* Fill "struct tomoyo_request_info". */ int tomoyo_init_request_info(struct tomoyo_request_info *r, struct tomoyo_domain_info *domain, @@ -759,7 +757,7 @@ int tomoyo_init_request_info(struct tomoyo_request_info *r, int tomoyo_mount_permission(char *dev_name, struct path *path, char *type, unsigned long flags, void *data_page); /* Create "aggregator" entry in exception policy. */ -int tomoyo_write_aggregator_policy(char *data, const bool is_delete); +int tomoyo_write_aggregator(char *data, const bool is_delete); int tomoyo_write_transition_control(char *data, const bool is_delete, const u8 type); /* @@ -769,17 +767,17 @@ int tomoyo_write_transition_control(char *data, const bool is_delete, * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_rename" and * "allow_link" entry in domain policy. */ -int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, - const bool is_delete); +int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, + const bool is_delete); /* Create "allow_read" entry in exception policy. */ -int tomoyo_write_globally_readable_policy(char *data, const bool is_delete); +int tomoyo_write_globally_readable(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, - const bool is_delete); +int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain, + const bool is_delete); /* Create "deny_rewrite" entry in exception policy. */ -int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete); +int tomoyo_write_no_rewrite(char *data, const bool is_delete); /* Create "file_pattern" entry in exception policy. */ -int tomoyo_write_pattern_policy(char *data, const bool is_delete); +int tomoyo_write_pattern(char *data, const bool is_delete); /* Create "path_group"/"number_group" entry in exception policy. */ int tomoyo_write_group(char *data, const bool is_delete, const u8 type); int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) @@ -787,9 +785,8 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) /* Find a domain by the given name. */ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); /* Find or create a domain by the given name. */ -struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * - domainname, - const u8 profile); +struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, + const u8 profile); struct tomoyo_profile *tomoyo_profile(const u8 profile); /* * Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group". @@ -820,7 +817,7 @@ char *tomoyo_realpath_nofollow(const char *pathname); */ char *tomoyo_realpath_from_path(struct path *path); /* Get patterned pathname. */ -const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename); +const char *tomoyo_pattern(const struct tomoyo_path_info *filename); /* Check memory quota. */ bool tomoyo_memory_ok(void *ptr); @@ -882,7 +879,6 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, void tomoyo_check_acl(struct tomoyo_request_info *r, bool (*check_entry) (const struct tomoyo_request_info *, const struct tomoyo_acl_info *)); -const char *tomoyo_last_word(const char *name); /********** External variable definitions. **********/ @@ -959,8 +955,8 @@ static inline bool tomoyo_invalid(const unsigned char c) static inline void tomoyo_put_name(const struct tomoyo_path_info *name) { if (name) { - struct tomoyo_name_entry *ptr = - container_of(name, struct tomoyo_name_entry, entry); + struct tomoyo_name *ptr = + container_of(name, typeof(*ptr), entry); atomic_dec(&ptr->users); } } diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 05450b17c57f..4e0101b0041a 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c @@ -134,26 +134,22 @@ struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY]; struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP]; /** - * tomoyo_get_last_name - Get last component of a domainname. + * tomoyo_last_word - Get last component of a domainname. * - * @domain: Pointer to "struct tomoyo_domain_info". + * @domainname: Domainname to check. * - * Returns the last component of the domainname. + * Returns the last word of @domainname. */ -const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain) +static const char *tomoyo_last_word(const char *name) { - const char *cp0 = domain->domainname->name; - const char *cp1 = strrchr(cp0, ' '); - - if (cp1) - return cp1 + 1; - return cp0; + const char *cp = strrchr(name, ' '); + if (cp) + return cp + 1; + return name; } -static bool tomoyo_same_transition_control_entry(const struct tomoyo_acl_head * - a, - const struct tomoyo_acl_head * - b) +static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a, + const struct tomoyo_acl_head *b) { const struct tomoyo_transition_control *p1 = container_of(a, typeof(*p1), @@ -203,7 +199,7 @@ static int tomoyo_update_transition_control_entry(const char *domainname, error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, &tomoyo_policy_list [TOMOYO_ID_TRANSITION_CONTROL], - tomoyo_same_transition_control_entry); + tomoyo_same_transition_control); out: tomoyo_put_name(e.domainname); tomoyo_put_name(e.program); @@ -292,19 +288,17 @@ static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname, return type; } -static bool tomoyo_same_aggregator_entry(const struct tomoyo_acl_head *a, - const struct tomoyo_acl_head *b) +static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a, + const struct tomoyo_acl_head *b) { - const struct tomoyo_aggregator_entry *p1 = container_of(a, typeof(*p1), - head); - const struct tomoyo_aggregator_entry *p2 = container_of(b, typeof(*p2), - head); + const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1), 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; } /** - * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator_entry" list. + * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator" list. * * @original_name: The original program's name. * @aggregated_name: The program name to use. @@ -318,7 +312,7 @@ static int tomoyo_update_aggregator_entry(const char *original_name, const char *aggregated_name, const bool is_delete) { - struct tomoyo_aggregator_entry e = { }; + struct tomoyo_aggregator e = { }; int error = is_delete ? -ENOENT : -ENOMEM; if (!tomoyo_correct_path(original_name) || @@ -331,7 +325,7 @@ static int tomoyo_update_aggregator_entry(const char *original_name, goto out; error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR], - tomoyo_same_aggregator_entry); + tomoyo_same_aggregator); out: tomoyo_put_name(e.original_name); tomoyo_put_name(e.aggregated_name); @@ -339,7 +333,7 @@ static int tomoyo_update_aggregator_entry(const char *original_name, } /** - * tomoyo_write_aggregator_policy - Write "struct tomoyo_aggregator_entry" list. + * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list. * * @data: String to parse. * @is_delete: True if it is a delete request. @@ -348,7 +342,7 @@ static int tomoyo_update_aggregator_entry(const char *original_name, * * Caller holds tomoyo_read_lock(). */ -int tomoyo_write_aggregator_policy(char *data, const bool is_delete) +int tomoyo_write_aggregator(char *data, const bool is_delete) { char *cp = strchr(data, ' '); @@ -359,7 +353,7 @@ int tomoyo_write_aggregator_policy(char *data, const bool is_delete) } /** - * tomoyo_find_or_assign_new_domain - Create a domain. + * tomoyo_assign_domain - Create a domain. * * @domainname: The name of domain. * @profile: Profile number to assign if the domain was newly created. @@ -368,9 +362,8 @@ int tomoyo_write_aggregator_policy(char *data, const bool is_delete) * * Caller holds tomoyo_read_lock(). */ -struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * - domainname, - const u8 profile) +struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, + const u8 profile) { struct tomoyo_domain_info *entry; struct tomoyo_domain_info *domain = NULL; @@ -430,10 +423,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) int retval = -ENOMEM; bool need_kfree = false; struct tomoyo_path_info rn = { }; /* real 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) @@ -454,7 +444,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) /* Check 'aggregator' directive. */ { - struct tomoyo_aggregator_entry *ptr; + struct tomoyo_aggregator *ptr; list_for_each_entry_rcu(ptr, &tomoyo_policy_list [TOMOYO_ID_AGGREGATOR], head.list) { if (ptr->head.is_deleted || @@ -517,7 +507,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) if (error < 0) goto done; } - domain = tomoyo_find_or_assign_new_domain(tmp, old_domain->profile); + domain = tomoyo_assign_domain(tmp, old_domain->profile); done: if (domain) goto out; diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index e7687ebdc5f6..f7877fa80f14 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -179,7 +179,7 @@ static int tomoyo_audit_path_log(struct tomoyo_request_info *r) return 0; tomoyo_warn_log(r, "%s %s", operation, filename->name); return tomoyo_supervisor(r, "allow_%s %s\n", operation, - tomoyo_file_pattern(filename)); + tomoyo_pattern(filename)); } /** @@ -199,8 +199,8 @@ static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) tomoyo_warn_log(r, "%s %s %s", operation, filename1->name, filename2->name); return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, - tomoyo_file_pattern(filename1), - tomoyo_file_pattern(filename2)); + tomoyo_pattern(filename1), + tomoyo_pattern(filename2)); } /** @@ -222,8 +222,7 @@ static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r) tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode, major, minor); return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation, - tomoyo_file_pattern(filename), mode, major, - minor); + tomoyo_pattern(filename), mode, major, minor); } /** @@ -262,20 +261,20 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) radix); tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer); return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, - tomoyo_file_pattern(filename), buffer); + tomoyo_pattern(filename), buffer); } static bool tomoyo_same_globally_readable(const struct tomoyo_acl_head *a, const struct tomoyo_acl_head *b) { - return container_of(a, struct tomoyo_globally_readable_file_entry, + return container_of(a, struct tomoyo_readable_file, head)->filename == - container_of(b, struct tomoyo_globally_readable_file_entry, + container_of(b, struct tomoyo_readable_file, head)->filename; } /** - * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list. + * tomoyo_update_globally_readable_entry - Update "struct tomoyo_readable_file" list. * * @filename: Filename unconditionally permitted to open() for reading. * @is_delete: True if it is a delete request. @@ -287,7 +286,7 @@ static bool tomoyo_same_globally_readable(const struct tomoyo_acl_head *a, static int tomoyo_update_globally_readable_entry(const char *filename, const bool is_delete) { - struct tomoyo_globally_readable_file_entry e = { }; + struct tomoyo_readable_file e = { }; int error; if (!tomoyo_correct_word(filename)) @@ -315,7 +314,7 @@ static int tomoyo_update_globally_readable_entry(const char *filename, static bool tomoyo_globally_readable_file(const struct tomoyo_path_info * filename) { - struct tomoyo_globally_readable_file_entry *ptr; + struct tomoyo_readable_file *ptr; bool found = false; list_for_each_entry_rcu(ptr, &tomoyo_policy_list @@ -330,7 +329,7 @@ static bool tomoyo_globally_readable_file(const struct tomoyo_path_info * } /** - * tomoyo_write_globally_readable_policy - Write "struct tomoyo_globally_readable_file_entry" list. + * tomoyo_write_globally_readable - Write "struct tomoyo_readable_file" list. * * @data: String to parse. * @is_delete: True if it is a delete request. @@ -339,7 +338,7 @@ static bool tomoyo_globally_readable_file(const struct tomoyo_path_info * * * Caller holds tomoyo_read_lock(). */ -int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) +int tomoyo_write_globally_readable(char *data, const bool is_delete) { return tomoyo_update_globally_readable_entry(data, is_delete); } @@ -347,12 +346,12 @@ int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a, const struct tomoyo_acl_head *b) { - return container_of(a, struct tomoyo_pattern_entry, head)->pattern == - container_of(b, struct tomoyo_pattern_entry, head)->pattern; + return container_of(a, struct tomoyo_no_pattern, head)->pattern == + container_of(b, struct tomoyo_no_pattern, head)->pattern; } /** - * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. + * tomoyo_update_file_pattern_entry - Update "struct tomoyo_no_pattern" list. * * @pattern: Pathname pattern. * @is_delete: True if it is a delete request. @@ -364,7 +363,7 @@ static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a, static int tomoyo_update_file_pattern_entry(const char *pattern, const bool is_delete) { - struct tomoyo_pattern_entry e = { }; + struct tomoyo_no_pattern e = { }; int error; if (!tomoyo_correct_word(pattern)) @@ -380,7 +379,7 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, } /** - * tomoyo_file_pattern - Get patterned pathname. + * tomoyo_pattern - Get patterned pathname. * * @filename: The filename to find patterned pathname. * @@ -388,9 +387,9 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, * * Caller holds tomoyo_read_lock(). */ -const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename) +const char *tomoyo_pattern(const struct tomoyo_path_info *filename) { - struct tomoyo_pattern_entry *ptr; + struct tomoyo_no_pattern *ptr; const struct tomoyo_path_info *pattern = NULL; list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_PATTERN], @@ -413,7 +412,7 @@ const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename) } /** - * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list. + * tomoyo_write_pattern - Write "struct tomoyo_no_pattern" list. * * @data: String to parse. * @is_delete: True if it is a delete request. @@ -422,7 +421,7 @@ const char *tomoyo_file_pattern(const struct tomoyo_path_info *filename) * * Caller holds tomoyo_read_lock(). */ -int tomoyo_write_pattern_policy(char *data, const bool is_delete) +int tomoyo_write_pattern(char *data, const bool is_delete) { return tomoyo_update_file_pattern_entry(data, is_delete); } @@ -430,13 +429,13 @@ int tomoyo_write_pattern_policy(char *data, const bool is_delete) static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a, const struct tomoyo_acl_head *b) { - return container_of(a, struct tomoyo_no_rewrite_entry, head)->pattern - == container_of(b, struct tomoyo_no_rewrite_entry, head) + return container_of(a, struct tomoyo_no_rewrite, head)->pattern + == container_of(b, struct tomoyo_no_rewrite, head) ->pattern; } /** - * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list. + * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite" list. * * @pattern: Pathname pattern that are not rewritable by default. * @is_delete: True if it is a delete request. @@ -448,7 +447,7 @@ static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a, static int tomoyo_update_no_rewrite_entry(const char *pattern, const bool is_delete) { - struct tomoyo_no_rewrite_entry e = { }; + struct tomoyo_no_rewrite e = { }; int error; if (!tomoyo_correct_word(pattern)) @@ -475,7 +474,7 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, */ static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename) { - struct tomoyo_no_rewrite_entry *ptr; + struct tomoyo_no_rewrite *ptr; bool found = false; list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE], @@ -491,7 +490,7 @@ static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename) } /** - * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list. + * tomoyo_write_no_rewrite - Write "struct tomoyo_no_rewrite" list. * * @data: String to parse. * @is_delete: True if it is a delete request. @@ -500,7 +499,7 @@ static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename) * * Caller holds tomoyo_read_lock(). */ -int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) +int tomoyo_write_no_rewrite(char *data, const bool is_delete) { return tomoyo_update_no_rewrite_entry(data, is_delete); } @@ -1121,7 +1120,7 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, } /** - * tomoyo_write_file_policy - Update file related list. + * tomoyo_write_file - Update file related list. * * @data: String to parse. * @domain: Pointer to "struct tomoyo_domain_info". @@ -1131,8 +1130,8 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1, * * Caller holds tomoyo_read_lock(). */ -int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, - const bool is_delete) +int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, + const bool is_delete) { char *w[5]; u8 type; diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 254ac1145552..a877e4c3b101 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c @@ -11,7 +11,7 @@ #include #include -struct tomoyo_gc_entry { +struct tomoyo_gc { struct list_head list; int type; struct list_head *element; @@ -22,7 +22,7 @@ static DEFINE_MUTEX(tomoyo_gc_mutex); /* Caller holds tomoyo_policy_lock mutex. */ static bool tomoyo_add_to_gc(const int type, struct list_head *element) { - struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); + struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); if (!entry) return false; entry->type = type; @@ -34,21 +34,21 @@ static bool tomoyo_add_to_gc(const int type, struct list_head *element) static void tomoyo_del_allow_read(struct list_head *element) { - struct tomoyo_globally_readable_file_entry *ptr = + struct tomoyo_readable_file *ptr = container_of(element, typeof(*ptr), head.list); tomoyo_put_name(ptr->filename); } static void tomoyo_del_file_pattern(struct list_head *element) { - struct tomoyo_pattern_entry *ptr = + struct tomoyo_no_pattern *ptr = container_of(element, typeof(*ptr), head.list); tomoyo_put_name(ptr->pattern); } static void tomoyo_del_no_rewrite(struct list_head *element) { - struct tomoyo_no_rewrite_entry *ptr = + struct tomoyo_no_rewrite *ptr = container_of(element, typeof(*ptr), head.list); tomoyo_put_name(ptr->pattern); } @@ -63,7 +63,7 @@ static void tomoyo_del_transition_control(struct list_head *element) static void tomoyo_del_aggregator(struct list_head *element) { - struct tomoyo_aggregator_entry *ptr = + struct tomoyo_aggregator *ptr = container_of(element, typeof(*ptr), head.list); tomoyo_put_name(ptr->original_name); tomoyo_put_name(ptr->aggregated_name); @@ -71,7 +71,7 @@ static void tomoyo_del_aggregator(struct list_head *element) static void tomoyo_del_manager(struct list_head *element) { - struct tomoyo_policy_manager_entry *ptr = + struct tomoyo_manager *ptr = container_of(element, typeof(*ptr), head.list); tomoyo_put_name(ptr->manager); } @@ -168,7 +168,7 @@ static bool tomoyo_del_domain(struct list_head *element) static void tomoyo_del_name(struct list_head *element) { - const struct tomoyo_name_entry *ptr = + const struct tomoyo_name *ptr = container_of(element, typeof(*ptr), list); } @@ -242,7 +242,7 @@ static void tomoyo_collect_entry(void) } } for (i = 0; i < TOMOYO_MAX_HASH; i++) { - struct tomoyo_name_entry *ptr; + struct tomoyo_name *ptr; list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], list) { if (atomic_read(&ptr->users)) continue; @@ -278,8 +278,8 @@ static void tomoyo_collect_entry(void) static void tomoyo_kfree_entry(void) { - struct tomoyo_gc_entry *p; - struct tomoyo_gc_entry *tmp; + struct tomoyo_gc *p; + struct tomoyo_gc *tmp; list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) { struct list_head *element = p->element; diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c index a4aba4d9ca2e..297612669c74 100644 --- a/security/tomoyo/memory.c +++ b/security/tomoyo/memory.c @@ -150,7 +150,7 @@ struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; */ const struct tomoyo_path_info *tomoyo_get_name(const char *name) { - struct tomoyo_name_entry *ptr; + struct tomoyo_name *ptr; unsigned int hash; int len; int allocated_len; diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 7872226f72ee..cfeff871908e 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c @@ -55,8 +55,8 @@ static int tomoyo_audit_mount_log(struct tomoyo_request_info *r) flags); return tomoyo_supervisor(r, TOMOYO_KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n", - tomoyo_file_pattern(r->param.mount.dev), - tomoyo_file_pattern(r->param.mount.dir), type, + tomoyo_pattern(r->param.mount.dev), + tomoyo_pattern(r->param.mount.dir), type, flags); } @@ -250,7 +250,7 @@ static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, } /** - * tomoyo_write_mount_policy - Write "struct tomoyo_mount_acl" list. + * tomoyo_write_mount - Write "struct tomoyo_mount_acl" list. * * @data: String to parse. * @domain: Pointer to "struct tomoyo_domain_info". @@ -260,8 +260,8 @@ static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, * * Caller holds tomoyo_read_lock(). */ -int tomoyo_write_mount_policy(char *data, struct tomoyo_domain_info *domain, - const bool is_delete) +int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain, + const bool is_delete) { struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; int error = is_delete ? -ENOENT : -ENOMEM; diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 12a768e6ee3f..150167d0cc3a 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c @@ -26,7 +26,7 @@ bool tomoyo_policy_loaded; * The @src is updated to point the first character after the value * on success. */ -u8 tomoyo_parse_ulong(unsigned long *result, char **str) +static u8 tomoyo_parse_ulong(unsigned long *result, char **str) { const char *cp = *str; char *ep; -- cgit v1.2.3 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/mount.c') diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 2ffad6138555..04454cb7b24a 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 4e0101b0041a..35388408e475 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 f7877fa80f14..9d32f182301e 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 3f0a2abf65cc..e94352ce723f 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 cfeff871908e..82bf8c2390bc 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