^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * security/tomoyo/util.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2005-2011 NTT DATA CORPORATION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/rculist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /* Lock for protecting policy. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) DEFINE_MUTEX(tomoyo_policy_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* Has /sbin/init started? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) bool tomoyo_policy_loaded;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Mapping table from "enum tomoyo_mac_index" to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * "enum tomoyo_mac_category_index".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) /* CONFIG::file group */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) [TOMOYO_MAC_FILE_EXECUTE] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) [TOMOYO_MAC_FILE_OPEN] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) [TOMOYO_MAC_FILE_CREATE] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) [TOMOYO_MAC_FILE_UNLINK] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) [TOMOYO_MAC_FILE_GETATTR] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) [TOMOYO_MAC_FILE_MKDIR] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) [TOMOYO_MAC_FILE_RMDIR] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) [TOMOYO_MAC_FILE_MKFIFO] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) [TOMOYO_MAC_FILE_MKSOCK] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) [TOMOYO_MAC_FILE_TRUNCATE] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) [TOMOYO_MAC_FILE_SYMLINK] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) [TOMOYO_MAC_FILE_MKBLOCK] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) [TOMOYO_MAC_FILE_MKCHAR] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) [TOMOYO_MAC_FILE_LINK] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) [TOMOYO_MAC_FILE_RENAME] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) [TOMOYO_MAC_FILE_CHMOD] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) [TOMOYO_MAC_FILE_CHOWN] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) [TOMOYO_MAC_FILE_CHGRP] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) [TOMOYO_MAC_FILE_IOCTL] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) [TOMOYO_MAC_FILE_CHROOT] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) [TOMOYO_MAC_FILE_MOUNT] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) [TOMOYO_MAC_FILE_UMOUNT] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) [TOMOYO_MAC_FILE_PIVOT_ROOT] = TOMOYO_MAC_CATEGORY_FILE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* CONFIG::network group */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) [TOMOYO_MAC_NETWORK_INET_STREAM_BIND] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) [TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) [TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) [TOMOYO_MAC_NETWORK_INET_DGRAM_BIND] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) [TOMOYO_MAC_NETWORK_INET_DGRAM_SEND] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) [TOMOYO_MAC_NETWORK_INET_RAW_BIND] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) [TOMOYO_MAC_NETWORK_INET_RAW_SEND] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) [TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) [TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) [TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) [TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) [TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) TOMOYO_MAC_CATEGORY_NETWORK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /* CONFIG::misc group */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) [TOMOYO_MAC_ENVIRON] = TOMOYO_MAC_CATEGORY_MISC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * tomoyo_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) * @time: Seconds since 1970/01/01 00:00:00.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * @stamp: Pointer to "struct tomoyo_time".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * Returns nothing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) void tomoyo_convert_time(time64_t time64, struct tomoyo_time *stamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct tm tm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) time64_to_tm(time64, 0, &tm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) stamp->sec = tm.tm_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) stamp->min = tm.tm_min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) stamp->hour = tm.tm_hour;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) stamp->day = tm.tm_mday;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) stamp->month = tm.tm_mon + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) stamp->year = tm.tm_year + 1900;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * tomoyo_permstr - Find permission keywords.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * @string: String representation for permissions in foo/bar/buz format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * @keyword: Keyword to find from @string/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * Returns true if @keyword was found in @string, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) bool tomoyo_permstr(const char *string, const char *keyword)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) const char *cp = strstr(string, keyword);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return cp == string || *(cp - 1) == '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * tomoyo_read_token - Read a word from a line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * @param: Pointer to "struct tomoyo_acl_param".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * Returns a word on success, "" otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * To allow the caller to skip NULL check, this function returns "" rather than
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * NULL if there is no more words to read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) char *tomoyo_read_token(struct tomoyo_acl_param *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) char *pos = param->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) char *del = strchr(pos, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (del)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) *del++ = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) del = pos + strlen(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) param->data = del;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static bool tomoyo_correct_path2(const char *filename, const size_t len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * tomoyo_get_domainname - Read a domainname from a line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * @param: Pointer to "struct tomoyo_acl_param".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * Returns a domainname on success, NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) const struct tomoyo_path_info *tomoyo_get_domainname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) (struct tomoyo_acl_param *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) char *start = param->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) char *pos = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) while (*pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (*pos++ != ' ' ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) tomoyo_correct_path2(pos, strchrnul(pos, ' ') - pos))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) *(pos - 1) = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) param->data = pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (tomoyo_correct_domain(start))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return tomoyo_get_name(start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) * tomoyo_parse_ulong - Parse an "unsigned long" value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * @result: Pointer to "unsigned long".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * @str: Pointer to string to parse.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * Returns one of values in "enum tomoyo_value_type".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * The @src is updated to point the first character after the value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * on success.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) u8 tomoyo_parse_ulong(unsigned long *result, char **str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) const char *cp = *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) char *ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) int base = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (*cp == '0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) char c = *(cp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (c == 'x' || c == 'X') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) base = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) cp += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) } else if (c >= '0' && c <= '7') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) base = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) cp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) *result = simple_strtoul(cp, &ep, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (cp == ep)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return TOMOYO_VALUE_TYPE_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) *str = ep;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) switch (base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return TOMOYO_VALUE_TYPE_HEXADECIMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) return TOMOYO_VALUE_TYPE_OCTAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) return TOMOYO_VALUE_TYPE_DECIMAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * tomoyo_print_ulong - Print an "unsigned long" value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * @buffer: Pointer to buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * @buffer_len: Size of @buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * @value: An "unsigned long" value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * @type: Type of @value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * Returns nothing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) void tomoyo_print_ulong(char *buffer, const int buffer_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) const unsigned long value, const u8 type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (type == TOMOYO_VALUE_TYPE_DECIMAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) snprintf(buffer, buffer_len, "%lu", value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) else if (type == TOMOYO_VALUE_TYPE_OCTAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) snprintf(buffer, buffer_len, "0%lo", value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) else if (type == TOMOYO_VALUE_TYPE_HEXADECIMAL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) snprintf(buffer, buffer_len, "0x%lX", value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) snprintf(buffer, buffer_len, "type(%u)", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * tomoyo_parse_name_union - Parse a tomoyo_name_union.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * @param: Pointer to "struct tomoyo_acl_param".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * @ptr: Pointer to "struct tomoyo_name_union".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * Returns true on success, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) bool tomoyo_parse_name_union(struct tomoyo_acl_param *param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct tomoyo_name_union *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) char *filename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (param->data[0] == '@') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) param->data++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ptr->group = tomoyo_get_group(param, TOMOYO_PATH_GROUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return ptr->group != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) filename = tomoyo_read_token(param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) if (!tomoyo_correct_word(filename))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) ptr->filename = tomoyo_get_name(filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return ptr->filename != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) * tomoyo_parse_number_union - Parse a tomoyo_number_union.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * @param: Pointer to "struct tomoyo_acl_param".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) * @ptr: Pointer to "struct tomoyo_number_union".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * Returns true on success, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) bool tomoyo_parse_number_union(struct tomoyo_acl_param *param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct tomoyo_number_union *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) char *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) u8 type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) unsigned long v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) memset(ptr, 0, sizeof(*ptr));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (param->data[0] == '@') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) param->data++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ptr->group = tomoyo_get_group(param, TOMOYO_NUMBER_GROUP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return ptr->group != NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) data = tomoyo_read_token(param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) type = tomoyo_parse_ulong(&v, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (type == TOMOYO_VALUE_TYPE_INVALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ptr->values[0] = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ptr->value_type[0] = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (!*data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ptr->values[1] = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) ptr->value_type[1] = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (*data++ != '-')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) type = tomoyo_parse_ulong(&v, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (type == TOMOYO_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) ptr->values[1] = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) ptr->value_type[1] = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * tomoyo_byte_range - Check whether the string is a \ooo style octal value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * @str: Pointer to the string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) * Returns true if @str is a \ooo style octal value, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * This function verifies that \ooo is in valid range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static inline bool tomoyo_byte_range(const char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return *str >= '0' && *str++ <= '3' &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) *str >= '0' && *str++ <= '7' &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) *str >= '0' && *str <= '7';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * tomoyo_alphabet_char - Check whether the character is an alphabet.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * @c: The character to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * Returns true if @c is an alphabet character, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static inline bool tomoyo_alphabet_char(const char c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) * tomoyo_make_byte - Make byte value from three octal characters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) * @c1: The first character.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) * @c2: The second character.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) * @c3: The third character.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * Returns byte value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * tomoyo_valid - Check whether the character is a valid char.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) * @c: The character to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) * Returns true if @c is a valid character, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) static inline bool tomoyo_valid(const unsigned char c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return c > ' ' && c < 127;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * tomoyo_invalid - Check whether the character is an invalid char.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * @c: The character to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * Returns true if @c is an invalid character, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) static inline bool tomoyo_invalid(const unsigned char c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return c && (c <= ' ' || c >= 127);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * tomoyo_str_starts - Check whether the given string starts with the given keyword.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * @src: Pointer to pointer to the string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * @find: Pointer to the keyword.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * Returns true if @src starts with @find, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * The @src is updated to point the first character after the @find
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * if @src starts with @find.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) bool tomoyo_str_starts(char **src, const char *find)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) const int len = strlen(find);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) char *tmp = *src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (strncmp(tmp, find, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) tmp += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) *src = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * tomoyo_normalize_line - Format string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) * @buffer: The line to normalize.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * Leading and trailing whitespaces are removed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * Multiple whitespaces are packed into single space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * Returns nothing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) void tomoyo_normalize_line(unsigned char *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) unsigned char *sp = buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) unsigned char *dp = buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) bool first = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) while (tomoyo_invalid(*sp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) sp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) while (*sp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (!first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) *dp++ = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) first = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) while (tomoyo_valid(*sp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) *dp++ = *sp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) while (tomoyo_invalid(*sp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) sp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) *dp = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * tomoyo_correct_word2 - Validate a string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * @string: The string to check. Maybe non-'\0'-terminated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * @len: Length of @string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * Check whether the given string follows the naming rules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * Returns true if @string follows the naming rules, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static bool tomoyo_correct_word2(const char *string, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) const char *const start = string;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) bool in_repetition = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) unsigned char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) unsigned char d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) unsigned char e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) if (!len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) while (len--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) c = *string++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) if (c == '\\') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (!len--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) c = *string++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) switch (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) case '\\': /* "\\" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) case '$': /* "\$" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) case '+': /* "\+" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) case '?': /* "\?" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) case '*': /* "\*" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) case '@': /* "\@" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) case 'x': /* "\x" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) case 'X': /* "\X" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) case 'a': /* "\a" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) case 'A': /* "\A" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) case '-': /* "\-" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) case '{': /* "/\{" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (string - 3 < start || *(string - 3) != '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) in_repetition = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) case '}': /* "\}/" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (*string != '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (!in_repetition)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) in_repetition = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) case '0': /* "\ooo" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) case '1':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) case '2':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) case '3':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (!len-- || !len--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) d = *string++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) e = *string++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (d < '0' || d > '7' || e < '0' || e > '7')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) c = tomoyo_make_byte(c, d, e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) if (c <= ' ' || c >= 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) } else if (in_repetition && c == '/') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) } else if (c <= ' ' || c >= 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (in_repetition)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * tomoyo_correct_word - Validate a string.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) * @string: The string to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * Check whether the given string follows the naming rules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) * Returns true if @string follows the naming rules, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) bool tomoyo_correct_word(const char *string)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) return tomoyo_correct_word2(string, strlen(string));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) * tomoyo_correct_path2 - Check whether the given pathname follows the naming rules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) * @filename: The pathname to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * @len: Length of @filename.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) * Returns true if @filename follows the naming rules, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) static bool tomoyo_correct_path2(const char *filename, const size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) const char *cp1 = memchr(filename, '/', len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) const char *cp2 = memchr(filename, '.', len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return cp1 && (!cp2 || (cp1 < cp2)) && tomoyo_correct_word2(filename, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * tomoyo_correct_path - Validate a pathname.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * @filename: The pathname to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * Check whether the given pathname follows the naming rules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * Returns true if @filename follows the naming rules, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) bool tomoyo_correct_path(const char *filename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) return tomoyo_correct_path2(filename, strlen(filename));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * tomoyo_correct_domain - Check whether the given domainname follows the naming rules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * @domainname: The domainname to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * Returns true if @domainname follows the naming rules, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) bool tomoyo_correct_domain(const unsigned char *domainname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (!domainname || !tomoyo_domain_def(domainname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) domainname = strchr(domainname, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (!domainname++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) const unsigned char *cp = strchr(domainname, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) if (!cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (!tomoyo_correct_path2(domainname, cp - domainname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) domainname = cp + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return tomoyo_correct_path(domainname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * tomoyo_domain_def - Check whether the given token can be a domainname.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * @buffer: The token to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * Returns true if @buffer possibly be a domainname, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) bool tomoyo_domain_def(const unsigned char *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) const unsigned char *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (*buffer != '<')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) cp = strchr(buffer, ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (!cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) len = strlen(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) len = cp - buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (buffer[len - 1] != '>' ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) !tomoyo_correct_word2(buffer + 1, len - 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * tomoyo_find_domain - Find a domain by the given name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * @domainname: The domainname to find.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) * Caller holds tomoyo_read_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) struct tomoyo_domain_info *domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) struct tomoyo_path_info name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) name.name = domainname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) tomoyo_fill_path_info(&name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) list_for_each_entry_rcu(domain, &tomoyo_domain_list, list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) srcu_read_lock_held(&tomoyo_ss)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (!domain->is_deleted &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) !tomoyo_pathcmp(&name, domain->domainname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) return domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) * @filename: The string to evaluate.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * Returns the initial length without a pattern in @filename.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static int tomoyo_const_part_length(const char *filename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) int len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) if (!filename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) while ((c = *filename++) != '\0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) if (c != '\\') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) len++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) c = *filename++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) switch (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) case '\\': /* "\\" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) len += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) case '0': /* "\ooo" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) case '1':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) case '2':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) case '3':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) c = *filename++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (c < '0' || c > '7')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) c = *filename++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (c < '0' || c > '7')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) len += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * @ptr: Pointer to "struct tomoyo_path_info" to fill in.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * The caller sets "struct tomoyo_path_info"->name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) const char *name = ptr->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) const int len = strlen(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) ptr->const_len = tomoyo_const_part_length(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) ptr->is_dir = len && (name[len - 1] == '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) ptr->is_patterned = (ptr->const_len < len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) ptr->hash = full_name_hash(NULL, name, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * tomoyo_file_matches_pattern2 - Pattern matching without '/' character and "\-" pattern.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * @filename: The start of string to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * @filename_end: The end of string to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * @pattern: The start of pattern to compare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * @pattern_end: The end of pattern to compare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) * Returns true if @filename matches @pattern, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) static bool tomoyo_file_matches_pattern2(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) const char *filename_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) const char *pattern,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) const char *pattern_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) while (filename < filename_end && pattern < pattern_end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (*pattern != '\\') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (*filename++ != *pattern++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) c = *filename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) pattern++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) switch (*pattern) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) case '?':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (c == '/') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) } else if (c == '\\') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (filename[1] == '\\')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) filename++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) else if (tomoyo_byte_range(filename + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) filename += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) case '\\':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (c != '\\')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (*++filename != '\\')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) case '+':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (!isdigit(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) case 'x':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (!isxdigit(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) case 'a':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (!tomoyo_alphabet_char(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) case '0':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) case '1':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) case '2':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) case '3':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (c == '\\' && tomoyo_byte_range(filename + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) && strncmp(filename + 1, pattern, 3) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) filename += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) pattern += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) return false; /* Not matched. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) case '*':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) case '@':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) for (i = 0; i <= filename_end - filename; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) if (tomoyo_file_matches_pattern2(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) filename + i, filename_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) pattern + 1, pattern_end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) c = filename[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (c == '.' && *pattern == '@')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (c != '\\')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (filename[i + 1] == '\\')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) else if (tomoyo_byte_range(filename + i + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) i += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) break; /* Bad pattern. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) return false; /* Not matched. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) j = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) c = *pattern;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (c == '$') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) while (isdigit(filename[j]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) j++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) } else if (c == 'X') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) while (isxdigit(filename[j]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) j++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) } else if (c == 'A') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) while (tomoyo_alphabet_char(filename[j]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) j++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) for (i = 1; i <= j; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (tomoyo_file_matches_pattern2(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) filename + i, filename_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) pattern + 1, pattern_end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return false; /* Not matched or bad pattern. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) filename++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) pattern++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) while (*pattern == '\\' &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) pattern += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) return filename == filename_end && pattern == pattern_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) * tomoyo_file_matches_pattern - Pattern matching without '/' character.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) * @filename: The start of string to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) * @filename_end: The end of string to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) * @pattern: The start of pattern to compare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) * @pattern_end: The end of pattern to compare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) * Returns true if @filename matches @pattern, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) static bool tomoyo_file_matches_pattern(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) const char *filename_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) const char *pattern,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) const char *pattern_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) const char *pattern_start = pattern;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) bool first = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) bool result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) while (pattern < pattern_end - 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) /* Split at "\-" pattern. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) if (*pattern++ != '\\' || *pattern++ != '-')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) result = tomoyo_file_matches_pattern2(filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) filename_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) pattern_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) pattern - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (first)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) result = !result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) first = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) pattern_start = pattern;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) result = tomoyo_file_matches_pattern2(filename, filename_end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) pattern_start, pattern_end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) return first ? result : !result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) * tomoyo_path_matches_pattern2 - Do pathname pattern matching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) * @f: The start of string to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) * @p: The start of pattern to compare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) * Returns true if @f matches @p, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) const char *f_delimiter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) const char *p_delimiter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) while (*f && *p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) f_delimiter = strchr(f, '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) if (!f_delimiter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) f_delimiter = f + strlen(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) p_delimiter = strchr(p, '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) if (!p_delimiter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) p_delimiter = p + strlen(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) if (*p == '\\' && *(p + 1) == '{')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) goto recursive;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) p_delimiter))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) f = f_delimiter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (*f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) f++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) p = p_delimiter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (*p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) p++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) /* Ignore trailing "\*" and "\@" in @pattern. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) while (*p == '\\' &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) (*(p + 1) == '*' || *(p + 1) == '@'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) p += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return !*f && !*p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) recursive:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) * The "\{" pattern is permitted only after '/' character.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) * This guarantees that below "*(p - 1)" is safe.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) * Also, the "\}" pattern is permitted only before '/' character
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) * so that "\{" + "\}" pair will not break the "\-" operator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) return false; /* Bad pattern. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) /* Compare current component with pattern. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) p_delimiter - 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) /* Proceed to next component. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) f = f_delimiter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) if (!*f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) f++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /* Continue comparison. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) f_delimiter = strchr(f, '/');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) } while (f_delimiter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return false; /* Not matched. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) * @filename: The filename to check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) * @pattern: The pattern to compare.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) * Returns true if matches, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) * The following patterns are available.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) * \\ \ itself.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) * \ooo Octal representation of a byte.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) * \* Zero or more repetitions of characters other than '/'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) * \@ Zero or more repetitions of characters other than '/' or '.'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) * \? 1 byte character other than '/'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) * \$ One or more repetitions of decimal digits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) * \+ 1 decimal digit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) * \X One or more repetitions of hexadecimal digits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) * \x 1 hexadecimal digit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) * \A One or more repetitions of alphabet characters.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) * \a 1 alphabet character.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) * \- Subtraction operator.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) * /dir/dir/dir/ ).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) const struct tomoyo_path_info *pattern)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) const char *f = filename->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) const char *p = pattern->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) const int len = pattern->const_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) /* If @pattern doesn't contain pattern, I can use strcmp(). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (!pattern->is_patterned)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) return !tomoyo_pathcmp(filename, pattern);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) /* Don't compare directory and non-directory. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) if (filename->is_dir != pattern->is_dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) /* Compare the initial length without patterns. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (strncmp(f, p, len))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) f += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) p += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) return tomoyo_path_matches_pattern2(f, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) * tomoyo_get_exe - Get tomoyo_realpath() of current process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) * This function uses kzalloc(), so the caller must call kfree()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) * if this function didn't return NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) const char *tomoyo_get_exe(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) struct file *exe_file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) const char *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) struct mm_struct *mm = current->mm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (!mm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) exe_file = get_mm_exe_file(mm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) if (!exe_file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) cp = tomoyo_realpath_from_path(&exe_file->f_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) fput(exe_file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) return cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) * tomoyo_get_mode - Get MAC mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) * @ns: Pointer to "struct tomoyo_policy_namespace".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) * @profile: Profile number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) * @index: Index number of functionality.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) * Returns mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) const u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) u8 mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) struct tomoyo_profile *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (!tomoyo_policy_loaded)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) return TOMOYO_CONFIG_DISABLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) p = tomoyo_profile(ns, profile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) mode = p->config[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) if (mode == TOMOYO_CONFIG_USE_DEFAULT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) mode = p->config[tomoyo_index2category[index]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) + TOMOYO_MAX_MAC_INDEX];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if (mode == TOMOYO_CONFIG_USE_DEFAULT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) mode = p->default_config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) return mode & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) * tomoyo_init_request_info - Initialize "struct tomoyo_request_info" members.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) * @r: Pointer to "struct tomoyo_request_info" to initialize.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) * @domain: Pointer to "struct tomoyo_domain_info". NULL for tomoyo_domain().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) * @index: Index number of functionality.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) * Returns mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) int tomoyo_init_request_info(struct tomoyo_request_info *r,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) struct tomoyo_domain_info *domain, const u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) u8 profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) memset(r, 0, sizeof(*r));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (!domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) domain = tomoyo_domain();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) r->domain = domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) profile = domain->profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) r->profile = profile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) r->type = index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) r->mode = tomoyo_get_mode(domain->ns, profile, index);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) return r->mode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) * tomoyo_domain_quota_is_ok - Check for domain's quota.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) * @r: Pointer to "struct tomoyo_request_info".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) * Returns true if the domain is not exceeded quota, false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) * Caller holds tomoyo_read_lock().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) unsigned int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) struct tomoyo_domain_info *domain = r->domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) struct tomoyo_acl_info *ptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (r->mode != TOMOYO_CONFIG_LEARNING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) if (!domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) if (READ_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) list_for_each_entry_rcu(ptr, &domain->acl_info_list, list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) srcu_read_lock_held(&tomoyo_ss)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) u16 perm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (ptr->is_deleted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) * Reading perm bitmap might race with tomoyo_merge_*() because
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) * caller does not hold tomoyo_policy_lock mutex. But exceeding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) * max_learning_entry parameter by a few entries does not harm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) switch (ptr->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) case TOMOYO_TYPE_PATH_ACL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) perm = data_race(container_of(ptr, struct tomoyo_path_acl, head)->perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) case TOMOYO_TYPE_PATH2_ACL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) perm = data_race(container_of(ptr, struct tomoyo_path2_acl, head)->perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) case TOMOYO_TYPE_PATH_NUMBER_ACL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) perm = data_race(container_of(ptr, struct tomoyo_path_number_acl, head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) ->perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) case TOMOYO_TYPE_MKDEV_ACL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) perm = data_race(container_of(ptr, struct tomoyo_mkdev_acl, head)->perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) case TOMOYO_TYPE_INET_ACL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) perm = data_race(container_of(ptr, struct tomoyo_inet_acl, head)->perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) case TOMOYO_TYPE_UNIX_ACL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) perm = data_race(container_of(ptr, struct tomoyo_unix_acl, head)->perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) case TOMOYO_TYPE_MANUAL_TASK_ACL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) perm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) perm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) count += hweight16(perm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (count < tomoyo_profile(domain->ns, domain->profile)->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) pref[TOMOYO_PREF_MAX_LEARNING_ENTRY])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) WRITE_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED], true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) /* r->granted = false; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) #ifndef CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) pr_warn("WARNING: Domain '%s' has too many ACLs to hold. Stopped learning mode.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) domain->domainname->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) }