3025 lines · 80.2 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.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 <linux/string_helpers.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_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. */__printf(3, 4)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,			     ...)	__must_hold(&head->io_sem){	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 = 20150505;	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 voidtomoyo_print_number_union_nospace(struct tomoyo_io_buffer *head, const struct tomoyo_number_union *ptr)	__must_hold(&head->io_sem){	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)	__must_hold(&head->io_sem){	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_obj(*entry, GFP_NOFS | __GFP_NOWARN);	if (mutex_lock_interruptible(&tomoyo_policy_lock))		goto out;	ptr = ns->profile_ptr[profile];	if (!ptr && tomoyo_memory_ok(entry)) {

Lines 1–500 of 3025.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t