diff options
Diffstat (limited to 'ANDROID_3.4.5/security/tomoyo')
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/Kconfig | 74 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/Makefile | 48 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/audit.c | 461 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/common.c | 2806 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/common.h | 1331 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/condition.c | 1094 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/domain.c | 901 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/environ.c | 122 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/file.c | 1026 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/gc.c | 655 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/group.c | 198 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/load_policy.c | 109 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/memory.c | 201 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/mount.c | 235 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/network.c | 771 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/realpath.c | 328 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/securityfs_if.c | 273 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/tomoyo.c | 560 | ||||
-rw-r--r-- | ANDROID_3.4.5/security/tomoyo/util.c | 1090 |
19 files changed, 0 insertions, 12283 deletions
diff --git a/ANDROID_3.4.5/security/tomoyo/Kconfig b/ANDROID_3.4.5/security/tomoyo/Kconfig deleted file mode 100644 index 8eb779b9..00000000 --- a/ANDROID_3.4.5/security/tomoyo/Kconfig +++ /dev/null @@ -1,74 +0,0 @@ -config SECURITY_TOMOYO - bool "TOMOYO Linux Support" - depends on SECURITY - depends on NET - select SECURITYFS - select SECURITY_PATH - select SECURITY_NETWORK - default n - help - This selects TOMOYO Linux, pathname-based access control. - Required userspace tools and further information may be - found at <http://tomoyo.sourceforge.jp/>. - If you are unsure how to answer this question, answer N. - -config SECURITY_TOMOYO_MAX_ACCEPT_ENTRY - int "Default maximal count for learning mode" - default 2048 - range 0 2147483647 - depends on SECURITY_TOMOYO - help - This is the default value for maximal ACL entries - that are automatically appended into policy at "learning mode". - Some programs access thousands of objects, so running - such programs in "learning mode" dulls the system response - and consumes much memory. - This is the safeguard for such programs. - -config SECURITY_TOMOYO_MAX_AUDIT_LOG - int "Default maximal count for audit log" - default 1024 - range 0 2147483647 - depends on SECURITY_TOMOYO - help - This is the default value for maximal entries for - audit logs that the kernel can hold on memory. - You can read the log via /sys/kernel/security/tomoyo/audit. - If you don't need audit logs, you may set this value to 0. - -config SECURITY_TOMOYO_OMIT_USERSPACE_LOADER - bool "Activate without calling userspace policy loader." - default n - depends on SECURITY_TOMOYO - ---help--- - Say Y here if you want to activate access control as soon as built-in - policy was loaded. This option will be useful for systems where - operations which can lead to the hijacking of the boot sequence are - needed before loading the policy. For example, you can activate - immediately after loading the fixed part of policy which will allow - only operations needed for mounting a partition which contains the - variant part of policy and verifying (e.g. running GPG check) and - loading the variant part of policy. Since you can start using - enforcing mode from the beginning, you can reduce the possibility of - hijacking the boot sequence. - -config SECURITY_TOMOYO_POLICY_LOADER - string "Location of userspace policy loader" - default "/sbin/tomoyo-init" - depends on SECURITY_TOMOYO - depends on !SECURITY_TOMOYO_OMIT_USERSPACE_LOADER - ---help--- - This is the default pathname of policy loader which is called before - activation. You can override this setting via TOMOYO_loader= kernel - command line option. - -config SECURITY_TOMOYO_ACTIVATION_TRIGGER - string "Trigger for calling userspace policy loader" - default "/sbin/init" - depends on SECURITY_TOMOYO - depends on !SECURITY_TOMOYO_OMIT_USERSPACE_LOADER - ---help--- - This is the default pathname of activation trigger. - You can override this setting via TOMOYO_trigger= kernel command line - option. For example, if you pass init=/bin/systemd option, you may - want to also pass TOMOYO_trigger=/bin/systemd option. diff --git a/ANDROID_3.4.5/security/tomoyo/Makefile b/ANDROID_3.4.5/security/tomoyo/Makefile deleted file mode 100644 index 56a0c7be..00000000 --- a/ANDROID_3.4.5/security/tomoyo/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load_policy.o memory.o mount.o network.o realpath.o securityfs_if.o tomoyo.o util.o - -$(obj)/policy/profile.conf: - @mkdir -p $(obj)/policy/ - @echo Creating an empty policy/profile.conf - @touch $@ - -$(obj)/policy/exception_policy.conf: - @mkdir -p $(obj)/policy/ - @echo Creating a default policy/exception_policy.conf - @echo initialize_domain /sbin/modprobe from any >> $@ - @echo initialize_domain /sbin/hotplug from any >> $@ - -$(obj)/policy/domain_policy.conf: - @mkdir -p $(obj)/policy/ - @echo Creating an empty policy/domain_policy.conf - @touch $@ - -$(obj)/policy/manager.conf: - @mkdir -p $(obj)/policy/ - @echo Creating an empty policy/manager.conf - @touch $@ - -$(obj)/policy/stat.conf: - @mkdir -p $(obj)/policy/ - @echo Creating an empty policy/stat.conf - @touch $@ - -$(obj)/builtin-policy.h: $(obj)/policy/profile.conf $(obj)/policy/exception_policy.conf $(obj)/policy/domain_policy.conf $(obj)/policy/manager.conf $(obj)/policy/stat.conf - @echo Generating built-in policy for TOMOYO 2.5.x. - @echo "static char tomoyo_builtin_profile[] __initdata =" > $@.tmp - @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/profile.conf >> $@.tmp - @echo "\"\";" >> $@.tmp - @echo "static char tomoyo_builtin_exception_policy[] __initdata =" >> $@.tmp - @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/exception_policy.conf >> $@.tmp - @echo "\"\";" >> $@.tmp - @echo "static char tomoyo_builtin_domain_policy[] __initdata =" >> $@.tmp - @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/domain_policy.conf >> $@.tmp - @echo "\"\";" >> $@.tmp - @echo "static char tomoyo_builtin_manager[] __initdata =" >> $@.tmp - @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/manager.conf >> $@.tmp - @echo "\"\";" >> $@.tmp - @echo "static char tomoyo_builtin_stat[] __initdata =" >> $@.tmp - @sed -e 's/\\/\\\\/g' -e 's/\"/\\"/g' -e 's/\(.*\)/"\1\\n"/' < $(obj)/policy/stat.conf >> $@.tmp - @echo "\"\";" >> $@.tmp - @mv $@.tmp $@ - -$(obj)/common.o: $(obj)/builtin-policy.h diff --git a/ANDROID_3.4.5/security/tomoyo/audit.c b/ANDROID_3.4.5/security/tomoyo/audit.c deleted file mode 100644 index 7ef9fa3e..00000000 --- a/ANDROID_3.4.5/security/tomoyo/audit.c +++ /dev/null @@ -1,461 +0,0 @@ -/* - * security/tomoyo/audit.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include "common.h" -#include <linux/slab.h> - -/** - * tomoyo_print_bprm - Print "struct linux_binprm" for auditing. - * - * @bprm: Pointer to "struct linux_binprm". - * @dump: Pointer to "struct tomoyo_page_dump". - * - * Returns the contents of @bprm on success, NULL otherwise. - * - * This function uses kzalloc(), so caller must kfree() if this function - * didn't return NULL. - */ -static char *tomoyo_print_bprm(struct linux_binprm *bprm, - struct tomoyo_page_dump *dump) -{ - static const int tomoyo_buffer_len = 4096 * 2; - char *buffer = kzalloc(tomoyo_buffer_len, GFP_NOFS); - char *cp; - char *last_start; - int len; - unsigned long pos = bprm->p; - int offset = pos % PAGE_SIZE; - int argv_count = bprm->argc; - int envp_count = bprm->envc; - bool truncated = false; - if (!buffer) - return NULL; - len = snprintf(buffer, tomoyo_buffer_len - 1, "argv[]={ "); - cp = buffer + len; - if (!argv_count) { - memmove(cp, "} envp[]={ ", 11); - cp += 11; - } - last_start = cp; - while (argv_count || envp_count) { - if (!tomoyo_dump_page(bprm, pos, dump)) - goto out; - pos += PAGE_SIZE - offset; - /* Read. */ - while (offset < PAGE_SIZE) { - const char *kaddr = dump->data; - const unsigned char c = kaddr[offset++]; - if (cp == last_start) - *cp++ = '"'; - if (cp >= buffer + tomoyo_buffer_len - 32) { - /* Reserve some room for "..." string. */ - truncated = true; - } else if (c == '\\') { - *cp++ = '\\'; - *cp++ = '\\'; - } else if (c > ' ' && c < 127) { - *cp++ = c; - } else if (!c) { - *cp++ = '"'; - *cp++ = ' '; - last_start = cp; - } else { - *cp++ = '\\'; - *cp++ = (c >> 6) + '0'; - *cp++ = ((c >> 3) & 7) + '0'; - *cp++ = (c & 7) + '0'; - } - if (c) - continue; - if (argv_count) { - if (--argv_count == 0) { - if (truncated) { - cp = last_start; - memmove(cp, "... ", 4); - cp += 4; - } - memmove(cp, "} envp[]={ ", 11); - cp += 11; - last_start = cp; - truncated = false; - } - } else if (envp_count) { - if (--envp_count == 0) { - if (truncated) { - cp = last_start; - memmove(cp, "... ", 4); - cp += 4; - } - } - } - if (!argv_count && !envp_count) - break; - } - offset = 0; - } - *cp++ = '}'; - *cp = '\0'; - return buffer; -out: - snprintf(buffer, tomoyo_buffer_len - 1, - "argv[]={ ... } envp[]= { ... }"); - return buffer; -} - -/** - * tomoyo_filetype - Get string representation of file type. - * - * @mode: Mode value for stat(). - * - * Returns file type string. - */ -static inline const char *tomoyo_filetype(const umode_t mode) -{ - switch (mode & S_IFMT) { - case S_IFREG: - case 0: - return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FILE]; - case S_IFDIR: - return tomoyo_condition_keyword[TOMOYO_TYPE_IS_DIRECTORY]; - case S_IFLNK: - return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SYMLINK]; - case S_IFIFO: - return tomoyo_condition_keyword[TOMOYO_TYPE_IS_FIFO]; - case S_IFSOCK: - return tomoyo_condition_keyword[TOMOYO_TYPE_IS_SOCKET]; - case S_IFBLK: - return tomoyo_condition_keyword[TOMOYO_TYPE_IS_BLOCK_DEV]; - case S_IFCHR: - return tomoyo_condition_keyword[TOMOYO_TYPE_IS_CHAR_DEV]; - } - return "unknown"; /* This should not happen. */ -} - -/** - * 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) -{ - struct tomoyo_time stamp; - const pid_t gpid = task_pid_nr(current); - struct tomoyo_obj_info *obj = r->obj; - static const int tomoyo_buffer_len = 4096; - char *buffer = kmalloc(tomoyo_buffer_len, GFP_NOFS); - int pos; - u8 i; - if (!buffer) - return NULL; - { - struct timeval tv; - do_gettimeofday(&tv); - tomoyo_convert_time(tv.tv_sec, &stamp); - } - pos = snprintf(buffer, tomoyo_buffer_len - 1, - "#%04u/%02u/%02u %02u:%02u:%02u# profile=%u mode=%s " - "granted=%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 }", stamp.year, stamp.month, - stamp.day, stamp.hour, stamp.min, stamp.sec, r->profile, - tomoyo_mode[r->mode], tomoyo_yesno(r->granted), gpid, - tomoyo_sys_getpid(), tomoyo_sys_getppid(), - current_uid(), current_gid(), current_euid(), - current_egid(), current_suid(), current_sgid(), - current_fsuid(), current_fsgid()); - if (!obj) - goto no_obj_info; - if (!obj->validate_done) { - tomoyo_get_attributes(obj); - obj->validate_done = true; - } - for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) { - struct tomoyo_mini_stat *stat; - unsigned int dev; - umode_t mode; - if (!obj->stat_valid[i]) - continue; - stat = &obj->stat[i]; - dev = stat->dev; - mode = stat->mode; - if (i & 1) { - pos += snprintf(buffer + pos, - tomoyo_buffer_len - 1 - pos, - " path%u.parent={ uid=%u gid=%u " - "ino=%lu perm=0%o }", (i >> 1) + 1, - stat->uid, stat->gid, (unsigned long) - stat->ino, stat->mode & S_IALLUGO); - continue; - } - pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos, - " path%u={ uid=%u gid=%u ino=%lu major=%u" - " minor=%u perm=0%o type=%s", (i >> 1) + 1, - stat->uid, stat->gid, (unsigned long) - stat->ino, MAJOR(dev), MINOR(dev), - mode & S_IALLUGO, tomoyo_filetype(mode)); - if (S_ISCHR(mode) || S_ISBLK(mode)) { - dev = stat->rdev; - pos += snprintf(buffer + pos, - tomoyo_buffer_len - 1 - pos, - " dev_major=%u dev_minor=%u", - MAJOR(dev), MINOR(dev)); - } - pos += snprintf(buffer + pos, tomoyo_buffer_len - 1 - pos, - " }"); - } -no_obj_info: - if (pos < tomoyo_buffer_len - 1) - return buffer; - kfree(buffer); - return NULL; -} - -/** - * tomoyo_init_log - Allocate buffer for audit logs. - * - * @r: Pointer to "struct tomoyo_request_info". - * @len: Buffer size needed for @fmt and @args. - * @fmt: The printf()'s format string. - * @args: va_list structure for @fmt. - * - * Returns pointer to allocated memory. - * - * This function uses kzalloc(), so caller must kfree() if this function - * didn't return NULL. - */ -char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, - va_list args) -{ - char *buf = NULL; - char *bprm_info = NULL; - const char *header = NULL; - char *realpath = NULL; - const char *symlink = NULL; - int pos; - const char *domainname = r->domain->domainname->name; - header = tomoyo_print_header(r); - if (!header) - return NULL; - /* +10 is for '\n' etc. and '\0'. */ - len += strlen(domainname) + strlen(header) + 10; - if (r->ee) { - struct file *file = r->ee->bprm->file; - realpath = tomoyo_realpath_from_path(&file->f_path); - bprm_info = tomoyo_print_bprm(r->ee->bprm, &r->ee->dump); - if (!realpath || !bprm_info) - goto out; - /* +80 is for " exec={ realpath=\"%s\" argc=%d envc=%d %s }" */ - len += strlen(realpath) + 80 + strlen(bprm_info); - } else if (r->obj && r->obj->symlink_target) { - symlink = r->obj->symlink_target->name; - /* +18 is for " symlink.target=\"%s\"" */ - len += 18 + strlen(symlink); - } - len = tomoyo_round2(len); - buf = kzalloc(len, GFP_NOFS); - if (!buf) - goto out; - len--; - pos = snprintf(buf, len, "%s", header); - if (realpath) { - struct linux_binprm *bprm = r->ee->bprm; - pos += snprintf(buf + pos, len - pos, - " exec={ realpath=\"%s\" argc=%d envc=%d %s }", - realpath, bprm->argc, bprm->envc, bprm_info); - } else if (symlink) - pos += snprintf(buf + pos, len - pos, " symlink.target=\"%s\"", - symlink); - pos += snprintf(buf + pos, len - pos, "\n%s\n", domainname); - vsnprintf(buf + pos, len - pos, fmt, args); -out: - kfree(realpath); - kfree(bprm_info); - kfree(header); - return buf; -} - -/* Wait queue for /sys/kernel/security/tomoyo/audit. */ -static DECLARE_WAIT_QUEUE_HEAD(tomoyo_log_wait); - -/* Structure for audit log. */ -struct tomoyo_log { - struct list_head list; - char *log; - int size; -}; - -/* The list for "struct tomoyo_log". */ -static LIST_HEAD(tomoyo_log); - -/* Lock for "struct list_head tomoyo_log". */ -static DEFINE_SPINLOCK(tomoyo_log_lock); - -/* Length of "stuct list_head tomoyo_log". */ -static unsigned int tomoyo_log_count; - -/** - * tomoyo_get_audit - Get audit mode. - * - * @ns: Pointer to "struct tomoyo_policy_namespace". - * @profile: Profile number. - * @index: Index number of functionality. - * @is_granted: True if granted log, false otherwise. - * - * Returns true if this request should be audited, false otherwise. - */ -static bool tomoyo_get_audit(const struct tomoyo_policy_namespace *ns, - const u8 profile, const u8 index, - const struct tomoyo_acl_info *matched_acl, - const bool is_granted) -{ - u8 mode; - const u8 category = tomoyo_index2category[index] + - TOMOYO_MAX_MAC_INDEX; - struct tomoyo_profile *p; - if (!tomoyo_policy_loaded) - return false; - p = tomoyo_profile(ns, profile); - if (tomoyo_log_count >= p->pref[TOMOYO_PREF_MAX_AUDIT_LOG]) - return false; - if (is_granted && matched_acl && matched_acl->cond && - matched_acl->cond->grant_log != TOMOYO_GRANTLOG_AUTO) - return matched_acl->cond->grant_log == TOMOYO_GRANTLOG_YES; - mode = p->config[index]; - if (mode == TOMOYO_CONFIG_USE_DEFAULT) - mode = p->config[category]; - if (mode == TOMOYO_CONFIG_USE_DEFAULT) - mode = p->default_config; - if (is_granted) - return mode & TOMOYO_CONFIG_WANT_GRANT_LOG; - return mode & TOMOYO_CONFIG_WANT_REJECT_LOG; -} - -/** - * tomoyo_write_log2 - Write an audit log. - * - * @r: Pointer to "struct tomoyo_request_info". - * @len: Buffer size needed for @fmt and @args. - * @fmt: The printf()'s format string. - * @args: va_list structure for @fmt. - * - * Returns nothing. - */ -void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, - va_list args) -{ - char *buf; - struct tomoyo_log *entry; - bool quota_exceeded = false; - if (!tomoyo_get_audit(r->domain->ns, r->profile, r->type, - r->matched_acl, r->granted)) - goto out; - buf = tomoyo_init_log(r, len, fmt, args); - if (!buf) - goto out; - entry = kzalloc(sizeof(*entry), GFP_NOFS); - if (!entry) { - kfree(buf); - goto out; - } - entry->log = buf; - len = tomoyo_round2(strlen(buf) + 1); - /* - * The entry->size is used for memory quota checks. - * Don't go beyond strlen(entry->log). - */ - entry->size = len + tomoyo_round2(sizeof(*entry)); - spin_lock(&tomoyo_log_lock); - if (tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT] && - tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] + entry->size >= - tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT]) { - quota_exceeded = true; - } else { - tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] += entry->size; - list_add_tail(&entry->list, &tomoyo_log); - tomoyo_log_count++; - } - spin_unlock(&tomoyo_log_lock); - if (quota_exceeded) { - kfree(buf); - kfree(entry); - goto out; - } - wake_up(&tomoyo_log_wait); -out: - return; -} - -/** - * tomoyo_write_log - Write an audit log. - * - * @r: Pointer to "struct tomoyo_request_info". - * @fmt: The printf()'s format string, followed by parameters. - * - * Returns nothing. - */ -void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...) -{ - va_list args; - int len; - va_start(args, fmt); - len = vsnprintf((char *) &len, 1, fmt, args) + 1; - va_end(args); - va_start(args, fmt); - tomoyo_write_log2(r, len, fmt, args); - va_end(args); -} - -/** - * tomoyo_read_log - Read an audit log. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns nothing. - */ -void tomoyo_read_log(struct tomoyo_io_buffer *head) -{ - struct tomoyo_log *ptr = NULL; - if (head->r.w_pos) - return; - kfree(head->read_buf); - head->read_buf = NULL; - spin_lock(&tomoyo_log_lock); - if (!list_empty(&tomoyo_log)) { - ptr = list_entry(tomoyo_log.next, typeof(*ptr), list); - list_del(&ptr->list); - tomoyo_log_count--; - tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] -= ptr->size; - } - spin_unlock(&tomoyo_log_lock); - if (ptr) { - head->read_buf = ptr->log; - head->r.w[head->r.w_pos++] = head->read_buf; - kfree(ptr); - } -} - -/** - * tomoyo_poll_log - Wait for an audit log. - * - * @file: Pointer to "struct file". - * @wait: Pointer to "poll_table". Maybe NULL. - * - * Returns POLLIN | POLLRDNORM when ready to read an audit log. - */ -unsigned int tomoyo_poll_log(struct file *file, poll_table *wait) -{ - if (tomoyo_log_count) - return POLLIN | POLLRDNORM; - poll_wait(file, &tomoyo_log_wait, wait); - if (tomoyo_log_count) - return POLLIN | POLLRDNORM; - return 0; -} diff --git a/ANDROID_3.4.5/security/tomoyo/common.c b/ANDROID_3.4.5/security/tomoyo/common.c deleted file mode 100644 index 8656b16e..00000000 --- a/ANDROID_3.4.5/security/tomoyo/common.c +++ /dev/null @@ -1,2806 +0,0 @@ -/* - * security/tomoyo/common.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include <linux/uaccess.h> -#include <linux/slab.h> -#include <linux/security.h> -#include "common.h" - -/* String table for operation mode. */ -const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE] = { - [TOMOYO_CONFIG_DISABLED] = "disabled", - [TOMOYO_CONFIG_LEARNING] = "learning", - [TOMOYO_CONFIG_PERMISSIVE] = "permissive", - [TOMOYO_CONFIG_ENFORCING] = "enforcing" -}; - -/* String table for /sys/kernel/security/tomoyo/profile */ -const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX - + TOMOYO_MAX_MAC_CATEGORY_INDEX] = { - /* CONFIG::file group */ - [TOMOYO_MAC_FILE_EXECUTE] = "execute", - [TOMOYO_MAC_FILE_OPEN] = "open", - [TOMOYO_MAC_FILE_CREATE] = "create", - [TOMOYO_MAC_FILE_UNLINK] = "unlink", - [TOMOYO_MAC_FILE_GETATTR] = "getattr", - [TOMOYO_MAC_FILE_MKDIR] = "mkdir", - [TOMOYO_MAC_FILE_RMDIR] = "rmdir", - [TOMOYO_MAC_FILE_MKFIFO] = "mkfifo", - [TOMOYO_MAC_FILE_MKSOCK] = "mksock", - [TOMOYO_MAC_FILE_TRUNCATE] = "truncate", - [TOMOYO_MAC_FILE_SYMLINK] = "symlink", - [TOMOYO_MAC_FILE_MKBLOCK] = "mkblock", - [TOMOYO_MAC_FILE_MKCHAR] = "mkchar", - [TOMOYO_MAC_FILE_LINK] = "link", - [TOMOYO_MAC_FILE_RENAME] = "rename", - [TOMOYO_MAC_FILE_CHMOD] = "chmod", - [TOMOYO_MAC_FILE_CHOWN] = "chown", - [TOMOYO_MAC_FILE_CHGRP] = "chgrp", - [TOMOYO_MAC_FILE_IOCTL] = "ioctl", - [TOMOYO_MAC_FILE_CHROOT] = "chroot", - [TOMOYO_MAC_FILE_MOUNT] = "mount", - [TOMOYO_MAC_FILE_UMOUNT] = "unmount", - [TOMOYO_MAC_FILE_PIVOT_ROOT] = "pivot_root", - /* CONFIG::network group */ - [TOMOYO_MAC_NETWORK_INET_STREAM_BIND] = "inet_stream_bind", - [TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN] = "inet_stream_listen", - [TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT] = "inet_stream_connect", - [TOMOYO_MAC_NETWORK_INET_DGRAM_BIND] = "inet_dgram_bind", - [TOMOYO_MAC_NETWORK_INET_DGRAM_SEND] = "inet_dgram_send", - [TOMOYO_MAC_NETWORK_INET_RAW_BIND] = "inet_raw_bind", - [TOMOYO_MAC_NETWORK_INET_RAW_SEND] = "inet_raw_send", - [TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND] = "unix_stream_bind", - [TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN] = "unix_stream_listen", - [TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT] = "unix_stream_connect", - [TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND] = "unix_dgram_bind", - [TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND] = "unix_dgram_send", - [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND] = "unix_seqpacket_bind", - [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = "unix_seqpacket_listen", - [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = "unix_seqpacket_connect", - /* CONFIG::misc group */ - [TOMOYO_MAC_ENVIRON] = "env", - /* CONFIG group */ - [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file", - [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_NETWORK] = "network", - [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_MISC] = "misc", -}; - -/* String table for conditions. */ -const char * const tomoyo_condition_keyword[TOMOYO_MAX_CONDITION_KEYWORD] = { - [TOMOYO_TASK_UID] = "task.uid", - [TOMOYO_TASK_EUID] = "task.euid", - [TOMOYO_TASK_SUID] = "task.suid", - [TOMOYO_TASK_FSUID] = "task.fsuid", - [TOMOYO_TASK_GID] = "task.gid", - [TOMOYO_TASK_EGID] = "task.egid", - [TOMOYO_TASK_SGID] = "task.sgid", - [TOMOYO_TASK_FSGID] = "task.fsgid", - [TOMOYO_TASK_PID] = "task.pid", - [TOMOYO_TASK_PPID] = "task.ppid", - [TOMOYO_EXEC_ARGC] = "exec.argc", - [TOMOYO_EXEC_ENVC] = "exec.envc", - [TOMOYO_TYPE_IS_SOCKET] = "socket", - [TOMOYO_TYPE_IS_SYMLINK] = "symlink", - [TOMOYO_TYPE_IS_FILE] = "file", - [TOMOYO_TYPE_IS_BLOCK_DEV] = "block", - [TOMOYO_TYPE_IS_DIRECTORY] = "directory", - [TOMOYO_TYPE_IS_CHAR_DEV] = "char", - [TOMOYO_TYPE_IS_FIFO] = "fifo", - [TOMOYO_MODE_SETUID] = "setuid", - [TOMOYO_MODE_SETGID] = "setgid", - [TOMOYO_MODE_STICKY] = "sticky", - [TOMOYO_MODE_OWNER_READ] = "owner_read", - [TOMOYO_MODE_OWNER_WRITE] = "owner_write", - [TOMOYO_MODE_OWNER_EXECUTE] = "owner_execute", - [TOMOYO_MODE_GROUP_READ] = "group_read", - [TOMOYO_MODE_GROUP_WRITE] = "group_write", - [TOMOYO_MODE_GROUP_EXECUTE] = "group_execute", - [TOMOYO_MODE_OTHERS_READ] = "others_read", - [TOMOYO_MODE_OTHERS_WRITE] = "others_write", - [TOMOYO_MODE_OTHERS_EXECUTE] = "others_execute", - [TOMOYO_EXEC_REALPATH] = "exec.realpath", - [TOMOYO_SYMLINK_TARGET] = "symlink.target", - [TOMOYO_PATH1_UID] = "path1.uid", - [TOMOYO_PATH1_GID] = "path1.gid", - [TOMOYO_PATH1_INO] = "path1.ino", - [TOMOYO_PATH1_MAJOR] = "path1.major", - [TOMOYO_PATH1_MINOR] = "path1.minor", - [TOMOYO_PATH1_PERM] = "path1.perm", - [TOMOYO_PATH1_TYPE] = "path1.type", - [TOMOYO_PATH1_DEV_MAJOR] = "path1.dev_major", - [TOMOYO_PATH1_DEV_MINOR] = "path1.dev_minor", - [TOMOYO_PATH2_UID] = "path2.uid", - [TOMOYO_PATH2_GID] = "path2.gid", - [TOMOYO_PATH2_INO] = "path2.ino", - [TOMOYO_PATH2_MAJOR] = "path2.major", - [TOMOYO_PATH2_MINOR] = "path2.minor", - [TOMOYO_PATH2_PERM] = "path2.perm", - [TOMOYO_PATH2_TYPE] = "path2.type", - [TOMOYO_PATH2_DEV_MAJOR] = "path2.dev_major", - [TOMOYO_PATH2_DEV_MINOR] = "path2.dev_minor", - [TOMOYO_PATH1_PARENT_UID] = "path1.parent.uid", - [TOMOYO_PATH1_PARENT_GID] = "path1.parent.gid", - [TOMOYO_PATH1_PARENT_INO] = "path1.parent.ino", - [TOMOYO_PATH1_PARENT_PERM] = "path1.parent.perm", - [TOMOYO_PATH2_PARENT_UID] = "path2.parent.uid", - [TOMOYO_PATH2_PARENT_GID] = "path2.parent.gid", - [TOMOYO_PATH2_PARENT_INO] = "path2.parent.ino", - [TOMOYO_PATH2_PARENT_PERM] = "path2.parent.perm", -}; - -/* String table for PREFERENCE keyword. */ -static const char * const tomoyo_pref_keywords[TOMOYO_MAX_PREF] = { - [TOMOYO_PREF_MAX_AUDIT_LOG] = "max_audit_log", - [TOMOYO_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry", -}; - -/* String table for path operation. */ -const char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { - [TOMOYO_TYPE_EXECUTE] = "execute", - [TOMOYO_TYPE_READ] = "read", - [TOMOYO_TYPE_WRITE] = "write", - [TOMOYO_TYPE_APPEND] = "append", - [TOMOYO_TYPE_UNLINK] = "unlink", - [TOMOYO_TYPE_GETATTR] = "getattr", - [TOMOYO_TYPE_RMDIR] = "rmdir", - [TOMOYO_TYPE_TRUNCATE] = "truncate", - [TOMOYO_TYPE_SYMLINK] = "symlink", - [TOMOYO_TYPE_CHROOT] = "chroot", - [TOMOYO_TYPE_UMOUNT] = "unmount", -}; - -/* String table for socket's operation. */ -const char * const tomoyo_socket_keyword[TOMOYO_MAX_NETWORK_OPERATION] = { - [TOMOYO_NETWORK_BIND] = "bind", - [TOMOYO_NETWORK_LISTEN] = "listen", - [TOMOYO_NETWORK_CONNECT] = "connect", - [TOMOYO_NETWORK_SEND] = "send", -}; - -/* String table for categories. */ -static const char * const tomoyo_category_keywords -[TOMOYO_MAX_MAC_CATEGORY_INDEX] = { - [TOMOYO_MAC_CATEGORY_FILE] = "file", - [TOMOYO_MAC_CATEGORY_NETWORK] = "network", - [TOMOYO_MAC_CATEGORY_MISC] = "misc", -}; - -/* 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. - */ -const char *tomoyo_yesno(const unsigned int value) -{ - return value ? "yes" : "no"; -} - -/** - * tomoyo_addprintf - strncat()-like-snprintf(). - * - * @buffer: Buffer to write to. Must be '\0'-terminated. - * @len: Size of @buffer. - * @fmt: The printf()'s format string, followed by parameters. - * - * Returns nothing. - */ -static void tomoyo_addprintf(char *buffer, int len, const char *fmt, ...) -{ - va_list args; - const int pos = strlen(buffer); - va_start(args, fmt); - vsnprintf(buffer + pos, len - pos - 1, fmt, args); - va_end(args); -} - -/** - * tomoyo_flush - Flush queued string to userspace's buffer. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns true if all data was flushed, false otherwise. - */ -static bool tomoyo_flush(struct tomoyo_io_buffer *head) -{ - while (head->r.w_pos) { - const char *w = head->r.w[0]; - size_t len = strlen(w); - if (len) { - if (len > head->read_user_buf_avail) - len = head->read_user_buf_avail; - if (!len) - return false; - if (copy_to_user(head->read_user_buf, w, len)) - return false; - head->read_user_buf_avail -= len; - head->read_user_buf += len; - w += len; - } - head->r.w[0] = w; - if (*w) - return false; - /* Add '\0' for audit logs and query. */ - if (head->poll) { - if (!head->read_user_buf_avail || - copy_to_user(head->read_user_buf, "", 1)) - return false; - head->read_user_buf_avail--; - head->read_user_buf++; - } - head->r.w_pos--; - for (len = 0; len < head->r.w_pos; len++) - head->r.w[len] = head->r.w[len + 1]; - } - head->r.avail = 0; - return true; -} - -/** - * tomoyo_set_string - Queue string to "struct tomoyo_io_buffer" structure. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @string: String to print. - * - * Note that @string has to be kept valid until @head is kfree()d. - * This means that char[] allocated on stack memory cannot be passed to - * this function. Use tomoyo_io_printf() for char[] allocated on stack memory. - */ -static void tomoyo_set_string(struct tomoyo_io_buffer *head, const char *string) -{ - if (head->r.w_pos < TOMOYO_MAX_IO_READ_QUEUE) { - head->r.w[head->r.w_pos++] = string; - tomoyo_flush(head); - } else - WARN_ON(1); -} - -static void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, - ...) __printf(2, 3); - -/** - * tomoyo_io_printf - printf() to "struct tomoyo_io_buffer" structure. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @fmt: The printf()'s format string, followed by parameters. - */ -static void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, - ...) -{ - va_list args; - size_t len; - size_t pos = head->r.avail; - int size = head->readbuf_size - pos; - if (size <= 0) - return; - va_start(args, fmt); - len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1; - va_end(args); - if (pos + len >= head->readbuf_size) { - WARN_ON(1); - return; - } - head->r.avail += len; - tomoyo_set_string(head, head->read_buf + pos); -} - -/** - * tomoyo_set_space - Put a space to "struct tomoyo_io_buffer" structure. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns nothing. - */ -static void tomoyo_set_space(struct tomoyo_io_buffer *head) -{ - tomoyo_set_string(head, " "); -} - -/** - * tomoyo_set_lf - Put a line feed to "struct tomoyo_io_buffer" structure. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns nothing. - */ -static bool tomoyo_set_lf(struct tomoyo_io_buffer *head) -{ - tomoyo_set_string(head, "\n"); - return !head->r.w_pos; -} - -/** - * tomoyo_set_slash - Put a shash to "struct tomoyo_io_buffer" structure. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns nothing. - */ -static void tomoyo_set_slash(struct tomoyo_io_buffer *head) -{ - tomoyo_set_string(head, "/"); -} - -/* List of namespaces. */ -LIST_HEAD(tomoyo_namespace_list); -/* True if namespace other than tomoyo_kernel_namespace is defined. */ -static bool tomoyo_namespace_enabled; - -/** - * tomoyo_init_policy_namespace - Initialize namespace. - * - * @ns: Pointer to "struct tomoyo_policy_namespace". - * - * Returns nothing. - */ -void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns) -{ - unsigned int idx; - for (idx = 0; idx < TOMOYO_MAX_ACL_GROUPS; idx++) - INIT_LIST_HEAD(&ns->acl_group[idx]); - for (idx = 0; idx < TOMOYO_MAX_GROUP; idx++) - INIT_LIST_HEAD(&ns->group_list[idx]); - for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++) - INIT_LIST_HEAD(&ns->policy_list[idx]); - ns->profile_version = 20110903; - tomoyo_namespace_enabled = !list_empty(&tomoyo_namespace_list); - list_add_tail_rcu(&ns->namespace_list, &tomoyo_namespace_list); -} - -/** - * tomoyo_print_namespace - Print namespace header. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns nothing. - */ -static void tomoyo_print_namespace(struct tomoyo_io_buffer *head) -{ - if (!tomoyo_namespace_enabled) - return; - tomoyo_set_string(head, - container_of(head->r.ns, - struct tomoyo_policy_namespace, - namespace_list)->name); - tomoyo_set_space(head); -} - -/** - * tomoyo_print_name_union - Print a tomoyo_name_union. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @ptr: Pointer to "struct tomoyo_name_union". - */ -static void tomoyo_print_name_union(struct tomoyo_io_buffer *head, - const struct tomoyo_name_union *ptr) -{ - tomoyo_set_space(head); - if (ptr->group) { - tomoyo_set_string(head, "@"); - tomoyo_set_string(head, ptr->group->group_name->name); - } else { - tomoyo_set_string(head, ptr->filename->name); - } -} - -/** - * tomoyo_print_name_union_quoted - Print a tomoyo_name_union with a quote. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @ptr: Pointer to "struct tomoyo_name_union". - * - * Returns nothing. - */ -static void tomoyo_print_name_union_quoted(struct tomoyo_io_buffer *head, - const struct tomoyo_name_union *ptr) -{ - if (ptr->group) { - tomoyo_set_string(head, "@"); - tomoyo_set_string(head, ptr->group->group_name->name); - } else { - tomoyo_set_string(head, "\""); - tomoyo_set_string(head, ptr->filename->name); - tomoyo_set_string(head, "\""); - } -} - -/** - * tomoyo_print_number_union_nospace - Print a tomoyo_number_union without a space. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @ptr: Pointer to "struct tomoyo_number_union". - * - * Returns nothing. - */ -static void tomoyo_print_number_union_nospace -(struct tomoyo_io_buffer *head, const struct tomoyo_number_union *ptr) -{ - if (ptr->group) { - tomoyo_set_string(head, "@"); - tomoyo_set_string(head, ptr->group->group_name->name); - } else { - int i; - unsigned long min = ptr->values[0]; - const unsigned long max = ptr->values[1]; - u8 min_type = ptr->value_type[0]; - const u8 max_type = ptr->value_type[1]; - char buffer[128]; - buffer[0] = '\0'; - for (i = 0; i < 2; i++) { - switch (min_type) { - case TOMOYO_VALUE_TYPE_HEXADECIMAL: - tomoyo_addprintf(buffer, sizeof(buffer), - "0x%lX", min); - break; - case TOMOYO_VALUE_TYPE_OCTAL: - tomoyo_addprintf(buffer, sizeof(buffer), - "0%lo", min); - break; - default: - tomoyo_addprintf(buffer, sizeof(buffer), "%lu", - min); - break; - } - if (min == max && min_type == max_type) - break; - tomoyo_addprintf(buffer, sizeof(buffer), "-"); - min_type = max_type; - min = max; - } - tomoyo_io_printf(head, "%s", buffer); - } -} - -/** - * tomoyo_print_number_union - Print a tomoyo_number_union. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @ptr: Pointer to "struct tomoyo_number_union". - * - * Returns nothing. - */ -static void tomoyo_print_number_union(struct tomoyo_io_buffer *head, - const struct tomoyo_number_union *ptr) -{ - tomoyo_set_space(head); - tomoyo_print_number_union_nospace(head, ptr); -} - -/** - * tomoyo_assign_profile - Create a new profile. - * - * @ns: Pointer to "struct tomoyo_policy_namespace". - * @profile: Profile number to create. - * - * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise. - */ -static struct tomoyo_profile *tomoyo_assign_profile -(struct tomoyo_policy_namespace *ns, const unsigned int profile) -{ - struct tomoyo_profile *ptr; - struct tomoyo_profile *entry; - if (profile >= TOMOYO_MAX_PROFILES) - return NULL; - ptr = ns->profile_ptr[profile]; - if (ptr) - return ptr; - entry = kzalloc(sizeof(*entry), GFP_NOFS); - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - goto out; - ptr = ns->profile_ptr[profile]; - if (!ptr && tomoyo_memory_ok(entry)) { - ptr = entry; - ptr->default_config = TOMOYO_CONFIG_DISABLED | - TOMOYO_CONFIG_WANT_GRANT_LOG | - TOMOYO_CONFIG_WANT_REJECT_LOG; - memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT, - sizeof(ptr->config)); - ptr->pref[TOMOYO_PREF_MAX_AUDIT_LOG] = - CONFIG_SECURITY_TOMOYO_MAX_AUDIT_LOG; - ptr->pref[TOMOYO_PREF_MAX_LEARNING_ENTRY] = - CONFIG_SECURITY_TOMOYO_MAX_ACCEPT_ENTRY; - mb(); /* Avoid out-of-order execution. */ - ns->profile_ptr[profile] = ptr; - entry = NULL; - } - mutex_unlock(&tomoyo_policy_lock); - out: - kfree(entry); - return ptr; -} - -/** - * tomoyo_profile - Find a profile. - * - * @ns: Pointer to "struct tomoyo_policy_namespace". - * @profile: Profile number to find. - * - * Returns pointer to "struct tomoyo_profile". - */ -struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns, - const u8 profile) -{ - static struct tomoyo_profile tomoyo_null_profile; - struct tomoyo_profile *ptr = ns->profile_ptr[profile]; - if (!ptr) - ptr = &tomoyo_null_profile; - return ptr; -} - -/** - * tomoyo_find_yesno - Find values for specified keyword. - * - * @string: String to check. - * @find: Name of keyword. - * - * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise. - */ -static s8 tomoyo_find_yesno(const char *string, const char *find) -{ - const char *cp = strstr(string, find); - if (cp) { - cp += strlen(find); - if (!strncmp(cp, "=yes", 4)) - return 1; - else if (!strncmp(cp, "=no", 3)) - return 0; - } - return -1; -} - -/** - * tomoyo_set_uint - Set value for specified preference. - * - * @i: Pointer to "unsigned int". - * @string: String to check. - * @find: Name of keyword. - * - * Returns nothing. - */ -static void tomoyo_set_uint(unsigned int *i, const char *string, - const char *find) -{ - const char *cp = strstr(string, find); - if (cp) - sscanf(cp + strlen(find), "=%u", i); -} - -/** - * tomoyo_set_mode - Set mode for specified profile. - * - * @name: Name of functionality. - * @value: Mode for @name. - * @profile: Pointer to "struct tomoyo_profile". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_set_mode(char *name, const char *value, - struct tomoyo_profile *profile) -{ - u8 i; - u8 config; - if (!strcmp(name, "CONFIG")) { - i = TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX; - config = profile->default_config; - } else if (tomoyo_str_starts(&name, "CONFIG::")) { - config = 0; - for (i = 0; i < TOMOYO_MAX_MAC_INDEX - + TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) { - int len = 0; - if (i < TOMOYO_MAX_MAC_INDEX) { - const u8 c = tomoyo_index2category[i]; - const char *category = - tomoyo_category_keywords[c]; - len = strlen(category); - if (strncmp(name, category, len) || - name[len++] != ':' || name[len++] != ':') - continue; - } - if (strcmp(name + len, tomoyo_mac_keywords[i])) - continue; - config = profile->config[i]; - break; - } - if (i == TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX) - return -EINVAL; - } else { - return -EINVAL; - } - if (strstr(value, "use_default")) { - config = TOMOYO_CONFIG_USE_DEFAULT; - } else { - u8 mode; - for (mode = 0; mode < 4; mode++) - if (strstr(value, tomoyo_mode[mode])) - /* - * Update lower 3 bits in order to distinguish - * 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'. - */ - config = (config & ~7) | mode; - if (config != TOMOYO_CONFIG_USE_DEFAULT) { - switch (tomoyo_find_yesno(value, "grant_log")) { - case 1: - config |= TOMOYO_CONFIG_WANT_GRANT_LOG; - break; - case 0: - config &= ~TOMOYO_CONFIG_WANT_GRANT_LOG; - break; - } - switch (tomoyo_find_yesno(value, "reject_log")) { - case 1: - config |= TOMOYO_CONFIG_WANT_REJECT_LOG; - break; - case 0: - config &= ~TOMOYO_CONFIG_WANT_REJECT_LOG; - break; - } - } - } - 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_write_profile - Write profile table. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_write_profile(struct tomoyo_io_buffer *head) -{ - char *data = head->write_buf; - unsigned int i; - char *cp; - struct tomoyo_profile *profile; - if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version) - == 1) - return 0; - i = simple_strtoul(data, &cp, 10); - if (*cp != '-') - return -EINVAL; - data = cp + 1; - profile = tomoyo_assign_profile(head->w.ns, i); - if (!profile) - return -EINVAL; - cp = strchr(data, '='); - if (!cp) - return -EINVAL; - *cp++ = '\0'; - if (!strcmp(data, "COMMENT")) { - static DEFINE_SPINLOCK(lock); - const struct tomoyo_path_info *new_comment - = tomoyo_get_name(cp); - const struct tomoyo_path_info *old_comment; - if (!new_comment) - return -ENOMEM; - spin_lock(&lock); - old_comment = profile->comment; - profile->comment = new_comment; - spin_unlock(&lock); - tomoyo_put_name(old_comment); - return 0; - } - if (!strcmp(data, "PREFERENCE")) { - for (i = 0; i < TOMOYO_MAX_PREF; i++) - tomoyo_set_uint(&profile->pref[i], cp, - tomoyo_pref_keywords[i]); - return 0; - } - return tomoyo_set_mode(data, cp, profile); -} - -/** - * tomoyo_print_config - Print mode for specified functionality. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @config: Mode for that functionality. - * - * Returns nothing. - * - * Caller prints functionality's name. - */ -static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config) -{ - tomoyo_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n", - tomoyo_mode[config & 3], - tomoyo_yesno(config & TOMOYO_CONFIG_WANT_GRANT_LOG), - tomoyo_yesno(config & TOMOYO_CONFIG_WANT_REJECT_LOG)); -} - -/** - * tomoyo_read_profile - Read profile table. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns nothing. - */ -static void tomoyo_read_profile(struct tomoyo_io_buffer *head) -{ - u8 index; - struct tomoyo_policy_namespace *ns = - container_of(head->r.ns, typeof(*ns), namespace_list); - const struct tomoyo_profile *profile; - if (head->r.eof) - return; - next: - index = head->r.index; - profile = ns->profile_ptr[index]; - switch (head->r.step) { - case 0: - tomoyo_print_namespace(head); - tomoyo_io_printf(head, "PROFILE_VERSION=%u\n", - ns->profile_version); - head->r.step++; - break; - case 1: - for ( ; head->r.index < TOMOYO_MAX_PROFILES; - head->r.index++) - if (ns->profile_ptr[head->r.index]) - break; - if (head->r.index == TOMOYO_MAX_PROFILES) { - head->r.eof = true; - return; - } - head->r.step++; - break; - case 2: - { - u8 i; - const struct tomoyo_path_info *comment = - profile->comment; - tomoyo_print_namespace(head); - tomoyo_io_printf(head, "%u-COMMENT=", index); - tomoyo_set_string(head, comment ? comment->name : ""); - tomoyo_set_lf(head); - tomoyo_print_namespace(head); - tomoyo_io_printf(head, "%u-PREFERENCE={ ", index); - for (i = 0; i < TOMOYO_MAX_PREF; i++) - tomoyo_io_printf(head, "%s=%u ", - tomoyo_pref_keywords[i], - profile->pref[i]); - tomoyo_set_string(head, "}\n"); - head->r.step++; - } - break; - case 3: - { - tomoyo_print_namespace(head); - tomoyo_io_printf(head, "%u-%s", index, "CONFIG"); - tomoyo_print_config(head, profile->default_config); - head->r.bit = 0; - head->r.step++; - } - break; - case 4: - for ( ; head->r.bit < TOMOYO_MAX_MAC_INDEX - + TOMOYO_MAX_MAC_CATEGORY_INDEX; head->r.bit++) { - const u8 i = head->r.bit; - const u8 config = profile->config[i]; - if (config == TOMOYO_CONFIG_USE_DEFAULT) - continue; - tomoyo_print_namespace(head); - if (i < TOMOYO_MAX_MAC_INDEX) - tomoyo_io_printf(head, "%u-CONFIG::%s::%s", - index, - tomoyo_category_keywords - [tomoyo_index2category[i]], - tomoyo_mac_keywords[i]); - else - tomoyo_io_printf(head, "%u-CONFIG::%s", index, - tomoyo_mac_keywords[i]); - tomoyo_print_config(head, config); - head->r.bit++; - break; - } - if (head->r.bit == TOMOYO_MAX_MAC_INDEX - + TOMOYO_MAX_MAC_CATEGORY_INDEX) { - head->r.index++; - head->r.step = 1; - } - break; - } - if (tomoyo_flush(head)) - goto next; -} - -/** - * tomoyo_same_manager - Check for duplicated "struct tomoyo_manager" entry. - * - * @a: Pointer to "struct tomoyo_acl_head". - * @b: Pointer to "struct tomoyo_acl_head". - * - * Returns true if @a == @b, false otherwise. - */ -static bool tomoyo_same_manager(const struct tomoyo_acl_head *a, - const struct tomoyo_acl_head *b) -{ - return container_of(a, struct tomoyo_manager, head)->manager == - container_of(b, struct tomoyo_manager, head)->manager; -} - -/** - * tomoyo_update_manager_entry - Add a manager entry. - * - * @manager: The path to manager or the domainnamme. - * @is_delete: True if it is a delete request. - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_update_manager_entry(const char *manager, - const bool is_delete) -{ - struct tomoyo_manager e = { }; - struct tomoyo_acl_param param = { - /* .ns = &tomoyo_kernel_namespace, */ - .is_delete = is_delete, - .list = &tomoyo_kernel_namespace. - policy_list[TOMOYO_ID_MANAGER], - }; - int error = is_delete ? -ENOENT : -ENOMEM; - if (tomoyo_domain_def(manager)) { - if (!tomoyo_correct_domain(manager)) - return -EINVAL; - e.is_domain = true; - } else { - if (!tomoyo_correct_path(manager)) - return -EINVAL; - } - e.manager = tomoyo_get_name(manager); - if (e.manager) { - error = tomoyo_update_policy(&e.head, sizeof(e), ¶m, - tomoyo_same_manager); - tomoyo_put_name(e.manager); - } - return error; -} - -/** - * tomoyo_write_manager - Write manager policy. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_write_manager(struct tomoyo_io_buffer *head) -{ - char *data = head->write_buf; - - if (!strcmp(data, "manage_by_non_root")) { - tomoyo_manage_by_non_root = !head->w.is_delete; - return 0; - } - return tomoyo_update_manager_entry(data, head->w.is_delete); -} - -/** - * tomoyo_read_manager - Read manager policy. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Caller holds tomoyo_read_lock(). - */ -static void tomoyo_read_manager(struct tomoyo_io_buffer *head) -{ - if (head->r.eof) - return; - list_for_each_cookie(head->r.acl, &tomoyo_kernel_namespace. - policy_list[TOMOYO_ID_MANAGER]) { - struct tomoyo_manager *ptr = - list_entry(head->r.acl, typeof(*ptr), head.list); - if (ptr->head.is_deleted) - continue; - if (!tomoyo_flush(head)) - return; - tomoyo_set_string(head, ptr->manager->name); - tomoyo_set_lf(head); - } - head->r.eof = true; -} - -/** - * 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_manager(void) -{ - struct tomoyo_manager *ptr; - const char *exe; - const struct task_struct *task = current; - const struct tomoyo_path_info *domainname = tomoyo_domain()->domainname; - bool found = false; - - if (!tomoyo_policy_loaded) - return true; - if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid)) - return false; - list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace. - policy_list[TOMOYO_ID_MANAGER], head.list) { - if (!ptr->head.is_deleted && ptr->is_domain - && !tomoyo_pathcmp(domainname, ptr->manager)) { - found = true; - break; - } - } - if (found) - return true; - exe = tomoyo_get_exe(); - if (!exe) - return false; - list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace. - policy_list[TOMOYO_ID_MANAGER], head.list) { - if (!ptr->head.is_deleted && !ptr->is_domain - && !strcmp(exe, ptr->manager->name)) { - found = true; - break; - } - } - if (!found) { /* Reduce error messages. */ - static pid_t last_pid; - const pid_t pid = current->pid; - if (last_pid != pid) { - printk(KERN_WARNING "%s ( %s ) is not permitted to " - "update policies.\n", domainname->name, exe); - last_pid = pid; - } - } - kfree(exe); - return found; -} - -static struct tomoyo_domain_info *tomoyo_find_domain_by_qid -(unsigned int serial); - -/** - * tomoyo_select_domain - Parse select command. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @data: String to parse. - * - * Returns true on success, false otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static bool tomoyo_select_domain(struct tomoyo_io_buffer *head, - const char *data) -{ - unsigned int pid; - struct tomoyo_domain_info *domain = NULL; - bool global_pid = false; - if (strncmp(data, "select ", 7)) - return false; - data += 7; - if (sscanf(data, "pid=%u", &pid) == 1 || - (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) { - struct task_struct *p; - rcu_read_lock(); - if (global_pid) - p = find_task_by_pid_ns(pid, &init_pid_ns); - else - p = find_task_by_vpid(pid); - if (p) - domain = tomoyo_real_domain(p); - rcu_read_unlock(); - } else if (!strncmp(data, "domain=", 7)) { - if (tomoyo_domain_def(data + 7)) - domain = tomoyo_find_domain(data + 7); - } else if (sscanf(data, "Q=%u", &pid) == 1) { - domain = tomoyo_find_domain_by_qid(pid); - } else - return false; - head->w.domain = domain; - /* Accessing read_buf is safe because head->io_sem is held. */ - if (!head->read_buf) - return true; /* Do nothing if open(O_WRONLY). */ - memset(&head->r, 0, sizeof(head->r)); - head->r.print_this_domain_only = true; - if (domain) - head->r.domain = &domain->list; - else - head->r.eof = 1; - tomoyo_io_printf(head, "# select %s\n", data); - if (domain && domain->is_deleted) - tomoyo_io_printf(head, "# This is a deleted domain.\n"); - return true; -} - -/** - * tomoyo_same_task_acl - Check for duplicated "struct tomoyo_task_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * - * Returns true if @a == @b, false otherwise. - */ -static bool tomoyo_same_task_acl(const struct tomoyo_acl_info *a, - const struct tomoyo_acl_info *b) -{ - const struct tomoyo_task_acl *p1 = container_of(a, typeof(*p1), head); - const struct tomoyo_task_acl *p2 = container_of(b, typeof(*p2), head); - return p1->domainname == p2->domainname; -} - -/** - * tomoyo_write_task - Update task related list. - * - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_write_task(struct tomoyo_acl_param *param) -{ - int error = -EINVAL; - if (tomoyo_str_starts(¶m->data, "manual_domain_transition ")) { - struct tomoyo_task_acl e = { - .head.type = TOMOYO_TYPE_MANUAL_TASK_ACL, - .domainname = tomoyo_get_domainname(param), - }; - if (e.domainname) - error = tomoyo_update_domain(&e.head, sizeof(e), param, - tomoyo_same_task_acl, - NULL); - tomoyo_put_name(e.domainname); - } - return error; -} - -/** - * tomoyo_delete_domain - Delete a domain. - * - * @domainname: The name of domain. - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_delete_domain(char *domainname) -{ - struct tomoyo_domain_info *domain; - struct tomoyo_path_info name; - - name.name = domainname; - tomoyo_fill_path_info(&name); - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - return -EINTR; - /* Is there an active domain? */ - list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { - /* Never delete tomoyo_kernel_domain */ - if (domain == &tomoyo_kernel_domain) - continue; - if (domain->is_deleted || - tomoyo_pathcmp(domain->domainname, &name)) - continue; - domain->is_deleted = true; - break; - } - mutex_unlock(&tomoyo_policy_lock); - return 0; -} - -/** - * tomoyo_write_domain2 - Write domain policy. - * - * @ns: Pointer to "struct tomoyo_policy_namespace". - * @list: Pointer to "struct list_head". - * @data: Policy to be interpreted. - * @is_delete: True if it is a delete request. - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_write_domain2(struct tomoyo_policy_namespace *ns, - struct list_head *list, char *data, - const bool is_delete) -{ - struct tomoyo_acl_param param = { - .ns = ns, - .list = list, - .data = data, - .is_delete = is_delete, - }; - static const struct { - const char *keyword; - int (*write) (struct tomoyo_acl_param *); - } tomoyo_callback[5] = { - { "file ", tomoyo_write_file }, - { "network inet ", tomoyo_write_inet_network }, - { "network unix ", tomoyo_write_unix_network }, - { "misc ", tomoyo_write_misc }, - { "task ", tomoyo_write_task }, - }; - u8 i; - - for (i = 0; i < ARRAY_SIZE(tomoyo_callback); i++) { - if (!tomoyo_str_starts(¶m.data, - tomoyo_callback[i].keyword)) - continue; - return tomoyo_callback[i].write(¶m); - } - return -EINVAL; -} - -/* String table for domain flags. */ -const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS] = { - [TOMOYO_DIF_QUOTA_WARNED] = "quota_exceeded\n", - [TOMOYO_DIF_TRANSITION_FAILED] = "transition_failed\n", -}; - -/** - * tomoyo_write_domain - 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(struct tomoyo_io_buffer *head) -{ - char *data = head->write_buf; - struct tomoyo_policy_namespace *ns; - struct tomoyo_domain_info *domain = head->w.domain; - const bool is_delete = head->w.is_delete; - bool is_select = !is_delete && tomoyo_str_starts(&data, "select "); - unsigned int profile; - if (*data == '<') { - int ret = 0; - domain = NULL; - if (is_delete) - ret = tomoyo_delete_domain(data); - else if (is_select) - domain = tomoyo_find_domain(data); - else - domain = tomoyo_assign_domain(data, false); - head->w.domain = domain; - return ret; - } - if (!domain) - return -EINVAL; - ns = domain->ns; - if (sscanf(data, "use_profile %u", &profile) == 1 - && profile < TOMOYO_MAX_PROFILES) { - if (!tomoyo_policy_loaded || ns->profile_ptr[profile]) - domain->profile = (u8) profile; - return 0; - } - if (sscanf(data, "use_group %u\n", &profile) == 1 - && profile < TOMOYO_MAX_ACL_GROUPS) { - if (!is_delete) - domain->group = (u8) profile; - return 0; - } - for (profile = 0; profile < TOMOYO_MAX_DOMAIN_INFO_FLAGS; profile++) { - const char *cp = tomoyo_dif[profile]; - if (strncmp(data, cp, strlen(cp) - 1)) - continue; - domain->flags[profile] = !is_delete; - return 0; - } - return tomoyo_write_domain2(ns, &domain->acl_info_list, data, - is_delete); -} - -/** - * tomoyo_print_condition - Print condition part. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @cond: Pointer to "struct tomoyo_condition". - * - * Returns true on success, false otherwise. - */ -static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, - const struct tomoyo_condition *cond) -{ - switch (head->r.cond_step) { - case 0: - head->r.cond_index = 0; - head->r.cond_step++; - if (cond->transit) { - tomoyo_set_space(head); - tomoyo_set_string(head, cond->transit->name); - } - /* fall through */ - case 1: - { - const u16 condc = cond->condc; - const struct tomoyo_condition_element *condp = - (typeof(condp)) (cond + 1); - const struct tomoyo_number_union *numbers_p = - (typeof(numbers_p)) (condp + condc); - const struct tomoyo_name_union *names_p = - (typeof(names_p)) - (numbers_p + cond->numbers_count); - const struct tomoyo_argv *argv = - (typeof(argv)) (names_p + cond->names_count); - const struct tomoyo_envp *envp = - (typeof(envp)) (argv + cond->argc); - u16 skip; - for (skip = 0; skip < head->r.cond_index; skip++) { - const u8 left = condp->left; - const u8 right = condp->right; - condp++; - switch (left) { - case TOMOYO_ARGV_ENTRY: - argv++; - continue; - case TOMOYO_ENVP_ENTRY: - envp++; - continue; - case TOMOYO_NUMBER_UNION: - numbers_p++; - break; - } - switch (right) { - case TOMOYO_NAME_UNION: - names_p++; - break; - case TOMOYO_NUMBER_UNION: - numbers_p++; - break; - } - } - while (head->r.cond_index < condc) { - const u8 match = condp->equals; - const u8 left = condp->left; - const u8 right = condp->right; - if (!tomoyo_flush(head)) - return false; - condp++; - head->r.cond_index++; - tomoyo_set_space(head); - switch (left) { - case TOMOYO_ARGV_ENTRY: - tomoyo_io_printf(head, - "exec.argv[%lu]%s=\"", - argv->index, argv-> - is_not ? "!" : ""); - tomoyo_set_string(head, - argv->value->name); - tomoyo_set_string(head, "\""); - argv++; - continue; - case TOMOYO_ENVP_ENTRY: - tomoyo_set_string(head, - "exec.envp[\""); - tomoyo_set_string(head, - envp->name->name); - tomoyo_io_printf(head, "\"]%s=", envp-> - is_not ? "!" : ""); - if (envp->value) { - tomoyo_set_string(head, "\""); - tomoyo_set_string(head, envp-> - value->name); - tomoyo_set_string(head, "\""); - } else { - tomoyo_set_string(head, - "NULL"); - } - envp++; - continue; - case TOMOYO_NUMBER_UNION: - tomoyo_print_number_union_nospace - (head, numbers_p++); - break; - default: - tomoyo_set_string(head, - tomoyo_condition_keyword[left]); - break; - } - tomoyo_set_string(head, match ? "=" : "!="); - switch (right) { - case TOMOYO_NAME_UNION: - tomoyo_print_name_union_quoted - (head, names_p++); - break; - case TOMOYO_NUMBER_UNION: - tomoyo_print_number_union_nospace - (head, numbers_p++); - break; - default: - tomoyo_set_string(head, - tomoyo_condition_keyword[right]); - break; - } - } - } - head->r.cond_step++; - /* fall through */ - case 2: - if (!tomoyo_flush(head)) - break; - head->r.cond_step++; - /* fall through */ - case 3: - if (cond->grant_log != TOMOYO_GRANTLOG_AUTO) - tomoyo_io_printf(head, " grant_log=%s", - tomoyo_yesno(cond->grant_log == - TOMOYO_GRANTLOG_YES)); - tomoyo_set_lf(head); - return true; - } - return false; -} - -/** - * tomoyo_set_group - Print "acl_group " header keyword and category name. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @category: Category name. - * - * Returns nothing. - */ -static void tomoyo_set_group(struct tomoyo_io_buffer *head, - const char *category) -{ - if (head->type == TOMOYO_EXCEPTIONPOLICY) { - tomoyo_print_namespace(head); - tomoyo_io_printf(head, "acl_group %u ", - head->r.acl_group_index); - } - tomoyo_set_string(head, category); -} - -/** - * tomoyo_print_entry - Print an ACL entry. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @acl: Pointer to an ACL entry. - * - * Returns true on success, false otherwise. - */ -static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, - struct tomoyo_acl_info *acl) -{ - const u8 acl_type = acl->type; - bool first = true; - u8 bit; - - if (head->r.print_cond_part) - goto print_cond_part; - if (acl->is_deleted) - return true; - if (!tomoyo_flush(head)) - return false; - else if (acl_type == TOMOYO_TYPE_PATH_ACL) { - struct tomoyo_path_acl *ptr = - container_of(acl, typeof(*ptr), head); - const u16 perm = ptr->perm; - for (bit = 0; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { - if (!(perm & (1 << bit))) - continue; - if (head->r.print_transition_related_only && - bit != TOMOYO_TYPE_EXECUTE) - continue; - if (first) { - tomoyo_set_group(head, "file "); - first = false; - } else { - tomoyo_set_slash(head); - } - tomoyo_set_string(head, tomoyo_path_keyword[bit]); - } - if (first) - return true; - tomoyo_print_name_union(head, &ptr->name); - } else if (acl_type == TOMOYO_TYPE_MANUAL_TASK_ACL) { - struct tomoyo_task_acl *ptr = - container_of(acl, typeof(*ptr), head); - tomoyo_set_group(head, "task "); - tomoyo_set_string(head, "manual_domain_transition "); - tomoyo_set_string(head, ptr->domainname->name); - } else if (head->r.print_transition_related_only) { - return true; - } else if (acl_type == TOMOYO_TYPE_PATH2_ACL) { - struct tomoyo_path2_acl *ptr = - container_of(acl, typeof(*ptr), head); - const u8 perm = ptr->perm; - for (bit = 0; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) { - if (!(perm & (1 << bit))) - continue; - if (first) { - tomoyo_set_group(head, "file "); - first = false; - } else { - tomoyo_set_slash(head); - } - tomoyo_set_string(head, tomoyo_mac_keywords - [tomoyo_pp2mac[bit]]); - } - if (first) - return true; - tomoyo_print_name_union(head, &ptr->name1); - tomoyo_print_name_union(head, &ptr->name2); - } else if (acl_type == TOMOYO_TYPE_PATH_NUMBER_ACL) { - struct tomoyo_path_number_acl *ptr = - container_of(acl, typeof(*ptr), head); - const u8 perm = ptr->perm; - for (bit = 0; bit < TOMOYO_MAX_PATH_NUMBER_OPERATION; bit++) { - if (!(perm & (1 << bit))) - continue; - if (first) { - tomoyo_set_group(head, "file "); - first = false; - } else { - tomoyo_set_slash(head); - } - tomoyo_set_string(head, tomoyo_mac_keywords - [tomoyo_pn2mac[bit]]); - } - if (first) - return true; - tomoyo_print_name_union(head, &ptr->name); - tomoyo_print_number_union(head, &ptr->number); - } else if (acl_type == TOMOYO_TYPE_MKDEV_ACL) { - struct tomoyo_mkdev_acl *ptr = - container_of(acl, typeof(*ptr), head); - const u8 perm = ptr->perm; - for (bit = 0; bit < TOMOYO_MAX_MKDEV_OPERATION; bit++) { - if (!(perm & (1 << bit))) - continue; - if (first) { - tomoyo_set_group(head, "file "); - first = false; - } else { - tomoyo_set_slash(head); - } - tomoyo_set_string(head, tomoyo_mac_keywords - [tomoyo_pnnn2mac[bit]]); - } - if (first) - return true; - tomoyo_print_name_union(head, &ptr->name); - tomoyo_print_number_union(head, &ptr->mode); - tomoyo_print_number_union(head, &ptr->major); - tomoyo_print_number_union(head, &ptr->minor); - } else if (acl_type == TOMOYO_TYPE_INET_ACL) { - struct tomoyo_inet_acl *ptr = - container_of(acl, typeof(*ptr), head); - const u8 perm = ptr->perm; - - for (bit = 0; bit < TOMOYO_MAX_NETWORK_OPERATION; bit++) { - if (!(perm & (1 << bit))) - continue; - if (first) { - tomoyo_set_group(head, "network inet "); - tomoyo_set_string(head, tomoyo_proto_keyword - [ptr->protocol]); - tomoyo_set_space(head); - first = false; - } else { - tomoyo_set_slash(head); - } - tomoyo_set_string(head, tomoyo_socket_keyword[bit]); - } - if (first) - return true; - tomoyo_set_space(head); - if (ptr->address.group) { - tomoyo_set_string(head, "@"); - tomoyo_set_string(head, ptr->address.group->group_name - ->name); - } else { - char buf[128]; - tomoyo_print_ip(buf, sizeof(buf), &ptr->address); - tomoyo_io_printf(head, "%s", buf); - } - tomoyo_print_number_union(head, &ptr->port); - } else if (acl_type == TOMOYO_TYPE_UNIX_ACL) { - struct tomoyo_unix_acl *ptr = - container_of(acl, typeof(*ptr), head); - const u8 perm = ptr->perm; - - for (bit = 0; bit < TOMOYO_MAX_NETWORK_OPERATION; bit++) { - if (!(perm & (1 << bit))) - continue; - if (first) { - tomoyo_set_group(head, "network unix "); - tomoyo_set_string(head, tomoyo_proto_keyword - [ptr->protocol]); - tomoyo_set_space(head); - first = false; - } else { - tomoyo_set_slash(head); - } - tomoyo_set_string(head, tomoyo_socket_keyword[bit]); - } - if (first) - return true; - tomoyo_print_name_union(head, &ptr->name); - } else if (acl_type == TOMOYO_TYPE_MOUNT_ACL) { - struct tomoyo_mount_acl *ptr = - container_of(acl, typeof(*ptr), head); - tomoyo_set_group(head, "file mount"); - tomoyo_print_name_union(head, &ptr->dev_name); - tomoyo_print_name_union(head, &ptr->dir_name); - tomoyo_print_name_union(head, &ptr->fs_type); - tomoyo_print_number_union(head, &ptr->flags); - } else if (acl_type == TOMOYO_TYPE_ENV_ACL) { - struct tomoyo_env_acl *ptr = - container_of(acl, typeof(*ptr), head); - - tomoyo_set_group(head, "misc env "); - tomoyo_set_string(head, ptr->env->name); - } - if (acl->cond) { - head->r.print_cond_part = true; - head->r.cond_step = 0; - if (!tomoyo_flush(head)) - return false; -print_cond_part: - if (!tomoyo_print_condition(head, acl->cond)) - return false; - head->r.print_cond_part = false; - } else { - tomoyo_set_lf(head); - } - return true; -} - -/** - * tomoyo_read_domain2 - Read domain policy. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @list: Pointer to "struct list_head". - * - * Caller holds tomoyo_read_lock(). - * - * Returns true on success, false otherwise. - */ -static bool tomoyo_read_domain2(struct tomoyo_io_buffer *head, - struct list_head *list) -{ - list_for_each_cookie(head->r.acl, list) { - struct tomoyo_acl_info *ptr = - list_entry(head->r.acl, typeof(*ptr), list); - if (!tomoyo_print_entry(head, ptr)) - return false; - } - head->r.acl = NULL; - return true; -} - -/** - * tomoyo_read_domain - Read domain policy. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Caller holds tomoyo_read_lock(). - */ -static void tomoyo_read_domain(struct tomoyo_io_buffer *head) -{ - if (head->r.eof) - return; - list_for_each_cookie(head->r.domain, &tomoyo_domain_list) { - struct tomoyo_domain_info *domain = - list_entry(head->r.domain, typeof(*domain), list); - switch (head->r.step) { - u8 i; - case 0: - if (domain->is_deleted && - !head->r.print_this_domain_only) - continue; - /* Print domainname and flags. */ - tomoyo_set_string(head, domain->domainname->name); - tomoyo_set_lf(head); - tomoyo_io_printf(head, "use_profile %u\n", - domain->profile); - tomoyo_io_printf(head, "use_group %u\n", - domain->group); - for (i = 0; i < TOMOYO_MAX_DOMAIN_INFO_FLAGS; i++) - if (domain->flags[i]) - tomoyo_set_string(head, tomoyo_dif[i]); - head->r.step++; - tomoyo_set_lf(head); - /* fall through */ - case 1: - if (!tomoyo_read_domain2(head, &domain->acl_info_list)) - return; - head->r.step++; - if (!tomoyo_set_lf(head)) - return; - /* fall through */ - case 2: - head->r.step = 0; - if (head->r.print_this_domain_only) - goto done; - } - } - done: - head->r.eof = true; -} - -/** - * tomoyo_write_pid: Specify PID to obtain domainname. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns 0. - */ -static int tomoyo_write_pid(struct tomoyo_io_buffer *head) -{ - head->r.eof = false; - return 0; -} - -/** - * tomoyo_read_pid - Get domainname of the specified PID. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns the domainname which the specified PID is in on success, - * empty string otherwise. - * The PID is specified by tomoyo_write_pid() so that the user can obtain - * using read()/write() interface rather than sysctl() interface. - */ -static void tomoyo_read_pid(struct tomoyo_io_buffer *head) -{ - char *buf = head->write_buf; - bool global_pid = false; - unsigned int pid; - struct task_struct *p; - struct tomoyo_domain_info *domain = NULL; - - /* Accessing write_buf is safe because head->io_sem is held. */ - if (!buf) { - head->r.eof = true; - return; /* Do nothing if open(O_RDONLY). */ - } - if (head->r.w_pos || head->r.eof) - return; - head->r.eof = true; - if (tomoyo_str_starts(&buf, "global-pid ")) - global_pid = true; - pid = (unsigned int) simple_strtoul(buf, NULL, 10); - rcu_read_lock(); - if (global_pid) - p = find_task_by_pid_ns(pid, &init_pid_ns); - else - p = find_task_by_vpid(pid); - if (p) - domain = tomoyo_real_domain(p); - rcu_read_unlock(); - if (!domain) - return; - tomoyo_io_printf(head, "%u %u ", pid, domain->profile); - tomoyo_set_string(head, domain->domainname->name); -} - -/* String table for domain transition control keywords. */ -static const char *tomoyo_transition_type[TOMOYO_MAX_TRANSITION_TYPE] = { - [TOMOYO_TRANSITION_CONTROL_NO_RESET] = "no_reset_domain ", - [TOMOYO_TRANSITION_CONTROL_RESET] = "reset_domain ", - [TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ", - [TOMOYO_TRANSITION_CONTROL_INITIALIZE] = "initialize_domain ", - [TOMOYO_TRANSITION_CONTROL_NO_KEEP] = "no_keep_domain ", - [TOMOYO_TRANSITION_CONTROL_KEEP] = "keep_domain ", -}; - -/* String table for grouping keywords. */ -static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = { - [TOMOYO_PATH_GROUP] = "path_group ", - [TOMOYO_NUMBER_GROUP] = "number_group ", - [TOMOYO_ADDRESS_GROUP] = "address_group ", -}; - -/** - * tomoyo_write_exception - Write exception policy. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_write_exception(struct tomoyo_io_buffer *head) -{ - const bool is_delete = head->w.is_delete; - struct tomoyo_acl_param param = { - .ns = head->w.ns, - .is_delete = is_delete, - .data = head->write_buf, - }; - u8 i; - if (tomoyo_str_starts(¶m.data, "aggregator ")) - return tomoyo_write_aggregator(¶m); - for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) - if (tomoyo_str_starts(¶m.data, tomoyo_transition_type[i])) - return tomoyo_write_transition_control(¶m, i); - for (i = 0; i < TOMOYO_MAX_GROUP; i++) - if (tomoyo_str_starts(¶m.data, tomoyo_group_name[i])) - return tomoyo_write_group(¶m, i); - if (tomoyo_str_starts(¶m.data, "acl_group ")) { - unsigned int group; - char *data; - group = simple_strtoul(param.data, &data, 10); - if (group < TOMOYO_MAX_ACL_GROUPS && *data++ == ' ') - return tomoyo_write_domain2 - (head->w.ns, &head->w.ns->acl_group[group], - data, is_delete); - } - return -EINVAL; -} - -/** - * tomoyo_read_group - Read "struct tomoyo_path_group"/"struct tomoyo_number_group"/"struct tomoyo_address_group" list. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @idx: Index number. - * - * Returns true on success, false otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx) -{ - struct tomoyo_policy_namespace *ns = - container_of(head->r.ns, typeof(*ns), namespace_list); - struct list_head *list = &ns->group_list[idx]; - list_for_each_cookie(head->r.group, list) { - struct tomoyo_group *group = - list_entry(head->r.group, typeof(*group), head.list); - list_for_each_cookie(head->r.acl, &group->member_list) { - struct tomoyo_acl_head *ptr = - list_entry(head->r.acl, typeof(*ptr), list); - if (ptr->is_deleted) - continue; - if (!tomoyo_flush(head)) - return false; - tomoyo_print_namespace(head); - tomoyo_set_string(head, tomoyo_group_name[idx]); - tomoyo_set_string(head, group->group_name->name); - if (idx == TOMOYO_PATH_GROUP) { - tomoyo_set_space(head); - tomoyo_set_string(head, container_of - (ptr, struct tomoyo_path_group, - head)->member_name->name); - } else if (idx == TOMOYO_NUMBER_GROUP) { - tomoyo_print_number_union(head, &container_of - (ptr, - struct tomoyo_number_group, - head)->number); - } else if (idx == TOMOYO_ADDRESS_GROUP) { - char buffer[128]; - - struct tomoyo_address_group *member = - container_of(ptr, typeof(*member), - head); - tomoyo_print_ip(buffer, sizeof(buffer), - &member->address); - tomoyo_io_printf(head, " %s", buffer); - } - tomoyo_set_lf(head); - } - head->r.acl = NULL; - } - head->r.group = NULL; - return true; -} - -/** - * tomoyo_read_policy - Read "struct tomoyo_..._entry" list. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @idx: Index number. - * - * Returns true on success, false otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) -{ - struct tomoyo_policy_namespace *ns = - container_of(head->r.ns, typeof(*ns), namespace_list); - struct list_head *list = &ns->policy_list[idx]; - list_for_each_cookie(head->r.acl, list) { - struct tomoyo_acl_head *acl = - container_of(head->r.acl, typeof(*acl), list); - if (acl->is_deleted) - continue; - if (!tomoyo_flush(head)) - return false; - switch (idx) { - case TOMOYO_ID_TRANSITION_CONTROL: - { - struct tomoyo_transition_control *ptr = - container_of(acl, typeof(*ptr), head); - tomoyo_print_namespace(head); - tomoyo_set_string(head, tomoyo_transition_type - [ptr->type]); - tomoyo_set_string(head, ptr->program ? - ptr->program->name : "any"); - tomoyo_set_string(head, " from "); - tomoyo_set_string(head, ptr->domainname ? - ptr->domainname->name : - "any"); - } - break; - case TOMOYO_ID_AGGREGATOR: - { - struct tomoyo_aggregator *ptr = - container_of(acl, typeof(*ptr), head); - tomoyo_print_namespace(head); - tomoyo_set_string(head, "aggregator "); - tomoyo_set_string(head, - ptr->original_name->name); - tomoyo_set_space(head); - tomoyo_set_string(head, - ptr->aggregated_name->name); - } - break; - default: - continue; - } - tomoyo_set_lf(head); - } - head->r.acl = NULL; - return true; -} - -/** - * tomoyo_read_exception - Read exception policy. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Caller holds tomoyo_read_lock(). - */ -static void tomoyo_read_exception(struct tomoyo_io_buffer *head) -{ - struct tomoyo_policy_namespace *ns = - container_of(head->r.ns, typeof(*ns), namespace_list); - if (head->r.eof) - return; - while (head->r.step < TOMOYO_MAX_POLICY && - tomoyo_read_policy(head, head->r.step)) - head->r.step++; - if (head->r.step < TOMOYO_MAX_POLICY) - return; - while (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP && - tomoyo_read_group(head, head->r.step - TOMOYO_MAX_POLICY)) - head->r.step++; - if (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP) - return; - while (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP - + TOMOYO_MAX_ACL_GROUPS) { - head->r.acl_group_index = head->r.step - TOMOYO_MAX_POLICY - - TOMOYO_MAX_GROUP; - if (!tomoyo_read_domain2(head, &ns->acl_group - [head->r.acl_group_index])) - return; - head->r.step++; - } - head->r.eof = true; -} - -/* Wait queue for kernel -> userspace notification. */ -static DECLARE_WAIT_QUEUE_HEAD(tomoyo_query_wait); -/* Wait queue for userspace -> kernel notification. */ -static DECLARE_WAIT_QUEUE_HEAD(tomoyo_answer_wait); - -/* Structure for query. */ -struct tomoyo_query { - struct list_head list; - struct tomoyo_domain_info *domain; - char *query; - size_t query_len; - unsigned int serial; - u8 timer; - u8 answer; - u8 retry; -}; - -/* The list for "struct tomoyo_query". */ -static LIST_HEAD(tomoyo_query_list); - -/* Lock for manipulating tomoyo_query_list. */ -static DEFINE_SPINLOCK(tomoyo_query_list_lock); - -/* - * Number of "struct file" referring /sys/kernel/security/tomoyo/query - * interface. - */ -static atomic_t tomoyo_query_observers = ATOMIC_INIT(0); - -/** - * tomoyo_truncate - Truncate a line. - * - * @str: String to truncate. - * - * Returns length of truncated @str. - */ -static int tomoyo_truncate(char *str) -{ - char *start = str; - while (*(unsigned char *) str > (unsigned char) ' ') - str++; - *str = '\0'; - return strlen(start) + 1; -} - -/** - * tomoyo_add_entry - Add an ACL to current thread's domain. Used by learning mode. - * - * @domain: Pointer to "struct tomoyo_domain_info". - * @header: Lines containing ACL. - * - * Returns nothing. - */ -static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header) -{ - char *buffer; - char *realpath = NULL; - char *argv0 = NULL; - char *symlink = NULL; - char *cp = strchr(header, '\n'); - int len; - if (!cp) - return; - cp = strchr(cp + 1, '\n'); - if (!cp) - return; - *cp++ = '\0'; - len = strlen(cp) + 1; - /* strstr() will return NULL if ordering is wrong. */ - if (*cp == 'f') { - argv0 = strstr(header, " argv[]={ \""); - if (argv0) { - argv0 += 10; - len += tomoyo_truncate(argv0) + 14; - } - realpath = strstr(header, " exec={ realpath=\""); - if (realpath) { - realpath += 8; - len += tomoyo_truncate(realpath) + 6; - } - symlink = strstr(header, " symlink.target=\""); - if (symlink) - len += tomoyo_truncate(symlink + 1) + 1; - } - buffer = kmalloc(len, GFP_NOFS); - if (!buffer) - return; - snprintf(buffer, len - 1, "%s", cp); - if (realpath) - tomoyo_addprintf(buffer, len, " exec.%s", realpath); - if (argv0) - tomoyo_addprintf(buffer, len, " exec.argv[0]=%s", argv0); - if (symlink) - tomoyo_addprintf(buffer, len, "%s", symlink); - tomoyo_normalize_line(buffer); - if (!tomoyo_write_domain2(domain->ns, &domain->acl_info_list, buffer, - false)) - tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES); - kfree(buffer); -} - -/** - * 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; - int len; - static unsigned int tomoyo_serial; - struct tomoyo_query entry = { }; - bool quota_exceeded = false; - va_start(args, fmt); - len = vsnprintf((char *) &len, 1, fmt, args) + 1; - va_end(args); - /* Write /sys/kernel/security/tomoyo/audit. */ - va_start(args, fmt); - tomoyo_write_log2(r, len, fmt, args); - va_end(args); - /* Nothing more to do if granted. */ - if (r->granted) - return 0; - if (r->mode) - tomoyo_update_stat(r->mode); - switch (r->mode) { - case TOMOYO_CONFIG_ENFORCING: - error = -EPERM; - if (atomic_read(&tomoyo_query_observers)) - break; - goto out; - case TOMOYO_CONFIG_LEARNING: - error = 0; - /* Check max_learning_entry parameter. */ - if (tomoyo_domain_quota_is_ok(r)) - break; - /* fall through */ - default: - return 0; - } - /* Get message. */ - va_start(args, fmt); - entry.query = tomoyo_init_log(r, len, fmt, args); - va_end(args); - if (!entry.query) - goto out; - entry.query_len = strlen(entry.query) + 1; - if (!error) { - tomoyo_add_entry(r->domain, entry.query); - goto out; - } - len = tomoyo_round2(entry.query_len); - entry.domain = r->domain; - spin_lock(&tomoyo_query_list_lock); - if (tomoyo_memory_quota[TOMOYO_MEMORY_QUERY] && - tomoyo_memory_used[TOMOYO_MEMORY_QUERY] + len - >= tomoyo_memory_quota[TOMOYO_MEMORY_QUERY]) { - quota_exceeded = true; - } else { - entry.serial = tomoyo_serial++; - entry.retry = r->retry; - tomoyo_memory_used[TOMOYO_MEMORY_QUERY] += len; - list_add_tail(&entry.list, &tomoyo_query_list); - } - spin_unlock(&tomoyo_query_list_lock); - if (quota_exceeded) - goto out; - /* Give 10 seconds for supervisor's opinion. */ - while (entry.timer < 10) { - wake_up_all(&tomoyo_query_wait); - if (wait_event_interruptible_timeout - (tomoyo_answer_wait, entry.answer || - !atomic_read(&tomoyo_query_observers), HZ)) - break; - else - entry.timer++; - } - spin_lock(&tomoyo_query_list_lock); - list_del(&entry.list); - tomoyo_memory_used[TOMOYO_MEMORY_QUERY] -= len; - spin_unlock(&tomoyo_query_list_lock); - switch (entry.answer) { - case 3: /* Asked to retry by administrator. */ - error = TOMOYO_RETRY_REQUEST; - r->retry++; - break; - case 1: - /* Granted by administrator. */ - error = 0; - break; - default: - /* Timed out or rejected by administrator. */ - break; - } -out: - kfree(entry.query); - return error; -} - -/** - * tomoyo_find_domain_by_qid - Get domain by query id. - * - * @serial: Query ID assigned by tomoyo_supervisor(). - * - * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise. - */ -static struct tomoyo_domain_info *tomoyo_find_domain_by_qid -(unsigned int serial) -{ - struct tomoyo_query *ptr; - struct tomoyo_domain_info *domain = NULL; - spin_lock(&tomoyo_query_list_lock); - list_for_each_entry(ptr, &tomoyo_query_list, list) { - if (ptr->serial != serial) - continue; - domain = ptr->domain; - break; - } - spin_unlock(&tomoyo_query_list_lock); - return domain; -} - -/** - * 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 unsigned int tomoyo_poll_query(struct file *file, poll_table *wait) -{ - if (!list_empty(&tomoyo_query_list)) - return POLLIN | POLLRDNORM; - poll_wait(file, &tomoyo_query_wait, wait); - if (!list_empty(&tomoyo_query_list)) - return POLLIN | POLLRDNORM; - return 0; -} - -/** - * tomoyo_read_query - Read access requests which violated policy in enforcing mode. - * - * @head: Pointer to "struct tomoyo_io_buffer". - */ -static void tomoyo_read_query(struct tomoyo_io_buffer *head) -{ - struct list_head *tmp; - unsigned int pos = 0; - size_t len = 0; - char *buf; - if (head->r.w_pos) - return; - if (head->read_buf) { - kfree(head->read_buf); - head->read_buf = NULL; - } - spin_lock(&tomoyo_query_list_lock); - list_for_each(tmp, &tomoyo_query_list) { - struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); - if (pos++ != head->r.query_index) - continue; - len = ptr->query_len; - break; - } - spin_unlock(&tomoyo_query_list_lock); - if (!len) { - head->r.query_index = 0; - return; - } - buf = kzalloc(len + 32, GFP_NOFS); - if (!buf) - return; - pos = 0; - spin_lock(&tomoyo_query_list_lock); - list_for_each(tmp, &tomoyo_query_list) { - struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); - if (pos++ != head->r.query_index) - continue; - /* - * Some query can be skipped because tomoyo_query_list - * can change, but I don't care. - */ - if (len == ptr->query_len) - snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial, - ptr->retry, ptr->query); - break; - } - spin_unlock(&tomoyo_query_list_lock); - if (buf[0]) { - head->read_buf = buf; - head->r.w[head->r.w_pos++] = buf; - head->r.query_index++; - } else { - kfree(buf); - } -} - -/** - * 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 *ptr = list_entry(tmp, typeof(*ptr), 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 *ptr = list_entry(tmp, typeof(*ptr), list); - if (ptr->serial != serial) - continue; - ptr->answer = answer; - /* Remove from tomoyo_query_list. */ - if (ptr->answer) - list_del_init(&ptr->list); - break; - } - spin_unlock(&tomoyo_query_list_lock); - return 0; -} - -/** - * tomoyo_read_version: Get version. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns version information. - */ -static void tomoyo_read_version(struct tomoyo_io_buffer *head) -{ - if (!head->r.eof) { - tomoyo_io_printf(head, "2.5.0"); - head->r.eof = true; - } -} - -/* String table for /sys/kernel/security/tomoyo/stat interface. */ -static const char * const tomoyo_policy_headers[TOMOYO_MAX_POLICY_STAT] = { - [TOMOYO_STAT_POLICY_UPDATES] = "update:", - [TOMOYO_STAT_POLICY_LEARNING] = "violation in learning mode:", - [TOMOYO_STAT_POLICY_PERMISSIVE] = "violation in permissive mode:", - [TOMOYO_STAT_POLICY_ENFORCING] = "violation in enforcing mode:", -}; - -/* String table for /sys/kernel/security/tomoyo/stat interface. */ -static const char * const tomoyo_memory_headers[TOMOYO_MAX_MEMORY_STAT] = { - [TOMOYO_MEMORY_POLICY] = "policy:", - [TOMOYO_MEMORY_AUDIT] = "audit log:", - [TOMOYO_MEMORY_QUERY] = "query message:", -}; - -/* Timestamp counter for last updated. */ -static unsigned int tomoyo_stat_updated[TOMOYO_MAX_POLICY_STAT]; -/* Counter for number of updates. */ -static unsigned int tomoyo_stat_modified[TOMOYO_MAX_POLICY_STAT]; - -/** - * tomoyo_update_stat - Update statistic counters. - * - * @index: Index for policy type. - * - * Returns nothing. - */ -void tomoyo_update_stat(const u8 index) -{ - struct timeval tv; - do_gettimeofday(&tv); - /* - * I don't use atomic operations because race condition is not fatal. - */ - tomoyo_stat_updated[index]++; - tomoyo_stat_modified[index] = tv.tv_sec; -} - -/** - * tomoyo_read_stat - Read statistic data. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns nothing. - */ -static void tomoyo_read_stat(struct tomoyo_io_buffer *head) -{ - u8 i; - unsigned int total = 0; - if (head->r.eof) - return; - for (i = 0; i < TOMOYO_MAX_POLICY_STAT; i++) { - tomoyo_io_printf(head, "Policy %-30s %10u", - tomoyo_policy_headers[i], - tomoyo_stat_updated[i]); - if (tomoyo_stat_modified[i]) { - struct tomoyo_time stamp; - tomoyo_convert_time(tomoyo_stat_modified[i], &stamp); - tomoyo_io_printf(head, " (Last: %04u/%02u/%02u " - "%02u:%02u:%02u)", - stamp.year, stamp.month, stamp.day, - stamp.hour, stamp.min, stamp.sec); - } - tomoyo_set_lf(head); - } - for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++) { - unsigned int used = tomoyo_memory_used[i]; - total += used; - tomoyo_io_printf(head, "Memory used by %-22s %10u", - tomoyo_memory_headers[i], used); - used = tomoyo_memory_quota[i]; - if (used) - tomoyo_io_printf(head, " (Quota: %10u)", used); - tomoyo_set_lf(head); - } - tomoyo_io_printf(head, "Total memory used: %10u\n", - total); - head->r.eof = true; -} - -/** - * tomoyo_write_stat - Set memory quota. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns 0. - */ -static int tomoyo_write_stat(struct tomoyo_io_buffer *head) -{ - char *data = head->write_buf; - u8 i; - if (tomoyo_str_starts(&data, "Memory used by ")) - for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++) - if (tomoyo_str_starts(&data, tomoyo_memory_headers[i])) - sscanf(data, "%u", &tomoyo_memory_quota[i]); - return 0; -} - -/** - * tomoyo_open_control - open() for /sys/kernel/security/tomoyo/ interface. - * - * @type: Type of interface. - * @file: Pointer to "struct file". - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_open_control(const u8 type, struct file *file) -{ - struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_NOFS); - - if (!head) - return -ENOMEM; - mutex_init(&head->io_sem); - head->type = type; - switch (type) { - case TOMOYO_DOMAINPOLICY: - /* /sys/kernel/security/tomoyo/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; - head->read = tomoyo_read_exception; - break; - case TOMOYO_AUDIT: - /* /sys/kernel/security/tomoyo/audit */ - head->poll = tomoyo_poll_log; - head->read = tomoyo_read_log; - break; - case TOMOYO_PROCESS_STATUS: - /* /sys/kernel/security/tomoyo/.process_status */ - head->write = tomoyo_write_pid; - head->read = tomoyo_read_pid; - break; - case TOMOYO_VERSION: - /* /sys/kernel/security/tomoyo/version */ - head->read = tomoyo_read_version; - head->readbuf_size = 128; - break; - case TOMOYO_STAT: - /* /sys/kernel/security/tomoyo/stat */ - head->write = tomoyo_write_stat; - head->read = tomoyo_read_stat; - head->readbuf_size = 1024; - break; - case TOMOYO_PROFILE: - /* /sys/kernel/security/tomoyo/profile */ - 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; - head->read = tomoyo_read_manager; - break; - } - if (!(file->f_mode & FMODE_READ)) { - /* - * No need to allocate read_buf since it is not opened - * for reading. - */ - head->read = NULL; - 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); - if (!head->read_buf) { - kfree(head); - return -ENOMEM; - } - } - if (!(file->f_mode & FMODE_WRITE)) { - /* - * No need to allocate write_buf since it is not opened - * for writing. - */ - head->write = NULL; - } else if (head->write) { - head->writebuf_size = 4096 * 2; - head->write_buf = kzalloc(head->writebuf_size, GFP_NOFS); - if (!head->write_buf) { - kfree(head->read_buf); - kfree(head); - return -ENOMEM; - } - } - /* - * 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. - */ - if (type == TOMOYO_QUERY) - atomic_inc(&tomoyo_query_observers); - file->private_data = head; - tomoyo_notify_gc(head, true); - return 0; -} - -/** - * tomoyo_poll_control - poll() for /sys/kernel/security/tomoyo/ interface. - * - * @file: Pointer to "struct file". - * @wait: Pointer to "poll_table". Maybe NULL. - * - * Returns POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM if ready to read/write, - * POLLOUT | POLLWRNORM otherwise. - */ -unsigned int tomoyo_poll_control(struct file *file, poll_table *wait) -{ - struct tomoyo_io_buffer *head = file->private_data; - if (head->poll) - return head->poll(file, wait) | POLLOUT | POLLWRNORM; - return POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM; -} - -/** - * tomoyo_set_namespace_cursor - Set namespace to read. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns nothing. - */ -static inline void tomoyo_set_namespace_cursor(struct tomoyo_io_buffer *head) -{ - struct list_head *ns; - if (head->type != TOMOYO_EXCEPTIONPOLICY && - head->type != TOMOYO_PROFILE) - return; - /* - * If this is the first read, or reading previous namespace finished - * and has more namespaces to read, update the namespace cursor. - */ - ns = head->r.ns; - if (!ns || (head->r.eof && ns->next != &tomoyo_namespace_list)) { - /* Clearing is OK because tomoyo_flush() returned true. */ - memset(&head->r, 0, sizeof(head->r)); - head->r.ns = ns ? ns->next : tomoyo_namespace_list.next; - } -} - -/** - * tomoyo_has_more_namespace - Check for unread namespaces. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns true if we have more entries to print, false otherwise. - */ -static inline bool tomoyo_has_more_namespace(struct tomoyo_io_buffer *head) -{ - return (head->type == TOMOYO_EXCEPTIONPOLICY || - head->type == TOMOYO_PROFILE) && head->r.eof && - head->r.ns->next != &tomoyo_namespace_list; -} - -/** - * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @buffer: Poiner to buffer to write to. - * @buffer_len: Size of @buffer. - * - * Returns bytes read on success, negative value otherwise. - */ -ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, - const int buffer_len) -{ - int len; - int idx; - - if (!head->read) - return -ENOSYS; - if (mutex_lock_interruptible(&head->io_sem)) - return -EINTR; - head->read_user_buf = buffer; - head->read_user_buf_avail = buffer_len; - idx = tomoyo_read_lock(); - if (tomoyo_flush(head)) - /* Call the policy handler. */ - do { - tomoyo_set_namespace_cursor(head); - head->read(head); - } while (tomoyo_flush(head) && - tomoyo_has_more_namespace(head)); - tomoyo_read_unlock(idx); - len = head->read_user_buf - buffer; - mutex_unlock(&head->io_sem); - return len; -} - -/** - * tomoyo_parse_policy - Parse a policy line. - * - * @head: Poiter to "struct tomoyo_io_buffer". - * @line: Line to parse. - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_parse_policy(struct tomoyo_io_buffer *head, char *line) -{ - /* Delete request? */ - head->w.is_delete = !strncmp(line, "delete ", 7); - if (head->w.is_delete) - memmove(line, line + 7, strlen(line + 7) + 1); - /* Selecting namespace to update. */ - if (head->type == TOMOYO_EXCEPTIONPOLICY || - head->type == TOMOYO_PROFILE) { - if (*line == '<') { - char *cp = strchr(line, ' '); - if (cp) { - *cp++ = '\0'; - head->w.ns = tomoyo_assign_namespace(line); - memmove(line, cp, strlen(cp) + 1); - } else - head->w.ns = NULL; - } else - head->w.ns = &tomoyo_kernel_namespace; - /* Don't allow updating if namespace is invalid. */ - if (!head->w.ns) - return -ENOENT; - } - /* Do the update. */ - return head->write(head); -} - -/** - * tomoyo_write_control - write() for /sys/kernel/security/tomoyo/ interface. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @buffer: Pointer to buffer to read from. - * @buffer_len: Size of @buffer. - * - * Returns @buffer_len on success, negative value otherwise. - */ -ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, - const char __user *buffer, const int buffer_len) -{ - int error = buffer_len; - size_t avail_len = buffer_len; - char *cp0 = head->write_buf; - int idx; - if (!head->write) - return -ENOSYS; - if (!access_ok(VERIFY_READ, buffer, buffer_len)) - return -EFAULT; - if (mutex_lock_interruptible(&head->io_sem)) - return -EINTR; - head->read_user_buf_avail = 0; - idx = tomoyo_read_lock(); - /* Read a line and dispatch it to the policy handler. */ - while (avail_len > 0) { - char c; - if (head->w.avail >= head->writebuf_size - 1) { - const int len = head->writebuf_size * 2; - char *cp = kzalloc(len, GFP_NOFS); - if (!cp) { - error = -ENOMEM; - break; - } - memmove(cp, cp0, head->w.avail); - kfree(cp0); - head->write_buf = cp; - cp0 = cp; - head->writebuf_size = len; - } - if (get_user(c, buffer)) { - error = -EFAULT; - break; - } - buffer++; - avail_len--; - cp0[head->w.avail++] = c; - if (c != '\n') - continue; - cp0[head->w.avail - 1] = '\0'; - head->w.avail = 0; - tomoyo_normalize_line(cp0); - if (!strcmp(cp0, "reset")) { - head->w.ns = &tomoyo_kernel_namespace; - head->w.domain = NULL; - memset(&head->r, 0, sizeof(head->r)); - continue; - } - /* Don't allow updating policies by non manager programs. */ - switch (head->type) { - case TOMOYO_PROCESS_STATUS: - /* This does not write anything. */ - break; - case TOMOYO_DOMAINPOLICY: - if (tomoyo_select_domain(head, cp0)) - continue; - /* fall through */ - case TOMOYO_EXCEPTIONPOLICY: - if (!strcmp(cp0, "select transition_only")) { - head->r.print_transition_related_only = true; - continue; - } - /* fall through */ - default: - if (!tomoyo_manager()) { - error = -EPERM; - goto out; - } - } - switch (tomoyo_parse_policy(head, cp0)) { - case -EPERM: - error = -EPERM; - goto out; - case 0: - switch (head->type) { - case TOMOYO_DOMAINPOLICY: - case TOMOYO_EXCEPTIONPOLICY: - case TOMOYO_STAT: - case TOMOYO_PROFILE: - case TOMOYO_MANAGER: - tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES); - break; - default: - break; - } - break; - } - } -out: - tomoyo_read_unlock(idx); - mutex_unlock(&head->io_sem); - return error; -} - -/** - * tomoyo_close_control - close() for /sys/kernel/security/tomoyo/ interface. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns 0. - */ -int tomoyo_close_control(struct tomoyo_io_buffer *head) -{ - /* - * If the file is /sys/kernel/security/tomoyo/query , decrement the - * observer counter. - */ - if (head->type == TOMOYO_QUERY && - atomic_dec_and_test(&tomoyo_query_observers)) - wake_up_all(&tomoyo_answer_wait); - tomoyo_notify_gc(head, false); - return 0; -} - -/** - * tomoyo_check_profile - Check all profiles currently assigned to domains are defined. - */ -void tomoyo_check_profile(void) -{ - struct tomoyo_domain_info *domain; - const int idx = tomoyo_read_lock(); - tomoyo_policy_loaded = true; - printk(KERN_INFO "TOMOYO: 2.5.0\n"); - list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { - const u8 profile = domain->profile; - const struct tomoyo_policy_namespace *ns = domain->ns; - if (ns->profile_version != 20110903) - printk(KERN_ERR - "Profile version %u is not supported.\n", - ns->profile_version); - else if (!ns->profile_ptr[profile]) - printk(KERN_ERR - "Profile %u (used by '%s') is not defined.\n", - profile, domain->domainname->name); - else - continue; - printk(KERN_ERR - "Userland tools for TOMOYO 2.5 must be installed and " - "policy must be initialized.\n"); - printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.5/ " - "for more information.\n"); - panic("STOP!"); - } - tomoyo_read_unlock(idx); - printk(KERN_INFO "Mandatory Access Control activated.\n"); -} - -/** - * tomoyo_load_builtin_policy - Load built-in policy. - * - * Returns nothing. - */ -void __init tomoyo_load_builtin_policy(void) -{ - /* - * This include file is manually created and contains built-in policy - * named "tomoyo_builtin_profile", "tomoyo_builtin_exception_policy", - * "tomoyo_builtin_domain_policy", "tomoyo_builtin_manager", - * "tomoyo_builtin_stat" in the form of "static char [] __initdata". - */ -#include "builtin-policy.h" - u8 i; - const int idx = tomoyo_read_lock(); - for (i = 0; i < 5; i++) { - struct tomoyo_io_buffer head = { }; - char *start = ""; - switch (i) { - case 0: - start = tomoyo_builtin_profile; - head.type = TOMOYO_PROFILE; - head.write = tomoyo_write_profile; - break; - case 1: - start = tomoyo_builtin_exception_policy; - head.type = TOMOYO_EXCEPTIONPOLICY; - head.write = tomoyo_write_exception; - break; - case 2: - start = tomoyo_builtin_domain_policy; - head.type = TOMOYO_DOMAINPOLICY; - head.write = tomoyo_write_domain; - break; - case 3: - start = tomoyo_builtin_manager; - head.type = TOMOYO_MANAGER; - head.write = tomoyo_write_manager; - break; - case 4: - start = tomoyo_builtin_stat; - head.type = TOMOYO_STAT; - head.write = tomoyo_write_stat; - break; - } - while (1) { - char *end = strchr(start, '\n'); - if (!end) - break; - *end = '\0'; - tomoyo_normalize_line(start); - head.write_buf = start; - tomoyo_parse_policy(&head, start); - start = end + 1; - } - } - tomoyo_read_unlock(idx); -#ifdef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER - tomoyo_check_profile(); -#endif -} diff --git a/ANDROID_3.4.5/security/tomoyo/common.h b/ANDROID_3.4.5/security/tomoyo/common.h deleted file mode 100644 index 30fd9836..00000000 --- a/ANDROID_3.4.5/security/tomoyo/common.h +++ /dev/null @@ -1,1331 +0,0 @@ -/* - * security/tomoyo/common.h - * - * Header file for TOMOYO. - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#ifndef _SECURITY_TOMOYO_COMMON_H -#define _SECURITY_TOMOYO_COMMON_H - -#include <linux/ctype.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/file.h> -#include <linux/kmod.h> -#include <linux/fs.h> -#include <linux/sched.h> -#include <linux/namei.h> -#include <linux/mount.h> -#include <linux/list.h> -#include <linux/cred.h> -#include <linux/poll.h> -#include <linux/binfmts.h> -#include <linux/highmem.h> -#include <linux/net.h> -#include <linux/inet.h> -#include <linux/in.h> -#include <linux/in6.h> -#include <linux/un.h> -#include <net/sock.h> -#include <net/af_unix.h> -#include <net/ip.h> -#include <net/ipv6.h> -#include <net/udp.h> - -/********** Constants definitions. **********/ - -/* - * TOMOYO uses this hash only when appending a string into the string - * table. Frequency of appending strings is very low. So we don't need - * large (e.g. 64k) hash size. 256 will be sufficient. - */ -#define TOMOYO_HASH_BITS 8 -#define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS) - -/* - * TOMOYO checks only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET. - * Therefore, we don't need SOCK_MAX. - */ -#define TOMOYO_SOCK_MAX 6 - -#define TOMOYO_EXEC_TMPSIZE 4096 - -/* Garbage collector is trying to kfree() this element. */ -#define TOMOYO_GC_IN_PROGRESS -1 - -/* Profile number is an integer between 0 and 255. */ -#define TOMOYO_MAX_PROFILES 256 - -/* Group number is an integer between 0 and 255. */ -#define TOMOYO_MAX_ACL_GROUPS 256 - -/* Index numbers for "struct tomoyo_condition". */ -enum tomoyo_conditions_index { - TOMOYO_TASK_UID, /* current_uid() */ - TOMOYO_TASK_EUID, /* current_euid() */ - TOMOYO_TASK_SUID, /* current_suid() */ - TOMOYO_TASK_FSUID, /* current_fsuid() */ - TOMOYO_TASK_GID, /* current_gid() */ - TOMOYO_TASK_EGID, /* current_egid() */ - TOMOYO_TASK_SGID, /* current_sgid() */ - TOMOYO_TASK_FSGID, /* current_fsgid() */ - TOMOYO_TASK_PID, /* sys_getpid() */ - TOMOYO_TASK_PPID, /* sys_getppid() */ - TOMOYO_EXEC_ARGC, /* "struct linux_binprm *"->argc */ - TOMOYO_EXEC_ENVC, /* "struct linux_binprm *"->envc */ - TOMOYO_TYPE_IS_SOCKET, /* S_IFSOCK */ - TOMOYO_TYPE_IS_SYMLINK, /* S_IFLNK */ - TOMOYO_TYPE_IS_FILE, /* S_IFREG */ - TOMOYO_TYPE_IS_BLOCK_DEV, /* S_IFBLK */ - TOMOYO_TYPE_IS_DIRECTORY, /* S_IFDIR */ - TOMOYO_TYPE_IS_CHAR_DEV, /* S_IFCHR */ - TOMOYO_TYPE_IS_FIFO, /* S_IFIFO */ - TOMOYO_MODE_SETUID, /* S_ISUID */ - TOMOYO_MODE_SETGID, /* S_ISGID */ - TOMOYO_MODE_STICKY, /* S_ISVTX */ - TOMOYO_MODE_OWNER_READ, /* S_IRUSR */ - TOMOYO_MODE_OWNER_WRITE, /* S_IWUSR */ - TOMOYO_MODE_OWNER_EXECUTE, /* S_IXUSR */ - TOMOYO_MODE_GROUP_READ, /* S_IRGRP */ - TOMOYO_MODE_GROUP_WRITE, /* S_IWGRP */ - TOMOYO_MODE_GROUP_EXECUTE, /* S_IXGRP */ - TOMOYO_MODE_OTHERS_READ, /* S_IROTH */ - TOMOYO_MODE_OTHERS_WRITE, /* S_IWOTH */ - TOMOYO_MODE_OTHERS_EXECUTE, /* S_IXOTH */ - TOMOYO_EXEC_REALPATH, - TOMOYO_SYMLINK_TARGET, - TOMOYO_PATH1_UID, - TOMOYO_PATH1_GID, - TOMOYO_PATH1_INO, - TOMOYO_PATH1_MAJOR, - TOMOYO_PATH1_MINOR, - TOMOYO_PATH1_PERM, - TOMOYO_PATH1_TYPE, - TOMOYO_PATH1_DEV_MAJOR, - TOMOYO_PATH1_DEV_MINOR, - TOMOYO_PATH2_UID, - TOMOYO_PATH2_GID, - TOMOYO_PATH2_INO, - TOMOYO_PATH2_MAJOR, - TOMOYO_PATH2_MINOR, - TOMOYO_PATH2_PERM, - TOMOYO_PATH2_TYPE, - TOMOYO_PATH2_DEV_MAJOR, - TOMOYO_PATH2_DEV_MINOR, - TOMOYO_PATH1_PARENT_UID, - TOMOYO_PATH1_PARENT_GID, - TOMOYO_PATH1_PARENT_INO, - TOMOYO_PATH1_PARENT_PERM, - TOMOYO_PATH2_PARENT_UID, - TOMOYO_PATH2_PARENT_GID, - TOMOYO_PATH2_PARENT_INO, - TOMOYO_PATH2_PARENT_PERM, - TOMOYO_MAX_CONDITION_KEYWORD, - TOMOYO_NUMBER_UNION, - TOMOYO_NAME_UNION, - TOMOYO_ARGV_ENTRY, - TOMOYO_ENVP_ENTRY, -}; - - -/* Index numbers for stat(). */ -enum tomoyo_path_stat_index { - /* Do not change this order. */ - TOMOYO_PATH1, - TOMOYO_PATH1_PARENT, - TOMOYO_PATH2, - TOMOYO_PATH2_PARENT, - TOMOYO_MAX_PATH_STAT -}; - -/* Index numbers for operation mode. */ -enum tomoyo_mode_index { - TOMOYO_CONFIG_DISABLED, - TOMOYO_CONFIG_LEARNING, - TOMOYO_CONFIG_PERMISSIVE, - TOMOYO_CONFIG_ENFORCING, - TOMOYO_CONFIG_MAX_MODE, - TOMOYO_CONFIG_WANT_REJECT_LOG = 64, - TOMOYO_CONFIG_WANT_GRANT_LOG = 128, - TOMOYO_CONFIG_USE_DEFAULT = 255, -}; - -/* Index numbers for entry type. */ -enum tomoyo_policy_id { - TOMOYO_ID_GROUP, - TOMOYO_ID_ADDRESS_GROUP, - TOMOYO_ID_PATH_GROUP, - TOMOYO_ID_NUMBER_GROUP, - TOMOYO_ID_TRANSITION_CONTROL, - TOMOYO_ID_AGGREGATOR, - TOMOYO_ID_MANAGER, - TOMOYO_ID_CONDITION, - TOMOYO_ID_NAME, - TOMOYO_ID_ACL, - TOMOYO_ID_DOMAIN, - TOMOYO_MAX_POLICY -}; - -/* Index numbers for domain's attributes. */ -enum tomoyo_domain_info_flags_index { - /* Quota warnning flag. */ - TOMOYO_DIF_QUOTA_WARNED, - /* - * This domain was unable to create a new domain at - * tomoyo_find_next_domain() because the name of the domain to be - * created was too long or it could not allocate memory. - * More than one process continued execve() without domain transition. - */ - TOMOYO_DIF_TRANSITION_FAILED, - TOMOYO_MAX_DOMAIN_INFO_FLAGS -}; - -/* Index numbers for audit type. */ -enum tomoyo_grant_log { - /* Follow profile's configuration. */ - TOMOYO_GRANTLOG_AUTO, - /* Do not generate grant log. */ - TOMOYO_GRANTLOG_NO, - /* Generate grant_log. */ - TOMOYO_GRANTLOG_YES, -}; - -/* Index numbers for group entries. */ -enum tomoyo_group_id { - TOMOYO_PATH_GROUP, - TOMOYO_NUMBER_GROUP, - TOMOYO_ADDRESS_GROUP, - TOMOYO_MAX_GROUP -}; - -/* Index numbers for type of numeric values. */ -enum tomoyo_value_type { - TOMOYO_VALUE_TYPE_INVALID, - TOMOYO_VALUE_TYPE_DECIMAL, - TOMOYO_VALUE_TYPE_OCTAL, - TOMOYO_VALUE_TYPE_HEXADECIMAL, -}; - -/* Index numbers for domain transition control keywords. */ -enum tomoyo_transition_type { - /* Do not change this order, */ - TOMOYO_TRANSITION_CONTROL_NO_RESET, - TOMOYO_TRANSITION_CONTROL_RESET, - TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE, - TOMOYO_TRANSITION_CONTROL_INITIALIZE, - TOMOYO_TRANSITION_CONTROL_NO_KEEP, - TOMOYO_TRANSITION_CONTROL_KEEP, - TOMOYO_MAX_TRANSITION_TYPE -}; - -/* Index numbers for Access Controls. */ -enum tomoyo_acl_entry_type_index { - TOMOYO_TYPE_PATH_ACL, - TOMOYO_TYPE_PATH2_ACL, - TOMOYO_TYPE_PATH_NUMBER_ACL, - TOMOYO_TYPE_MKDEV_ACL, - TOMOYO_TYPE_MOUNT_ACL, - TOMOYO_TYPE_INET_ACL, - TOMOYO_TYPE_UNIX_ACL, - TOMOYO_TYPE_ENV_ACL, - TOMOYO_TYPE_MANUAL_TASK_ACL, -}; - -/* Index numbers for access controls with one pathname. */ -enum tomoyo_path_acl_index { - TOMOYO_TYPE_EXECUTE, - TOMOYO_TYPE_READ, - TOMOYO_TYPE_WRITE, - TOMOYO_TYPE_APPEND, - TOMOYO_TYPE_UNLINK, - TOMOYO_TYPE_GETATTR, - TOMOYO_TYPE_RMDIR, - TOMOYO_TYPE_TRUNCATE, - TOMOYO_TYPE_SYMLINK, - TOMOYO_TYPE_CHROOT, - TOMOYO_TYPE_UMOUNT, - TOMOYO_MAX_PATH_OPERATION -}; - -/* Index numbers for /sys/kernel/security/tomoyo/stat interface. */ -enum tomoyo_memory_stat_type { - TOMOYO_MEMORY_POLICY, - TOMOYO_MEMORY_AUDIT, - TOMOYO_MEMORY_QUERY, - TOMOYO_MAX_MEMORY_STAT -}; - -enum tomoyo_mkdev_acl_index { - TOMOYO_TYPE_MKBLOCK, - TOMOYO_TYPE_MKCHAR, - TOMOYO_MAX_MKDEV_OPERATION -}; - -/* Index numbers for socket operations. */ -enum tomoyo_network_acl_index { - TOMOYO_NETWORK_BIND, /* bind() operation. */ - TOMOYO_NETWORK_LISTEN, /* listen() operation. */ - TOMOYO_NETWORK_CONNECT, /* connect() operation. */ - TOMOYO_NETWORK_SEND, /* send() operation. */ - TOMOYO_MAX_NETWORK_OPERATION -}; - -/* Index numbers for access controls with two pathnames. */ -enum tomoyo_path2_acl_index { - TOMOYO_TYPE_LINK, - TOMOYO_TYPE_RENAME, - TOMOYO_TYPE_PIVOT_ROOT, - TOMOYO_MAX_PATH2_OPERATION -}; - -/* Index numbers for access controls with one pathname and one number. */ -enum tomoyo_path_number_acl_index { - TOMOYO_TYPE_CREATE, - TOMOYO_TYPE_MKDIR, - TOMOYO_TYPE_MKFIFO, - TOMOYO_TYPE_MKSOCK, - TOMOYO_TYPE_IOCTL, - TOMOYO_TYPE_CHMOD, - TOMOYO_TYPE_CHOWN, - TOMOYO_TYPE_CHGRP, - TOMOYO_MAX_PATH_NUMBER_OPERATION -}; - -/* Index numbers for /sys/kernel/security/tomoyo/ interfaces. */ -enum tomoyo_securityfs_interface_index { - TOMOYO_DOMAINPOLICY, - TOMOYO_EXCEPTIONPOLICY, - TOMOYO_PROCESS_STATUS, - TOMOYO_STAT, - TOMOYO_AUDIT, - TOMOYO_VERSION, - TOMOYO_PROFILE, - TOMOYO_QUERY, - TOMOYO_MANAGER -}; - -/* Index numbers for special mount operations. */ -enum tomoyo_special_mount { - TOMOYO_MOUNT_BIND, /* mount --bind /source /dest */ - TOMOYO_MOUNT_MOVE, /* mount --move /old /new */ - TOMOYO_MOUNT_REMOUNT, /* mount -o remount /dir */ - TOMOYO_MOUNT_MAKE_UNBINDABLE, /* mount --make-unbindable /dir */ - TOMOYO_MOUNT_MAKE_PRIVATE, /* mount --make-private /dir */ - TOMOYO_MOUNT_MAKE_SLAVE, /* mount --make-slave /dir */ - TOMOYO_MOUNT_MAKE_SHARED, /* mount --make-shared /dir */ - TOMOYO_MAX_SPECIAL_MOUNT -}; - -/* Index numbers for functionality. */ -enum tomoyo_mac_index { - TOMOYO_MAC_FILE_EXECUTE, - TOMOYO_MAC_FILE_OPEN, - TOMOYO_MAC_FILE_CREATE, - TOMOYO_MAC_FILE_UNLINK, - TOMOYO_MAC_FILE_GETATTR, - 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_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_MAC_NETWORK_INET_STREAM_BIND, - TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN, - TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT, - TOMOYO_MAC_NETWORK_INET_DGRAM_BIND, - TOMOYO_MAC_NETWORK_INET_DGRAM_SEND, - TOMOYO_MAC_NETWORK_INET_RAW_BIND, - TOMOYO_MAC_NETWORK_INET_RAW_SEND, - TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND, - TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN, - TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT, - TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND, - TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND, - TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND, - TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN, - TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT, - TOMOYO_MAC_ENVIRON, - TOMOYO_MAX_MAC_INDEX -}; - -/* Index numbers for category of functionality. */ -enum tomoyo_mac_category_index { - TOMOYO_MAC_CATEGORY_FILE, - TOMOYO_MAC_CATEGORY_NETWORK, - TOMOYO_MAC_CATEGORY_MISC, - TOMOYO_MAX_MAC_CATEGORY_INDEX -}; - -/* - * Retry this request. Returned by tomoyo_supervisor() if policy violation has - * occurred in enforcing mode and the userspace daemon decided to retry. - * - * We must choose a positive value in order to distinguish "granted" (which is - * 0) and "rejected" (which is a negative value) and "retry". - */ -#define TOMOYO_RETRY_REQUEST 1 - -/* Index numbers for /sys/kernel/security/tomoyo/stat interface. */ -enum tomoyo_policy_stat_type { - /* Do not change this order. */ - TOMOYO_STAT_POLICY_UPDATES, - TOMOYO_STAT_POLICY_LEARNING, /* == TOMOYO_CONFIG_LEARNING */ - TOMOYO_STAT_POLICY_PERMISSIVE, /* == TOMOYO_CONFIG_PERMISSIVE */ - TOMOYO_STAT_POLICY_ENFORCING, /* == TOMOYO_CONFIG_ENFORCING */ - TOMOYO_MAX_POLICY_STAT -}; - -/* Index numbers for profile's PREFERENCE values. */ -enum tomoyo_pref_index { - TOMOYO_PREF_MAX_AUDIT_LOG, - TOMOYO_PREF_MAX_LEARNING_ENTRY, - TOMOYO_MAX_PREF -}; - -/********** Structure definitions. **********/ - -/* Common header for holding ACL entries. */ -struct tomoyo_acl_head { - struct list_head list; - s8 is_deleted; /* true or false or TOMOYO_GC_IN_PROGRESS */ -} __packed; - -/* Common header for shared entries. */ -struct tomoyo_shared_acl_head { - struct list_head list; - atomic_t users; -} __packed; - -struct tomoyo_policy_namespace; - -/* Structure for request info. */ -struct tomoyo_request_info { - /* - * For holding parameters specific to operations which deal files. - * NULL if not dealing files. - */ - struct tomoyo_obj_info *obj; - /* - * For holding parameters specific to execve() request. - * NULL if not dealing do_execve(). - */ - struct tomoyo_execve *ee; - struct tomoyo_domain_info *domain; - /* For holding parameters. */ - union { - struct { - const struct tomoyo_path_info *filename; - /* For using wildcards at tomoyo_find_next_domain(). */ - const struct tomoyo_path_info *matched_path; - /* One of values in "enum tomoyo_path_acl_index". */ - u8 operation; - } path; - struct { - const struct tomoyo_path_info *filename1; - const struct tomoyo_path_info *filename2; - /* One of values in "enum tomoyo_path2_acl_index". */ - u8 operation; - } path2; - struct { - const struct tomoyo_path_info *filename; - unsigned int mode; - unsigned int major; - unsigned int minor; - /* One of values in "enum tomoyo_mkdev_acl_index". */ - u8 operation; - } mkdev; - struct { - const struct tomoyo_path_info *filename; - unsigned long number; - /* - * One of values in - * "enum tomoyo_path_number_acl_index". - */ - u8 operation; - } path_number; - struct { - const struct tomoyo_path_info *name; - } environ; - struct { - const __be32 *address; - u16 port; - /* One of values smaller than TOMOYO_SOCK_MAX. */ - u8 protocol; - /* One of values in "enum tomoyo_network_acl_index". */ - u8 operation; - bool is_ipv6; - } inet_network; - struct { - const struct tomoyo_path_info *address; - /* One of values smaller than TOMOYO_SOCK_MAX. */ - u8 protocol; - /* One of values in "enum tomoyo_network_acl_index". */ - u8 operation; - } unix_network; - 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; - struct { - const struct tomoyo_path_info *domainname; - } task; - } param; - struct tomoyo_acl_info *matched_acl; - u8 param_type; - bool granted; - u8 retry; - u8 profile; - u8 mode; /* One of tomoyo_mode_index . */ - u8 type; -}; - -/* Structure for holding a token. */ -struct tomoyo_path_info { - const char *name; - u32 hash; /* = full_name_hash(name, strlen(name)) */ - u16 const_len; /* = tomoyo_const_part_length(name) */ - bool is_dir; /* = tomoyo_strendswith(name, "/") */ - bool is_patterned; /* = tomoyo_path_contains_pattern(name) */ -}; - -/* Structure for holding string data. */ -struct tomoyo_name { - struct tomoyo_shared_acl_head head; - struct tomoyo_path_info entry; -}; - -/* Structure for holding a word. */ -struct tomoyo_name_union { - /* Either @filename or @group is NULL. */ - const struct tomoyo_path_info *filename; - struct tomoyo_group *group; -}; - -/* Structure for holding a number. */ -struct tomoyo_number_union { - unsigned long values[2]; - struct tomoyo_group *group; /* Maybe NULL. */ - /* One of values in "enum tomoyo_value_type". */ - u8 value_type[2]; -}; - -/* Structure for holding an IP address. */ -struct tomoyo_ipaddr_union { - struct in6_addr ip[2]; /* Big endian. */ - struct tomoyo_group *group; /* Pointer to address group. */ - bool is_ipv6; /* Valid only if @group == NULL. */ -}; - -/* Structure for "path_group"/"number_group"/"address_group" directive. */ -struct tomoyo_group { - struct tomoyo_shared_acl_head head; - const struct tomoyo_path_info *group_name; - struct list_head member_list; -}; - -/* Structure for "path_group" directive. */ -struct tomoyo_path_group { - struct tomoyo_acl_head head; - const struct tomoyo_path_info *member_name; -}; - -/* Structure for "number_group" directive. */ -struct tomoyo_number_group { - struct tomoyo_acl_head head; - struct tomoyo_number_union number; -}; - -/* Structure for "address_group" directive. */ -struct tomoyo_address_group { - struct tomoyo_acl_head head; - /* Structure for holding an IP address. */ - struct tomoyo_ipaddr_union address; -}; - -/* Subset of "struct stat". Used by conditional ACL and audit logs. */ -struct tomoyo_mini_stat { - uid_t uid; - gid_t gid; - ino_t ino; - umode_t mode; - dev_t dev; - dev_t rdev; -}; - -/* Structure for dumping argv[] and envp[] of "struct linux_binprm". */ -struct tomoyo_page_dump { - struct page *page; /* Previously dumped page. */ - char *data; /* Contents of "page". Size is PAGE_SIZE. */ -}; - -/* Structure for attribute checks in addition to pathname checks. */ -struct tomoyo_obj_info { - /* - * True if tomoyo_get_attributes() was already called, false otherwise. - */ - bool validate_done; - /* True if @stat[] is valid. */ - bool stat_valid[TOMOYO_MAX_PATH_STAT]; - /* First pathname. Initialized with { NULL, NULL } if no path. */ - struct path path1; - /* Second pathname. Initialized with { NULL, NULL } if no path. */ - struct path path2; - /* - * Information on @path1, @path1's parent directory, @path2, @path2's - * parent directory. - */ - struct tomoyo_mini_stat stat[TOMOYO_MAX_PATH_STAT]; - /* - * Content of symbolic link to be created. NULL for operations other - * than symlink(). - */ - struct tomoyo_path_info *symlink_target; -}; - -/* Structure for argv[]. */ -struct tomoyo_argv { - unsigned long index; - const struct tomoyo_path_info *value; - bool is_not; -}; - -/* Structure for envp[]. */ -struct tomoyo_envp { - const struct tomoyo_path_info *name; - const struct tomoyo_path_info *value; - bool is_not; -}; - -/* Structure for execve() operation. */ -struct tomoyo_execve { - struct tomoyo_request_info r; - struct tomoyo_obj_info obj; - struct linux_binprm *bprm; - const struct tomoyo_path_info *transition; - /* For dumping argv[] and envp[]. */ - struct tomoyo_page_dump dump; - /* For temporary use. */ - char *tmp; /* Size is TOMOYO_EXEC_TMPSIZE bytes */ -}; - -/* Structure for entries which follows "struct tomoyo_condition". */ -struct tomoyo_condition_element { - /* - * Left hand operand. A "struct tomoyo_argv" for TOMOYO_ARGV_ENTRY, a - * "struct tomoyo_envp" for TOMOYO_ENVP_ENTRY is attached to the tail - * of the array of this struct. - */ - u8 left; - /* - * Right hand operand. A "struct tomoyo_number_union" for - * TOMOYO_NUMBER_UNION, a "struct tomoyo_name_union" for - * TOMOYO_NAME_UNION is attached to the tail of the array of this - * struct. - */ - u8 right; - /* Equation operator. True if equals or overlaps, false otherwise. */ - bool equals; -}; - -/* Structure for optional arguments. */ -struct tomoyo_condition { - struct tomoyo_shared_acl_head head; - u32 size; /* Memory size allocated for this entry. */ - u16 condc; /* Number of conditions in this struct. */ - u16 numbers_count; /* Number of "struct tomoyo_number_union values". */ - u16 names_count; /* Number of "struct tomoyo_name_union names". */ - u16 argc; /* Number of "struct tomoyo_argv". */ - u16 envc; /* Number of "struct tomoyo_envp". */ - u8 grant_log; /* One of values in "enum tomoyo_grant_log". */ - const struct tomoyo_path_info *transit; /* Maybe NULL. */ - /* - * struct tomoyo_condition_element condition[condc]; - * struct tomoyo_number_union values[numbers_count]; - * struct tomoyo_name_union names[names_count]; - * struct tomoyo_argv argv[argc]; - * struct tomoyo_envp envp[envc]; - */ -}; - -/* Common header for individual entries. */ -struct tomoyo_acl_info { - struct list_head list; - struct tomoyo_condition *cond; /* Maybe NULL. */ - s8 is_deleted; /* true or false or TOMOYO_GC_IN_PROGRESS */ - u8 type; /* One of values in "enum tomoyo_acl_entry_type_index". */ -} __packed; - -/* Structure for domain information. */ -struct tomoyo_domain_info { - struct list_head list; - struct list_head acl_info_list; - /* Name of this domain. Never NULL. */ - const struct tomoyo_path_info *domainname; - /* Namespace for this domain. Never NULL. */ - struct tomoyo_policy_namespace *ns; - u8 profile; /* Profile number to use. */ - u8 group; /* Group number to use. */ - bool is_deleted; /* Delete flag. */ - bool flags[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; - atomic_t users; /* Number of referring credentials. */ -}; - -/* - * Structure for "task manual_domain_transition" directive. - */ -struct tomoyo_task_acl { - struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MANUAL_TASK_ACL */ - /* Pointer to domainname. */ - const struct tomoyo_path_info *domainname; -}; - -/* - * Structure for "file execute", "file read", "file write", "file append", - * "file unlink", "file getattr", "file rmdir", "file truncate", - * "file symlink", "file chroot" and "file unmount" directive. - */ -struct tomoyo_path_acl { - struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ - u16 perm; /* Bitmask of values in "enum tomoyo_path_acl_index". */ - struct tomoyo_name_union name; -}; - -/* - * Structure for "file create", "file mkdir", "file mkfifo", "file mksock", - * "file ioctl", "file chmod", "file chown" and "file chgrp" directive. - */ -struct tomoyo_path_number_acl { - struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_NUMBER_ACL */ - /* Bitmask of values in "enum tomoyo_path_number_acl_index". */ - u8 perm; - struct tomoyo_name_union name; - struct tomoyo_number_union number; -}; - -/* Structure for "file mkblock" and "file mkchar" directive. */ -struct tomoyo_mkdev_acl { - struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MKDEV_ACL */ - u8 perm; /* Bitmask of values in "enum tomoyo_mkdev_acl_index". */ - struct tomoyo_name_union name; - struct tomoyo_number_union mode; - struct tomoyo_number_union major; - struct tomoyo_number_union minor; -}; - -/* - * Structure for "file rename", "file link" and "file pivot_root" directive. - */ -struct tomoyo_path2_acl { - struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */ - u8 perm; /* Bitmask of values in "enum tomoyo_path2_acl_index". */ - struct tomoyo_name_union name1; - struct tomoyo_name_union name2; -}; - -/* Structure for "file mount" directive. */ -struct tomoyo_mount_acl { - struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_MOUNT_ACL */ - struct tomoyo_name_union dev_name; - struct tomoyo_name_union dir_name; - struct tomoyo_name_union fs_type; - struct tomoyo_number_union flags; -}; - -/* Structure for "misc env" directive in domain policy. */ -struct tomoyo_env_acl { - struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_ENV_ACL */ - const struct tomoyo_path_info *env; /* environment variable */ -}; - -/* Structure for "network inet" directive. */ -struct tomoyo_inet_acl { - struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_INET_ACL */ - u8 protocol; - u8 perm; /* Bitmask of values in "enum tomoyo_network_acl_index" */ - struct tomoyo_ipaddr_union address; - struct tomoyo_number_union port; -}; - -/* Structure for "network unix" directive. */ -struct tomoyo_unix_acl { - struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_UNIX_ACL */ - u8 protocol; - u8 perm; /* Bitmask of values in "enum tomoyo_network_acl_index" */ - struct tomoyo_name_union name; -}; - -/* Structure for holding a line from /sys/kernel/security/tomoyo/ interface. */ -struct tomoyo_acl_param { - char *data; - struct list_head *list; - struct tomoyo_policy_namespace *ns; - bool is_delete; -}; - -#define TOMOYO_MAX_IO_READ_QUEUE 64 - -/* - * Structure for reading/writing policy via /sys/kernel/security/tomoyo - * interfaces. - */ -struct tomoyo_io_buffer { - void (*read) (struct tomoyo_io_buffer *); - int (*write) (struct tomoyo_io_buffer *); - unsigned int (*poll) (struct file *file, poll_table *wait); - /* Exclusive lock for this structure. */ - struct mutex io_sem; - char __user *read_user_buf; - size_t read_user_buf_avail; - struct { - struct list_head *ns; - struct list_head *domain; - struct list_head *group; - struct list_head *acl; - size_t avail; - unsigned int step; - unsigned int query_index; - u16 index; - u16 cond_index; - u8 acl_group_index; - u8 cond_step; - u8 bit; - u8 w_pos; - bool eof; - bool print_this_domain_only; - bool print_transition_related_only; - bool print_cond_part; - const char *w[TOMOYO_MAX_IO_READ_QUEUE]; - } r; - struct { - struct tomoyo_policy_namespace *ns; - /* The position currently writing to. */ - struct tomoyo_domain_info *domain; - /* Bytes available for writing. */ - size_t avail; - bool is_delete; - } w; - /* Buffer for reading. */ - char *read_buf; - /* Size of read buffer. */ - size_t readbuf_size; - /* Buffer for writing. */ - char *write_buf; - /* Size of write buffer. */ - size_t writebuf_size; - /* Type of this interface. */ - enum tomoyo_securityfs_interface_index type; - /* Users counter protected by tomoyo_io_buffer_list_lock. */ - u8 users; - /* List for telling GC not to kfree() elements. */ - struct list_head list; -}; - -/* - * Structure for "initialize_domain"/"no_initialize_domain"/"keep_domain"/ - * "no_keep_domain" keyword. - */ -struct tomoyo_transition_control { - struct tomoyo_acl_head head; - u8 type; /* One of values in "enum tomoyo_transition_type". */ - /* True if the domainname is tomoyo_get_last_name(). */ - bool is_last_name; - const struct tomoyo_path_info *domainname; /* Maybe NULL */ - const struct tomoyo_path_info *program; /* Maybe NULL */ -}; - -/* Structure for "aggregator" keyword. */ -struct tomoyo_aggregator { - struct tomoyo_acl_head head; - const struct tomoyo_path_info *original_name; - const struct tomoyo_path_info *aggregated_name; -}; - -/* Structure for policy manager. */ -struct tomoyo_manager { - struct tomoyo_acl_head head; - bool is_domain; /* True if manager is a domainname. */ - /* A path to program or a domainname. */ - const struct tomoyo_path_info *manager; -}; - -struct tomoyo_preference { - unsigned int learning_max_entry; - bool enforcing_verbose; - bool learning_verbose; - bool permissive_verbose; -}; - -/* Structure for /sys/kernel/security/tomnoyo/profile interface. */ -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]; - unsigned int pref[TOMOYO_MAX_PREF]; -}; - -/* Structure for representing YYYY/MM/DD hh/mm/ss. */ -struct tomoyo_time { - u16 year; - u8 month; - u8 day; - u8 hour; - u8 min; - u8 sec; -}; - -/* Structure for policy namespace. */ -struct tomoyo_policy_namespace { - /* Profile table. Memory is allocated as needed. */ - struct tomoyo_profile *profile_ptr[TOMOYO_MAX_PROFILES]; - /* List of "struct tomoyo_group". */ - struct list_head group_list[TOMOYO_MAX_GROUP]; - /* List of policy. */ - struct list_head policy_list[TOMOYO_MAX_POLICY]; - /* The global ACL referred by "use_group" keyword. */ - struct list_head acl_group[TOMOYO_MAX_ACL_GROUPS]; - /* List for connecting to tomoyo_namespace_list list. */ - struct list_head namespace_list; - /* Profile version. Currently only 20110903 is defined. */ - unsigned int profile_version; - /* Name of this namespace (e.g. "<kernel>", "</usr/sbin/httpd>" ). */ - const char *name; -}; - -/********** Function prototypes. **********/ - -bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address, - const struct tomoyo_group *group); -bool tomoyo_compare_number_union(const unsigned long value, - const struct tomoyo_number_union *ptr); -bool tomoyo_condition(struct tomoyo_request_info *r, - const struct tomoyo_condition *cond); -bool tomoyo_correct_domain(const unsigned char *domainname); -bool tomoyo_correct_path(const char *filename); -bool tomoyo_correct_word(const char *string); -bool tomoyo_domain_def(const unsigned char *buffer); -bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); -bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos, - struct tomoyo_page_dump *dump); -bool tomoyo_memory_ok(void *ptr); -bool tomoyo_number_matches_group(const unsigned long min, - const unsigned long max, - const struct tomoyo_group *group); -bool tomoyo_parse_ipaddr_union(struct tomoyo_acl_param *param, - struct tomoyo_ipaddr_union *ptr); -bool tomoyo_parse_name_union(struct tomoyo_acl_param *param, - struct tomoyo_name_union *ptr); -bool tomoyo_parse_number_union(struct tomoyo_acl_param *param, - struct tomoyo_number_union *ptr); -bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, - const struct tomoyo_path_info *pattern); -bool tomoyo_permstr(const char *string, const char *keyword); -bool tomoyo_str_starts(char **src, const char *find); -char *tomoyo_encode(const char *str); -char *tomoyo_encode2(const char *str, int str_len); -char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, - va_list args); -char *tomoyo_read_token(struct tomoyo_acl_param *param); -char *tomoyo_realpath_from_path(struct path *path); -char *tomoyo_realpath_nofollow(const char *pathname); -const char *tomoyo_get_exe(void); -const char *tomoyo_yesno(const unsigned int value); -const struct tomoyo_path_info *tomoyo_compare_name_union -(const struct tomoyo_path_info *name, const struct tomoyo_name_union *ptr); -const struct tomoyo_path_info *tomoyo_get_domainname -(struct tomoyo_acl_param *param); -const struct tomoyo_path_info *tomoyo_get_name(const char *name); -const struct tomoyo_path_info *tomoyo_path_matches_group -(const struct tomoyo_path_info *pathname, const struct tomoyo_group *group); -int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, - struct path *path, const int flag); -int tomoyo_close_control(struct tomoyo_io_buffer *head); -int tomoyo_env_perm(struct tomoyo_request_info *r, const char *env); -int tomoyo_execute_permission(struct tomoyo_request_info *r, - const struct tomoyo_path_info *filename); -int tomoyo_find_next_domain(struct linux_binprm *bprm); -int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile, - const u8 index); -int tomoyo_init_request_info(struct tomoyo_request_info *r, - struct tomoyo_domain_info *domain, - const u8 index); -int tomoyo_mkdev_perm(const u8 operation, struct path *path, - const unsigned int mode, unsigned int dev); -int tomoyo_mount_permission(char *dev_name, struct path *path, - const char *type, unsigned long flags, - void *data_page); -int tomoyo_open_control(const u8 type, struct file *file); -int tomoyo_path2_perm(const u8 operation, struct path *path1, - struct path *path2); -int tomoyo_path_number_perm(const u8 operation, struct path *path, - unsigned long number); -int tomoyo_path_perm(const u8 operation, struct path *path, - const char *target); -unsigned int tomoyo_poll_control(struct file *file, poll_table *wait); -unsigned int tomoyo_poll_log(struct file *file, poll_table *wait); -int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr, - int addr_len); -int tomoyo_socket_connect_permission(struct socket *sock, - struct sockaddr *addr, int addr_len); -int tomoyo_socket_listen_permission(struct socket *sock); -int tomoyo_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg, - int size); -int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) - __printf(2, 3); -int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, - struct tomoyo_acl_param *param, - bool (*check_duplicate) - (const struct tomoyo_acl_info *, - const struct tomoyo_acl_info *), - bool (*merge_duplicate) - (struct tomoyo_acl_info *, struct tomoyo_acl_info *, - const bool)); -int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, - struct tomoyo_acl_param *param, - bool (*check_duplicate) - (const struct tomoyo_acl_head *, - const struct tomoyo_acl_head *)); -int tomoyo_write_aggregator(struct tomoyo_acl_param *param); -int tomoyo_write_file(struct tomoyo_acl_param *param); -int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type); -int tomoyo_write_misc(struct tomoyo_acl_param *param); -int tomoyo_write_inet_network(struct tomoyo_acl_param *param); -int tomoyo_write_transition_control(struct tomoyo_acl_param *param, - const u8 type); -int tomoyo_write_unix_network(struct tomoyo_acl_param *param); -ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, - const int buffer_len); -ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, - const char __user *buffer, const int buffer_len); -struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param); -struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, - const bool transit); -struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); -struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param, - const u8 idx); -struct tomoyo_policy_namespace *tomoyo_assign_namespace -(const char *domainname); -struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns, - const u8 profile); -unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, - const u8 index); -u8 tomoyo_parse_ulong(unsigned long *result, char **str); -void *tomoyo_commit_ok(void *data, const unsigned int size); -void __init tomoyo_load_builtin_policy(void); -void __init tomoyo_mm_init(void); -void tomoyo_check_acl(struct tomoyo_request_info *r, - bool (*check_entry) (struct tomoyo_request_info *, - const struct tomoyo_acl_info *)); -void tomoyo_check_profile(void); -void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp); -void tomoyo_del_condition(struct list_head *element); -void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); -void tomoyo_get_attributes(struct tomoyo_obj_info *obj); -void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns); -void tomoyo_load_policy(const char *filename); -void tomoyo_normalize_line(unsigned char *buffer); -void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register); -void tomoyo_print_ip(char *buf, const unsigned int size, - const struct tomoyo_ipaddr_union *ptr); -void tomoyo_print_ulong(char *buffer, const int buffer_len, - const unsigned long value, const u8 type); -void tomoyo_put_name_union(struct tomoyo_name_union *ptr); -void tomoyo_put_number_union(struct tomoyo_number_union *ptr); -void tomoyo_read_log(struct tomoyo_io_buffer *head); -void tomoyo_update_stat(const u8 index); -void tomoyo_warn_oom(const char *function); -void tomoyo_write_log(struct tomoyo_request_info *r, const char *fmt, ...) - __printf(2, 3); -void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, - va_list args); - -/********** External variable definitions. **********/ - -extern bool tomoyo_policy_loaded; -extern const char * const tomoyo_condition_keyword -[TOMOYO_MAX_CONDITION_KEYWORD]; -extern const char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS]; -extern const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX - + TOMOYO_MAX_MAC_CATEGORY_INDEX]; -extern const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE]; -extern const char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION]; -extern const char * const tomoyo_proto_keyword[TOMOYO_SOCK_MAX]; -extern const char * const tomoyo_socket_keyword[TOMOYO_MAX_NETWORK_OPERATION]; -extern const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX]; -extern const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION]; -extern const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION]; -extern const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION]; -extern struct list_head tomoyo_condition_list; -extern struct list_head tomoyo_domain_list; -extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; -extern struct list_head tomoyo_namespace_list; -extern struct mutex tomoyo_policy_lock; -extern struct srcu_struct tomoyo_ss; -extern struct tomoyo_domain_info tomoyo_kernel_domain; -extern struct tomoyo_policy_namespace tomoyo_kernel_namespace; -extern unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT]; -extern unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; - -/********** Inlined functions. **********/ - -/** - * tomoyo_read_lock - Take lock for protecting policy. - * - * Returns index number for tomoyo_read_unlock(). - */ -static inline int tomoyo_read_lock(void) -{ - return srcu_read_lock(&tomoyo_ss); -} - -/** - * tomoyo_read_unlock - Release lock for protecting policy. - * - * @idx: Index number returned by tomoyo_read_lock(). - * - * Returns nothing. - */ -static inline void tomoyo_read_unlock(int idx) -{ - srcu_read_unlock(&tomoyo_ss, idx); -} - -/** - * tomoyo_sys_getppid - Copy of getppid(). - * - * Returns parent process's PID. - * - * Alpha does not have getppid() defined. To be able to build this module on - * Alpha, I have to copy getppid() from kernel/timer.c. - */ -static inline pid_t tomoyo_sys_getppid(void) -{ - pid_t pid; - rcu_read_lock(); - pid = task_tgid_vnr(rcu_dereference(current->real_parent)); - rcu_read_unlock(); - return pid; -} - -/** - * tomoyo_sys_getpid - Copy of getpid(). - * - * Returns current thread's PID. - * - * Alpha does not have getpid() defined. To be able to build this module on - * Alpha, I have to copy getpid() from kernel/timer.c. - */ -static inline pid_t tomoyo_sys_getpid(void) -{ - return task_tgid_vnr(current); -} - -/** - * tomoyo_pathcmp - strcmp() for "struct tomoyo_path_info" structure. - * - * @a: Pointer to "struct tomoyo_path_info". - * @b: Pointer to "struct tomoyo_path_info". - * - * Returns true if @a == @b, false otherwise. - */ -static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, - const struct tomoyo_path_info *b) -{ - return a->hash != b->hash || strcmp(a->name, b->name); -} - -/** - * tomoyo_put_name - Drop reference on "struct tomoyo_name". - * - * @name: Pointer to "struct tomoyo_path_info". Maybe NULL. - * - * Returns nothing. - */ -static inline void tomoyo_put_name(const struct tomoyo_path_info *name) -{ - if (name) { - struct tomoyo_name *ptr = - container_of(name, typeof(*ptr), entry); - atomic_dec(&ptr->head.users); - } -} - -/** - * tomoyo_put_condition - Drop reference on "struct tomoyo_condition". - * - * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. - * - * Returns nothing. - */ -static inline void tomoyo_put_condition(struct tomoyo_condition *cond) -{ - if (cond) - atomic_dec(&cond->head.users); -} - -/** - * tomoyo_put_group - Drop reference on "struct tomoyo_group". - * - * @group: Pointer to "struct tomoyo_group". Maybe NULL. - * - * Returns nothing. - */ -static inline void tomoyo_put_group(struct tomoyo_group *group) -{ - if (group) - atomic_dec(&group->head.users); -} - -/** - * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread. - * - * Returns pointer to "struct tomoyo_domain_info" for current thread. - */ -static inline struct tomoyo_domain_info *tomoyo_domain(void) -{ - return current_cred()->security; -} - -/** - * tomoyo_real_domain - Get "struct tomoyo_domain_info" for specified thread. - * - * @task: Pointer to "struct task_struct". - * - * Returns pointer to "struct tomoyo_security" for specified thread. - */ -static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct - *task) -{ - return task_cred_xxx(task, security); -} - -/** - * tomoyo_same_name_union - Check for duplicated "struct tomoyo_name_union" entry. - * - * @a: Pointer to "struct tomoyo_name_union". - * @b: Pointer to "struct tomoyo_name_union". - * - * Returns true if @a == @b, false otherwise. - */ -static inline bool tomoyo_same_name_union -(const struct tomoyo_name_union *a, const struct tomoyo_name_union *b) -{ - return a->filename == b->filename && a->group == b->group; -} - -/** - * tomoyo_same_number_union - Check for duplicated "struct tomoyo_number_union" entry. - * - * @a: Pointer to "struct tomoyo_number_union". - * @b: Pointer to "struct tomoyo_number_union". - * - * Returns true if @a == @b, false otherwise. - */ -static inline bool tomoyo_same_number_union -(const struct tomoyo_number_union *a, const struct tomoyo_number_union *b) -{ - return a->values[0] == b->values[0] && a->values[1] == b->values[1] && - a->group == b->group && a->value_type[0] == b->value_type[0] && - a->value_type[1] == b->value_type[1]; -} - -/** - * tomoyo_same_ipaddr_union - Check for duplicated "struct tomoyo_ipaddr_union" entry. - * - * @a: Pointer to "struct tomoyo_ipaddr_union". - * @b: Pointer to "struct tomoyo_ipaddr_union". - * - * Returns true if @a == @b, false otherwise. - */ -static inline bool tomoyo_same_ipaddr_union -(const struct tomoyo_ipaddr_union *a, const struct tomoyo_ipaddr_union *b) -{ - return !memcmp(a->ip, b->ip, sizeof(a->ip)) && a->group == b->group && - a->is_ipv6 == b->is_ipv6; -} - -/** - * tomoyo_current_namespace - Get "struct tomoyo_policy_namespace" for current thread. - * - * Returns pointer to "struct tomoyo_policy_namespace" for current thread. - */ -static inline struct tomoyo_policy_namespace *tomoyo_current_namespace(void) -{ - return tomoyo_domain()->ns; -} - -#if defined(CONFIG_SLOB) - -/** - * tomoyo_round2 - Round up to power of 2 for calculating memory usage. - * - * @size: Size to be rounded up. - * - * Returns @size. - * - * Since SLOB does not round up, this function simply returns @size. - */ -static inline int tomoyo_round2(size_t size) -{ - return size; -} - -#else - -/** - * tomoyo_round2 - Round up to power of 2 for calculating memory usage. - * - * @size: Size to be rounded up. - * - * Returns rounded size. - * - * Strictly speaking, SLAB may be able to allocate (e.g.) 96 bytes instead of - * (e.g.) 128 bytes. - */ -static inline int tomoyo_round2(size_t size) -{ -#if PAGE_SIZE == 4096 - size_t bsize = 32; -#else - size_t bsize = 64; -#endif - if (!size) - return 0; - while (size > bsize) - bsize <<= 1; - return bsize; -} - -#endif - -/** - * list_for_each_cookie - iterate over a list with cookie. - * @pos: the &struct list_head to use as a loop cursor. - * @head: the head for your list. - */ -#define list_for_each_cookie(pos, head) \ - if (!pos) \ - pos = srcu_dereference((head)->next, &tomoyo_ss); \ - for ( ; pos != (head); pos = srcu_dereference(pos->next, &tomoyo_ss)) - -#endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ diff --git a/ANDROID_3.4.5/security/tomoyo/condition.c b/ANDROID_3.4.5/security/tomoyo/condition.c deleted file mode 100644 index 986330b8..00000000 --- a/ANDROID_3.4.5/security/tomoyo/condition.c +++ /dev/null @@ -1,1094 +0,0 @@ -/* - * security/tomoyo/condition.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include "common.h" -#include <linux/slab.h> - -/* List of "struct tomoyo_condition". */ -LIST_HEAD(tomoyo_condition_list); - -/** - * tomoyo_argv - Check argv[] in "struct linux_binbrm". - * - * @index: Index number of @arg_ptr. - * @arg_ptr: Contents of argv[@index]. - * @argc: Length of @argv. - * @argv: Pointer to "struct tomoyo_argv". - * @checked: Set to true if @argv[@index] was found. - * - * Returns true on success, false otherwise. - */ -static bool tomoyo_argv(const unsigned int index, const char *arg_ptr, - const int argc, const struct tomoyo_argv *argv, - u8 *checked) -{ - int i; - struct tomoyo_path_info arg; - arg.name = arg_ptr; - for (i = 0; i < argc; argv++, checked++, i++) { - bool result; - if (index != argv->index) - continue; - *checked = 1; - tomoyo_fill_path_info(&arg); - result = tomoyo_path_matches_pattern(&arg, argv->value); - if (argv->is_not) - result = !result; - if (!result) - return false; - } - return true; -} - -/** - * tomoyo_envp - Check envp[] in "struct linux_binbrm". - * - * @env_name: The name of environment variable. - * @env_value: The value of environment variable. - * @envc: Length of @envp. - * @envp: Pointer to "struct tomoyo_envp". - * @checked: Set to true if @envp[@env_name] was found. - * - * Returns true on success, false otherwise. - */ -static bool tomoyo_envp(const char *env_name, const char *env_value, - const int envc, const struct tomoyo_envp *envp, - u8 *checked) -{ - int i; - struct tomoyo_path_info name; - struct tomoyo_path_info value; - name.name = env_name; - tomoyo_fill_path_info(&name); - value.name = env_value; - tomoyo_fill_path_info(&value); - for (i = 0; i < envc; envp++, checked++, i++) { - bool result; - if (!tomoyo_path_matches_pattern(&name, envp->name)) - continue; - *checked = 1; - if (envp->value) { - result = tomoyo_path_matches_pattern(&value, - envp->value); - if (envp->is_not) - result = !result; - } else { - result = true; - if (!envp->is_not) - result = !result; - } - if (!result) - return false; - } - return true; -} - -/** - * tomoyo_scan_bprm - Scan "struct linux_binprm". - * - * @ee: Pointer to "struct tomoyo_execve". - * @argc: Length of @argc. - * @argv: Pointer to "struct tomoyo_argv". - * @envc: Length of @envp. - * @envp: Poiner to "struct tomoyo_envp". - * - * Returns true on success, false otherwise. - */ -static bool tomoyo_scan_bprm(struct tomoyo_execve *ee, - const u16 argc, const struct tomoyo_argv *argv, - const u16 envc, const struct tomoyo_envp *envp) -{ - struct linux_binprm *bprm = ee->bprm; - struct tomoyo_page_dump *dump = &ee->dump; - char *arg_ptr = ee->tmp; - int arg_len = 0; - unsigned long pos = bprm->p; - int offset = pos % PAGE_SIZE; - int argv_count = bprm->argc; - int envp_count = bprm->envc; - bool result = true; - u8 local_checked[32]; - u8 *checked; - if (argc + envc <= sizeof(local_checked)) { - checked = local_checked; - memset(local_checked, 0, sizeof(local_checked)); - } else { - checked = kzalloc(argc + envc, GFP_NOFS); - if (!checked) - return false; - } - while (argv_count || envp_count) { - if (!tomoyo_dump_page(bprm, pos, dump)) { - result = false; - goto out; - } - pos += PAGE_SIZE - offset; - while (offset < PAGE_SIZE) { - /* Read. */ - const char *kaddr = dump->data; - const unsigned char c = kaddr[offset++]; - if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) { - if (c == '\\') { - arg_ptr[arg_len++] = '\\'; - arg_ptr[arg_len++] = '\\'; - } else if (c > ' ' && c < 127) { - arg_ptr[arg_len++] = c; - } else { - arg_ptr[arg_len++] = '\\'; - arg_ptr[arg_len++] = (c >> 6) + '0'; - arg_ptr[arg_len++] = - ((c >> 3) & 7) + '0'; - arg_ptr[arg_len++] = (c & 7) + '0'; - } - } else { - arg_ptr[arg_len] = '\0'; - } - if (c) - continue; - /* Check. */ - if (argv_count) { - if (!tomoyo_argv(bprm->argc - argv_count, - arg_ptr, argc, argv, - checked)) { - result = false; - break; - } - argv_count--; - } else if (envp_count) { - char *cp = strchr(arg_ptr, '='); - if (cp) { - *cp = '\0'; - if (!tomoyo_envp(arg_ptr, cp + 1, - envc, envp, - checked + argc)) { - result = false; - break; - } - } - envp_count--; - } else { - break; - } - arg_len = 0; - } - offset = 0; - if (!result) - break; - } -out: - if (result) { - int i; - /* Check not-yet-checked entries. */ - for (i = 0; i < argc; i++) { - if (checked[i]) - continue; - /* - * Return true only if all unchecked indexes in - * bprm->argv[] are not matched. - */ - if (argv[i].is_not) - continue; - result = false; - break; - } - for (i = 0; i < envc; envp++, i++) { - if (checked[argc + i]) - continue; - /* - * Return true only if all unchecked environ variables - * in bprm->envp[] are either undefined or not matched. - */ - if ((!envp->value && !envp->is_not) || - (envp->value && envp->is_not)) - continue; - result = false; - break; - } - } - if (checked != local_checked) - kfree(checked); - return result; -} - -/** - * tomoyo_scan_exec_realpath - Check "exec.realpath" parameter of "struct tomoyo_condition". - * - * @file: Pointer to "struct file". - * @ptr: Pointer to "struct tomoyo_name_union". - * @match: True if "exec.realpath=", false if "exec.realpath!=". - * - * Returns true on success, false otherwise. - */ -static bool tomoyo_scan_exec_realpath(struct file *file, - const struct tomoyo_name_union *ptr, - const bool match) -{ - bool result; - struct tomoyo_path_info exe; - if (!file) - return false; - exe.name = tomoyo_realpath_from_path(&file->f_path); - if (!exe.name) - return false; - tomoyo_fill_path_info(&exe); - result = tomoyo_compare_name_union(&exe, ptr); - kfree(exe.name); - return result == match; -} - -/** - * tomoyo_get_dqword - tomoyo_get_name() for a quoted string. - * - * @start: String to save. - * - * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. - */ -static const struct tomoyo_path_info *tomoyo_get_dqword(char *start) -{ - char *cp = start + strlen(start) - 1; - if (cp == start || *start++ != '"' || *cp != '"') - return NULL; - *cp = '\0'; - if (*start && !tomoyo_correct_word(start)) - return NULL; - return tomoyo_get_name(start); -} - -/** - * tomoyo_parse_name_union_quoted - Parse a quoted word. - * - * @param: Pointer to "struct tomoyo_acl_param". - * @ptr: Pointer to "struct tomoyo_name_union". - * - * Returns true on success, false otherwise. - */ -static bool tomoyo_parse_name_union_quoted(struct tomoyo_acl_param *param, - struct tomoyo_name_union *ptr) -{ - char *filename = param->data; - if (*filename == '@') - return tomoyo_parse_name_union(param, ptr); - ptr->filename = tomoyo_get_dqword(filename); - return ptr->filename != NULL; -} - -/** - * tomoyo_parse_argv - Parse an argv[] condition part. - * - * @left: Lefthand value. - * @right: Righthand value. - * @argv: Pointer to "struct tomoyo_argv". - * - * Returns true on success, false otherwise. - */ -static bool tomoyo_parse_argv(char *left, char *right, - struct tomoyo_argv *argv) -{ - if (tomoyo_parse_ulong(&argv->index, &left) != - TOMOYO_VALUE_TYPE_DECIMAL || *left++ != ']' || *left) - return false; - argv->value = tomoyo_get_dqword(right); - return argv->value != NULL; -} - -/** - * tomoyo_parse_envp - Parse an envp[] condition part. - * - * @left: Lefthand value. - * @right: Righthand value. - * @envp: Pointer to "struct tomoyo_envp". - * - * Returns true on success, false otherwise. - */ -static bool tomoyo_parse_envp(char *left, char *right, - struct tomoyo_envp *envp) -{ - const struct tomoyo_path_info *name; - const struct tomoyo_path_info *value; - char *cp = left + strlen(left) - 1; - if (*cp-- != ']' || *cp != '"') - goto out; - *cp = '\0'; - if (!tomoyo_correct_word(left)) - goto out; - name = tomoyo_get_name(left); - if (!name) - goto out; - if (!strcmp(right, "NULL")) { - value = NULL; - } else { - value = tomoyo_get_dqword(right); - if (!value) { - tomoyo_put_name(name); - goto out; - } - } - envp->name = name; - envp->value = value; - return true; -out: - return false; -} - -/** - * tomoyo_same_condition - Check for duplicated "struct tomoyo_condition" entry. - * - * @a: Pointer to "struct tomoyo_condition". - * @b: Pointer to "struct tomoyo_condition". - * - * Returns true if @a == @b, false otherwise. - */ -static inline bool tomoyo_same_condition(const struct tomoyo_condition *a, - const struct tomoyo_condition *b) -{ - return a->size == b->size && a->condc == b->condc && - a->numbers_count == b->numbers_count && - a->names_count == b->names_count && - a->argc == b->argc && a->envc == b->envc && - a->grant_log == b->grant_log && a->transit == b->transit && - !memcmp(a + 1, b + 1, a->size - sizeof(*a)); -} - -/** - * tomoyo_condition_type - Get condition type. - * - * @word: Keyword string. - * - * Returns one of values in "enum tomoyo_conditions_index" on success, - * TOMOYO_MAX_CONDITION_KEYWORD otherwise. - */ -static u8 tomoyo_condition_type(const char *word) -{ - u8 i; - for (i = 0; i < TOMOYO_MAX_CONDITION_KEYWORD; i++) { - if (!strcmp(word, tomoyo_condition_keyword[i])) - break; - } - return i; -} - -/* Define this to enable debug mode. */ -/* #define DEBUG_CONDITION */ - -#ifdef DEBUG_CONDITION -#define dprintk printk -#else -#define dprintk(...) do { } while (0) -#endif - -/** - * tomoyo_commit_condition - Commit "struct tomoyo_condition". - * - * @entry: Pointer to "struct tomoyo_condition". - * - * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise. - * - * This function merges duplicated entries. This function returns NULL if - * @entry is not duplicated but memory quota for policy has exceeded. - */ -static struct tomoyo_condition *tomoyo_commit_condition -(struct tomoyo_condition *entry) -{ - struct tomoyo_condition *ptr; - bool found = false; - if (mutex_lock_interruptible(&tomoyo_policy_lock)) { - dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__); - ptr = NULL; - found = true; - goto out; - } - list_for_each_entry(ptr, &tomoyo_condition_list, head.list) { - if (!tomoyo_same_condition(ptr, entry) || - atomic_read(&ptr->head.users) == TOMOYO_GC_IN_PROGRESS) - continue; - /* Same entry found. Share this entry. */ - atomic_inc(&ptr->head.users); - found = true; - break; - } - if (!found) { - if (tomoyo_memory_ok(entry)) { - atomic_set(&entry->head.users, 1); - list_add(&entry->head.list, &tomoyo_condition_list); - } else { - found = true; - ptr = NULL; - } - } - mutex_unlock(&tomoyo_policy_lock); -out: - if (found) { - tomoyo_del_condition(&entry->head.list); - kfree(entry); - entry = ptr; - } - return entry; -} - -/** - * tomoyo_get_transit_preference - Parse domain transition preference for execve(). - * - * @param: Pointer to "struct tomoyo_acl_param". - * @e: Pointer to "struct tomoyo_condition". - * - * Returns the condition string part. - */ -static char *tomoyo_get_transit_preference(struct tomoyo_acl_param *param, - struct tomoyo_condition *e) -{ - char * const pos = param->data; - bool flag; - if (*pos == '<') { - e->transit = tomoyo_get_domainname(param); - goto done; - } - { - char *cp = strchr(pos, ' '); - if (cp) - *cp = '\0'; - flag = tomoyo_correct_path(pos) || !strcmp(pos, "keep") || - !strcmp(pos, "initialize") || !strcmp(pos, "reset") || - !strcmp(pos, "child") || !strcmp(pos, "parent"); - if (cp) - *cp = ' '; - } - if (!flag) - return pos; - e->transit = tomoyo_get_name(tomoyo_read_token(param)); -done: - if (e->transit) - return param->data; - /* - * Return a bad read-only condition string that will let - * tomoyo_get_condition() return NULL. - */ - return "/"; -} - -/** - * tomoyo_get_condition - Parse condition part. - * - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns pointer to "struct tomoyo_condition" on success, NULL otherwise. - */ -struct tomoyo_condition *tomoyo_get_condition(struct tomoyo_acl_param *param) -{ - struct tomoyo_condition *entry = NULL; - struct tomoyo_condition_element *condp = NULL; - struct tomoyo_number_union *numbers_p = NULL; - struct tomoyo_name_union *names_p = NULL; - struct tomoyo_argv *argv = NULL; - struct tomoyo_envp *envp = NULL; - struct tomoyo_condition e = { }; - char * const start_of_string = - tomoyo_get_transit_preference(param, &e); - char * const end_of_string = start_of_string + strlen(start_of_string); - char *pos; -rerun: - pos = start_of_string; - while (1) { - u8 left = -1; - u8 right = -1; - char *left_word = pos; - char *cp; - char *right_word; - bool is_not; - if (!*left_word) - break; - /* - * Since left-hand condition does not allow use of "path_group" - * or "number_group" and environment variable's names do not - * accept '=', it is guaranteed that the original line consists - * of one or more repetition of $left$operator$right blocks - * where "$left is free from '=' and ' '" and "$operator is - * either '=' or '!='" and "$right is free from ' '". - * Therefore, we can reconstruct the original line at the end - * of dry run even if we overwrite $operator with '\0'. - */ - cp = strchr(pos, ' '); - if (cp) { - *cp = '\0'; /* Will restore later. */ - pos = cp + 1; - } else { - pos = ""; - } - right_word = strchr(left_word, '='); - if (!right_word || right_word == left_word) - goto out; - is_not = *(right_word - 1) == '!'; - if (is_not) - *(right_word++ - 1) = '\0'; /* Will restore later. */ - else if (*(right_word + 1) != '=') - *right_word++ = '\0'; /* Will restore later. */ - else - goto out; - dprintk(KERN_WARNING "%u: <%s>%s=<%s>\n", __LINE__, left_word, - is_not ? "!" : "", right_word); - if (!strcmp(left_word, "grant_log")) { - if (entry) { - if (is_not || - entry->grant_log != TOMOYO_GRANTLOG_AUTO) - goto out; - else if (!strcmp(right_word, "yes")) - entry->grant_log = TOMOYO_GRANTLOG_YES; - else if (!strcmp(right_word, "no")) - entry->grant_log = TOMOYO_GRANTLOG_NO; - else - goto out; - } - continue; - } - if (!strncmp(left_word, "exec.argv[", 10)) { - if (!argv) { - e.argc++; - e.condc++; - } else { - e.argc--; - e.condc--; - left = TOMOYO_ARGV_ENTRY; - argv->is_not = is_not; - if (!tomoyo_parse_argv(left_word + 10, - right_word, argv++)) - goto out; - } - goto store_value; - } - if (!strncmp(left_word, "exec.envp[\"", 11)) { - if (!envp) { - e.envc++; - e.condc++; - } else { - e.envc--; - e.condc--; - left = TOMOYO_ENVP_ENTRY; - envp->is_not = is_not; - if (!tomoyo_parse_envp(left_word + 11, - right_word, envp++)) - goto out; - } - goto store_value; - } - left = tomoyo_condition_type(left_word); - dprintk(KERN_WARNING "%u: <%s> left=%u\n", __LINE__, left_word, - left); - if (left == TOMOYO_MAX_CONDITION_KEYWORD) { - if (!numbers_p) { - e.numbers_count++; - } else { - e.numbers_count--; - left = TOMOYO_NUMBER_UNION; - param->data = left_word; - if (*left_word == '@' || - !tomoyo_parse_number_union(param, - numbers_p++)) - goto out; - } - } - if (!condp) - e.condc++; - else - e.condc--; - if (left == TOMOYO_EXEC_REALPATH || - left == TOMOYO_SYMLINK_TARGET) { - if (!names_p) { - e.names_count++; - } else { - e.names_count--; - right = TOMOYO_NAME_UNION; - param->data = right_word; - if (!tomoyo_parse_name_union_quoted(param, - names_p++)) - goto out; - } - goto store_value; - } - right = tomoyo_condition_type(right_word); - if (right == TOMOYO_MAX_CONDITION_KEYWORD) { - if (!numbers_p) { - e.numbers_count++; - } else { - e.numbers_count--; - right = TOMOYO_NUMBER_UNION; - param->data = right_word; - if (!tomoyo_parse_number_union(param, - numbers_p++)) - goto out; - } - } -store_value: - if (!condp) { - dprintk(KERN_WARNING "%u: dry_run left=%u right=%u " - "match=%u\n", __LINE__, left, right, !is_not); - continue; - } - condp->left = left; - condp->right = right; - condp->equals = !is_not; - dprintk(KERN_WARNING "%u: left=%u right=%u match=%u\n", - __LINE__, condp->left, condp->right, - condp->equals); - condp++; - } - dprintk(KERN_INFO "%u: cond=%u numbers=%u names=%u ac=%u ec=%u\n", - __LINE__, e.condc, e.numbers_count, e.names_count, e.argc, - e.envc); - if (entry) { - BUG_ON(e.names_count | e.numbers_count | e.argc | e.envc | - e.condc); - return tomoyo_commit_condition(entry); - } - e.size = sizeof(*entry) - + e.condc * sizeof(struct tomoyo_condition_element) - + e.numbers_count * sizeof(struct tomoyo_number_union) - + e.names_count * sizeof(struct tomoyo_name_union) - + e.argc * sizeof(struct tomoyo_argv) - + e.envc * sizeof(struct tomoyo_envp); - entry = kzalloc(e.size, GFP_NOFS); - if (!entry) - goto out2; - *entry = e; - e.transit = NULL; - condp = (struct tomoyo_condition_element *) (entry + 1); - numbers_p = (struct tomoyo_number_union *) (condp + e.condc); - names_p = (struct tomoyo_name_union *) (numbers_p + e.numbers_count); - argv = (struct tomoyo_argv *) (names_p + e.names_count); - envp = (struct tomoyo_envp *) (argv + e.argc); - { - bool flag = false; - for (pos = start_of_string; pos < end_of_string; pos++) { - if (*pos) - continue; - if (flag) /* Restore " ". */ - *pos = ' '; - else if (*(pos + 1) == '=') /* Restore "!=". */ - *pos = '!'; - else /* Restore "=". */ - *pos = '='; - flag = !flag; - } - } - goto rerun; -out: - dprintk(KERN_WARNING "%u: %s failed\n", __LINE__, __func__); - if (entry) { - tomoyo_del_condition(&entry->head.list); - kfree(entry); - } -out2: - tomoyo_put_name(e.transit); - return NULL; -} - -/** - * tomoyo_get_attributes - Revalidate "struct inode". - * - * @obj: Pointer to "struct tomoyo_obj_info". - * - * Returns nothing. - */ -void tomoyo_get_attributes(struct tomoyo_obj_info *obj) -{ - u8 i; - struct dentry *dentry = NULL; - - for (i = 0; i < TOMOYO_MAX_PATH_STAT; i++) { - struct inode *inode; - switch (i) { - case TOMOYO_PATH1: - dentry = obj->path1.dentry; - if (!dentry) - continue; - break; - case TOMOYO_PATH2: - dentry = obj->path2.dentry; - if (!dentry) - continue; - break; - default: - if (!dentry) - continue; - dentry = dget_parent(dentry); - break; - } - inode = dentry->d_inode; - if (inode) { - struct tomoyo_mini_stat *stat = &obj->stat[i]; - stat->uid = inode->i_uid; - stat->gid = inode->i_gid; - stat->ino = inode->i_ino; - stat->mode = inode->i_mode; - stat->dev = inode->i_sb->s_dev; - stat->rdev = inode->i_rdev; - obj->stat_valid[i] = true; - } - if (i & 1) /* i == TOMOYO_PATH1_PARENT || - i == TOMOYO_PATH2_PARENT */ - dput(dentry); - } -} - -/** - * tomoyo_condition - Check condition part. - * - * @r: Pointer to "struct tomoyo_request_info". - * @cond: Pointer to "struct tomoyo_condition". Maybe NULL. - * - * Returns true on success, false otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -bool tomoyo_condition(struct tomoyo_request_info *r, - const struct tomoyo_condition *cond) -{ - u32 i; - unsigned long min_v[2] = { 0, 0 }; - unsigned long max_v[2] = { 0, 0 }; - const struct tomoyo_condition_element *condp; - const struct tomoyo_number_union *numbers_p; - const struct tomoyo_name_union *names_p; - const struct tomoyo_argv *argv; - const struct tomoyo_envp *envp; - struct tomoyo_obj_info *obj; - u16 condc; - u16 argc; - u16 envc; - struct linux_binprm *bprm = NULL; - if (!cond) - return true; - condc = cond->condc; - argc = cond->argc; - envc = cond->envc; - obj = r->obj; - if (r->ee) - bprm = r->ee->bprm; - if (!bprm && (argc || envc)) - return false; - condp = (struct tomoyo_condition_element *) (cond + 1); - numbers_p = (const struct tomoyo_number_union *) (condp + condc); - names_p = (const struct tomoyo_name_union *) - (numbers_p + cond->numbers_count); - argv = (const struct tomoyo_argv *) (names_p + cond->names_count); - envp = (const struct tomoyo_envp *) (argv + argc); - for (i = 0; i < condc; i++) { - const bool match = condp->equals; - const u8 left = condp->left; - const u8 right = condp->right; - bool is_bitop[2] = { false, false }; - u8 j; - condp++; - /* Check argv[] and envp[] later. */ - if (left == TOMOYO_ARGV_ENTRY || left == TOMOYO_ENVP_ENTRY) - continue; - /* Check string expressions. */ - if (right == TOMOYO_NAME_UNION) { - const struct tomoyo_name_union *ptr = names_p++; - switch (left) { - struct tomoyo_path_info *symlink; - struct tomoyo_execve *ee; - struct file *file; - case TOMOYO_SYMLINK_TARGET: - symlink = obj ? obj->symlink_target : NULL; - if (!symlink || - !tomoyo_compare_name_union(symlink, ptr) - == match) - goto out; - break; - case TOMOYO_EXEC_REALPATH: - ee = r->ee; - file = ee ? ee->bprm->file : NULL; - if (!tomoyo_scan_exec_realpath(file, ptr, - match)) - goto out; - break; - } - continue; - } - /* Check numeric or bit-op expressions. */ - for (j = 0; j < 2; j++) { - const u8 index = j ? right : left; - unsigned long value = 0; - switch (index) { - case TOMOYO_TASK_UID: - value = current_uid(); - break; - case TOMOYO_TASK_EUID: - value = current_euid(); - break; - case TOMOYO_TASK_SUID: - value = current_suid(); - break; - case TOMOYO_TASK_FSUID: - value = current_fsuid(); - break; - case TOMOYO_TASK_GID: - value = current_gid(); - break; - case TOMOYO_TASK_EGID: - value = current_egid(); - break; - case TOMOYO_TASK_SGID: - value = current_sgid(); - break; - case TOMOYO_TASK_FSGID: - value = current_fsgid(); - break; - case TOMOYO_TASK_PID: - value = tomoyo_sys_getpid(); - break; - case TOMOYO_TASK_PPID: - value = tomoyo_sys_getppid(); - break; - case TOMOYO_TYPE_IS_SOCKET: - value = S_IFSOCK; - break; - case TOMOYO_TYPE_IS_SYMLINK: - value = S_IFLNK; - break; - case TOMOYO_TYPE_IS_FILE: - value = S_IFREG; - break; - case TOMOYO_TYPE_IS_BLOCK_DEV: - value = S_IFBLK; - break; - case TOMOYO_TYPE_IS_DIRECTORY: - value = S_IFDIR; - break; - case TOMOYO_TYPE_IS_CHAR_DEV: - value = S_IFCHR; - break; - case TOMOYO_TYPE_IS_FIFO: - value = S_IFIFO; - break; - case TOMOYO_MODE_SETUID: - value = S_ISUID; - break; - case TOMOYO_MODE_SETGID: - value = S_ISGID; - break; - case TOMOYO_MODE_STICKY: - value = S_ISVTX; - break; - case TOMOYO_MODE_OWNER_READ: - value = S_IRUSR; - break; - case TOMOYO_MODE_OWNER_WRITE: - value = S_IWUSR; - break; - case TOMOYO_MODE_OWNER_EXECUTE: - value = S_IXUSR; - break; - case TOMOYO_MODE_GROUP_READ: - value = S_IRGRP; - break; - case TOMOYO_MODE_GROUP_WRITE: - value = S_IWGRP; - break; - case TOMOYO_MODE_GROUP_EXECUTE: - value = S_IXGRP; - break; - case TOMOYO_MODE_OTHERS_READ: - value = S_IROTH; - break; - case TOMOYO_MODE_OTHERS_WRITE: - value = S_IWOTH; - break; - case TOMOYO_MODE_OTHERS_EXECUTE: - value = S_IXOTH; - break; - case TOMOYO_EXEC_ARGC: - if (!bprm) - goto out; - value = bprm->argc; - break; - case TOMOYO_EXEC_ENVC: - if (!bprm) - goto out; - value = bprm->envc; - break; - case TOMOYO_NUMBER_UNION: - /* Fetch values later. */ - break; - default: - if (!obj) - goto out; - if (!obj->validate_done) { - tomoyo_get_attributes(obj); - obj->validate_done = true; - } - { - u8 stat_index; - struct tomoyo_mini_stat *stat; - switch (index) { - case TOMOYO_PATH1_UID: - case TOMOYO_PATH1_GID: - case TOMOYO_PATH1_INO: - case TOMOYO_PATH1_MAJOR: - case TOMOYO_PATH1_MINOR: - case TOMOYO_PATH1_TYPE: - case TOMOYO_PATH1_DEV_MAJOR: - case TOMOYO_PATH1_DEV_MINOR: - case TOMOYO_PATH1_PERM: - stat_index = TOMOYO_PATH1; - break; - case TOMOYO_PATH2_UID: - case TOMOYO_PATH2_GID: - case TOMOYO_PATH2_INO: - case TOMOYO_PATH2_MAJOR: - case TOMOYO_PATH2_MINOR: - case TOMOYO_PATH2_TYPE: - case TOMOYO_PATH2_DEV_MAJOR: - case TOMOYO_PATH2_DEV_MINOR: - case TOMOYO_PATH2_PERM: - stat_index = TOMOYO_PATH2; - break; - case TOMOYO_PATH1_PARENT_UID: - case TOMOYO_PATH1_PARENT_GID: - case TOMOYO_PATH1_PARENT_INO: - case TOMOYO_PATH1_PARENT_PERM: - stat_index = - TOMOYO_PATH1_PARENT; - break; - case TOMOYO_PATH2_PARENT_UID: - case TOMOYO_PATH2_PARENT_GID: - case TOMOYO_PATH2_PARENT_INO: - case TOMOYO_PATH2_PARENT_PERM: - stat_index = - TOMOYO_PATH2_PARENT; - break; - default: - goto out; - } - if (!obj->stat_valid[stat_index]) - goto out; - stat = &obj->stat[stat_index]; - switch (index) { - case TOMOYO_PATH1_UID: - case TOMOYO_PATH2_UID: - case TOMOYO_PATH1_PARENT_UID: - case TOMOYO_PATH2_PARENT_UID: - value = stat->uid; - break; - case TOMOYO_PATH1_GID: - case TOMOYO_PATH2_GID: - case TOMOYO_PATH1_PARENT_GID: - case TOMOYO_PATH2_PARENT_GID: - value = stat->gid; - break; - case TOMOYO_PATH1_INO: - case TOMOYO_PATH2_INO: - case TOMOYO_PATH1_PARENT_INO: - case TOMOYO_PATH2_PARENT_INO: - value = stat->ino; - break; - case TOMOYO_PATH1_MAJOR: - case TOMOYO_PATH2_MAJOR: - value = MAJOR(stat->dev); - break; - case TOMOYO_PATH1_MINOR: - case TOMOYO_PATH2_MINOR: - value = MINOR(stat->dev); - break; - case TOMOYO_PATH1_TYPE: - case TOMOYO_PATH2_TYPE: - value = stat->mode & S_IFMT; - break; - case TOMOYO_PATH1_DEV_MAJOR: - case TOMOYO_PATH2_DEV_MAJOR: - value = MAJOR(stat->rdev); - break; - case TOMOYO_PATH1_DEV_MINOR: - case TOMOYO_PATH2_DEV_MINOR: - value = MINOR(stat->rdev); - break; - case TOMOYO_PATH1_PERM: - case TOMOYO_PATH2_PERM: - case TOMOYO_PATH1_PARENT_PERM: - case TOMOYO_PATH2_PARENT_PERM: - value = stat->mode & S_IALLUGO; - break; - } - } - break; - } - max_v[j] = value; - min_v[j] = value; - switch (index) { - case TOMOYO_MODE_SETUID: - case TOMOYO_MODE_SETGID: - case TOMOYO_MODE_STICKY: - case TOMOYO_MODE_OWNER_READ: - case TOMOYO_MODE_OWNER_WRITE: - case TOMOYO_MODE_OWNER_EXECUTE: - case TOMOYO_MODE_GROUP_READ: - case TOMOYO_MODE_GROUP_WRITE: - case TOMOYO_MODE_GROUP_EXECUTE: - case TOMOYO_MODE_OTHERS_READ: - case TOMOYO_MODE_OTHERS_WRITE: - case TOMOYO_MODE_OTHERS_EXECUTE: - is_bitop[j] = true; - } - } - if (left == TOMOYO_NUMBER_UNION) { - /* Fetch values now. */ - const struct tomoyo_number_union *ptr = numbers_p++; - min_v[0] = ptr->values[0]; - max_v[0] = ptr->values[1]; - } - if (right == TOMOYO_NUMBER_UNION) { - /* Fetch values now. */ - const struct tomoyo_number_union *ptr = numbers_p++; - if (ptr->group) { - if (tomoyo_number_matches_group(min_v[0], - max_v[0], - ptr->group) - == match) - continue; - } else { - if ((min_v[0] <= ptr->values[1] && - max_v[0] >= ptr->values[0]) == match) - continue; - } - goto out; - } - /* - * Bit operation is valid only when counterpart value - * represents permission. - */ - if (is_bitop[0] && is_bitop[1]) { - goto out; - } else if (is_bitop[0]) { - switch (right) { - case TOMOYO_PATH1_PERM: - case TOMOYO_PATH1_PARENT_PERM: - case TOMOYO_PATH2_PERM: - case TOMOYO_PATH2_PARENT_PERM: - if (!(max_v[0] & max_v[1]) == !match) - continue; - } - goto out; - } else if (is_bitop[1]) { - switch (left) { - case TOMOYO_PATH1_PERM: - case TOMOYO_PATH1_PARENT_PERM: - case TOMOYO_PATH2_PERM: - case TOMOYO_PATH2_PARENT_PERM: - if (!(max_v[0] & max_v[1]) == !match) - continue; - } - goto out; - } - /* Normal value range comparison. */ - if ((min_v[0] <= max_v[1] && max_v[0] >= min_v[1]) == match) - continue; -out: - return false; - } - /* Check argv[] and envp[] now. */ - if (r->ee && (argc || envc)) - return tomoyo_scan_bprm(r->ee, argc, argv, envc, envp); - return true; -} diff --git a/ANDROID_3.4.5/security/tomoyo/domain.c b/ANDROID_3.4.5/security/tomoyo/domain.c deleted file mode 100644 index 38651454..00000000 --- a/ANDROID_3.4.5/security/tomoyo/domain.c +++ /dev/null @@ -1,901 +0,0 @@ -/* - * security/tomoyo/domain.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include "common.h" -#include <linux/binfmts.h> -#include <linux/slab.h> - -/* Variables definitions.*/ - -/* The initial domain. */ -struct tomoyo_domain_info tomoyo_kernel_domain; - -/** - * tomoyo_update_policy - Update an entry for exception policy. - * - * @new_entry: Pointer to "struct tomoyo_acl_info". - * @size: Size of @new_entry in bytes. - * @param: Pointer to "struct tomoyo_acl_param". - * @check_duplicate: Callback function to find duplicated entry. - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, - struct tomoyo_acl_param *param, - bool (*check_duplicate) (const struct tomoyo_acl_head - *, - const struct tomoyo_acl_head - *)) -{ - int error = param->is_delete ? -ENOENT : -ENOMEM; - struct tomoyo_acl_head *entry; - struct list_head *list = param->list; - - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - return -ENOMEM; - list_for_each_entry_rcu(entry, list, list) { - if (entry->is_deleted == TOMOYO_GC_IN_PROGRESS) - continue; - if (!check_duplicate(entry, new_entry)) - continue; - entry->is_deleted = param->is_delete; - error = 0; - break; - } - if (error && !param->is_delete) { - entry = tomoyo_commit_ok(new_entry, size); - if (entry) { - list_add_tail_rcu(&entry->list, list); - error = 0; - } - } - mutex_unlock(&tomoyo_policy_lock); - return error; -} - -/** - * tomoyo_same_acl_head - Check for duplicated "struct tomoyo_acl_info" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * - * Returns true if @a == @b, false otherwise. - */ -static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a, - const struct tomoyo_acl_info *b) -{ - return a->type == b->type && a->cond == b->cond; -} - -/** - * tomoyo_update_domain - Update an entry for domain policy. - * - * @new_entry: Pointer to "struct tomoyo_acl_info". - * @size: Size of @new_entry in bytes. - * @param: Pointer to "struct tomoyo_acl_param". - * @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, - struct tomoyo_acl_param *param, - bool (*check_duplicate) (const struct tomoyo_acl_info - *, - const struct tomoyo_acl_info - *), - bool (*merge_duplicate) (struct tomoyo_acl_info *, - struct tomoyo_acl_info *, - const bool)) -{ - const bool is_delete = param->is_delete; - int error = is_delete ? -ENOENT : -ENOMEM; - struct tomoyo_acl_info *entry; - struct list_head * const list = param->list; - - if (param->data[0]) { - new_entry->cond = tomoyo_get_condition(param); - if (!new_entry->cond) - return -EINVAL; - /* - * Domain transition preference is allowed for only - * "file execute" entries. - */ - if (new_entry->cond->transit && - !(new_entry->type == TOMOYO_TYPE_PATH_ACL && - container_of(new_entry, struct tomoyo_path_acl, head) - ->perm == 1 << TOMOYO_TYPE_EXECUTE)) - goto out; - } - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - goto out; - list_for_each_entry_rcu(entry, list, list) { - if (entry->is_deleted == TOMOYO_GC_IN_PROGRESS) - continue; - if (!tomoyo_same_acl_head(entry, new_entry) || - !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, list); - error = 0; - } - } - mutex_unlock(&tomoyo_policy_lock); -out: - tomoyo_put_condition(new_entry->cond); - return error; -} - -/** - * tomoyo_check_acl - Do permission check. - * - * @r: Pointer to "struct tomoyo_request_info". - * @check_entry: Callback function to check type specific parameters. - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -void tomoyo_check_acl(struct tomoyo_request_info *r, - bool (*check_entry) (struct tomoyo_request_info *, - const struct tomoyo_acl_info *)) -{ - const struct tomoyo_domain_info *domain = r->domain; - struct tomoyo_acl_info *ptr; - bool retried = false; - const struct list_head *list = &domain->acl_info_list; - -retry: - list_for_each_entry_rcu(ptr, list, list) { - if (ptr->is_deleted || ptr->type != r->param_type) - continue; - if (!check_entry(r, ptr)) - continue; - if (!tomoyo_condition(r, ptr->cond)) - continue; - r->matched_acl = ptr; - r->granted = true; - return; - } - if (!retried) { - retried = true; - list = &domain->ns->acl_group[domain->group]; - goto retry; - } - r->granted = false; -} - -/* The list for "struct tomoyo_domain_info". */ -LIST_HEAD(tomoyo_domain_list); - -/** - * tomoyo_last_word - Get last component of a domainname. - * - * @name: Domainname to check. - * - * Returns the last word of @domainname. - */ -static const char *tomoyo_last_word(const char *name) -{ - const char *cp = strrchr(name, ' '); - if (cp) - return cp + 1; - return name; -} - -/** - * tomoyo_same_transition_control - Check for duplicated "struct tomoyo_transition_control" entry. - * - * @a: Pointer to "struct tomoyo_acl_head". - * @b: Pointer to "struct tomoyo_acl_head". - * - * Returns true if @a == @b, false otherwise. - */ -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), - head); - const struct tomoyo_transition_control *p2 = container_of(b, - typeof(*p2), - head); - return p1->type == p2->type && p1->is_last_name == p2->is_last_name - && p1->domainname == p2->domainname - && p1->program == p2->program; -} - -/** - * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list. - * - * @param: Pointer to "struct tomoyo_acl_param". - * @type: Type of this entry. - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_write_transition_control(struct tomoyo_acl_param *param, - const u8 type) -{ - struct tomoyo_transition_control e = { .type = type }; - int error = param->is_delete ? -ENOENT : -ENOMEM; - char *program = param->data; - char *domainname = strstr(program, " from "); - if (domainname) { - *domainname = '\0'; - domainname += 6; - } else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP || - type == TOMOYO_TRANSITION_CONTROL_KEEP) { - domainname = program; - program = NULL; - } - if (program && strcmp(program, "any")) { - if (!tomoyo_correct_path(program)) - return -EINVAL; - e.program = tomoyo_get_name(program); - if (!e.program) - goto out; - } - if (domainname && strcmp(domainname, "any")) { - if (!tomoyo_correct_domain(domainname)) { - if (!tomoyo_correct_path(domainname)) - goto out; - e.is_last_name = true; - } - e.domainname = tomoyo_get_name(domainname); - if (!e.domainname) - goto out; - } - param->list = ¶m->ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL]; - error = tomoyo_update_policy(&e.head, sizeof(e), param, - tomoyo_same_transition_control); -out: - tomoyo_put_name(e.domainname); - tomoyo_put_name(e.program); - return error; -} - -/** - * tomoyo_scan_transition - Try to find specific domain transition type. - * - * @list: Pointer to "struct list_head". - * @domainname: The name of current domain. - * @program: The name of requested program. - * @last_name: The last component of @domainname. - * @type: One of values in "enum tomoyo_transition_type". - * - * Returns true if found one, false otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static inline bool tomoyo_scan_transition -(const struct list_head *list, const struct tomoyo_path_info *domainname, - const struct tomoyo_path_info *program, const char *last_name, - const enum tomoyo_transition_type type) -{ - const struct tomoyo_transition_control *ptr; - list_for_each_entry_rcu(ptr, list, head.list) { - if (ptr->head.is_deleted || ptr->type != type) - continue; - if (ptr->domainname) { - if (!ptr->is_last_name) { - if (ptr->domainname != domainname) - continue; - } else { - /* - * Use direct strcmp() since this is - * unlikely used. - */ - if (strcmp(ptr->domainname->name, last_name)) - continue; - } - } - if (ptr->program && tomoyo_pathcmp(ptr->program, program)) - continue; - return true; - } - return false; -} - -/** - * tomoyo_transition_type - Get domain transition type. - * - * @ns: Pointer to "struct tomoyo_policy_namespace". - * @domainname: The name of current domain. - * @program: The name of requested program. - * - * Returns TOMOYO_TRANSITION_CONTROL_TRANSIT if executing @program causes - * domain transition across namespaces, TOMOYO_TRANSITION_CONTROL_INITIALIZE if - * executing @program reinitializes domain transition within that namespace, - * TOMOYO_TRANSITION_CONTROL_KEEP if executing @program stays at @domainname , - * others otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static enum tomoyo_transition_type tomoyo_transition_type -(const struct tomoyo_policy_namespace *ns, - const struct tomoyo_path_info *domainname, - const struct tomoyo_path_info *program) -{ - const char *last_name = tomoyo_last_word(domainname->name); - enum tomoyo_transition_type type = TOMOYO_TRANSITION_CONTROL_NO_RESET; - while (type < TOMOYO_MAX_TRANSITION_TYPE) { - const struct list_head * const list = - &ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL]; - if (!tomoyo_scan_transition(list, domainname, program, - last_name, type)) { - type++; - continue; - } - if (type != TOMOYO_TRANSITION_CONTROL_NO_RESET && - type != TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) - break; - /* - * Do not check for reset_domain if no_reset_domain matched. - * Do not check for initialize_domain if no_initialize_domain - * matched. - */ - type++; - type++; - } - return type; -} - -/** - * tomoyo_same_aggregator - Check for duplicated "struct tomoyo_aggregator" entry. - * - * @a: Pointer to "struct tomoyo_acl_head". - * @b: Pointer to "struct tomoyo_acl_head". - * - * Returns true if @a == @b, false otherwise. - */ -static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a, - const struct tomoyo_acl_head *b) -{ - 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_write_aggregator - Write "struct tomoyo_aggregator" list. - * - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -int tomoyo_write_aggregator(struct tomoyo_acl_param *param) -{ - struct tomoyo_aggregator e = { }; - int error = param->is_delete ? -ENOENT : -ENOMEM; - const char *original_name = tomoyo_read_token(param); - const char *aggregated_name = tomoyo_read_token(param); - if (!tomoyo_correct_word(original_name) || - !tomoyo_correct_path(aggregated_name)) - return -EINVAL; - e.original_name = tomoyo_get_name(original_name); - e.aggregated_name = tomoyo_get_name(aggregated_name); - if (!e.original_name || !e.aggregated_name || - e.aggregated_name->is_patterned) /* No patterns allowed. */ - goto out; - param->list = ¶m->ns->policy_list[TOMOYO_ID_AGGREGATOR]; - error = tomoyo_update_policy(&e.head, sizeof(e), param, - tomoyo_same_aggregator); -out: - tomoyo_put_name(e.original_name); - tomoyo_put_name(e.aggregated_name); - return error; -} - -/** - * tomoyo_find_namespace - Find specified namespace. - * - * @name: Name of namespace to find. - * @len: Length of @name. - * - * Returns pointer to "struct tomoyo_policy_namespace" if found, - * NULL otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static struct tomoyo_policy_namespace *tomoyo_find_namespace -(const char *name, const unsigned int len) -{ - struct tomoyo_policy_namespace *ns; - list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { - if (strncmp(name, ns->name, len) || - (name[len] && name[len] != ' ')) - continue; - return ns; - } - return NULL; -} - -/** - * tomoyo_assign_namespace - Create a new namespace. - * - * @domainname: Name of namespace to create. - * - * Returns pointer to "struct tomoyo_policy_namespace" on success, - * NULL otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname) -{ - struct tomoyo_policy_namespace *ptr; - struct tomoyo_policy_namespace *entry; - const char *cp = domainname; - unsigned int len = 0; - while (*cp && *cp++ != ' ') - len++; - ptr = tomoyo_find_namespace(domainname, len); - if (ptr) - return ptr; - if (len >= TOMOYO_EXEC_TMPSIZE - 10 || !tomoyo_domain_def(domainname)) - return NULL; - entry = kzalloc(sizeof(*entry) + len + 1, GFP_NOFS); - if (!entry) - return NULL; - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - goto out; - ptr = tomoyo_find_namespace(domainname, len); - if (!ptr && tomoyo_memory_ok(entry)) { - char *name = (char *) (entry + 1); - ptr = entry; - memmove(name, domainname, len); - name[len] = '\0'; - entry->name = name; - tomoyo_init_policy_namespace(entry); - entry = NULL; - } - mutex_unlock(&tomoyo_policy_lock); -out: - kfree(entry); - return ptr; -} - -/** - * tomoyo_namespace_jump - Check for namespace jump. - * - * @domainname: Name of domain. - * - * Returns true if namespace differs, false otherwise. - */ -static bool tomoyo_namespace_jump(const char *domainname) -{ - const char *namespace = tomoyo_current_namespace()->name; - const int len = strlen(namespace); - return strncmp(domainname, namespace, len) || - (domainname[len] && domainname[len] != ' '); -} - -/** - * tomoyo_assign_domain - Create a domain or a namespace. - * - * @domainname: The name of domain. - * @transit: True if transit to domain found or created. - * - * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, - const bool transit) -{ - struct tomoyo_domain_info e = { }; - struct tomoyo_domain_info *entry = tomoyo_find_domain(domainname); - bool created = false; - if (entry) { - if (transit) { - /* - * Since namespace is created at runtime, profiles may - * not be created by the moment the process transits to - * that domain. Do not perform domain transition if - * profile for that domain is not yet created. - */ - if (tomoyo_policy_loaded && - !entry->ns->profile_ptr[entry->profile]) - return NULL; - } - return entry; - } - /* Requested domain does not exist. */ - /* Don't create requested domain if domainname is invalid. */ - if (strlen(domainname) >= TOMOYO_EXEC_TMPSIZE - 10 || - !tomoyo_correct_domain(domainname)) - return NULL; - /* - * Since definition of profiles and acl_groups may differ across - * namespaces, do not inherit "use_profile" and "use_group" settings - * by automatically creating requested domain upon domain transition. - */ - if (transit && tomoyo_namespace_jump(domainname)) - return NULL; - e.ns = tomoyo_assign_namespace(domainname); - if (!e.ns) - return NULL; - /* - * "use_profile" and "use_group" settings for automatically created - * domains are inherited from current domain. These are 0 for manually - * created domains. - */ - if (transit) { - const struct tomoyo_domain_info *domain = tomoyo_domain(); - e.profile = domain->profile; - e.group = domain->group; - } - e.domainname = tomoyo_get_name(domainname); - if (!e.domainname) - return NULL; - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - goto out; - entry = tomoyo_find_domain(domainname); - if (!entry) { - entry = tomoyo_commit_ok(&e, sizeof(e)); - if (entry) { - INIT_LIST_HEAD(&entry->acl_info_list); - list_add_tail_rcu(&entry->list, &tomoyo_domain_list); - created = true; - } - } - mutex_unlock(&tomoyo_policy_lock); -out: - tomoyo_put_name(e.domainname); - if (entry && transit) { - if (created) { - struct tomoyo_request_info r; - tomoyo_init_request_info(&r, entry, - TOMOYO_MAC_FILE_EXECUTE); - r.granted = false; - tomoyo_write_log(&r, "use_profile %u\n", - entry->profile); - tomoyo_write_log(&r, "use_group %u\n", entry->group); - tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES); - } - } - return entry; -} - -/** - * tomoyo_environ - Check permission for environment variable names. - * - * @ee: Pointer to "struct tomoyo_execve". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_environ(struct tomoyo_execve *ee) -{ - struct tomoyo_request_info *r = &ee->r; - struct linux_binprm *bprm = ee->bprm; - /* env_page.data is allocated by tomoyo_dump_page(). */ - struct tomoyo_page_dump env_page = { }; - char *arg_ptr; /* Size is TOMOYO_EXEC_TMPSIZE bytes */ - int arg_len = 0; - unsigned long pos = bprm->p; - int offset = pos % PAGE_SIZE; - int argv_count = bprm->argc; - int envp_count = bprm->envc; - int error = -ENOMEM; - - ee->r.type = TOMOYO_MAC_ENVIRON; - ee->r.profile = r->domain->profile; - ee->r.mode = tomoyo_get_mode(r->domain->ns, ee->r.profile, - TOMOYO_MAC_ENVIRON); - if (!r->mode || !envp_count) - return 0; - arg_ptr = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); - if (!arg_ptr) - goto out; - while (error == -ENOMEM) { - if (!tomoyo_dump_page(bprm, pos, &env_page)) - goto out; - pos += PAGE_SIZE - offset; - /* Read. */ - while (argv_count && offset < PAGE_SIZE) { - if (!env_page.data[offset++]) - argv_count--; - } - if (argv_count) { - offset = 0; - continue; - } - while (offset < PAGE_SIZE) { - const unsigned char c = env_page.data[offset++]; - - if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) { - if (c == '=') { - arg_ptr[arg_len++] = '\0'; - } else if (c == '\\') { - arg_ptr[arg_len++] = '\\'; - arg_ptr[arg_len++] = '\\'; - } else if (c > ' ' && c < 127) { - arg_ptr[arg_len++] = c; - } else { - arg_ptr[arg_len++] = '\\'; - arg_ptr[arg_len++] = (c >> 6) + '0'; - arg_ptr[arg_len++] - = ((c >> 3) & 7) + '0'; - arg_ptr[arg_len++] = (c & 7) + '0'; - } - } else { - arg_ptr[arg_len] = '\0'; - } - if (c) - continue; - if (tomoyo_env_perm(r, arg_ptr)) { - error = -EPERM; - break; - } - if (!--envp_count) { - error = 0; - break; - } - arg_len = 0; - } - offset = 0; - } -out: - if (r->mode != TOMOYO_CONFIG_ENFORCING) - error = 0; - kfree(env_page.data); - kfree(arg_ptr); - return error; -} - -/** - * tomoyo_find_next_domain - Find a domain. - * - * @bprm: Pointer to "struct linux_binprm". - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -int tomoyo_find_next_domain(struct linux_binprm *bprm) -{ - struct tomoyo_domain_info *old_domain = tomoyo_domain(); - struct tomoyo_domain_info *domain = NULL; - const char *original_name = bprm->filename; - int retval = -ENOMEM; - bool reject_on_transition_failure = false; - const struct tomoyo_path_info *candidate; - struct tomoyo_path_info exename; - struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS); - - if (!ee) - return -ENOMEM; - ee->tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); - if (!ee->tmp) { - kfree(ee); - return -ENOMEM; - } - /* ee->dump->data is allocated by tomoyo_dump_page(). */ - tomoyo_init_request_info(&ee->r, NULL, TOMOYO_MAC_FILE_EXECUTE); - ee->r.ee = ee; - ee->bprm = bprm; - ee->r.obj = &ee->obj; - ee->obj.path1 = bprm->file->f_path; - /* Get symlink's pathname of program. */ - retval = -ENOENT; - exename.name = tomoyo_realpath_nofollow(original_name); - if (!exename.name) - goto out; - tomoyo_fill_path_info(&exename); -retry: - /* Check 'aggregator' directive. */ - { - struct tomoyo_aggregator *ptr; - struct list_head *list = - &old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR]; - /* Check 'aggregator' directive. */ - candidate = &exename; - list_for_each_entry_rcu(ptr, list, head.list) { - if (ptr->head.is_deleted || - !tomoyo_path_matches_pattern(&exename, - ptr->original_name)) - continue; - candidate = ptr->aggregated_name; - break; - } - } - - /* Check execute permission. */ - retval = tomoyo_execute_permission(&ee->r, candidate); - if (retval == TOMOYO_RETRY_REQUEST) - 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 (ee->r.param.path.matched_path) - candidate = ee->r.param.path.matched_path; - - /* - * Check for domain transition preference if "file execute" matched. - * If preference is given, make do_execve() fail if domain transition - * has failed, for domain transition preference should be used with - * destination domain defined. - */ - if (ee->transition) { - const char *domainname = ee->transition->name; - reject_on_transition_failure = true; - if (!strcmp(domainname, "keep")) - goto force_keep_domain; - if (!strcmp(domainname, "child")) - goto force_child_domain; - if (!strcmp(domainname, "reset")) - goto force_reset_domain; - if (!strcmp(domainname, "initialize")) - goto force_initialize_domain; - if (!strcmp(domainname, "parent")) { - char *cp; - strncpy(ee->tmp, old_domain->domainname->name, - TOMOYO_EXEC_TMPSIZE - 1); - cp = strrchr(ee->tmp, ' '); - if (cp) - *cp = '\0'; - } else if (*domainname == '<') - strncpy(ee->tmp, domainname, TOMOYO_EXEC_TMPSIZE - 1); - else - snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", - old_domain->domainname->name, domainname); - goto force_jump_domain; - } - /* - * No domain transition preference specified. - * Calculate domain to transit to. - */ - switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname, - candidate)) { - case TOMOYO_TRANSITION_CONTROL_RESET: -force_reset_domain: - /* Transit to the root of specified namespace. */ - snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", - candidate->name); - /* - * Make do_execve() fail if domain transition across namespaces - * has failed. - */ - reject_on_transition_failure = true; - break; - case TOMOYO_TRANSITION_CONTROL_INITIALIZE: -force_initialize_domain: - /* Transit to the child of current namespace's root. */ - snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", - old_domain->ns->name, candidate->name); - break; - case TOMOYO_TRANSITION_CONTROL_KEEP: -force_keep_domain: - /* Keep current domain. */ - domain = old_domain; - break; - default: - if (old_domain == &tomoyo_kernel_domain && - !tomoyo_policy_loaded) { - /* - * Needn't to transit from kernel domain before - * starting /sbin/init. But transit from kernel domain - * if executing initializers because they might start - * before /sbin/init. - */ - domain = old_domain; - break; - } -force_child_domain: - /* Normal domain transition. */ - snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", - old_domain->domainname->name, candidate->name); - break; - } -force_jump_domain: - if (!domain) - domain = tomoyo_assign_domain(ee->tmp, true); - if (domain) - retval = 0; - else if (reject_on_transition_failure) { - printk(KERN_WARNING "ERROR: Domain '%s' not ready.\n", - ee->tmp); - retval = -ENOMEM; - } else if (ee->r.mode == TOMOYO_CONFIG_ENFORCING) - retval = -ENOMEM; - else { - retval = 0; - if (!old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED]) { - old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED] = true; - ee->r.granted = false; - tomoyo_write_log(&ee->r, "%s", tomoyo_dif - [TOMOYO_DIF_TRANSITION_FAILED]); - printk(KERN_WARNING - "ERROR: Domain '%s' not defined.\n", ee->tmp); - } - } - out: - if (!domain) - domain = old_domain; - /* Update reference count on "struct tomoyo_domain_info". */ - atomic_inc(&domain->users); - bprm->cred->security = domain; - kfree(exename.name); - if (!retval) { - ee->r.domain = domain; - retval = tomoyo_environ(ee); - } - kfree(ee->tmp); - kfree(ee->dump.data); - kfree(ee); - return retval; -} - -/** - * tomoyo_dump_page - Dump a page to buffer. - * - * @bprm: Pointer to "struct linux_binprm". - * @pos: Location to dump. - * @dump: Poiner to "struct tomoyo_page_dump". - * - * Returns true on success, false otherwise. - */ -bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos, - struct tomoyo_page_dump *dump) -{ - struct page *page; - - /* dump->data is released by tomoyo_find_next_domain(). */ - if (!dump->data) { - dump->data = kzalloc(PAGE_SIZE, GFP_NOFS); - if (!dump->data) - return false; - } - /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */ -#ifdef CONFIG_MMU - if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0) - return false; -#else - page = bprm->page[pos / PAGE_SIZE]; -#endif - if (page != dump->page) { - const unsigned int offset = pos % PAGE_SIZE; - /* - * Maybe kmap()/kunmap() should be used here. - * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic(). - * So do I. - */ - char *kaddr = kmap_atomic(page); - - dump->page = page; - memcpy(dump->data + offset, kaddr + offset, - PAGE_SIZE - offset); - kunmap_atomic(kaddr); - } - /* Same with put_arg_page(page) in fs/exec.c */ -#ifdef CONFIG_MMU - put_page(page); -#endif - return true; -} diff --git a/ANDROID_3.4.5/security/tomoyo/environ.c b/ANDROID_3.4.5/security/tomoyo/environ.c deleted file mode 100644 index ad4c6e18..00000000 --- a/ANDROID_3.4.5/security/tomoyo/environ.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * security/tomoyo/environ.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include "common.h" - -/** - * tomoyo_check_env_acl - Check permission for environment variable's name. - * - * @r: Pointer to "struct tomoyo_request_info". - * @ptr: Pointer to "struct tomoyo_acl_info". - * - * Returns true if granted, false otherwise. - */ -static bool tomoyo_check_env_acl(struct tomoyo_request_info *r, - const struct tomoyo_acl_info *ptr) -{ - const struct tomoyo_env_acl *acl = - container_of(ptr, typeof(*acl), head); - - return tomoyo_path_matches_pattern(r->param.environ.name, acl->env); -} - -/** - * tomoyo_audit_env_log - Audit environment variable name log. - * - * @r: Pointer to "struct tomoyo_request_info". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_audit_env_log(struct tomoyo_request_info *r) -{ - return tomoyo_supervisor(r, "misc env %s\n", - r->param.environ.name->name); -} - -/** - * tomoyo_env_perm - Check permission for environment variable's name. - * - * @r: Pointer to "struct tomoyo_request_info". - * @env: The name of environment variable. - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -int tomoyo_env_perm(struct tomoyo_request_info *r, const char *env) -{ - struct tomoyo_path_info environ; - int error; - - if (!env || !*env) - return 0; - environ.name = env; - tomoyo_fill_path_info(&environ); - r->param_type = TOMOYO_TYPE_ENV_ACL; - r->param.environ.name = &environ; - do { - tomoyo_check_acl(r, tomoyo_check_env_acl); - error = tomoyo_audit_env_log(r); - } while (error == TOMOYO_RETRY_REQUEST); - return error; -} - -/** - * tomoyo_same_env_acl - Check for duplicated "struct tomoyo_env_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * - * Returns true if @a == @b, false otherwise. - */ -static bool tomoyo_same_env_acl(const struct tomoyo_acl_info *a, - const struct tomoyo_acl_info *b) -{ - const struct tomoyo_env_acl *p1 = container_of(a, typeof(*p1), head); - const struct tomoyo_env_acl *p2 = container_of(b, typeof(*p2), head); - - return p1->env == p2->env; -} - -/** - * tomoyo_write_env - Write "struct tomoyo_env_acl" list. - * - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_write_env(struct tomoyo_acl_param *param) -{ - struct tomoyo_env_acl e = { .head.type = TOMOYO_TYPE_ENV_ACL }; - int error = -ENOMEM; - const char *data = tomoyo_read_token(param); - - if (!tomoyo_correct_word(data) || strchr(data, '=')) - return -EINVAL; - e.env = tomoyo_get_name(data); - if (!e.env) - return error; - error = tomoyo_update_domain(&e.head, sizeof(e), param, - tomoyo_same_env_acl, NULL); - tomoyo_put_name(e.env); - return error; -} - -/** - * tomoyo_write_misc - Update environment variable list. - * - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_write_misc(struct tomoyo_acl_param *param) -{ - if (tomoyo_str_starts(¶m->data, "env ")) - return tomoyo_write_env(param); - return -EINVAL; -} diff --git a/ANDROID_3.4.5/security/tomoyo/file.c b/ANDROID_3.4.5/security/tomoyo/file.c deleted file mode 100644 index 40039079..00000000 --- a/ANDROID_3.4.5/security/tomoyo/file.c +++ /dev/null @@ -1,1026 +0,0 @@ -/* - * security/tomoyo/file.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include "common.h" -#include <linux/slab.h> - -/* - * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index". - */ -static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { - [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, - [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, - [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN, - [TOMOYO_TYPE_APPEND] = TOMOYO_MAC_FILE_OPEN, - [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK, - [TOMOYO_TYPE_GETATTR] = TOMOYO_MAC_FILE_GETATTR, - [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR, - [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE, - [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK, - [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT, - [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, -}; - -/* - * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index". - */ -const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = { - [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, - [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR, -}; - -/* - * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index". - */ -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, -}; - -/* - * Mapping table from "enum tomoyo_path_number_acl_index" to - * "enum tomoyo_mac_index". - */ -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, -}; - -/** - * tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union". - * - * @ptr: Pointer to "struct tomoyo_name_union". - * - * Returns nothing. - */ -void tomoyo_put_name_union(struct tomoyo_name_union *ptr) -{ - tomoyo_put_group(ptr->group); - tomoyo_put_name(ptr->filename); -} - -/** - * tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not. - * - * @name: Pointer to "struct tomoyo_path_info". - * @ptr: Pointer to "struct tomoyo_name_union". - * - * Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise. - */ -const struct tomoyo_path_info * -tomoyo_compare_name_union(const struct tomoyo_path_info *name, - const struct tomoyo_name_union *ptr) -{ - if (ptr->group) - return tomoyo_path_matches_group(name, ptr->group); - if (tomoyo_path_matches_pattern(name, ptr->filename)) - return ptr->filename; - return NULL; -} - -/** - * tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union". - * - * @ptr: Pointer to "struct tomoyo_number_union". - * - * Returns nothing. - */ -void tomoyo_put_number_union(struct tomoyo_number_union *ptr) -{ - tomoyo_put_group(ptr->group); -} - -/** - * tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not. - * - * @value: Number to check. - * @ptr: Pointer to "struct tomoyo_number_union". - * - * Returns true if @value matches @ptr, false otherwise. - */ -bool tomoyo_compare_number_union(const unsigned long value, - const struct tomoyo_number_union *ptr) -{ - if (ptr->group) - return tomoyo_number_matches_group(value, value, ptr->group); - return value >= ptr->values[0] && value <= ptr->values[1]; -} - -/** - * tomoyo_add_slash - Add trailing '/' if needed. - * - * @buf: Pointer to "struct tomoyo_path_info". - * - * Returns nothing. - * - * @buf must be generated by tomoyo_encode() because this function does not - * allocate memory for adding '/'. - */ -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_get_realpath - Get realpath. - * - * @buf: Pointer to "struct tomoyo_path_info". - * @path: Pointer to "struct path". - * - * Returns true on success, false otherwise. - */ -static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path) -{ - buf->name = tomoyo_realpath_from_path(path); - if (buf->name) { - tomoyo_fill_path_info(buf); - return true; - } - 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) -{ - return tomoyo_supervisor(r, "file %s %s\n", tomoyo_path_keyword - [r->param.path.operation], - r->param.path.filename->name); -} - -/** - * 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) -{ - return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords - [tomoyo_pp2mac[r->param.path2.operation]], - r->param.path2.filename1->name, - r->param.path2.filename2->name); -} - -/** - * 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) -{ - return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n", - tomoyo_mac_keywords - [tomoyo_pnnn2mac[r->param.mkdev.operation]], - r->param.mkdev.filename->name, - r->param.mkdev.mode, r->param.mkdev.major, - r->param.mkdev.minor); -} - -/** - * tomoyo_audit_path_number_log - Audit path/number request log. - * - * @r: Pointer to "struct tomoyo_request_info". - * - * 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; - char buffer[64]; - 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); - return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords - [tomoyo_pn2mac[type]], - r->param.path_number.filename->name, buffer); -} - -/** - * tomoyo_check_path_acl - Check permission for path operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @ptr: Pointer to "struct tomoyo_acl_info". - * - * Returns true if granted, false otherwise. - * - * To be able to use wildcard for domain transition, this function sets - * matching entry on success. Since the caller holds tomoyo_read_lock(), - * it is safe to set matching entry. - */ -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); - 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; -} - -/** - * tomoyo_check_path_number_acl - Check permission for path number operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @ptr: Pointer to "struct tomoyo_acl_info". - * - * Returns true if granted, false otherwise. - */ -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 = - 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); -} - -/** - * tomoyo_check_path2_acl - Check permission for path path operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @ptr: Pointer to "struct tomoyo_acl_info". - * - * Returns true if granted, false otherwise. - */ -static bool tomoyo_check_path2_acl(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); -} - -/** - * tomoyo_check_mkdev_acl - Check permission for path number number number operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @ptr: Pointer to "struct tomoyo_acl_info". - * - * Returns true if granted, false otherwise. - */ -static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, - const struct tomoyo_acl_info *ptr) -{ - 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, - &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); -} - -/** - * tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * - * Returns true if @a == @b except permission bits, false otherwise. - */ -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_same_name_union(&p1->name, &p2->name); -} - -/** - * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * @is_delete: True for @a &= ~@b, false for @a |= @b. - * - * Returns true if @a is empty, false otherwise. - */ -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; - else - perm |= b_perm; - *a_perm = perm; - return !perm; -} - -/** - * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. - * - * @perm: Permission. - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_update_path_acl(const u16 perm, - struct tomoyo_acl_param *param) -{ - struct tomoyo_path_acl e = { - .head.type = TOMOYO_TYPE_PATH_ACL, - .perm = perm - }; - int error; - if (!tomoyo_parse_name_union(param, &e.name)) - error = -EINVAL; - else - error = tomoyo_update_domain(&e.head, sizeof(e), param, - tomoyo_same_path_acl, - tomoyo_merge_path_acl); - tomoyo_put_name_union(&e.name); - return error; -} - -/** - * tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * - * Returns true if @a == @b except permission bits, false otherwise. - */ -static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a, - const struct tomoyo_acl_info *b) -{ - const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head); - const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head); - return 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); -} - -/** - * tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * @is_delete: True for @a &= ~@b, false for @a |= @b. - * - * Returns true if @a is empty, false otherwise. - */ -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_mkdev_acl, - head)->perm; - u8 perm = *a_perm; - const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head) - ->perm; - if (is_delete) - perm &= ~b_perm; - else - perm |= b_perm; - *a_perm = perm; - return !perm; -} - -/** - * tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list. - * - * @perm: Permission. - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_update_mkdev_acl(const u8 perm, - struct tomoyo_acl_param *param) -{ - struct tomoyo_mkdev_acl e = { - .head.type = TOMOYO_TYPE_MKDEV_ACL, - .perm = perm - }; - int error; - if (!tomoyo_parse_name_union(param, &e.name) || - !tomoyo_parse_number_union(param, &e.mode) || - !tomoyo_parse_number_union(param, &e.major) || - !tomoyo_parse_number_union(param, &e.minor)) - error = -EINVAL; - else - error = tomoyo_update_domain(&e.head, sizeof(e), param, - tomoyo_same_mkdev_acl, - tomoyo_merge_mkdev_acl); - tomoyo_put_name_union(&e.name); - tomoyo_put_number_union(&e.mode); - tomoyo_put_number_union(&e.major); - tomoyo_put_number_union(&e.minor); - return error; -} - -/** - * tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * - * Returns true if @a == @b except permission bits, false otherwise. - */ -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_same_name_union(&p1->name1, &p2->name1) && - tomoyo_same_name_union(&p1->name2, &p2->name2); -} - -/** - * tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * @is_delete: True for @a &= ~@b, false for @a |= @b. - * - * Returns true if @a is empty, false otherwise. - */ -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. - * - * @perm: Permission. - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_update_path2_acl(const u8 perm, - struct tomoyo_acl_param *param) -{ - struct tomoyo_path2_acl e = { - .head.type = TOMOYO_TYPE_PATH2_ACL, - .perm = perm - }; - int error; - if (!tomoyo_parse_name_union(param, &e.name1) || - !tomoyo_parse_name_union(param, &e.name2)) - error = -EINVAL; - else - error = tomoyo_update_domain(&e.head, sizeof(e), param, - tomoyo_same_path2_acl, - tomoyo_merge_path2_acl); - tomoyo_put_name_union(&e.name1); - tomoyo_put_name_union(&e.name2); - return error; -} - -/** - * tomoyo_path_permission - Check permission for single path operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @operation: Type of operation. - * @filename: Filename to check. - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, - const struct tomoyo_path_info *filename) -{ - int error; - - r->type = tomoyo_p2mac[operation]; - r->mode = tomoyo_get_mode(r->domain->ns, 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 { - tomoyo_check_acl(r, tomoyo_check_path_acl); - error = tomoyo_audit_path_log(r); - } while (error == TOMOYO_RETRY_REQUEST); - return error; -} - -/** - * tomoyo_execute_permission - Check permission for execute operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @filename: Filename to check. - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -int tomoyo_execute_permission(struct tomoyo_request_info *r, - const struct tomoyo_path_info *filename) -{ - /* - * Unlike other permission checks, this check is done regardless of - * profile mode settings in order to check for domain transition - * preference. - */ - r->type = TOMOYO_MAC_FILE_EXECUTE; - r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type); - r->param_type = TOMOYO_TYPE_PATH_ACL; - r->param.path.filename = filename; - r->param.path.operation = TOMOYO_TYPE_EXECUTE; - tomoyo_check_acl(r, tomoyo_check_path_acl); - r->ee->transition = r->matched_acl && r->matched_acl->cond ? - r->matched_acl->cond->transit : NULL; - if (r->mode != TOMOYO_CONFIG_DISABLED) - return tomoyo_audit_path_log(r); - return 0; -} - -/** - * tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * - * Returns true if @a == @b except permission bits, false otherwise. - */ -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_same_name_union(&p1->name, &p2->name) && - tomoyo_same_number_union(&p1->number, &p2->number); -} - -/** - * tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * @is_delete: True for @a &= ~@b, false for @a |= @b. - * - * Returns true if @a is empty, false otherwise. - */ -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. - * - * @perm: Permission. - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_update_path_number_acl(const u8 perm, - struct tomoyo_acl_param *param) -{ - struct tomoyo_path_number_acl e = { - .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, - .perm = perm - }; - int error; - if (!tomoyo_parse_name_union(param, &e.name) || - !tomoyo_parse_number_union(param, &e.number)) - error = -EINVAL; - else - error = tomoyo_update_domain(&e.head, sizeof(e), param, - tomoyo_same_path_number_acl, - tomoyo_merge_path_number_acl); - tomoyo_put_name_union(&e.name); - tomoyo_put_number_union(&e.number); - return error; -} - -/** - * tomoyo_path_number_perm - Check permission for "create", "mkdir", "mkfifo", "mksock", "ioctl", "chmod", "chown", "chgrp". - * - * @type: Type of operation. - * @path: Pointer to "struct path". - * @number: Number. - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_path_number_perm(const u8 type, struct path *path, - unsigned long number) -{ - struct tomoyo_request_info r; - struct tomoyo_obj_info obj = { - .path1 = *path, - }; - int error = -ENOMEM; - struct tomoyo_path_info buf; - int idx; - - if (tomoyo_init_request_info(&r, NULL, tomoyo_pn2mac[type]) - == TOMOYO_CONFIG_DISABLED || !path->dentry) - return 0; - idx = tomoyo_read_lock(); - if (!tomoyo_get_realpath(&buf, path)) - goto out; - r.obj = &obj; - if (type == TOMOYO_TYPE_MKDIR) - tomoyo_add_slash(&buf); - r.param_type = TOMOYO_TYPE_PATH_NUMBER_ACL; - r.param.path_number.operation = type; - r.param.path_number.filename = &buf; - r.param.path_number.number = number; - do { - tomoyo_check_acl(&r, tomoyo_check_path_number_acl); - error = tomoyo_audit_path_number_log(&r); - } while (error == TOMOYO_RETRY_REQUEST); - kfree(buf.name); - out: - tomoyo_read_unlock(idx); - if (r.mode != TOMOYO_CONFIG_ENFORCING) - error = 0; - return error; -} - -/** - * tomoyo_check_open_permission - Check permission for "read" and "write". - * - * @domain: Pointer to "struct tomoyo_domain_info". - * @path: Pointer to "struct path". - * @flag: Flags for open(). - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, - struct path *path, const int flag) -{ - const u8 acc_mode = ACC_MODE(flag); - int error = 0; - struct tomoyo_path_info buf; - struct tomoyo_request_info r; - struct tomoyo_obj_info obj = { - .path1 = *path, - }; - int idx; - - buf.name = NULL; - r.mode = TOMOYO_CONFIG_DISABLED; - idx = tomoyo_read_lock(); - if (acc_mode && - tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) - != TOMOYO_CONFIG_DISABLED) { - if (!tomoyo_get_realpath(&buf, path)) { - error = -ENOMEM; - goto out; - } - r.obj = &obj; - if (acc_mode & MAY_READ) - error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ, - &buf); - if (!error && (acc_mode & MAY_WRITE)) - error = tomoyo_path_permission(&r, (flag & O_APPEND) ? - TOMOYO_TYPE_APPEND : - TOMOYO_TYPE_WRITE, - &buf); - } - out: - kfree(buf.name); - tomoyo_read_unlock(idx); - if (r.mode != TOMOYO_CONFIG_ENFORCING) - error = 0; - return error; -} - -/** - * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount". - * - * @operation: Type of operation. - * @path: Pointer to "struct path". - * @target: Symlink's target if @operation is TOMOYO_TYPE_SYMLINK, - * NULL otherwise. - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_path_perm(const u8 operation, struct path *path, const char *target) -{ - struct tomoyo_request_info r; - struct tomoyo_obj_info obj = { - .path1 = *path, - }; - int error; - struct tomoyo_path_info buf; - bool is_enforce; - struct tomoyo_path_info symlink_target; - int idx; - - if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) - == TOMOYO_CONFIG_DISABLED) - return 0; - is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING); - error = -ENOMEM; - buf.name = NULL; - idx = tomoyo_read_lock(); - if (!tomoyo_get_realpath(&buf, path)) - goto out; - r.obj = &obj; - switch (operation) { - case TOMOYO_TYPE_RMDIR: - case TOMOYO_TYPE_CHROOT: - tomoyo_add_slash(&buf); - break; - case TOMOYO_TYPE_SYMLINK: - symlink_target.name = tomoyo_encode(target); - if (!symlink_target.name) - goto out; - tomoyo_fill_path_info(&symlink_target); - obj.symlink_target = &symlink_target; - break; - } - error = tomoyo_path_permission(&r, operation, &buf); - if (operation == TOMOYO_TYPE_SYMLINK) - kfree(symlink_target.name); - out: - kfree(buf.name); - tomoyo_read_unlock(idx); - if (!is_enforce) - error = 0; - return error; -} - -/** - * 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". - * @mode: Create mode. - * @dev: Device number. - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_mkdev_perm(const u8 operation, struct path *path, - const unsigned int mode, unsigned int dev) -{ - struct tomoyo_request_info r; - struct tomoyo_obj_info obj = { - .path1 = *path, - }; - int error = -ENOMEM; - struct tomoyo_path_info buf; - int idx; - - if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation]) - == TOMOYO_CONFIG_DISABLED) - return 0; - idx = tomoyo_read_lock(); - error = -ENOMEM; - if (tomoyo_get_realpath(&buf, path)) { - r.obj = &obj; - dev = new_decode_dev(dev); - r.param_type = TOMOYO_TYPE_MKDEV_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); - tomoyo_check_acl(&r, tomoyo_check_mkdev_acl); - error = tomoyo_audit_mkdev_log(&r); - kfree(buf.name); - } - tomoyo_read_unlock(idx); - if (r.mode != TOMOYO_CONFIG_ENFORCING) - error = 0; - return error; -} - -/** - * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". - * - * @operation: Type of operation. - * @path1: Pointer to "struct path". - * @path2: Pointer to "struct path". - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_path2_perm(const u8 operation, struct path *path1, - struct path *path2) -{ - int error = -ENOMEM; - struct tomoyo_path_info buf1; - struct tomoyo_path_info buf2; - struct tomoyo_request_info r; - struct tomoyo_obj_info obj = { - .path1 = *path1, - .path2 = *path2, - }; - int idx; - - if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation]) - == TOMOYO_CONFIG_DISABLED) - return 0; - buf1.name = NULL; - buf2.name = NULL; - idx = tomoyo_read_lock(); - if (!tomoyo_get_realpath(&buf1, path1) || - !tomoyo_get_realpath(&buf2, path2)) - goto out; - 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; - } - r.obj = &obj; - r.param_type = TOMOYO_TYPE_PATH2_ACL; - r.param.path2.operation = operation; - r.param.path2.filename1 = &buf1; - r.param.path2.filename2 = &buf2; - do { - 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); - tomoyo_read_unlock(idx); - if (r.mode != TOMOYO_CONFIG_ENFORCING) - error = 0; - return error; -} - -/** - * tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * - * Returns true if @a == @b, false otherwise. - */ -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_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); -} - -/** - * tomoyo_update_mount_acl - Write "struct tomoyo_mount_acl" list. - * - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param) -{ - struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL }; - int error; - if (!tomoyo_parse_name_union(param, &e.dev_name) || - !tomoyo_parse_name_union(param, &e.dir_name) || - !tomoyo_parse_name_union(param, &e.fs_type) || - !tomoyo_parse_number_union(param, &e.flags)) - error = -EINVAL; - else - error = tomoyo_update_domain(&e.head, sizeof(e), param, - tomoyo_same_mount_acl, NULL); - 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; -} - -/** - * tomoyo_write_file - Update file related list. - * - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -int tomoyo_write_file(struct tomoyo_acl_param *param) -{ - u16 perm = 0; - u8 type; - const char *operation = tomoyo_read_token(param); - for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) - if (tomoyo_permstr(operation, tomoyo_path_keyword[type])) - perm |= 1 << type; - if (perm) - return tomoyo_update_path_acl(perm, param); - for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) - if (tomoyo_permstr(operation, - tomoyo_mac_keywords[tomoyo_pp2mac[type]])) - perm |= 1 << type; - if (perm) - return tomoyo_update_path2_acl(perm, param); - for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) - if (tomoyo_permstr(operation, - tomoyo_mac_keywords[tomoyo_pn2mac[type]])) - perm |= 1 << type; - if (perm) - return tomoyo_update_path_number_acl(perm, param); - for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) - if (tomoyo_permstr(operation, - tomoyo_mac_keywords[tomoyo_pnnn2mac[type]])) - perm |= 1 << type; - if (perm) - return tomoyo_update_mkdev_acl(perm, param); - if (tomoyo_permstr(operation, - tomoyo_mac_keywords[TOMOYO_MAC_FILE_MOUNT])) - return tomoyo_update_mount_acl(param); - return -EINVAL; -} diff --git a/ANDROID_3.4.5/security/tomoyo/gc.c b/ANDROID_3.4.5/security/tomoyo/gc.c deleted file mode 100644 index 986a6a75..00000000 --- a/ANDROID_3.4.5/security/tomoyo/gc.c +++ /dev/null @@ -1,655 +0,0 @@ -/* - * security/tomoyo/gc.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include "common.h" -#include <linux/kthread.h> -#include <linux/slab.h> - -/** - * tomoyo_memory_free - Free memory for elements. - * - * @ptr: Pointer to allocated memory. - * - * Returns nothing. - * - * Caller holds tomoyo_policy_lock mutex. - */ -static inline void tomoyo_memory_free(void *ptr) -{ - tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= ksize(ptr); - kfree(ptr); -} - -/* The list for "struct tomoyo_io_buffer". */ -static LIST_HEAD(tomoyo_io_buffer_list); -/* Lock for protecting tomoyo_io_buffer_list. */ -static DEFINE_SPINLOCK(tomoyo_io_buffer_list_lock); - -/** - * tomoyo_struct_used_by_io_buffer - Check whether the list element is used by /sys/kernel/security/tomoyo/ users or not. - * - * @element: Pointer to "struct list_head". - * - * Returns true if @element is used by /sys/kernel/security/tomoyo/ users, - * false otherwise. - */ -static bool tomoyo_struct_used_by_io_buffer(const struct list_head *element) -{ - struct tomoyo_io_buffer *head; - bool in_use = false; - - spin_lock(&tomoyo_io_buffer_list_lock); - list_for_each_entry(head, &tomoyo_io_buffer_list, list) { - head->users++; - spin_unlock(&tomoyo_io_buffer_list_lock); - mutex_lock(&head->io_sem); - if (head->r.domain == element || head->r.group == element || - head->r.acl == element || &head->w.domain->list == element) - in_use = true; - mutex_unlock(&head->io_sem); - spin_lock(&tomoyo_io_buffer_list_lock); - head->users--; - if (in_use) - break; - } - spin_unlock(&tomoyo_io_buffer_list_lock); - return in_use; -} - -/** - * tomoyo_name_used_by_io_buffer - Check whether the string is used by /sys/kernel/security/tomoyo/ users or not. - * - * @string: String to check. - * - * Returns true if @string is used by /sys/kernel/security/tomoyo/ users, - * false otherwise. - */ -static bool tomoyo_name_used_by_io_buffer(const char *string) -{ - struct tomoyo_io_buffer *head; - const size_t size = strlen(string) + 1; - bool in_use = false; - - spin_lock(&tomoyo_io_buffer_list_lock); - list_for_each_entry(head, &tomoyo_io_buffer_list, list) { - int i; - head->users++; - spin_unlock(&tomoyo_io_buffer_list_lock); - mutex_lock(&head->io_sem); - for (i = 0; i < TOMOYO_MAX_IO_READ_QUEUE; i++) { - const char *w = head->r.w[i]; - if (w < string || w > string + size) - continue; - in_use = true; - break; - } - mutex_unlock(&head->io_sem); - spin_lock(&tomoyo_io_buffer_list_lock); - head->users--; - if (in_use) - break; - } - spin_unlock(&tomoyo_io_buffer_list_lock); - return in_use; -} - -/** - * tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control". - * - * @element: Pointer to "struct list_head". - * - * Returns nothing. - */ -static inline void tomoyo_del_transition_control(struct list_head *element) -{ - struct tomoyo_transition_control *ptr = - container_of(element, typeof(*ptr), head.list); - tomoyo_put_name(ptr->domainname); - tomoyo_put_name(ptr->program); -} - -/** - * tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator". - * - * @element: Pointer to "struct list_head". - * - * Returns nothing. - */ -static inline void tomoyo_del_aggregator(struct list_head *element) -{ - struct tomoyo_aggregator *ptr = - container_of(element, typeof(*ptr), head.list); - tomoyo_put_name(ptr->original_name); - tomoyo_put_name(ptr->aggregated_name); -} - -/** - * tomoyo_del_manager - Delete members in "struct tomoyo_manager". - * - * @element: Pointer to "struct list_head". - * - * Returns nothing. - */ -static inline void tomoyo_del_manager(struct list_head *element) -{ - struct tomoyo_manager *ptr = - container_of(element, typeof(*ptr), head.list); - tomoyo_put_name(ptr->manager); -} - -/** - * tomoyo_del_acl - Delete members in "struct tomoyo_acl_info". - * - * @element: Pointer to "struct list_head". - * - * Returns nothing. - */ -static void tomoyo_del_acl(struct list_head *element) -{ - struct tomoyo_acl_info *acl = - container_of(element, typeof(*acl), list); - tomoyo_put_condition(acl->cond); - switch (acl->type) { - case TOMOYO_TYPE_PATH_ACL: - { - struct tomoyo_path_acl *entry - = container_of(acl, typeof(*entry), head); - tomoyo_put_name_union(&entry->name); - } - break; - case TOMOYO_TYPE_PATH2_ACL: - { - struct tomoyo_path2_acl *entry - = container_of(acl, typeof(*entry), head); - tomoyo_put_name_union(&entry->name1); - tomoyo_put_name_union(&entry->name2); - } - break; - case TOMOYO_TYPE_PATH_NUMBER_ACL: - { - struct tomoyo_path_number_acl *entry - = container_of(acl, typeof(*entry), head); - tomoyo_put_name_union(&entry->name); - tomoyo_put_number_union(&entry->number); - } - break; - case TOMOYO_TYPE_MKDEV_ACL: - { - struct tomoyo_mkdev_acl *entry - = container_of(acl, typeof(*entry), head); - tomoyo_put_name_union(&entry->name); - tomoyo_put_number_union(&entry->mode); - tomoyo_put_number_union(&entry->major); - tomoyo_put_number_union(&entry->minor); - } - break; - case TOMOYO_TYPE_MOUNT_ACL: - { - struct tomoyo_mount_acl *entry - = container_of(acl, typeof(*entry), head); - tomoyo_put_name_union(&entry->dev_name); - tomoyo_put_name_union(&entry->dir_name); - tomoyo_put_name_union(&entry->fs_type); - tomoyo_put_number_union(&entry->flags); - } - break; - case TOMOYO_TYPE_ENV_ACL: - { - struct tomoyo_env_acl *entry = - container_of(acl, typeof(*entry), head); - - tomoyo_put_name(entry->env); - } - break; - case TOMOYO_TYPE_INET_ACL: - { - struct tomoyo_inet_acl *entry = - container_of(acl, typeof(*entry), head); - - tomoyo_put_group(entry->address.group); - tomoyo_put_number_union(&entry->port); - } - break; - case TOMOYO_TYPE_UNIX_ACL: - { - struct tomoyo_unix_acl *entry = - container_of(acl, typeof(*entry), head); - - tomoyo_put_name_union(&entry->name); - } - break; - case TOMOYO_TYPE_MANUAL_TASK_ACL: - { - struct tomoyo_task_acl *entry = - container_of(acl, typeof(*entry), head); - tomoyo_put_name(entry->domainname); - } - break; - } -} - -/** - * tomoyo_del_domain - Delete members in "struct tomoyo_domain_info". - * - * @element: Pointer to "struct list_head". - * - * Returns nothing. - * - * Caller holds tomoyo_policy_lock mutex. - */ -static inline void tomoyo_del_domain(struct list_head *element) -{ - struct tomoyo_domain_info *domain = - container_of(element, typeof(*domain), list); - struct tomoyo_acl_info *acl; - struct tomoyo_acl_info *tmp; - /* - * Since this domain is referenced from neither - * "struct tomoyo_io_buffer" nor "struct cred"->security, we can delete - * elements without checking for is_deleted flag. - */ - list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { - tomoyo_del_acl(&acl->list); - tomoyo_memory_free(acl); - } - tomoyo_put_name(domain->domainname); -} - -/** - * tomoyo_del_condition - Delete members in "struct tomoyo_condition". - * - * @element: Pointer to "struct list_head". - * - * Returns nothing. - */ -void tomoyo_del_condition(struct list_head *element) -{ - struct tomoyo_condition *cond = container_of(element, typeof(*cond), - head.list); - const u16 condc = cond->condc; - const u16 numbers_count = cond->numbers_count; - const u16 names_count = cond->names_count; - const u16 argc = cond->argc; - const u16 envc = cond->envc; - unsigned int i; - const struct tomoyo_condition_element *condp - = (const struct tomoyo_condition_element *) (cond + 1); - struct tomoyo_number_union *numbers_p - = (struct tomoyo_number_union *) (condp + condc); - struct tomoyo_name_union *names_p - = (struct tomoyo_name_union *) (numbers_p + numbers_count); - const struct tomoyo_argv *argv - = (const struct tomoyo_argv *) (names_p + names_count); - const struct tomoyo_envp *envp - = (const struct tomoyo_envp *) (argv + argc); - for (i = 0; i < numbers_count; i++) - tomoyo_put_number_union(numbers_p++); - for (i = 0; i < names_count; i++) - tomoyo_put_name_union(names_p++); - for (i = 0; i < argc; argv++, i++) - tomoyo_put_name(argv->value); - for (i = 0; i < envc; envp++, i++) { - tomoyo_put_name(envp->name); - tomoyo_put_name(envp->value); - } -} - -/** - * tomoyo_del_name - Delete members in "struct tomoyo_name". - * - * @element: Pointer to "struct list_head". - * - * Returns nothing. - */ -static inline void tomoyo_del_name(struct list_head *element) -{ - /* Nothing to do. */ -} - -/** - * tomoyo_del_path_group - Delete members in "struct tomoyo_path_group". - * - * @element: Pointer to "struct list_head". - * - * Returns nothing. - */ -static inline void tomoyo_del_path_group(struct list_head *element) -{ - struct tomoyo_path_group *member = - container_of(element, typeof(*member), head.list); - tomoyo_put_name(member->member_name); -} - -/** - * tomoyo_del_group - Delete "struct tomoyo_group". - * - * @element: Pointer to "struct list_head". - * - * Returns nothing. - */ -static inline void tomoyo_del_group(struct list_head *element) -{ - struct tomoyo_group *group = - container_of(element, typeof(*group), head.list); - tomoyo_put_name(group->group_name); -} - -/** - * tomoyo_del_address_group - Delete members in "struct tomoyo_address_group". - * - * @element: Pointer to "struct list_head". - * - * Returns nothing. - */ -static inline void tomoyo_del_address_group(struct list_head *element) -{ - /* Nothing to do. */ -} - -/** - * tomoyo_del_number_group - Delete members in "struct tomoyo_number_group". - * - * @element: Pointer to "struct list_head". - * - * Returns nothing. - */ -static inline void tomoyo_del_number_group(struct list_head *element) -{ - /* Nothing to do. */ -} - -/** - * tomoyo_try_to_gc - Try to kfree() an entry. - * - * @type: One of values in "enum tomoyo_policy_id". - * @element: Pointer to "struct list_head". - * - * Returns nothing. - * - * Caller holds tomoyo_policy_lock mutex. - */ -static void tomoyo_try_to_gc(const enum tomoyo_policy_id type, - struct list_head *element) -{ - /* - * __list_del_entry() guarantees that the list element became no longer - * reachable from the list which the element was originally on (e.g. - * tomoyo_domain_list). Also, synchronize_srcu() guarantees that the - * list element became no longer referenced by syscall users. - */ - __list_del_entry(element); - mutex_unlock(&tomoyo_policy_lock); - synchronize_srcu(&tomoyo_ss); - /* - * However, there are two users which may still be using the list - * element. We need to defer until both users forget this element. - * - * Don't kfree() until "struct tomoyo_io_buffer"->r.{domain,group,acl} - * and "struct tomoyo_io_buffer"->w.domain forget this element. - */ - if (tomoyo_struct_used_by_io_buffer(element)) - goto reinject; - switch (type) { - case TOMOYO_ID_TRANSITION_CONTROL: - tomoyo_del_transition_control(element); - break; - case TOMOYO_ID_MANAGER: - tomoyo_del_manager(element); - break; - case TOMOYO_ID_AGGREGATOR: - tomoyo_del_aggregator(element); - break; - case TOMOYO_ID_GROUP: - tomoyo_del_group(element); - break; - case TOMOYO_ID_PATH_GROUP: - tomoyo_del_path_group(element); - break; - case TOMOYO_ID_ADDRESS_GROUP: - tomoyo_del_address_group(element); - break; - case TOMOYO_ID_NUMBER_GROUP: - tomoyo_del_number_group(element); - break; - case TOMOYO_ID_CONDITION: - tomoyo_del_condition(element); - break; - case TOMOYO_ID_NAME: - /* - * Don't kfree() until all "struct tomoyo_io_buffer"->r.w[] - * forget this element. - */ - if (tomoyo_name_used_by_io_buffer - (container_of(element, typeof(struct tomoyo_name), - head.list)->entry.name)) - goto reinject; - tomoyo_del_name(element); - break; - case TOMOYO_ID_ACL: - tomoyo_del_acl(element); - break; - case TOMOYO_ID_DOMAIN: - /* - * Don't kfree() until all "struct cred"->security forget this - * element. - */ - if (atomic_read(&container_of - (element, typeof(struct tomoyo_domain_info), - list)->users)) - goto reinject; - break; - case TOMOYO_MAX_POLICY: - break; - } - mutex_lock(&tomoyo_policy_lock); - if (type == TOMOYO_ID_DOMAIN) - tomoyo_del_domain(element); - tomoyo_memory_free(element); - return; -reinject: - /* - * We can safely reinject this element here bacause - * (1) Appending list elements and removing list elements are protected - * by tomoyo_policy_lock mutex. - * (2) Only this function removes list elements and this function is - * exclusively executed by tomoyo_gc_mutex mutex. - * are true. - */ - mutex_lock(&tomoyo_policy_lock); - list_add_rcu(element, element->prev); -} - -/** - * tomoyo_collect_member - Delete elements with "struct tomoyo_acl_head". - * - * @id: One of values in "enum tomoyo_policy_id". - * @member_list: Pointer to "struct list_head". - * - * Returns nothing. - */ -static void tomoyo_collect_member(const enum tomoyo_policy_id id, - struct list_head *member_list) -{ - struct tomoyo_acl_head *member; - struct tomoyo_acl_head *tmp; - list_for_each_entry_safe(member, tmp, member_list, list) { - if (!member->is_deleted) - continue; - member->is_deleted = TOMOYO_GC_IN_PROGRESS; - tomoyo_try_to_gc(id, &member->list); - } -} - -/** - * tomoyo_collect_acl - Delete elements in "struct tomoyo_domain_info". - * - * @list: Pointer to "struct list_head". - * - * Returns nothing. - */ -static void tomoyo_collect_acl(struct list_head *list) -{ - struct tomoyo_acl_info *acl; - struct tomoyo_acl_info *tmp; - list_for_each_entry_safe(acl, tmp, list, list) { - if (!acl->is_deleted) - continue; - acl->is_deleted = TOMOYO_GC_IN_PROGRESS; - tomoyo_try_to_gc(TOMOYO_ID_ACL, &acl->list); - } -} - -/** - * tomoyo_collect_entry - Try to kfree() deleted elements. - * - * Returns nothing. - */ -static void tomoyo_collect_entry(void) -{ - int i; - enum tomoyo_policy_id id; - struct tomoyo_policy_namespace *ns; - mutex_lock(&tomoyo_policy_lock); - { - struct tomoyo_domain_info *domain; - struct tomoyo_domain_info *tmp; - list_for_each_entry_safe(domain, tmp, &tomoyo_domain_list, - list) { - tomoyo_collect_acl(&domain->acl_info_list); - if (!domain->is_deleted || atomic_read(&domain->users)) - continue; - tomoyo_try_to_gc(TOMOYO_ID_DOMAIN, &domain->list); - } - } - list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { - for (id = 0; id < TOMOYO_MAX_POLICY; id++) - tomoyo_collect_member(id, &ns->policy_list[id]); - for (i = 0; i < TOMOYO_MAX_ACL_GROUPS; i++) - tomoyo_collect_acl(&ns->acl_group[i]); - } - { - struct tomoyo_shared_acl_head *ptr; - struct tomoyo_shared_acl_head *tmp; - list_for_each_entry_safe(ptr, tmp, &tomoyo_condition_list, - list) { - if (atomic_read(&ptr->users) > 0) - continue; - atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS); - tomoyo_try_to_gc(TOMOYO_ID_CONDITION, &ptr->list); - } - } - list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { - for (i = 0; i < TOMOYO_MAX_GROUP; i++) { - struct list_head *list = &ns->group_list[i]; - struct tomoyo_group *group; - struct tomoyo_group *tmp; - switch (i) { - case 0: - id = TOMOYO_ID_PATH_GROUP; - break; - case 1: - id = TOMOYO_ID_NUMBER_GROUP; - break; - default: - id = TOMOYO_ID_ADDRESS_GROUP; - break; - } - list_for_each_entry_safe(group, tmp, list, head.list) { - tomoyo_collect_member(id, &group->member_list); - if (!list_empty(&group->member_list) || - atomic_read(&group->head.users) > 0) - continue; - atomic_set(&group->head.users, - TOMOYO_GC_IN_PROGRESS); - tomoyo_try_to_gc(TOMOYO_ID_GROUP, - &group->head.list); - } - } - } - for (i = 0; i < TOMOYO_MAX_HASH; i++) { - struct list_head *list = &tomoyo_name_list[i]; - struct tomoyo_shared_acl_head *ptr; - struct tomoyo_shared_acl_head *tmp; - list_for_each_entry_safe(ptr, tmp, list, list) { - if (atomic_read(&ptr->users) > 0) - continue; - atomic_set(&ptr->users, TOMOYO_GC_IN_PROGRESS); - tomoyo_try_to_gc(TOMOYO_ID_NAME, &ptr->list); - } - } - mutex_unlock(&tomoyo_policy_lock); -} - -/** - * tomoyo_gc_thread - Garbage collector thread function. - * - * @unused: Unused. - * - * Returns 0. - */ -static int tomoyo_gc_thread(void *unused) -{ - /* Garbage collector thread is exclusive. */ - static DEFINE_MUTEX(tomoyo_gc_mutex); - if (!mutex_trylock(&tomoyo_gc_mutex)) - goto out; - tomoyo_collect_entry(); - { - struct tomoyo_io_buffer *head; - struct tomoyo_io_buffer *tmp; - - spin_lock(&tomoyo_io_buffer_list_lock); - list_for_each_entry_safe(head, tmp, &tomoyo_io_buffer_list, - list) { - if (head->users) - continue; - list_del(&head->list); - kfree(head->read_buf); - kfree(head->write_buf); - kfree(head); - } - spin_unlock(&tomoyo_io_buffer_list_lock); - } - mutex_unlock(&tomoyo_gc_mutex); -out: - /* This acts as do_exit(0). */ - return 0; -} - -/** - * tomoyo_notify_gc - Register/unregister /sys/kernel/security/tomoyo/ users. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * @is_register: True if register, false if unregister. - * - * Returns nothing. - */ -void tomoyo_notify_gc(struct tomoyo_io_buffer *head, const bool is_register) -{ - bool is_write = false; - - spin_lock(&tomoyo_io_buffer_list_lock); - if (is_register) { - head->users = 1; - list_add(&head->list, &tomoyo_io_buffer_list); - } else { - is_write = head->write_buf != NULL; - if (!--head->users) { - list_del(&head->list); - kfree(head->read_buf); - kfree(head->write_buf); - kfree(head); - } - } - spin_unlock(&tomoyo_io_buffer_list_lock); - if (is_write) { - struct task_struct *task = kthread_create(tomoyo_gc_thread, - NULL, - "GC for TOMOYO"); - if (!IS_ERR(task)) - wake_up_process(task); - } -} diff --git a/ANDROID_3.4.5/security/tomoyo/group.c b/ANDROID_3.4.5/security/tomoyo/group.c deleted file mode 100644 index 50092534..00000000 --- a/ANDROID_3.4.5/security/tomoyo/group.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * security/tomoyo/group.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include <linux/slab.h> -#include "common.h" - -/** - * tomoyo_same_path_group - Check for duplicated "struct tomoyo_path_group" entry. - * - * @a: Pointer to "struct tomoyo_acl_head". - * @b: Pointer to "struct tomoyo_acl_head". - * - * Returns true if @a == @b, false otherwise. - */ -static bool tomoyo_same_path_group(const struct tomoyo_acl_head *a, - const struct tomoyo_acl_head *b) -{ - return container_of(a, struct tomoyo_path_group, head)->member_name == - container_of(b, struct tomoyo_path_group, head)->member_name; -} - -/** - * tomoyo_same_number_group - Check for duplicated "struct tomoyo_number_group" entry. - * - * @a: Pointer to "struct tomoyo_acl_head". - * @b: Pointer to "struct tomoyo_acl_head". - * - * Returns true if @a == @b, false otherwise. - */ -static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a, - const struct tomoyo_acl_head *b) -{ - return !memcmp(&container_of(a, struct tomoyo_number_group, head) - ->number, - &container_of(b, struct tomoyo_number_group, head) - ->number, - sizeof(container_of(a, struct tomoyo_number_group, head) - ->number)); -} - -/** - * tomoyo_same_address_group - Check for duplicated "struct tomoyo_address_group" entry. - * - * @a: Pointer to "struct tomoyo_acl_head". - * @b: Pointer to "struct tomoyo_acl_head". - * - * Returns true if @a == @b, false otherwise. - */ -static bool tomoyo_same_address_group(const struct tomoyo_acl_head *a, - const struct tomoyo_acl_head *b) -{ - const struct tomoyo_address_group *p1 = container_of(a, typeof(*p1), - head); - const struct tomoyo_address_group *p2 = container_of(b, typeof(*p2), - head); - - return tomoyo_same_ipaddr_union(&p1->address, &p2->address); -} - -/** - * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group"/"struct tomoyo_address_group" list. - * - * @param: Pointer to "struct tomoyo_acl_param". - * @type: Type of this group. - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type) -{ - struct tomoyo_group *group = tomoyo_get_group(param, type); - int error = -EINVAL; - if (!group) - return -ENOMEM; - param->list = &group->member_list; - if (type == TOMOYO_PATH_GROUP) { - struct tomoyo_path_group e = { }; - e.member_name = tomoyo_get_name(tomoyo_read_token(param)); - if (!e.member_name) { - error = -ENOMEM; - goto out; - } - error = tomoyo_update_policy(&e.head, sizeof(e), param, - tomoyo_same_path_group); - tomoyo_put_name(e.member_name); - } else if (type == TOMOYO_NUMBER_GROUP) { - struct tomoyo_number_group e = { }; - if (param->data[0] == '@' || - !tomoyo_parse_number_union(param, &e.number)) - goto out; - error = tomoyo_update_policy(&e.head, sizeof(e), param, - tomoyo_same_number_group); - /* - * tomoyo_put_number_union() is not needed because - * param->data[0] != '@'. - */ - } else { - struct tomoyo_address_group e = { }; - - if (param->data[0] == '@' || - !tomoyo_parse_ipaddr_union(param, &e.address)) - goto out; - error = tomoyo_update_policy(&e.head, sizeof(e), param, - tomoyo_same_address_group); - } -out: - tomoyo_put_group(group); - return error; -} - -/** - * tomoyo_path_matches_group - Check whether the given pathname matches members of the given pathname group. - * - * @pathname: The name of pathname. - * @group: Pointer to "struct tomoyo_path_group". - * - * Returns matched member's pathname if @pathname matches pathnames in @group, - * NULL otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -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; - 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; - return member->member_name; - } - return NULL; -} - -/** - * tomoyo_number_matches_group - Check whether the given number matches members of the given number group. - * - * @min: Min number. - * @max: Max number. - * @group: Pointer to "struct tomoyo_number_group". - * - * Returns true if @min and @max partially overlaps @group, false otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -bool tomoyo_number_matches_group(const unsigned long min, - const unsigned long max, - const struct tomoyo_group *group) -{ - struct tomoyo_number_group *member; - bool matched = false; - list_for_each_entry_rcu(member, &group->member_list, head.list) { - if (member->head.is_deleted) - continue; - if (min > member->number.values[1] || - max < member->number.values[0]) - continue; - matched = true; - break; - } - return matched; -} - -/** - * tomoyo_address_matches_group - Check whether the given address matches members of the given address group. - * - * @is_ipv6: True if @address is an IPv6 address. - * @address: An IPv4 or IPv6 address. - * @group: Pointer to "struct tomoyo_address_group". - * - * Returns true if @address matches addresses in @group group, false otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address, - const struct tomoyo_group *group) -{ - struct tomoyo_address_group *member; - bool matched = false; - const u8 size = is_ipv6 ? 16 : 4; - - list_for_each_entry_rcu(member, &group->member_list, head.list) { - if (member->head.is_deleted) - continue; - if (member->address.is_ipv6 != is_ipv6) - continue; - if (memcmp(&member->address.ip[0], address, size) > 0 || - memcmp(address, &member->address.ip[1], size) > 0) - continue; - matched = true; - break; - } - return matched; -} diff --git a/ANDROID_3.4.5/security/tomoyo/load_policy.c b/ANDROID_3.4.5/security/tomoyo/load_policy.c deleted file mode 100644 index 078fac0b..00000000 --- a/ANDROID_3.4.5/security/tomoyo/load_policy.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * security/tomoyo/load_policy.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include "common.h" - -#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER - -/* - * Path to the policy loader. (default = CONFIG_SECURITY_TOMOYO_POLICY_LOADER) - */ -static const char *tomoyo_loader; - -/** - * tomoyo_loader_setup - Set policy loader. - * - * @str: Program to use as a policy loader (e.g. /sbin/tomoyo-init ). - * - * Returns 0. - */ -static int __init tomoyo_loader_setup(char *str) -{ - tomoyo_loader = str; - return 0; -} - -__setup("TOMOYO_loader=", tomoyo_loader_setup); - -/** - * tomoyo_policy_loader_exists - Check whether /sbin/tomoyo-init exists. - * - * Returns true if /sbin/tomoyo-init exists, false otherwise. - */ -static bool tomoyo_policy_loader_exists(void) -{ - struct path path; - if (!tomoyo_loader) - tomoyo_loader = CONFIG_SECURITY_TOMOYO_POLICY_LOADER; - if (kern_path(tomoyo_loader, LOOKUP_FOLLOW, &path)) { - printk(KERN_INFO "Not activating Mandatory Access Control " - "as %s does not exist.\n", tomoyo_loader); - return false; - } - path_put(&path); - return true; -} - -/* - * Path to the trigger. (default = CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER) - */ -static const char *tomoyo_trigger; - -/** - * tomoyo_trigger_setup - Set trigger for activation. - * - * @str: Program to use as an activation trigger (e.g. /sbin/init ). - * - * Returns 0. - */ -static int __init tomoyo_trigger_setup(char *str) -{ - tomoyo_trigger = str; - return 0; -} - -__setup("TOMOYO_trigger=", tomoyo_trigger_setup); - -/** - * tomoyo_load_policy - Run external policy loader to load policy. - * - * @filename: The program about to start. - * - * This function checks whether @filename is /sbin/init , and if so - * invoke /sbin/tomoyo-init and wait for the termination of /sbin/tomoyo-init - * and then continues invocation of /sbin/init. - * /sbin/tomoyo-init reads policy files in /etc/tomoyo/ directory and - * writes to /sys/kernel/security/tomoyo/ interfaces. - * - * Returns nothing. - */ -void tomoyo_load_policy(const char *filename) -{ - static bool done; - char *argv[2]; - char *envp[3]; - - if (tomoyo_policy_loaded || done) - return; - if (!tomoyo_trigger) - tomoyo_trigger = CONFIG_SECURITY_TOMOYO_ACTIVATION_TRIGGER; - if (strcmp(filename, tomoyo_trigger)) - return; - if (!tomoyo_policy_loader_exists()) - return; - done = true; - printk(KERN_INFO "Calling %s to load policy. Please wait.\n", - tomoyo_loader); - argv[0] = (char *) tomoyo_loader; - argv[1] = NULL; - envp[0] = "HOME=/"; - envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; - envp[2] = NULL; - call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); - tomoyo_check_profile(); -} - -#endif diff --git a/ANDROID_3.4.5/security/tomoyo/memory.c b/ANDROID_3.4.5/security/tomoyo/memory.c deleted file mode 100644 index 0e995716..00000000 --- a/ANDROID_3.4.5/security/tomoyo/memory.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * security/tomoyo/memory.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include <linux/hash.h> -#include <linux/slab.h> -#include "common.h" - -/** - * tomoyo_warn_oom - Print out of memory warning message. - * - * @function: Function's name. - */ -void tomoyo_warn_oom(const char *function) -{ - /* Reduce error messages. */ - static pid_t tomoyo_last_pid; - const pid_t pid = current->pid; - if (tomoyo_last_pid != pid) { - printk(KERN_WARNING "ERROR: Out of memory at %s.\n", - function); - tomoyo_last_pid = pid; - } - if (!tomoyo_policy_loaded) - panic("MAC Initialization failed.\n"); -} - -/* Memoy currently used by policy/audit log/query. */ -unsigned int tomoyo_memory_used[TOMOYO_MAX_MEMORY_STAT]; -/* Memory quota for "policy"/"audit log"/"query". */ -unsigned int tomoyo_memory_quota[TOMOYO_MAX_MEMORY_STAT]; - -/** - * tomoyo_memory_ok - Check memory quota. - * - * @ptr: Pointer to allocated memory. - * - * Returns true on success, false otherwise. - * - * Returns true if @ptr is not NULL and quota not exceeded, false otherwise. - * - * Caller holds tomoyo_policy_lock mutex. - */ -bool tomoyo_memory_ok(void *ptr) -{ - if (ptr) { - const size_t s = ksize(ptr); - tomoyo_memory_used[TOMOYO_MEMORY_POLICY] += s; - if (!tomoyo_memory_quota[TOMOYO_MEMORY_POLICY] || - tomoyo_memory_used[TOMOYO_MEMORY_POLICY] <= - tomoyo_memory_quota[TOMOYO_MEMORY_POLICY]) - return true; - tomoyo_memory_used[TOMOYO_MEMORY_POLICY] -= s; - } - tomoyo_warn_oom(__func__); - return false; -} - -/** - * tomoyo_commit_ok - Check memory quota. - * - * @data: Data to copy from. - * @size: Size in byte. - * - * Returns pointer to allocated memory on success, NULL otherwise. - * @data is zero-cleared on success. - * - * Caller holds tomoyo_policy_lock mutex. - */ -void *tomoyo_commit_ok(void *data, const unsigned int size) -{ - void *ptr = kzalloc(size, GFP_NOFS); - if (tomoyo_memory_ok(ptr)) { - memmove(ptr, data, size); - memset(data, 0, size); - return ptr; - } - kfree(ptr); - return NULL; -} - -/** - * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group". - * - * @param: Pointer to "struct tomoyo_acl_param". - * @idx: Index number. - * - * Returns pointer to "struct tomoyo_group" on success, NULL otherwise. - */ -struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param, - const u8 idx) -{ - struct tomoyo_group e = { }; - struct tomoyo_group *group = NULL; - struct list_head *list; - const char *group_name = tomoyo_read_token(param); - bool found = false; - if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP) - return NULL; - e.group_name = tomoyo_get_name(group_name); - if (!e.group_name) - return NULL; - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - goto out; - list = ¶m->ns->group_list[idx]; - list_for_each_entry(group, list, head.list) { - if (e.group_name != group->group_name || - atomic_read(&group->head.users) == TOMOYO_GC_IN_PROGRESS) - continue; - atomic_inc(&group->head.users); - found = true; - break; - } - if (!found) { - struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e)); - if (entry) { - INIT_LIST_HEAD(&entry->member_list); - atomic_set(&entry->head.users, 1); - list_add_tail_rcu(&entry->head.list, list); - group = entry; - found = true; - } - } - mutex_unlock(&tomoyo_policy_lock); -out: - tomoyo_put_name(e.group_name); - return found ? group : NULL; -} - -/* - * tomoyo_name_list is used for holding string data used by TOMOYO. - * Since same string data is likely used for multiple times (e.g. - * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of - * "const struct tomoyo_path_info *". - */ -struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; - -/** - * tomoyo_get_name - Allocate permanent memory for string data. - * - * @name: The string to store into the permernent memory. - * - * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. - */ -const struct tomoyo_path_info *tomoyo_get_name(const char *name) -{ - struct tomoyo_name *ptr; - unsigned int hash; - int len; - struct list_head *head; - - if (!name) - return NULL; - len = strlen(name) + 1; - hash = full_name_hash((const unsigned char *) name, len - 1); - head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; - if (mutex_lock_interruptible(&tomoyo_policy_lock)) - return NULL; - list_for_each_entry(ptr, head, head.list) { - if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name) || - atomic_read(&ptr->head.users) == TOMOYO_GC_IN_PROGRESS) - continue; - atomic_inc(&ptr->head.users); - goto out; - } - ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); - if (tomoyo_memory_ok(ptr)) { - ptr->entry.name = ((char *) ptr) + sizeof(*ptr); - memmove((char *) ptr->entry.name, name, len); - atomic_set(&ptr->head.users, 1); - tomoyo_fill_path_info(&ptr->entry); - list_add_tail(&ptr->head.list, head); - } else { - kfree(ptr); - ptr = NULL; - } -out: - mutex_unlock(&tomoyo_policy_lock); - return ptr ? &ptr->entry : NULL; -} - -/* Initial namespace.*/ -struct tomoyo_policy_namespace tomoyo_kernel_namespace; - -/** - * tomoyo_mm_init - Initialize mm related code. - */ -void __init tomoyo_mm_init(void) -{ - int idx; - for (idx = 0; idx < TOMOYO_MAX_HASH; idx++) - INIT_LIST_HEAD(&tomoyo_name_list[idx]); - tomoyo_kernel_namespace.name = "<kernel>"; - tomoyo_init_policy_namespace(&tomoyo_kernel_namespace); - tomoyo_kernel_domain.ns = &tomoyo_kernel_namespace; - INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); - tomoyo_kernel_domain.domainname = tomoyo_get_name("<kernel>"); - list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list); -} diff --git a/ANDROID_3.4.5/security/tomoyo/mount.c b/ANDROID_3.4.5/security/tomoyo/mount.c deleted file mode 100644 index fe00cdfd..00000000 --- a/ANDROID_3.4.5/security/tomoyo/mount.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * security/tomoyo/mount.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include <linux/slab.h> -#include "common.h" - -/* String table for special mount operations. */ -static const char * const tomoyo_mounts[TOMOYO_MAX_SPECIAL_MOUNT] = { - [TOMOYO_MOUNT_BIND] = "--bind", - [TOMOYO_MOUNT_MOVE] = "--move", - [TOMOYO_MOUNT_REMOUNT] = "--remount", - [TOMOYO_MOUNT_MAKE_UNBINDABLE] = "--make-unbindable", - [TOMOYO_MOUNT_MAKE_PRIVATE] = "--make-private", - [TOMOYO_MOUNT_MAKE_SLAVE] = "--make-slave", - [TOMOYO_MOUNT_MAKE_SHARED] = "--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) -{ - return tomoyo_supervisor(r, "file mount %s %s %s 0x%lX\n", - r->param.mount.dev->name, - r->param.mount.dir->name, - r->param.mount.type->name, - r->param.mount.flags); -} - -/** - * tomoyo_check_mount_acl - Check permission for path path path number operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @ptr: Pointer to "struct tomoyo_acl_info". - * - * Returns true if granted, false otherwise. - */ -static bool tomoyo_check_mount_acl(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_acl - Check permission for mount() operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @dev_name: Name of device file. Maybe NULL. - * @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, const char *type, - unsigned long flags) -{ - struct tomoyo_obj_info obj = { }; - struct path path; - 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; - r->obj = &obj; - - /* Get fstype. */ - requested_type = tomoyo_encode(type); - if (!requested_type) - goto out; - rtype.name = requested_type; - tomoyo_fill_path_info(&rtype); - - /* Get mount point. */ - obj.path2 = *dir; - 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 (type == tomoyo_mounts[TOMOYO_MOUNT_REMOUNT]) { - /* dev_name is ignored. */ - } else if (type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE] || - type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE] || - type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE] || - type == tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]) { - /* dev_name is ignored. */ - } else if (type == tomoyo_mounts[TOMOYO_MOUNT_BIND] || - type == tomoyo_mounts[TOMOYO_MOUNT_MOVE]) { - 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 (!dev_name || kern_path(dev_name, LOOKUP_FOLLOW, &path)) { - error = -ENOENT; - goto out; - } - obj.path1 = path; - requested_dev_name = tomoyo_realpath_from_path(&path); - if (!requested_dev_name) { - error = -ENOENT; - goto out; - } - } else { - /* Map dev_name to "<NULL>" if no dev_name given. */ - if (!dev_name) - dev_name = "<NULL>"; - requested_dev_name = tomoyo_encode(dev_name); - if (!requested_dev_name) { - error = -ENOMEM; - goto out; - } - } - 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; - 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); - if (fstype) - put_filesystem(fstype); - kfree(requested_type); - /* Drop refcount obtained by kern_path(). */ - if (obj.path1.dentry) - path_put(&obj.path1); - return error; -} - -/** - * tomoyo_mount_permission - Check permission for mount() operation. - * - * @dev_name: Name of device file. Maybe NULL. - * @path: Pointer to "struct path". - * @type: Name of filesystem type. Maybe NULL. - * @flags: Mount options. - * @data_page: Optional data. Maybe NULL. - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_mount_permission(char *dev_name, struct path *path, - const 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_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_mounts[TOMOYO_MOUNT_REMOUNT]; - flags &= ~MS_REMOUNT; - } else if (flags & MS_BIND) { - type = tomoyo_mounts[TOMOYO_MOUNT_BIND]; - flags &= ~MS_BIND; - } else if (flags & MS_SHARED) { - if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) - return -EINVAL; - type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SHARED]; - flags &= ~MS_SHARED; - } else if (flags & MS_PRIVATE) { - if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE)) - return -EINVAL; - type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_PRIVATE]; - flags &= ~MS_PRIVATE; - } else if (flags & MS_SLAVE) { - if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE)) - return -EINVAL; - type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_SLAVE]; - flags &= ~MS_SLAVE; - } else if (flags & MS_UNBINDABLE) { - if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE)) - return -EINVAL; - type = tomoyo_mounts[TOMOYO_MOUNT_MAKE_UNBINDABLE]; - flags &= ~MS_UNBINDABLE; - } else if (flags & MS_MOVE) { - type = tomoyo_mounts[TOMOYO_MOUNT_MOVE]; - flags &= ~MS_MOVE; - } - if (!type) - type = "<NULL>"; - idx = tomoyo_read_lock(); - error = tomoyo_mount_acl(&r, dev_name, path, type, flags); - tomoyo_read_unlock(idx); - return error; -} diff --git a/ANDROID_3.4.5/security/tomoyo/network.c b/ANDROID_3.4.5/security/tomoyo/network.c deleted file mode 100644 index 97527710..00000000 --- a/ANDROID_3.4.5/security/tomoyo/network.c +++ /dev/null @@ -1,771 +0,0 @@ -/* - * security/tomoyo/network.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include "common.h" -#include <linux/slab.h> - -/* Structure for holding inet domain socket's address. */ -struct tomoyo_inet_addr_info { - __be16 port; /* In network byte order. */ - const __be32 *address; /* In network byte order. */ - bool is_ipv6; -}; - -/* Structure for holding unix domain socket's address. */ -struct tomoyo_unix_addr_info { - u8 *addr; /* This may not be '\0' terminated string. */ - unsigned int addr_len; -}; - -/* Structure for holding socket address. */ -struct tomoyo_addr_info { - u8 protocol; - u8 operation; - struct tomoyo_inet_addr_info inet; - struct tomoyo_unix_addr_info unix0; -}; - -/* String table for socket's protocols. */ -const char * const tomoyo_proto_keyword[TOMOYO_SOCK_MAX] = { - [SOCK_STREAM] = "stream", - [SOCK_DGRAM] = "dgram", - [SOCK_RAW] = "raw", - [SOCK_SEQPACKET] = "seqpacket", - [0] = " ", /* Dummy for avoiding NULL pointer dereference. */ - [4] = " ", /* Dummy for avoiding NULL pointer dereference. */ -}; - -/** - * tomoyo_parse_ipaddr_union - Parse an IP address. - * - * @param: Pointer to "struct tomoyo_acl_param". - * @ptr: Pointer to "struct tomoyo_ipaddr_union". - * - * Returns true on success, false otherwise. - */ -bool tomoyo_parse_ipaddr_union(struct tomoyo_acl_param *param, - struct tomoyo_ipaddr_union *ptr) -{ - u8 * const min = ptr->ip[0].in6_u.u6_addr8; - u8 * const max = ptr->ip[1].in6_u.u6_addr8; - char *address = tomoyo_read_token(param); - const char *end; - - if (!strchr(address, ':') && - in4_pton(address, -1, min, '-', &end) > 0) { - ptr->is_ipv6 = false; - if (!*end) - ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0]; - else if (*end++ != '-' || - in4_pton(end, -1, max, '\0', &end) <= 0 || *end) - return false; - return true; - } - if (in6_pton(address, -1, min, '-', &end) > 0) { - ptr->is_ipv6 = true; - if (!*end) - memmove(max, min, sizeof(u16) * 8); - else if (*end++ != '-' || - in6_pton(end, -1, max, '\0', &end) <= 0 || *end) - return false; - return true; - } - return false; -} - -/** - * tomoyo_print_ipv4 - Print an IPv4 address. - * - * @buffer: Buffer to write to. - * @buffer_len: Size of @buffer. - * @min_ip: Pointer to __be32. - * @max_ip: Pointer to __be32. - * - * Returns nothing. - */ -static void tomoyo_print_ipv4(char *buffer, const unsigned int buffer_len, - const __be32 *min_ip, const __be32 *max_ip) -{ - snprintf(buffer, buffer_len, "%pI4%c%pI4", min_ip, - *min_ip == *max_ip ? '\0' : '-', max_ip); -} - -/** - * tomoyo_print_ipv6 - Print an IPv6 address. - * - * @buffer: Buffer to write to. - * @buffer_len: Size of @buffer. - * @min_ip: Pointer to "struct in6_addr". - * @max_ip: Pointer to "struct in6_addr". - * - * Returns nothing. - */ -static void tomoyo_print_ipv6(char *buffer, const unsigned int buffer_len, - const struct in6_addr *min_ip, - const struct in6_addr *max_ip) -{ - snprintf(buffer, buffer_len, "%pI6c%c%pI6c", min_ip, - !memcmp(min_ip, max_ip, 16) ? '\0' : '-', max_ip); -} - -/** - * tomoyo_print_ip - Print an IP address. - * - * @buf: Buffer to write to. - * @size: Size of @buf. - * @ptr: Pointer to "struct ipaddr_union". - * - * Returns nothing. - */ -void tomoyo_print_ip(char *buf, const unsigned int size, - const struct tomoyo_ipaddr_union *ptr) -{ - if (ptr->is_ipv6) - tomoyo_print_ipv6(buf, size, &ptr->ip[0], &ptr->ip[1]); - else - tomoyo_print_ipv4(buf, size, &ptr->ip[0].s6_addr32[0], - &ptr->ip[1].s6_addr32[0]); -} - -/* - * Mapping table from "enum tomoyo_network_acl_index" to - * "enum tomoyo_mac_index" for inet domain socket. - */ -static const u8 tomoyo_inet2mac -[TOMOYO_SOCK_MAX][TOMOYO_MAX_NETWORK_OPERATION] = { - [SOCK_STREAM] = { - [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_STREAM_BIND, - [TOMOYO_NETWORK_LISTEN] = - TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN, - [TOMOYO_NETWORK_CONNECT] = - TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT, - }, - [SOCK_DGRAM] = { - [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_DGRAM_BIND, - [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_INET_DGRAM_SEND, - }, - [SOCK_RAW] = { - [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_INET_RAW_BIND, - [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_INET_RAW_SEND, - }, -}; - -/* - * Mapping table from "enum tomoyo_network_acl_index" to - * "enum tomoyo_mac_index" for unix domain socket. - */ -static const u8 tomoyo_unix2mac -[TOMOYO_SOCK_MAX][TOMOYO_MAX_NETWORK_OPERATION] = { - [SOCK_STREAM] = { - [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND, - [TOMOYO_NETWORK_LISTEN] = - TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN, - [TOMOYO_NETWORK_CONNECT] = - TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT, - }, - [SOCK_DGRAM] = { - [TOMOYO_NETWORK_BIND] = TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND, - [TOMOYO_NETWORK_SEND] = TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND, - }, - [SOCK_SEQPACKET] = { - [TOMOYO_NETWORK_BIND] = - TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND, - [TOMOYO_NETWORK_LISTEN] = - TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN, - [TOMOYO_NETWORK_CONNECT] = - TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT, - }, -}; - -/** - * tomoyo_same_inet_acl - Check for duplicated "struct tomoyo_inet_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * - * Returns true if @a == @b except permission bits, false otherwise. - */ -static bool tomoyo_same_inet_acl(const struct tomoyo_acl_info *a, - const struct tomoyo_acl_info *b) -{ - const struct tomoyo_inet_acl *p1 = container_of(a, typeof(*p1), head); - const struct tomoyo_inet_acl *p2 = container_of(b, typeof(*p2), head); - - return p1->protocol == p2->protocol && - tomoyo_same_ipaddr_union(&p1->address, &p2->address) && - tomoyo_same_number_union(&p1->port, &p2->port); -} - -/** - * tomoyo_same_unix_acl - Check for duplicated "struct tomoyo_unix_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * - * Returns true if @a == @b except permission bits, false otherwise. - */ -static bool tomoyo_same_unix_acl(const struct tomoyo_acl_info *a, - const struct tomoyo_acl_info *b) -{ - const struct tomoyo_unix_acl *p1 = container_of(a, typeof(*p1), head); - const struct tomoyo_unix_acl *p2 = container_of(b, typeof(*p2), head); - - return p1->protocol == p2->protocol && - tomoyo_same_name_union(&p1->name, &p2->name); -} - -/** - * tomoyo_merge_inet_acl - Merge duplicated "struct tomoyo_inet_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * @is_delete: True for @a &= ~@b, false for @a |= @b. - * - * Returns true if @a is empty, false otherwise. - */ -static bool tomoyo_merge_inet_acl(struct tomoyo_acl_info *a, - struct tomoyo_acl_info *b, - const bool is_delete) -{ - u8 * const a_perm = - &container_of(a, struct tomoyo_inet_acl, head)->perm; - u8 perm = *a_perm; - const u8 b_perm = container_of(b, struct tomoyo_inet_acl, head)->perm; - - if (is_delete) - perm &= ~b_perm; - else - perm |= b_perm; - *a_perm = perm; - return !perm; -} - -/** - * tomoyo_merge_unix_acl - Merge duplicated "struct tomoyo_unix_acl" entry. - * - * @a: Pointer to "struct tomoyo_acl_info". - * @b: Pointer to "struct tomoyo_acl_info". - * @is_delete: True for @a &= ~@b, false for @a |= @b. - * - * Returns true if @a is empty, false otherwise. - */ -static bool tomoyo_merge_unix_acl(struct tomoyo_acl_info *a, - struct tomoyo_acl_info *b, - const bool is_delete) -{ - u8 * const a_perm = - &container_of(a, struct tomoyo_unix_acl, head)->perm; - u8 perm = *a_perm; - const u8 b_perm = container_of(b, struct tomoyo_unix_acl, head)->perm; - - if (is_delete) - perm &= ~b_perm; - else - perm |= b_perm; - *a_perm = perm; - return !perm; -} - -/** - * tomoyo_write_inet_network - Write "struct tomoyo_inet_acl" list. - * - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns 0 on success, negative value otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -int tomoyo_write_inet_network(struct tomoyo_acl_param *param) -{ - struct tomoyo_inet_acl e = { .head.type = TOMOYO_TYPE_INET_ACL }; - int error = -EINVAL; - u8 type; - const char *protocol = tomoyo_read_token(param); - const char *operation = tomoyo_read_token(param); - - for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++) - if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol])) - break; - for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++) - if (tomoyo_permstr(operation, tomoyo_socket_keyword[type])) - e.perm |= 1 << type; - if (e.protocol == TOMOYO_SOCK_MAX || !e.perm) - return -EINVAL; - if (param->data[0] == '@') { - param->data++; - e.address.group = - tomoyo_get_group(param, TOMOYO_ADDRESS_GROUP); - if (!e.address.group) - return -ENOMEM; - } else { - if (!tomoyo_parse_ipaddr_union(param, &e.address)) - goto out; - } - if (!tomoyo_parse_number_union(param, &e.port) || - e.port.values[1] > 65535) - goto out; - error = tomoyo_update_domain(&e.head, sizeof(e), param, - tomoyo_same_inet_acl, - tomoyo_merge_inet_acl); -out: - tomoyo_put_group(e.address.group); - tomoyo_put_number_union(&e.port); - return error; -} - -/** - * tomoyo_write_unix_network - Write "struct tomoyo_unix_acl" list. - * - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_write_unix_network(struct tomoyo_acl_param *param) -{ - struct tomoyo_unix_acl e = { .head.type = TOMOYO_TYPE_UNIX_ACL }; - int error; - u8 type; - const char *protocol = tomoyo_read_token(param); - const char *operation = tomoyo_read_token(param); - - for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++) - if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol])) - break; - for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++) - if (tomoyo_permstr(operation, tomoyo_socket_keyword[type])) - e.perm |= 1 << type; - if (e.protocol == TOMOYO_SOCK_MAX || !e.perm) - return -EINVAL; - if (!tomoyo_parse_name_union(param, &e.name)) - return -EINVAL; - error = tomoyo_update_domain(&e.head, sizeof(e), param, - tomoyo_same_unix_acl, - tomoyo_merge_unix_acl); - tomoyo_put_name_union(&e.name); - return error; -} - -/** - * tomoyo_audit_net_log - Audit network log. - * - * @r: Pointer to "struct tomoyo_request_info". - * @family: Name of socket family ("inet" or "unix"). - * @protocol: Name of protocol in @family. - * @operation: Name of socket operation. - * @address: Name of address. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_audit_net_log(struct tomoyo_request_info *r, - const char *family, const u8 protocol, - const u8 operation, const char *address) -{ - return tomoyo_supervisor(r, "network %s %s %s %s\n", family, - tomoyo_proto_keyword[protocol], - tomoyo_socket_keyword[operation], address); -} - -/** - * tomoyo_audit_inet_log - Audit INET network log. - * - * @r: Pointer to "struct tomoyo_request_info". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_audit_inet_log(struct tomoyo_request_info *r) -{ - char buf[128]; - int len; - const __be32 *address = r->param.inet_network.address; - - if (r->param.inet_network.is_ipv6) - tomoyo_print_ipv6(buf, sizeof(buf), (const struct in6_addr *) - address, (const struct in6_addr *) address); - else - tomoyo_print_ipv4(buf, sizeof(buf), address, address); - len = strlen(buf); - snprintf(buf + len, sizeof(buf) - len, " %u", - r->param.inet_network.port); - return tomoyo_audit_net_log(r, "inet", r->param.inet_network.protocol, - r->param.inet_network.operation, buf); -} - -/** - * tomoyo_audit_unix_log - Audit UNIX network log. - * - * @r: Pointer to "struct tomoyo_request_info". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_audit_unix_log(struct tomoyo_request_info *r) -{ - return tomoyo_audit_net_log(r, "unix", r->param.unix_network.protocol, - r->param.unix_network.operation, - r->param.unix_network.address->name); -} - -/** - * tomoyo_check_inet_acl - Check permission for inet domain socket operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @ptr: Pointer to "struct tomoyo_acl_info". - * - * Returns true if granted, false otherwise. - */ -static bool tomoyo_check_inet_acl(struct tomoyo_request_info *r, - const struct tomoyo_acl_info *ptr) -{ - const struct tomoyo_inet_acl *acl = - container_of(ptr, typeof(*acl), head); - const u8 size = r->param.inet_network.is_ipv6 ? 16 : 4; - - if (!(acl->perm & (1 << r->param.inet_network.operation)) || - !tomoyo_compare_number_union(r->param.inet_network.port, - &acl->port)) - return false; - if (acl->address.group) - return tomoyo_address_matches_group - (r->param.inet_network.is_ipv6, - r->param.inet_network.address, acl->address.group); - return acl->address.is_ipv6 == r->param.inet_network.is_ipv6 && - memcmp(&acl->address.ip[0], - r->param.inet_network.address, size) <= 0 && - memcmp(r->param.inet_network.address, - &acl->address.ip[1], size) <= 0; -} - -/** - * tomoyo_check_unix_acl - Check permission for unix domain socket operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @ptr: Pointer to "struct tomoyo_acl_info". - * - * Returns true if granted, false otherwise. - */ -static bool tomoyo_check_unix_acl(struct tomoyo_request_info *r, - const struct tomoyo_acl_info *ptr) -{ - const struct tomoyo_unix_acl *acl = - container_of(ptr, typeof(*acl), head); - - return (acl->perm & (1 << r->param.unix_network.operation)) && - tomoyo_compare_name_union(r->param.unix_network.address, - &acl->name); -} - -/** - * tomoyo_inet_entry - Check permission for INET network operation. - * - * @address: Pointer to "struct tomoyo_addr_info". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_inet_entry(const struct tomoyo_addr_info *address) -{ - const int idx = tomoyo_read_lock(); - struct tomoyo_request_info r; - int error = 0; - const u8 type = tomoyo_inet2mac[address->protocol][address->operation]; - - if (type && tomoyo_init_request_info(&r, NULL, type) - != TOMOYO_CONFIG_DISABLED) { - r.param_type = TOMOYO_TYPE_INET_ACL; - r.param.inet_network.protocol = address->protocol; - r.param.inet_network.operation = address->operation; - r.param.inet_network.is_ipv6 = address->inet.is_ipv6; - r.param.inet_network.address = address->inet.address; - r.param.inet_network.port = ntohs(address->inet.port); - do { - tomoyo_check_acl(&r, tomoyo_check_inet_acl); - error = tomoyo_audit_inet_log(&r); - } while (error == TOMOYO_RETRY_REQUEST); - } - tomoyo_read_unlock(idx); - return error; -} - -/** - * tomoyo_check_inet_address - Check permission for inet domain socket's operation. - * - * @addr: Pointer to "struct sockaddr". - * @addr_len: Size of @addr. - * @port: Port number. - * @address: Pointer to "struct tomoyo_addr_info". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_check_inet_address(const struct sockaddr *addr, - const unsigned int addr_len, - const u16 port, - struct tomoyo_addr_info *address) -{ - struct tomoyo_inet_addr_info *i = &address->inet; - - switch (addr->sa_family) { - case AF_INET6: - if (addr_len < SIN6_LEN_RFC2133) - goto skip; - i->is_ipv6 = true; - i->address = (__be32 *) - ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr; - i->port = ((struct sockaddr_in6 *) addr)->sin6_port; - break; - case AF_INET: - if (addr_len < sizeof(struct sockaddr_in)) - goto skip; - i->is_ipv6 = false; - i->address = (__be32 *) - &((struct sockaddr_in *) addr)->sin_addr; - i->port = ((struct sockaddr_in *) addr)->sin_port; - break; - default: - goto skip; - } - if (address->protocol == SOCK_RAW) - i->port = htons(port); - return tomoyo_inet_entry(address); -skip: - return 0; -} - -/** - * tomoyo_unix_entry - Check permission for UNIX network operation. - * - * @address: Pointer to "struct tomoyo_addr_info". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_unix_entry(const struct tomoyo_addr_info *address) -{ - const int idx = tomoyo_read_lock(); - struct tomoyo_request_info r; - int error = 0; - const u8 type = tomoyo_unix2mac[address->protocol][address->operation]; - - if (type && tomoyo_init_request_info(&r, NULL, type) - != TOMOYO_CONFIG_DISABLED) { - char *buf = address->unix0.addr; - int len = address->unix0.addr_len - sizeof(sa_family_t); - - if (len <= 0) { - buf = "anonymous"; - len = 9; - } else if (buf[0]) { - len = strnlen(buf, len); - } - buf = tomoyo_encode2(buf, len); - if (buf) { - struct tomoyo_path_info addr; - - addr.name = buf; - tomoyo_fill_path_info(&addr); - r.param_type = TOMOYO_TYPE_UNIX_ACL; - r.param.unix_network.protocol = address->protocol; - r.param.unix_network.operation = address->operation; - r.param.unix_network.address = &addr; - do { - tomoyo_check_acl(&r, tomoyo_check_unix_acl); - error = tomoyo_audit_unix_log(&r); - } while (error == TOMOYO_RETRY_REQUEST); - kfree(buf); - } else - error = -ENOMEM; - } - tomoyo_read_unlock(idx); - return error; -} - -/** - * tomoyo_check_unix_address - Check permission for unix domain socket's operation. - * - * @addr: Pointer to "struct sockaddr". - * @addr_len: Size of @addr. - * @address: Pointer to "struct tomoyo_addr_info". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_check_unix_address(struct sockaddr *addr, - const unsigned int addr_len, - struct tomoyo_addr_info *address) -{ - struct tomoyo_unix_addr_info *u = &address->unix0; - - if (addr->sa_family != AF_UNIX) - return 0; - u->addr = ((struct sockaddr_un *) addr)->sun_path; - u->addr_len = addr_len; - return tomoyo_unix_entry(address); -} - -/** - * tomoyo_kernel_service - Check whether I'm kernel service or not. - * - * Returns true if I'm kernel service, false otherwise. - */ -static bool tomoyo_kernel_service(void) -{ - /* Nothing to do if I am a kernel service. */ - return segment_eq(get_fs(), KERNEL_DS); -} - -/** - * tomoyo_sock_family - Get socket's family. - * - * @sk: Pointer to "struct sock". - * - * Returns one of PF_INET, PF_INET6, PF_UNIX or 0. - */ -static u8 tomoyo_sock_family(struct sock *sk) -{ - u8 family; - - if (tomoyo_kernel_service()) - return 0; - family = sk->sk_family; - switch (family) { - case PF_INET: - case PF_INET6: - case PF_UNIX: - return family; - default: - return 0; - } -} - -/** - * tomoyo_socket_listen_permission - Check permission for listening a socket. - * - * @sock: Pointer to "struct socket". - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_socket_listen_permission(struct socket *sock) -{ - struct tomoyo_addr_info address; - const u8 family = tomoyo_sock_family(sock->sk); - const unsigned int type = sock->type; - struct sockaddr_storage addr; - int addr_len; - - if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET)) - return 0; - { - const int error = sock->ops->getname(sock, (struct sockaddr *) - &addr, &addr_len, 0); - - if (error) - return error; - } - address.protocol = type; - address.operation = TOMOYO_NETWORK_LISTEN; - if (family == PF_UNIX) - return tomoyo_check_unix_address((struct sockaddr *) &addr, - addr_len, &address); - return tomoyo_check_inet_address((struct sockaddr *) &addr, addr_len, - 0, &address); -} - -/** - * tomoyo_socket_connect_permission - Check permission for setting the remote address of a socket. - * - * @sock: Pointer to "struct socket". - * @addr: Pointer to "struct sockaddr". - * @addr_len: Size of @addr. - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_socket_connect_permission(struct socket *sock, - struct sockaddr *addr, int addr_len) -{ - struct tomoyo_addr_info address; - const u8 family = tomoyo_sock_family(sock->sk); - const unsigned int type = sock->type; - - if (!family) - return 0; - address.protocol = type; - switch (type) { - case SOCK_DGRAM: - case SOCK_RAW: - address.operation = TOMOYO_NETWORK_SEND; - break; - case SOCK_STREAM: - case SOCK_SEQPACKET: - address.operation = TOMOYO_NETWORK_CONNECT; - break; - default: - return 0; - } - if (family == PF_UNIX) - return tomoyo_check_unix_address(addr, addr_len, &address); - return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol, - &address); -} - -/** - * tomoyo_socket_bind_permission - Check permission for setting the local address of a socket. - * - * @sock: Pointer to "struct socket". - * @addr: Pointer to "struct sockaddr". - * @addr_len: Size of @addr. - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_socket_bind_permission(struct socket *sock, struct sockaddr *addr, - int addr_len) -{ - struct tomoyo_addr_info address; - const u8 family = tomoyo_sock_family(sock->sk); - const unsigned int type = sock->type; - - if (!family) - return 0; - switch (type) { - case SOCK_STREAM: - case SOCK_DGRAM: - case SOCK_RAW: - case SOCK_SEQPACKET: - address.protocol = type; - address.operation = TOMOYO_NETWORK_BIND; - break; - default: - return 0; - } - if (family == PF_UNIX) - return tomoyo_check_unix_address(addr, addr_len, &address); - return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol, - &address); -} - -/** - * tomoyo_socket_sendmsg_permission - Check permission for sending a datagram. - * - * @sock: Pointer to "struct socket". - * @msg: Pointer to "struct msghdr". - * @size: Unused. - * - * Returns 0 on success, negative value otherwise. - */ -int tomoyo_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg, - int size) -{ - struct tomoyo_addr_info address; - const u8 family = tomoyo_sock_family(sock->sk); - const unsigned int type = sock->type; - - if (!msg->msg_name || !family || - (type != SOCK_DGRAM && type != SOCK_RAW)) - return 0; - address.protocol = type; - address.operation = TOMOYO_NETWORK_SEND; - if (family == PF_UNIX) - return tomoyo_check_unix_address((struct sockaddr *) - msg->msg_name, - msg->msg_namelen, &address); - return tomoyo_check_inet_address((struct sockaddr *) msg->msg_name, - msg->msg_namelen, - sock->sk->sk_protocol, &address); -} diff --git a/ANDROID_3.4.5/security/tomoyo/realpath.c b/ANDROID_3.4.5/security/tomoyo/realpath.c deleted file mode 100644 index 80a09c37..00000000 --- a/ANDROID_3.4.5/security/tomoyo/realpath.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * security/tomoyo/realpath.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include "common.h" -#include <linux/magic.h> - -/** - * tomoyo_encode2 - Encode binary string to ascii string. - * - * @str: String in binary format. - * @str_len: Size of @str in byte. - * - * 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. - */ -char *tomoyo_encode2(const char *str, int str_len) -{ - int i; - int len = 0; - const char *p = str; - char *cp; - char *cp0; - - if (!p) - return NULL; - for (i = 0; i < str_len; i++) { - const unsigned char c = p[i]; - - 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; - for (i = 0; i < str_len; i++) { - const unsigned char c = p[i]; - - 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_encode - 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. - */ -char *tomoyo_encode(const char *str) -{ - return str ? tomoyo_encode2(str, strlen(str)) : NULL; -} - -/** - * tomoyo_get_absolute_path - Get the path of a dentry but ignores chroot'ed root. - * - * @path: Pointer to "struct path". - * @buffer: Pointer to buffer to return value in. - * @buflen: Sizeof @buffer. - * - * Returns the buffer on success, an error code otherwise. - * - * If dentry is a directory, trailing '/' is appended. - */ -static char *tomoyo_get_absolute_path(struct path *path, char * const buffer, - const int buflen) -{ - char *pos = ERR_PTR(-ENOMEM); - if (buflen >= 256) { - /* go to whatever namespace root we are under */ - pos = d_absolute_path(path, buffer, buflen - 1); - if (!IS_ERR(pos) && *pos == '/' && pos[1]) { - struct inode *inode = path->dentry->d_inode; - if (inode && S_ISDIR(inode->i_mode)) { - buffer[buflen - 2] = '/'; - buffer[buflen - 1] = '\0'; - } - } - } - return pos; -} - -/** - * tomoyo_get_dentry_path - Get the path of a dentry. - * - * @dentry: Pointer to "struct dentry". - * @buffer: Pointer to buffer to return value in. - * @buflen: Sizeof @buffer. - * - * Returns the buffer on success, an error code otherwise. - * - * If dentry is a directory, trailing '/' is appended. - */ -static char *tomoyo_get_dentry_path(struct dentry *dentry, char * const buffer, - const int buflen) -{ - char *pos = ERR_PTR(-ENOMEM); - if (buflen >= 256) { - pos = dentry_path_raw(dentry, buffer, buflen - 1); - if (!IS_ERR(pos) && *pos == '/' && pos[1]) { - struct inode *inode = dentry->d_inode; - if (inode && S_ISDIR(inode->i_mode)) { - buffer[buflen - 2] = '/'; - buffer[buflen - 1] = '\0'; - } - } - } - return pos; -} - -/** - * tomoyo_get_local_path - Get the path of a dentry. - * - * @dentry: Pointer to "struct dentry". - * @buffer: Pointer to buffer to return value in. - * @buflen: Sizeof @buffer. - * - * Returns the buffer on success, an error code otherwise. - */ -static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer, - const int buflen) -{ - struct super_block *sb = dentry->d_sb; - char *pos = tomoyo_get_dentry_path(dentry, buffer, buflen); - if (IS_ERR(pos)) - return pos; - /* Convert from $PID to self if $PID is current thread. */ - if (sb->s_magic == PROC_SUPER_MAGIC && *pos == '/') { - char *ep; - const pid_t pid = (pid_t) simple_strtoul(pos + 1, &ep, 10); - if (*ep == '/' && pid && pid == - task_tgid_nr_ns(current, sb->s_fs_info)) { - pos = ep - 5; - if (pos < buffer) - goto out; - memmove(pos, "/self", 5); - } - goto prepend_filesystem_name; - } - /* Use filesystem name for unnamed devices. */ - if (!MAJOR(sb->s_dev)) - goto prepend_filesystem_name; - { - struct inode *inode = sb->s_root->d_inode; - /* - * Use filesystem name if filesystem does not support rename() - * operation. - */ - if (inode->i_op && !inode->i_op->rename) - goto prepend_filesystem_name; - } - /* Prepend device name. */ - { - char name[64]; - int name_len; - const dev_t dev = sb->s_dev; - name[sizeof(name) - 1] = '\0'; - snprintf(name, sizeof(name) - 1, "dev(%u,%u):", MAJOR(dev), - MINOR(dev)); - name_len = strlen(name); - pos -= name_len; - if (pos < buffer) - goto out; - memmove(pos, name, name_len); - return pos; - } - /* Prepend filesystem name. */ -prepend_filesystem_name: - { - const char *name = sb->s_type->name; - const int name_len = strlen(name); - pos -= name_len + 1; - if (pos < buffer) - goto out; - memmove(pos, name, name_len); - pos[name_len] = ':'; - } - return pos; -out: - return ERR_PTR(-ENOMEM); -} - -/** - * tomoyo_get_socket_name - Get the name of a socket. - * - * @path: Pointer to "struct path". - * @buffer: Pointer to buffer to return value in. - * @buflen: Sizeof @buffer. - * - * Returns the buffer. - */ -static char *tomoyo_get_socket_name(struct path *path, char * const buffer, - const int buflen) -{ - struct inode *inode = path->dentry->d_inode; - struct socket *sock = inode ? SOCKET_I(inode) : NULL; - struct sock *sk = sock ? sock->sk : NULL; - if (sk) { - snprintf(buffer, buflen, "socket:[family=%u:type=%u:" - "protocol=%u]", sk->sk_family, sk->sk_type, - sk->sk_protocol); - } else { - snprintf(buffer, buflen, "socket:[unknown]"); - } - return buffer; -} - -/** - * 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. - * - * 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. - */ -char *tomoyo_realpath_from_path(struct path *path) -{ - char *buf = NULL; - char *name = NULL; - unsigned int buf_len = PAGE_SIZE / 2; - struct dentry *dentry = path->dentry; - struct super_block *sb; - if (!dentry) - return NULL; - sb = dentry->d_sb; - while (1) { - char *pos; - struct inode *inode; - buf_len <<= 1; - kfree(buf); - buf = kmalloc(buf_len, GFP_NOFS); - if (!buf) - break; - /* To make sure that pos is '\0' terminated. */ - buf[buf_len - 1] = '\0'; - /* Get better name for socket. */ - if (sb->s_magic == SOCKFS_MAGIC) { - pos = tomoyo_get_socket_name(path, buf, buf_len - 1); - goto encode; - } - /* For "pipe:[\$]". */ - if (dentry->d_op && dentry->d_op->d_dname) { - pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1); - goto encode; - } - inode = sb->s_root->d_inode; - /* - * Get local name for filesystems without rename() operation - * or dentry without vfsmount. - */ - if (!path->mnt || (inode->i_op && !inode->i_op->rename)) - pos = tomoyo_get_local_path(path->dentry, buf, - buf_len - 1); - /* Get absolute name for the rest. */ - else { - pos = tomoyo_get_absolute_path(path, buf, buf_len - 1); - /* - * Fall back to local name if absolute name is not - * available. - */ - if (pos == ERR_PTR(-EINVAL)) - pos = tomoyo_get_local_path(path->dentry, buf, - buf_len - 1); - } -encode: - if (IS_ERR(pos)) - continue; - name = tomoyo_encode(pos); - break; - } - kfree(buf); - if (!name) - tomoyo_warn_oom(__func__); - return name; -} - -/** - * tomoyo_realpath_nofollow - Get realpath of a pathname. - * - * @pathname: The pathname to solve. - * - * Returns the realpath of @pathname on success, NULL otherwise. - */ -char *tomoyo_realpath_nofollow(const char *pathname) -{ - struct path path; - - if (pathname && kern_path(pathname, 0, &path) == 0) { - char *buf = tomoyo_realpath_from_path(&path); - path_put(&path); - return buf; - } - return NULL; -} diff --git a/ANDROID_3.4.5/security/tomoyo/securityfs_if.c b/ANDROID_3.4.5/security/tomoyo/securityfs_if.c deleted file mode 100644 index 8592f2fc..00000000 --- a/ANDROID_3.4.5/security/tomoyo/securityfs_if.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * security/tomoyo/securityfs_if.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include <linux/security.h> -#include "common.h" - -/** - * tomoyo_check_task_acl - Check permission for task operation. - * - * @r: Pointer to "struct tomoyo_request_info". - * @ptr: Pointer to "struct tomoyo_acl_info". - * - * Returns true if granted, false otherwise. - */ -static bool tomoyo_check_task_acl(struct tomoyo_request_info *r, - const struct tomoyo_acl_info *ptr) -{ - const struct tomoyo_task_acl *acl = container_of(ptr, typeof(*acl), - head); - return !tomoyo_pathcmp(r->param.task.domainname, acl->domainname); -} - -/** - * tomoyo_write_self - write() for /sys/kernel/security/tomoyo/self_domain interface. - * - * @file: Pointer to "struct file". - * @buf: Domainname to transit to. - * @count: Size of @buf. - * @ppos: Unused. - * - * Returns @count on success, negative value otherwise. - * - * If domain transition was permitted but the domain transition failed, this - * function returns error rather than terminating current thread with SIGKILL. - */ -static ssize_t tomoyo_write_self(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - char *data; - int error; - if (!count || count >= TOMOYO_EXEC_TMPSIZE - 10) - return -ENOMEM; - data = kzalloc(count + 1, GFP_NOFS); - if (!data) - return -ENOMEM; - if (copy_from_user(data, buf, count)) { - error = -EFAULT; - goto out; - } - tomoyo_normalize_line(data); - if (tomoyo_correct_domain(data)) { - const int idx = tomoyo_read_lock(); - struct tomoyo_path_info name; - struct tomoyo_request_info r; - name.name = data; - tomoyo_fill_path_info(&name); - /* Check "task manual_domain_transition" permission. */ - tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE); - r.param_type = TOMOYO_TYPE_MANUAL_TASK_ACL; - r.param.task.domainname = &name; - tomoyo_check_acl(&r, tomoyo_check_task_acl); - if (!r.granted) - error = -EPERM; - else { - struct tomoyo_domain_info *new_domain = - tomoyo_assign_domain(data, true); - if (!new_domain) { - error = -ENOENT; - } else { - struct cred *cred = prepare_creds(); - if (!cred) { - error = -ENOMEM; - } else { - struct tomoyo_domain_info *old_domain = - cred->security; - cred->security = new_domain; - atomic_inc(&new_domain->users); - atomic_dec(&old_domain->users); - commit_creds(cred); - error = 0; - } - } - } - tomoyo_read_unlock(idx); - } else - error = -EINVAL; -out: - kfree(data); - return error ? error : count; -} - -/** - * tomoyo_read_self - read() for /sys/kernel/security/tomoyo/self_domain interface. - * - * @file: Pointer to "struct file". - * @buf: Domainname which current thread belongs to. - * @count: Size of @buf. - * @ppos: Bytes read by now. - * - * Returns read size on success, negative value otherwise. - */ -static ssize_t tomoyo_read_self(struct file *file, char __user *buf, - size_t count, loff_t *ppos) -{ - const char *domain = tomoyo_domain()->domainname->name; - loff_t len = strlen(domain); - loff_t pos = *ppos; - if (pos >= len || !count) - return 0; - len -= pos; - if (count < len) - len = count; - if (copy_to_user(buf, domain + pos, len)) - return -EFAULT; - *ppos += len; - return len; -} - -/* Operations for /sys/kernel/security/tomoyo/self_domain interface. */ -static const struct file_operations tomoyo_self_operations = { - .write = tomoyo_write_self, - .read = tomoyo_read_self, -}; - -/** - * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface. - * - * @inode: Pointer to "struct inode". - * @file: Pointer to "struct file". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_open(struct inode *inode, struct file *file) -{ - const int key = ((u8 *) file->f_path.dentry->d_inode->i_private) - - ((u8 *) NULL); - return tomoyo_open_control(key, file); -} - -/** - * tomoyo_release - close() for /sys/kernel/security/tomoyo/ interface. - * - * @inode: Pointer to "struct inode". - * @file: Pointer to "struct file". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_release(struct inode *inode, struct file *file) -{ - return tomoyo_close_control(file->private_data); -} - -/** - * tomoyo_poll - poll() for /sys/kernel/security/tomoyo/ interface. - * - * @file: Pointer to "struct file". - * @wait: Pointer to "poll_table". Maybe NULL. - * - * Returns POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM if ready to read/write, - * POLLOUT | POLLWRNORM otherwise. - */ -static unsigned int tomoyo_poll(struct file *file, poll_table *wait) -{ - return tomoyo_poll_control(file, wait); -} - -/** - * tomoyo_read - read() for /sys/kernel/security/tomoyo/ interface. - * - * @file: Pointer to "struct file". - * @buf: Pointer to buffer. - * @count: Size of @buf. - * @ppos: Unused. - * - * Returns bytes read on success, negative value otherwise. - */ -static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - return tomoyo_read_control(file->private_data, buf, count); -} - -/** - * tomoyo_write - write() for /sys/kernel/security/tomoyo/ interface. - * - * @file: Pointer to "struct file". - * @buf: Pointer to buffer. - * @count: Size of @buf. - * @ppos: Unused. - * - * Returns @count on success, negative value otherwise. - */ -static ssize_t tomoyo_write(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - return tomoyo_write_control(file->private_data, buf, count); -} - -/* - * tomoyo_operations is a "struct file_operations" which is used for handling - * /sys/kernel/security/tomoyo/ interface. - * - * Some files under /sys/kernel/security/tomoyo/ directory accept open(O_RDWR). - * See tomoyo_io_buffer for internals. - */ -static const struct file_operations tomoyo_operations = { - .open = tomoyo_open, - .release = tomoyo_release, - .poll = tomoyo_poll, - .read = tomoyo_read, - .write = tomoyo_write, - .llseek = noop_llseek, -}; - -/** - * tomoyo_create_entry - Create interface files under /sys/kernel/security/tomoyo/ directory. - * - * @name: The name of the interface file. - * @mode: The permission of the interface file. - * @parent: The parent directory. - * @key: Type of interface. - * - * Returns nothing. - */ -static void __init tomoyo_create_entry(const char *name, const umode_t mode, - struct dentry *parent, const u8 key) -{ - securityfs_create_file(name, mode, parent, ((u8 *) NULL) + key, - &tomoyo_operations); -} - -/** - * tomoyo_initerface_init - Initialize /sys/kernel/security/tomoyo/ interface. - * - * Returns 0. - */ -static int __init tomoyo_initerface_init(void) -{ - struct dentry *tomoyo_dir; - - /* Don't create securityfs entries unless registered. */ - if (current_cred()->security != &tomoyo_kernel_domain) - 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, - TOMOYO_EXCEPTIONPOLICY); - tomoyo_create_entry("audit", 0400, tomoyo_dir, - TOMOYO_AUDIT); - tomoyo_create_entry(".process_status", 0600, tomoyo_dir, - TOMOYO_PROCESS_STATUS); - tomoyo_create_entry("stat", 0644, tomoyo_dir, - TOMOYO_STAT); - tomoyo_create_entry("profile", 0600, tomoyo_dir, - TOMOYO_PROFILE); - tomoyo_create_entry("manager", 0600, tomoyo_dir, - TOMOYO_MANAGER); - tomoyo_create_entry("version", 0400, tomoyo_dir, - TOMOYO_VERSION); - securityfs_create_file("self_domain", 0666, tomoyo_dir, NULL, - &tomoyo_self_operations); - tomoyo_load_builtin_policy(); - return 0; -} - -fs_initcall(tomoyo_initerface_init); diff --git a/ANDROID_3.4.5/security/tomoyo/tomoyo.c b/ANDROID_3.4.5/security/tomoyo/tomoyo.c deleted file mode 100644 index 620d37c1..00000000 --- a/ANDROID_3.4.5/security/tomoyo/tomoyo.c +++ /dev/null @@ -1,560 +0,0 @@ -/* - * security/tomoyo/tomoyo.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include <linux/security.h> -#include "common.h" - -/** - * tomoyo_cred_alloc_blank - Target for security_cred_alloc_blank(). - * - * @new: Pointer to "struct cred". - * @gfp: Memory allocation flags. - * - * Returns 0. - */ -static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) -{ - new->security = NULL; - return 0; -} - -/** - * tomoyo_cred_prepare - Target for security_prepare_creds(). - * - * @new: Pointer to "struct cred". - * @old: Pointer to "struct cred". - * @gfp: Memory allocation flags. - * - * Returns 0. - */ -static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, - gfp_t gfp) -{ - struct tomoyo_domain_info *domain = old->security; - new->security = domain; - if (domain) - atomic_inc(&domain->users); - return 0; -} - -/** - * tomoyo_cred_transfer - Target for security_transfer_creds(). - * - * @new: Pointer to "struct cred". - * @old: Pointer to "struct cred". - */ -static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) -{ - tomoyo_cred_prepare(new, old, 0); -} - -/** - * tomoyo_cred_free - Target for security_cred_free(). - * - * @cred: Pointer to "struct cred". - */ -static void tomoyo_cred_free(struct cred *cred) -{ - struct tomoyo_domain_info *domain = cred->security; - if (domain) - atomic_dec(&domain->users); -} - -/** - * tomoyo_bprm_set_creds - Target for security_bprm_set_creds(). - * - * @bprm: Pointer to "struct linux_binprm". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) -{ - int rc; - - rc = cap_bprm_set_creds(bprm); - if (rc) - return rc; - - /* - * Do only if this function is called for the first time of an execve - * operation. - */ - if (bprm->cred_prepared) - return 0; -#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER - /* - * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested - * for the first time. - */ - if (!tomoyo_policy_loaded) - tomoyo_load_policy(bprm->filename); -#endif - /* - * Release reference to "struct tomoyo_domain_info" stored inside - * "bprm->cred->security". New reference to "struct tomoyo_domain_info" - * stored inside "bprm->cred->security" will be acquired later inside - * tomoyo_find_next_domain(). - */ - atomic_dec(&((struct tomoyo_domain_info *) - bprm->cred->security)->users); - /* - * Tell tomoyo_bprm_check_security() is called for the first time of an - * execve operation. - */ - bprm->cred->security = NULL; - return 0; -} - -/** - * tomoyo_bprm_check_security - Target for security_bprm_check(). - * - * @bprm: Pointer to "struct linux_binprm". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_bprm_check_security(struct linux_binprm *bprm) -{ - struct tomoyo_domain_info *domain = bprm->cred->security; - - /* - * Execute permission is checked against pathname passed to do_execve() - * using current domain. - */ - if (!domain) { - const int idx = tomoyo_read_lock(); - const int err = tomoyo_find_next_domain(bprm); - tomoyo_read_unlock(idx); - return err; - } - /* - * Read permission is checked against interpreters using next domain. - */ - return tomoyo_check_open_permission(domain, &bprm->file->f_path, - O_RDONLY); -} - -/** - * tomoyo_inode_getattr - Target for security_inode_getattr(). - * - * @mnt: Pointer to "struct vfsmount". - * @dentry: Pointer to "struct dentry". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) -{ - struct path path = { mnt, dentry }; - return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path, NULL); -} - -/** - * tomoyo_path_truncate - Target for security_path_truncate(). - * - * @path: Pointer to "struct path". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_truncate(struct path *path) -{ - return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path, NULL); -} - -/** - * tomoyo_path_unlink - Target for security_path_unlink(). - * - * @parent: Pointer to "struct path". - * @dentry: Pointer to "struct dentry". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) -{ - struct path path = { parent->mnt, dentry }; - return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL); -} - -/** - * tomoyo_path_mkdir - Target for security_path_mkdir(). - * - * @parent: Pointer to "struct path". - * @dentry: Pointer to "struct dentry". - * @mode: DAC permission mode. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, - umode_t mode) -{ - struct path path = { parent->mnt, dentry }; - return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path, - mode & S_IALLUGO); -} - -/** - * tomoyo_path_rmdir - Target for security_path_rmdir(). - * - * @parent: Pointer to "struct path". - * @dentry: Pointer to "struct dentry". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) -{ - struct path path = { parent->mnt, dentry }; - return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL); -} - -/** - * tomoyo_path_symlink - Target for security_path_symlink(). - * - * @parent: Pointer to "struct path". - * @dentry: Pointer to "struct dentry". - * @old_name: Symlink's content. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, - const char *old_name) -{ - struct path path = { parent->mnt, dentry }; - return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name); -} - -/** - * tomoyo_path_mknod - Target for security_path_mknod(). - * - * @parent: Pointer to "struct path". - * @dentry: Pointer to "struct dentry". - * @mode: DAC permission mode. - * @dev: Device attributes. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, - umode_t mode, unsigned int dev) -{ - struct path path = { parent->mnt, dentry }; - int type = TOMOYO_TYPE_CREATE; - const unsigned int perm = mode & S_IALLUGO; - - switch (mode & S_IFMT) { - case S_IFCHR: - type = TOMOYO_TYPE_MKCHAR; - break; - case S_IFBLK: - type = TOMOYO_TYPE_MKBLOCK; - break; - default: - goto no_dev; - } - return tomoyo_mkdev_perm(type, &path, perm, dev); - no_dev: - switch (mode & S_IFMT) { - case S_IFIFO: - type = TOMOYO_TYPE_MKFIFO; - break; - case S_IFSOCK: - type = TOMOYO_TYPE_MKSOCK; - break; - } - return tomoyo_path_number_perm(type, &path, perm); -} - -/** - * tomoyo_path_link - Target for security_path_link(). - * - * @old_dentry: Pointer to "struct dentry". - * @new_dir: Pointer to "struct path". - * @new_dentry: Pointer to "struct dentry". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, - struct dentry *new_dentry) -{ - struct path path1 = { new_dir->mnt, old_dentry }; - struct path path2 = { new_dir->mnt, new_dentry }; - return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); -} - -/** - * tomoyo_path_rename - Target for security_path_rename(). - * - * @old_parent: Pointer to "struct path". - * @old_dentry: Pointer to "struct dentry". - * @new_parent: Pointer to "struct path". - * @new_dentry: Pointer to "struct dentry". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_rename(struct path *old_parent, - struct dentry *old_dentry, - struct path *new_parent, - struct dentry *new_dentry) -{ - struct path path1 = { old_parent->mnt, old_dentry }; - struct path path2 = { new_parent->mnt, new_dentry }; - return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); -} - -/** - * tomoyo_file_fcntl - Target for security_file_fcntl(). - * - * @file: Pointer to "struct file". - * @cmd: Command for fcntl(). - * @arg: Argument for @cmd. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - if (!(cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))) - return 0; - return tomoyo_check_open_permission(tomoyo_domain(), &file->f_path, - O_WRONLY | (arg & O_APPEND)); -} - -/** - * tomoyo_dentry_open - Target for security_dentry_open(). - * - * @f: Pointer to "struct file". - * @cred: Pointer to "struct cred". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_dentry_open(struct file *f, const struct cred *cred) -{ - int flags = f->f_flags; - /* Don't check read permission here if called from do_execve(). */ - if (current->in_execve) - return 0; - return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); -} - -/** - * tomoyo_file_ioctl - Target for security_file_ioctl(). - * - * @file: Pointer to "struct file". - * @cmd: Command for ioctl(). - * @arg: Argument for @cmd. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - return tomoyo_path_number_perm(TOMOYO_TYPE_IOCTL, &file->f_path, cmd); -} - -/** - * tomoyo_path_chmod - Target for security_path_chmod(). - * - * @path: Pointer to "struct path". - * @mode: DAC permission mode. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_chmod(struct path *path, umode_t mode) -{ - return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, path, - mode & S_IALLUGO); -} - -/** - * tomoyo_path_chown - Target for security_path_chown(). - * - * @path: Pointer to "struct path". - * @uid: Owner ID. - * @gid: Group ID. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid) -{ - int error = 0; - if (uid != (uid_t) -1) - error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, uid); - if (!error && gid != (gid_t) -1) - error = tomoyo_path_number_perm(TOMOYO_TYPE_CHGRP, path, gid); - return error; -} - -/** - * tomoyo_path_chroot - Target for security_path_chroot(). - * - * @path: Pointer to "struct path". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_chroot(struct path *path) -{ - return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path, NULL); -} - -/** - * tomoyo_sb_mount - Target for security_sb_mount(). - * - * @dev_name: Name of device file. Maybe NULL. - * @path: Pointer to "struct path". - * @type: Name of filesystem type. Maybe NULL. - * @flags: Mount options. - * @data: Optional data. Maybe NULL. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_sb_mount(char *dev_name, struct path *path, - char *type, unsigned long flags, void *data) -{ - return tomoyo_mount_permission(dev_name, path, type, flags, data); -} - -/** - * tomoyo_sb_umount - Target for security_sb_umount(). - * - * @mnt: Pointer to "struct vfsmount". - * @flags: Unmount options. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) -{ - struct path path = { mnt, mnt->mnt_root }; - return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL); -} - -/** - * tomoyo_sb_pivotroot - Target for security_sb_pivotroot(). - * - * @old_path: Pointer to "struct path". - * @new_path: Pointer to "struct path". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path) -{ - return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path); -} - -/** - * tomoyo_socket_listen - Check permission for listen(). - * - * @sock: Pointer to "struct socket". - * @backlog: Backlog parameter. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_socket_listen(struct socket *sock, int backlog) -{ - return tomoyo_socket_listen_permission(sock); -} - -/** - * tomoyo_socket_connect - Check permission for connect(). - * - * @sock: Pointer to "struct socket". - * @addr: Pointer to "struct sockaddr". - * @addr_len: Size of @addr. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_socket_connect(struct socket *sock, struct sockaddr *addr, - int addr_len) -{ - return tomoyo_socket_connect_permission(sock, addr, addr_len); -} - -/** - * tomoyo_socket_bind - Check permission for bind(). - * - * @sock: Pointer to "struct socket". - * @addr: Pointer to "struct sockaddr". - * @addr_len: Size of @addr. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_socket_bind(struct socket *sock, struct sockaddr *addr, - int addr_len) -{ - return tomoyo_socket_bind_permission(sock, addr, addr_len); -} - -/** - * tomoyo_socket_sendmsg - Check permission for sendmsg(). - * - * @sock: Pointer to "struct socket". - * @msg: Pointer to "struct msghdr". - * @size: Size of message. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, - int size) -{ - return tomoyo_socket_sendmsg_permission(sock, msg, size); -} - -/* - * tomoyo_security_ops is a "struct security_operations" which is used for - * registering TOMOYO. - */ -static struct security_operations tomoyo_security_ops = { - .name = "tomoyo", - .cred_alloc_blank = tomoyo_cred_alloc_blank, - .cred_prepare = tomoyo_cred_prepare, - .cred_transfer = tomoyo_cred_transfer, - .cred_free = tomoyo_cred_free, - .bprm_set_creds = tomoyo_bprm_set_creds, - .bprm_check_security = tomoyo_bprm_check_security, - .file_fcntl = tomoyo_file_fcntl, - .dentry_open = tomoyo_dentry_open, - .path_truncate = tomoyo_path_truncate, - .path_unlink = tomoyo_path_unlink, - .path_mkdir = tomoyo_path_mkdir, - .path_rmdir = tomoyo_path_rmdir, - .path_symlink = tomoyo_path_symlink, - .path_mknod = tomoyo_path_mknod, - .path_link = tomoyo_path_link, - .path_rename = tomoyo_path_rename, - .inode_getattr = tomoyo_inode_getattr, - .file_ioctl = tomoyo_file_ioctl, - .path_chmod = tomoyo_path_chmod, - .path_chown = tomoyo_path_chown, - .path_chroot = tomoyo_path_chroot, - .sb_mount = tomoyo_sb_mount, - .sb_umount = tomoyo_sb_umount, - .sb_pivotroot = tomoyo_sb_pivotroot, - .socket_bind = tomoyo_socket_bind, - .socket_connect = tomoyo_socket_connect, - .socket_listen = tomoyo_socket_listen, - .socket_sendmsg = tomoyo_socket_sendmsg, -}; - -/* Lock for GC. */ -struct srcu_struct tomoyo_ss; - -/** - * tomoyo_init - Register TOMOYO Linux as a LSM module. - * - * Returns 0. - */ -static int __init tomoyo_init(void) -{ - struct cred *cred = (struct cred *) current_cred(); - - if (!security_module_enable(&tomoyo_security_ops)) - return 0; - /* register ourselves with the security framework */ - if (register_security(&tomoyo_security_ops) || - init_srcu_struct(&tomoyo_ss)) - panic("Failure registering TOMOYO Linux"); - printk(KERN_INFO "TOMOYO Linux initialized\n"); - cred->security = &tomoyo_kernel_domain; - tomoyo_mm_init(); - return 0; -} - -security_initcall(tomoyo_init); diff --git a/ANDROID_3.4.5/security/tomoyo/util.c b/ANDROID_3.4.5/security/tomoyo/util.c deleted file mode 100644 index 867558c9..00000000 --- a/ANDROID_3.4.5/security/tomoyo/util.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * security/tomoyo/util.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include <linux/slab.h> -#include "common.h" - -/* Lock for protecting policy. */ -DEFINE_MUTEX(tomoyo_policy_lock); - -/* Has /sbin/init started? */ -bool tomoyo_policy_loaded; - -/* - * Mapping table from "enum tomoyo_mac_index" to - * "enum tomoyo_mac_category_index". - */ -const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX] = { - /* CONFIG::file group */ - [TOMOYO_MAC_FILE_EXECUTE] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_OPEN] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_CREATE] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_UNLINK] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_GETATTR] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_MKDIR] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_RMDIR] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_MKFIFO] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_MKSOCK] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_TRUNCATE] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_SYMLINK] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_MKBLOCK] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_MKCHAR] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_LINK] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_RENAME] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_CHMOD] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_CHOWN] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_CHGRP] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_IOCTL] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_CHROOT] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_MOUNT] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_UMOUNT] = TOMOYO_MAC_CATEGORY_FILE, - [TOMOYO_MAC_FILE_PIVOT_ROOT] = TOMOYO_MAC_CATEGORY_FILE, - /* CONFIG::network group */ - [TOMOYO_MAC_NETWORK_INET_STREAM_BIND] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_INET_DGRAM_BIND] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_INET_DGRAM_SEND] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_INET_RAW_BIND] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_INET_RAW_SEND] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = - TOMOYO_MAC_CATEGORY_NETWORK, - [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = - TOMOYO_MAC_CATEGORY_NETWORK, - /* CONFIG::misc group */ - [TOMOYO_MAC_ENVIRON] = TOMOYO_MAC_CATEGORY_MISC, -}; - -/** - * tomoyo_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss. - * - * @time: Seconds since 1970/01/01 00:00:00. - * @stamp: Pointer to "struct tomoyo_time". - * - * Returns nothing. - * - * This function does not handle Y2038 problem. - */ -void tomoyo_convert_time(time_t time, struct tomoyo_time *stamp) -{ - static const u16 tomoyo_eom[2][12] = { - { 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, - { 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } - }; - u16 y; - u8 m; - bool r; - stamp->sec = time % 60; - time /= 60; - stamp->min = time % 60; - time /= 60; - stamp->hour = time % 24; - time /= 24; - for (y = 1970; ; y++) { - const unsigned short days = (y & 3) ? 365 : 366; - if (time < days) - break; - time -= days; - } - r = (y & 3) == 0; - for (m = 0; m < 11 && time >= tomoyo_eom[r][m]; m++) - ; - if (m) - time -= tomoyo_eom[r][m - 1]; - stamp->year = y; - stamp->month = ++m; - stamp->day = ++time; -} - -/** - * tomoyo_permstr - Find permission keywords. - * - * @string: String representation for permissions in foo/bar/buz format. - * @keyword: Keyword to find from @string/ - * - * Returns ture if @keyword was found in @string, false otherwise. - * - * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2. - */ -bool tomoyo_permstr(const char *string, const char *keyword) -{ - const char *cp = strstr(string, keyword); - if (cp) - return cp == string || *(cp - 1) == '/'; - return false; -} - -/** - * tomoyo_read_token - Read a word from a line. - * - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns a word on success, "" otherwise. - * - * To allow the caller to skip NULL check, this function returns "" rather than - * NULL if there is no more words to read. - */ -char *tomoyo_read_token(struct tomoyo_acl_param *param) -{ - char *pos = param->data; - char *del = strchr(pos, ' '); - if (del) - *del++ = '\0'; - else - del = pos + strlen(pos); - param->data = del; - return pos; -} - -/** - * tomoyo_get_domainname - Read a domainname from a line. - * - * @param: Pointer to "struct tomoyo_acl_param". - * - * Returns a domainname on success, NULL otherwise. - */ -const struct tomoyo_path_info *tomoyo_get_domainname -(struct tomoyo_acl_param *param) -{ - char *start = param->data; - char *pos = start; - while (*pos) { - if (*pos++ != ' ' || *pos++ == '/') - continue; - pos -= 2; - *pos++ = '\0'; - break; - } - param->data = pos; - if (tomoyo_correct_domain(start)) - return tomoyo_get_name(start); - return NULL; -} - -/** - * tomoyo_parse_ulong - Parse an "unsigned long" value. - * - * @result: Pointer to "unsigned long". - * @str: Pointer to string to parse. - * - * Returns one of values in "enum tomoyo_value_type". - * - * The @src is updated to point the first character after the value - * on success. - */ -u8 tomoyo_parse_ulong(unsigned long *result, char **str) -{ - const char *cp = *str; - char *ep; - int base = 10; - if (*cp == '0') { - char c = *(cp + 1); - if (c == 'x' || c == 'X') { - base = 16; - cp += 2; - } else if (c >= '0' && c <= '7') { - base = 8; - cp++; - } - } - *result = simple_strtoul(cp, &ep, base); - if (cp == ep) - return TOMOYO_VALUE_TYPE_INVALID; - *str = ep; - switch (base) { - case 16: - return TOMOYO_VALUE_TYPE_HEXADECIMAL; - case 8: - return TOMOYO_VALUE_TYPE_OCTAL; - default: - return TOMOYO_VALUE_TYPE_DECIMAL; - } -} - -/** - * tomoyo_print_ulong - Print an "unsigned long" value. - * - * @buffer: Pointer to buffer. - * @buffer_len: Size of @buffer. - * @value: An "unsigned long" value. - * @type: Type of @value. - * - * Returns nothing. - */ -void tomoyo_print_ulong(char *buffer, const int buffer_len, - const unsigned long value, const u8 type) -{ - if (type == TOMOYO_VALUE_TYPE_DECIMAL) - snprintf(buffer, buffer_len, "%lu", value); - else if (type == TOMOYO_VALUE_TYPE_OCTAL) - snprintf(buffer, buffer_len, "0%lo", value); - else if (type == TOMOYO_VALUE_TYPE_HEXADECIMAL) - snprintf(buffer, buffer_len, "0x%lX", value); - else - snprintf(buffer, buffer_len, "type(%u)", type); -} - -/** - * tomoyo_parse_name_union - Parse a tomoyo_name_union. - * - * @param: Pointer to "struct tomoyo_acl_param". - * @ptr: Pointer to "struct tomoyo_name_union". - * - * Returns true on success, false otherwise. - */ -bool tomoyo_parse_name_union(struct tomoyo_acl_param *param, - struct tomoyo_name_union *ptr) -{ - char *filename; - if (param->data[0] == '@') { - param->data++; - ptr->group = tomoyo_get_group(param, TOMOYO_PATH_GROUP); - return ptr->group != NULL; - } - filename = tomoyo_read_token(param); - if (!tomoyo_correct_word(filename)) - return false; - ptr->filename = tomoyo_get_name(filename); - return ptr->filename != NULL; -} - -/** - * tomoyo_parse_number_union - Parse a tomoyo_number_union. - * - * @param: Pointer to "struct tomoyo_acl_param". - * @ptr: Pointer to "struct tomoyo_number_union". - * - * Returns true on success, false otherwise. - */ -bool tomoyo_parse_number_union(struct tomoyo_acl_param *param, - struct tomoyo_number_union *ptr) -{ - char *data; - u8 type; - unsigned long v; - memset(ptr, 0, sizeof(*ptr)); - if (param->data[0] == '@') { - param->data++; - ptr->group = tomoyo_get_group(param, TOMOYO_NUMBER_GROUP); - return ptr->group != NULL; - } - data = tomoyo_read_token(param); - type = tomoyo_parse_ulong(&v, &data); - if (type == TOMOYO_VALUE_TYPE_INVALID) - return false; - ptr->values[0] = v; - ptr->value_type[0] = type; - if (!*data) { - ptr->values[1] = v; - ptr->value_type[1] = type; - return true; - } - if (*data++ != '-') - return false; - type = tomoyo_parse_ulong(&v, &data); - if (type == TOMOYO_VALUE_TYPE_INVALID || *data || ptr->values[0] > v) - return false; - ptr->values[1] = v; - ptr->value_type[1] = type; - return true; -} - -/** - * tomoyo_byte_range - Check whether the string is a \ooo style octal value. - * - * @str: Pointer to the string. - * - * Returns true if @str is a \ooo style octal value, false otherwise. - * - * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF. - * This function verifies that \ooo is in valid range. - */ -static inline bool tomoyo_byte_range(const char *str) -{ - return *str >= '0' && *str++ <= '3' && - *str >= '0' && *str++ <= '7' && - *str >= '0' && *str <= '7'; -} - -/** - * 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_alphabet_char(const char c) -{ - return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); -} - -/** - * tomoyo_make_byte - Make byte value from three octal characters. - * - * @c1: The first character. - * @c2: The second character. - * @c3: The third character. - * - * Returns byte value. - */ -static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3) -{ - return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0'); -} - -/** - * 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_valid(const unsigned char c) -{ - return c > ' ' && c < 127; -} - -/** - * 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_invalid(const unsigned char c) -{ - return c && (c <= ' ' || c >= 127); -} - -/** - * tomoyo_str_starts - Check whether the given string starts with the given keyword. - * - * @src: Pointer to pointer to the string. - * @find: Pointer to the keyword. - * - * Returns true if @src starts with @find, false otherwise. - * - * The @src is updated to point the first character after the @find - * if @src starts with @find. - */ -bool tomoyo_str_starts(char **src, const char *find) -{ - const int len = strlen(find); - char *tmp = *src; - - if (strncmp(tmp, find, len)) - return false; - tmp += len; - *src = tmp; - return true; -} - -/** - * tomoyo_normalize_line - Format string. - * - * @buffer: The line to normalize. - * - * Leading and trailing whitespaces are removed. - * Multiple whitespaces are packed into single space. - * - * Returns nothing. - */ -void tomoyo_normalize_line(unsigned char *buffer) -{ - unsigned char *sp = buffer; - unsigned char *dp = buffer; - bool first = true; - - while (tomoyo_invalid(*sp)) - sp++; - while (*sp) { - if (!first) - *dp++ = ' '; - first = false; - while (tomoyo_valid(*sp)) - *dp++ = *sp++; - while (tomoyo_invalid(*sp)) - sp++; - } - *dp = '\0'; -} - -/** - * tomoyo_correct_word2 - Validate a string. - * - * @string: The string to check. Maybe non-'\0'-terminated. - * @len: Length of @string. - * - * Check whether the given string follows the naming rules. - * Returns true if @string follows the naming rules, false otherwise. - */ -static bool tomoyo_correct_word2(const char *string, size_t len) -{ - const char *const start = string; - bool in_repetition = false; - unsigned char c; - unsigned char d; - unsigned char e; - if (!len) - goto out; - while (len--) { - c = *string++; - if (c == '\\') { - if (!len--) - goto out; - c = *string++; - switch (c) { - case '\\': /* "\\" */ - continue; - case '$': /* "\$" */ - case '+': /* "\+" */ - case '?': /* "\?" */ - case '*': /* "\*" */ - case '@': /* "\@" */ - case 'x': /* "\x" */ - case 'X': /* "\X" */ - case 'a': /* "\a" */ - case 'A': /* "\A" */ - case '-': /* "\-" */ - continue; - case '{': /* "/\{" */ - if (string - 3 < start || *(string - 3) != '/') - break; - in_repetition = true; - continue; - case '}': /* "\}/" */ - if (*string != '/') - break; - if (!in_repetition) - break; - in_repetition = false; - continue; - case '0': /* "\ooo" */ - case '1': - case '2': - case '3': - if (!len-- || !len--) - break; - d = *string++; - e = *string++; - if (d < '0' || d > '7' || e < '0' || e > '7') - break; - c = tomoyo_make_byte(c, d, e); - if (c <= ' ' || c >= 127) - continue; - } - goto out; - } else if (in_repetition && c == '/') { - goto out; - } else if (c <= ' ' || c >= 127) { - goto out; - } - } - if (in_repetition) - goto out; - return true; - out: - return false; -} - -/** - * 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_correct_word(const char *string) -{ - return tomoyo_correct_word2(string, strlen(string)); -} - -/** - * 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_correct_path(const char *filename) -{ - return *filename == '/' && tomoyo_correct_word(filename); -} - -/** - * 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_correct_domain(const unsigned char *domainname) -{ - if (!domainname || !tomoyo_domain_def(domainname)) - return false; - domainname = strchr(domainname, ' '); - if (!domainname++) - return true; - while (1) { - const unsigned char *cp = strchr(domainname, ' '); - if (!cp) - break; - if (*domainname != '/' || - !tomoyo_correct_word2(domainname, cp - domainname)) - return false; - domainname = cp + 1; - } - return tomoyo_correct_path(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_domain_def(const unsigned char *buffer) -{ - const unsigned char *cp; - int len; - if (*buffer != '<') - return false; - cp = strchr(buffer, ' '); - if (!cp) - len = strlen(buffer); - else - len = cp - buffer; - if (buffer[len - 1] != '>' || - !tomoyo_correct_word2(buffer + 1, len - 2)) - return false; - return true; -} - -/** - * tomoyo_find_domain - Find a domain by the given name. - * - * @domainname: The domainname to find. - * - * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) -{ - struct tomoyo_domain_info *domain; - struct tomoyo_path_info name; - - name.name = domainname; - tomoyo_fill_path_info(&name); - list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { - if (!domain->is_deleted && - !tomoyo_pathcmp(&name, domain->domainname)) - return domain; - } - return NULL; -} - -/** - * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token. - * - * @filename: The string to evaluate. - * - * Returns the initial length without a pattern in @filename. - */ -static int tomoyo_const_part_length(const char *filename) -{ - char c; - int len = 0; - - if (!filename) - return 0; - while ((c = *filename++) != '\0') { - if (c != '\\') { - len++; - continue; - } - c = *filename++; - switch (c) { - case '\\': /* "\\" */ - len += 2; - continue; - case '0': /* "\ooo" */ - case '1': - case '2': - case '3': - c = *filename++; - if (c < '0' || c > '7') - break; - c = *filename++; - if (c < '0' || c > '7') - break; - len += 4; - continue; - } - break; - } - return len; -} - -/** - * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members. - * - * @ptr: Pointer to "struct tomoyo_path_info" to fill in. - * - * The caller sets "struct tomoyo_path_info"->name. - */ -void tomoyo_fill_path_info(struct tomoyo_path_info *ptr) -{ - const char *name = ptr->name; - const int len = strlen(name); - - ptr->const_len = tomoyo_const_part_length(name); - ptr->is_dir = len && (name[len - 1] == '/'); - ptr->is_patterned = (ptr->const_len < len); - ptr->hash = full_name_hash(name, len); -} - -/** - * tomoyo_file_matches_pattern2 - Pattern matching without '/' character and "\-" pattern. - * - * @filename: The start of string to check. - * @filename_end: The end of string to check. - * @pattern: The start of pattern to compare. - * @pattern_end: The end of pattern to compare. - * - * Returns true if @filename matches @pattern, false otherwise. - */ -static bool tomoyo_file_matches_pattern2(const char *filename, - const char *filename_end, - const char *pattern, - const char *pattern_end) -{ - while (filename < filename_end && pattern < pattern_end) { - char c; - if (*pattern != '\\') { - if (*filename++ != *pattern++) - return false; - continue; - } - c = *filename; - pattern++; - switch (*pattern) { - int i; - int j; - case '?': - if (c == '/') { - return false; - } else if (c == '\\') { - if (filename[1] == '\\') - filename++; - else if (tomoyo_byte_range(filename + 1)) - filename += 3; - else - return false; - } - break; - case '\\': - if (c != '\\') - return false; - if (*++filename != '\\') - return false; - break; - case '+': - if (!isdigit(c)) - return false; - break; - case 'x': - if (!isxdigit(c)) - return false; - break; - case 'a': - if (!tomoyo_alphabet_char(c)) - return false; - break; - case '0': - case '1': - case '2': - case '3': - if (c == '\\' && tomoyo_byte_range(filename + 1) - && strncmp(filename + 1, pattern, 3) == 0) { - filename += 3; - pattern += 2; - break; - } - return false; /* Not matched. */ - case '*': - case '@': - for (i = 0; i <= filename_end - filename; i++) { - if (tomoyo_file_matches_pattern2( - filename + i, filename_end, - pattern + 1, pattern_end)) - return true; - c = filename[i]; - if (c == '.' && *pattern == '@') - break; - if (c != '\\') - continue; - if (filename[i + 1] == '\\') - i++; - else if (tomoyo_byte_range(filename + i + 1)) - i += 3; - else - break; /* Bad pattern. */ - } - return false; /* Not matched. */ - default: - j = 0; - c = *pattern; - if (c == '$') { - while (isdigit(filename[j])) - j++; - } else if (c == 'X') { - while (isxdigit(filename[j])) - j++; - } else if (c == 'A') { - while (tomoyo_alphabet_char(filename[j])) - j++; - } - for (i = 1; i <= j; i++) { - if (tomoyo_file_matches_pattern2( - filename + i, filename_end, - pattern + 1, pattern_end)) - return true; - } - return false; /* Not matched or bad pattern. */ - } - filename++; - pattern++; - } - while (*pattern == '\\' && - (*(pattern + 1) == '*' || *(pattern + 1) == '@')) - pattern += 2; - return filename == filename_end && pattern == pattern_end; -} - -/** - * tomoyo_file_matches_pattern - Pattern matching without '/' character. - * - * @filename: The start of string to check. - * @filename_end: The end of string to check. - * @pattern: The start of pattern to compare. - * @pattern_end: The end of pattern to compare. - * - * Returns true if @filename matches @pattern, false otherwise. - */ -static bool tomoyo_file_matches_pattern(const char *filename, - const char *filename_end, - const char *pattern, - const char *pattern_end) -{ - const char *pattern_start = pattern; - bool first = true; - bool result; - - while (pattern < pattern_end - 1) { - /* Split at "\-" pattern. */ - if (*pattern++ != '\\' || *pattern++ != '-') - continue; - result = tomoyo_file_matches_pattern2(filename, - filename_end, - pattern_start, - pattern - 2); - if (first) - result = !result; - if (result) - return false; - first = false; - pattern_start = pattern; - } - result = tomoyo_file_matches_pattern2(filename, filename_end, - pattern_start, pattern_end); - return first ? result : !result; -} - -/** - * tomoyo_path_matches_pattern2 - Do pathname pattern matching. - * - * @f: The start of string to check. - * @p: The start of pattern to compare. - * - * Returns true if @f matches @p, false otherwise. - */ -static bool tomoyo_path_matches_pattern2(const char *f, const char *p) -{ - const char *f_delimiter; - const char *p_delimiter; - - while (*f && *p) { - f_delimiter = strchr(f, '/'); - if (!f_delimiter) - f_delimiter = f + strlen(f); - p_delimiter = strchr(p, '/'); - if (!p_delimiter) - p_delimiter = p + strlen(p); - if (*p == '\\' && *(p + 1) == '{') - goto recursive; - if (!tomoyo_file_matches_pattern(f, f_delimiter, p, - p_delimiter)) - return false; - f = f_delimiter; - if (*f) - f++; - p = p_delimiter; - if (*p) - p++; - } - /* Ignore trailing "\*" and "\@" in @pattern. */ - while (*p == '\\' && - (*(p + 1) == '*' || *(p + 1) == '@')) - p += 2; - return !*f && !*p; - recursive: - /* - * The "\{" pattern is permitted only after '/' character. - * This guarantees that below "*(p - 1)" is safe. - * Also, the "\}" pattern is permitted only before '/' character - * so that "\{" + "\}" pair will not break the "\-" operator. - */ - if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' || - *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\') - return false; /* Bad pattern. */ - do { - /* Compare current component with pattern. */ - if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2, - p_delimiter - 2)) - break; - /* Proceed to next component. */ - f = f_delimiter; - if (!*f) - break; - f++; - /* Continue comparison. */ - if (tomoyo_path_matches_pattern2(f, p_delimiter + 1)) - return true; - f_delimiter = strchr(f, '/'); - } while (f_delimiter); - return false; /* Not matched. */ -} - -/** - * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern. - * - * @filename: The filename to check. - * @pattern: The pattern to compare. - * - * Returns true if matches, false otherwise. - * - * The following patterns are available. - * \\ \ itself. - * \ooo Octal representation of a byte. - * \* Zero or more repetitions of characters other than '/'. - * \@ Zero or more repetitions of characters other than '/' or '.'. - * \? 1 byte character other than '/'. - * \$ One or more repetitions of decimal digits. - * \+ 1 decimal digit. - * \X One or more repetitions of hexadecimal digits. - * \x 1 hexadecimal digit. - * \A One or more repetitions of alphabet characters. - * \a 1 alphabet character. - * - * \- Subtraction operator. - * - * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/ - * /dir/dir/dir/ ). - */ -bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, - const struct tomoyo_path_info *pattern) -{ - const char *f = filename->name; - const char *p = pattern->name; - const int len = pattern->const_len; - - /* If @pattern doesn't contain pattern, I can use strcmp(). */ - if (!pattern->is_patterned) - return !tomoyo_pathcmp(filename, pattern); - /* Don't compare directory and non-directory. */ - if (filename->is_dir != pattern->is_dir) - return false; - /* Compare the initial length without patterns. */ - if (strncmp(f, p, len)) - return false; - f += len; - p += len; - return tomoyo_path_matches_pattern2(f, p); -} - -/** - * tomoyo_get_exe - Get tomoyo_realpath() of current process. - * - * Returns the tomoyo_realpath() of current process on success, NULL otherwise. - * - * This function uses kzalloc(), so the caller must call kfree() - * if this function didn't return NULL. - */ -const char *tomoyo_get_exe(void) -{ - struct mm_struct *mm = current->mm; - struct vm_area_struct *vma; - const char *cp = NULL; - - if (!mm) - return NULL; - down_read(&mm->mmap_sem); - for (vma = mm->mmap; vma; vma = vma->vm_next) { - if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) { - cp = tomoyo_realpath_from_path(&vma->vm_file->f_path); - break; - } - } - up_read(&mm->mmap_sem); - return cp; -} - -/** - * tomoyo_get_mode - Get MAC mode. - * - * @ns: Pointer to "struct tomoyo_policy_namespace". - * @profile: Profile number. - * @index: Index number of functionality. - * - * Returns mode. - */ -int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile, - const u8 index) -{ - u8 mode; - struct tomoyo_profile *p; - - if (!tomoyo_policy_loaded) - return TOMOYO_CONFIG_DISABLED; - p = tomoyo_profile(ns, profile); - mode = p->config[index]; - if (mode == TOMOYO_CONFIG_USE_DEFAULT) - mode = p->config[tomoyo_index2category[index] - + TOMOYO_MAX_MAC_INDEX]; - if (mode == TOMOYO_CONFIG_USE_DEFAULT) - mode = p->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, const u8 index) -{ - u8 profile; - memset(r, 0, sizeof(*r)); - if (!domain) - domain = tomoyo_domain(); - r->domain = domain; - profile = domain->profile; - r->profile = profile; - r->type = index; - r->mode = tomoyo_get_mode(domain->ns, profile, index); - return r->mode; -} - -/** - * tomoyo_domain_quota_is_ok - Check for domain's quota. - * - * @r: Pointer to "struct tomoyo_request_info". - * - * Returns true if the domain is not exceeded quota, false otherwise. - * - * Caller holds tomoyo_read_lock(). - */ -bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) -{ - unsigned int count = 0; - struct tomoyo_domain_info *domain = r->domain; - struct tomoyo_acl_info *ptr; - - if (r->mode != TOMOYO_CONFIG_LEARNING) - return false; - if (!domain) - return true; - list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { - u16 perm; - u8 i; - if (ptr->is_deleted) - continue; - switch (ptr->type) { - case TOMOYO_TYPE_PATH_ACL: - perm = container_of(ptr, struct tomoyo_path_acl, head) - ->perm; - break; - case TOMOYO_TYPE_PATH2_ACL: - perm = container_of(ptr, struct tomoyo_path2_acl, head) - ->perm; - break; - case TOMOYO_TYPE_PATH_NUMBER_ACL: - perm = container_of(ptr, struct tomoyo_path_number_acl, - head)->perm; - break; - case TOMOYO_TYPE_MKDEV_ACL: - perm = container_of(ptr, struct tomoyo_mkdev_acl, - head)->perm; - break; - case TOMOYO_TYPE_INET_ACL: - perm = container_of(ptr, struct tomoyo_inet_acl, - head)->perm; - break; - case TOMOYO_TYPE_UNIX_ACL: - perm = container_of(ptr, struct tomoyo_unix_acl, - head)->perm; - break; - case TOMOYO_TYPE_MANUAL_TASK_ACL: - perm = 0; - break; - default: - perm = 1; - } - for (i = 0; i < 16; i++) - if (perm & (1 << i)) - count++; - } - if (count < tomoyo_profile(domain->ns, domain->profile)-> - pref[TOMOYO_PREF_MAX_LEARNING_ENTRY]) - return true; - if (!domain->flags[TOMOYO_DIF_QUOTA_WARNED]) { - domain->flags[TOMOYO_DIF_QUOTA_WARNED] = true; - /* r->granted = false; */ - tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]); - printk(KERN_WARNING "WARNING: " - "Domain '%s' has too many ACLs to hold. " - "Stopped learning mode.\n", domain->domainname->name); - } - return false; -} |