18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * security/tomoyo/util.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2005-2011 NTT DATA CORPORATION 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/slab.h> 98c2ecf20Sopenharmony_ci#include <linux/rculist.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "common.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* Lock for protecting policy. */ 148c2ecf20Sopenharmony_ciDEFINE_MUTEX(tomoyo_policy_lock); 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* Has /sbin/init started? */ 178c2ecf20Sopenharmony_cibool tomoyo_policy_loaded; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci/* 208c2ecf20Sopenharmony_ci * Mapping table from "enum tomoyo_mac_index" to 218c2ecf20Sopenharmony_ci * "enum tomoyo_mac_category_index". 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ciconst u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX] = { 248c2ecf20Sopenharmony_ci /* CONFIG::file group */ 258c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_EXECUTE] = TOMOYO_MAC_CATEGORY_FILE, 268c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_OPEN] = TOMOYO_MAC_CATEGORY_FILE, 278c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_CREATE] = TOMOYO_MAC_CATEGORY_FILE, 288c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_UNLINK] = TOMOYO_MAC_CATEGORY_FILE, 298c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_GETATTR] = TOMOYO_MAC_CATEGORY_FILE, 308c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_MKDIR] = TOMOYO_MAC_CATEGORY_FILE, 318c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_RMDIR] = TOMOYO_MAC_CATEGORY_FILE, 328c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_MKFIFO] = TOMOYO_MAC_CATEGORY_FILE, 338c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_MKSOCK] = TOMOYO_MAC_CATEGORY_FILE, 348c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_TRUNCATE] = TOMOYO_MAC_CATEGORY_FILE, 358c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_SYMLINK] = TOMOYO_MAC_CATEGORY_FILE, 368c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_MKBLOCK] = TOMOYO_MAC_CATEGORY_FILE, 378c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_MKCHAR] = TOMOYO_MAC_CATEGORY_FILE, 388c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_LINK] = TOMOYO_MAC_CATEGORY_FILE, 398c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_RENAME] = TOMOYO_MAC_CATEGORY_FILE, 408c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_CHMOD] = TOMOYO_MAC_CATEGORY_FILE, 418c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_CHOWN] = TOMOYO_MAC_CATEGORY_FILE, 428c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_CHGRP] = TOMOYO_MAC_CATEGORY_FILE, 438c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_IOCTL] = TOMOYO_MAC_CATEGORY_FILE, 448c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_CHROOT] = TOMOYO_MAC_CATEGORY_FILE, 458c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_MOUNT] = TOMOYO_MAC_CATEGORY_FILE, 468c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_UMOUNT] = TOMOYO_MAC_CATEGORY_FILE, 478c2ecf20Sopenharmony_ci [TOMOYO_MAC_FILE_PIVOT_ROOT] = TOMOYO_MAC_CATEGORY_FILE, 488c2ecf20Sopenharmony_ci /* CONFIG::network group */ 498c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_STREAM_BIND] = 508c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 518c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN] = 528c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 538c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT] = 548c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 558c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_DGRAM_BIND] = 568c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 578c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_DGRAM_SEND] = 588c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 598c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_RAW_BIND] = 608c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 618c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_INET_RAW_SEND] = 628c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 638c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND] = 648c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 658c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN] = 668c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 678c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT] = 688c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 698c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND] = 708c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 718c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND] = 728c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 738c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND] = 748c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 758c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] = 768c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 778c2ecf20Sopenharmony_ci [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] = 788c2ecf20Sopenharmony_ci TOMOYO_MAC_CATEGORY_NETWORK, 798c2ecf20Sopenharmony_ci /* CONFIG::misc group */ 808c2ecf20Sopenharmony_ci [TOMOYO_MAC_ENVIRON] = TOMOYO_MAC_CATEGORY_MISC, 818c2ecf20Sopenharmony_ci}; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci/** 848c2ecf20Sopenharmony_ci * tomoyo_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss. 858c2ecf20Sopenharmony_ci * 868c2ecf20Sopenharmony_ci * @time: Seconds since 1970/01/01 00:00:00. 878c2ecf20Sopenharmony_ci * @stamp: Pointer to "struct tomoyo_time". 888c2ecf20Sopenharmony_ci * 898c2ecf20Sopenharmony_ci * Returns nothing. 908c2ecf20Sopenharmony_ci */ 918c2ecf20Sopenharmony_civoid tomoyo_convert_time(time64_t time64, struct tomoyo_time *stamp) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci struct tm tm; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci time64_to_tm(time64, 0, &tm); 968c2ecf20Sopenharmony_ci stamp->sec = tm.tm_sec; 978c2ecf20Sopenharmony_ci stamp->min = tm.tm_min; 988c2ecf20Sopenharmony_ci stamp->hour = tm.tm_hour; 998c2ecf20Sopenharmony_ci stamp->day = tm.tm_mday; 1008c2ecf20Sopenharmony_ci stamp->month = tm.tm_mon + 1; 1018c2ecf20Sopenharmony_ci stamp->year = tm.tm_year + 1900; 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci/** 1058c2ecf20Sopenharmony_ci * tomoyo_permstr - Find permission keywords. 1068c2ecf20Sopenharmony_ci * 1078c2ecf20Sopenharmony_ci * @string: String representation for permissions in foo/bar/buz format. 1088c2ecf20Sopenharmony_ci * @keyword: Keyword to find from @string/ 1098c2ecf20Sopenharmony_ci * 1108c2ecf20Sopenharmony_ci * Returns true if @keyword was found in @string, false otherwise. 1118c2ecf20Sopenharmony_ci * 1128c2ecf20Sopenharmony_ci * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2. 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_cibool tomoyo_permstr(const char *string, const char *keyword) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci const char *cp = strstr(string, keyword); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci if (cp) 1198c2ecf20Sopenharmony_ci return cp == string || *(cp - 1) == '/'; 1208c2ecf20Sopenharmony_ci return false; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci/** 1248c2ecf20Sopenharmony_ci * tomoyo_read_token - Read a word from a line. 1258c2ecf20Sopenharmony_ci * 1268c2ecf20Sopenharmony_ci * @param: Pointer to "struct tomoyo_acl_param". 1278c2ecf20Sopenharmony_ci * 1288c2ecf20Sopenharmony_ci * Returns a word on success, "" otherwise. 1298c2ecf20Sopenharmony_ci * 1308c2ecf20Sopenharmony_ci * To allow the caller to skip NULL check, this function returns "" rather than 1318c2ecf20Sopenharmony_ci * NULL if there is no more words to read. 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_cichar *tomoyo_read_token(struct tomoyo_acl_param *param) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci char *pos = param->data; 1368c2ecf20Sopenharmony_ci char *del = strchr(pos, ' '); 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci if (del) 1398c2ecf20Sopenharmony_ci *del++ = '\0'; 1408c2ecf20Sopenharmony_ci else 1418c2ecf20Sopenharmony_ci del = pos + strlen(pos); 1428c2ecf20Sopenharmony_ci param->data = del; 1438c2ecf20Sopenharmony_ci return pos; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic bool tomoyo_correct_path2(const char *filename, const size_t len); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci/** 1498c2ecf20Sopenharmony_ci * tomoyo_get_domainname - Read a domainname from a line. 1508c2ecf20Sopenharmony_ci * 1518c2ecf20Sopenharmony_ci * @param: Pointer to "struct tomoyo_acl_param". 1528c2ecf20Sopenharmony_ci * 1538c2ecf20Sopenharmony_ci * Returns a domainname on success, NULL otherwise. 1548c2ecf20Sopenharmony_ci */ 1558c2ecf20Sopenharmony_ciconst struct tomoyo_path_info *tomoyo_get_domainname 1568c2ecf20Sopenharmony_ci(struct tomoyo_acl_param *param) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci char *start = param->data; 1598c2ecf20Sopenharmony_ci char *pos = start; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci while (*pos) { 1628c2ecf20Sopenharmony_ci if (*pos++ != ' ' || 1638c2ecf20Sopenharmony_ci tomoyo_correct_path2(pos, strchrnul(pos, ' ') - pos)) 1648c2ecf20Sopenharmony_ci continue; 1658c2ecf20Sopenharmony_ci *(pos - 1) = '\0'; 1668c2ecf20Sopenharmony_ci break; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci param->data = pos; 1698c2ecf20Sopenharmony_ci if (tomoyo_correct_domain(start)) 1708c2ecf20Sopenharmony_ci return tomoyo_get_name(start); 1718c2ecf20Sopenharmony_ci return NULL; 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci/** 1758c2ecf20Sopenharmony_ci * tomoyo_parse_ulong - Parse an "unsigned long" value. 1768c2ecf20Sopenharmony_ci * 1778c2ecf20Sopenharmony_ci * @result: Pointer to "unsigned long". 1788c2ecf20Sopenharmony_ci * @str: Pointer to string to parse. 1798c2ecf20Sopenharmony_ci * 1808c2ecf20Sopenharmony_ci * Returns one of values in "enum tomoyo_value_type". 1818c2ecf20Sopenharmony_ci * 1828c2ecf20Sopenharmony_ci * The @src is updated to point the first character after the value 1838c2ecf20Sopenharmony_ci * on success. 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ciu8 tomoyo_parse_ulong(unsigned long *result, char **str) 1868c2ecf20Sopenharmony_ci{ 1878c2ecf20Sopenharmony_ci const char *cp = *str; 1888c2ecf20Sopenharmony_ci char *ep; 1898c2ecf20Sopenharmony_ci int base = 10; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci if (*cp == '0') { 1928c2ecf20Sopenharmony_ci char c = *(cp + 1); 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci if (c == 'x' || c == 'X') { 1958c2ecf20Sopenharmony_ci base = 16; 1968c2ecf20Sopenharmony_ci cp += 2; 1978c2ecf20Sopenharmony_ci } else if (c >= '0' && c <= '7') { 1988c2ecf20Sopenharmony_ci base = 8; 1998c2ecf20Sopenharmony_ci cp++; 2008c2ecf20Sopenharmony_ci } 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci *result = simple_strtoul(cp, &ep, base); 2038c2ecf20Sopenharmony_ci if (cp == ep) 2048c2ecf20Sopenharmony_ci return TOMOYO_VALUE_TYPE_INVALID; 2058c2ecf20Sopenharmony_ci *str = ep; 2068c2ecf20Sopenharmony_ci switch (base) { 2078c2ecf20Sopenharmony_ci case 16: 2088c2ecf20Sopenharmony_ci return TOMOYO_VALUE_TYPE_HEXADECIMAL; 2098c2ecf20Sopenharmony_ci case 8: 2108c2ecf20Sopenharmony_ci return TOMOYO_VALUE_TYPE_OCTAL; 2118c2ecf20Sopenharmony_ci default: 2128c2ecf20Sopenharmony_ci return TOMOYO_VALUE_TYPE_DECIMAL; 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci/** 2178c2ecf20Sopenharmony_ci * tomoyo_print_ulong - Print an "unsigned long" value. 2188c2ecf20Sopenharmony_ci * 2198c2ecf20Sopenharmony_ci * @buffer: Pointer to buffer. 2208c2ecf20Sopenharmony_ci * @buffer_len: Size of @buffer. 2218c2ecf20Sopenharmony_ci * @value: An "unsigned long" value. 2228c2ecf20Sopenharmony_ci * @type: Type of @value. 2238c2ecf20Sopenharmony_ci * 2248c2ecf20Sopenharmony_ci * Returns nothing. 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_civoid tomoyo_print_ulong(char *buffer, const int buffer_len, 2278c2ecf20Sopenharmony_ci const unsigned long value, const u8 type) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci if (type == TOMOYO_VALUE_TYPE_DECIMAL) 2308c2ecf20Sopenharmony_ci snprintf(buffer, buffer_len, "%lu", value); 2318c2ecf20Sopenharmony_ci else if (type == TOMOYO_VALUE_TYPE_OCTAL) 2328c2ecf20Sopenharmony_ci snprintf(buffer, buffer_len, "0%lo", value); 2338c2ecf20Sopenharmony_ci else if (type == TOMOYO_VALUE_TYPE_HEXADECIMAL) 2348c2ecf20Sopenharmony_ci snprintf(buffer, buffer_len, "0x%lX", value); 2358c2ecf20Sopenharmony_ci else 2368c2ecf20Sopenharmony_ci snprintf(buffer, buffer_len, "type(%u)", type); 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci/** 2408c2ecf20Sopenharmony_ci * tomoyo_parse_name_union - Parse a tomoyo_name_union. 2418c2ecf20Sopenharmony_ci * 2428c2ecf20Sopenharmony_ci * @param: Pointer to "struct tomoyo_acl_param". 2438c2ecf20Sopenharmony_ci * @ptr: Pointer to "struct tomoyo_name_union". 2448c2ecf20Sopenharmony_ci * 2458c2ecf20Sopenharmony_ci * Returns true on success, false otherwise. 2468c2ecf20Sopenharmony_ci */ 2478c2ecf20Sopenharmony_cibool tomoyo_parse_name_union(struct tomoyo_acl_param *param, 2488c2ecf20Sopenharmony_ci struct tomoyo_name_union *ptr) 2498c2ecf20Sopenharmony_ci{ 2508c2ecf20Sopenharmony_ci char *filename; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci if (param->data[0] == '@') { 2538c2ecf20Sopenharmony_ci param->data++; 2548c2ecf20Sopenharmony_ci ptr->group = tomoyo_get_group(param, TOMOYO_PATH_GROUP); 2558c2ecf20Sopenharmony_ci return ptr->group != NULL; 2568c2ecf20Sopenharmony_ci } 2578c2ecf20Sopenharmony_ci filename = tomoyo_read_token(param); 2588c2ecf20Sopenharmony_ci if (!tomoyo_correct_word(filename)) 2598c2ecf20Sopenharmony_ci return false; 2608c2ecf20Sopenharmony_ci ptr->filename = tomoyo_get_name(filename); 2618c2ecf20Sopenharmony_ci return ptr->filename != NULL; 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci/** 2658c2ecf20Sopenharmony_ci * tomoyo_parse_number_union - Parse a tomoyo_number_union. 2668c2ecf20Sopenharmony_ci * 2678c2ecf20Sopenharmony_ci * @param: Pointer to "struct tomoyo_acl_param". 2688c2ecf20Sopenharmony_ci * @ptr: Pointer to "struct tomoyo_number_union". 2698c2ecf20Sopenharmony_ci * 2708c2ecf20Sopenharmony_ci * Returns true on success, false otherwise. 2718c2ecf20Sopenharmony_ci */ 2728c2ecf20Sopenharmony_cibool tomoyo_parse_number_union(struct tomoyo_acl_param *param, 2738c2ecf20Sopenharmony_ci struct tomoyo_number_union *ptr) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci char *data; 2768c2ecf20Sopenharmony_ci u8 type; 2778c2ecf20Sopenharmony_ci unsigned long v; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci memset(ptr, 0, sizeof(*ptr)); 2808c2ecf20Sopenharmony_ci if (param->data[0] == '@') { 2818c2ecf20Sopenharmony_ci param->data++; 2828c2ecf20Sopenharmony_ci ptr->group = tomoyo_get_group(param, TOMOYO_NUMBER_GROUP); 2838c2ecf20Sopenharmony_ci return ptr->group != NULL; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci data = tomoyo_read_token(param); 2868c2ecf20Sopenharmony_ci type = tomoyo_parse_ulong(&v, &data); 2878c2ecf20Sopenharmony_ci if (type == TOMOYO_VALUE_TYPE_INVALID) 2888c2ecf20Sopenharmony_ci return false; 2898c2ecf20Sopenharmony_ci ptr->values[0] = v; 2908c2ecf20Sopenharmony_ci ptr->value_type[0] = type; 2918c2ecf20Sopenharmony_ci if (!*data) { 2928c2ecf20Sopenharmony_ci ptr->values[1] = v; 2938c2ecf20Sopenharmony_ci ptr->value_type[1] = type; 2948c2ecf20Sopenharmony_ci return true; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci if (*data++ != '-') 2978c2ecf20Sopenharmony_ci return false; 2988c2ecf20Sopenharmony_ci type = tomoyo_parse_ulong(&v, &data); 2998c2ecf20Sopenharmony_ci if (type == TOMOYO_VALUE_TYPE_INVALID || *data || ptr->values[0] > v) 3008c2ecf20Sopenharmony_ci return false; 3018c2ecf20Sopenharmony_ci ptr->values[1] = v; 3028c2ecf20Sopenharmony_ci ptr->value_type[1] = type; 3038c2ecf20Sopenharmony_ci return true; 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci/** 3078c2ecf20Sopenharmony_ci * tomoyo_byte_range - Check whether the string is a \ooo style octal value. 3088c2ecf20Sopenharmony_ci * 3098c2ecf20Sopenharmony_ci * @str: Pointer to the string. 3108c2ecf20Sopenharmony_ci * 3118c2ecf20Sopenharmony_ci * Returns true if @str is a \ooo style octal value, false otherwise. 3128c2ecf20Sopenharmony_ci * 3138c2ecf20Sopenharmony_ci * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF. 3148c2ecf20Sopenharmony_ci * This function verifies that \ooo is in valid range. 3158c2ecf20Sopenharmony_ci */ 3168c2ecf20Sopenharmony_cistatic inline bool tomoyo_byte_range(const char *str) 3178c2ecf20Sopenharmony_ci{ 3188c2ecf20Sopenharmony_ci return *str >= '0' && *str++ <= '3' && 3198c2ecf20Sopenharmony_ci *str >= '0' && *str++ <= '7' && 3208c2ecf20Sopenharmony_ci *str >= '0' && *str <= '7'; 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci/** 3248c2ecf20Sopenharmony_ci * tomoyo_alphabet_char - Check whether the character is an alphabet. 3258c2ecf20Sopenharmony_ci * 3268c2ecf20Sopenharmony_ci * @c: The character to check. 3278c2ecf20Sopenharmony_ci * 3288c2ecf20Sopenharmony_ci * Returns true if @c is an alphabet character, false otherwise. 3298c2ecf20Sopenharmony_ci */ 3308c2ecf20Sopenharmony_cistatic inline bool tomoyo_alphabet_char(const char c) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci/** 3368c2ecf20Sopenharmony_ci * tomoyo_make_byte - Make byte value from three octal characters. 3378c2ecf20Sopenharmony_ci * 3388c2ecf20Sopenharmony_ci * @c1: The first character. 3398c2ecf20Sopenharmony_ci * @c2: The second character. 3408c2ecf20Sopenharmony_ci * @c3: The third character. 3418c2ecf20Sopenharmony_ci * 3428c2ecf20Sopenharmony_ci * Returns byte value. 3438c2ecf20Sopenharmony_ci */ 3448c2ecf20Sopenharmony_cistatic inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0'); 3478c2ecf20Sopenharmony_ci} 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci/** 3508c2ecf20Sopenharmony_ci * tomoyo_valid - Check whether the character is a valid char. 3518c2ecf20Sopenharmony_ci * 3528c2ecf20Sopenharmony_ci * @c: The character to check. 3538c2ecf20Sopenharmony_ci * 3548c2ecf20Sopenharmony_ci * Returns true if @c is a valid character, false otherwise. 3558c2ecf20Sopenharmony_ci */ 3568c2ecf20Sopenharmony_cistatic inline bool tomoyo_valid(const unsigned char c) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci return c > ' ' && c < 127; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci/** 3628c2ecf20Sopenharmony_ci * tomoyo_invalid - Check whether the character is an invalid char. 3638c2ecf20Sopenharmony_ci * 3648c2ecf20Sopenharmony_ci * @c: The character to check. 3658c2ecf20Sopenharmony_ci * 3668c2ecf20Sopenharmony_ci * Returns true if @c is an invalid character, false otherwise. 3678c2ecf20Sopenharmony_ci */ 3688c2ecf20Sopenharmony_cistatic inline bool tomoyo_invalid(const unsigned char c) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci return c && (c <= ' ' || c >= 127); 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci/** 3748c2ecf20Sopenharmony_ci * tomoyo_str_starts - Check whether the given string starts with the given keyword. 3758c2ecf20Sopenharmony_ci * 3768c2ecf20Sopenharmony_ci * @src: Pointer to pointer to the string. 3778c2ecf20Sopenharmony_ci * @find: Pointer to the keyword. 3788c2ecf20Sopenharmony_ci * 3798c2ecf20Sopenharmony_ci * Returns true if @src starts with @find, false otherwise. 3808c2ecf20Sopenharmony_ci * 3818c2ecf20Sopenharmony_ci * The @src is updated to point the first character after the @find 3828c2ecf20Sopenharmony_ci * if @src starts with @find. 3838c2ecf20Sopenharmony_ci */ 3848c2ecf20Sopenharmony_cibool tomoyo_str_starts(char **src, const char *find) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci const int len = strlen(find); 3878c2ecf20Sopenharmony_ci char *tmp = *src; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci if (strncmp(tmp, find, len)) 3908c2ecf20Sopenharmony_ci return false; 3918c2ecf20Sopenharmony_ci tmp += len; 3928c2ecf20Sopenharmony_ci *src = tmp; 3938c2ecf20Sopenharmony_ci return true; 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci/** 3978c2ecf20Sopenharmony_ci * tomoyo_normalize_line - Format string. 3988c2ecf20Sopenharmony_ci * 3998c2ecf20Sopenharmony_ci * @buffer: The line to normalize. 4008c2ecf20Sopenharmony_ci * 4018c2ecf20Sopenharmony_ci * Leading and trailing whitespaces are removed. 4028c2ecf20Sopenharmony_ci * Multiple whitespaces are packed into single space. 4038c2ecf20Sopenharmony_ci * 4048c2ecf20Sopenharmony_ci * Returns nothing. 4058c2ecf20Sopenharmony_ci */ 4068c2ecf20Sopenharmony_civoid tomoyo_normalize_line(unsigned char *buffer) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci unsigned char *sp = buffer; 4098c2ecf20Sopenharmony_ci unsigned char *dp = buffer; 4108c2ecf20Sopenharmony_ci bool first = true; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci while (tomoyo_invalid(*sp)) 4138c2ecf20Sopenharmony_ci sp++; 4148c2ecf20Sopenharmony_ci while (*sp) { 4158c2ecf20Sopenharmony_ci if (!first) 4168c2ecf20Sopenharmony_ci *dp++ = ' '; 4178c2ecf20Sopenharmony_ci first = false; 4188c2ecf20Sopenharmony_ci while (tomoyo_valid(*sp)) 4198c2ecf20Sopenharmony_ci *dp++ = *sp++; 4208c2ecf20Sopenharmony_ci while (tomoyo_invalid(*sp)) 4218c2ecf20Sopenharmony_ci sp++; 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci *dp = '\0'; 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci/** 4278c2ecf20Sopenharmony_ci * tomoyo_correct_word2 - Validate a string. 4288c2ecf20Sopenharmony_ci * 4298c2ecf20Sopenharmony_ci * @string: The string to check. Maybe non-'\0'-terminated. 4308c2ecf20Sopenharmony_ci * @len: Length of @string. 4318c2ecf20Sopenharmony_ci * 4328c2ecf20Sopenharmony_ci * Check whether the given string follows the naming rules. 4338c2ecf20Sopenharmony_ci * Returns true if @string follows the naming rules, false otherwise. 4348c2ecf20Sopenharmony_ci */ 4358c2ecf20Sopenharmony_cistatic bool tomoyo_correct_word2(const char *string, size_t len) 4368c2ecf20Sopenharmony_ci{ 4378c2ecf20Sopenharmony_ci const char *const start = string; 4388c2ecf20Sopenharmony_ci bool in_repetition = false; 4398c2ecf20Sopenharmony_ci unsigned char c; 4408c2ecf20Sopenharmony_ci unsigned char d; 4418c2ecf20Sopenharmony_ci unsigned char e; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci if (!len) 4448c2ecf20Sopenharmony_ci goto out; 4458c2ecf20Sopenharmony_ci while (len--) { 4468c2ecf20Sopenharmony_ci c = *string++; 4478c2ecf20Sopenharmony_ci if (c == '\\') { 4488c2ecf20Sopenharmony_ci if (!len--) 4498c2ecf20Sopenharmony_ci goto out; 4508c2ecf20Sopenharmony_ci c = *string++; 4518c2ecf20Sopenharmony_ci switch (c) { 4528c2ecf20Sopenharmony_ci case '\\': /* "\\" */ 4538c2ecf20Sopenharmony_ci continue; 4548c2ecf20Sopenharmony_ci case '$': /* "\$" */ 4558c2ecf20Sopenharmony_ci case '+': /* "\+" */ 4568c2ecf20Sopenharmony_ci case '?': /* "\?" */ 4578c2ecf20Sopenharmony_ci case '*': /* "\*" */ 4588c2ecf20Sopenharmony_ci case '@': /* "\@" */ 4598c2ecf20Sopenharmony_ci case 'x': /* "\x" */ 4608c2ecf20Sopenharmony_ci case 'X': /* "\X" */ 4618c2ecf20Sopenharmony_ci case 'a': /* "\a" */ 4628c2ecf20Sopenharmony_ci case 'A': /* "\A" */ 4638c2ecf20Sopenharmony_ci case '-': /* "\-" */ 4648c2ecf20Sopenharmony_ci continue; 4658c2ecf20Sopenharmony_ci case '{': /* "/\{" */ 4668c2ecf20Sopenharmony_ci if (string - 3 < start || *(string - 3) != '/') 4678c2ecf20Sopenharmony_ci break; 4688c2ecf20Sopenharmony_ci in_repetition = true; 4698c2ecf20Sopenharmony_ci continue; 4708c2ecf20Sopenharmony_ci case '}': /* "\}/" */ 4718c2ecf20Sopenharmony_ci if (*string != '/') 4728c2ecf20Sopenharmony_ci break; 4738c2ecf20Sopenharmony_ci if (!in_repetition) 4748c2ecf20Sopenharmony_ci break; 4758c2ecf20Sopenharmony_ci in_repetition = false; 4768c2ecf20Sopenharmony_ci continue; 4778c2ecf20Sopenharmony_ci case '0': /* "\ooo" */ 4788c2ecf20Sopenharmony_ci case '1': 4798c2ecf20Sopenharmony_ci case '2': 4808c2ecf20Sopenharmony_ci case '3': 4818c2ecf20Sopenharmony_ci if (!len-- || !len--) 4828c2ecf20Sopenharmony_ci break; 4838c2ecf20Sopenharmony_ci d = *string++; 4848c2ecf20Sopenharmony_ci e = *string++; 4858c2ecf20Sopenharmony_ci if (d < '0' || d > '7' || e < '0' || e > '7') 4868c2ecf20Sopenharmony_ci break; 4878c2ecf20Sopenharmony_ci c = tomoyo_make_byte(c, d, e); 4888c2ecf20Sopenharmony_ci if (c <= ' ' || c >= 127) 4898c2ecf20Sopenharmony_ci continue; 4908c2ecf20Sopenharmony_ci } 4918c2ecf20Sopenharmony_ci goto out; 4928c2ecf20Sopenharmony_ci } else if (in_repetition && c == '/') { 4938c2ecf20Sopenharmony_ci goto out; 4948c2ecf20Sopenharmony_ci } else if (c <= ' ' || c >= 127) { 4958c2ecf20Sopenharmony_ci goto out; 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci } 4988c2ecf20Sopenharmony_ci if (in_repetition) 4998c2ecf20Sopenharmony_ci goto out; 5008c2ecf20Sopenharmony_ci return true; 5018c2ecf20Sopenharmony_ci out: 5028c2ecf20Sopenharmony_ci return false; 5038c2ecf20Sopenharmony_ci} 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci/** 5068c2ecf20Sopenharmony_ci * tomoyo_correct_word - Validate a string. 5078c2ecf20Sopenharmony_ci * 5088c2ecf20Sopenharmony_ci * @string: The string to check. 5098c2ecf20Sopenharmony_ci * 5108c2ecf20Sopenharmony_ci * Check whether the given string follows the naming rules. 5118c2ecf20Sopenharmony_ci * Returns true if @string follows the naming rules, false otherwise. 5128c2ecf20Sopenharmony_ci */ 5138c2ecf20Sopenharmony_cibool tomoyo_correct_word(const char *string) 5148c2ecf20Sopenharmony_ci{ 5158c2ecf20Sopenharmony_ci return tomoyo_correct_word2(string, strlen(string)); 5168c2ecf20Sopenharmony_ci} 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci/** 5198c2ecf20Sopenharmony_ci * tomoyo_correct_path2 - Check whether the given pathname follows the naming rules. 5208c2ecf20Sopenharmony_ci * 5218c2ecf20Sopenharmony_ci * @filename: The pathname to check. 5228c2ecf20Sopenharmony_ci * @len: Length of @filename. 5238c2ecf20Sopenharmony_ci * 5248c2ecf20Sopenharmony_ci * Returns true if @filename follows the naming rules, false otherwise. 5258c2ecf20Sopenharmony_ci */ 5268c2ecf20Sopenharmony_cistatic bool tomoyo_correct_path2(const char *filename, const size_t len) 5278c2ecf20Sopenharmony_ci{ 5288c2ecf20Sopenharmony_ci const char *cp1 = memchr(filename, '/', len); 5298c2ecf20Sopenharmony_ci const char *cp2 = memchr(filename, '.', len); 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci return cp1 && (!cp2 || (cp1 < cp2)) && tomoyo_correct_word2(filename, len); 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci/** 5358c2ecf20Sopenharmony_ci * tomoyo_correct_path - Validate a pathname. 5368c2ecf20Sopenharmony_ci * 5378c2ecf20Sopenharmony_ci * @filename: The pathname to check. 5388c2ecf20Sopenharmony_ci * 5398c2ecf20Sopenharmony_ci * Check whether the given pathname follows the naming rules. 5408c2ecf20Sopenharmony_ci * Returns true if @filename follows the naming rules, false otherwise. 5418c2ecf20Sopenharmony_ci */ 5428c2ecf20Sopenharmony_cibool tomoyo_correct_path(const char *filename) 5438c2ecf20Sopenharmony_ci{ 5448c2ecf20Sopenharmony_ci return tomoyo_correct_path2(filename, strlen(filename)); 5458c2ecf20Sopenharmony_ci} 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci/** 5488c2ecf20Sopenharmony_ci * tomoyo_correct_domain - Check whether the given domainname follows the naming rules. 5498c2ecf20Sopenharmony_ci * 5508c2ecf20Sopenharmony_ci * @domainname: The domainname to check. 5518c2ecf20Sopenharmony_ci * 5528c2ecf20Sopenharmony_ci * Returns true if @domainname follows the naming rules, false otherwise. 5538c2ecf20Sopenharmony_ci */ 5548c2ecf20Sopenharmony_cibool tomoyo_correct_domain(const unsigned char *domainname) 5558c2ecf20Sopenharmony_ci{ 5568c2ecf20Sopenharmony_ci if (!domainname || !tomoyo_domain_def(domainname)) 5578c2ecf20Sopenharmony_ci return false; 5588c2ecf20Sopenharmony_ci domainname = strchr(domainname, ' '); 5598c2ecf20Sopenharmony_ci if (!domainname++) 5608c2ecf20Sopenharmony_ci return true; 5618c2ecf20Sopenharmony_ci while (1) { 5628c2ecf20Sopenharmony_ci const unsigned char *cp = strchr(domainname, ' '); 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci if (!cp) 5658c2ecf20Sopenharmony_ci break; 5668c2ecf20Sopenharmony_ci if (!tomoyo_correct_path2(domainname, cp - domainname)) 5678c2ecf20Sopenharmony_ci return false; 5688c2ecf20Sopenharmony_ci domainname = cp + 1; 5698c2ecf20Sopenharmony_ci } 5708c2ecf20Sopenharmony_ci return tomoyo_correct_path(domainname); 5718c2ecf20Sopenharmony_ci} 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci/** 5748c2ecf20Sopenharmony_ci * tomoyo_domain_def - Check whether the given token can be a domainname. 5758c2ecf20Sopenharmony_ci * 5768c2ecf20Sopenharmony_ci * @buffer: The token to check. 5778c2ecf20Sopenharmony_ci * 5788c2ecf20Sopenharmony_ci * Returns true if @buffer possibly be a domainname, false otherwise. 5798c2ecf20Sopenharmony_ci */ 5808c2ecf20Sopenharmony_cibool tomoyo_domain_def(const unsigned char *buffer) 5818c2ecf20Sopenharmony_ci{ 5828c2ecf20Sopenharmony_ci const unsigned char *cp; 5838c2ecf20Sopenharmony_ci int len; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci if (*buffer != '<') 5868c2ecf20Sopenharmony_ci return false; 5878c2ecf20Sopenharmony_ci cp = strchr(buffer, ' '); 5888c2ecf20Sopenharmony_ci if (!cp) 5898c2ecf20Sopenharmony_ci len = strlen(buffer); 5908c2ecf20Sopenharmony_ci else 5918c2ecf20Sopenharmony_ci len = cp - buffer; 5928c2ecf20Sopenharmony_ci if (buffer[len - 1] != '>' || 5938c2ecf20Sopenharmony_ci !tomoyo_correct_word2(buffer + 1, len - 2)) 5948c2ecf20Sopenharmony_ci return false; 5958c2ecf20Sopenharmony_ci return true; 5968c2ecf20Sopenharmony_ci} 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci/** 5998c2ecf20Sopenharmony_ci * tomoyo_find_domain - Find a domain by the given name. 6008c2ecf20Sopenharmony_ci * 6018c2ecf20Sopenharmony_ci * @domainname: The domainname to find. 6028c2ecf20Sopenharmony_ci * 6038c2ecf20Sopenharmony_ci * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise. 6048c2ecf20Sopenharmony_ci * 6058c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 6068c2ecf20Sopenharmony_ci */ 6078c2ecf20Sopenharmony_cistruct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) 6088c2ecf20Sopenharmony_ci{ 6098c2ecf20Sopenharmony_ci struct tomoyo_domain_info *domain; 6108c2ecf20Sopenharmony_ci struct tomoyo_path_info name; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci name.name = domainname; 6138c2ecf20Sopenharmony_ci tomoyo_fill_path_info(&name); 6148c2ecf20Sopenharmony_ci list_for_each_entry_rcu(domain, &tomoyo_domain_list, list, 6158c2ecf20Sopenharmony_ci srcu_read_lock_held(&tomoyo_ss)) { 6168c2ecf20Sopenharmony_ci if (!domain->is_deleted && 6178c2ecf20Sopenharmony_ci !tomoyo_pathcmp(&name, domain->domainname)) 6188c2ecf20Sopenharmony_ci return domain; 6198c2ecf20Sopenharmony_ci } 6208c2ecf20Sopenharmony_ci return NULL; 6218c2ecf20Sopenharmony_ci} 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci/** 6248c2ecf20Sopenharmony_ci * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token. 6258c2ecf20Sopenharmony_ci * 6268c2ecf20Sopenharmony_ci * @filename: The string to evaluate. 6278c2ecf20Sopenharmony_ci * 6288c2ecf20Sopenharmony_ci * Returns the initial length without a pattern in @filename. 6298c2ecf20Sopenharmony_ci */ 6308c2ecf20Sopenharmony_cistatic int tomoyo_const_part_length(const char *filename) 6318c2ecf20Sopenharmony_ci{ 6328c2ecf20Sopenharmony_ci char c; 6338c2ecf20Sopenharmony_ci int len = 0; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci if (!filename) 6368c2ecf20Sopenharmony_ci return 0; 6378c2ecf20Sopenharmony_ci while ((c = *filename++) != '\0') { 6388c2ecf20Sopenharmony_ci if (c != '\\') { 6398c2ecf20Sopenharmony_ci len++; 6408c2ecf20Sopenharmony_ci continue; 6418c2ecf20Sopenharmony_ci } 6428c2ecf20Sopenharmony_ci c = *filename++; 6438c2ecf20Sopenharmony_ci switch (c) { 6448c2ecf20Sopenharmony_ci case '\\': /* "\\" */ 6458c2ecf20Sopenharmony_ci len += 2; 6468c2ecf20Sopenharmony_ci continue; 6478c2ecf20Sopenharmony_ci case '0': /* "\ooo" */ 6488c2ecf20Sopenharmony_ci case '1': 6498c2ecf20Sopenharmony_ci case '2': 6508c2ecf20Sopenharmony_ci case '3': 6518c2ecf20Sopenharmony_ci c = *filename++; 6528c2ecf20Sopenharmony_ci if (c < '0' || c > '7') 6538c2ecf20Sopenharmony_ci break; 6548c2ecf20Sopenharmony_ci c = *filename++; 6558c2ecf20Sopenharmony_ci if (c < '0' || c > '7') 6568c2ecf20Sopenharmony_ci break; 6578c2ecf20Sopenharmony_ci len += 4; 6588c2ecf20Sopenharmony_ci continue; 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci break; 6618c2ecf20Sopenharmony_ci } 6628c2ecf20Sopenharmony_ci return len; 6638c2ecf20Sopenharmony_ci} 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci/** 6668c2ecf20Sopenharmony_ci * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members. 6678c2ecf20Sopenharmony_ci * 6688c2ecf20Sopenharmony_ci * @ptr: Pointer to "struct tomoyo_path_info" to fill in. 6698c2ecf20Sopenharmony_ci * 6708c2ecf20Sopenharmony_ci * The caller sets "struct tomoyo_path_info"->name. 6718c2ecf20Sopenharmony_ci */ 6728c2ecf20Sopenharmony_civoid tomoyo_fill_path_info(struct tomoyo_path_info *ptr) 6738c2ecf20Sopenharmony_ci{ 6748c2ecf20Sopenharmony_ci const char *name = ptr->name; 6758c2ecf20Sopenharmony_ci const int len = strlen(name); 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci ptr->const_len = tomoyo_const_part_length(name); 6788c2ecf20Sopenharmony_ci ptr->is_dir = len && (name[len - 1] == '/'); 6798c2ecf20Sopenharmony_ci ptr->is_patterned = (ptr->const_len < len); 6808c2ecf20Sopenharmony_ci ptr->hash = full_name_hash(NULL, name, len); 6818c2ecf20Sopenharmony_ci} 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci/** 6848c2ecf20Sopenharmony_ci * tomoyo_file_matches_pattern2 - Pattern matching without '/' character and "\-" pattern. 6858c2ecf20Sopenharmony_ci * 6868c2ecf20Sopenharmony_ci * @filename: The start of string to check. 6878c2ecf20Sopenharmony_ci * @filename_end: The end of string to check. 6888c2ecf20Sopenharmony_ci * @pattern: The start of pattern to compare. 6898c2ecf20Sopenharmony_ci * @pattern_end: The end of pattern to compare. 6908c2ecf20Sopenharmony_ci * 6918c2ecf20Sopenharmony_ci * Returns true if @filename matches @pattern, false otherwise. 6928c2ecf20Sopenharmony_ci */ 6938c2ecf20Sopenharmony_cistatic bool tomoyo_file_matches_pattern2(const char *filename, 6948c2ecf20Sopenharmony_ci const char *filename_end, 6958c2ecf20Sopenharmony_ci const char *pattern, 6968c2ecf20Sopenharmony_ci const char *pattern_end) 6978c2ecf20Sopenharmony_ci{ 6988c2ecf20Sopenharmony_ci while (filename < filename_end && pattern < pattern_end) { 6998c2ecf20Sopenharmony_ci char c; 7008c2ecf20Sopenharmony_ci int i; 7018c2ecf20Sopenharmony_ci int j; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci if (*pattern != '\\') { 7048c2ecf20Sopenharmony_ci if (*filename++ != *pattern++) 7058c2ecf20Sopenharmony_ci return false; 7068c2ecf20Sopenharmony_ci continue; 7078c2ecf20Sopenharmony_ci } 7088c2ecf20Sopenharmony_ci c = *filename; 7098c2ecf20Sopenharmony_ci pattern++; 7108c2ecf20Sopenharmony_ci switch (*pattern) { 7118c2ecf20Sopenharmony_ci case '?': 7128c2ecf20Sopenharmony_ci if (c == '/') { 7138c2ecf20Sopenharmony_ci return false; 7148c2ecf20Sopenharmony_ci } else if (c == '\\') { 7158c2ecf20Sopenharmony_ci if (filename[1] == '\\') 7168c2ecf20Sopenharmony_ci filename++; 7178c2ecf20Sopenharmony_ci else if (tomoyo_byte_range(filename + 1)) 7188c2ecf20Sopenharmony_ci filename += 3; 7198c2ecf20Sopenharmony_ci else 7208c2ecf20Sopenharmony_ci return false; 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci break; 7238c2ecf20Sopenharmony_ci case '\\': 7248c2ecf20Sopenharmony_ci if (c != '\\') 7258c2ecf20Sopenharmony_ci return false; 7268c2ecf20Sopenharmony_ci if (*++filename != '\\') 7278c2ecf20Sopenharmony_ci return false; 7288c2ecf20Sopenharmony_ci break; 7298c2ecf20Sopenharmony_ci case '+': 7308c2ecf20Sopenharmony_ci if (!isdigit(c)) 7318c2ecf20Sopenharmony_ci return false; 7328c2ecf20Sopenharmony_ci break; 7338c2ecf20Sopenharmony_ci case 'x': 7348c2ecf20Sopenharmony_ci if (!isxdigit(c)) 7358c2ecf20Sopenharmony_ci return false; 7368c2ecf20Sopenharmony_ci break; 7378c2ecf20Sopenharmony_ci case 'a': 7388c2ecf20Sopenharmony_ci if (!tomoyo_alphabet_char(c)) 7398c2ecf20Sopenharmony_ci return false; 7408c2ecf20Sopenharmony_ci break; 7418c2ecf20Sopenharmony_ci case '0': 7428c2ecf20Sopenharmony_ci case '1': 7438c2ecf20Sopenharmony_ci case '2': 7448c2ecf20Sopenharmony_ci case '3': 7458c2ecf20Sopenharmony_ci if (c == '\\' && tomoyo_byte_range(filename + 1) 7468c2ecf20Sopenharmony_ci && strncmp(filename + 1, pattern, 3) == 0) { 7478c2ecf20Sopenharmony_ci filename += 3; 7488c2ecf20Sopenharmony_ci pattern += 2; 7498c2ecf20Sopenharmony_ci break; 7508c2ecf20Sopenharmony_ci } 7518c2ecf20Sopenharmony_ci return false; /* Not matched. */ 7528c2ecf20Sopenharmony_ci case '*': 7538c2ecf20Sopenharmony_ci case '@': 7548c2ecf20Sopenharmony_ci for (i = 0; i <= filename_end - filename; i++) { 7558c2ecf20Sopenharmony_ci if (tomoyo_file_matches_pattern2( 7568c2ecf20Sopenharmony_ci filename + i, filename_end, 7578c2ecf20Sopenharmony_ci pattern + 1, pattern_end)) 7588c2ecf20Sopenharmony_ci return true; 7598c2ecf20Sopenharmony_ci c = filename[i]; 7608c2ecf20Sopenharmony_ci if (c == '.' && *pattern == '@') 7618c2ecf20Sopenharmony_ci break; 7628c2ecf20Sopenharmony_ci if (c != '\\') 7638c2ecf20Sopenharmony_ci continue; 7648c2ecf20Sopenharmony_ci if (filename[i + 1] == '\\') 7658c2ecf20Sopenharmony_ci i++; 7668c2ecf20Sopenharmony_ci else if (tomoyo_byte_range(filename + i + 1)) 7678c2ecf20Sopenharmony_ci i += 3; 7688c2ecf20Sopenharmony_ci else 7698c2ecf20Sopenharmony_ci break; /* Bad pattern. */ 7708c2ecf20Sopenharmony_ci } 7718c2ecf20Sopenharmony_ci return false; /* Not matched. */ 7728c2ecf20Sopenharmony_ci default: 7738c2ecf20Sopenharmony_ci j = 0; 7748c2ecf20Sopenharmony_ci c = *pattern; 7758c2ecf20Sopenharmony_ci if (c == '$') { 7768c2ecf20Sopenharmony_ci while (isdigit(filename[j])) 7778c2ecf20Sopenharmony_ci j++; 7788c2ecf20Sopenharmony_ci } else if (c == 'X') { 7798c2ecf20Sopenharmony_ci while (isxdigit(filename[j])) 7808c2ecf20Sopenharmony_ci j++; 7818c2ecf20Sopenharmony_ci } else if (c == 'A') { 7828c2ecf20Sopenharmony_ci while (tomoyo_alphabet_char(filename[j])) 7838c2ecf20Sopenharmony_ci j++; 7848c2ecf20Sopenharmony_ci } 7858c2ecf20Sopenharmony_ci for (i = 1; i <= j; i++) { 7868c2ecf20Sopenharmony_ci if (tomoyo_file_matches_pattern2( 7878c2ecf20Sopenharmony_ci filename + i, filename_end, 7888c2ecf20Sopenharmony_ci pattern + 1, pattern_end)) 7898c2ecf20Sopenharmony_ci return true; 7908c2ecf20Sopenharmony_ci } 7918c2ecf20Sopenharmony_ci return false; /* Not matched or bad pattern. */ 7928c2ecf20Sopenharmony_ci } 7938c2ecf20Sopenharmony_ci filename++; 7948c2ecf20Sopenharmony_ci pattern++; 7958c2ecf20Sopenharmony_ci } 7968c2ecf20Sopenharmony_ci while (*pattern == '\\' && 7978c2ecf20Sopenharmony_ci (*(pattern + 1) == '*' || *(pattern + 1) == '@')) 7988c2ecf20Sopenharmony_ci pattern += 2; 7998c2ecf20Sopenharmony_ci return filename == filename_end && pattern == pattern_end; 8008c2ecf20Sopenharmony_ci} 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci/** 8038c2ecf20Sopenharmony_ci * tomoyo_file_matches_pattern - Pattern matching without '/' character. 8048c2ecf20Sopenharmony_ci * 8058c2ecf20Sopenharmony_ci * @filename: The start of string to check. 8068c2ecf20Sopenharmony_ci * @filename_end: The end of string to check. 8078c2ecf20Sopenharmony_ci * @pattern: The start of pattern to compare. 8088c2ecf20Sopenharmony_ci * @pattern_end: The end of pattern to compare. 8098c2ecf20Sopenharmony_ci * 8108c2ecf20Sopenharmony_ci * Returns true if @filename matches @pattern, false otherwise. 8118c2ecf20Sopenharmony_ci */ 8128c2ecf20Sopenharmony_cistatic bool tomoyo_file_matches_pattern(const char *filename, 8138c2ecf20Sopenharmony_ci const char *filename_end, 8148c2ecf20Sopenharmony_ci const char *pattern, 8158c2ecf20Sopenharmony_ci const char *pattern_end) 8168c2ecf20Sopenharmony_ci{ 8178c2ecf20Sopenharmony_ci const char *pattern_start = pattern; 8188c2ecf20Sopenharmony_ci bool first = true; 8198c2ecf20Sopenharmony_ci bool result; 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci while (pattern < pattern_end - 1) { 8228c2ecf20Sopenharmony_ci /* Split at "\-" pattern. */ 8238c2ecf20Sopenharmony_ci if (*pattern++ != '\\' || *pattern++ != '-') 8248c2ecf20Sopenharmony_ci continue; 8258c2ecf20Sopenharmony_ci result = tomoyo_file_matches_pattern2(filename, 8268c2ecf20Sopenharmony_ci filename_end, 8278c2ecf20Sopenharmony_ci pattern_start, 8288c2ecf20Sopenharmony_ci pattern - 2); 8298c2ecf20Sopenharmony_ci if (first) 8308c2ecf20Sopenharmony_ci result = !result; 8318c2ecf20Sopenharmony_ci if (result) 8328c2ecf20Sopenharmony_ci return false; 8338c2ecf20Sopenharmony_ci first = false; 8348c2ecf20Sopenharmony_ci pattern_start = pattern; 8358c2ecf20Sopenharmony_ci } 8368c2ecf20Sopenharmony_ci result = tomoyo_file_matches_pattern2(filename, filename_end, 8378c2ecf20Sopenharmony_ci pattern_start, pattern_end); 8388c2ecf20Sopenharmony_ci return first ? result : !result; 8398c2ecf20Sopenharmony_ci} 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci/** 8428c2ecf20Sopenharmony_ci * tomoyo_path_matches_pattern2 - Do pathname pattern matching. 8438c2ecf20Sopenharmony_ci * 8448c2ecf20Sopenharmony_ci * @f: The start of string to check. 8458c2ecf20Sopenharmony_ci * @p: The start of pattern to compare. 8468c2ecf20Sopenharmony_ci * 8478c2ecf20Sopenharmony_ci * Returns true if @f matches @p, false otherwise. 8488c2ecf20Sopenharmony_ci */ 8498c2ecf20Sopenharmony_cistatic bool tomoyo_path_matches_pattern2(const char *f, const char *p) 8508c2ecf20Sopenharmony_ci{ 8518c2ecf20Sopenharmony_ci const char *f_delimiter; 8528c2ecf20Sopenharmony_ci const char *p_delimiter; 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci while (*f && *p) { 8558c2ecf20Sopenharmony_ci f_delimiter = strchr(f, '/'); 8568c2ecf20Sopenharmony_ci if (!f_delimiter) 8578c2ecf20Sopenharmony_ci f_delimiter = f + strlen(f); 8588c2ecf20Sopenharmony_ci p_delimiter = strchr(p, '/'); 8598c2ecf20Sopenharmony_ci if (!p_delimiter) 8608c2ecf20Sopenharmony_ci p_delimiter = p + strlen(p); 8618c2ecf20Sopenharmony_ci if (*p == '\\' && *(p + 1) == '{') 8628c2ecf20Sopenharmony_ci goto recursive; 8638c2ecf20Sopenharmony_ci if (!tomoyo_file_matches_pattern(f, f_delimiter, p, 8648c2ecf20Sopenharmony_ci p_delimiter)) 8658c2ecf20Sopenharmony_ci return false; 8668c2ecf20Sopenharmony_ci f = f_delimiter; 8678c2ecf20Sopenharmony_ci if (*f) 8688c2ecf20Sopenharmony_ci f++; 8698c2ecf20Sopenharmony_ci p = p_delimiter; 8708c2ecf20Sopenharmony_ci if (*p) 8718c2ecf20Sopenharmony_ci p++; 8728c2ecf20Sopenharmony_ci } 8738c2ecf20Sopenharmony_ci /* Ignore trailing "\*" and "\@" in @pattern. */ 8748c2ecf20Sopenharmony_ci while (*p == '\\' && 8758c2ecf20Sopenharmony_ci (*(p + 1) == '*' || *(p + 1) == '@')) 8768c2ecf20Sopenharmony_ci p += 2; 8778c2ecf20Sopenharmony_ci return !*f && !*p; 8788c2ecf20Sopenharmony_ci recursive: 8798c2ecf20Sopenharmony_ci /* 8808c2ecf20Sopenharmony_ci * The "\{" pattern is permitted only after '/' character. 8818c2ecf20Sopenharmony_ci * This guarantees that below "*(p - 1)" is safe. 8828c2ecf20Sopenharmony_ci * Also, the "\}" pattern is permitted only before '/' character 8838c2ecf20Sopenharmony_ci * so that "\{" + "\}" pair will not break the "\-" operator. 8848c2ecf20Sopenharmony_ci */ 8858c2ecf20Sopenharmony_ci if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' || 8868c2ecf20Sopenharmony_ci *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\') 8878c2ecf20Sopenharmony_ci return false; /* Bad pattern. */ 8888c2ecf20Sopenharmony_ci do { 8898c2ecf20Sopenharmony_ci /* Compare current component with pattern. */ 8908c2ecf20Sopenharmony_ci if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2, 8918c2ecf20Sopenharmony_ci p_delimiter - 2)) 8928c2ecf20Sopenharmony_ci break; 8938c2ecf20Sopenharmony_ci /* Proceed to next component. */ 8948c2ecf20Sopenharmony_ci f = f_delimiter; 8958c2ecf20Sopenharmony_ci if (!*f) 8968c2ecf20Sopenharmony_ci break; 8978c2ecf20Sopenharmony_ci f++; 8988c2ecf20Sopenharmony_ci /* Continue comparison. */ 8998c2ecf20Sopenharmony_ci if (tomoyo_path_matches_pattern2(f, p_delimiter + 1)) 9008c2ecf20Sopenharmony_ci return true; 9018c2ecf20Sopenharmony_ci f_delimiter = strchr(f, '/'); 9028c2ecf20Sopenharmony_ci } while (f_delimiter); 9038c2ecf20Sopenharmony_ci return false; /* Not matched. */ 9048c2ecf20Sopenharmony_ci} 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci/** 9078c2ecf20Sopenharmony_ci * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern. 9088c2ecf20Sopenharmony_ci * 9098c2ecf20Sopenharmony_ci * @filename: The filename to check. 9108c2ecf20Sopenharmony_ci * @pattern: The pattern to compare. 9118c2ecf20Sopenharmony_ci * 9128c2ecf20Sopenharmony_ci * Returns true if matches, false otherwise. 9138c2ecf20Sopenharmony_ci * 9148c2ecf20Sopenharmony_ci * The following patterns are available. 9158c2ecf20Sopenharmony_ci * \\ \ itself. 9168c2ecf20Sopenharmony_ci * \ooo Octal representation of a byte. 9178c2ecf20Sopenharmony_ci * \* Zero or more repetitions of characters other than '/'. 9188c2ecf20Sopenharmony_ci * \@ Zero or more repetitions of characters other than '/' or '.'. 9198c2ecf20Sopenharmony_ci * \? 1 byte character other than '/'. 9208c2ecf20Sopenharmony_ci * \$ One or more repetitions of decimal digits. 9218c2ecf20Sopenharmony_ci * \+ 1 decimal digit. 9228c2ecf20Sopenharmony_ci * \X One or more repetitions of hexadecimal digits. 9238c2ecf20Sopenharmony_ci * \x 1 hexadecimal digit. 9248c2ecf20Sopenharmony_ci * \A One or more repetitions of alphabet characters. 9258c2ecf20Sopenharmony_ci * \a 1 alphabet character. 9268c2ecf20Sopenharmony_ci * 9278c2ecf20Sopenharmony_ci * \- Subtraction operator. 9288c2ecf20Sopenharmony_ci * 9298c2ecf20Sopenharmony_ci * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/ 9308c2ecf20Sopenharmony_ci * /dir/dir/dir/ ). 9318c2ecf20Sopenharmony_ci */ 9328c2ecf20Sopenharmony_cibool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, 9338c2ecf20Sopenharmony_ci const struct tomoyo_path_info *pattern) 9348c2ecf20Sopenharmony_ci{ 9358c2ecf20Sopenharmony_ci const char *f = filename->name; 9368c2ecf20Sopenharmony_ci const char *p = pattern->name; 9378c2ecf20Sopenharmony_ci const int len = pattern->const_len; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci /* If @pattern doesn't contain pattern, I can use strcmp(). */ 9408c2ecf20Sopenharmony_ci if (!pattern->is_patterned) 9418c2ecf20Sopenharmony_ci return !tomoyo_pathcmp(filename, pattern); 9428c2ecf20Sopenharmony_ci /* Don't compare directory and non-directory. */ 9438c2ecf20Sopenharmony_ci if (filename->is_dir != pattern->is_dir) 9448c2ecf20Sopenharmony_ci return false; 9458c2ecf20Sopenharmony_ci /* Compare the initial length without patterns. */ 9468c2ecf20Sopenharmony_ci if (strncmp(f, p, len)) 9478c2ecf20Sopenharmony_ci return false; 9488c2ecf20Sopenharmony_ci f += len; 9498c2ecf20Sopenharmony_ci p += len; 9508c2ecf20Sopenharmony_ci return tomoyo_path_matches_pattern2(f, p); 9518c2ecf20Sopenharmony_ci} 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci/** 9548c2ecf20Sopenharmony_ci * tomoyo_get_exe - Get tomoyo_realpath() of current process. 9558c2ecf20Sopenharmony_ci * 9568c2ecf20Sopenharmony_ci * Returns the tomoyo_realpath() of current process on success, NULL otherwise. 9578c2ecf20Sopenharmony_ci * 9588c2ecf20Sopenharmony_ci * This function uses kzalloc(), so the caller must call kfree() 9598c2ecf20Sopenharmony_ci * if this function didn't return NULL. 9608c2ecf20Sopenharmony_ci */ 9618c2ecf20Sopenharmony_ciconst char *tomoyo_get_exe(void) 9628c2ecf20Sopenharmony_ci{ 9638c2ecf20Sopenharmony_ci struct file *exe_file; 9648c2ecf20Sopenharmony_ci const char *cp; 9658c2ecf20Sopenharmony_ci struct mm_struct *mm = current->mm; 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci if (!mm) 9688c2ecf20Sopenharmony_ci return NULL; 9698c2ecf20Sopenharmony_ci exe_file = get_mm_exe_file(mm); 9708c2ecf20Sopenharmony_ci if (!exe_file) 9718c2ecf20Sopenharmony_ci return NULL; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci cp = tomoyo_realpath_from_path(&exe_file->f_path); 9748c2ecf20Sopenharmony_ci fput(exe_file); 9758c2ecf20Sopenharmony_ci return cp; 9768c2ecf20Sopenharmony_ci} 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci/** 9798c2ecf20Sopenharmony_ci * tomoyo_get_mode - Get MAC mode. 9808c2ecf20Sopenharmony_ci * 9818c2ecf20Sopenharmony_ci * @ns: Pointer to "struct tomoyo_policy_namespace". 9828c2ecf20Sopenharmony_ci * @profile: Profile number. 9838c2ecf20Sopenharmony_ci * @index: Index number of functionality. 9848c2ecf20Sopenharmony_ci * 9858c2ecf20Sopenharmony_ci * Returns mode. 9868c2ecf20Sopenharmony_ci */ 9878c2ecf20Sopenharmony_ciint tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile, 9888c2ecf20Sopenharmony_ci const u8 index) 9898c2ecf20Sopenharmony_ci{ 9908c2ecf20Sopenharmony_ci u8 mode; 9918c2ecf20Sopenharmony_ci struct tomoyo_profile *p; 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci if (!tomoyo_policy_loaded) 9948c2ecf20Sopenharmony_ci return TOMOYO_CONFIG_DISABLED; 9958c2ecf20Sopenharmony_ci p = tomoyo_profile(ns, profile); 9968c2ecf20Sopenharmony_ci mode = p->config[index]; 9978c2ecf20Sopenharmony_ci if (mode == TOMOYO_CONFIG_USE_DEFAULT) 9988c2ecf20Sopenharmony_ci mode = p->config[tomoyo_index2category[index] 9998c2ecf20Sopenharmony_ci + TOMOYO_MAX_MAC_INDEX]; 10008c2ecf20Sopenharmony_ci if (mode == TOMOYO_CONFIG_USE_DEFAULT) 10018c2ecf20Sopenharmony_ci mode = p->default_config; 10028c2ecf20Sopenharmony_ci return mode & 3; 10038c2ecf20Sopenharmony_ci} 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci/** 10068c2ecf20Sopenharmony_ci * tomoyo_init_request_info - Initialize "struct tomoyo_request_info" members. 10078c2ecf20Sopenharmony_ci * 10088c2ecf20Sopenharmony_ci * @r: Pointer to "struct tomoyo_request_info" to initialize. 10098c2ecf20Sopenharmony_ci * @domain: Pointer to "struct tomoyo_domain_info". NULL for tomoyo_domain(). 10108c2ecf20Sopenharmony_ci * @index: Index number of functionality. 10118c2ecf20Sopenharmony_ci * 10128c2ecf20Sopenharmony_ci * Returns mode. 10138c2ecf20Sopenharmony_ci */ 10148c2ecf20Sopenharmony_ciint tomoyo_init_request_info(struct tomoyo_request_info *r, 10158c2ecf20Sopenharmony_ci struct tomoyo_domain_info *domain, const u8 index) 10168c2ecf20Sopenharmony_ci{ 10178c2ecf20Sopenharmony_ci u8 profile; 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_ci memset(r, 0, sizeof(*r)); 10208c2ecf20Sopenharmony_ci if (!domain) 10218c2ecf20Sopenharmony_ci domain = tomoyo_domain(); 10228c2ecf20Sopenharmony_ci r->domain = domain; 10238c2ecf20Sopenharmony_ci profile = domain->profile; 10248c2ecf20Sopenharmony_ci r->profile = profile; 10258c2ecf20Sopenharmony_ci r->type = index; 10268c2ecf20Sopenharmony_ci r->mode = tomoyo_get_mode(domain->ns, profile, index); 10278c2ecf20Sopenharmony_ci return r->mode; 10288c2ecf20Sopenharmony_ci} 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci/** 10318c2ecf20Sopenharmony_ci * tomoyo_domain_quota_is_ok - Check for domain's quota. 10328c2ecf20Sopenharmony_ci * 10338c2ecf20Sopenharmony_ci * @r: Pointer to "struct tomoyo_request_info". 10348c2ecf20Sopenharmony_ci * 10358c2ecf20Sopenharmony_ci * Returns true if the domain is not exceeded quota, false otherwise. 10368c2ecf20Sopenharmony_ci * 10378c2ecf20Sopenharmony_ci * Caller holds tomoyo_read_lock(). 10388c2ecf20Sopenharmony_ci */ 10398c2ecf20Sopenharmony_cibool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) 10408c2ecf20Sopenharmony_ci{ 10418c2ecf20Sopenharmony_ci unsigned int count = 0; 10428c2ecf20Sopenharmony_ci struct tomoyo_domain_info *domain = r->domain; 10438c2ecf20Sopenharmony_ci struct tomoyo_acl_info *ptr; 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci if (r->mode != TOMOYO_CONFIG_LEARNING) 10468c2ecf20Sopenharmony_ci return false; 10478c2ecf20Sopenharmony_ci if (!domain) 10488c2ecf20Sopenharmony_ci return true; 10498c2ecf20Sopenharmony_ci if (READ_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED])) 10508c2ecf20Sopenharmony_ci return false; 10518c2ecf20Sopenharmony_ci list_for_each_entry_rcu(ptr, &domain->acl_info_list, list, 10528c2ecf20Sopenharmony_ci srcu_read_lock_held(&tomoyo_ss)) { 10538c2ecf20Sopenharmony_ci u16 perm; 10548c2ecf20Sopenharmony_ci 10558c2ecf20Sopenharmony_ci if (ptr->is_deleted) 10568c2ecf20Sopenharmony_ci continue; 10578c2ecf20Sopenharmony_ci /* 10588c2ecf20Sopenharmony_ci * Reading perm bitmap might race with tomoyo_merge_*() because 10598c2ecf20Sopenharmony_ci * caller does not hold tomoyo_policy_lock mutex. But exceeding 10608c2ecf20Sopenharmony_ci * max_learning_entry parameter by a few entries does not harm. 10618c2ecf20Sopenharmony_ci */ 10628c2ecf20Sopenharmony_ci switch (ptr->type) { 10638c2ecf20Sopenharmony_ci case TOMOYO_TYPE_PATH_ACL: 10648c2ecf20Sopenharmony_ci perm = data_race(container_of(ptr, struct tomoyo_path_acl, head)->perm); 10658c2ecf20Sopenharmony_ci break; 10668c2ecf20Sopenharmony_ci case TOMOYO_TYPE_PATH2_ACL: 10678c2ecf20Sopenharmony_ci perm = data_race(container_of(ptr, struct tomoyo_path2_acl, head)->perm); 10688c2ecf20Sopenharmony_ci break; 10698c2ecf20Sopenharmony_ci case TOMOYO_TYPE_PATH_NUMBER_ACL: 10708c2ecf20Sopenharmony_ci perm = data_race(container_of(ptr, struct tomoyo_path_number_acl, head) 10718c2ecf20Sopenharmony_ci ->perm); 10728c2ecf20Sopenharmony_ci break; 10738c2ecf20Sopenharmony_ci case TOMOYO_TYPE_MKDEV_ACL: 10748c2ecf20Sopenharmony_ci perm = data_race(container_of(ptr, struct tomoyo_mkdev_acl, head)->perm); 10758c2ecf20Sopenharmony_ci break; 10768c2ecf20Sopenharmony_ci case TOMOYO_TYPE_INET_ACL: 10778c2ecf20Sopenharmony_ci perm = data_race(container_of(ptr, struct tomoyo_inet_acl, head)->perm); 10788c2ecf20Sopenharmony_ci break; 10798c2ecf20Sopenharmony_ci case TOMOYO_TYPE_UNIX_ACL: 10808c2ecf20Sopenharmony_ci perm = data_race(container_of(ptr, struct tomoyo_unix_acl, head)->perm); 10818c2ecf20Sopenharmony_ci break; 10828c2ecf20Sopenharmony_ci case TOMOYO_TYPE_MANUAL_TASK_ACL: 10838c2ecf20Sopenharmony_ci perm = 0; 10848c2ecf20Sopenharmony_ci break; 10858c2ecf20Sopenharmony_ci default: 10868c2ecf20Sopenharmony_ci perm = 1; 10878c2ecf20Sopenharmony_ci } 10888c2ecf20Sopenharmony_ci count += hweight16(perm); 10898c2ecf20Sopenharmony_ci } 10908c2ecf20Sopenharmony_ci if (count < tomoyo_profile(domain->ns, domain->profile)-> 10918c2ecf20Sopenharmony_ci pref[TOMOYO_PREF_MAX_LEARNING_ENTRY]) 10928c2ecf20Sopenharmony_ci return true; 10938c2ecf20Sopenharmony_ci WRITE_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED], true); 10948c2ecf20Sopenharmony_ci /* r->granted = false; */ 10958c2ecf20Sopenharmony_ci tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]); 10968c2ecf20Sopenharmony_ci#ifndef CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING 10978c2ecf20Sopenharmony_ci pr_warn("WARNING: Domain '%s' has too many ACLs to hold. Stopped learning mode.\n", 10988c2ecf20Sopenharmony_ci domain->domainname->name); 10998c2ecf20Sopenharmony_ci#endif 11008c2ecf20Sopenharmony_ci return false; 11018c2ecf20Sopenharmony_ci} 1102