18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * security/tomoyo/common.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2005-2011 NTT DATA CORPORATION 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 98c2ecf20Sopenharmony_ci#include <linux/slab.h> 108c2ecf20Sopenharmony_ci#include <linux/security.h> 118c2ecf20Sopenharmony_ci#include "common.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* String table for operation mode. */ 148c2ecf20Sopenharmony_ciconst char * const tomoyo_mode[TOMOYO_CONFIG_MAX_MODE] = { 158c2ecf20Sopenharmony_ci [TOMOYO_CONFIG_DISABLED] = "disabled", 168c2ecf20Sopenharmony_ci [TOMOYO_CONFIG_LEARNING] = "learning", 178c2ecf20Sopenharmony_ci [TOMOYO_CONFIG_PERMISSIVE] = "permissive", 188c2ecf20Sopenharmony_ci [TOMOYO_CONFIG_ENFORCING] = "enforcing" 198c2ecf20Sopenharmony_ci}; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* String table for /sys/kernel/security/tomoyo/profile */ 228c2ecf20Sopenharmony_ciconst char * const tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX 238c2ecf20Sopenharmony_ci + TOMOYO_MAX_MAC_CATEGORY_INDEX] = { 248c2ecf20Sopenharmony_ci /* CONFIG::file group */ 258c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_EXECUTE] = "execute", 268c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_OPEN] = "open", 278c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_CREATE] = "create", 288c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_UNLINK] = "unlink", 298c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_GETATTR] = "getattr", 308c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_MKDIR] = "mkdir", 318c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_RMDIR] = "rmdir", 328c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_MKFIFO] = "mkfifo", 338c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_MKSOCK] = "mksock", 348c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_TRUNCATE] = "truncate", 358c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_SYMLINK] = "symlink", 368c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_MKBLOCK] = "mkblock", 378c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_MKCHAR] = "mkchar", 388c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_LINK] = "link", 398c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_RENAME] = "rename", 408c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_CHMOD] = "chmod", 418c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_CHOWN] = "chown", 428c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_CHGRP] = "chgrp", 438c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_IOCTL] = "ioctl", 448c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_CHROOT] = "chroot", 458c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_MOUNT] = "mount", 468c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_UMOUNT] = "unmount", 478c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_PIVOT_ROOT] = "pivot_root", 488c2ecf20Sopenharmony_ci /* CONFIG::network group */ 498c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_STREAM_BIND] = "inet_stream_bind", 508c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN] = "inet_stream_listen", 518c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT] = "inet_stream_connect", 528c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_DGRAM_BIND] = "inet_dgram_bind", 538c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_DGRAM_SEND] = "inet_dgram_send", 548c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_RAW_BIND] = "inet_raw_bind", 558c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_RAW_SEND] = "inet_raw_send", 568c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND] = "unix_stream_bind", 578c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN] = "unix_stream_listen", 588c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT] = "unix_stream_connect", 598c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND] = "unix_dgram_bind", 608c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND] = "unix_dgram_send", 618c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND] = "unix_seqpacket_bind", 628c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = "unix_seqpacket_listen", 638c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = "unix_seqpacket_connect", 648c2ecf20Sopenharmony_ci /* CONFIG::misc group */ 658c2ecf20Sopenharmony_ci [TOMOYO_MAC_ENVIRON] = "env", 668c2ecf20Sopenharmony_ci /* CONFIG group */ 678c2ecf20Sopenharmony_ci [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file", 688c2ecf20Sopenharmony_ci [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_NETWORK] = "network", 698c2ecf20Sopenharmony_ci [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_MISC] = "misc", 708c2ecf20Sopenharmony_ci}; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci/* String table for conditions. */ 738c2ecf20Sopenharmony_ciconst char * const tomoyo_condition_keyword[TOMOYO_MAX_CONDITION_KEYWORD] = { 748c2ecf20Sopenharmony_ci [TOMOYO_TASK_UID] = "task.uid", 758c2ecf20Sopenharmony_ci [TOMOYO_TASK_EUID] = "task.euid", 768c2ecf20Sopenharmony_ci [TOMOYO_TASK_SUID] = "task.suid", 778c2ecf20Sopenharmony_ci [TOMOYO_TASK_FSUID] = "task.fsuid", 788c2ecf20Sopenharmony_ci [TOMOYO_TASK_GID] = "task.gid", 798c2ecf20Sopenharmony_ci [TOMOYO_TASK_EGID] = "task.egid", 808c2ecf20Sopenharmony_ci [TOMOYO_TASK_SGID] = "task.sgid", 818c2ecf20Sopenharmony_ci [TOMOYO_TASK_FSGID] = "task.fsgid", 828c2ecf20Sopenharmony_ci [TOMOYO_TASK_PID] = "task.pid", 838c2ecf20Sopenharmony_ci [TOMOYO_TASK_PPID] = "task.ppid", 848c2ecf20Sopenharmony_ci [TOMOYO_EXEC_ARGC] = "exec.argc", 858c2ecf20Sopenharmony_ci [TOMOYO_EXEC_ENVC] = "exec.envc", 868c2ecf20Sopenharmony_ci [TOMOYO_TYPE_IS_SOCKET] = "socket", 878c2ecf20Sopenharmony_ci [TOMOYO_TYPE_IS_SYMLINK] = "symlink", 888c2ecf20Sopenharmony_ci [TOMOYO_TYPE_IS_FILE] = "file", 898c2ecf20Sopenharmony_ci [TOMOYO_TYPE_IS_BLOCK_DEV] = "block", 908c2ecf20Sopenharmony_ci [TOMOYO_TYPE_IS_DIRECTORY] = "directory", 918c2ecf20Sopenharmony_ci [TOMOYO_TYPE_IS_CHAR_DEV] = "char", 928c2ecf20Sopenharmony_ci [TOMOYO_TYPE_IS_FIFO] = "fifo", 938c2ecf20Sopenharmony_ci [TOMOYO_MODE_SETUID] = "setuid", 948c2ecf20Sopenharmony_ci [TOMOYO_MODE_SETGID] = "setgid", 958c2ecf20Sopenharmony_ci [TOMOYO_MODE_STICKY] = "sticky", 968c2ecf20Sopenharmony_ci [TOMOYO_MODE_OWNER_READ] = "owner_read", 978c2ecf20Sopenharmony_ci [TOMOYO_MODE_OWNER_WRITE] = "owner_write", 988c2ecf20Sopenharmony_ci [TOMOYO_MODE_OWNER_EXECUTE] = "owner_execute", 998c2ecf20Sopenharmony_ci [TOMOYO_MODE_GROUP_READ] = "group_read", 1008c2ecf20Sopenharmony_ci [TOMOYO_MODE_GROUP_WRITE] = "group_write", 1018c2ecf20Sopenharmony_ci [TOMOYO_MODE_GROUP_EXECUTE] = "group_execute", 1028c2ecf20Sopenharmony_ci [TOMOYO_MODE_OTHERS_READ] = "others_read", 1038c2ecf20Sopenharmony_ci [TOMOYO_MODE_OTHERS_WRITE] = "others_write", 1048c2ecf20Sopenharmony_ci [TOMOYO_MODE_OTHERS_EXECUTE] = "others_execute", 1058c2ecf20Sopenharmony_ci [TOMOYO_EXEC_REALPATH] = "exec.realpath", 1068c2ecf20Sopenharmony_ci [TOMOYO_SYMLINK_TARGET] = "symlink.target", 1078c2ecf20Sopenharmony_ci [TOMOYO_PATH1_UID] = "path1.uid", 1088c2ecf20Sopenharmony_ci [TOMOYO_PATH1_GID] = "path1.gid", 1098c2ecf20Sopenharmony_ci [TOMOYO_PATH1_INO] = "path1.ino", 1108c2ecf20Sopenharmony_ci [TOMOYO_PATH1_MAJOR] = "path1.major", 1118c2ecf20Sopenharmony_ci [TOMOYO_PATH1_MINOR] = "path1.minor", 1128c2ecf20Sopenharmony_ci [TOMOYO_PATH1_PERM] = "path1.perm", 1138c2ecf20Sopenharmony_ci [TOMOYO_PATH1_TYPE] = "path1.type", 1148c2ecf20Sopenharmony_ci [TOMOYO_PATH1_DEV_MAJOR] = "path1.dev_major", 1158c2ecf20Sopenharmony_ci [TOMOYO_PATH1_DEV_MINOR] = "path1.dev_minor", 1168c2ecf20Sopenharmony_ci [TOMOYO_PATH2_UID] = "path2.uid", 1178c2ecf20Sopenharmony_ci [TOMOYO_PATH2_GID] = "path2.gid", 1188c2ecf20Sopenharmony_ci [TOMOYO_PATH2_INO] = "path2.ino", 1198c2ecf20Sopenharmony_ci [TOMOYO_PATH2_MAJOR] = "path2.major", 1208c2ecf20Sopenharmony_ci [TOMOYO_PATH2_MINOR] = "path2.minor", 1218c2ecf20Sopenharmony_ci [TOMOYO_PATH2_PERM] = "path2.perm", 1228c2ecf20Sopenharmony_ci [TOMOYO_PATH2_TYPE] = "path2.type", 1238c2ecf20Sopenharmony_ci [TOMOYO_PATH2_DEV_MAJOR] = "path2.dev_major", 1248c2ecf20Sopenharmony_ci [TOMOYO_PATH2_DEV_MINOR] = "path2.dev_minor", 1258c2ecf20Sopenharmony_ci [TOMOYO_PATH1_PARENT_UID] = "path1.parent.uid", 1268c2ecf20Sopenharmony_ci [TOMOYO_PATH1_PARENT_GID] = "path1.parent.gid", 1278c2ecf20Sopenharmony_ci [TOMOYO_PATH1_PARENT_INO] = "path1.parent.ino", 1288c2ecf20Sopenharmony_ci [TOMOYO_PATH1_PARENT_PERM] = "path1.parent.perm", 1298c2ecf20Sopenharmony_ci [TOMOYO_PATH2_PARENT_UID] = "path2.parent.uid", 1308c2ecf20Sopenharmony_ci [TOMOYO_PATH2_PARENT_GID] = "path2.parent.gid", 1318c2ecf20Sopenharmony_ci [TOMOYO_PATH2_PARENT_INO] = "path2.parent.ino", 1328c2ecf20Sopenharmony_ci [TOMOYO_PATH2_PARENT_PERM] = "path2.parent.perm", 1338c2ecf20Sopenharmony_ci}; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci/* String table for PREFERENCE keyword. */ 1368c2ecf20Sopenharmony_cistatic const char * const tomoyo_pref_keywords[TOMOYO_MAX_PREF] = { 1378c2ecf20Sopenharmony_ci [TOMOYO_PREF_MAX_AUDIT_LOG] = "max_audit_log", 1388c2ecf20Sopenharmony_ci [TOMOYO_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry", 1398c2ecf20Sopenharmony_ci}; 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci/* String table for path operation. */ 1428c2ecf20Sopenharmony_ciconst char * const tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { 1438c2ecf20Sopenharmony_ci [TOMOYO_TYPE_EXECUTE] = "execute", 1448c2ecf20Sopenharmony_ci [TOMOYO_TYPE_READ] = "read", 1458c2ecf20Sopenharmony_ci [TOMOYO_TYPE_WRITE] = "write", 1468c2ecf20Sopenharmony_ci [TOMOYO_TYPE_APPEND] = "append", 1478c2ecf20Sopenharmony_ci [TOMOYO_TYPE_UNLINK] = "unlink", 1488c2ecf20Sopenharmony_ci [TOMOYO_TYPE_GETATTR] = "getattr", 1498c2ecf20Sopenharmony_ci [TOMOYO_TYPE_RMDIR] = "rmdir", 1508c2ecf20Sopenharmony_ci [TOMOYO_TYPE_TRUNCATE] = "truncate", 1518c2ecf20Sopenharmony_ci [TOMOYO_TYPE_SYMLINK] = "symlink", 1528c2ecf20Sopenharmony_ci [TOMOYO_TYPE_CHROOT] = "chroot", 1538c2ecf20Sopenharmony_ci [TOMOYO_TYPE_UMOUNT] = "unmount", 1548c2ecf20Sopenharmony_ci}; 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci/* String table for socket's operation. */ 1578c2ecf20Sopenharmony_ciconst char * const tomoyo_socket_keyword[TOMOYO_MAX_NETWORK_OPERATION] = { 1588c2ecf20Sopenharmony_ci [TOMOYO_NETWORK_BIND] = "bind", 1598c2ecf20Sopenharmony_ci [TOMOYO_NETWORK_LISTEN] = "listen", 1608c2ecf20Sopenharmony_ci [TOMOYO_NETWORK_CONNECT] = "connect", 1618c2ecf20Sopenharmony_ci [TOMOYO_NETWORK_SEND] = "send", 1628c2ecf20Sopenharmony_ci}; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci/* String table for categories. */ 1658c2ecf20Sopenharmony_cistatic const char * const tomoyo_category_keywords 1668c2ecf20Sopenharmony_ci[TOMOYO_MAX_MAC_CATEGORY_INDEX] = { 1678c2ecf20Sopenharmony_ci [TOMOYO_MAC_CATEGORY_FILE] = "file", 1688c2ecf20Sopenharmony_ci [TOMOYO_MAC_CATEGORY_NETWORK] = "network", 1698c2ecf20Sopenharmony_ci [TOMOYO_MAC_CATEGORY_MISC] = "misc", 1708c2ecf20Sopenharmony_ci}; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci/* Permit policy management by non-root user? */ 1738c2ecf20Sopenharmony_cistatic bool tomoyo_manage_by_non_root; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci/* Utility functions. */ 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci/** 1788c2ecf20Sopenharmony_ci * tomoyo_yesno - Return "yes" or "no". 1798c2ecf20Sopenharmony_ci * 1808c2ecf20Sopenharmony_ci * @value: Bool value. 1818c2ecf20Sopenharmony_ci */ 1828c2ecf20Sopenharmony_ciconst char *tomoyo_yesno(const unsigned int value) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci return value ? "yes" : "no"; 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci/** 1888c2ecf20Sopenharmony_ci * tomoyo_addprintf - strncat()-like-snprintf(). 1898c2ecf20Sopenharmony_ci * 1908c2ecf20Sopenharmony_ci * @buffer: Buffer to write to. Must be '\0'-terminated. 1918c2ecf20Sopenharmony_ci * @len: Size of @buffer. 1928c2ecf20Sopenharmony_ci * @fmt: The printf()'s format string, followed by parameters. 1938c2ecf20Sopenharmony_ci * 1948c2ecf20Sopenharmony_ci * Returns nothing. 1958c2ecf20Sopenharmony_ci */ 1968c2ecf20Sopenharmony_cistatic void tomoyo_addprintf(char *buffer, int len, const char *fmt, ...) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci va_list args; 1998c2ecf20Sopenharmony_ci const int pos = strlen(buffer); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci va_start(args, fmt); 2028c2ecf20Sopenharmony_ci vsnprintf(buffer + pos, len - pos - 1, fmt, args); 2038c2ecf20Sopenharmony_ci va_end(args); 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci/** 2078c2ecf20Sopenharmony_ci * tomoyo_flush - Flush queued string to userspace's buffer. 2088c2ecf20Sopenharmony_ci * 2098c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 2108c2ecf20Sopenharmony_ci * 2118c2ecf20Sopenharmony_ci * Returns true if all data was flushed, false otherwise. 2128c2ecf20Sopenharmony_ci */ 2138c2ecf20Sopenharmony_cistatic bool tomoyo_flush(struct tomoyo_io_buffer *head) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci while (head->r.w_pos) { 2168c2ecf20Sopenharmony_ci const char *w = head->r.w[0]; 2178c2ecf20Sopenharmony_ci size_t len = strlen(w); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci if (len) { 2208c2ecf20Sopenharmony_ci if (len > head->read_user_buf_avail) 2218c2ecf20Sopenharmony_ci len = head->read_user_buf_avail; 2228c2ecf20Sopenharmony_ci if (!len) 2238c2ecf20Sopenharmony_ci return false; 2248c2ecf20Sopenharmony_ci if (copy_to_user(head->read_user_buf, w, len)) 2258c2ecf20Sopenharmony_ci return false; 2268c2ecf20Sopenharmony_ci head->read_user_buf_avail -= len; 2278c2ecf20Sopenharmony_ci head->read_user_buf += len; 2288c2ecf20Sopenharmony_ci w += len; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci head->r.w[0] = w; 2318c2ecf20Sopenharmony_ci if (*w) 2328c2ecf20Sopenharmony_ci return false; 2338c2ecf20Sopenharmony_ci /* Add '\0' for audit logs and query. */ 2348c2ecf20Sopenharmony_ci if (head->poll) { 2358c2ecf20Sopenharmony_ci if (!head->read_user_buf_avail || 2368c2ecf20Sopenharmony_ci copy_to_user(head->read_user_buf, "", 1)) 2378c2ecf20Sopenharmony_ci return false; 2388c2ecf20Sopenharmony_ci head->read_user_buf_avail--; 2398c2ecf20Sopenharmony_ci head->read_user_buf++; 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci head->r.w_pos--; 2428c2ecf20Sopenharmony_ci for (len = 0; len < head->r.w_pos; len++) 2438c2ecf20Sopenharmony_ci head->r.w[len] = head->r.w[len + 1]; 2448c2ecf20Sopenharmony_ci } 2458c2ecf20Sopenharmony_ci head->r.avail = 0; 2468c2ecf20Sopenharmony_ci return true; 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci/** 2508c2ecf20Sopenharmony_ci * tomoyo_set_string - Queue string to "struct tomoyo_io_buffer" structure. 2518c2ecf20Sopenharmony_ci * 2528c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 2538c2ecf20Sopenharmony_ci * @string: String to print. 2548c2ecf20Sopenharmony_ci * 2558c2ecf20Sopenharmony_ci * Note that @string has to be kept valid until @head is kfree()d. 2568c2ecf20Sopenharmony_ci * This means that char[] allocated on stack memory cannot be passed to 2578c2ecf20Sopenharmony_ci * this function. Use tomoyo_io_printf() for char[] allocated on stack memory. 2588c2ecf20Sopenharmony_ci */ 2598c2ecf20Sopenharmony_cistatic void tomoyo_set_string(struct tomoyo_io_buffer *head, const char *string) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci if (head->r.w_pos < TOMOYO_MAX_IO_READ_QUEUE) { 2628c2ecf20Sopenharmony_ci head->r.w[head->r.w_pos++] = string; 2638c2ecf20Sopenharmony_ci tomoyo_flush(head); 2648c2ecf20Sopenharmony_ci } else 2658c2ecf20Sopenharmony_ci WARN_ON(1); 2668c2ecf20Sopenharmony_ci} 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_cistatic void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, 2698c2ecf20Sopenharmony_ci ...) __printf(2, 3); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci/** 2728c2ecf20Sopenharmony_ci * tomoyo_io_printf - printf() to "struct tomoyo_io_buffer" structure. 2738c2ecf20Sopenharmony_ci * 2748c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 2758c2ecf20Sopenharmony_ci * @fmt: The printf()'s format string, followed by parameters. 2768c2ecf20Sopenharmony_ci */ 2778c2ecf20Sopenharmony_cistatic void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, 2788c2ecf20Sopenharmony_ci ...) 2798c2ecf20Sopenharmony_ci{ 2808c2ecf20Sopenharmony_ci va_list args; 2818c2ecf20Sopenharmony_ci size_t len; 2828c2ecf20Sopenharmony_ci size_t pos = head->r.avail; 2838c2ecf20Sopenharmony_ci int size = head->readbuf_size - pos; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if (size <= 0) 2868c2ecf20Sopenharmony_ci return; 2878c2ecf20Sopenharmony_ci va_start(args, fmt); 2888c2ecf20Sopenharmony_ci len = vsnprintf(head->read_buf + pos, size, fmt, args) + 1; 2898c2ecf20Sopenharmony_ci va_end(args); 2908c2ecf20Sopenharmony_ci if (pos + len >= head->readbuf_size) { 2918c2ecf20Sopenharmony_ci WARN_ON(1); 2928c2ecf20Sopenharmony_ci return; 2938c2ecf20Sopenharmony_ci } 2948c2ecf20Sopenharmony_ci head->r.avail += len; 2958c2ecf20Sopenharmony_ci tomoyo_set_string(head, head->read_buf + pos); 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci/** 2998c2ecf20Sopenharmony_ci * tomoyo_set_space - Put a space to "struct tomoyo_io_buffer" structure. 3008c2ecf20Sopenharmony_ci * 3018c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 3028c2ecf20Sopenharmony_ci * 3038c2ecf20Sopenharmony_ci * Returns nothing. 3048c2ecf20Sopenharmony_ci */ 3058c2ecf20Sopenharmony_cistatic void tomoyo_set_space(struct tomoyo_io_buffer *head) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci tomoyo_set_string(head, " "); 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci/** 3118c2ecf20Sopenharmony_ci * tomoyo_set_lf - Put a line feed to "struct tomoyo_io_buffer" structure. 3128c2ecf20Sopenharmony_ci * 3138c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 3148c2ecf20Sopenharmony_ci * 3158c2ecf20Sopenharmony_ci * Returns nothing. 3168c2ecf20Sopenharmony_ci */ 3178c2ecf20Sopenharmony_cistatic bool tomoyo_set_lf(struct tomoyo_io_buffer *head) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci tomoyo_set_string(head, "\n"); 3208c2ecf20Sopenharmony_ci return !head->r.w_pos; 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci/** 3248c2ecf20Sopenharmony_ci * tomoyo_set_slash - Put a shash to "struct tomoyo_io_buffer" structure. 3258c2ecf20Sopenharmony_ci * 3268c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 3278c2ecf20Sopenharmony_ci * 3288c2ecf20Sopenharmony_ci * Returns nothing. 3298c2ecf20Sopenharmony_ci */ 3308c2ecf20Sopenharmony_cistatic void tomoyo_set_slash(struct tomoyo_io_buffer *head) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci tomoyo_set_string(head, "/"); 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci/* List of namespaces. */ 3368c2ecf20Sopenharmony_ciLIST_HEAD(tomoyo_namespace_list); 3378c2ecf20Sopenharmony_ci/* True if namespace other than tomoyo_kernel_namespace is defined. */ 3388c2ecf20Sopenharmony_cistatic bool tomoyo_namespace_enabled; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci/** 3418c2ecf20Sopenharmony_ci * tomoyo_init_policy_namespace - Initialize namespace. 3428c2ecf20Sopenharmony_ci * 3438c2ecf20Sopenharmony_ci * @ns: Pointer to "struct tomoyo_policy_namespace". 3448c2ecf20Sopenharmony_ci * 3458c2ecf20Sopenharmony_ci * Returns nothing. 3468c2ecf20Sopenharmony_ci */ 3478c2ecf20Sopenharmony_civoid tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci unsigned int idx; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci for (idx = 0; idx < TOMOYO_MAX_ACL_GROUPS; idx++) 3528c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ns->acl_group[idx]); 3538c2ecf20Sopenharmony_ci for (idx = 0; idx < TOMOYO_MAX_GROUP; idx++) 3548c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ns->group_list[idx]); 3558c2ecf20Sopenharmony_ci for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++) 3568c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&ns->policy_list[idx]); 3578c2ecf20Sopenharmony_ci ns->profile_version = 20150505; 3588c2ecf20Sopenharmony_ci tomoyo_namespace_enabled = !list_empty(&tomoyo_namespace_list); 3598c2ecf20Sopenharmony_ci list_add_tail_rcu(&ns->namespace_list, &tomoyo_namespace_list); 3608c2ecf20Sopenharmony_ci} 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci/** 3638c2ecf20Sopenharmony_ci * tomoyo_print_namespace - Print namespace header. 3648c2ecf20Sopenharmony_ci * 3658c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 3668c2ecf20Sopenharmony_ci * 3678c2ecf20Sopenharmony_ci * Returns nothing. 3688c2ecf20Sopenharmony_ci */ 3698c2ecf20Sopenharmony_cistatic void tomoyo_print_namespace(struct tomoyo_io_buffer *head) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci if (!tomoyo_namespace_enabled) 3728c2ecf20Sopenharmony_ci return; 3738c2ecf20Sopenharmony_ci tomoyo_set_string(head, 3748c2ecf20Sopenharmony_ci container_of(head->r.ns, 3758c2ecf20Sopenharmony_ci struct tomoyo_policy_namespace, 3768c2ecf20Sopenharmony_ci namespace_list)->name); 3778c2ecf20Sopenharmony_ci tomoyo_set_space(head); 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci/** 3818c2ecf20Sopenharmony_ci * tomoyo_print_name_union - Print a tomoyo_name_union. 3828c2ecf20Sopenharmony_ci * 3838c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 3848c2ecf20Sopenharmony_ci * @ptr: Pointer to "struct tomoyo_name_union". 3858c2ecf20Sopenharmony_ci */ 3868c2ecf20Sopenharmony_cistatic void tomoyo_print_name_union(struct tomoyo_io_buffer *head, 3878c2ecf20Sopenharmony_ci const struct tomoyo_name_union *ptr) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci tomoyo_set_space(head); 3908c2ecf20Sopenharmony_ci if (ptr->group) { 3918c2ecf20Sopenharmony_ci tomoyo_set_string(head, "@"); 3928c2ecf20Sopenharmony_ci tomoyo_set_string(head, ptr->group->group_name->name); 3938c2ecf20Sopenharmony_ci } else { 3948c2ecf20Sopenharmony_ci tomoyo_set_string(head, ptr->filename->name); 3958c2ecf20Sopenharmony_ci } 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci/** 3998c2ecf20Sopenharmony_ci * tomoyo_print_name_union_quoted - Print a tomoyo_name_union with a quote. 4008c2ecf20Sopenharmony_ci * 4018c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 4028c2ecf20Sopenharmony_ci * @ptr: Pointer to "struct tomoyo_name_union". 4038c2ecf20Sopenharmony_ci * 4048c2ecf20Sopenharmony_ci * Returns nothing. 4058c2ecf20Sopenharmony_ci */ 4068c2ecf20Sopenharmony_cistatic void tomoyo_print_name_union_quoted(struct tomoyo_io_buffer *head, 4078c2ecf20Sopenharmony_ci const struct tomoyo_name_union *ptr) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci if (ptr->group) { 4108c2ecf20Sopenharmony_ci tomoyo_set_string(head, "@"); 4118c2ecf20Sopenharmony_ci tomoyo_set_string(head, ptr->group->group_name->name); 4128c2ecf20Sopenharmony_ci } else { 4138c2ecf20Sopenharmony_ci tomoyo_set_string(head, "\""); 4148c2ecf20Sopenharmony_ci tomoyo_set_string(head, ptr->filename->name); 4158c2ecf20Sopenharmony_ci tomoyo_set_string(head, "\""); 4168c2ecf20Sopenharmony_ci } 4178c2ecf20Sopenharmony_ci} 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci/** 4208c2ecf20Sopenharmony_ci * tomoyo_print_number_union_nospace - Print a tomoyo_number_union without a space. 4218c2ecf20Sopenharmony_ci * 4228c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 4238c2ecf20Sopenharmony_ci * @ptr: Pointer to "struct tomoyo_number_union". 4248c2ecf20Sopenharmony_ci * 4258c2ecf20Sopenharmony_ci * Returns nothing. 4268c2ecf20Sopenharmony_ci */ 4278c2ecf20Sopenharmony_cistatic void tomoyo_print_number_union_nospace 4288c2ecf20Sopenharmony_ci(struct tomoyo_io_buffer *head, const struct tomoyo_number_union *ptr) 4298c2ecf20Sopenharmony_ci{ 4308c2ecf20Sopenharmony_ci if (ptr->group) { 4318c2ecf20Sopenharmony_ci tomoyo_set_string(head, "@"); 4328c2ecf20Sopenharmony_ci tomoyo_set_string(head, ptr->group->group_name->name); 4338c2ecf20Sopenharmony_ci } else { 4348c2ecf20Sopenharmony_ci int i; 4358c2ecf20Sopenharmony_ci unsigned long min = ptr->values[0]; 4368c2ecf20Sopenharmony_ci const unsigned long max = ptr->values[1]; 4378c2ecf20Sopenharmony_ci u8 min_type = ptr->value_type[0]; 4388c2ecf20Sopenharmony_ci const u8 max_type = ptr->value_type[1]; 4398c2ecf20Sopenharmony_ci char buffer[128]; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci buffer[0] = '\0'; 4428c2ecf20Sopenharmony_ci for (i = 0; i < 2; i++) { 4438c2ecf20Sopenharmony_ci switch (min_type) { 4448c2ecf20Sopenharmony_ci case TOMOYO_VALUE_TYPE_HEXADECIMAL: 4458c2ecf20Sopenharmony_ci tomoyo_addprintf(buffer, sizeof(buffer), 4468c2ecf20Sopenharmony_ci "0x%lX", min); 4478c2ecf20Sopenharmony_ci break; 4488c2ecf20Sopenharmony_ci case TOMOYO_VALUE_TYPE_OCTAL: 4498c2ecf20Sopenharmony_ci tomoyo_addprintf(buffer, sizeof(buffer), 4508c2ecf20Sopenharmony_ci "0%lo", min); 4518c2ecf20Sopenharmony_ci break; 4528c2ecf20Sopenharmony_ci default: 4538c2ecf20Sopenharmony_ci tomoyo_addprintf(buffer, sizeof(buffer), "%lu", 4548c2ecf20Sopenharmony_ci min); 4558c2ecf20Sopenharmony_ci break; 4568c2ecf20Sopenharmony_ci } 4578c2ecf20Sopenharmony_ci if (min == max && min_type == max_type) 4588c2ecf20Sopenharmony_ci break; 4598c2ecf20Sopenharmony_ci tomoyo_addprintf(buffer, sizeof(buffer), "-"); 4608c2ecf20Sopenharmony_ci min_type = max_type; 4618c2ecf20Sopenharmony_ci min = max; 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "%s", buffer); 4648c2ecf20Sopenharmony_ci } 4658c2ecf20Sopenharmony_ci} 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_ci/** 4688c2ecf20Sopenharmony_ci * tomoyo_print_number_union - Print a tomoyo_number_union. 4698c2ecf20Sopenharmony_ci * 4708c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 4718c2ecf20Sopenharmony_ci * @ptr: Pointer to "struct tomoyo_number_union". 4728c2ecf20Sopenharmony_ci * 4738c2ecf20Sopenharmony_ci * Returns nothing. 4748c2ecf20Sopenharmony_ci */ 4758c2ecf20Sopenharmony_cistatic void tomoyo_print_number_union(struct tomoyo_io_buffer *head, 4768c2ecf20Sopenharmony_ci const struct tomoyo_number_union *ptr) 4778c2ecf20Sopenharmony_ci{ 4788c2ecf20Sopenharmony_ci tomoyo_set_space(head); 4798c2ecf20Sopenharmony_ci tomoyo_print_number_union_nospace(head, ptr); 4808c2ecf20Sopenharmony_ci} 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci/** 4838c2ecf20Sopenharmony_ci * tomoyo_assign_profile - Create a new profile. 4848c2ecf20Sopenharmony_ci * 4858c2ecf20Sopenharmony_ci * @ns: Pointer to "struct tomoyo_policy_namespace". 4868c2ecf20Sopenharmony_ci * @profile: Profile number to create. 4878c2ecf20Sopenharmony_ci * 4888c2ecf20Sopenharmony_ci * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise. 4898c2ecf20Sopenharmony_ci */ 4908c2ecf20Sopenharmony_cistatic struct tomoyo_profile *tomoyo_assign_profile 4918c2ecf20Sopenharmony_ci(struct tomoyo_policy_namespace *ns, const unsigned int profile) 4928c2ecf20Sopenharmony_ci{ 4938c2ecf20Sopenharmony_ci struct tomoyo_profile *ptr; 4948c2ecf20Sopenharmony_ci struct tomoyo_profile *entry; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci if (profile >= TOMOYO_MAX_PROFILES) 4978c2ecf20Sopenharmony_ci return NULL; 4988c2ecf20Sopenharmony_ci ptr = ns->profile_ptr[profile]; 4998c2ecf20Sopenharmony_ci if (ptr) 5008c2ecf20Sopenharmony_ci return ptr; 5018c2ecf20Sopenharmony_ci entry = kzalloc(sizeof(*entry), GFP_NOFS); 5028c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&tomoyo_policy_lock)) 5038c2ecf20Sopenharmony_ci goto out; 5048c2ecf20Sopenharmony_ci ptr = ns->profile_ptr[profile]; 5058c2ecf20Sopenharmony_ci if (!ptr && tomoyo_memory_ok(entry)) { 5068c2ecf20Sopenharmony_ci ptr = entry; 5078c2ecf20Sopenharmony_ci ptr->default_config = TOMOYO_CONFIG_DISABLED | 5088c2ecf20Sopenharmony_ci TOMOYO_CONFIG_WANT_GRANT_LOG | 5098c2ecf20Sopenharmony_ci TOMOYO_CONFIG_WANT_REJECT_LOG; 5108c2ecf20Sopenharmony_ci memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT, 5118c2ecf20Sopenharmony_ci sizeof(ptr->config)); 5128c2ecf20Sopenharmony_ci ptr->pref[TOMOYO_PREF_MAX_AUDIT_LOG] = 5138c2ecf20Sopenharmony_ci CONFIG_SECURITY_TOMOYO_MAX_AUDIT_LOG; 5148c2ecf20Sopenharmony_ci ptr->pref[TOMOYO_PREF_MAX_LEARNING_ENTRY] = 5158c2ecf20Sopenharmony_ci CONFIG_SECURITY_TOMOYO_MAX_ACCEPT_ENTRY; 5168c2ecf20Sopenharmony_ci mb(); /* Avoid out-of-order execution. */ 5178c2ecf20Sopenharmony_ci ns->profile_ptr[profile] = ptr; 5188c2ecf20Sopenharmony_ci entry = NULL; 5198c2ecf20Sopenharmony_ci } 5208c2ecf20Sopenharmony_ci mutex_unlock(&tomoyo_policy_lock); 5218c2ecf20Sopenharmony_ci out: 5228c2ecf20Sopenharmony_ci kfree(entry); 5238c2ecf20Sopenharmony_ci return ptr; 5248c2ecf20Sopenharmony_ci} 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci/** 5278c2ecf20Sopenharmony_ci * tomoyo_profile - Find a profile. 5288c2ecf20Sopenharmony_ci * 5298c2ecf20Sopenharmony_ci * @ns: Pointer to "struct tomoyo_policy_namespace". 5308c2ecf20Sopenharmony_ci * @profile: Profile number to find. 5318c2ecf20Sopenharmony_ci * 5328c2ecf20Sopenharmony_ci * Returns pointer to "struct tomoyo_profile". 5338c2ecf20Sopenharmony_ci */ 5348c2ecf20Sopenharmony_cistruct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns, 5358c2ecf20Sopenharmony_ci const u8 profile) 5368c2ecf20Sopenharmony_ci{ 5378c2ecf20Sopenharmony_ci static struct tomoyo_profile tomoyo_null_profile; 5388c2ecf20Sopenharmony_ci struct tomoyo_profile *ptr = ns->profile_ptr[profile]; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci if (!ptr) 5418c2ecf20Sopenharmony_ci ptr = &tomoyo_null_profile; 5428c2ecf20Sopenharmony_ci return ptr; 5438c2ecf20Sopenharmony_ci} 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci/** 5468c2ecf20Sopenharmony_ci * tomoyo_find_yesno - Find values for specified keyword. 5478c2ecf20Sopenharmony_ci * 5488c2ecf20Sopenharmony_ci * @string: String to check. 5498c2ecf20Sopenharmony_ci * @find: Name of keyword. 5508c2ecf20Sopenharmony_ci * 5518c2ecf20Sopenharmony_ci * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise. 5528c2ecf20Sopenharmony_ci */ 5538c2ecf20Sopenharmony_cistatic s8 tomoyo_find_yesno(const char *string, const char *find) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci const char *cp = strstr(string, find); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci if (cp) { 5588c2ecf20Sopenharmony_ci cp += strlen(find); 5598c2ecf20Sopenharmony_ci if (!strncmp(cp, "=yes", 4)) 5608c2ecf20Sopenharmony_ci return 1; 5618c2ecf20Sopenharmony_ci else if (!strncmp(cp, "=no", 3)) 5628c2ecf20Sopenharmony_ci return 0; 5638c2ecf20Sopenharmony_ci } 5648c2ecf20Sopenharmony_ci return -1; 5658c2ecf20Sopenharmony_ci} 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci/** 5688c2ecf20Sopenharmony_ci * tomoyo_set_uint - Set value for specified preference. 5698c2ecf20Sopenharmony_ci * 5708c2ecf20Sopenharmony_ci * @i: Pointer to "unsigned int". 5718c2ecf20Sopenharmony_ci * @string: String to check. 5728c2ecf20Sopenharmony_ci * @find: Name of keyword. 5738c2ecf20Sopenharmony_ci * 5748c2ecf20Sopenharmony_ci * Returns nothing. 5758c2ecf20Sopenharmony_ci */ 5768c2ecf20Sopenharmony_cistatic void tomoyo_set_uint(unsigned int *i, const char *string, 5778c2ecf20Sopenharmony_ci const char *find) 5788c2ecf20Sopenharmony_ci{ 5798c2ecf20Sopenharmony_ci const char *cp = strstr(string, find); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci if (cp) 5828c2ecf20Sopenharmony_ci sscanf(cp + strlen(find), "=%u", i); 5838c2ecf20Sopenharmony_ci} 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci/** 5868c2ecf20Sopenharmony_ci * tomoyo_set_mode - Set mode for specified profile. 5878c2ecf20Sopenharmony_ci * 5888c2ecf20Sopenharmony_ci * @name: Name of functionality. 5898c2ecf20Sopenharmony_ci * @value: Mode for @name. 5908c2ecf20Sopenharmony_ci * @profile: Pointer to "struct tomoyo_profile". 5918c2ecf20Sopenharmony_ci * 5928c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 5938c2ecf20Sopenharmony_ci */ 5948c2ecf20Sopenharmony_cistatic int tomoyo_set_mode(char *name, const char *value, 5958c2ecf20Sopenharmony_ci struct tomoyo_profile *profile) 5968c2ecf20Sopenharmony_ci{ 5978c2ecf20Sopenharmony_ci u8 i; 5988c2ecf20Sopenharmony_ci u8 config; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci if (!strcmp(name, "CONFIG")) { 6018c2ecf20Sopenharmony_ci i = TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX; 6028c2ecf20Sopenharmony_ci config = profile->default_config; 6038c2ecf20Sopenharmony_ci } else if (tomoyo_str_starts(&name, "CONFIG::")) { 6048c2ecf20Sopenharmony_ci config = 0; 6058c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_MAC_INDEX 6068c2ecf20Sopenharmony_ci + TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) { 6078c2ecf20Sopenharmony_ci int len = 0; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci if (i < TOMOYO_MAX_MAC_INDEX) { 6108c2ecf20Sopenharmony_ci const u8 c = tomoyo_index2category[i]; 6118c2ecf20Sopenharmony_ci const char *category = 6128c2ecf20Sopenharmony_ci tomoyo_category_keywords[c]; 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci len = strlen(category); 6158c2ecf20Sopenharmony_ci if (strncmp(name, category, len) || 6168c2ecf20Sopenharmony_ci name[len++] != ':' || name[len++] != ':') 6178c2ecf20Sopenharmony_ci continue; 6188c2ecf20Sopenharmony_ci } 6198c2ecf20Sopenharmony_ci if (strcmp(name + len, tomoyo_mac_keywords[i])) 6208c2ecf20Sopenharmony_ci continue; 6218c2ecf20Sopenharmony_ci config = profile->config[i]; 6228c2ecf20Sopenharmony_ci break; 6238c2ecf20Sopenharmony_ci } 6248c2ecf20Sopenharmony_ci if (i == TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX) 6258c2ecf20Sopenharmony_ci return -EINVAL; 6268c2ecf20Sopenharmony_ci } else { 6278c2ecf20Sopenharmony_ci return -EINVAL; 6288c2ecf20Sopenharmony_ci } 6298c2ecf20Sopenharmony_ci if (strstr(value, "use_default")) { 6308c2ecf20Sopenharmony_ci config = TOMOYO_CONFIG_USE_DEFAULT; 6318c2ecf20Sopenharmony_ci } else { 6328c2ecf20Sopenharmony_ci u8 mode; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci for (mode = 0; mode < 4; mode++) 6358c2ecf20Sopenharmony_ci if (strstr(value, tomoyo_mode[mode])) 6368c2ecf20Sopenharmony_ci /* 6378c2ecf20Sopenharmony_ci * Update lower 3 bits in order to distinguish 6388c2ecf20Sopenharmony_ci * 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'. 6398c2ecf20Sopenharmony_ci */ 6408c2ecf20Sopenharmony_ci config = (config & ~7) | mode; 6418c2ecf20Sopenharmony_ci if (config != TOMOYO_CONFIG_USE_DEFAULT) { 6428c2ecf20Sopenharmony_ci switch (tomoyo_find_yesno(value, "grant_log")) { 6438c2ecf20Sopenharmony_ci case 1: 6448c2ecf20Sopenharmony_ci config |= TOMOYO_CONFIG_WANT_GRANT_LOG; 6458c2ecf20Sopenharmony_ci break; 6468c2ecf20Sopenharmony_ci case 0: 6478c2ecf20Sopenharmony_ci config &= ~TOMOYO_CONFIG_WANT_GRANT_LOG; 6488c2ecf20Sopenharmony_ci break; 6498c2ecf20Sopenharmony_ci } 6508c2ecf20Sopenharmony_ci switch (tomoyo_find_yesno(value, "reject_log")) { 6518c2ecf20Sopenharmony_ci case 1: 6528c2ecf20Sopenharmony_ci config |= TOMOYO_CONFIG_WANT_REJECT_LOG; 6538c2ecf20Sopenharmony_ci break; 6548c2ecf20Sopenharmony_ci case 0: 6558c2ecf20Sopenharmony_ci config &= ~TOMOYO_CONFIG_WANT_REJECT_LOG; 6568c2ecf20Sopenharmony_ci break; 6578c2ecf20Sopenharmony_ci } 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci if (i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX) 6618c2ecf20Sopenharmony_ci profile->config[i] = config; 6628c2ecf20Sopenharmony_ci else if (config != TOMOYO_CONFIG_USE_DEFAULT) 6638c2ecf20Sopenharmony_ci profile->default_config = config; 6648c2ecf20Sopenharmony_ci return 0; 6658c2ecf20Sopenharmony_ci} 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci/** 6688c2ecf20Sopenharmony_ci * tomoyo_write_profile - Write profile table. 6698c2ecf20Sopenharmony_ci * 6708c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 6718c2ecf20Sopenharmony_ci * 6728c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 6738c2ecf20Sopenharmony_ci */ 6748c2ecf20Sopenharmony_cistatic int tomoyo_write_profile(struct tomoyo_io_buffer *head) 6758c2ecf20Sopenharmony_ci{ 6768c2ecf20Sopenharmony_ci char *data = head->write_buf; 6778c2ecf20Sopenharmony_ci unsigned int i; 6788c2ecf20Sopenharmony_ci char *cp; 6798c2ecf20Sopenharmony_ci struct tomoyo_profile *profile; 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version) 6828c2ecf20Sopenharmony_ci == 1) 6838c2ecf20Sopenharmony_ci return 0; 6848c2ecf20Sopenharmony_ci i = simple_strtoul(data, &cp, 10); 6858c2ecf20Sopenharmony_ci if (*cp != '-') 6868c2ecf20Sopenharmony_ci return -EINVAL; 6878c2ecf20Sopenharmony_ci data = cp + 1; 6888c2ecf20Sopenharmony_ci profile = tomoyo_assign_profile(head->w.ns, i); 6898c2ecf20Sopenharmony_ci if (!profile) 6908c2ecf20Sopenharmony_ci return -EINVAL; 6918c2ecf20Sopenharmony_ci cp = strchr(data, '='); 6928c2ecf20Sopenharmony_ci if (!cp) 6938c2ecf20Sopenharmony_ci return -EINVAL; 6948c2ecf20Sopenharmony_ci *cp++ = '\0'; 6958c2ecf20Sopenharmony_ci if (!strcmp(data, "COMMENT")) { 6968c2ecf20Sopenharmony_ci static DEFINE_SPINLOCK(lock); 6978c2ecf20Sopenharmony_ci const struct tomoyo_path_info *new_comment 6988c2ecf20Sopenharmony_ci = tomoyo_get_name(cp); 6998c2ecf20Sopenharmony_ci const struct tomoyo_path_info *old_comment; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci if (!new_comment) 7028c2ecf20Sopenharmony_ci return -ENOMEM; 7038c2ecf20Sopenharmony_ci spin_lock(&lock); 7048c2ecf20Sopenharmony_ci old_comment = profile->comment; 7058c2ecf20Sopenharmony_ci profile->comment = new_comment; 7068c2ecf20Sopenharmony_ci spin_unlock(&lock); 7078c2ecf20Sopenharmony_ci tomoyo_put_name(old_comment); 7088c2ecf20Sopenharmony_ci return 0; 7098c2ecf20Sopenharmony_ci } 7108c2ecf20Sopenharmony_ci if (!strcmp(data, "PREFERENCE")) { 7118c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_PREF; i++) 7128c2ecf20Sopenharmony_ci tomoyo_set_uint(&profile->pref[i], cp, 7138c2ecf20Sopenharmony_ci tomoyo_pref_keywords[i]); 7148c2ecf20Sopenharmony_ci return 0; 7158c2ecf20Sopenharmony_ci } 7168c2ecf20Sopenharmony_ci return tomoyo_set_mode(data, cp, profile); 7178c2ecf20Sopenharmony_ci} 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci/** 7208c2ecf20Sopenharmony_ci * tomoyo_print_config - Print mode for specified functionality. 7218c2ecf20Sopenharmony_ci * 7228c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 7238c2ecf20Sopenharmony_ci * @config: Mode for that functionality. 7248c2ecf20Sopenharmony_ci * 7258c2ecf20Sopenharmony_ci * Returns nothing. 7268c2ecf20Sopenharmony_ci * 7278c2ecf20Sopenharmony_ci * Caller prints functionality's name. 7288c2ecf20Sopenharmony_ci */ 7298c2ecf20Sopenharmony_cistatic void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config) 7308c2ecf20Sopenharmony_ci{ 7318c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n", 7328c2ecf20Sopenharmony_ci tomoyo_mode[config & 3], 7338c2ecf20Sopenharmony_ci tomoyo_yesno(config & TOMOYO_CONFIG_WANT_GRANT_LOG), 7348c2ecf20Sopenharmony_ci tomoyo_yesno(config & TOMOYO_CONFIG_WANT_REJECT_LOG)); 7358c2ecf20Sopenharmony_ci} 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci/** 7388c2ecf20Sopenharmony_ci * tomoyo_read_profile - Read profile table. 7398c2ecf20Sopenharmony_ci * 7408c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 7418c2ecf20Sopenharmony_ci * 7428c2ecf20Sopenharmony_ci * Returns nothing. 7438c2ecf20Sopenharmony_ci */ 7448c2ecf20Sopenharmony_cistatic void tomoyo_read_profile(struct tomoyo_io_buffer *head) 7458c2ecf20Sopenharmony_ci{ 7468c2ecf20Sopenharmony_ci u8 index; 7478c2ecf20Sopenharmony_ci struct tomoyo_policy_namespace *ns = 7488c2ecf20Sopenharmony_ci container_of(head->r.ns, typeof(*ns), namespace_list); 7498c2ecf20Sopenharmony_ci const struct tomoyo_profile *profile; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci if (head->r.eof) 7528c2ecf20Sopenharmony_ci return; 7538c2ecf20Sopenharmony_ci next: 7548c2ecf20Sopenharmony_ci index = head->r.index; 7558c2ecf20Sopenharmony_ci profile = ns->profile_ptr[index]; 7568c2ecf20Sopenharmony_ci switch (head->r.step) { 7578c2ecf20Sopenharmony_ci case 0: 7588c2ecf20Sopenharmony_ci tomoyo_print_namespace(head); 7598c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "PROFILE_VERSION=%u\n", 7608c2ecf20Sopenharmony_ci ns->profile_version); 7618c2ecf20Sopenharmony_ci head->r.step++; 7628c2ecf20Sopenharmony_ci break; 7638c2ecf20Sopenharmony_ci case 1: 7648c2ecf20Sopenharmony_ci for ( ; head->r.index < TOMOYO_MAX_PROFILES; 7658c2ecf20Sopenharmony_ci head->r.index++) 7668c2ecf20Sopenharmony_ci if (ns->profile_ptr[head->r.index]) 7678c2ecf20Sopenharmony_ci break; 7688c2ecf20Sopenharmony_ci if (head->r.index == TOMOYO_MAX_PROFILES) { 7698c2ecf20Sopenharmony_ci head->r.eof = true; 7708c2ecf20Sopenharmony_ci return; 7718c2ecf20Sopenharmony_ci } 7728c2ecf20Sopenharmony_ci head->r.step++; 7738c2ecf20Sopenharmony_ci break; 7748c2ecf20Sopenharmony_ci case 2: 7758c2ecf20Sopenharmony_ci { 7768c2ecf20Sopenharmony_ci u8 i; 7778c2ecf20Sopenharmony_ci const struct tomoyo_path_info *comment = 7788c2ecf20Sopenharmony_ci profile->comment; 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci tomoyo_print_namespace(head); 7818c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "%u-COMMENT=", index); 7828c2ecf20Sopenharmony_ci tomoyo_set_string(head, comment ? comment->name : ""); 7838c2ecf20Sopenharmony_ci tomoyo_set_lf(head); 7848c2ecf20Sopenharmony_ci tomoyo_print_namespace(head); 7858c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "%u-PREFERENCE={ ", index); 7868c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_PREF; i++) 7878c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "%s=%u ", 7888c2ecf20Sopenharmony_ci tomoyo_pref_keywords[i], 7898c2ecf20Sopenharmony_ci profile->pref[i]); 7908c2ecf20Sopenharmony_ci tomoyo_set_string(head, "}\n"); 7918c2ecf20Sopenharmony_ci head->r.step++; 7928c2ecf20Sopenharmony_ci } 7938c2ecf20Sopenharmony_ci break; 7948c2ecf20Sopenharmony_ci case 3: 7958c2ecf20Sopenharmony_ci { 7968c2ecf20Sopenharmony_ci tomoyo_print_namespace(head); 7978c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "%u-%s", index, "CONFIG"); 7988c2ecf20Sopenharmony_ci tomoyo_print_config(head, profile->default_config); 7998c2ecf20Sopenharmony_ci head->r.bit = 0; 8008c2ecf20Sopenharmony_ci head->r.step++; 8018c2ecf20Sopenharmony_ci } 8028c2ecf20Sopenharmony_ci break; 8038c2ecf20Sopenharmony_ci case 4: 8048c2ecf20Sopenharmony_ci for ( ; head->r.bit < TOMOYO_MAX_MAC_INDEX 8058c2ecf20Sopenharmony_ci + TOMOYO_MAX_MAC_CATEGORY_INDEX; head->r.bit++) { 8068c2ecf20Sopenharmony_ci const u8 i = head->r.bit; 8078c2ecf20Sopenharmony_ci const u8 config = profile->config[i]; 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci if (config == TOMOYO_CONFIG_USE_DEFAULT) 8108c2ecf20Sopenharmony_ci continue; 8118c2ecf20Sopenharmony_ci tomoyo_print_namespace(head); 8128c2ecf20Sopenharmony_ci if (i < TOMOYO_MAX_MAC_INDEX) 8138c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "%u-CONFIG::%s::%s", 8148c2ecf20Sopenharmony_ci index, 8158c2ecf20Sopenharmony_ci tomoyo_category_keywords 8168c2ecf20Sopenharmony_ci [tomoyo_index2category[i]], 8178c2ecf20Sopenharmony_ci tomoyo_mac_keywords[i]); 8188c2ecf20Sopenharmony_ci else 8198c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "%u-CONFIG::%s", index, 8208c2ecf20Sopenharmony_ci tomoyo_mac_keywords[i]); 8218c2ecf20Sopenharmony_ci tomoyo_print_config(head, config); 8228c2ecf20Sopenharmony_ci head->r.bit++; 8238c2ecf20Sopenharmony_ci break; 8248c2ecf20Sopenharmony_ci } 8258c2ecf20Sopenharmony_ci if (head->r.bit == TOMOYO_MAX_MAC_INDEX 8268c2ecf20Sopenharmony_ci + TOMOYO_MAX_MAC_CATEGORY_INDEX) { 8278c2ecf20Sopenharmony_ci head->r.index++; 8288c2ecf20Sopenharmony_ci head->r.step = 1; 8298c2ecf20Sopenharmony_ci } 8308c2ecf20Sopenharmony_ci break; 8318c2ecf20Sopenharmony_ci } 8328c2ecf20Sopenharmony_ci if (tomoyo_flush(head)) 8338c2ecf20Sopenharmony_ci goto next; 8348c2ecf20Sopenharmony_ci} 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci/** 8378c2ecf20Sopenharmony_ci * tomoyo_same_manager - Check for duplicated "struct tomoyo_manager" entry. 8388c2ecf20Sopenharmony_ci * 8398c2ecf20Sopenharmony_ci * @a: Pointer to "struct tomoyo_acl_head". 8408c2ecf20Sopenharmony_ci * @b: Pointer to "struct tomoyo_acl_head". 8418c2ecf20Sopenharmony_ci * 8428c2ecf20Sopenharmony_ci * Returns true if @a == @b, false otherwise. 8438c2ecf20Sopenharmony_ci */ 8448c2ecf20Sopenharmony_cistatic bool tomoyo_same_manager(const struct tomoyo_acl_head *a, 8458c2ecf20Sopenharmony_ci const struct tomoyo_acl_head *b) 8468c2ecf20Sopenharmony_ci{ 8478c2ecf20Sopenharmony_ci return container_of(a, struct tomoyo_manager, head)->manager == 8488c2ecf20Sopenharmony_ci container_of(b, struct tomoyo_manager, head)->manager; 8498c2ecf20Sopenharmony_ci} 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci/** 8528c2ecf20Sopenharmony_ci * tomoyo_update_manager_entry - Add a manager entry. 8538c2ecf20Sopenharmony_ci * 8548c2ecf20Sopenharmony_ci * @manager: The path to manager or the domainnamme. 8558c2ecf20Sopenharmony_ci * @is_delete: True if it is a delete request. 8568c2ecf20Sopenharmony_ci * 8578c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 8588c2ecf20Sopenharmony_ci * 8598c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 8608c2ecf20Sopenharmony_ci */ 8618c2ecf20Sopenharmony_cistatic int tomoyo_update_manager_entry(const char *manager, 8628c2ecf20Sopenharmony_ci const bool is_delete) 8638c2ecf20Sopenharmony_ci{ 8648c2ecf20Sopenharmony_ci struct tomoyo_manager e = { }; 8658c2ecf20Sopenharmony_ci struct tomoyo_acl_param param = { 8668c2ecf20Sopenharmony_ci /* .ns = &tomoyo_kernel_namespace, */ 8678c2ecf20Sopenharmony_ci .is_delete = is_delete, 8688c2ecf20Sopenharmony_ci .list = &tomoyo_kernel_namespace.policy_list[TOMOYO_ID_MANAGER], 8698c2ecf20Sopenharmony_ci }; 8708c2ecf20Sopenharmony_ci int error = is_delete ? -ENOENT : -ENOMEM; 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci if (!tomoyo_correct_domain(manager) && 8738c2ecf20Sopenharmony_ci !tomoyo_correct_word(manager)) 8748c2ecf20Sopenharmony_ci return -EINVAL; 8758c2ecf20Sopenharmony_ci e.manager = tomoyo_get_name(manager); 8768c2ecf20Sopenharmony_ci if (e.manager) { 8778c2ecf20Sopenharmony_ci error = tomoyo_update_policy(&e.head, sizeof(e), ¶m, 8788c2ecf20Sopenharmony_ci tomoyo_same_manager); 8798c2ecf20Sopenharmony_ci tomoyo_put_name(e.manager); 8808c2ecf20Sopenharmony_ci } 8818c2ecf20Sopenharmony_ci return error; 8828c2ecf20Sopenharmony_ci} 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci/** 8858c2ecf20Sopenharmony_ci * tomoyo_write_manager - Write manager policy. 8868c2ecf20Sopenharmony_ci * 8878c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 8888c2ecf20Sopenharmony_ci * 8898c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 8908c2ecf20Sopenharmony_ci * 8918c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 8928c2ecf20Sopenharmony_ci */ 8938c2ecf20Sopenharmony_cistatic int tomoyo_write_manager(struct tomoyo_io_buffer *head) 8948c2ecf20Sopenharmony_ci{ 8958c2ecf20Sopenharmony_ci char *data = head->write_buf; 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci if (!strcmp(data, "manage_by_non_root")) { 8988c2ecf20Sopenharmony_ci tomoyo_manage_by_non_root = !head->w.is_delete; 8998c2ecf20Sopenharmony_ci return 0; 9008c2ecf20Sopenharmony_ci } 9018c2ecf20Sopenharmony_ci return tomoyo_update_manager_entry(data, head->w.is_delete); 9028c2ecf20Sopenharmony_ci} 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci/** 9058c2ecf20Sopenharmony_ci * tomoyo_read_manager - Read manager policy. 9068c2ecf20Sopenharmony_ci * 9078c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 9088c2ecf20Sopenharmony_ci * 9098c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 9108c2ecf20Sopenharmony_ci */ 9118c2ecf20Sopenharmony_cistatic void tomoyo_read_manager(struct tomoyo_io_buffer *head) 9128c2ecf20Sopenharmony_ci{ 9138c2ecf20Sopenharmony_ci if (head->r.eof) 9148c2ecf20Sopenharmony_ci return; 9158c2ecf20Sopenharmony_ci list_for_each_cookie(head->r.acl, &tomoyo_kernel_namespace.policy_list[TOMOYO_ID_MANAGER]) { 9168c2ecf20Sopenharmony_ci struct tomoyo_manager *ptr = 9178c2ecf20Sopenharmony_ci list_entry(head->r.acl, typeof(*ptr), head.list); 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci if (ptr->head.is_deleted) 9208c2ecf20Sopenharmony_ci continue; 9218c2ecf20Sopenharmony_ci if (!tomoyo_flush(head)) 9228c2ecf20Sopenharmony_ci return; 9238c2ecf20Sopenharmony_ci tomoyo_set_string(head, ptr->manager->name); 9248c2ecf20Sopenharmony_ci tomoyo_set_lf(head); 9258c2ecf20Sopenharmony_ci } 9268c2ecf20Sopenharmony_ci head->r.eof = true; 9278c2ecf20Sopenharmony_ci} 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci/** 9308c2ecf20Sopenharmony_ci * tomoyo_manager - Check whether the current process is a policy manager. 9318c2ecf20Sopenharmony_ci * 9328c2ecf20Sopenharmony_ci * Returns true if the current process is permitted to modify policy 9338c2ecf20Sopenharmony_ci * via /sys/kernel/security/tomoyo/ interface. 9348c2ecf20Sopenharmony_ci * 9358c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 9368c2ecf20Sopenharmony_ci */ 9378c2ecf20Sopenharmony_cistatic bool tomoyo_manager(void) 9388c2ecf20Sopenharmony_ci{ 9398c2ecf20Sopenharmony_ci struct tomoyo_manager *ptr; 9408c2ecf20Sopenharmony_ci const char *exe; 9418c2ecf20Sopenharmony_ci const struct task_struct *task = current; 9428c2ecf20Sopenharmony_ci const struct tomoyo_path_info *domainname = tomoyo_domain()->domainname; 9438c2ecf20Sopenharmony_ci bool found = IS_ENABLED(CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING); 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci if (!tomoyo_policy_loaded) 9468c2ecf20Sopenharmony_ci return true; 9478c2ecf20Sopenharmony_ci if (!tomoyo_manage_by_non_root && 9488c2ecf20Sopenharmony_ci (!uid_eq(task->cred->uid, GLOBAL_ROOT_UID) || 9498c2ecf20Sopenharmony_ci !uid_eq(task->cred->euid, GLOBAL_ROOT_UID))) 9508c2ecf20Sopenharmony_ci return false; 9518c2ecf20Sopenharmony_ci exe = tomoyo_get_exe(); 9528c2ecf20Sopenharmony_ci if (!exe) 9538c2ecf20Sopenharmony_ci return false; 9548c2ecf20Sopenharmony_ci list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace.policy_list[TOMOYO_ID_MANAGER], head.list, 9558c2ecf20Sopenharmony_ci srcu_read_lock_held(&tomoyo_ss)) { 9568c2ecf20Sopenharmony_ci if (!ptr->head.is_deleted && 9578c2ecf20Sopenharmony_ci (!tomoyo_pathcmp(domainname, ptr->manager) || 9588c2ecf20Sopenharmony_ci !strcmp(exe, ptr->manager->name))) { 9598c2ecf20Sopenharmony_ci found = true; 9608c2ecf20Sopenharmony_ci break; 9618c2ecf20Sopenharmony_ci } 9628c2ecf20Sopenharmony_ci } 9638c2ecf20Sopenharmony_ci if (!found) { /* Reduce error messages. */ 9648c2ecf20Sopenharmony_ci static pid_t last_pid; 9658c2ecf20Sopenharmony_ci const pid_t pid = current->pid; 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci if (last_pid != pid) { 9688c2ecf20Sopenharmony_ci pr_warn("%s ( %s ) is not permitted to update policies.\n", 9698c2ecf20Sopenharmony_ci domainname->name, exe); 9708c2ecf20Sopenharmony_ci last_pid = pid; 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci } 9738c2ecf20Sopenharmony_ci kfree(exe); 9748c2ecf20Sopenharmony_ci return found; 9758c2ecf20Sopenharmony_ci} 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_cistatic struct tomoyo_domain_info *tomoyo_find_domain_by_qid 9788c2ecf20Sopenharmony_ci(unsigned int serial); 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci/** 9818c2ecf20Sopenharmony_ci * tomoyo_select_domain - Parse select command. 9828c2ecf20Sopenharmony_ci * 9838c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 9848c2ecf20Sopenharmony_ci * @data: String to parse. 9858c2ecf20Sopenharmony_ci * 9868c2ecf20Sopenharmony_ci * Returns true on success, false otherwise. 9878c2ecf20Sopenharmony_ci * 9888c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 9898c2ecf20Sopenharmony_ci */ 9908c2ecf20Sopenharmony_cistatic bool tomoyo_select_domain(struct tomoyo_io_buffer *head, 9918c2ecf20Sopenharmony_ci const char *data) 9928c2ecf20Sopenharmony_ci{ 9938c2ecf20Sopenharmony_ci unsigned int pid; 9948c2ecf20Sopenharmony_ci struct tomoyo_domain_info *domain = NULL; 9958c2ecf20Sopenharmony_ci bool global_pid = false; 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci if (strncmp(data, "select ", 7)) 9988c2ecf20Sopenharmony_ci return false; 9998c2ecf20Sopenharmony_ci data += 7; 10008c2ecf20Sopenharmony_ci if (sscanf(data, "pid=%u", &pid) == 1 || 10018c2ecf20Sopenharmony_ci (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) { 10028c2ecf20Sopenharmony_ci struct task_struct *p; 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci rcu_read_lock(); 10058c2ecf20Sopenharmony_ci if (global_pid) 10068c2ecf20Sopenharmony_ci p = find_task_by_pid_ns(pid, &init_pid_ns); 10078c2ecf20Sopenharmony_ci else 10088c2ecf20Sopenharmony_ci p = find_task_by_vpid(pid); 10098c2ecf20Sopenharmony_ci if (p) 10108c2ecf20Sopenharmony_ci domain = tomoyo_task(p)->domain_info; 10118c2ecf20Sopenharmony_ci rcu_read_unlock(); 10128c2ecf20Sopenharmony_ci } else if (!strncmp(data, "domain=", 7)) { 10138c2ecf20Sopenharmony_ci if (tomoyo_domain_def(data + 7)) 10148c2ecf20Sopenharmony_ci domain = tomoyo_find_domain(data + 7); 10158c2ecf20Sopenharmony_ci } else if (sscanf(data, "Q=%u", &pid) == 1) { 10168c2ecf20Sopenharmony_ci domain = tomoyo_find_domain_by_qid(pid); 10178c2ecf20Sopenharmony_ci } else 10188c2ecf20Sopenharmony_ci return false; 10198c2ecf20Sopenharmony_ci head->w.domain = domain; 10208c2ecf20Sopenharmony_ci /* Accessing read_buf is safe because head->io_sem is held. */ 10218c2ecf20Sopenharmony_ci if (!head->read_buf) 10228c2ecf20Sopenharmony_ci return true; /* Do nothing if open(O_WRONLY). */ 10238c2ecf20Sopenharmony_ci memset(&head->r, 0, sizeof(head->r)); 10248c2ecf20Sopenharmony_ci head->r.print_this_domain_only = true; 10258c2ecf20Sopenharmony_ci if (domain) 10268c2ecf20Sopenharmony_ci head->r.domain = &domain->list; 10278c2ecf20Sopenharmony_ci else 10288c2ecf20Sopenharmony_ci head->r.eof = true; 10298c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "# select %s\n", data); 10308c2ecf20Sopenharmony_ci if (domain && domain->is_deleted) 10318c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "# This is a deleted domain.\n"); 10328c2ecf20Sopenharmony_ci return true; 10338c2ecf20Sopenharmony_ci} 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci/** 10368c2ecf20Sopenharmony_ci * tomoyo_same_task_acl - Check for duplicated "struct tomoyo_task_acl" entry. 10378c2ecf20Sopenharmony_ci * 10388c2ecf20Sopenharmony_ci * @a: Pointer to "struct tomoyo_acl_info". 10398c2ecf20Sopenharmony_ci * @b: Pointer to "struct tomoyo_acl_info". 10408c2ecf20Sopenharmony_ci * 10418c2ecf20Sopenharmony_ci * Returns true if @a == @b, false otherwise. 10428c2ecf20Sopenharmony_ci */ 10438c2ecf20Sopenharmony_cistatic bool tomoyo_same_task_acl(const struct tomoyo_acl_info *a, 10448c2ecf20Sopenharmony_ci const struct tomoyo_acl_info *b) 10458c2ecf20Sopenharmony_ci{ 10468c2ecf20Sopenharmony_ci const struct tomoyo_task_acl *p1 = container_of(a, typeof(*p1), head); 10478c2ecf20Sopenharmony_ci const struct tomoyo_task_acl *p2 = container_of(b, typeof(*p2), head); 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci return p1->domainname == p2->domainname; 10508c2ecf20Sopenharmony_ci} 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci/** 10538c2ecf20Sopenharmony_ci * tomoyo_write_task - Update task related list. 10548c2ecf20Sopenharmony_ci * 10558c2ecf20Sopenharmony_ci * @param: Pointer to "struct tomoyo_acl_param". 10568c2ecf20Sopenharmony_ci * 10578c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 10588c2ecf20Sopenharmony_ci * 10598c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 10608c2ecf20Sopenharmony_ci */ 10618c2ecf20Sopenharmony_cistatic int tomoyo_write_task(struct tomoyo_acl_param *param) 10628c2ecf20Sopenharmony_ci{ 10638c2ecf20Sopenharmony_ci int error = -EINVAL; 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci if (tomoyo_str_starts(¶m->data, "manual_domain_transition ")) { 10668c2ecf20Sopenharmony_ci struct tomoyo_task_acl e = { 10678c2ecf20Sopenharmony_ci .head.type = TOMOYO_TYPE_MANUAL_TASK_ACL, 10688c2ecf20Sopenharmony_ci .domainname = tomoyo_get_domainname(param), 10698c2ecf20Sopenharmony_ci }; 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci if (e.domainname) 10728c2ecf20Sopenharmony_ci error = tomoyo_update_domain(&e.head, sizeof(e), param, 10738c2ecf20Sopenharmony_ci tomoyo_same_task_acl, 10748c2ecf20Sopenharmony_ci NULL); 10758c2ecf20Sopenharmony_ci tomoyo_put_name(e.domainname); 10768c2ecf20Sopenharmony_ci } 10778c2ecf20Sopenharmony_ci return error; 10788c2ecf20Sopenharmony_ci} 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci/** 10818c2ecf20Sopenharmony_ci * tomoyo_delete_domain - Delete a domain. 10828c2ecf20Sopenharmony_ci * 10838c2ecf20Sopenharmony_ci * @domainname: The name of domain. 10848c2ecf20Sopenharmony_ci * 10858c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 10868c2ecf20Sopenharmony_ci * 10878c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 10888c2ecf20Sopenharmony_ci */ 10898c2ecf20Sopenharmony_cistatic int tomoyo_delete_domain(char *domainname) 10908c2ecf20Sopenharmony_ci{ 10918c2ecf20Sopenharmony_ci struct tomoyo_domain_info *domain; 10928c2ecf20Sopenharmony_ci struct tomoyo_path_info name; 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci name.name = domainname; 10958c2ecf20Sopenharmony_ci tomoyo_fill_path_info(&name); 10968c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&tomoyo_policy_lock)) 10978c2ecf20Sopenharmony_ci return -EINTR; 10988c2ecf20Sopenharmony_ci /* Is there an active domain? */ 10998c2ecf20Sopenharmony_ci list_for_each_entry_rcu(domain, &tomoyo_domain_list, list, 11008c2ecf20Sopenharmony_ci srcu_read_lock_held(&tomoyo_ss)) { 11018c2ecf20Sopenharmony_ci /* Never delete tomoyo_kernel_domain */ 11028c2ecf20Sopenharmony_ci if (domain == &tomoyo_kernel_domain) 11038c2ecf20Sopenharmony_ci continue; 11048c2ecf20Sopenharmony_ci if (domain->is_deleted || 11058c2ecf20Sopenharmony_ci tomoyo_pathcmp(domain->domainname, &name)) 11068c2ecf20Sopenharmony_ci continue; 11078c2ecf20Sopenharmony_ci domain->is_deleted = true; 11088c2ecf20Sopenharmony_ci break; 11098c2ecf20Sopenharmony_ci } 11108c2ecf20Sopenharmony_ci mutex_unlock(&tomoyo_policy_lock); 11118c2ecf20Sopenharmony_ci return 0; 11128c2ecf20Sopenharmony_ci} 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci/** 11158c2ecf20Sopenharmony_ci * tomoyo_write_domain2 - Write domain policy. 11168c2ecf20Sopenharmony_ci * 11178c2ecf20Sopenharmony_ci * @ns: Pointer to "struct tomoyo_policy_namespace". 11188c2ecf20Sopenharmony_ci * @list: Pointer to "struct list_head". 11198c2ecf20Sopenharmony_ci * @data: Policy to be interpreted. 11208c2ecf20Sopenharmony_ci * @is_delete: True if it is a delete request. 11218c2ecf20Sopenharmony_ci * 11228c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 11238c2ecf20Sopenharmony_ci * 11248c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 11258c2ecf20Sopenharmony_ci */ 11268c2ecf20Sopenharmony_cistatic int tomoyo_write_domain2(struct tomoyo_policy_namespace *ns, 11278c2ecf20Sopenharmony_ci struct list_head *list, char *data, 11288c2ecf20Sopenharmony_ci const bool is_delete) 11298c2ecf20Sopenharmony_ci{ 11308c2ecf20Sopenharmony_ci struct tomoyo_acl_param param = { 11318c2ecf20Sopenharmony_ci .ns = ns, 11328c2ecf20Sopenharmony_ci .list = list, 11338c2ecf20Sopenharmony_ci .data = data, 11348c2ecf20Sopenharmony_ci .is_delete = is_delete, 11358c2ecf20Sopenharmony_ci }; 11368c2ecf20Sopenharmony_ci static const struct { 11378c2ecf20Sopenharmony_ci const char *keyword; 11388c2ecf20Sopenharmony_ci int (*write)(struct tomoyo_acl_param *param); 11398c2ecf20Sopenharmony_ci } tomoyo_callback[5] = { 11408c2ecf20Sopenharmony_ci { "file ", tomoyo_write_file }, 11418c2ecf20Sopenharmony_ci { "network inet ", tomoyo_write_inet_network }, 11428c2ecf20Sopenharmony_ci { "network unix ", tomoyo_write_unix_network }, 11438c2ecf20Sopenharmony_ci { "misc ", tomoyo_write_misc }, 11448c2ecf20Sopenharmony_ci { "task ", tomoyo_write_task }, 11458c2ecf20Sopenharmony_ci }; 11468c2ecf20Sopenharmony_ci u8 i; 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(tomoyo_callback); i++) { 11498c2ecf20Sopenharmony_ci if (!tomoyo_str_starts(¶m.data, 11508c2ecf20Sopenharmony_ci tomoyo_callback[i].keyword)) 11518c2ecf20Sopenharmony_ci continue; 11528c2ecf20Sopenharmony_ci return tomoyo_callback[i].write(¶m); 11538c2ecf20Sopenharmony_ci } 11548c2ecf20Sopenharmony_ci return -EINVAL; 11558c2ecf20Sopenharmony_ci} 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci/* String table for domain flags. */ 11588c2ecf20Sopenharmony_ciconst char * const tomoyo_dif[TOMOYO_MAX_DOMAIN_INFO_FLAGS] = { 11598c2ecf20Sopenharmony_ci [TOMOYO_DIF_QUOTA_WARNED] = "quota_exceeded\n", 11608c2ecf20Sopenharmony_ci [TOMOYO_DIF_TRANSITION_FAILED] = "transition_failed\n", 11618c2ecf20Sopenharmony_ci}; 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci/** 11648c2ecf20Sopenharmony_ci * tomoyo_write_domain - Write domain policy. 11658c2ecf20Sopenharmony_ci * 11668c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 11678c2ecf20Sopenharmony_ci * 11688c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 11698c2ecf20Sopenharmony_ci * 11708c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 11718c2ecf20Sopenharmony_ci */ 11728c2ecf20Sopenharmony_cistatic int tomoyo_write_domain(struct tomoyo_io_buffer *head) 11738c2ecf20Sopenharmony_ci{ 11748c2ecf20Sopenharmony_ci char *data = head->write_buf; 11758c2ecf20Sopenharmony_ci struct tomoyo_policy_namespace *ns; 11768c2ecf20Sopenharmony_ci struct tomoyo_domain_info *domain = head->w.domain; 11778c2ecf20Sopenharmony_ci const bool is_delete = head->w.is_delete; 11788c2ecf20Sopenharmony_ci bool is_select = !is_delete && tomoyo_str_starts(&data, "select "); 11798c2ecf20Sopenharmony_ci unsigned int idx; 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci if (*data == '<') { 11828c2ecf20Sopenharmony_ci int ret = 0; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci domain = NULL; 11858c2ecf20Sopenharmony_ci if (is_delete) 11868c2ecf20Sopenharmony_ci ret = tomoyo_delete_domain(data); 11878c2ecf20Sopenharmony_ci else if (is_select) 11888c2ecf20Sopenharmony_ci domain = tomoyo_find_domain(data); 11898c2ecf20Sopenharmony_ci else 11908c2ecf20Sopenharmony_ci domain = tomoyo_assign_domain(data, false); 11918c2ecf20Sopenharmony_ci head->w.domain = domain; 11928c2ecf20Sopenharmony_ci return ret; 11938c2ecf20Sopenharmony_ci } 11948c2ecf20Sopenharmony_ci if (!domain) 11958c2ecf20Sopenharmony_ci return -EINVAL; 11968c2ecf20Sopenharmony_ci ns = domain->ns; 11978c2ecf20Sopenharmony_ci if (sscanf(data, "use_profile %u", &idx) == 1 11988c2ecf20Sopenharmony_ci && idx < TOMOYO_MAX_PROFILES) { 11998c2ecf20Sopenharmony_ci if (!tomoyo_policy_loaded || ns->profile_ptr[idx]) 12008c2ecf20Sopenharmony_ci if (!is_delete) 12018c2ecf20Sopenharmony_ci domain->profile = (u8) idx; 12028c2ecf20Sopenharmony_ci return 0; 12038c2ecf20Sopenharmony_ci } 12048c2ecf20Sopenharmony_ci if (sscanf(data, "use_group %u\n", &idx) == 1 12058c2ecf20Sopenharmony_ci && idx < TOMOYO_MAX_ACL_GROUPS) { 12068c2ecf20Sopenharmony_ci if (!is_delete) 12078c2ecf20Sopenharmony_ci set_bit(idx, domain->group); 12088c2ecf20Sopenharmony_ci else 12098c2ecf20Sopenharmony_ci clear_bit(idx, domain->group); 12108c2ecf20Sopenharmony_ci return 0; 12118c2ecf20Sopenharmony_ci } 12128c2ecf20Sopenharmony_ci for (idx = 0; idx < TOMOYO_MAX_DOMAIN_INFO_FLAGS; idx++) { 12138c2ecf20Sopenharmony_ci const char *cp = tomoyo_dif[idx]; 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci if (strncmp(data, cp, strlen(cp) - 1)) 12168c2ecf20Sopenharmony_ci continue; 12178c2ecf20Sopenharmony_ci domain->flags[idx] = !is_delete; 12188c2ecf20Sopenharmony_ci return 0; 12198c2ecf20Sopenharmony_ci } 12208c2ecf20Sopenharmony_ci return tomoyo_write_domain2(ns, &domain->acl_info_list, data, 12218c2ecf20Sopenharmony_ci is_delete); 12228c2ecf20Sopenharmony_ci} 12238c2ecf20Sopenharmony_ci 12248c2ecf20Sopenharmony_ci/** 12258c2ecf20Sopenharmony_ci * tomoyo_print_condition - Print condition part. 12268c2ecf20Sopenharmony_ci * 12278c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 12288c2ecf20Sopenharmony_ci * @cond: Pointer to "struct tomoyo_condition". 12298c2ecf20Sopenharmony_ci * 12308c2ecf20Sopenharmony_ci * Returns true on success, false otherwise. 12318c2ecf20Sopenharmony_ci */ 12328c2ecf20Sopenharmony_cistatic bool tomoyo_print_condition(struct tomoyo_io_buffer *head, 12338c2ecf20Sopenharmony_ci const struct tomoyo_condition *cond) 12348c2ecf20Sopenharmony_ci{ 12358c2ecf20Sopenharmony_ci switch (head->r.cond_step) { 12368c2ecf20Sopenharmony_ci case 0: 12378c2ecf20Sopenharmony_ci head->r.cond_index = 0; 12388c2ecf20Sopenharmony_ci head->r.cond_step++; 12398c2ecf20Sopenharmony_ci if (cond->transit) { 12408c2ecf20Sopenharmony_ci tomoyo_set_space(head); 12418c2ecf20Sopenharmony_ci tomoyo_set_string(head, cond->transit->name); 12428c2ecf20Sopenharmony_ci } 12438c2ecf20Sopenharmony_ci fallthrough; 12448c2ecf20Sopenharmony_ci case 1: 12458c2ecf20Sopenharmony_ci { 12468c2ecf20Sopenharmony_ci const u16 condc = cond->condc; 12478c2ecf20Sopenharmony_ci const struct tomoyo_condition_element *condp = 12488c2ecf20Sopenharmony_ci (typeof(condp)) (cond + 1); 12498c2ecf20Sopenharmony_ci const struct tomoyo_number_union *numbers_p = 12508c2ecf20Sopenharmony_ci (typeof(numbers_p)) (condp + condc); 12518c2ecf20Sopenharmony_ci const struct tomoyo_name_union *names_p = 12528c2ecf20Sopenharmony_ci (typeof(names_p)) 12538c2ecf20Sopenharmony_ci (numbers_p + cond->numbers_count); 12548c2ecf20Sopenharmony_ci const struct tomoyo_argv *argv = 12558c2ecf20Sopenharmony_ci (typeof(argv)) (names_p + cond->names_count); 12568c2ecf20Sopenharmony_ci const struct tomoyo_envp *envp = 12578c2ecf20Sopenharmony_ci (typeof(envp)) (argv + cond->argc); 12588c2ecf20Sopenharmony_ci u16 skip; 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_ci for (skip = 0; skip < head->r.cond_index; skip++) { 12618c2ecf20Sopenharmony_ci const u8 left = condp->left; 12628c2ecf20Sopenharmony_ci const u8 right = condp->right; 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci condp++; 12658c2ecf20Sopenharmony_ci switch (left) { 12668c2ecf20Sopenharmony_ci case TOMOYO_ARGV_ENTRY: 12678c2ecf20Sopenharmony_ci argv++; 12688c2ecf20Sopenharmony_ci continue; 12698c2ecf20Sopenharmony_ci case TOMOYO_ENVP_ENTRY: 12708c2ecf20Sopenharmony_ci envp++; 12718c2ecf20Sopenharmony_ci continue; 12728c2ecf20Sopenharmony_ci case TOMOYO_NUMBER_UNION: 12738c2ecf20Sopenharmony_ci numbers_p++; 12748c2ecf20Sopenharmony_ci break; 12758c2ecf20Sopenharmony_ci } 12768c2ecf20Sopenharmony_ci switch (right) { 12778c2ecf20Sopenharmony_ci case TOMOYO_NAME_UNION: 12788c2ecf20Sopenharmony_ci names_p++; 12798c2ecf20Sopenharmony_ci break; 12808c2ecf20Sopenharmony_ci case TOMOYO_NUMBER_UNION: 12818c2ecf20Sopenharmony_ci numbers_p++; 12828c2ecf20Sopenharmony_ci break; 12838c2ecf20Sopenharmony_ci } 12848c2ecf20Sopenharmony_ci } 12858c2ecf20Sopenharmony_ci while (head->r.cond_index < condc) { 12868c2ecf20Sopenharmony_ci const u8 match = condp->equals; 12878c2ecf20Sopenharmony_ci const u8 left = condp->left; 12888c2ecf20Sopenharmony_ci const u8 right = condp->right; 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci if (!tomoyo_flush(head)) 12918c2ecf20Sopenharmony_ci return false; 12928c2ecf20Sopenharmony_ci condp++; 12938c2ecf20Sopenharmony_ci head->r.cond_index++; 12948c2ecf20Sopenharmony_ci tomoyo_set_space(head); 12958c2ecf20Sopenharmony_ci switch (left) { 12968c2ecf20Sopenharmony_ci case TOMOYO_ARGV_ENTRY: 12978c2ecf20Sopenharmony_ci tomoyo_io_printf(head, 12988c2ecf20Sopenharmony_ci "exec.argv[%lu]%s=\"", 12998c2ecf20Sopenharmony_ci argv->index, argv->is_not ? "!" : ""); 13008c2ecf20Sopenharmony_ci tomoyo_set_string(head, 13018c2ecf20Sopenharmony_ci argv->value->name); 13028c2ecf20Sopenharmony_ci tomoyo_set_string(head, "\""); 13038c2ecf20Sopenharmony_ci argv++; 13048c2ecf20Sopenharmony_ci continue; 13058c2ecf20Sopenharmony_ci case TOMOYO_ENVP_ENTRY: 13068c2ecf20Sopenharmony_ci tomoyo_set_string(head, 13078c2ecf20Sopenharmony_ci "exec.envp[\""); 13088c2ecf20Sopenharmony_ci tomoyo_set_string(head, 13098c2ecf20Sopenharmony_ci envp->name->name); 13108c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "\"]%s=", envp->is_not ? "!" : ""); 13118c2ecf20Sopenharmony_ci if (envp->value) { 13128c2ecf20Sopenharmony_ci tomoyo_set_string(head, "\""); 13138c2ecf20Sopenharmony_ci tomoyo_set_string(head, envp->value->name); 13148c2ecf20Sopenharmony_ci tomoyo_set_string(head, "\""); 13158c2ecf20Sopenharmony_ci } else { 13168c2ecf20Sopenharmony_ci tomoyo_set_string(head, 13178c2ecf20Sopenharmony_ci "NULL"); 13188c2ecf20Sopenharmony_ci } 13198c2ecf20Sopenharmony_ci envp++; 13208c2ecf20Sopenharmony_ci continue; 13218c2ecf20Sopenharmony_ci case TOMOYO_NUMBER_UNION: 13228c2ecf20Sopenharmony_ci tomoyo_print_number_union_nospace 13238c2ecf20Sopenharmony_ci (head, numbers_p++); 13248c2ecf20Sopenharmony_ci break; 13258c2ecf20Sopenharmony_ci default: 13268c2ecf20Sopenharmony_ci tomoyo_set_string(head, 13278c2ecf20Sopenharmony_ci tomoyo_condition_keyword[left]); 13288c2ecf20Sopenharmony_ci break; 13298c2ecf20Sopenharmony_ci } 13308c2ecf20Sopenharmony_ci tomoyo_set_string(head, match ? "=" : "!="); 13318c2ecf20Sopenharmony_ci switch (right) { 13328c2ecf20Sopenharmony_ci case TOMOYO_NAME_UNION: 13338c2ecf20Sopenharmony_ci tomoyo_print_name_union_quoted 13348c2ecf20Sopenharmony_ci (head, names_p++); 13358c2ecf20Sopenharmony_ci break; 13368c2ecf20Sopenharmony_ci case TOMOYO_NUMBER_UNION: 13378c2ecf20Sopenharmony_ci tomoyo_print_number_union_nospace 13388c2ecf20Sopenharmony_ci (head, numbers_p++); 13398c2ecf20Sopenharmony_ci break; 13408c2ecf20Sopenharmony_ci default: 13418c2ecf20Sopenharmony_ci tomoyo_set_string(head, 13428c2ecf20Sopenharmony_ci tomoyo_condition_keyword[right]); 13438c2ecf20Sopenharmony_ci break; 13448c2ecf20Sopenharmony_ci } 13458c2ecf20Sopenharmony_ci } 13468c2ecf20Sopenharmony_ci } 13478c2ecf20Sopenharmony_ci head->r.cond_step++; 13488c2ecf20Sopenharmony_ci fallthrough; 13498c2ecf20Sopenharmony_ci case 2: 13508c2ecf20Sopenharmony_ci if (!tomoyo_flush(head)) 13518c2ecf20Sopenharmony_ci break; 13528c2ecf20Sopenharmony_ci head->r.cond_step++; 13538c2ecf20Sopenharmony_ci fallthrough; 13548c2ecf20Sopenharmony_ci case 3: 13558c2ecf20Sopenharmony_ci if (cond->grant_log != TOMOYO_GRANTLOG_AUTO) 13568c2ecf20Sopenharmony_ci tomoyo_io_printf(head, " grant_log=%s", 13578c2ecf20Sopenharmony_ci tomoyo_yesno(cond->grant_log == 13588c2ecf20Sopenharmony_ci TOMOYO_GRANTLOG_YES)); 13598c2ecf20Sopenharmony_ci tomoyo_set_lf(head); 13608c2ecf20Sopenharmony_ci return true; 13618c2ecf20Sopenharmony_ci } 13628c2ecf20Sopenharmony_ci return false; 13638c2ecf20Sopenharmony_ci} 13648c2ecf20Sopenharmony_ci 13658c2ecf20Sopenharmony_ci/** 13668c2ecf20Sopenharmony_ci * tomoyo_set_group - Print "acl_group " header keyword and category name. 13678c2ecf20Sopenharmony_ci * 13688c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 13698c2ecf20Sopenharmony_ci * @category: Category name. 13708c2ecf20Sopenharmony_ci * 13718c2ecf20Sopenharmony_ci * Returns nothing. 13728c2ecf20Sopenharmony_ci */ 13738c2ecf20Sopenharmony_cistatic void tomoyo_set_group(struct tomoyo_io_buffer *head, 13748c2ecf20Sopenharmony_ci const char *category) 13758c2ecf20Sopenharmony_ci{ 13768c2ecf20Sopenharmony_ci if (head->type == TOMOYO_EXCEPTIONPOLICY) { 13778c2ecf20Sopenharmony_ci tomoyo_print_namespace(head); 13788c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "acl_group %u ", 13798c2ecf20Sopenharmony_ci head->r.acl_group_index); 13808c2ecf20Sopenharmony_ci } 13818c2ecf20Sopenharmony_ci tomoyo_set_string(head, category); 13828c2ecf20Sopenharmony_ci} 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci/** 13858c2ecf20Sopenharmony_ci * tomoyo_print_entry - Print an ACL entry. 13868c2ecf20Sopenharmony_ci * 13878c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 13888c2ecf20Sopenharmony_ci * @acl: Pointer to an ACL entry. 13898c2ecf20Sopenharmony_ci * 13908c2ecf20Sopenharmony_ci * Returns true on success, false otherwise. 13918c2ecf20Sopenharmony_ci */ 13928c2ecf20Sopenharmony_cistatic bool tomoyo_print_entry(struct tomoyo_io_buffer *head, 13938c2ecf20Sopenharmony_ci struct tomoyo_acl_info *acl) 13948c2ecf20Sopenharmony_ci{ 13958c2ecf20Sopenharmony_ci const u8 acl_type = acl->type; 13968c2ecf20Sopenharmony_ci bool first = true; 13978c2ecf20Sopenharmony_ci u8 bit; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci if (head->r.print_cond_part) 14008c2ecf20Sopenharmony_ci goto print_cond_part; 14018c2ecf20Sopenharmony_ci if (acl->is_deleted) 14028c2ecf20Sopenharmony_ci return true; 14038c2ecf20Sopenharmony_ci if (!tomoyo_flush(head)) 14048c2ecf20Sopenharmony_ci return false; 14058c2ecf20Sopenharmony_ci else if (acl_type == TOMOYO_TYPE_PATH_ACL) { 14068c2ecf20Sopenharmony_ci struct tomoyo_path_acl *ptr = 14078c2ecf20Sopenharmony_ci container_of(acl, typeof(*ptr), head); 14088c2ecf20Sopenharmony_ci const u16 perm = ptr->perm; 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci for (bit = 0; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { 14118c2ecf20Sopenharmony_ci if (!(perm & (1 << bit))) 14128c2ecf20Sopenharmony_ci continue; 14138c2ecf20Sopenharmony_ci if (head->r.print_transition_related_only && 14148c2ecf20Sopenharmony_ci bit != TOMOYO_TYPE_EXECUTE) 14158c2ecf20Sopenharmony_ci continue; 14168c2ecf20Sopenharmony_ci if (first) { 14178c2ecf20Sopenharmony_ci tomoyo_set_group(head, "file "); 14188c2ecf20Sopenharmony_ci first = false; 14198c2ecf20Sopenharmony_ci } else { 14208c2ecf20Sopenharmony_ci tomoyo_set_slash(head); 14218c2ecf20Sopenharmony_ci } 14228c2ecf20Sopenharmony_ci tomoyo_set_string(head, tomoyo_path_keyword[bit]); 14238c2ecf20Sopenharmony_ci } 14248c2ecf20Sopenharmony_ci if (first) 14258c2ecf20Sopenharmony_ci return true; 14268c2ecf20Sopenharmony_ci tomoyo_print_name_union(head, &ptr->name); 14278c2ecf20Sopenharmony_ci } else if (acl_type == TOMOYO_TYPE_MANUAL_TASK_ACL) { 14288c2ecf20Sopenharmony_ci struct tomoyo_task_acl *ptr = 14298c2ecf20Sopenharmony_ci container_of(acl, typeof(*ptr), head); 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_ci tomoyo_set_group(head, "task "); 14328c2ecf20Sopenharmony_ci tomoyo_set_string(head, "manual_domain_transition "); 14338c2ecf20Sopenharmony_ci tomoyo_set_string(head, ptr->domainname->name); 14348c2ecf20Sopenharmony_ci } else if (head->r.print_transition_related_only) { 14358c2ecf20Sopenharmony_ci return true; 14368c2ecf20Sopenharmony_ci } else if (acl_type == TOMOYO_TYPE_PATH2_ACL) { 14378c2ecf20Sopenharmony_ci struct tomoyo_path2_acl *ptr = 14388c2ecf20Sopenharmony_ci container_of(acl, typeof(*ptr), head); 14398c2ecf20Sopenharmony_ci const u8 perm = ptr->perm; 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_ci for (bit = 0; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) { 14428c2ecf20Sopenharmony_ci if (!(perm & (1 << bit))) 14438c2ecf20Sopenharmony_ci continue; 14448c2ecf20Sopenharmony_ci if (first) { 14458c2ecf20Sopenharmony_ci tomoyo_set_group(head, "file "); 14468c2ecf20Sopenharmony_ci first = false; 14478c2ecf20Sopenharmony_ci } else { 14488c2ecf20Sopenharmony_ci tomoyo_set_slash(head); 14498c2ecf20Sopenharmony_ci } 14508c2ecf20Sopenharmony_ci tomoyo_set_string(head, tomoyo_mac_keywords 14518c2ecf20Sopenharmony_ci [tomoyo_pp2mac[bit]]); 14528c2ecf20Sopenharmony_ci } 14538c2ecf20Sopenharmony_ci if (first) 14548c2ecf20Sopenharmony_ci return true; 14558c2ecf20Sopenharmony_ci tomoyo_print_name_union(head, &ptr->name1); 14568c2ecf20Sopenharmony_ci tomoyo_print_name_union(head, &ptr->name2); 14578c2ecf20Sopenharmony_ci } else if (acl_type == TOMOYO_TYPE_PATH_NUMBER_ACL) { 14588c2ecf20Sopenharmony_ci struct tomoyo_path_number_acl *ptr = 14598c2ecf20Sopenharmony_ci container_of(acl, typeof(*ptr), head); 14608c2ecf20Sopenharmony_ci const u8 perm = ptr->perm; 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ci for (bit = 0; bit < TOMOYO_MAX_PATH_NUMBER_OPERATION; bit++) { 14638c2ecf20Sopenharmony_ci if (!(perm & (1 << bit))) 14648c2ecf20Sopenharmony_ci continue; 14658c2ecf20Sopenharmony_ci if (first) { 14668c2ecf20Sopenharmony_ci tomoyo_set_group(head, "file "); 14678c2ecf20Sopenharmony_ci first = false; 14688c2ecf20Sopenharmony_ci } else { 14698c2ecf20Sopenharmony_ci tomoyo_set_slash(head); 14708c2ecf20Sopenharmony_ci } 14718c2ecf20Sopenharmony_ci tomoyo_set_string(head, tomoyo_mac_keywords 14728c2ecf20Sopenharmony_ci [tomoyo_pn2mac[bit]]); 14738c2ecf20Sopenharmony_ci } 14748c2ecf20Sopenharmony_ci if (first) 14758c2ecf20Sopenharmony_ci return true; 14768c2ecf20Sopenharmony_ci tomoyo_print_name_union(head, &ptr->name); 14778c2ecf20Sopenharmony_ci tomoyo_print_number_union(head, &ptr->number); 14788c2ecf20Sopenharmony_ci } else if (acl_type == TOMOYO_TYPE_MKDEV_ACL) { 14798c2ecf20Sopenharmony_ci struct tomoyo_mkdev_acl *ptr = 14808c2ecf20Sopenharmony_ci container_of(acl, typeof(*ptr), head); 14818c2ecf20Sopenharmony_ci const u8 perm = ptr->perm; 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci for (bit = 0; bit < TOMOYO_MAX_MKDEV_OPERATION; bit++) { 14848c2ecf20Sopenharmony_ci if (!(perm & (1 << bit))) 14858c2ecf20Sopenharmony_ci continue; 14868c2ecf20Sopenharmony_ci if (first) { 14878c2ecf20Sopenharmony_ci tomoyo_set_group(head, "file "); 14888c2ecf20Sopenharmony_ci first = false; 14898c2ecf20Sopenharmony_ci } else { 14908c2ecf20Sopenharmony_ci tomoyo_set_slash(head); 14918c2ecf20Sopenharmony_ci } 14928c2ecf20Sopenharmony_ci tomoyo_set_string(head, tomoyo_mac_keywords 14938c2ecf20Sopenharmony_ci [tomoyo_pnnn2mac[bit]]); 14948c2ecf20Sopenharmony_ci } 14958c2ecf20Sopenharmony_ci if (first) 14968c2ecf20Sopenharmony_ci return true; 14978c2ecf20Sopenharmony_ci tomoyo_print_name_union(head, &ptr->name); 14988c2ecf20Sopenharmony_ci tomoyo_print_number_union(head, &ptr->mode); 14998c2ecf20Sopenharmony_ci tomoyo_print_number_union(head, &ptr->major); 15008c2ecf20Sopenharmony_ci tomoyo_print_number_union(head, &ptr->minor); 15018c2ecf20Sopenharmony_ci } else if (acl_type == TOMOYO_TYPE_INET_ACL) { 15028c2ecf20Sopenharmony_ci struct tomoyo_inet_acl *ptr = 15038c2ecf20Sopenharmony_ci container_of(acl, typeof(*ptr), head); 15048c2ecf20Sopenharmony_ci const u8 perm = ptr->perm; 15058c2ecf20Sopenharmony_ci 15068c2ecf20Sopenharmony_ci for (bit = 0; bit < TOMOYO_MAX_NETWORK_OPERATION; bit++) { 15078c2ecf20Sopenharmony_ci if (!(perm & (1 << bit))) 15088c2ecf20Sopenharmony_ci continue; 15098c2ecf20Sopenharmony_ci if (first) { 15108c2ecf20Sopenharmony_ci tomoyo_set_group(head, "network inet "); 15118c2ecf20Sopenharmony_ci tomoyo_set_string(head, tomoyo_proto_keyword 15128c2ecf20Sopenharmony_ci [ptr->protocol]); 15138c2ecf20Sopenharmony_ci tomoyo_set_space(head); 15148c2ecf20Sopenharmony_ci first = false; 15158c2ecf20Sopenharmony_ci } else { 15168c2ecf20Sopenharmony_ci tomoyo_set_slash(head); 15178c2ecf20Sopenharmony_ci } 15188c2ecf20Sopenharmony_ci tomoyo_set_string(head, tomoyo_socket_keyword[bit]); 15198c2ecf20Sopenharmony_ci } 15208c2ecf20Sopenharmony_ci if (first) 15218c2ecf20Sopenharmony_ci return true; 15228c2ecf20Sopenharmony_ci tomoyo_set_space(head); 15238c2ecf20Sopenharmony_ci if (ptr->address.group) { 15248c2ecf20Sopenharmony_ci tomoyo_set_string(head, "@"); 15258c2ecf20Sopenharmony_ci tomoyo_set_string(head, ptr->address.group->group_name 15268c2ecf20Sopenharmony_ci ->name); 15278c2ecf20Sopenharmony_ci } else { 15288c2ecf20Sopenharmony_ci char buf[128]; 15298c2ecf20Sopenharmony_ci 15308c2ecf20Sopenharmony_ci tomoyo_print_ip(buf, sizeof(buf), &ptr->address); 15318c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "%s", buf); 15328c2ecf20Sopenharmony_ci } 15338c2ecf20Sopenharmony_ci tomoyo_print_number_union(head, &ptr->port); 15348c2ecf20Sopenharmony_ci } else if (acl_type == TOMOYO_TYPE_UNIX_ACL) { 15358c2ecf20Sopenharmony_ci struct tomoyo_unix_acl *ptr = 15368c2ecf20Sopenharmony_ci container_of(acl, typeof(*ptr), head); 15378c2ecf20Sopenharmony_ci const u8 perm = ptr->perm; 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci for (bit = 0; bit < TOMOYO_MAX_NETWORK_OPERATION; bit++) { 15408c2ecf20Sopenharmony_ci if (!(perm & (1 << bit))) 15418c2ecf20Sopenharmony_ci continue; 15428c2ecf20Sopenharmony_ci if (first) { 15438c2ecf20Sopenharmony_ci tomoyo_set_group(head, "network unix "); 15448c2ecf20Sopenharmony_ci tomoyo_set_string(head, tomoyo_proto_keyword 15458c2ecf20Sopenharmony_ci [ptr->protocol]); 15468c2ecf20Sopenharmony_ci tomoyo_set_space(head); 15478c2ecf20Sopenharmony_ci first = false; 15488c2ecf20Sopenharmony_ci } else { 15498c2ecf20Sopenharmony_ci tomoyo_set_slash(head); 15508c2ecf20Sopenharmony_ci } 15518c2ecf20Sopenharmony_ci tomoyo_set_string(head, tomoyo_socket_keyword[bit]); 15528c2ecf20Sopenharmony_ci } 15538c2ecf20Sopenharmony_ci if (first) 15548c2ecf20Sopenharmony_ci return true; 15558c2ecf20Sopenharmony_ci tomoyo_print_name_union(head, &ptr->name); 15568c2ecf20Sopenharmony_ci } else if (acl_type == TOMOYO_TYPE_MOUNT_ACL) { 15578c2ecf20Sopenharmony_ci struct tomoyo_mount_acl *ptr = 15588c2ecf20Sopenharmony_ci container_of(acl, typeof(*ptr), head); 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci tomoyo_set_group(head, "file mount"); 15618c2ecf20Sopenharmony_ci tomoyo_print_name_union(head, &ptr->dev_name); 15628c2ecf20Sopenharmony_ci tomoyo_print_name_union(head, &ptr->dir_name); 15638c2ecf20Sopenharmony_ci tomoyo_print_name_union(head, &ptr->fs_type); 15648c2ecf20Sopenharmony_ci tomoyo_print_number_union(head, &ptr->flags); 15658c2ecf20Sopenharmony_ci } else if (acl_type == TOMOYO_TYPE_ENV_ACL) { 15668c2ecf20Sopenharmony_ci struct tomoyo_env_acl *ptr = 15678c2ecf20Sopenharmony_ci container_of(acl, typeof(*ptr), head); 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_ci tomoyo_set_group(head, "misc env "); 15708c2ecf20Sopenharmony_ci tomoyo_set_string(head, ptr->env->name); 15718c2ecf20Sopenharmony_ci } 15728c2ecf20Sopenharmony_ci if (acl->cond) { 15738c2ecf20Sopenharmony_ci head->r.print_cond_part = true; 15748c2ecf20Sopenharmony_ci head->r.cond_step = 0; 15758c2ecf20Sopenharmony_ci if (!tomoyo_flush(head)) 15768c2ecf20Sopenharmony_ci return false; 15778c2ecf20Sopenharmony_ciprint_cond_part: 15788c2ecf20Sopenharmony_ci if (!tomoyo_print_condition(head, acl->cond)) 15798c2ecf20Sopenharmony_ci return false; 15808c2ecf20Sopenharmony_ci head->r.print_cond_part = false; 15818c2ecf20Sopenharmony_ci } else { 15828c2ecf20Sopenharmony_ci tomoyo_set_lf(head); 15838c2ecf20Sopenharmony_ci } 15848c2ecf20Sopenharmony_ci return true; 15858c2ecf20Sopenharmony_ci} 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci/** 15888c2ecf20Sopenharmony_ci * tomoyo_read_domain2 - Read domain policy. 15898c2ecf20Sopenharmony_ci * 15908c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 15918c2ecf20Sopenharmony_ci * @list: Pointer to "struct list_head". 15928c2ecf20Sopenharmony_ci * 15938c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 15948c2ecf20Sopenharmony_ci * 15958c2ecf20Sopenharmony_ci * Returns true on success, false otherwise. 15968c2ecf20Sopenharmony_ci */ 15978c2ecf20Sopenharmony_cistatic bool tomoyo_read_domain2(struct tomoyo_io_buffer *head, 15988c2ecf20Sopenharmony_ci struct list_head *list) 15998c2ecf20Sopenharmony_ci{ 16008c2ecf20Sopenharmony_ci list_for_each_cookie(head->r.acl, list) { 16018c2ecf20Sopenharmony_ci struct tomoyo_acl_info *ptr = 16028c2ecf20Sopenharmony_ci list_entry(head->r.acl, typeof(*ptr), list); 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci if (!tomoyo_print_entry(head, ptr)) 16058c2ecf20Sopenharmony_ci return false; 16068c2ecf20Sopenharmony_ci } 16078c2ecf20Sopenharmony_ci head->r.acl = NULL; 16088c2ecf20Sopenharmony_ci return true; 16098c2ecf20Sopenharmony_ci} 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_ci/** 16128c2ecf20Sopenharmony_ci * tomoyo_read_domain - Read domain policy. 16138c2ecf20Sopenharmony_ci * 16148c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 16158c2ecf20Sopenharmony_ci * 16168c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 16178c2ecf20Sopenharmony_ci */ 16188c2ecf20Sopenharmony_cistatic void tomoyo_read_domain(struct tomoyo_io_buffer *head) 16198c2ecf20Sopenharmony_ci{ 16208c2ecf20Sopenharmony_ci if (head->r.eof) 16218c2ecf20Sopenharmony_ci return; 16228c2ecf20Sopenharmony_ci list_for_each_cookie(head->r.domain, &tomoyo_domain_list) { 16238c2ecf20Sopenharmony_ci struct tomoyo_domain_info *domain = 16248c2ecf20Sopenharmony_ci list_entry(head->r.domain, typeof(*domain), list); 16258c2ecf20Sopenharmony_ci u8 i; 16268c2ecf20Sopenharmony_ci 16278c2ecf20Sopenharmony_ci switch (head->r.step) { 16288c2ecf20Sopenharmony_ci case 0: 16298c2ecf20Sopenharmony_ci if (domain->is_deleted && 16308c2ecf20Sopenharmony_ci !head->r.print_this_domain_only) 16318c2ecf20Sopenharmony_ci continue; 16328c2ecf20Sopenharmony_ci /* Print domainname and flags. */ 16338c2ecf20Sopenharmony_ci tomoyo_set_string(head, domain->domainname->name); 16348c2ecf20Sopenharmony_ci tomoyo_set_lf(head); 16358c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "use_profile %u\n", 16368c2ecf20Sopenharmony_ci domain->profile); 16378c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_DOMAIN_INFO_FLAGS; i++) 16388c2ecf20Sopenharmony_ci if (domain->flags[i]) 16398c2ecf20Sopenharmony_ci tomoyo_set_string(head, tomoyo_dif[i]); 16408c2ecf20Sopenharmony_ci head->r.index = 0; 16418c2ecf20Sopenharmony_ci head->r.step++; 16428c2ecf20Sopenharmony_ci fallthrough; 16438c2ecf20Sopenharmony_ci case 1: 16448c2ecf20Sopenharmony_ci while (head->r.index < TOMOYO_MAX_ACL_GROUPS) { 16458c2ecf20Sopenharmony_ci i = head->r.index++; 16468c2ecf20Sopenharmony_ci if (!test_bit(i, domain->group)) 16478c2ecf20Sopenharmony_ci continue; 16488c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "use_group %u\n", i); 16498c2ecf20Sopenharmony_ci if (!tomoyo_flush(head)) 16508c2ecf20Sopenharmony_ci return; 16518c2ecf20Sopenharmony_ci } 16528c2ecf20Sopenharmony_ci head->r.index = 0; 16538c2ecf20Sopenharmony_ci head->r.step++; 16548c2ecf20Sopenharmony_ci tomoyo_set_lf(head); 16558c2ecf20Sopenharmony_ci fallthrough; 16568c2ecf20Sopenharmony_ci case 2: 16578c2ecf20Sopenharmony_ci if (!tomoyo_read_domain2(head, &domain->acl_info_list)) 16588c2ecf20Sopenharmony_ci return; 16598c2ecf20Sopenharmony_ci head->r.step++; 16608c2ecf20Sopenharmony_ci if (!tomoyo_set_lf(head)) 16618c2ecf20Sopenharmony_ci return; 16628c2ecf20Sopenharmony_ci fallthrough; 16638c2ecf20Sopenharmony_ci case 3: 16648c2ecf20Sopenharmony_ci head->r.step = 0; 16658c2ecf20Sopenharmony_ci if (head->r.print_this_domain_only) 16668c2ecf20Sopenharmony_ci goto done; 16678c2ecf20Sopenharmony_ci } 16688c2ecf20Sopenharmony_ci } 16698c2ecf20Sopenharmony_ci done: 16708c2ecf20Sopenharmony_ci head->r.eof = true; 16718c2ecf20Sopenharmony_ci} 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_ci/** 16748c2ecf20Sopenharmony_ci * tomoyo_write_pid: Specify PID to obtain domainname. 16758c2ecf20Sopenharmony_ci * 16768c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 16778c2ecf20Sopenharmony_ci * 16788c2ecf20Sopenharmony_ci * Returns 0. 16798c2ecf20Sopenharmony_ci */ 16808c2ecf20Sopenharmony_cistatic int tomoyo_write_pid(struct tomoyo_io_buffer *head) 16818c2ecf20Sopenharmony_ci{ 16828c2ecf20Sopenharmony_ci head->r.eof = false; 16838c2ecf20Sopenharmony_ci return 0; 16848c2ecf20Sopenharmony_ci} 16858c2ecf20Sopenharmony_ci 16868c2ecf20Sopenharmony_ci/** 16878c2ecf20Sopenharmony_ci * tomoyo_read_pid - Get domainname of the specified PID. 16888c2ecf20Sopenharmony_ci * 16898c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 16908c2ecf20Sopenharmony_ci * 16918c2ecf20Sopenharmony_ci * Returns the domainname which the specified PID is in on success, 16928c2ecf20Sopenharmony_ci * empty string otherwise. 16938c2ecf20Sopenharmony_ci * The PID is specified by tomoyo_write_pid() so that the user can obtain 16948c2ecf20Sopenharmony_ci * using read()/write() interface rather than sysctl() interface. 16958c2ecf20Sopenharmony_ci */ 16968c2ecf20Sopenharmony_cistatic void tomoyo_read_pid(struct tomoyo_io_buffer *head) 16978c2ecf20Sopenharmony_ci{ 16988c2ecf20Sopenharmony_ci char *buf = head->write_buf; 16998c2ecf20Sopenharmony_ci bool global_pid = false; 17008c2ecf20Sopenharmony_ci unsigned int pid; 17018c2ecf20Sopenharmony_ci struct task_struct *p; 17028c2ecf20Sopenharmony_ci struct tomoyo_domain_info *domain = NULL; 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci /* Accessing write_buf is safe because head->io_sem is held. */ 17058c2ecf20Sopenharmony_ci if (!buf) { 17068c2ecf20Sopenharmony_ci head->r.eof = true; 17078c2ecf20Sopenharmony_ci return; /* Do nothing if open(O_RDONLY). */ 17088c2ecf20Sopenharmony_ci } 17098c2ecf20Sopenharmony_ci if (head->r.w_pos || head->r.eof) 17108c2ecf20Sopenharmony_ci return; 17118c2ecf20Sopenharmony_ci head->r.eof = true; 17128c2ecf20Sopenharmony_ci if (tomoyo_str_starts(&buf, "global-pid ")) 17138c2ecf20Sopenharmony_ci global_pid = true; 17148c2ecf20Sopenharmony_ci if (kstrtouint(buf, 10, &pid)) 17158c2ecf20Sopenharmony_ci return; 17168c2ecf20Sopenharmony_ci rcu_read_lock(); 17178c2ecf20Sopenharmony_ci if (global_pid) 17188c2ecf20Sopenharmony_ci p = find_task_by_pid_ns(pid, &init_pid_ns); 17198c2ecf20Sopenharmony_ci else 17208c2ecf20Sopenharmony_ci p = find_task_by_vpid(pid); 17218c2ecf20Sopenharmony_ci if (p) 17228c2ecf20Sopenharmony_ci domain = tomoyo_task(p)->domain_info; 17238c2ecf20Sopenharmony_ci rcu_read_unlock(); 17248c2ecf20Sopenharmony_ci if (!domain) 17258c2ecf20Sopenharmony_ci return; 17268c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "%u %u ", pid, domain->profile); 17278c2ecf20Sopenharmony_ci tomoyo_set_string(head, domain->domainname->name); 17288c2ecf20Sopenharmony_ci} 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_ci/* String table for domain transition control keywords. */ 17318c2ecf20Sopenharmony_cistatic const char *tomoyo_transition_type[TOMOYO_MAX_TRANSITION_TYPE] = { 17328c2ecf20Sopenharmony_ci [TOMOYO_TRANSITION_CONTROL_NO_RESET] = "no_reset_domain ", 17338c2ecf20Sopenharmony_ci [TOMOYO_TRANSITION_CONTROL_RESET] = "reset_domain ", 17348c2ecf20Sopenharmony_ci [TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ", 17358c2ecf20Sopenharmony_ci [TOMOYO_TRANSITION_CONTROL_INITIALIZE] = "initialize_domain ", 17368c2ecf20Sopenharmony_ci [TOMOYO_TRANSITION_CONTROL_NO_KEEP] = "no_keep_domain ", 17378c2ecf20Sopenharmony_ci [TOMOYO_TRANSITION_CONTROL_KEEP] = "keep_domain ", 17388c2ecf20Sopenharmony_ci}; 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci/* String table for grouping keywords. */ 17418c2ecf20Sopenharmony_cistatic const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = { 17428c2ecf20Sopenharmony_ci [TOMOYO_PATH_GROUP] = "path_group ", 17438c2ecf20Sopenharmony_ci [TOMOYO_NUMBER_GROUP] = "number_group ", 17448c2ecf20Sopenharmony_ci [TOMOYO_ADDRESS_GROUP] = "address_group ", 17458c2ecf20Sopenharmony_ci}; 17468c2ecf20Sopenharmony_ci 17478c2ecf20Sopenharmony_ci/** 17488c2ecf20Sopenharmony_ci * tomoyo_write_exception - Write exception policy. 17498c2ecf20Sopenharmony_ci * 17508c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 17518c2ecf20Sopenharmony_ci * 17528c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 17538c2ecf20Sopenharmony_ci * 17548c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 17558c2ecf20Sopenharmony_ci */ 17568c2ecf20Sopenharmony_cistatic int tomoyo_write_exception(struct tomoyo_io_buffer *head) 17578c2ecf20Sopenharmony_ci{ 17588c2ecf20Sopenharmony_ci const bool is_delete = head->w.is_delete; 17598c2ecf20Sopenharmony_ci struct tomoyo_acl_param param = { 17608c2ecf20Sopenharmony_ci .ns = head->w.ns, 17618c2ecf20Sopenharmony_ci .is_delete = is_delete, 17628c2ecf20Sopenharmony_ci .data = head->write_buf, 17638c2ecf20Sopenharmony_ci }; 17648c2ecf20Sopenharmony_ci u8 i; 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci if (tomoyo_str_starts(¶m.data, "aggregator ")) 17678c2ecf20Sopenharmony_ci return tomoyo_write_aggregator(¶m); 17688c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) 17698c2ecf20Sopenharmony_ci if (tomoyo_str_starts(¶m.data, tomoyo_transition_type[i])) 17708c2ecf20Sopenharmony_ci return tomoyo_write_transition_control(¶m, i); 17718c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_GROUP; i++) 17728c2ecf20Sopenharmony_ci if (tomoyo_str_starts(¶m.data, tomoyo_group_name[i])) 17738c2ecf20Sopenharmony_ci return tomoyo_write_group(¶m, i); 17748c2ecf20Sopenharmony_ci if (tomoyo_str_starts(¶m.data, "acl_group ")) { 17758c2ecf20Sopenharmony_ci unsigned int group; 17768c2ecf20Sopenharmony_ci char *data; 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_ci group = simple_strtoul(param.data, &data, 10); 17798c2ecf20Sopenharmony_ci if (group < TOMOYO_MAX_ACL_GROUPS && *data++ == ' ') 17808c2ecf20Sopenharmony_ci return tomoyo_write_domain2 17818c2ecf20Sopenharmony_ci (head->w.ns, &head->w.ns->acl_group[group], 17828c2ecf20Sopenharmony_ci data, is_delete); 17838c2ecf20Sopenharmony_ci } 17848c2ecf20Sopenharmony_ci return -EINVAL; 17858c2ecf20Sopenharmony_ci} 17868c2ecf20Sopenharmony_ci 17878c2ecf20Sopenharmony_ci/** 17888c2ecf20Sopenharmony_ci * tomoyo_read_group - Read "struct tomoyo_path_group"/"struct tomoyo_number_group"/"struct tomoyo_address_group" list. 17898c2ecf20Sopenharmony_ci * 17908c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 17918c2ecf20Sopenharmony_ci * @idx: Index number. 17928c2ecf20Sopenharmony_ci * 17938c2ecf20Sopenharmony_ci * Returns true on success, false otherwise. 17948c2ecf20Sopenharmony_ci * 17958c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 17968c2ecf20Sopenharmony_ci */ 17978c2ecf20Sopenharmony_cistatic bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx) 17988c2ecf20Sopenharmony_ci{ 17998c2ecf20Sopenharmony_ci struct tomoyo_policy_namespace *ns = 18008c2ecf20Sopenharmony_ci container_of(head->r.ns, typeof(*ns), namespace_list); 18018c2ecf20Sopenharmony_ci struct list_head *list = &ns->group_list[idx]; 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci list_for_each_cookie(head->r.group, list) { 18048c2ecf20Sopenharmony_ci struct tomoyo_group *group = 18058c2ecf20Sopenharmony_ci list_entry(head->r.group, typeof(*group), head.list); 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci list_for_each_cookie(head->r.acl, &group->member_list) { 18088c2ecf20Sopenharmony_ci struct tomoyo_acl_head *ptr = 18098c2ecf20Sopenharmony_ci list_entry(head->r.acl, typeof(*ptr), list); 18108c2ecf20Sopenharmony_ci 18118c2ecf20Sopenharmony_ci if (ptr->is_deleted) 18128c2ecf20Sopenharmony_ci continue; 18138c2ecf20Sopenharmony_ci if (!tomoyo_flush(head)) 18148c2ecf20Sopenharmony_ci return false; 18158c2ecf20Sopenharmony_ci tomoyo_print_namespace(head); 18168c2ecf20Sopenharmony_ci tomoyo_set_string(head, tomoyo_group_name[idx]); 18178c2ecf20Sopenharmony_ci tomoyo_set_string(head, group->group_name->name); 18188c2ecf20Sopenharmony_ci if (idx == TOMOYO_PATH_GROUP) { 18198c2ecf20Sopenharmony_ci tomoyo_set_space(head); 18208c2ecf20Sopenharmony_ci tomoyo_set_string(head, container_of 18218c2ecf20Sopenharmony_ci (ptr, struct tomoyo_path_group, 18228c2ecf20Sopenharmony_ci head)->member_name->name); 18238c2ecf20Sopenharmony_ci } else if (idx == TOMOYO_NUMBER_GROUP) { 18248c2ecf20Sopenharmony_ci tomoyo_print_number_union(head, &container_of 18258c2ecf20Sopenharmony_ci (ptr, 18268c2ecf20Sopenharmony_ci struct tomoyo_number_group, 18278c2ecf20Sopenharmony_ci head)->number); 18288c2ecf20Sopenharmony_ci } else if (idx == TOMOYO_ADDRESS_GROUP) { 18298c2ecf20Sopenharmony_ci char buffer[128]; 18308c2ecf20Sopenharmony_ci struct tomoyo_address_group *member = 18318c2ecf20Sopenharmony_ci container_of(ptr, typeof(*member), 18328c2ecf20Sopenharmony_ci head); 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_ci tomoyo_print_ip(buffer, sizeof(buffer), 18358c2ecf20Sopenharmony_ci &member->address); 18368c2ecf20Sopenharmony_ci tomoyo_io_printf(head, " %s", buffer); 18378c2ecf20Sopenharmony_ci } 18388c2ecf20Sopenharmony_ci tomoyo_set_lf(head); 18398c2ecf20Sopenharmony_ci } 18408c2ecf20Sopenharmony_ci head->r.acl = NULL; 18418c2ecf20Sopenharmony_ci } 18428c2ecf20Sopenharmony_ci head->r.group = NULL; 18438c2ecf20Sopenharmony_ci return true; 18448c2ecf20Sopenharmony_ci} 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci/** 18478c2ecf20Sopenharmony_ci * tomoyo_read_policy - Read "struct tomoyo_..._entry" list. 18488c2ecf20Sopenharmony_ci * 18498c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 18508c2ecf20Sopenharmony_ci * @idx: Index number. 18518c2ecf20Sopenharmony_ci * 18528c2ecf20Sopenharmony_ci * Returns true on success, false otherwise. 18538c2ecf20Sopenharmony_ci * 18548c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 18558c2ecf20Sopenharmony_ci */ 18568c2ecf20Sopenharmony_cistatic bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) 18578c2ecf20Sopenharmony_ci{ 18588c2ecf20Sopenharmony_ci struct tomoyo_policy_namespace *ns = 18598c2ecf20Sopenharmony_ci container_of(head->r.ns, typeof(*ns), namespace_list); 18608c2ecf20Sopenharmony_ci struct list_head *list = &ns->policy_list[idx]; 18618c2ecf20Sopenharmony_ci 18628c2ecf20Sopenharmony_ci list_for_each_cookie(head->r.acl, list) { 18638c2ecf20Sopenharmony_ci struct tomoyo_acl_head *acl = 18648c2ecf20Sopenharmony_ci container_of(head->r.acl, typeof(*acl), list); 18658c2ecf20Sopenharmony_ci if (acl->is_deleted) 18668c2ecf20Sopenharmony_ci continue; 18678c2ecf20Sopenharmony_ci if (!tomoyo_flush(head)) 18688c2ecf20Sopenharmony_ci return false; 18698c2ecf20Sopenharmony_ci switch (idx) { 18708c2ecf20Sopenharmony_ci case TOMOYO_ID_TRANSITION_CONTROL: 18718c2ecf20Sopenharmony_ci { 18728c2ecf20Sopenharmony_ci struct tomoyo_transition_control *ptr = 18738c2ecf20Sopenharmony_ci container_of(acl, typeof(*ptr), head); 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ci tomoyo_print_namespace(head); 18768c2ecf20Sopenharmony_ci tomoyo_set_string(head, tomoyo_transition_type 18778c2ecf20Sopenharmony_ci [ptr->type]); 18788c2ecf20Sopenharmony_ci tomoyo_set_string(head, ptr->program ? 18798c2ecf20Sopenharmony_ci ptr->program->name : "any"); 18808c2ecf20Sopenharmony_ci tomoyo_set_string(head, " from "); 18818c2ecf20Sopenharmony_ci tomoyo_set_string(head, ptr->domainname ? 18828c2ecf20Sopenharmony_ci ptr->domainname->name : 18838c2ecf20Sopenharmony_ci "any"); 18848c2ecf20Sopenharmony_ci } 18858c2ecf20Sopenharmony_ci break; 18868c2ecf20Sopenharmony_ci case TOMOYO_ID_AGGREGATOR: 18878c2ecf20Sopenharmony_ci { 18888c2ecf20Sopenharmony_ci struct tomoyo_aggregator *ptr = 18898c2ecf20Sopenharmony_ci container_of(acl, typeof(*ptr), head); 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci tomoyo_print_namespace(head); 18928c2ecf20Sopenharmony_ci tomoyo_set_string(head, "aggregator "); 18938c2ecf20Sopenharmony_ci tomoyo_set_string(head, 18948c2ecf20Sopenharmony_ci ptr->original_name->name); 18958c2ecf20Sopenharmony_ci tomoyo_set_space(head); 18968c2ecf20Sopenharmony_ci tomoyo_set_string(head, 18978c2ecf20Sopenharmony_ci ptr->aggregated_name->name); 18988c2ecf20Sopenharmony_ci } 18998c2ecf20Sopenharmony_ci break; 19008c2ecf20Sopenharmony_ci default: 19018c2ecf20Sopenharmony_ci continue; 19028c2ecf20Sopenharmony_ci } 19038c2ecf20Sopenharmony_ci tomoyo_set_lf(head); 19048c2ecf20Sopenharmony_ci } 19058c2ecf20Sopenharmony_ci head->r.acl = NULL; 19068c2ecf20Sopenharmony_ci return true; 19078c2ecf20Sopenharmony_ci} 19088c2ecf20Sopenharmony_ci 19098c2ecf20Sopenharmony_ci/** 19108c2ecf20Sopenharmony_ci * tomoyo_read_exception - Read exception policy. 19118c2ecf20Sopenharmony_ci * 19128c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 19138c2ecf20Sopenharmony_ci * 19148c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 19158c2ecf20Sopenharmony_ci */ 19168c2ecf20Sopenharmony_cistatic void tomoyo_read_exception(struct tomoyo_io_buffer *head) 19178c2ecf20Sopenharmony_ci{ 19188c2ecf20Sopenharmony_ci struct tomoyo_policy_namespace *ns = 19198c2ecf20Sopenharmony_ci container_of(head->r.ns, typeof(*ns), namespace_list); 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_ci if (head->r.eof) 19228c2ecf20Sopenharmony_ci return; 19238c2ecf20Sopenharmony_ci while (head->r.step < TOMOYO_MAX_POLICY && 19248c2ecf20Sopenharmony_ci tomoyo_read_policy(head, head->r.step)) 19258c2ecf20Sopenharmony_ci head->r.step++; 19268c2ecf20Sopenharmony_ci if (head->r.step < TOMOYO_MAX_POLICY) 19278c2ecf20Sopenharmony_ci return; 19288c2ecf20Sopenharmony_ci while (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP && 19298c2ecf20Sopenharmony_ci tomoyo_read_group(head, head->r.step - TOMOYO_MAX_POLICY)) 19308c2ecf20Sopenharmony_ci head->r.step++; 19318c2ecf20Sopenharmony_ci if (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP) 19328c2ecf20Sopenharmony_ci return; 19338c2ecf20Sopenharmony_ci while (head->r.step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP 19348c2ecf20Sopenharmony_ci + TOMOYO_MAX_ACL_GROUPS) { 19358c2ecf20Sopenharmony_ci head->r.acl_group_index = head->r.step - TOMOYO_MAX_POLICY 19368c2ecf20Sopenharmony_ci - TOMOYO_MAX_GROUP; 19378c2ecf20Sopenharmony_ci if (!tomoyo_read_domain2(head, &ns->acl_group 19388c2ecf20Sopenharmony_ci [head->r.acl_group_index])) 19398c2ecf20Sopenharmony_ci return; 19408c2ecf20Sopenharmony_ci head->r.step++; 19418c2ecf20Sopenharmony_ci } 19428c2ecf20Sopenharmony_ci head->r.eof = true; 19438c2ecf20Sopenharmony_ci} 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_ci/* Wait queue for kernel -> userspace notification. */ 19468c2ecf20Sopenharmony_cistatic DECLARE_WAIT_QUEUE_HEAD(tomoyo_query_wait); 19478c2ecf20Sopenharmony_ci/* Wait queue for userspace -> kernel notification. */ 19488c2ecf20Sopenharmony_cistatic DECLARE_WAIT_QUEUE_HEAD(tomoyo_answer_wait); 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_ci/* Structure for query. */ 19518c2ecf20Sopenharmony_cistruct tomoyo_query { 19528c2ecf20Sopenharmony_ci struct list_head list; 19538c2ecf20Sopenharmony_ci struct tomoyo_domain_info *domain; 19548c2ecf20Sopenharmony_ci char *query; 19558c2ecf20Sopenharmony_ci size_t query_len; 19568c2ecf20Sopenharmony_ci unsigned int serial; 19578c2ecf20Sopenharmony_ci u8 timer; 19588c2ecf20Sopenharmony_ci u8 answer; 19598c2ecf20Sopenharmony_ci u8 retry; 19608c2ecf20Sopenharmony_ci}; 19618c2ecf20Sopenharmony_ci 19628c2ecf20Sopenharmony_ci/* The list for "struct tomoyo_query". */ 19638c2ecf20Sopenharmony_cistatic LIST_HEAD(tomoyo_query_list); 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci/* Lock for manipulating tomoyo_query_list. */ 19668c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(tomoyo_query_list_lock); 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_ci/* 19698c2ecf20Sopenharmony_ci * Number of "struct file" referring /sys/kernel/security/tomoyo/query 19708c2ecf20Sopenharmony_ci * interface. 19718c2ecf20Sopenharmony_ci */ 19728c2ecf20Sopenharmony_cistatic atomic_t tomoyo_query_observers = ATOMIC_INIT(0); 19738c2ecf20Sopenharmony_ci 19748c2ecf20Sopenharmony_ci/** 19758c2ecf20Sopenharmony_ci * tomoyo_truncate - Truncate a line. 19768c2ecf20Sopenharmony_ci * 19778c2ecf20Sopenharmony_ci * @str: String to truncate. 19788c2ecf20Sopenharmony_ci * 19798c2ecf20Sopenharmony_ci * Returns length of truncated @str. 19808c2ecf20Sopenharmony_ci */ 19818c2ecf20Sopenharmony_cistatic int tomoyo_truncate(char *str) 19828c2ecf20Sopenharmony_ci{ 19838c2ecf20Sopenharmony_ci char *start = str; 19848c2ecf20Sopenharmony_ci 19858c2ecf20Sopenharmony_ci while (*(unsigned char *) str > (unsigned char) ' ') 19868c2ecf20Sopenharmony_ci str++; 19878c2ecf20Sopenharmony_ci *str = '\0'; 19888c2ecf20Sopenharmony_ci return strlen(start) + 1; 19898c2ecf20Sopenharmony_ci} 19908c2ecf20Sopenharmony_ci 19918c2ecf20Sopenharmony_ci/** 19928c2ecf20Sopenharmony_ci * tomoyo_add_entry - Add an ACL to current thread's domain. Used by learning mode. 19938c2ecf20Sopenharmony_ci * 19948c2ecf20Sopenharmony_ci * @domain: Pointer to "struct tomoyo_domain_info". 19958c2ecf20Sopenharmony_ci * @header: Lines containing ACL. 19968c2ecf20Sopenharmony_ci * 19978c2ecf20Sopenharmony_ci * Returns nothing. 19988c2ecf20Sopenharmony_ci */ 19998c2ecf20Sopenharmony_cistatic void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header) 20008c2ecf20Sopenharmony_ci{ 20018c2ecf20Sopenharmony_ci char *buffer; 20028c2ecf20Sopenharmony_ci char *realpath = NULL; 20038c2ecf20Sopenharmony_ci char *argv0 = NULL; 20048c2ecf20Sopenharmony_ci char *symlink = NULL; 20058c2ecf20Sopenharmony_ci char *cp = strchr(header, '\n'); 20068c2ecf20Sopenharmony_ci int len; 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci if (!cp) 20098c2ecf20Sopenharmony_ci return; 20108c2ecf20Sopenharmony_ci cp = strchr(cp + 1, '\n'); 20118c2ecf20Sopenharmony_ci if (!cp) 20128c2ecf20Sopenharmony_ci return; 20138c2ecf20Sopenharmony_ci *cp++ = '\0'; 20148c2ecf20Sopenharmony_ci len = strlen(cp) + 1; 20158c2ecf20Sopenharmony_ci /* strstr() will return NULL if ordering is wrong. */ 20168c2ecf20Sopenharmony_ci if (*cp == 'f') { 20178c2ecf20Sopenharmony_ci argv0 = strstr(header, " argv[]={ \""); 20188c2ecf20Sopenharmony_ci if (argv0) { 20198c2ecf20Sopenharmony_ci argv0 += 10; 20208c2ecf20Sopenharmony_ci len += tomoyo_truncate(argv0) + 14; 20218c2ecf20Sopenharmony_ci } 20228c2ecf20Sopenharmony_ci realpath = strstr(header, " exec={ realpath=\""); 20238c2ecf20Sopenharmony_ci if (realpath) { 20248c2ecf20Sopenharmony_ci realpath += 8; 20258c2ecf20Sopenharmony_ci len += tomoyo_truncate(realpath) + 6; 20268c2ecf20Sopenharmony_ci } 20278c2ecf20Sopenharmony_ci symlink = strstr(header, " symlink.target=\""); 20288c2ecf20Sopenharmony_ci if (symlink) 20298c2ecf20Sopenharmony_ci len += tomoyo_truncate(symlink + 1) + 1; 20308c2ecf20Sopenharmony_ci } 20318c2ecf20Sopenharmony_ci buffer = kmalloc(len, GFP_NOFS); 20328c2ecf20Sopenharmony_ci if (!buffer) 20338c2ecf20Sopenharmony_ci return; 20348c2ecf20Sopenharmony_ci snprintf(buffer, len - 1, "%s", cp); 20358c2ecf20Sopenharmony_ci if (realpath) 20368c2ecf20Sopenharmony_ci tomoyo_addprintf(buffer, len, " exec.%s", realpath); 20378c2ecf20Sopenharmony_ci if (argv0) 20388c2ecf20Sopenharmony_ci tomoyo_addprintf(buffer, len, " exec.argv[0]=%s", argv0); 20398c2ecf20Sopenharmony_ci if (symlink) 20408c2ecf20Sopenharmony_ci tomoyo_addprintf(buffer, len, "%s", symlink); 20418c2ecf20Sopenharmony_ci tomoyo_normalize_line(buffer); 20428c2ecf20Sopenharmony_ci if (!tomoyo_write_domain2(domain->ns, &domain->acl_info_list, buffer, 20438c2ecf20Sopenharmony_ci false)) 20448c2ecf20Sopenharmony_ci tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES); 20458c2ecf20Sopenharmony_ci kfree(buffer); 20468c2ecf20Sopenharmony_ci} 20478c2ecf20Sopenharmony_ci 20488c2ecf20Sopenharmony_ci/** 20498c2ecf20Sopenharmony_ci * tomoyo_supervisor - Ask for the supervisor's decision. 20508c2ecf20Sopenharmony_ci * 20518c2ecf20Sopenharmony_ci * @r: Pointer to "struct tomoyo_request_info". 20528c2ecf20Sopenharmony_ci * @fmt: The printf()'s format string, followed by parameters. 20538c2ecf20Sopenharmony_ci * 20548c2ecf20Sopenharmony_ci * Returns 0 if the supervisor decided to permit the access request which 20558c2ecf20Sopenharmony_ci * violated the policy in enforcing mode, TOMOYO_RETRY_REQUEST if the 20568c2ecf20Sopenharmony_ci * supervisor decided to retry the access request which violated the policy in 20578c2ecf20Sopenharmony_ci * enforcing mode, 0 if it is not in enforcing mode, -EPERM otherwise. 20588c2ecf20Sopenharmony_ci */ 20598c2ecf20Sopenharmony_ciint tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) 20608c2ecf20Sopenharmony_ci{ 20618c2ecf20Sopenharmony_ci va_list args; 20628c2ecf20Sopenharmony_ci int error; 20638c2ecf20Sopenharmony_ci int len; 20648c2ecf20Sopenharmony_ci static unsigned int tomoyo_serial; 20658c2ecf20Sopenharmony_ci struct tomoyo_query entry = { }; 20668c2ecf20Sopenharmony_ci bool quota_exceeded = false; 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci va_start(args, fmt); 20698c2ecf20Sopenharmony_ci len = vsnprintf((char *) &len, 1, fmt, args) + 1; 20708c2ecf20Sopenharmony_ci va_end(args); 20718c2ecf20Sopenharmony_ci /* Write /sys/kernel/security/tomoyo/audit. */ 20728c2ecf20Sopenharmony_ci va_start(args, fmt); 20738c2ecf20Sopenharmony_ci tomoyo_write_log2(r, len, fmt, args); 20748c2ecf20Sopenharmony_ci va_end(args); 20758c2ecf20Sopenharmony_ci /* Nothing more to do if granted. */ 20768c2ecf20Sopenharmony_ci if (r->granted) 20778c2ecf20Sopenharmony_ci return 0; 20788c2ecf20Sopenharmony_ci if (r->mode) 20798c2ecf20Sopenharmony_ci tomoyo_update_stat(r->mode); 20808c2ecf20Sopenharmony_ci switch (r->mode) { 20818c2ecf20Sopenharmony_ci case TOMOYO_CONFIG_ENFORCING: 20828c2ecf20Sopenharmony_ci error = -EPERM; 20838c2ecf20Sopenharmony_ci if (atomic_read(&tomoyo_query_observers)) 20848c2ecf20Sopenharmony_ci break; 20858c2ecf20Sopenharmony_ci goto out; 20868c2ecf20Sopenharmony_ci case TOMOYO_CONFIG_LEARNING: 20878c2ecf20Sopenharmony_ci error = 0; 20888c2ecf20Sopenharmony_ci /* Check max_learning_entry parameter. */ 20898c2ecf20Sopenharmony_ci if (tomoyo_domain_quota_is_ok(r)) 20908c2ecf20Sopenharmony_ci break; 20918c2ecf20Sopenharmony_ci fallthrough; 20928c2ecf20Sopenharmony_ci default: 20938c2ecf20Sopenharmony_ci return 0; 20948c2ecf20Sopenharmony_ci } 20958c2ecf20Sopenharmony_ci /* Get message. */ 20968c2ecf20Sopenharmony_ci va_start(args, fmt); 20978c2ecf20Sopenharmony_ci entry.query = tomoyo_init_log(r, len, fmt, args); 20988c2ecf20Sopenharmony_ci va_end(args); 20998c2ecf20Sopenharmony_ci if (!entry.query) 21008c2ecf20Sopenharmony_ci goto out; 21018c2ecf20Sopenharmony_ci entry.query_len = strlen(entry.query) + 1; 21028c2ecf20Sopenharmony_ci if (!error) { 21038c2ecf20Sopenharmony_ci tomoyo_add_entry(r->domain, entry.query); 21048c2ecf20Sopenharmony_ci goto out; 21058c2ecf20Sopenharmony_ci } 21068c2ecf20Sopenharmony_ci len = tomoyo_round2(entry.query_len); 21078c2ecf20Sopenharmony_ci entry.domain = r->domain; 21088c2ecf20Sopenharmony_ci spin_lock(&tomoyo_query_list_lock); 21098c2ecf20Sopenharmony_ci if (tomoyo_memory_quota[TOMOYO_MEMORY_QUERY] && 21108c2ecf20Sopenharmony_ci tomoyo_memory_used[TOMOYO_MEMORY_QUERY] + len 21118c2ecf20Sopenharmony_ci >= tomoyo_memory_quota[TOMOYO_MEMORY_QUERY]) { 21128c2ecf20Sopenharmony_ci quota_exceeded = true; 21138c2ecf20Sopenharmony_ci } else { 21148c2ecf20Sopenharmony_ci entry.serial = tomoyo_serial++; 21158c2ecf20Sopenharmony_ci entry.retry = r->retry; 21168c2ecf20Sopenharmony_ci tomoyo_memory_used[TOMOYO_MEMORY_QUERY] += len; 21178c2ecf20Sopenharmony_ci list_add_tail(&entry.list, &tomoyo_query_list); 21188c2ecf20Sopenharmony_ci } 21198c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_query_list_lock); 21208c2ecf20Sopenharmony_ci if (quota_exceeded) 21218c2ecf20Sopenharmony_ci goto out; 21228c2ecf20Sopenharmony_ci /* Give 10 seconds for supervisor's opinion. */ 21238c2ecf20Sopenharmony_ci while (entry.timer < 10) { 21248c2ecf20Sopenharmony_ci wake_up_all(&tomoyo_query_wait); 21258c2ecf20Sopenharmony_ci if (wait_event_interruptible_timeout 21268c2ecf20Sopenharmony_ci (tomoyo_answer_wait, entry.answer || 21278c2ecf20Sopenharmony_ci !atomic_read(&tomoyo_query_observers), HZ)) 21288c2ecf20Sopenharmony_ci break; 21298c2ecf20Sopenharmony_ci entry.timer++; 21308c2ecf20Sopenharmony_ci } 21318c2ecf20Sopenharmony_ci spin_lock(&tomoyo_query_list_lock); 21328c2ecf20Sopenharmony_ci list_del(&entry.list); 21338c2ecf20Sopenharmony_ci tomoyo_memory_used[TOMOYO_MEMORY_QUERY] -= len; 21348c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_query_list_lock); 21358c2ecf20Sopenharmony_ci switch (entry.answer) { 21368c2ecf20Sopenharmony_ci case 3: /* Asked to retry by administrator. */ 21378c2ecf20Sopenharmony_ci error = TOMOYO_RETRY_REQUEST; 21388c2ecf20Sopenharmony_ci r->retry++; 21398c2ecf20Sopenharmony_ci break; 21408c2ecf20Sopenharmony_ci case 1: 21418c2ecf20Sopenharmony_ci /* Granted by administrator. */ 21428c2ecf20Sopenharmony_ci error = 0; 21438c2ecf20Sopenharmony_ci break; 21448c2ecf20Sopenharmony_ci default: 21458c2ecf20Sopenharmony_ci /* Timed out or rejected by administrator. */ 21468c2ecf20Sopenharmony_ci break; 21478c2ecf20Sopenharmony_ci } 21488c2ecf20Sopenharmony_ciout: 21498c2ecf20Sopenharmony_ci kfree(entry.query); 21508c2ecf20Sopenharmony_ci return error; 21518c2ecf20Sopenharmony_ci} 21528c2ecf20Sopenharmony_ci 21538c2ecf20Sopenharmony_ci/** 21548c2ecf20Sopenharmony_ci * tomoyo_find_domain_by_qid - Get domain by query id. 21558c2ecf20Sopenharmony_ci * 21568c2ecf20Sopenharmony_ci * @serial: Query ID assigned by tomoyo_supervisor(). 21578c2ecf20Sopenharmony_ci * 21588c2ecf20Sopenharmony_ci * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise. 21598c2ecf20Sopenharmony_ci */ 21608c2ecf20Sopenharmony_cistatic struct tomoyo_domain_info *tomoyo_find_domain_by_qid 21618c2ecf20Sopenharmony_ci(unsigned int serial) 21628c2ecf20Sopenharmony_ci{ 21638c2ecf20Sopenharmony_ci struct tomoyo_query *ptr; 21648c2ecf20Sopenharmony_ci struct tomoyo_domain_info *domain = NULL; 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci spin_lock(&tomoyo_query_list_lock); 21678c2ecf20Sopenharmony_ci list_for_each_entry(ptr, &tomoyo_query_list, list) { 21688c2ecf20Sopenharmony_ci if (ptr->serial != serial) 21698c2ecf20Sopenharmony_ci continue; 21708c2ecf20Sopenharmony_ci domain = ptr->domain; 21718c2ecf20Sopenharmony_ci break; 21728c2ecf20Sopenharmony_ci } 21738c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_query_list_lock); 21748c2ecf20Sopenharmony_ci return domain; 21758c2ecf20Sopenharmony_ci} 21768c2ecf20Sopenharmony_ci 21778c2ecf20Sopenharmony_ci/** 21788c2ecf20Sopenharmony_ci * tomoyo_poll_query - poll() for /sys/kernel/security/tomoyo/query. 21798c2ecf20Sopenharmony_ci * 21808c2ecf20Sopenharmony_ci * @file: Pointer to "struct file". 21818c2ecf20Sopenharmony_ci * @wait: Pointer to "poll_table". 21828c2ecf20Sopenharmony_ci * 21838c2ecf20Sopenharmony_ci * Returns EPOLLIN | EPOLLRDNORM when ready to read, 0 otherwise. 21848c2ecf20Sopenharmony_ci * 21858c2ecf20Sopenharmony_ci * Waits for access requests which violated policy in enforcing mode. 21868c2ecf20Sopenharmony_ci */ 21878c2ecf20Sopenharmony_cistatic __poll_t tomoyo_poll_query(struct file *file, poll_table *wait) 21888c2ecf20Sopenharmony_ci{ 21898c2ecf20Sopenharmony_ci if (!list_empty(&tomoyo_query_list)) 21908c2ecf20Sopenharmony_ci return EPOLLIN | EPOLLRDNORM; 21918c2ecf20Sopenharmony_ci poll_wait(file, &tomoyo_query_wait, wait); 21928c2ecf20Sopenharmony_ci if (!list_empty(&tomoyo_query_list)) 21938c2ecf20Sopenharmony_ci return EPOLLIN | EPOLLRDNORM; 21948c2ecf20Sopenharmony_ci return 0; 21958c2ecf20Sopenharmony_ci} 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci/** 21988c2ecf20Sopenharmony_ci * tomoyo_read_query - Read access requests which violated policy in enforcing mode. 21998c2ecf20Sopenharmony_ci * 22008c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 22018c2ecf20Sopenharmony_ci */ 22028c2ecf20Sopenharmony_cistatic void tomoyo_read_query(struct tomoyo_io_buffer *head) 22038c2ecf20Sopenharmony_ci{ 22048c2ecf20Sopenharmony_ci struct list_head *tmp; 22058c2ecf20Sopenharmony_ci unsigned int pos = 0; 22068c2ecf20Sopenharmony_ci size_t len = 0; 22078c2ecf20Sopenharmony_ci char *buf; 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci if (head->r.w_pos) 22108c2ecf20Sopenharmony_ci return; 22118c2ecf20Sopenharmony_ci kfree(head->read_buf); 22128c2ecf20Sopenharmony_ci head->read_buf = NULL; 22138c2ecf20Sopenharmony_ci spin_lock(&tomoyo_query_list_lock); 22148c2ecf20Sopenharmony_ci list_for_each(tmp, &tomoyo_query_list) { 22158c2ecf20Sopenharmony_ci struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); 22168c2ecf20Sopenharmony_ci 22178c2ecf20Sopenharmony_ci if (pos++ != head->r.query_index) 22188c2ecf20Sopenharmony_ci continue; 22198c2ecf20Sopenharmony_ci len = ptr->query_len; 22208c2ecf20Sopenharmony_ci break; 22218c2ecf20Sopenharmony_ci } 22228c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_query_list_lock); 22238c2ecf20Sopenharmony_ci if (!len) { 22248c2ecf20Sopenharmony_ci head->r.query_index = 0; 22258c2ecf20Sopenharmony_ci return; 22268c2ecf20Sopenharmony_ci } 22278c2ecf20Sopenharmony_ci buf = kzalloc(len + 32, GFP_NOFS); 22288c2ecf20Sopenharmony_ci if (!buf) 22298c2ecf20Sopenharmony_ci return; 22308c2ecf20Sopenharmony_ci pos = 0; 22318c2ecf20Sopenharmony_ci spin_lock(&tomoyo_query_list_lock); 22328c2ecf20Sopenharmony_ci list_for_each(tmp, &tomoyo_query_list) { 22338c2ecf20Sopenharmony_ci struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); 22348c2ecf20Sopenharmony_ci 22358c2ecf20Sopenharmony_ci if (pos++ != head->r.query_index) 22368c2ecf20Sopenharmony_ci continue; 22378c2ecf20Sopenharmony_ci /* 22388c2ecf20Sopenharmony_ci * Some query can be skipped because tomoyo_query_list 22398c2ecf20Sopenharmony_ci * can change, but I don't care. 22408c2ecf20Sopenharmony_ci */ 22418c2ecf20Sopenharmony_ci if (len == ptr->query_len) 22428c2ecf20Sopenharmony_ci snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial, 22438c2ecf20Sopenharmony_ci ptr->retry, ptr->query); 22448c2ecf20Sopenharmony_ci break; 22458c2ecf20Sopenharmony_ci } 22468c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_query_list_lock); 22478c2ecf20Sopenharmony_ci if (buf[0]) { 22488c2ecf20Sopenharmony_ci head->read_buf = buf; 22498c2ecf20Sopenharmony_ci head->r.w[head->r.w_pos++] = buf; 22508c2ecf20Sopenharmony_ci head->r.query_index++; 22518c2ecf20Sopenharmony_ci } else { 22528c2ecf20Sopenharmony_ci kfree(buf); 22538c2ecf20Sopenharmony_ci } 22548c2ecf20Sopenharmony_ci} 22558c2ecf20Sopenharmony_ci 22568c2ecf20Sopenharmony_ci/** 22578c2ecf20Sopenharmony_ci * tomoyo_write_answer - Write the supervisor's decision. 22588c2ecf20Sopenharmony_ci * 22598c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 22608c2ecf20Sopenharmony_ci * 22618c2ecf20Sopenharmony_ci * Returns 0 on success, -EINVAL otherwise. 22628c2ecf20Sopenharmony_ci */ 22638c2ecf20Sopenharmony_cistatic int tomoyo_write_answer(struct tomoyo_io_buffer *head) 22648c2ecf20Sopenharmony_ci{ 22658c2ecf20Sopenharmony_ci char *data = head->write_buf; 22668c2ecf20Sopenharmony_ci struct list_head *tmp; 22678c2ecf20Sopenharmony_ci unsigned int serial; 22688c2ecf20Sopenharmony_ci unsigned int answer; 22698c2ecf20Sopenharmony_ci 22708c2ecf20Sopenharmony_ci spin_lock(&tomoyo_query_list_lock); 22718c2ecf20Sopenharmony_ci list_for_each(tmp, &tomoyo_query_list) { 22728c2ecf20Sopenharmony_ci struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); 22738c2ecf20Sopenharmony_ci 22748c2ecf20Sopenharmony_ci ptr->timer = 0; 22758c2ecf20Sopenharmony_ci } 22768c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_query_list_lock); 22778c2ecf20Sopenharmony_ci if (sscanf(data, "A%u=%u", &serial, &answer) != 2) 22788c2ecf20Sopenharmony_ci return -EINVAL; 22798c2ecf20Sopenharmony_ci spin_lock(&tomoyo_query_list_lock); 22808c2ecf20Sopenharmony_ci list_for_each(tmp, &tomoyo_query_list) { 22818c2ecf20Sopenharmony_ci struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list); 22828c2ecf20Sopenharmony_ci 22838c2ecf20Sopenharmony_ci if (ptr->serial != serial) 22848c2ecf20Sopenharmony_ci continue; 22858c2ecf20Sopenharmony_ci ptr->answer = answer; 22868c2ecf20Sopenharmony_ci /* Remove from tomoyo_query_list. */ 22878c2ecf20Sopenharmony_ci if (ptr->answer) 22888c2ecf20Sopenharmony_ci list_del_init(&ptr->list); 22898c2ecf20Sopenharmony_ci break; 22908c2ecf20Sopenharmony_ci } 22918c2ecf20Sopenharmony_ci spin_unlock(&tomoyo_query_list_lock); 22928c2ecf20Sopenharmony_ci return 0; 22938c2ecf20Sopenharmony_ci} 22948c2ecf20Sopenharmony_ci 22958c2ecf20Sopenharmony_ci/** 22968c2ecf20Sopenharmony_ci * tomoyo_read_version: Get version. 22978c2ecf20Sopenharmony_ci * 22988c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 22998c2ecf20Sopenharmony_ci * 23008c2ecf20Sopenharmony_ci * Returns version information. 23018c2ecf20Sopenharmony_ci */ 23028c2ecf20Sopenharmony_cistatic void tomoyo_read_version(struct tomoyo_io_buffer *head) 23038c2ecf20Sopenharmony_ci{ 23048c2ecf20Sopenharmony_ci if (!head->r.eof) { 23058c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "2.6.0"); 23068c2ecf20Sopenharmony_ci head->r.eof = true; 23078c2ecf20Sopenharmony_ci } 23088c2ecf20Sopenharmony_ci} 23098c2ecf20Sopenharmony_ci 23108c2ecf20Sopenharmony_ci/* String table for /sys/kernel/security/tomoyo/stat interface. */ 23118c2ecf20Sopenharmony_cistatic const char * const tomoyo_policy_headers[TOMOYO_MAX_POLICY_STAT] = { 23128c2ecf20Sopenharmony_ci [TOMOYO_STAT_POLICY_UPDATES] = "update:", 23138c2ecf20Sopenharmony_ci [TOMOYO_STAT_POLICY_LEARNING] = "violation in learning mode:", 23148c2ecf20Sopenharmony_ci [TOMOYO_STAT_POLICY_PERMISSIVE] = "violation in permissive mode:", 23158c2ecf20Sopenharmony_ci [TOMOYO_STAT_POLICY_ENFORCING] = "violation in enforcing mode:", 23168c2ecf20Sopenharmony_ci}; 23178c2ecf20Sopenharmony_ci 23188c2ecf20Sopenharmony_ci/* String table for /sys/kernel/security/tomoyo/stat interface. */ 23198c2ecf20Sopenharmony_cistatic const char * const tomoyo_memory_headers[TOMOYO_MAX_MEMORY_STAT] = { 23208c2ecf20Sopenharmony_ci [TOMOYO_MEMORY_POLICY] = "policy:", 23218c2ecf20Sopenharmony_ci [TOMOYO_MEMORY_AUDIT] = "audit log:", 23228c2ecf20Sopenharmony_ci [TOMOYO_MEMORY_QUERY] = "query message:", 23238c2ecf20Sopenharmony_ci}; 23248c2ecf20Sopenharmony_ci 23258c2ecf20Sopenharmony_ci/* Counter for number of updates. */ 23268c2ecf20Sopenharmony_cistatic atomic_t tomoyo_stat_updated[TOMOYO_MAX_POLICY_STAT]; 23278c2ecf20Sopenharmony_ci/* Timestamp counter for last updated. */ 23288c2ecf20Sopenharmony_cistatic time64_t tomoyo_stat_modified[TOMOYO_MAX_POLICY_STAT]; 23298c2ecf20Sopenharmony_ci 23308c2ecf20Sopenharmony_ci/** 23318c2ecf20Sopenharmony_ci * tomoyo_update_stat - Update statistic counters. 23328c2ecf20Sopenharmony_ci * 23338c2ecf20Sopenharmony_ci * @index: Index for policy type. 23348c2ecf20Sopenharmony_ci * 23358c2ecf20Sopenharmony_ci * Returns nothing. 23368c2ecf20Sopenharmony_ci */ 23378c2ecf20Sopenharmony_civoid tomoyo_update_stat(const u8 index) 23388c2ecf20Sopenharmony_ci{ 23398c2ecf20Sopenharmony_ci atomic_inc(&tomoyo_stat_updated[index]); 23408c2ecf20Sopenharmony_ci tomoyo_stat_modified[index] = ktime_get_real_seconds(); 23418c2ecf20Sopenharmony_ci} 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_ci/** 23448c2ecf20Sopenharmony_ci * tomoyo_read_stat - Read statistic data. 23458c2ecf20Sopenharmony_ci * 23468c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 23478c2ecf20Sopenharmony_ci * 23488c2ecf20Sopenharmony_ci * Returns nothing. 23498c2ecf20Sopenharmony_ci */ 23508c2ecf20Sopenharmony_cistatic void tomoyo_read_stat(struct tomoyo_io_buffer *head) 23518c2ecf20Sopenharmony_ci{ 23528c2ecf20Sopenharmony_ci u8 i; 23538c2ecf20Sopenharmony_ci unsigned int total = 0; 23548c2ecf20Sopenharmony_ci 23558c2ecf20Sopenharmony_ci if (head->r.eof) 23568c2ecf20Sopenharmony_ci return; 23578c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_POLICY_STAT; i++) { 23588c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "Policy %-30s %10u", 23598c2ecf20Sopenharmony_ci tomoyo_policy_headers[i], 23608c2ecf20Sopenharmony_ci atomic_read(&tomoyo_stat_updated[i])); 23618c2ecf20Sopenharmony_ci if (tomoyo_stat_modified[i]) { 23628c2ecf20Sopenharmony_ci struct tomoyo_time stamp; 23638c2ecf20Sopenharmony_ci 23648c2ecf20Sopenharmony_ci tomoyo_convert_time(tomoyo_stat_modified[i], &stamp); 23658c2ecf20Sopenharmony_ci tomoyo_io_printf(head, " (Last: %04u/%02u/%02u %02u:%02u:%02u)", 23668c2ecf20Sopenharmony_ci stamp.year, stamp.month, stamp.day, 23678c2ecf20Sopenharmony_ci stamp.hour, stamp.min, stamp.sec); 23688c2ecf20Sopenharmony_ci } 23698c2ecf20Sopenharmony_ci tomoyo_set_lf(head); 23708c2ecf20Sopenharmony_ci } 23718c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++) { 23728c2ecf20Sopenharmony_ci unsigned int used = tomoyo_memory_used[i]; 23738c2ecf20Sopenharmony_ci 23748c2ecf20Sopenharmony_ci total += used; 23758c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "Memory used by %-22s %10u", 23768c2ecf20Sopenharmony_ci tomoyo_memory_headers[i], used); 23778c2ecf20Sopenharmony_ci used = tomoyo_memory_quota[i]; 23788c2ecf20Sopenharmony_ci if (used) 23798c2ecf20Sopenharmony_ci tomoyo_io_printf(head, " (Quota: %10u)", used); 23808c2ecf20Sopenharmony_ci tomoyo_set_lf(head); 23818c2ecf20Sopenharmony_ci } 23828c2ecf20Sopenharmony_ci tomoyo_io_printf(head, "Total memory used: %10u\n", 23838c2ecf20Sopenharmony_ci total); 23848c2ecf20Sopenharmony_ci head->r.eof = true; 23858c2ecf20Sopenharmony_ci} 23868c2ecf20Sopenharmony_ci 23878c2ecf20Sopenharmony_ci/** 23888c2ecf20Sopenharmony_ci * tomoyo_write_stat - Set memory quota. 23898c2ecf20Sopenharmony_ci * 23908c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 23918c2ecf20Sopenharmony_ci * 23928c2ecf20Sopenharmony_ci * Returns 0. 23938c2ecf20Sopenharmony_ci */ 23948c2ecf20Sopenharmony_cistatic int tomoyo_write_stat(struct tomoyo_io_buffer *head) 23958c2ecf20Sopenharmony_ci{ 23968c2ecf20Sopenharmony_ci char *data = head->write_buf; 23978c2ecf20Sopenharmony_ci u8 i; 23988c2ecf20Sopenharmony_ci 23998c2ecf20Sopenharmony_ci if (tomoyo_str_starts(&data, "Memory used by ")) 24008c2ecf20Sopenharmony_ci for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++) 24018c2ecf20Sopenharmony_ci if (tomoyo_str_starts(&data, tomoyo_memory_headers[i])) 24028c2ecf20Sopenharmony_ci sscanf(data, "%u", &tomoyo_memory_quota[i]); 24038c2ecf20Sopenharmony_ci return 0; 24048c2ecf20Sopenharmony_ci} 24058c2ecf20Sopenharmony_ci 24068c2ecf20Sopenharmony_ci/** 24078c2ecf20Sopenharmony_ci * tomoyo_open_control - open() for /sys/kernel/security/tomoyo/ interface. 24088c2ecf20Sopenharmony_ci * 24098c2ecf20Sopenharmony_ci * @type: Type of interface. 24108c2ecf20Sopenharmony_ci * @file: Pointer to "struct file". 24118c2ecf20Sopenharmony_ci * 24128c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 24138c2ecf20Sopenharmony_ci */ 24148c2ecf20Sopenharmony_ciint tomoyo_open_control(const u8 type, struct file *file) 24158c2ecf20Sopenharmony_ci{ 24168c2ecf20Sopenharmony_ci struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_NOFS); 24178c2ecf20Sopenharmony_ci 24188c2ecf20Sopenharmony_ci if (!head) 24198c2ecf20Sopenharmony_ci return -ENOMEM; 24208c2ecf20Sopenharmony_ci mutex_init(&head->io_sem); 24218c2ecf20Sopenharmony_ci head->type = type; 24228c2ecf20Sopenharmony_ci switch (type) { 24238c2ecf20Sopenharmony_ci case TOMOYO_DOMAINPOLICY: 24248c2ecf20Sopenharmony_ci /* /sys/kernel/security/tomoyo/domain_policy */ 24258c2ecf20Sopenharmony_ci head->write = tomoyo_write_domain; 24268c2ecf20Sopenharmony_ci head->read = tomoyo_read_domain; 24278c2ecf20Sopenharmony_ci break; 24288c2ecf20Sopenharmony_ci case TOMOYO_EXCEPTIONPOLICY: 24298c2ecf20Sopenharmony_ci /* /sys/kernel/security/tomoyo/exception_policy */ 24308c2ecf20Sopenharmony_ci head->write = tomoyo_write_exception; 24318c2ecf20Sopenharmony_ci head->read = tomoyo_read_exception; 24328c2ecf20Sopenharmony_ci break; 24338c2ecf20Sopenharmony_ci case TOMOYO_AUDIT: 24348c2ecf20Sopenharmony_ci /* /sys/kernel/security/tomoyo/audit */ 24358c2ecf20Sopenharmony_ci head->poll = tomoyo_poll_log; 24368c2ecf20Sopenharmony_ci head->read = tomoyo_read_log; 24378c2ecf20Sopenharmony_ci break; 24388c2ecf20Sopenharmony_ci case TOMOYO_PROCESS_STATUS: 24398c2ecf20Sopenharmony_ci /* /sys/kernel/security/tomoyo/.process_status */ 24408c2ecf20Sopenharmony_ci head->write = tomoyo_write_pid; 24418c2ecf20Sopenharmony_ci head->read = tomoyo_read_pid; 24428c2ecf20Sopenharmony_ci break; 24438c2ecf20Sopenharmony_ci case TOMOYO_VERSION: 24448c2ecf20Sopenharmony_ci /* /sys/kernel/security/tomoyo/version */ 24458c2ecf20Sopenharmony_ci head->read = tomoyo_read_version; 24468c2ecf20Sopenharmony_ci head->readbuf_size = 128; 24478c2ecf20Sopenharmony_ci break; 24488c2ecf20Sopenharmony_ci case TOMOYO_STAT: 24498c2ecf20Sopenharmony_ci /* /sys/kernel/security/tomoyo/stat */ 24508c2ecf20Sopenharmony_ci head->write = tomoyo_write_stat; 24518c2ecf20Sopenharmony_ci head->read = tomoyo_read_stat; 24528c2ecf20Sopenharmony_ci head->readbuf_size = 1024; 24538c2ecf20Sopenharmony_ci break; 24548c2ecf20Sopenharmony_ci case TOMOYO_PROFILE: 24558c2ecf20Sopenharmony_ci /* /sys/kernel/security/tomoyo/profile */ 24568c2ecf20Sopenharmony_ci head->write = tomoyo_write_profile; 24578c2ecf20Sopenharmony_ci head->read = tomoyo_read_profile; 24588c2ecf20Sopenharmony_ci break; 24598c2ecf20Sopenharmony_ci case TOMOYO_QUERY: /* /sys/kernel/security/tomoyo/query */ 24608c2ecf20Sopenharmony_ci head->poll = tomoyo_poll_query; 24618c2ecf20Sopenharmony_ci head->write = tomoyo_write_answer; 24628c2ecf20Sopenharmony_ci head->read = tomoyo_read_query; 24638c2ecf20Sopenharmony_ci break; 24648c2ecf20Sopenharmony_ci case TOMOYO_MANAGER: 24658c2ecf20Sopenharmony_ci /* /sys/kernel/security/tomoyo/manager */ 24668c2ecf20Sopenharmony_ci head->write = tomoyo_write_manager; 24678c2ecf20Sopenharmony_ci head->read = tomoyo_read_manager; 24688c2ecf20Sopenharmony_ci break; 24698c2ecf20Sopenharmony_ci } 24708c2ecf20Sopenharmony_ci if (!(file->f_mode & FMODE_READ)) { 24718c2ecf20Sopenharmony_ci /* 24728c2ecf20Sopenharmony_ci * No need to allocate read_buf since it is not opened 24738c2ecf20Sopenharmony_ci * for reading. 24748c2ecf20Sopenharmony_ci */ 24758c2ecf20Sopenharmony_ci head->read = NULL; 24768c2ecf20Sopenharmony_ci head->poll = NULL; 24778c2ecf20Sopenharmony_ci } else if (!head->poll) { 24788c2ecf20Sopenharmony_ci /* Don't allocate read_buf for poll() access. */ 24798c2ecf20Sopenharmony_ci if (!head->readbuf_size) 24808c2ecf20Sopenharmony_ci head->readbuf_size = 4096 * 2; 24818c2ecf20Sopenharmony_ci head->read_buf = kzalloc(head->readbuf_size, GFP_NOFS); 24828c2ecf20Sopenharmony_ci if (!head->read_buf) { 24838c2ecf20Sopenharmony_ci kfree(head); 24848c2ecf20Sopenharmony_ci return -ENOMEM; 24858c2ecf20Sopenharmony_ci } 24868c2ecf20Sopenharmony_ci } 24878c2ecf20Sopenharmony_ci if (!(file->f_mode & FMODE_WRITE)) { 24888c2ecf20Sopenharmony_ci /* 24898c2ecf20Sopenharmony_ci * No need to allocate write_buf since it is not opened 24908c2ecf20Sopenharmony_ci * for writing. 24918c2ecf20Sopenharmony_ci */ 24928c2ecf20Sopenharmony_ci head->write = NULL; 24938c2ecf20Sopenharmony_ci } else if (head->write) { 24948c2ecf20Sopenharmony_ci head->writebuf_size = 4096 * 2; 24958c2ecf20Sopenharmony_ci head->write_buf = kzalloc(head->writebuf_size, GFP_NOFS); 24968c2ecf20Sopenharmony_ci if (!head->write_buf) { 24978c2ecf20Sopenharmony_ci kfree(head->read_buf); 24988c2ecf20Sopenharmony_ci kfree(head); 24998c2ecf20Sopenharmony_ci return -ENOMEM; 25008c2ecf20Sopenharmony_ci } 25018c2ecf20Sopenharmony_ci } 25028c2ecf20Sopenharmony_ci /* 25038c2ecf20Sopenharmony_ci * If the file is /sys/kernel/security/tomoyo/query , increment the 25048c2ecf20Sopenharmony_ci * observer counter. 25058c2ecf20Sopenharmony_ci * The obserber counter is used by tomoyo_supervisor() to see if 25068c2ecf20Sopenharmony_ci * there is some process monitoring /sys/kernel/security/tomoyo/query. 25078c2ecf20Sopenharmony_ci */ 25088c2ecf20Sopenharmony_ci if (type == TOMOYO_QUERY) 25098c2ecf20Sopenharmony_ci atomic_inc(&tomoyo_query_observers); 25108c2ecf20Sopenharmony_ci file->private_data = head; 25118c2ecf20Sopenharmony_ci tomoyo_notify_gc(head, true); 25128c2ecf20Sopenharmony_ci return 0; 25138c2ecf20Sopenharmony_ci} 25148c2ecf20Sopenharmony_ci 25158c2ecf20Sopenharmony_ci/** 25168c2ecf20Sopenharmony_ci * tomoyo_poll_control - poll() for /sys/kernel/security/tomoyo/ interface. 25178c2ecf20Sopenharmony_ci * 25188c2ecf20Sopenharmony_ci * @file: Pointer to "struct file". 25198c2ecf20Sopenharmony_ci * @wait: Pointer to "poll_table". Maybe NULL. 25208c2ecf20Sopenharmony_ci * 25218c2ecf20Sopenharmony_ci * Returns EPOLLIN | EPOLLRDNORM | EPOLLOUT | EPOLLWRNORM if ready to read/write, 25228c2ecf20Sopenharmony_ci * EPOLLOUT | EPOLLWRNORM otherwise. 25238c2ecf20Sopenharmony_ci */ 25248c2ecf20Sopenharmony_ci__poll_t tomoyo_poll_control(struct file *file, poll_table *wait) 25258c2ecf20Sopenharmony_ci{ 25268c2ecf20Sopenharmony_ci struct tomoyo_io_buffer *head = file->private_data; 25278c2ecf20Sopenharmony_ci 25288c2ecf20Sopenharmony_ci if (head->poll) 25298c2ecf20Sopenharmony_ci return head->poll(file, wait) | EPOLLOUT | EPOLLWRNORM; 25308c2ecf20Sopenharmony_ci return EPOLLIN | EPOLLRDNORM | EPOLLOUT | EPOLLWRNORM; 25318c2ecf20Sopenharmony_ci} 25328c2ecf20Sopenharmony_ci 25338c2ecf20Sopenharmony_ci/** 25348c2ecf20Sopenharmony_ci * tomoyo_set_namespace_cursor - Set namespace to read. 25358c2ecf20Sopenharmony_ci * 25368c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 25378c2ecf20Sopenharmony_ci * 25388c2ecf20Sopenharmony_ci * Returns nothing. 25398c2ecf20Sopenharmony_ci */ 25408c2ecf20Sopenharmony_cistatic inline void tomoyo_set_namespace_cursor(struct tomoyo_io_buffer *head) 25418c2ecf20Sopenharmony_ci{ 25428c2ecf20Sopenharmony_ci struct list_head *ns; 25438c2ecf20Sopenharmony_ci 25448c2ecf20Sopenharmony_ci if (head->type != TOMOYO_EXCEPTIONPOLICY && 25458c2ecf20Sopenharmony_ci head->type != TOMOYO_PROFILE) 25468c2ecf20Sopenharmony_ci return; 25478c2ecf20Sopenharmony_ci /* 25488c2ecf20Sopenharmony_ci * If this is the first read, or reading previous namespace finished 25498c2ecf20Sopenharmony_ci * and has more namespaces to read, update the namespace cursor. 25508c2ecf20Sopenharmony_ci */ 25518c2ecf20Sopenharmony_ci ns = head->r.ns; 25528c2ecf20Sopenharmony_ci if (!ns || (head->r.eof && ns->next != &tomoyo_namespace_list)) { 25538c2ecf20Sopenharmony_ci /* Clearing is OK because tomoyo_flush() returned true. */ 25548c2ecf20Sopenharmony_ci memset(&head->r, 0, sizeof(head->r)); 25558c2ecf20Sopenharmony_ci head->r.ns = ns ? ns->next : tomoyo_namespace_list.next; 25568c2ecf20Sopenharmony_ci } 25578c2ecf20Sopenharmony_ci} 25588c2ecf20Sopenharmony_ci 25598c2ecf20Sopenharmony_ci/** 25608c2ecf20Sopenharmony_ci * tomoyo_has_more_namespace - Check for unread namespaces. 25618c2ecf20Sopenharmony_ci * 25628c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 25638c2ecf20Sopenharmony_ci * 25648c2ecf20Sopenharmony_ci * Returns true if we have more entries to print, false otherwise. 25658c2ecf20Sopenharmony_ci */ 25668c2ecf20Sopenharmony_cistatic inline bool tomoyo_has_more_namespace(struct tomoyo_io_buffer *head) 25678c2ecf20Sopenharmony_ci{ 25688c2ecf20Sopenharmony_ci return (head->type == TOMOYO_EXCEPTIONPOLICY || 25698c2ecf20Sopenharmony_ci head->type == TOMOYO_PROFILE) && head->r.eof && 25708c2ecf20Sopenharmony_ci head->r.ns->next != &tomoyo_namespace_list; 25718c2ecf20Sopenharmony_ci} 25728c2ecf20Sopenharmony_ci 25738c2ecf20Sopenharmony_ci/** 25748c2ecf20Sopenharmony_ci * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface. 25758c2ecf20Sopenharmony_ci * 25768c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 25778c2ecf20Sopenharmony_ci * @buffer: Poiner to buffer to write to. 25788c2ecf20Sopenharmony_ci * @buffer_len: Size of @buffer. 25798c2ecf20Sopenharmony_ci * 25808c2ecf20Sopenharmony_ci * Returns bytes read on success, negative value otherwise. 25818c2ecf20Sopenharmony_ci */ 25828c2ecf20Sopenharmony_cissize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer, 25838c2ecf20Sopenharmony_ci const int buffer_len) 25848c2ecf20Sopenharmony_ci{ 25858c2ecf20Sopenharmony_ci int len; 25868c2ecf20Sopenharmony_ci int idx; 25878c2ecf20Sopenharmony_ci 25888c2ecf20Sopenharmony_ci if (!head->read) 25898c2ecf20Sopenharmony_ci return -EINVAL; 25908c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&head->io_sem)) 25918c2ecf20Sopenharmony_ci return -EINTR; 25928c2ecf20Sopenharmony_ci head->read_user_buf = buffer; 25938c2ecf20Sopenharmony_ci head->read_user_buf_avail = buffer_len; 25948c2ecf20Sopenharmony_ci idx = tomoyo_read_lock(); 25958c2ecf20Sopenharmony_ci if (tomoyo_flush(head)) 25968c2ecf20Sopenharmony_ci /* Call the policy handler. */ 25978c2ecf20Sopenharmony_ci do { 25988c2ecf20Sopenharmony_ci tomoyo_set_namespace_cursor(head); 25998c2ecf20Sopenharmony_ci head->read(head); 26008c2ecf20Sopenharmony_ci } while (tomoyo_flush(head) && 26018c2ecf20Sopenharmony_ci tomoyo_has_more_namespace(head)); 26028c2ecf20Sopenharmony_ci tomoyo_read_unlock(idx); 26038c2ecf20Sopenharmony_ci len = head->read_user_buf - buffer; 26048c2ecf20Sopenharmony_ci mutex_unlock(&head->io_sem); 26058c2ecf20Sopenharmony_ci return len; 26068c2ecf20Sopenharmony_ci} 26078c2ecf20Sopenharmony_ci 26088c2ecf20Sopenharmony_ci/** 26098c2ecf20Sopenharmony_ci * tomoyo_parse_policy - Parse a policy line. 26108c2ecf20Sopenharmony_ci * 26118c2ecf20Sopenharmony_ci * @head: Poiter to "struct tomoyo_io_buffer". 26128c2ecf20Sopenharmony_ci * @line: Line to parse. 26138c2ecf20Sopenharmony_ci * 26148c2ecf20Sopenharmony_ci * Returns 0 on success, negative value otherwise. 26158c2ecf20Sopenharmony_ci * 26168c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 26178c2ecf20Sopenharmony_ci */ 26188c2ecf20Sopenharmony_cistatic int tomoyo_parse_policy(struct tomoyo_io_buffer *head, char *line) 26198c2ecf20Sopenharmony_ci{ 26208c2ecf20Sopenharmony_ci /* Delete request? */ 26218c2ecf20Sopenharmony_ci head->w.is_delete = !strncmp(line, "delete ", 7); 26228c2ecf20Sopenharmony_ci if (head->w.is_delete) 26238c2ecf20Sopenharmony_ci memmove(line, line + 7, strlen(line + 7) + 1); 26248c2ecf20Sopenharmony_ci /* Selecting namespace to update. */ 26258c2ecf20Sopenharmony_ci if (head->type == TOMOYO_EXCEPTIONPOLICY || 26268c2ecf20Sopenharmony_ci head->type == TOMOYO_PROFILE) { 26278c2ecf20Sopenharmony_ci if (*line == '<') { 26288c2ecf20Sopenharmony_ci char *cp = strchr(line, ' '); 26298c2ecf20Sopenharmony_ci 26308c2ecf20Sopenharmony_ci if (cp) { 26318c2ecf20Sopenharmony_ci *cp++ = '\0'; 26328c2ecf20Sopenharmony_ci head->w.ns = tomoyo_assign_namespace(line); 26338c2ecf20Sopenharmony_ci memmove(line, cp, strlen(cp) + 1); 26348c2ecf20Sopenharmony_ci } else 26358c2ecf20Sopenharmony_ci head->w.ns = NULL; 26368c2ecf20Sopenharmony_ci } else 26378c2ecf20Sopenharmony_ci head->w.ns = &tomoyo_kernel_namespace; 26388c2ecf20Sopenharmony_ci /* Don't allow updating if namespace is invalid. */ 26398c2ecf20Sopenharmony_ci if (!head->w.ns) 26408c2ecf20Sopenharmony_ci return -ENOENT; 26418c2ecf20Sopenharmony_ci } 26428c2ecf20Sopenharmony_ci /* Do the update. */ 26438c2ecf20Sopenharmony_ci return head->write(head); 26448c2ecf20Sopenharmony_ci} 26458c2ecf20Sopenharmony_ci 26468c2ecf20Sopenharmony_ci/** 26478c2ecf20Sopenharmony_ci * tomoyo_write_control - write() for /sys/kernel/security/tomoyo/ interface. 26488c2ecf20Sopenharmony_ci * 26498c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 26508c2ecf20Sopenharmony_ci * @buffer: Pointer to buffer to read from. 26518c2ecf20Sopenharmony_ci * @buffer_len: Size of @buffer. 26528c2ecf20Sopenharmony_ci * 26538c2ecf20Sopenharmony_ci * Returns @buffer_len on success, negative value otherwise. 26548c2ecf20Sopenharmony_ci */ 26558c2ecf20Sopenharmony_cissize_t tomoyo_write_control(struct tomoyo_io_buffer *head, 26568c2ecf20Sopenharmony_ci const char __user *buffer, const int buffer_len) 26578c2ecf20Sopenharmony_ci{ 26588c2ecf20Sopenharmony_ci int error = buffer_len; 26598c2ecf20Sopenharmony_ci size_t avail_len = buffer_len; 26608c2ecf20Sopenharmony_ci char *cp0 = head->write_buf; 26618c2ecf20Sopenharmony_ci int idx; 26628c2ecf20Sopenharmony_ci 26638c2ecf20Sopenharmony_ci if (!head->write) 26648c2ecf20Sopenharmony_ci return -EINVAL; 26658c2ecf20Sopenharmony_ci if (mutex_lock_interruptible(&head->io_sem)) 26668c2ecf20Sopenharmony_ci return -EINTR; 26678c2ecf20Sopenharmony_ci head->read_user_buf_avail = 0; 26688c2ecf20Sopenharmony_ci idx = tomoyo_read_lock(); 26698c2ecf20Sopenharmony_ci /* Read a line and dispatch it to the policy handler. */ 26708c2ecf20Sopenharmony_ci while (avail_len > 0) { 26718c2ecf20Sopenharmony_ci char c; 26728c2ecf20Sopenharmony_ci 26738c2ecf20Sopenharmony_ci if (head->w.avail >= head->writebuf_size - 1) { 26748c2ecf20Sopenharmony_ci const int len = head->writebuf_size * 2; 26758c2ecf20Sopenharmony_ci char *cp = kzalloc(len, GFP_NOFS); 26768c2ecf20Sopenharmony_ci 26778c2ecf20Sopenharmony_ci if (!cp) { 26788c2ecf20Sopenharmony_ci error = -ENOMEM; 26798c2ecf20Sopenharmony_ci break; 26808c2ecf20Sopenharmony_ci } 26818c2ecf20Sopenharmony_ci memmove(cp, cp0, head->w.avail); 26828c2ecf20Sopenharmony_ci kfree(cp0); 26838c2ecf20Sopenharmony_ci head->write_buf = cp; 26848c2ecf20Sopenharmony_ci cp0 = cp; 26858c2ecf20Sopenharmony_ci head->writebuf_size = len; 26868c2ecf20Sopenharmony_ci } 26878c2ecf20Sopenharmony_ci if (get_user(c, buffer)) { 26888c2ecf20Sopenharmony_ci error = -EFAULT; 26898c2ecf20Sopenharmony_ci break; 26908c2ecf20Sopenharmony_ci } 26918c2ecf20Sopenharmony_ci buffer++; 26928c2ecf20Sopenharmony_ci avail_len--; 26938c2ecf20Sopenharmony_ci cp0[head->w.avail++] = c; 26948c2ecf20Sopenharmony_ci if (c != '\n') 26958c2ecf20Sopenharmony_ci continue; 26968c2ecf20Sopenharmony_ci cp0[head->w.avail - 1] = '\0'; 26978c2ecf20Sopenharmony_ci head->w.avail = 0; 26988c2ecf20Sopenharmony_ci tomoyo_normalize_line(cp0); 26998c2ecf20Sopenharmony_ci if (!strcmp(cp0, "reset")) { 27008c2ecf20Sopenharmony_ci head->w.ns = &tomoyo_kernel_namespace; 27018c2ecf20Sopenharmony_ci head->w.domain = NULL; 27028c2ecf20Sopenharmony_ci memset(&head->r, 0, sizeof(head->r)); 27038c2ecf20Sopenharmony_ci continue; 27048c2ecf20Sopenharmony_ci } 27058c2ecf20Sopenharmony_ci /* Don't allow updating policies by non manager programs. */ 27068c2ecf20Sopenharmony_ci switch (head->type) { 27078c2ecf20Sopenharmony_ci case TOMOYO_PROCESS_STATUS: 27088c2ecf20Sopenharmony_ci /* This does not write anything. */ 27098c2ecf20Sopenharmony_ci break; 27108c2ecf20Sopenharmony_ci case TOMOYO_DOMAINPOLICY: 27118c2ecf20Sopenharmony_ci if (tomoyo_select_domain(head, cp0)) 27128c2ecf20Sopenharmony_ci continue; 27138c2ecf20Sopenharmony_ci fallthrough; 27148c2ecf20Sopenharmony_ci case TOMOYO_EXCEPTIONPOLICY: 27158c2ecf20Sopenharmony_ci if (!strcmp(cp0, "select transition_only")) { 27168c2ecf20Sopenharmony_ci head->r.print_transition_related_only = true; 27178c2ecf20Sopenharmony_ci continue; 27188c2ecf20Sopenharmony_ci } 27198c2ecf20Sopenharmony_ci fallthrough; 27208c2ecf20Sopenharmony_ci default: 27218c2ecf20Sopenharmony_ci if (!tomoyo_manager()) { 27228c2ecf20Sopenharmony_ci error = -EPERM; 27238c2ecf20Sopenharmony_ci goto out; 27248c2ecf20Sopenharmony_ci } 27258c2ecf20Sopenharmony_ci } 27268c2ecf20Sopenharmony_ci switch (tomoyo_parse_policy(head, cp0)) { 27278c2ecf20Sopenharmony_ci case -EPERM: 27288c2ecf20Sopenharmony_ci error = -EPERM; 27298c2ecf20Sopenharmony_ci goto out; 27308c2ecf20Sopenharmony_ci case 0: 27318c2ecf20Sopenharmony_ci switch (head->type) { 27328c2ecf20Sopenharmony_ci case TOMOYO_DOMAINPOLICY: 27338c2ecf20Sopenharmony_ci case TOMOYO_EXCEPTIONPOLICY: 27348c2ecf20Sopenharmony_ci case TOMOYO_STAT: 27358c2ecf20Sopenharmony_ci case TOMOYO_PROFILE: 27368c2ecf20Sopenharmony_ci case TOMOYO_MANAGER: 27378c2ecf20Sopenharmony_ci tomoyo_update_stat(TOMOYO_STAT_POLICY_UPDATES); 27388c2ecf20Sopenharmony_ci break; 27398c2ecf20Sopenharmony_ci default: 27408c2ecf20Sopenharmony_ci break; 27418c2ecf20Sopenharmony_ci } 27428c2ecf20Sopenharmony_ci break; 27438c2ecf20Sopenharmony_ci } 27448c2ecf20Sopenharmony_ci } 27458c2ecf20Sopenharmony_ciout: 27468c2ecf20Sopenharmony_ci tomoyo_read_unlock(idx); 27478c2ecf20Sopenharmony_ci mutex_unlock(&head->io_sem); 27488c2ecf20Sopenharmony_ci return error; 27498c2ecf20Sopenharmony_ci} 27508c2ecf20Sopenharmony_ci 27518c2ecf20Sopenharmony_ci/** 27528c2ecf20Sopenharmony_ci * tomoyo_close_control - close() for /sys/kernel/security/tomoyo/ interface. 27538c2ecf20Sopenharmony_ci * 27548c2ecf20Sopenharmony_ci * @head: Pointer to "struct tomoyo_io_buffer". 27558c2ecf20Sopenharmony_ci */ 27568c2ecf20Sopenharmony_civoid tomoyo_close_control(struct tomoyo_io_buffer *head) 27578c2ecf20Sopenharmony_ci{ 27588c2ecf20Sopenharmony_ci /* 27598c2ecf20Sopenharmony_ci * If the file is /sys/kernel/security/tomoyo/query , decrement the 27608c2ecf20Sopenharmony_ci * observer counter. 27618c2ecf20Sopenharmony_ci */ 27628c2ecf20Sopenharmony_ci if (head->type == TOMOYO_QUERY && 27638c2ecf20Sopenharmony_ci atomic_dec_and_test(&tomoyo_query_observers)) 27648c2ecf20Sopenharmony_ci wake_up_all(&tomoyo_answer_wait); 27658c2ecf20Sopenharmony_ci tomoyo_notify_gc(head, false); 27668c2ecf20Sopenharmony_ci} 27678c2ecf20Sopenharmony_ci 27688c2ecf20Sopenharmony_ci/** 27698c2ecf20Sopenharmony_ci * tomoyo_check_profile - Check all profiles currently assigned to domains are defined. 27708c2ecf20Sopenharmony_ci */ 27718c2ecf20Sopenharmony_civoid tomoyo_check_profile(void) 27728c2ecf20Sopenharmony_ci{ 27738c2ecf20Sopenharmony_ci struct tomoyo_domain_info *domain; 27748c2ecf20Sopenharmony_ci const int idx = tomoyo_read_lock(); 27758c2ecf20Sopenharmony_ci 27768c2ecf20Sopenharmony_ci tomoyo_policy_loaded = true; 27778c2ecf20Sopenharmony_ci pr_info("TOMOYO: 2.6.0\n"); 27788c2ecf20Sopenharmony_ci list_for_each_entry_rcu(domain, &tomoyo_domain_list, list, 27798c2ecf20Sopenharmony_ci srcu_read_lock_held(&tomoyo_ss)) { 27808c2ecf20Sopenharmony_ci const u8 profile = domain->profile; 27818c2ecf20Sopenharmony_ci struct tomoyo_policy_namespace *ns = domain->ns; 27828c2ecf20Sopenharmony_ci 27838c2ecf20Sopenharmony_ci if (ns->profile_version == 20110903) { 27848c2ecf20Sopenharmony_ci pr_info_once("Converting profile version from %u to %u.\n", 27858c2ecf20Sopenharmony_ci 20110903, 20150505); 27868c2ecf20Sopenharmony_ci ns->profile_version = 20150505; 27878c2ecf20Sopenharmony_ci } 27888c2ecf20Sopenharmony_ci if (ns->profile_version != 20150505) 27898c2ecf20Sopenharmony_ci pr_err("Profile version %u is not supported.\n", 27908c2ecf20Sopenharmony_ci ns->profile_version); 27918c2ecf20Sopenharmony_ci else if (!ns->profile_ptr[profile]) 27928c2ecf20Sopenharmony_ci pr_err("Profile %u (used by '%s') is not defined.\n", 27938c2ecf20Sopenharmony_ci profile, domain->domainname->name); 27948c2ecf20Sopenharmony_ci else 27958c2ecf20Sopenharmony_ci continue; 27968c2ecf20Sopenharmony_ci pr_err("Userland tools for TOMOYO 2.6 must be installed and policy must be initialized.\n"); 27978c2ecf20Sopenharmony_ci pr_err("Please see https://tomoyo.osdn.jp/2.6/ for more information.\n"); 27988c2ecf20Sopenharmony_ci panic("STOP!"); 27998c2ecf20Sopenharmony_ci } 28008c2ecf20Sopenharmony_ci tomoyo_read_unlock(idx); 28018c2ecf20Sopenharmony_ci pr_info("Mandatory Access Control activated.\n"); 28028c2ecf20Sopenharmony_ci} 28038c2ecf20Sopenharmony_ci 28048c2ecf20Sopenharmony_ci/** 28058c2ecf20Sopenharmony_ci * tomoyo_load_builtin_policy - Load built-in policy. 28068c2ecf20Sopenharmony_ci * 28078c2ecf20Sopenharmony_ci * Returns nothing. 28088c2ecf20Sopenharmony_ci */ 28098c2ecf20Sopenharmony_civoid __init tomoyo_load_builtin_policy(void) 28108c2ecf20Sopenharmony_ci{ 28118c2ecf20Sopenharmony_ci#ifdef CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING 28128c2ecf20Sopenharmony_ci static char tomoyo_builtin_profile[] __initdata = 28138c2ecf20Sopenharmony_ci "PROFILE_VERSION=20150505\n" 28148c2ecf20Sopenharmony_ci "0-CONFIG={ mode=learning grant_log=no reject_log=yes }\n"; 28158c2ecf20Sopenharmony_ci static char tomoyo_builtin_exception_policy[] __initdata = 28168c2ecf20Sopenharmony_ci "aggregator proc:/self/exe /proc/self/exe\n"; 28178c2ecf20Sopenharmony_ci static char tomoyo_builtin_domain_policy[] __initdata = ""; 28188c2ecf20Sopenharmony_ci static char tomoyo_builtin_manager[] __initdata = ""; 28198c2ecf20Sopenharmony_ci static char tomoyo_builtin_stat[] __initdata = ""; 28208c2ecf20Sopenharmony_ci#else 28218c2ecf20Sopenharmony_ci /* 28228c2ecf20Sopenharmony_ci * This include file is manually created and contains built-in policy 28238c2ecf20Sopenharmony_ci * named "tomoyo_builtin_profile", "tomoyo_builtin_exception_policy", 28248c2ecf20Sopenharmony_ci * "tomoyo_builtin_domain_policy", "tomoyo_builtin_manager", 28258c2ecf20Sopenharmony_ci * "tomoyo_builtin_stat" in the form of "static char [] __initdata". 28268c2ecf20Sopenharmony_ci */ 28278c2ecf20Sopenharmony_ci#include "builtin-policy.h" 28288c2ecf20Sopenharmony_ci#endif 28298c2ecf20Sopenharmony_ci u8 i; 28308c2ecf20Sopenharmony_ci const int idx = tomoyo_read_lock(); 28318c2ecf20Sopenharmony_ci 28328c2ecf20Sopenharmony_ci for (i = 0; i < 5; i++) { 28338c2ecf20Sopenharmony_ci struct tomoyo_io_buffer head = { }; 28348c2ecf20Sopenharmony_ci char *start = ""; 28358c2ecf20Sopenharmony_ci 28368c2ecf20Sopenharmony_ci switch (i) { 28378c2ecf20Sopenharmony_ci case 0: 28388c2ecf20Sopenharmony_ci start = tomoyo_builtin_profile; 28398c2ecf20Sopenharmony_ci head.type = TOMOYO_PROFILE; 28408c2ecf20Sopenharmony_ci head.write = tomoyo_write_profile; 28418c2ecf20Sopenharmony_ci break; 28428c2ecf20Sopenharmony_ci case 1: 28438c2ecf20Sopenharmony_ci start = tomoyo_builtin_exception_policy; 28448c2ecf20Sopenharmony_ci head.type = TOMOYO_EXCEPTIONPOLICY; 28458c2ecf20Sopenharmony_ci head.write = tomoyo_write_exception; 28468c2ecf20Sopenharmony_ci break; 28478c2ecf20Sopenharmony_ci case 2: 28488c2ecf20Sopenharmony_ci start = tomoyo_builtin_domain_policy; 28498c2ecf20Sopenharmony_ci head.type = TOMOYO_DOMAINPOLICY; 28508c2ecf20Sopenharmony_ci head.write = tomoyo_write_domain; 28518c2ecf20Sopenharmony_ci break; 28528c2ecf20Sopenharmony_ci case 3: 28538c2ecf20Sopenharmony_ci start = tomoyo_builtin_manager; 28548c2ecf20Sopenharmony_ci head.type = TOMOYO_MANAGER; 28558c2ecf20Sopenharmony_ci head.write = tomoyo_write_manager; 28568c2ecf20Sopenharmony_ci break; 28578c2ecf20Sopenharmony_ci case 4: 28588c2ecf20Sopenharmony_ci start = tomoyo_builtin_stat; 28598c2ecf20Sopenharmony_ci head.type = TOMOYO_STAT; 28608c2ecf20Sopenharmony_ci head.write = tomoyo_write_stat; 28618c2ecf20Sopenharmony_ci break; 28628c2ecf20Sopenharmony_ci } 28638c2ecf20Sopenharmony_ci while (1) { 28648c2ecf20Sopenharmony_ci char *end = strchr(start, '\n'); 28658c2ecf20Sopenharmony_ci 28668c2ecf20Sopenharmony_ci if (!end) 28678c2ecf20Sopenharmony_ci break; 28688c2ecf20Sopenharmony_ci *end = '\0'; 28698c2ecf20Sopenharmony_ci tomoyo_normalize_line(start); 28708c2ecf20Sopenharmony_ci head.write_buf = start; 28718c2ecf20Sopenharmony_ci tomoyo_parse_policy(&head, start); 28728c2ecf20Sopenharmony_ci start = end + 1; 28738c2ecf20Sopenharmony_ci } 28748c2ecf20Sopenharmony_ci } 28758c2ecf20Sopenharmony_ci tomoyo_read_unlock(idx); 28768c2ecf20Sopenharmony_ci#ifdef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER 28778c2ecf20Sopenharmony_ci tomoyo_check_profile(); 28788c2ecf20Sopenharmony_ci#endif 28798c2ecf20Sopenharmony_ci} 2880