diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 09:45:31 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-25 09:45:31 +0200 |
commit | 36b8d186e6cc8e32cb5227f5645a58e1bc0af190 (patch) | |
tree | 1000ad26e189e6ff2c53fb7eeff605f59c7ad94e /security/tomoyo | |
parent | cd85b557414fe4cd44ea6608825e96612a5fe2b2 (diff) | |
parent | c45ed235abf1b0b6666417e3c394f18717976acd (diff) |
Merge branch 'next' of git://selinuxproject.org/~jmorris/linux-security
* 'next' of git://selinuxproject.org/~jmorris/linux-security: (95 commits)
TOMOYO: Fix incomplete read after seek.
Smack: allow to access /smack/access as normal user
TOMOYO: Fix unused kernel config option.
Smack: fix: invalid length set for the result of /smack/access
Smack: compilation fix
Smack: fix for /smack/access output, use string instead of byte
Smack: domain transition protections (v3)
Smack: Provide information for UDS getsockopt(SO_PEERCRED)
Smack: Clean up comments
Smack: Repair processing of fcntl
Smack: Rule list lookup performance
Smack: check permissions from user space (v2)
TOMOYO: Fix quota and garbage collector.
TOMOYO: Remove redundant tasklist_lock.
TOMOYO: Fix domain transition failure warning.
TOMOYO: Remove tomoyo_policy_memory_lock spinlock.
TOMOYO: Simplify garbage collector.
TOMOYO: Fix make namespacecheck warnings.
target: check hex2bin result
encrypted-keys: check hex2bin result
...
Diffstat (limited to 'security/tomoyo')
-rw-r--r-- | security/tomoyo/Kconfig | 2 | ||||
-rw-r--r-- | security/tomoyo/Makefile | 4 | ||||
-rw-r--r-- | security/tomoyo/audit.c | 7 | ||||
-rw-r--r-- | security/tomoyo/common.c | 228 | ||||
-rw-r--r-- | security/tomoyo/common.h | 189 | ||||
-rw-r--r-- | security/tomoyo/condition.c | 71 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 209 | ||||
-rw-r--r-- | security/tomoyo/environ.c | 122 | ||||
-rw-r--r-- | security/tomoyo/file.c | 42 | ||||
-rw-r--r-- | security/tomoyo/gc.c | 540 | ||||
-rw-r--r-- | security/tomoyo/group.c | 61 | ||||
-rw-r--r-- | security/tomoyo/memory.c | 39 | ||||
-rw-r--r-- | security/tomoyo/network.c | 771 | ||||
-rw-r--r-- | security/tomoyo/realpath.c | 32 | ||||
-rw-r--r-- | security/tomoyo/securityfs_if.c | 123 | ||||
-rw-r--r-- | security/tomoyo/tomoyo.c | 62 | ||||
-rw-r--r-- | security/tomoyo/util.c | 80 |
17 files changed, 2128 insertions, 454 deletions
diff --git a/security/tomoyo/Kconfig b/security/tomoyo/Kconfig index 7c7f8c16c10f..8eb779b9d77f 100644 --- a/security/tomoyo/Kconfig +++ b/security/tomoyo/Kconfig @@ -1,8 +1,10 @@ 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. diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 95278b71fc21..56a0c7be409e 100644 --- a/security/tomoyo/Makefile +++ b/security/tomoyo/Makefile @@ -1,4 +1,4 @@ -obj-y = audit.o common.o condition.o domain.o file.o gc.o group.o load_policy.o memory.o mount.o realpath.o securityfs_if.o tomoyo.o util.o +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/ @@ -27,7 +27,7 @@ $(obj)/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.4.x. + @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 diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c index 5dbb1f7617c0..075c3a6d1649 100644 --- a/security/tomoyo/audit.c +++ b/security/tomoyo/audit.c @@ -313,6 +313,7 @@ static unsigned int tomoyo_log_count; */ 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; @@ -324,6 +325,9 @@ static bool tomoyo_get_audit(const struct tomoyo_policy_namespace *ns, 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]; @@ -350,7 +354,8 @@ void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, char *buf; struct tomoyo_log *entry; bool quota_exceeded = false; - if (!tomoyo_get_audit(r->domain->ns, r->profile, r->type, r->granted)) + 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) diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 2e43aec1c36b..150911c7ff08 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -20,6 +20,7 @@ const char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE] = { /* 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", @@ -43,7 +44,28 @@ const char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX [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. */ @@ -130,10 +152,20 @@ const char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { [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_FILE] = "file", + [TOMOYO_MAC_CATEGORY_NETWORK] = "network", + [TOMOYO_MAC_CATEGORY_MISC] = "misc", }; /* Permit policy management by non-root user? */ @@ -230,13 +262,17 @@ static void tomoyo_set_string(struct tomoyo_io_buffer *head, const char *string) 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. */ -void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) +static void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, + ...) { va_list args; size_t len; @@ -313,7 +349,7 @@ void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns) 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 = 20100903; + ns->profile_version = 20110903; tomoyo_namespace_enabled = !list_empty(&tomoyo_namespace_list); list_add_tail_rcu(&ns->namespace_list, &tomoyo_namespace_list); } @@ -466,8 +502,10 @@ static struct tomoyo_profile *tomoyo_assign_profile TOMOYO_CONFIG_WANT_REJECT_LOG; memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT, sizeof(ptr->config)); - ptr->pref[TOMOYO_PREF_MAX_AUDIT_LOG] = 1024; - ptr->pref[TOMOYO_PREF_MAX_LEARNING_ENTRY] = 2048; + 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; @@ -951,14 +989,12 @@ static bool tomoyo_select_domain(struct tomoyo_io_buffer *head, (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) { struct task_struct *p; rcu_read_lock(); - read_lock(&tasklist_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); - read_unlock(&tasklist_lock); rcu_read_unlock(); } else if (!strncmp(data, "domain=", 7)) { if (tomoyo_domain_def(data + 7)) @@ -982,6 +1018,48 @@ static bool tomoyo_select_domain(struct tomoyo_io_buffer *head, } /** + * 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. @@ -1039,11 +1117,16 @@ static int tomoyo_write_domain2(struct tomoyo_policy_namespace *ns, static const struct { const char *keyword; int (*write) (struct tomoyo_acl_param *); - } tomoyo_callback[1] = { + } 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 < 1; i++) { + + for (i = 0; i < ARRAY_SIZE(tomoyo_callback); i++) { if (!tomoyo_str_starts(¶m.data, tomoyo_callback[i].keyword)) continue; @@ -1127,6 +1210,10 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, 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: { @@ -1239,6 +1326,10 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, 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; } @@ -1306,6 +1397,12 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, 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) { @@ -1370,6 +1467,60 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, 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); @@ -1378,6 +1529,12 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, 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; @@ -1510,14 +1667,12 @@ static void tomoyo_read_pid(struct tomoyo_io_buffer *head) global_pid = true; pid = (unsigned int) simple_strtoul(buf, NULL, 10); rcu_read_lock(); - read_lock(&tasklist_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); - read_unlock(&tasklist_lock); rcu_read_unlock(); if (!domain) return; @@ -1537,8 +1692,9 @@ static const char *tomoyo_transition_type[TOMOYO_MAX_TRANSITION_TYPE] = { /* 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_PATH_GROUP] = "path_group ", + [TOMOYO_NUMBER_GROUP] = "number_group ", + [TOMOYO_ADDRESS_GROUP] = "address_group ", }; /** @@ -1580,7 +1736,7 @@ static int tomoyo_write_exception(struct tomoyo_io_buffer *head) } /** - * tomoyo_read_group - Read "struct tomoyo_path_group"/"struct tomoyo_number_group" list. + * 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. @@ -1617,6 +1773,15 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx) (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); } @@ -2066,27 +2231,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head) static void tomoyo_read_version(struct tomoyo_io_buffer *head) { if (!head->r.eof) { - tomoyo_io_printf(head, "2.4.0"); - head->r.eof = true; - } -} - -/** - * tomoyo_read_self_domain - Get the current process's domainname. - * - * @head: Pointer to "struct tomoyo_io_buffer". - * - * Returns the current process's domainname. - */ -static void tomoyo_read_self_domain(struct tomoyo_io_buffer *head) -{ - if (!head->r.eof) { - /* - * tomoyo_domain()->domainname != NULL - * because every process belongs to a domain and - * the domain's name cannot be NULL. - */ - tomoyo_io_printf(head, "%s", tomoyo_domain()->domainname->name); + tomoyo_io_printf(head, "2.5.0"); head->r.eof = true; } } @@ -2221,10 +2366,6 @@ int tomoyo_open_control(const u8 type, struct file *file) head->poll = tomoyo_poll_log; head->read = tomoyo_read_log; break; - case TOMOYO_SELFDOMAIN: - /* /sys/kernel/security/tomoyo/self_domain */ - head->read = tomoyo_read_self_domain; - break; case TOMOYO_PROCESS_STATUS: /* /sys/kernel/security/tomoyo/.process_status */ head->write = tomoyo_write_pid; @@ -2453,6 +2594,7 @@ ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, 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) { @@ -2562,11 +2704,11 @@ 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.4.0\n"); + 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 != 20100903) + if (ns->profile_version != 20110903) printk(KERN_ERR "Profile version %u is not supported.\n", ns->profile_version); @@ -2577,9 +2719,9 @@ void tomoyo_check_profile(void) else continue; printk(KERN_ERR - "Userland tools for TOMOYO 2.4 must be installed and " + "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.4/ " + printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.5/ " "for more information.\n"); panic("STOP!"); } diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index f7fbaa66e443..ed311d7a8ce0 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -3,7 +3,7 @@ * * Header file for TOMOYO. * - * Copyright (C) 2005-2010 NTT DATA CORPORATION + * Copyright (C) 2005-2011 NTT DATA CORPORATION */ #ifndef _SECURITY_TOMOYO_COMMON_H @@ -23,6 +23,16 @@ #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. **********/ @@ -34,8 +44,17 @@ #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 @@ -136,6 +155,7 @@ enum tomoyo_mode_index { /* 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, @@ -162,10 +182,21 @@ enum tomoyo_domain_info_flags_index { 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 }; @@ -196,6 +227,10 @@ enum tomoyo_acl_entry_type_index { 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. */ @@ -228,6 +263,15 @@ enum tomoyo_mkdev_acl_index { 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, @@ -255,7 +299,6 @@ enum tomoyo_securityfs_interface_index { TOMOYO_EXCEPTIONPOLICY, TOMOYO_PROCESS_STATUS, TOMOYO_STAT, - TOMOYO_SELFDOMAIN, TOMOYO_AUDIT, TOMOYO_VERSION, TOMOYO_PROFILE, @@ -300,12 +343,30 @@ enum tomoyo_mac_index { 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 }; @@ -340,7 +401,7 @@ enum tomoyo_pref_index { /* Common header for holding ACL entries. */ struct tomoyo_acl_head { struct list_head list; - bool is_deleted; + s8 is_deleted; /* true or false or TOMOYO_GC_IN_PROGRESS */ } __packed; /* Common header for shared entries. */ @@ -397,13 +458,36 @@ struct tomoyo_request_info { 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; @@ -442,7 +526,14 @@ struct tomoyo_number_union { u8 value_type[2]; }; -/* Structure for "path_group"/"number_group" directive. */ +/* 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; @@ -461,6 +552,13 @@ struct tomoyo_number_group { 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; @@ -520,6 +618,7 @@ 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. */ @@ -554,6 +653,8 @@ struct tomoyo_condition { 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]; @@ -567,7 +668,7 @@ struct tomoyo_condition { struct tomoyo_acl_info { struct list_head list; struct tomoyo_condition *cond; /* Maybe NULL. */ - bool is_deleted; + s8 is_deleted; /* true or false or TOMOYO_GC_IN_PROGRESS */ u8 type; /* One of values in "enum tomoyo_acl_entry_type_index". */ } __packed; @@ -587,6 +688,15 @@ struct tomoyo_domain_info { }; /* + * 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. @@ -638,6 +748,29 @@ struct tomoyo_mount_acl { 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; @@ -773,7 +906,7 @@ struct tomoyo_policy_namespace { 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 20100903 is defined. */ + /* Profile version. Currently only 20110903 is defined. */ unsigned int profile_version; /* Name of this namespace (e.g. "<kernel>", "</usr/sbin/httpd>" ). */ const char *name; @@ -781,6 +914,8 @@ struct tomoyo_policy_namespace { /********** 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, @@ -796,6 +931,8 @@ 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, @@ -805,6 +942,7 @@ bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, 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); @@ -814,12 +952,17 @@ 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); @@ -838,10 +981,15 @@ 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); -int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, - const struct tomoyo_path_info *filename); int tomoyo_poll_control(struct file *file, poll_table *wait); 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_s |