1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
2c3ef1500STetsuo Handa /*
3c3ef1500STetsuo Handa * security/tomoyo/util.c
4c3ef1500STetsuo Handa *
50f2a55d5STetsuo Handa * Copyright (C) 2005-2011 NTT DATA CORPORATION
6c3ef1500STetsuo Handa */
7c3ef1500STetsuo Handa
8c3ef1500STetsuo Handa #include <linux/slab.h>
9b2d09103SIngo Molnar #include <linux/rculist.h>
10b2d09103SIngo Molnar
11c3ef1500STetsuo Handa #include "common.h"
12c3ef1500STetsuo Handa
13c3ef1500STetsuo Handa /* Lock for protecting policy. */
14c3ef1500STetsuo Handa DEFINE_MUTEX(tomoyo_policy_lock);
15c3ef1500STetsuo Handa
16c3ef1500STetsuo Handa /* Has /sbin/init started? */
17c3ef1500STetsuo Handa bool tomoyo_policy_loaded;
18c3ef1500STetsuo Handa
192c47ab93STetsuo Handa /*
202c47ab93STetsuo Handa * Mapping table from "enum tomoyo_mac_index" to
212c47ab93STetsuo Handa * "enum tomoyo_mac_category_index".
222c47ab93STetsuo Handa */
232c47ab93STetsuo Handa const u8 tomoyo_index2category[TOMOYO_MAX_MAC_INDEX] = {
242c47ab93STetsuo Handa /* CONFIG::file group */
252c47ab93STetsuo Handa [TOMOYO_MAC_FILE_EXECUTE] = TOMOYO_MAC_CATEGORY_FILE,
262c47ab93STetsuo Handa [TOMOYO_MAC_FILE_OPEN] = TOMOYO_MAC_CATEGORY_FILE,
272c47ab93STetsuo Handa [TOMOYO_MAC_FILE_CREATE] = TOMOYO_MAC_CATEGORY_FILE,
282c47ab93STetsuo Handa [TOMOYO_MAC_FILE_UNLINK] = TOMOYO_MAC_CATEGORY_FILE,
292c47ab93STetsuo Handa [TOMOYO_MAC_FILE_GETATTR] = TOMOYO_MAC_CATEGORY_FILE,
302c47ab93STetsuo Handa [TOMOYO_MAC_FILE_MKDIR] = TOMOYO_MAC_CATEGORY_FILE,
312c47ab93STetsuo Handa [TOMOYO_MAC_FILE_RMDIR] = TOMOYO_MAC_CATEGORY_FILE,
322c47ab93STetsuo Handa [TOMOYO_MAC_FILE_MKFIFO] = TOMOYO_MAC_CATEGORY_FILE,
332c47ab93STetsuo Handa [TOMOYO_MAC_FILE_MKSOCK] = TOMOYO_MAC_CATEGORY_FILE,
342c47ab93STetsuo Handa [TOMOYO_MAC_FILE_TRUNCATE] = TOMOYO_MAC_CATEGORY_FILE,
352c47ab93STetsuo Handa [TOMOYO_MAC_FILE_SYMLINK] = TOMOYO_MAC_CATEGORY_FILE,
362c47ab93STetsuo Handa [TOMOYO_MAC_FILE_MKBLOCK] = TOMOYO_MAC_CATEGORY_FILE,
372c47ab93STetsuo Handa [TOMOYO_MAC_FILE_MKCHAR] = TOMOYO_MAC_CATEGORY_FILE,
382c47ab93STetsuo Handa [TOMOYO_MAC_FILE_LINK] = TOMOYO_MAC_CATEGORY_FILE,
392c47ab93STetsuo Handa [TOMOYO_MAC_FILE_RENAME] = TOMOYO_MAC_CATEGORY_FILE,
402c47ab93STetsuo Handa [TOMOYO_MAC_FILE_CHMOD] = TOMOYO_MAC_CATEGORY_FILE,
412c47ab93STetsuo Handa [TOMOYO_MAC_FILE_CHOWN] = TOMOYO_MAC_CATEGORY_FILE,
422c47ab93STetsuo Handa [TOMOYO_MAC_FILE_CHGRP] = TOMOYO_MAC_CATEGORY_FILE,
432c47ab93STetsuo Handa [TOMOYO_MAC_FILE_IOCTL] = TOMOYO_MAC_CATEGORY_FILE,
442c47ab93STetsuo Handa [TOMOYO_MAC_FILE_CHROOT] = TOMOYO_MAC_CATEGORY_FILE,
452c47ab93STetsuo Handa [TOMOYO_MAC_FILE_MOUNT] = TOMOYO_MAC_CATEGORY_FILE,
462c47ab93STetsuo Handa [TOMOYO_MAC_FILE_UMOUNT] = TOMOYO_MAC_CATEGORY_FILE,
472c47ab93STetsuo Handa [TOMOYO_MAC_FILE_PIVOT_ROOT] = TOMOYO_MAC_CATEGORY_FILE,
48059d84dbSTetsuo Handa /* CONFIG::network group */
49059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_INET_STREAM_BIND] =
50059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
51059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_INET_STREAM_LISTEN] =
52059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
53059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_INET_STREAM_CONNECT] =
54059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
55059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_INET_DGRAM_BIND] =
56059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
57059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_INET_DGRAM_SEND] =
58059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
59059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_INET_RAW_BIND] =
60059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
61059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_INET_RAW_SEND] =
62059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
63059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_UNIX_STREAM_BIND] =
64059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
65059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_UNIX_STREAM_LISTEN] =
66059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
67059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_UNIX_STREAM_CONNECT] =
68059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
69059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_UNIX_DGRAM_BIND] =
70059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
71059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_UNIX_DGRAM_SEND] =
72059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
73059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_BIND] =
74059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
75059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_LISTEN] =
76059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
77059d84dbSTetsuo Handa [TOMOYO_MAC_NETWORK_UNIX_SEQPACKET_CONNECT] =
78059d84dbSTetsuo Handa TOMOYO_MAC_CATEGORY_NETWORK,
79d58e0da8STetsuo Handa /* CONFIG::misc group */
80d58e0da8STetsuo Handa [TOMOYO_MAC_ENVIRON] = TOMOYO_MAC_CATEGORY_MISC,
812c47ab93STetsuo Handa };
822c47ab93STetsuo Handa
83c3ef1500STetsuo Handa /**
84b22b8b9fSTetsuo Handa * tomoyo_convert_time - Convert time_t to YYYY/MM/DD hh/mm/ss.
85b22b8b9fSTetsuo Handa *
8698eaa63eSChenXiaoSong * @time64: Seconds since 1970/01/01 00:00:00.
87b22b8b9fSTetsuo Handa * @stamp: Pointer to "struct tomoyo_time".
88b22b8b9fSTetsuo Handa *
89b22b8b9fSTetsuo Handa * Returns nothing.
90b22b8b9fSTetsuo Handa */
tomoyo_convert_time(time64_t time64,struct tomoyo_time * stamp)9192734092SArnd Bergmann void tomoyo_convert_time(time64_t time64, struct tomoyo_time *stamp)
92b22b8b9fSTetsuo Handa {
9392734092SArnd Bergmann struct tm tm;
94cdcf6723STetsuo Handa
9592734092SArnd Bergmann time64_to_tm(time64, 0, &tm);
9692734092SArnd Bergmann stamp->sec = tm.tm_sec;
9792734092SArnd Bergmann stamp->min = tm.tm_min;
9892734092SArnd Bergmann stamp->hour = tm.tm_hour;
9992734092SArnd Bergmann stamp->day = tm.tm_mday;
10092734092SArnd Bergmann stamp->month = tm.tm_mon + 1;
10192734092SArnd Bergmann stamp->year = tm.tm_year + 1900;
102b22b8b9fSTetsuo Handa }
103b22b8b9fSTetsuo Handa
104b22b8b9fSTetsuo Handa /**
105a238cf5bSTetsuo Handa * tomoyo_permstr - Find permission keywords.
106a238cf5bSTetsuo Handa *
107a238cf5bSTetsuo Handa * @string: String representation for permissions in foo/bar/buz format.
108a238cf5bSTetsuo Handa * @keyword: Keyword to find from @string/
109a238cf5bSTetsuo Handa *
110f09c296eSYangtao Li * Returns true if @keyword was found in @string, false otherwise.
111a238cf5bSTetsuo Handa *
112a238cf5bSTetsuo Handa * This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2.
113a238cf5bSTetsuo Handa */
tomoyo_permstr(const char * string,const char * keyword)114a238cf5bSTetsuo Handa bool tomoyo_permstr(const char *string, const char *keyword)
115a238cf5bSTetsuo Handa {
116a238cf5bSTetsuo Handa const char *cp = strstr(string, keyword);
117cdcf6723STetsuo Handa
118a238cf5bSTetsuo Handa if (cp)
119a238cf5bSTetsuo Handa return cp == string || *(cp - 1) == '/';
120a238cf5bSTetsuo Handa return false;
121a238cf5bSTetsuo Handa }
122a238cf5bSTetsuo Handa
123a238cf5bSTetsuo Handa /**
124a238cf5bSTetsuo Handa * tomoyo_read_token - Read a word from a line.
125a238cf5bSTetsuo Handa *
126a238cf5bSTetsuo Handa * @param: Pointer to "struct tomoyo_acl_param".
127a238cf5bSTetsuo Handa *
128a238cf5bSTetsuo Handa * Returns a word on success, "" otherwise.
129a238cf5bSTetsuo Handa *
130a238cf5bSTetsuo Handa * To allow the caller to skip NULL check, this function returns "" rather than
131a238cf5bSTetsuo Handa * NULL if there is no more words to read.
132a238cf5bSTetsuo Handa */
tomoyo_read_token(struct tomoyo_acl_param * param)133a238cf5bSTetsuo Handa char *tomoyo_read_token(struct tomoyo_acl_param *param)
134a238cf5bSTetsuo Handa {
135a238cf5bSTetsuo Handa char *pos = param->data;
136a238cf5bSTetsuo Handa char *del = strchr(pos, ' ');
137cdcf6723STetsuo Handa
138a238cf5bSTetsuo Handa if (del)
139a238cf5bSTetsuo Handa *del++ = '\0';
140a238cf5bSTetsuo Handa else
141a238cf5bSTetsuo Handa del = pos + strlen(pos);
142a238cf5bSTetsuo Handa param->data = del;
143a238cf5bSTetsuo Handa return pos;
144a238cf5bSTetsuo Handa }
145a238cf5bSTetsuo Handa
146a2075167STetsuo Handa static bool tomoyo_correct_path2(const char *filename, const size_t len);
147a2075167STetsuo Handa
148a238cf5bSTetsuo Handa /**
149731d37aaSTetsuo Handa * tomoyo_get_domainname - Read a domainname from a line.
150731d37aaSTetsuo Handa *
151731d37aaSTetsuo Handa * @param: Pointer to "struct tomoyo_acl_param".
152731d37aaSTetsuo Handa *
153731d37aaSTetsuo Handa * Returns a domainname on success, NULL otherwise.
154731d37aaSTetsuo Handa */
tomoyo_get_domainname(struct tomoyo_acl_param * param)155731d37aaSTetsuo Handa const struct tomoyo_path_info *tomoyo_get_domainname
156731d37aaSTetsuo Handa (struct tomoyo_acl_param *param)
157731d37aaSTetsuo Handa {
158731d37aaSTetsuo Handa char *start = param->data;
159731d37aaSTetsuo Handa char *pos = start;
160cdcf6723STetsuo Handa
161731d37aaSTetsuo Handa while (*pos) {
162a2075167STetsuo Handa if (*pos++ != ' ' ||
163a2075167STetsuo Handa tomoyo_correct_path2(pos, strchrnul(pos, ' ') - pos))
164731d37aaSTetsuo Handa continue;
165a2075167STetsuo Handa *(pos - 1) = '\0';
166731d37aaSTetsuo Handa break;
167731d37aaSTetsuo Handa }
168731d37aaSTetsuo Handa param->data = pos;
169731d37aaSTetsuo Handa if (tomoyo_correct_domain(start))
170731d37aaSTetsuo Handa return tomoyo_get_name(start);
171731d37aaSTetsuo Handa return NULL;
172731d37aaSTetsuo Handa }
173731d37aaSTetsuo Handa
174731d37aaSTetsuo Handa /**
175c3ef1500STetsuo Handa * tomoyo_parse_ulong - Parse an "unsigned long" value.
176c3ef1500STetsuo Handa *
177c3ef1500STetsuo Handa * @result: Pointer to "unsigned long".
178c3ef1500STetsuo Handa * @str: Pointer to string to parse.
179c3ef1500STetsuo Handa *
1800df7e8b8STetsuo Handa * Returns one of values in "enum tomoyo_value_type".
181c3ef1500STetsuo Handa *
182c3ef1500STetsuo Handa * The @src is updated to point the first character after the value
183c3ef1500STetsuo Handa * on success.
184c3ef1500STetsuo Handa */
tomoyo_parse_ulong(unsigned long * result,char ** str)1852066a361STetsuo Handa u8 tomoyo_parse_ulong(unsigned long *result, char **str)
186c3ef1500STetsuo Handa {
187c3ef1500STetsuo Handa const char *cp = *str;
188c3ef1500STetsuo Handa char *ep;
189c3ef1500STetsuo Handa int base = 10;
190cdcf6723STetsuo Handa
191c3ef1500STetsuo Handa if (*cp == '0') {
192c3ef1500STetsuo Handa char c = *(cp + 1);
193cdcf6723STetsuo Handa
194c3ef1500STetsuo Handa if (c == 'x' || c == 'X') {
195c3ef1500STetsuo Handa base = 16;
196c3ef1500STetsuo Handa cp += 2;
197c3ef1500STetsuo Handa } else if (c >= '0' && c <= '7') {
198c3ef1500STetsuo Handa base = 8;
199c3ef1500STetsuo Handa cp++;
200c3ef1500STetsuo Handa }
201c3ef1500STetsuo Handa }
202c3ef1500STetsuo Handa *result = simple_strtoul(cp, &ep, base);
203c3ef1500STetsuo Handa if (cp == ep)
2040df7e8b8STetsuo Handa return TOMOYO_VALUE_TYPE_INVALID;
205c3ef1500STetsuo Handa *str = ep;
206c3ef1500STetsuo Handa switch (base) {
207c3ef1500STetsuo Handa case 16:
208c3ef1500STetsuo Handa return TOMOYO_VALUE_TYPE_HEXADECIMAL;
209c3ef1500STetsuo Handa case 8:
210c3ef1500STetsuo Handa return TOMOYO_VALUE_TYPE_OCTAL;
211c3ef1500STetsuo Handa default:
212c3ef1500STetsuo Handa return TOMOYO_VALUE_TYPE_DECIMAL;
213c3ef1500STetsuo Handa }
214c3ef1500STetsuo Handa }
215c3ef1500STetsuo Handa
216c3ef1500STetsuo Handa /**
217c3ef1500STetsuo Handa * tomoyo_print_ulong - Print an "unsigned long" value.
218c3ef1500STetsuo Handa *
219c3ef1500STetsuo Handa * @buffer: Pointer to buffer.
220c3ef1500STetsuo Handa * @buffer_len: Size of @buffer.
221c3ef1500STetsuo Handa * @value: An "unsigned long" value.
222c3ef1500STetsuo Handa * @type: Type of @value.
223c3ef1500STetsuo Handa *
224c3ef1500STetsuo Handa * Returns nothing.
225c3ef1500STetsuo Handa */
tomoyo_print_ulong(char * buffer,const int buffer_len,const unsigned long value,const u8 type)226c3ef1500STetsuo Handa void tomoyo_print_ulong(char *buffer, const int buffer_len,
227c3ef1500STetsuo Handa const unsigned long value, const u8 type)
228c3ef1500STetsuo Handa {
229c3ef1500STetsuo Handa if (type == TOMOYO_VALUE_TYPE_DECIMAL)
230c3ef1500STetsuo Handa snprintf(buffer, buffer_len, "%lu", value);
231c3ef1500STetsuo Handa else if (type == TOMOYO_VALUE_TYPE_OCTAL)
232c3ef1500STetsuo Handa snprintf(buffer, buffer_len, "0%lo", value);
233c3ef1500STetsuo Handa else if (type == TOMOYO_VALUE_TYPE_HEXADECIMAL)
234c3ef1500STetsuo Handa snprintf(buffer, buffer_len, "0x%lX", value);
235c3ef1500STetsuo Handa else
236c3ef1500STetsuo Handa snprintf(buffer, buffer_len, "type(%u)", type);
237c3ef1500STetsuo Handa }
238c3ef1500STetsuo Handa
239c3ef1500STetsuo Handa /**
240c3ef1500STetsuo Handa * tomoyo_parse_name_union - Parse a tomoyo_name_union.
241c3ef1500STetsuo Handa *
242a238cf5bSTetsuo Handa * @param: Pointer to "struct tomoyo_acl_param".
243c3ef1500STetsuo Handa * @ptr: Pointer to "struct tomoyo_name_union".
244c3ef1500STetsuo Handa *
245c3ef1500STetsuo Handa * Returns true on success, false otherwise.
246c3ef1500STetsuo Handa */
tomoyo_parse_name_union(struct tomoyo_acl_param * param,struct tomoyo_name_union * ptr)247a238cf5bSTetsuo Handa bool tomoyo_parse_name_union(struct tomoyo_acl_param *param,
248c3ef1500STetsuo Handa struct tomoyo_name_union *ptr)
249c3ef1500STetsuo Handa {
250a238cf5bSTetsuo Handa char *filename;
251cdcf6723STetsuo Handa
252a238cf5bSTetsuo Handa if (param->data[0] == '@') {
253a238cf5bSTetsuo Handa param->data++;
254a238cf5bSTetsuo Handa ptr->group = tomoyo_get_group(param, TOMOYO_PATH_GROUP);
255c3ef1500STetsuo Handa return ptr->group != NULL;
256c3ef1500STetsuo Handa }
257a238cf5bSTetsuo Handa filename = tomoyo_read_token(param);
258a238cf5bSTetsuo Handa if (!tomoyo_correct_word(filename))
259a238cf5bSTetsuo Handa return false;
260c3ef1500STetsuo Handa ptr->filename = tomoyo_get_name(filename);
261c3ef1500STetsuo Handa return ptr->filename != NULL;
262c3ef1500STetsuo Handa }
263c3ef1500STetsuo Handa
264c3ef1500STetsuo Handa /**
265c3ef1500STetsuo Handa * tomoyo_parse_number_union - Parse a tomoyo_number_union.
266c3ef1500STetsuo Handa *
267a238cf5bSTetsuo Handa * @param: Pointer to "struct tomoyo_acl_param".
268c3ef1500STetsuo Handa * @ptr: Pointer to "struct tomoyo_number_union".
269c3ef1500STetsuo Handa *
270c3ef1500STetsuo Handa * Returns true on success, false otherwise.
271c3ef1500STetsuo Handa */
tomoyo_parse_number_union(struct tomoyo_acl_param * param,struct tomoyo_number_union * ptr)272a238cf5bSTetsuo Handa bool tomoyo_parse_number_union(struct tomoyo_acl_param *param,
273a238cf5bSTetsuo Handa struct tomoyo_number_union *ptr)
274c3ef1500STetsuo Handa {
275a238cf5bSTetsuo Handa char *data;
276c3ef1500STetsuo Handa u8 type;
277c3ef1500STetsuo Handa unsigned long v;
278cdcf6723STetsuo Handa
279a238cf5bSTetsuo Handa memset(ptr, 0, sizeof(*ptr));
280a238cf5bSTetsuo Handa if (param->data[0] == '@') {
281a238cf5bSTetsuo Handa param->data++;
282a238cf5bSTetsuo Handa ptr->group = tomoyo_get_group(param, TOMOYO_NUMBER_GROUP);
283a238cf5bSTetsuo Handa return ptr->group != NULL;
284c3ef1500STetsuo Handa }
285a238cf5bSTetsuo Handa data = tomoyo_read_token(param);
286c3ef1500STetsuo Handa type = tomoyo_parse_ulong(&v, &data);
287a238cf5bSTetsuo Handa if (type == TOMOYO_VALUE_TYPE_INVALID)
288c3ef1500STetsuo Handa return false;
289a238cf5bSTetsuo Handa ptr->values[0] = v;
290a238cf5bSTetsuo Handa ptr->value_type[0] = type;
291c3ef1500STetsuo Handa if (!*data) {
292a238cf5bSTetsuo Handa ptr->values[1] = v;
293a238cf5bSTetsuo Handa ptr->value_type[1] = type;
294c3ef1500STetsuo Handa return true;
295c3ef1500STetsuo Handa }
296c3ef1500STetsuo Handa if (*data++ != '-')
297c3ef1500STetsuo Handa return false;
298c3ef1500STetsuo Handa type = tomoyo_parse_ulong(&v, &data);
299a238cf5bSTetsuo Handa if (type == TOMOYO_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
300c3ef1500STetsuo Handa return false;
301a238cf5bSTetsuo Handa ptr->values[1] = v;
302a238cf5bSTetsuo Handa ptr->value_type[1] = type;
303c3ef1500STetsuo Handa return true;
304c3ef1500STetsuo Handa }
305c3ef1500STetsuo Handa
306c3ef1500STetsuo Handa /**
30775093152STetsuo Handa * tomoyo_byte_range - Check whether the string is a \ooo style octal value.
308c3ef1500STetsuo Handa *
309c3ef1500STetsuo Handa * @str: Pointer to the string.
310c3ef1500STetsuo Handa *
311c3ef1500STetsuo Handa * Returns true if @str is a \ooo style octal value, false otherwise.
312c3ef1500STetsuo Handa *
313c3ef1500STetsuo Handa * TOMOYO uses \ooo style representation for 0x01 - 0x20 and 0x7F - 0xFF.
314c3ef1500STetsuo Handa * This function verifies that \ooo is in valid range.
315c3ef1500STetsuo Handa */
tomoyo_byte_range(const char * str)31675093152STetsuo Handa static inline bool tomoyo_byte_range(const char *str)
317c3ef1500STetsuo Handa {
318c3ef1500STetsuo Handa return *str >= '0' && *str++ <= '3' &&
319c3ef1500STetsuo Handa *str >= '0' && *str++ <= '7' &&
320c3ef1500STetsuo Handa *str >= '0' && *str <= '7';
321c3ef1500STetsuo Handa }
322c3ef1500STetsuo Handa
323c3ef1500STetsuo Handa /**
32475093152STetsuo Handa * tomoyo_alphabet_char - Check whether the character is an alphabet.
325c3ef1500STetsuo Handa *
326c3ef1500STetsuo Handa * @c: The character to check.
327c3ef1500STetsuo Handa *
328c3ef1500STetsuo Handa * Returns true if @c is an alphabet character, false otherwise.
329c3ef1500STetsuo Handa */
tomoyo_alphabet_char(const char c)33075093152STetsuo Handa static inline bool tomoyo_alphabet_char(const char c)
331c3ef1500STetsuo Handa {
332c3ef1500STetsuo Handa return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
333c3ef1500STetsuo Handa }
334c3ef1500STetsuo Handa
335c3ef1500STetsuo Handa /**
336c3ef1500STetsuo Handa * tomoyo_make_byte - Make byte value from three octal characters.
337c3ef1500STetsuo Handa *
338c3ef1500STetsuo Handa * @c1: The first character.
339c3ef1500STetsuo Handa * @c2: The second character.
340c3ef1500STetsuo Handa * @c3: The third character.
341c3ef1500STetsuo Handa *
342c3ef1500STetsuo Handa * Returns byte value.
343c3ef1500STetsuo Handa */
tomoyo_make_byte(const u8 c1,const u8 c2,const u8 c3)344c3ef1500STetsuo Handa static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3)
345c3ef1500STetsuo Handa {
346c3ef1500STetsuo Handa return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
347c3ef1500STetsuo Handa }
348c3ef1500STetsuo Handa
349c3ef1500STetsuo Handa /**
3500df7e8b8STetsuo Handa * tomoyo_valid - Check whether the character is a valid char.
3510df7e8b8STetsuo Handa *
3520df7e8b8STetsuo Handa * @c: The character to check.
3530df7e8b8STetsuo Handa *
3540df7e8b8STetsuo Handa * Returns true if @c is a valid character, false otherwise.
3550df7e8b8STetsuo Handa */
tomoyo_valid(const unsigned char c)3560df7e8b8STetsuo Handa static inline bool tomoyo_valid(const unsigned char c)
3570df7e8b8STetsuo Handa {
3580df7e8b8STetsuo Handa return c > ' ' && c < 127;
3590df7e8b8STetsuo Handa }
3600df7e8b8STetsuo Handa
3610df7e8b8STetsuo Handa /**
3620df7e8b8STetsuo Handa * tomoyo_invalid - Check whether the character is an invalid char.
3630df7e8b8STetsuo Handa *
3640df7e8b8STetsuo Handa * @c: The character to check.
3650df7e8b8STetsuo Handa *
3660df7e8b8STetsuo Handa * Returns true if @c is an invalid character, false otherwise.
3670df7e8b8STetsuo Handa */
tomoyo_invalid(const unsigned char c)3680df7e8b8STetsuo Handa static inline bool tomoyo_invalid(const unsigned char c)
3690df7e8b8STetsuo Handa {
3700df7e8b8STetsuo Handa return c && (c <= ' ' || c >= 127);
3710df7e8b8STetsuo Handa }
3720df7e8b8STetsuo Handa
3730df7e8b8STetsuo Handa /**
374c3ef1500STetsuo Handa * tomoyo_str_starts - Check whether the given string starts with the given keyword.
375c3ef1500STetsuo Handa *
376c3ef1500STetsuo Handa * @src: Pointer to pointer to the string.
377c3ef1500STetsuo Handa * @find: Pointer to the keyword.
378c3ef1500STetsuo Handa *
379c3ef1500STetsuo Handa * Returns true if @src starts with @find, false otherwise.
380c3ef1500STetsuo Handa *
381c3ef1500STetsuo Handa * The @src is updated to point the first character after the @find
382c3ef1500STetsuo Handa * if @src starts with @find.
383c3ef1500STetsuo Handa */
tomoyo_str_starts(char ** src,const char * find)384c3ef1500STetsuo Handa bool tomoyo_str_starts(char **src, const char *find)
385c3ef1500STetsuo Handa {
386c3ef1500STetsuo Handa const int len = strlen(find);
387c3ef1500STetsuo Handa char *tmp = *src;
388c3ef1500STetsuo Handa
389c3ef1500STetsuo Handa if (strncmp(tmp, find, len))
390c3ef1500STetsuo Handa return false;
391c3ef1500STetsuo Handa tmp += len;
392c3ef1500STetsuo Handa *src = tmp;
393c3ef1500STetsuo Handa return true;
394c3ef1500STetsuo Handa }
395c3ef1500STetsuo Handa
396c3ef1500STetsuo Handa /**
397c3ef1500STetsuo Handa * tomoyo_normalize_line - Format string.
398c3ef1500STetsuo Handa *
399c3ef1500STetsuo Handa * @buffer: The line to normalize.
400c3ef1500STetsuo Handa *
401c3ef1500STetsuo Handa * Leading and trailing whitespaces are removed.
402c3ef1500STetsuo Handa * Multiple whitespaces are packed into single space.
403c3ef1500STetsuo Handa *
404c3ef1500STetsuo Handa * Returns nothing.
405c3ef1500STetsuo Handa */
tomoyo_normalize_line(unsigned char * buffer)406c3ef1500STetsuo Handa void tomoyo_normalize_line(unsigned char *buffer)
407c3ef1500STetsuo Handa {
408c3ef1500STetsuo Handa unsigned char *sp = buffer;
409c3ef1500STetsuo Handa unsigned char *dp = buffer;
410c3ef1500STetsuo Handa bool first = true;
411c3ef1500STetsuo Handa
41275093152STetsuo Handa while (tomoyo_invalid(*sp))
413c3ef1500STetsuo Handa sp++;
414c3ef1500STetsuo Handa while (*sp) {
415c3ef1500STetsuo Handa if (!first)
416c3ef1500STetsuo Handa *dp++ = ' ';
417c3ef1500STetsuo Handa first = false;
41875093152STetsuo Handa while (tomoyo_valid(*sp))
419c3ef1500STetsuo Handa *dp++ = *sp++;
42075093152STetsuo Handa while (tomoyo_invalid(*sp))
421c3ef1500STetsuo Handa sp++;
422c3ef1500STetsuo Handa }
423c3ef1500STetsuo Handa *dp = '\0';
424c3ef1500STetsuo Handa }
425c3ef1500STetsuo Handa
426c3ef1500STetsuo Handa /**
42775093152STetsuo Handa * tomoyo_correct_word2 - Validate a string.
428c3ef1500STetsuo Handa *
4293f629636STetsuo Handa * @string: The string to check. Maybe non-'\0'-terminated.
4303f629636STetsuo Handa * @len: Length of @string.
431c3ef1500STetsuo Handa *
4323f629636STetsuo Handa * Check whether the given string follows the naming rules.
4333f629636STetsuo Handa * Returns true if @string follows the naming rules, false otherwise.
434c3ef1500STetsuo Handa */
tomoyo_correct_word2(const char * string,size_t len)43575093152STetsuo Handa static bool tomoyo_correct_word2(const char *string, size_t len)
436c3ef1500STetsuo Handa {
437e991a40bSTetsuo Handa u8 recursion = 20;
4383f629636STetsuo Handa const char *const start = string;
439c3ef1500STetsuo Handa bool in_repetition = false;
440cdcf6723STetsuo Handa
4413f629636STetsuo Handa if (!len)
442c3ef1500STetsuo Handa goto out;
4433f629636STetsuo Handa while (len--) {
444e991a40bSTetsuo Handa unsigned char c = *string++;
445e991a40bSTetsuo Handa
446c3ef1500STetsuo Handa if (c == '\\') {
4473f629636STetsuo Handa if (!len--)
4483f629636STetsuo Handa goto out;
4493f629636STetsuo Handa c = *string++;
450e991a40bSTetsuo Handa if (c >= '0' && c <= '3') {
451e991a40bSTetsuo Handa unsigned char d;
452e991a40bSTetsuo Handa unsigned char e;
453e991a40bSTetsuo Handa
454e991a40bSTetsuo Handa if (!len-- || !len--)
455e991a40bSTetsuo Handa goto out;
456e991a40bSTetsuo Handa d = *string++;
457e991a40bSTetsuo Handa e = *string++;
458e991a40bSTetsuo Handa if (d < '0' || d > '7' || e < '0' || e > '7')
459e991a40bSTetsuo Handa goto out;
460e991a40bSTetsuo Handa c = tomoyo_make_byte(c, d, e);
461e991a40bSTetsuo Handa if (c <= ' ' || c >= 127)
462e991a40bSTetsuo Handa continue;
463e991a40bSTetsuo Handa goto out;
464e991a40bSTetsuo Handa }
465c3ef1500STetsuo Handa switch (c) {
466c3ef1500STetsuo Handa case '\\': /* "\\" */
467c3ef1500STetsuo Handa case '+': /* "\+" */
468c3ef1500STetsuo Handa case '?': /* "\?" */
469e991a40bSTetsuo Handa case 'x': /* "\x" */
470e991a40bSTetsuo Handa case 'a': /* "\a" */
471e991a40bSTetsuo Handa case '-': /* "\-" */
472e991a40bSTetsuo Handa continue;
473e991a40bSTetsuo Handa }
474e991a40bSTetsuo Handa if (!recursion--)
475e991a40bSTetsuo Handa goto out;
476e991a40bSTetsuo Handa switch (c) {
477c3ef1500STetsuo Handa case '*': /* "\*" */
478c3ef1500STetsuo Handa case '@': /* "\@" */
479e991a40bSTetsuo Handa case '$': /* "\$" */
480c3ef1500STetsuo Handa case 'X': /* "\X" */
481c3ef1500STetsuo Handa case 'A': /* "\A" */
482c3ef1500STetsuo Handa continue;
483c3ef1500STetsuo Handa case '{': /* "/\{" */
4843f629636STetsuo Handa if (string - 3 < start || *(string - 3) != '/')
485e991a40bSTetsuo Handa goto out;
486c3ef1500STetsuo Handa in_repetition = true;
487c3ef1500STetsuo Handa continue;
488c3ef1500STetsuo Handa case '}': /* "\}/" */
4893f629636STetsuo Handa if (*string != '/')
490e991a40bSTetsuo Handa goto out;
491c3ef1500STetsuo Handa if (!in_repetition)
492e991a40bSTetsuo Handa goto out;
493c3ef1500STetsuo Handa in_repetition = false;
494c3ef1500STetsuo Handa continue;
495c3ef1500STetsuo Handa }
496c3ef1500STetsuo Handa goto out;
497c3ef1500STetsuo Handa } else if (in_repetition && c == '/') {
498c3ef1500STetsuo Handa goto out;
49925add8cfSTetsuo Handa } else if (c <= ' ' || c >= 127) {
500c3ef1500STetsuo Handa goto out;
501c3ef1500STetsuo Handa }
502c3ef1500STetsuo Handa }
503c3ef1500STetsuo Handa if (in_repetition)
504c3ef1500STetsuo Handa goto out;
505c3ef1500STetsuo Handa return true;
506c3ef1500STetsuo Handa out:
507c3ef1500STetsuo Handa return false;
508c3ef1500STetsuo Handa }
509c3ef1500STetsuo Handa
510c3ef1500STetsuo Handa /**
51175093152STetsuo Handa * tomoyo_correct_word - Validate a string.
5123f629636STetsuo Handa *
5133f629636STetsuo Handa * @string: The string to check.
5143f629636STetsuo Handa *
5153f629636STetsuo Handa * Check whether the given string follows the naming rules.
5163f629636STetsuo Handa * Returns true if @string follows the naming rules, false otherwise.
5173f629636STetsuo Handa */
tomoyo_correct_word(const char * string)51875093152STetsuo Handa bool tomoyo_correct_word(const char *string)
5193f629636STetsuo Handa {
52075093152STetsuo Handa return tomoyo_correct_word2(string, strlen(string));
5213f629636STetsuo Handa }
5223f629636STetsuo Handa
5233f629636STetsuo Handa /**
524a2075167STetsuo Handa * tomoyo_correct_path2 - Check whether the given pathname follows the naming rules.
525a2075167STetsuo Handa *
526a2075167STetsuo Handa * @filename: The pathname to check.
527a2075167STetsuo Handa * @len: Length of @filename.
528a2075167STetsuo Handa *
529a2075167STetsuo Handa * Returns true if @filename follows the naming rules, false otherwise.
530a2075167STetsuo Handa */
tomoyo_correct_path2(const char * filename,const size_t len)531a2075167STetsuo Handa static bool tomoyo_correct_path2(const char *filename, const size_t len)
532a2075167STetsuo Handa {
533a2075167STetsuo Handa const char *cp1 = memchr(filename, '/', len);
534a2075167STetsuo Handa const char *cp2 = memchr(filename, '.', len);
535a2075167STetsuo Handa
536a2075167STetsuo Handa return cp1 && (!cp2 || (cp1 < cp2)) && tomoyo_correct_word2(filename, len);
537a2075167STetsuo Handa }
538a2075167STetsuo Handa
539a2075167STetsuo Handa /**
54075093152STetsuo Handa * tomoyo_correct_path - Validate a pathname.
5413f629636STetsuo Handa *
5423f629636STetsuo Handa * @filename: The pathname to check.
5433f629636STetsuo Handa *
5443f629636STetsuo Handa * Check whether the given pathname follows the naming rules.
5453f629636STetsuo Handa * Returns true if @filename follows the naming rules, false otherwise.
5463f629636STetsuo Handa */
tomoyo_correct_path(const char * filename)54775093152STetsuo Handa bool tomoyo_correct_path(const char *filename)
5483f629636STetsuo Handa {
549a2075167STetsuo Handa return tomoyo_correct_path2(filename, strlen(filename));
5503f629636STetsuo Handa }
5513f629636STetsuo Handa
5523f629636STetsuo Handa /**
55375093152STetsuo Handa * tomoyo_correct_domain - Check whether the given domainname follows the naming rules.
554c3ef1500STetsuo Handa *
555c3ef1500STetsuo Handa * @domainname: The domainname to check.
556c3ef1500STetsuo Handa *
557c3ef1500STetsuo Handa * Returns true if @domainname follows the naming rules, false otherwise.
558c3ef1500STetsuo Handa */
tomoyo_correct_domain(const unsigned char * domainname)55975093152STetsuo Handa bool tomoyo_correct_domain(const unsigned char *domainname)
560c3ef1500STetsuo Handa {
561bd03a3e4STetsuo Handa if (!domainname || !tomoyo_domain_def(domainname))
562bd03a3e4STetsuo Handa return false;
563bd03a3e4STetsuo Handa domainname = strchr(domainname, ' ');
564bd03a3e4STetsuo Handa if (!domainname++)
565c3ef1500STetsuo Handa return true;
5663f629636STetsuo Handa while (1) {
5673f629636STetsuo Handa const unsigned char *cp = strchr(domainname, ' ');
568cdcf6723STetsuo Handa
5693f629636STetsuo Handa if (!cp)
570c3ef1500STetsuo Handa break;
571a2075167STetsuo Handa if (!tomoyo_correct_path2(domainname, cp - domainname))
572bd03a3e4STetsuo Handa return false;
5733f629636STetsuo Handa domainname = cp + 1;
574c3ef1500STetsuo Handa }
57575093152STetsuo Handa return tomoyo_correct_path(domainname);
576c3ef1500STetsuo Handa }
577c3ef1500STetsuo Handa
578c3ef1500STetsuo Handa /**
57975093152STetsuo Handa * tomoyo_domain_def - Check whether the given token can be a domainname.
580c3ef1500STetsuo Handa *
581c3ef1500STetsuo Handa * @buffer: The token to check.
582c3ef1500STetsuo Handa *
583c3ef1500STetsuo Handa * Returns true if @buffer possibly be a domainname, false otherwise.
584c3ef1500STetsuo Handa */
tomoyo_domain_def(const unsigned char * buffer)58575093152STetsuo Handa bool tomoyo_domain_def(const unsigned char *buffer)
586c3ef1500STetsuo Handa {
587bd03a3e4STetsuo Handa const unsigned char *cp;
588bd03a3e4STetsuo Handa int len;
589cdcf6723STetsuo Handa
590bd03a3e4STetsuo Handa if (*buffer != '<')
591bd03a3e4STetsuo Handa return false;
592bd03a3e4STetsuo Handa cp = strchr(buffer, ' ');
593bd03a3e4STetsuo Handa if (!cp)
594bd03a3e4STetsuo Handa len = strlen(buffer);
595bd03a3e4STetsuo Handa else
596bd03a3e4STetsuo Handa len = cp - buffer;
597bd03a3e4STetsuo Handa if (buffer[len - 1] != '>' ||
598bd03a3e4STetsuo Handa !tomoyo_correct_word2(buffer + 1, len - 2))
599bd03a3e4STetsuo Handa return false;
600bd03a3e4STetsuo Handa return true;
601c3ef1500STetsuo Handa }
602c3ef1500STetsuo Handa
603c3ef1500STetsuo Handa /**
604c3ef1500STetsuo Handa * tomoyo_find_domain - Find a domain by the given name.
605c3ef1500STetsuo Handa *
606c3ef1500STetsuo Handa * @domainname: The domainname to find.
607c3ef1500STetsuo Handa *
608c3ef1500STetsuo Handa * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise.
609c3ef1500STetsuo Handa *
610c3ef1500STetsuo Handa * Caller holds tomoyo_read_lock().
611c3ef1500STetsuo Handa */
tomoyo_find_domain(const char * domainname)612c3ef1500STetsuo Handa struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
613c3ef1500STetsuo Handa {
614c3ef1500STetsuo Handa struct tomoyo_domain_info *domain;
615c3ef1500STetsuo Handa struct tomoyo_path_info name;
616c3ef1500STetsuo Handa
617c3ef1500STetsuo Handa name.name = domainname;
618c3ef1500STetsuo Handa tomoyo_fill_path_info(&name);
6196bd5ce60STetsuo Handa list_for_each_entry_rcu(domain, &tomoyo_domain_list, list,
6206bd5ce60STetsuo Handa srcu_read_lock_held(&tomoyo_ss)) {
621c3ef1500STetsuo Handa if (!domain->is_deleted &&
622c3ef1500STetsuo Handa !tomoyo_pathcmp(&name, domain->domainname))
623c3ef1500STetsuo Handa return domain;
624c3ef1500STetsuo Handa }
625c3ef1500STetsuo Handa return NULL;
626c3ef1500STetsuo Handa }
627c3ef1500STetsuo Handa
628c3ef1500STetsuo Handa /**
629c3ef1500STetsuo Handa * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token.
630c3ef1500STetsuo Handa *
631c3ef1500STetsuo Handa * @filename: The string to evaluate.
632c3ef1500STetsuo Handa *
633c3ef1500STetsuo Handa * Returns the initial length without a pattern in @filename.
634c3ef1500STetsuo Handa */
tomoyo_const_part_length(const char * filename)635c3ef1500STetsuo Handa static int tomoyo_const_part_length(const char *filename)
636c3ef1500STetsuo Handa {
637c3ef1500STetsuo Handa char c;
638c3ef1500STetsuo Handa int len = 0;
639c3ef1500STetsuo Handa
640c3ef1500STetsuo Handa if (!filename)
641c3ef1500STetsuo Handa return 0;
642c3ef1500STetsuo Handa while ((c = *filename++) != '\0') {
643c3ef1500STetsuo Handa if (c != '\\') {
644c3ef1500STetsuo Handa len++;
645c3ef1500STetsuo Handa continue;
646c3ef1500STetsuo Handa }
647c3ef1500STetsuo Handa c = *filename++;
648c3ef1500STetsuo Handa switch (c) {
649c3ef1500STetsuo Handa case '\\': /* "\\" */
650c3ef1500STetsuo Handa len += 2;
651c3ef1500STetsuo Handa continue;
652c3ef1500STetsuo Handa case '0': /* "\ooo" */
653c3ef1500STetsuo Handa case '1':
654c3ef1500STetsuo Handa case '2':
655c3ef1500STetsuo Handa case '3':
656c3ef1500STetsuo Handa c = *filename++;
657c3ef1500STetsuo Handa if (c < '0' || c > '7')
658c3ef1500STetsuo Handa break;
659c3ef1500STetsuo Handa c = *filename++;
660c3ef1500STetsuo Handa if (c < '0' || c > '7')
661c3ef1500STetsuo Handa break;
662c3ef1500STetsuo Handa len += 4;
663c3ef1500STetsuo Handa continue;
664c3ef1500STetsuo Handa }
665c3ef1500STetsuo Handa break;
666c3ef1500STetsuo Handa }
667c3ef1500STetsuo Handa return len;
668c3ef1500STetsuo Handa }
669c3ef1500STetsuo Handa
670c3ef1500STetsuo Handa /**
671c3ef1500STetsuo Handa * tomoyo_fill_path_info - Fill in "struct tomoyo_path_info" members.
672c3ef1500STetsuo Handa *
673c3ef1500STetsuo Handa * @ptr: Pointer to "struct tomoyo_path_info" to fill in.
674c3ef1500STetsuo Handa *
675c3ef1500STetsuo Handa * The caller sets "struct tomoyo_path_info"->name.
676c3ef1500STetsuo Handa */
tomoyo_fill_path_info(struct tomoyo_path_info * ptr)677c3ef1500STetsuo Handa void tomoyo_fill_path_info(struct tomoyo_path_info *ptr)
678c3ef1500STetsuo Handa {
679c3ef1500STetsuo Handa const char *name = ptr->name;
680c3ef1500STetsuo Handa const int len = strlen(name);
681c3ef1500STetsuo Handa
682c3ef1500STetsuo Handa ptr->const_len = tomoyo_const_part_length(name);
683c3ef1500STetsuo Handa ptr->is_dir = len && (name[len - 1] == '/');
684c3ef1500STetsuo Handa ptr->is_patterned = (ptr->const_len < len);
6858387ff25SLinus Torvalds ptr->hash = full_name_hash(NULL, name, len);
686c3ef1500STetsuo Handa }
687c3ef1500STetsuo Handa
688c3ef1500STetsuo Handa /**
689c3ef1500STetsuo Handa * tomoyo_file_matches_pattern2 - Pattern matching without '/' character and "\-" pattern.
690c3ef1500STetsuo Handa *
691c3ef1500STetsuo Handa * @filename: The start of string to check.
692c3ef1500STetsuo Handa * @filename_end: The end of string to check.
693c3ef1500STetsuo Handa * @pattern: The start of pattern to compare.
694c3ef1500STetsuo Handa * @pattern_end: The end of pattern to compare.
695c3ef1500STetsuo Handa *
696c3ef1500STetsuo Handa * Returns true if @filename matches @pattern, false otherwise.
697c3ef1500STetsuo Handa */
tomoyo_file_matches_pattern2(const char * filename,const char * filename_end,const char * pattern,const char * pattern_end)698c3ef1500STetsuo Handa static bool tomoyo_file_matches_pattern2(const char *filename,
699c3ef1500STetsuo Handa const char *filename_end,
700c3ef1500STetsuo Handa const char *pattern,
701c3ef1500STetsuo Handa const char *pattern_end)
702c3ef1500STetsuo Handa {
703c3ef1500STetsuo Handa while (filename < filename_end && pattern < pattern_end) {
704c3ef1500STetsuo Handa char c;
705cdcf6723STetsuo Handa int i;
706cdcf6723STetsuo Handa int j;
707cdcf6723STetsuo Handa
708c3ef1500STetsuo Handa if (*pattern != '\\') {
709c3ef1500STetsuo Handa if (*filename++ != *pattern++)
710c3ef1500STetsuo Handa return false;
711c3ef1500STetsuo Handa continue;
712c3ef1500STetsuo Handa }
713c3ef1500STetsuo Handa c = *filename;
714c3ef1500STetsuo Handa pattern++;
715c3ef1500STetsuo Handa switch (*pattern) {
716c3ef1500STetsuo Handa case '?':
717c3ef1500STetsuo Handa if (c == '/') {
718c3ef1500STetsuo Handa return false;
719c3ef1500STetsuo Handa } else if (c == '\\') {
720c3ef1500STetsuo Handa if (filename[1] == '\\')
721c3ef1500STetsuo Handa filename++;
72275093152STetsuo Handa else if (tomoyo_byte_range(filename + 1))
723c3ef1500STetsuo Handa filename += 3;
724c3ef1500STetsuo Handa else
725c3ef1500STetsuo Handa return false;
726c3ef1500STetsuo Handa }
727c3ef1500STetsuo Handa break;
728c3ef1500STetsuo Handa case '\\':
729c3ef1500STetsuo Handa if (c != '\\')
730c3ef1500STetsuo Handa return false;
731c3ef1500STetsuo Handa if (*++filename != '\\')
732c3ef1500STetsuo Handa return false;
733c3ef1500STetsuo Handa break;
734c3ef1500STetsuo Handa case '+':
735c3ef1500STetsuo Handa if (!isdigit(c))
736c3ef1500STetsuo Handa return false;
737c3ef1500STetsuo Handa break;
738c3ef1500STetsuo Handa case 'x':
739c3ef1500STetsuo Handa if (!isxdigit(c))
740c3ef1500STetsuo Handa return false;
741c3ef1500STetsuo Handa break;
742c3ef1500STetsuo Handa case 'a':
74375093152STetsuo Handa if (!tomoyo_alphabet_char(c))
744c3ef1500STetsuo Handa return false;
745c3ef1500STetsuo Handa break;
746c3ef1500STetsuo Handa case '0':
747c3ef1500STetsuo Handa case '1':
748c3ef1500STetsuo Handa case '2':
749c3ef1500STetsuo Handa case '3':
75075093152STetsuo Handa if (c == '\\' && tomoyo_byte_range(filename + 1)
751c3ef1500STetsuo Handa && strncmp(filename + 1, pattern, 3) == 0) {
752c3ef1500STetsuo Handa filename += 3;
753c3ef1500STetsuo Handa pattern += 2;
754c3ef1500STetsuo Handa break;
755c3ef1500STetsuo Handa }
756c3ef1500STetsuo Handa return false; /* Not matched. */
757c3ef1500STetsuo Handa case '*':
758c3ef1500STetsuo Handa case '@':
759c3ef1500STetsuo Handa for (i = 0; i <= filename_end - filename; i++) {
760c3ef1500STetsuo Handa if (tomoyo_file_matches_pattern2(
761c3ef1500STetsuo Handa filename + i, filename_end,
762c3ef1500STetsuo Handa pattern + 1, pattern_end))
763c3ef1500STetsuo Handa return true;
764c3ef1500STetsuo Handa c = filename[i];
765c3ef1500STetsuo Handa if (c == '.' && *pattern == '@')
766c3ef1500STetsuo Handa break;
767c3ef1500STetsuo Handa if (c != '\\')
768c3ef1500STetsuo Handa continue;
769c3ef1500STetsuo Handa if (filename[i + 1] == '\\')
770c3ef1500STetsuo Handa i++;
77175093152STetsuo Handa else if (tomoyo_byte_range(filename + i + 1))
772c3ef1500STetsuo Handa i += 3;
773c3ef1500STetsuo Handa else
774c3ef1500STetsuo Handa break; /* Bad pattern. */
775c3ef1500STetsuo Handa }
776c3ef1500STetsuo Handa return false; /* Not matched. */
777c3ef1500STetsuo Handa default:
778c3ef1500STetsuo Handa j = 0;
779c3ef1500STetsuo Handa c = *pattern;
780c3ef1500STetsuo Handa if (c == '$') {
781c3ef1500STetsuo Handa while (isdigit(filename[j]))
782c3ef1500STetsuo Handa j++;
783c3ef1500STetsuo Handa } else if (c == 'X') {
784c3ef1500STetsuo Handa while (isxdigit(filename[j]))
785c3ef1500STetsuo Handa j++;
786c3ef1500STetsuo Handa } else if (c == 'A') {
78775093152STetsuo Handa while (tomoyo_alphabet_char(filename[j]))
788c3ef1500STetsuo Handa j++;
789c3ef1500STetsuo Handa }
790c3ef1500STetsuo Handa for (i = 1; i <= j; i++) {
791c3ef1500STetsuo Handa if (tomoyo_file_matches_pattern2(
792c3ef1500STetsuo Handa filename + i, filename_end,
793c3ef1500STetsuo Handa pattern + 1, pattern_end))
794c3ef1500STetsuo Handa return true;
795c3ef1500STetsuo Handa }
796c3ef1500STetsuo Handa return false; /* Not matched or bad pattern. */
797c3ef1500STetsuo Handa }
798c3ef1500STetsuo Handa filename++;
799c3ef1500STetsuo Handa pattern++;
800c3ef1500STetsuo Handa }
801c3ef1500STetsuo Handa while (*pattern == '\\' &&
802c3ef1500STetsuo Handa (*(pattern + 1) == '*' || *(pattern + 1) == '@'))
803c3ef1500STetsuo Handa pattern += 2;
804c3ef1500STetsuo Handa return filename == filename_end && pattern == pattern_end;
805c3ef1500STetsuo Handa }
806c3ef1500STetsuo Handa
807c3ef1500STetsuo Handa /**
808c3ef1500STetsuo Handa * tomoyo_file_matches_pattern - Pattern matching without '/' character.
809c3ef1500STetsuo Handa *
810c3ef1500STetsuo Handa * @filename: The start of string to check.
811c3ef1500STetsuo Handa * @filename_end: The end of string to check.
812c3ef1500STetsuo Handa * @pattern: The start of pattern to compare.
813c3ef1500STetsuo Handa * @pattern_end: The end of pattern to compare.
814c3ef1500STetsuo Handa *
815c3ef1500STetsuo Handa * Returns true if @filename matches @pattern, false otherwise.
816c3ef1500STetsuo Handa */
tomoyo_file_matches_pattern(const char * filename,const char * filename_end,const char * pattern,const char * pattern_end)817c3ef1500STetsuo Handa static bool tomoyo_file_matches_pattern(const char *filename,
818c3ef1500STetsuo Handa const char *filename_end,
819c3ef1500STetsuo Handa const char *pattern,
820c3ef1500STetsuo Handa const char *pattern_end)
821c3ef1500STetsuo Handa {
822c3ef1500STetsuo Handa const char *pattern_start = pattern;
823c3ef1500STetsuo Handa bool first = true;
824c3ef1500STetsuo Handa bool result;
825c3ef1500STetsuo Handa
826c3ef1500STetsuo Handa while (pattern < pattern_end - 1) {
827c3ef1500STetsuo Handa /* Split at "\-" pattern. */
828c3ef1500STetsuo Handa if (*pattern++ != '\\' || *pattern++ != '-')
829c3ef1500STetsuo Handa continue;
830c3ef1500STetsuo Handa result = tomoyo_file_matches_pattern2(filename,
831c3ef1500STetsuo Handa filename_end,
832c3ef1500STetsuo Handa pattern_start,
833c3ef1500STetsuo Handa pattern - 2);
834c3ef1500STetsuo Handa if (first)
835c3ef1500STetsuo Handa result = !result;
836c3ef1500STetsuo Handa if (result)
837c3ef1500STetsuo Handa return false;
838c3ef1500STetsuo Handa first = false;
839c3ef1500STetsuo Handa pattern_start = pattern;
840c3ef1500STetsuo Handa }
841c3ef1500STetsuo Handa result = tomoyo_file_matches_pattern2(filename, filename_end,
842c3ef1500STetsuo Handa pattern_start, pattern_end);
843c3ef1500STetsuo Handa return first ? result : !result;
844c3ef1500STetsuo Handa }
845c3ef1500STetsuo Handa
846c3ef1500STetsuo Handa /**
847c3ef1500STetsuo Handa * tomoyo_path_matches_pattern2 - Do pathname pattern matching.
848c3ef1500STetsuo Handa *
849c3ef1500STetsuo Handa * @f: The start of string to check.
850c3ef1500STetsuo Handa * @p: The start of pattern to compare.
851c3ef1500STetsuo Handa *
852c3ef1500STetsuo Handa * Returns true if @f matches @p, false otherwise.
853c3ef1500STetsuo Handa */
tomoyo_path_matches_pattern2(const char * f,const char * p)854c3ef1500STetsuo Handa static bool tomoyo_path_matches_pattern2(const char *f, const char *p)
855c3ef1500STetsuo Handa {
856c3ef1500STetsuo Handa const char *f_delimiter;
857c3ef1500STetsuo Handa const char *p_delimiter;
858c3ef1500STetsuo Handa
859c3ef1500STetsuo Handa while (*f && *p) {
860c3ef1500STetsuo Handa f_delimiter = strchr(f, '/');
861c3ef1500STetsuo Handa if (!f_delimiter)
862c3ef1500STetsuo Handa f_delimiter = f + strlen(f);
863c3ef1500STetsuo Handa p_delimiter = strchr(p, '/');
864c3ef1500STetsuo Handa if (!p_delimiter)
865c3ef1500STetsuo Handa p_delimiter = p + strlen(p);
866c3ef1500STetsuo Handa if (*p == '\\' && *(p + 1) == '{')
867c3ef1500STetsuo Handa goto recursive;
868c3ef1500STetsuo Handa if (!tomoyo_file_matches_pattern(f, f_delimiter, p,
869c3ef1500STetsuo Handa p_delimiter))
870c3ef1500STetsuo Handa return false;
871c3ef1500STetsuo Handa f = f_delimiter;
872c3ef1500STetsuo Handa if (*f)
873c3ef1500STetsuo Handa f++;
874c3ef1500STetsuo Handa p = p_delimiter;
875c3ef1500STetsuo Handa if (*p)
876c3ef1500STetsuo Handa p++;
877c3ef1500STetsuo Handa }
878c3ef1500STetsuo Handa /* Ignore trailing "\*" and "\@" in @pattern. */
879c3ef1500STetsuo Handa while (*p == '\\' &&
880c3ef1500STetsuo Handa (*(p + 1) == '*' || *(p + 1) == '@'))
881c3ef1500STetsuo Handa p += 2;
882c3ef1500STetsuo Handa return !*f && !*p;
883c3ef1500STetsuo Handa recursive:
884c3ef1500STetsuo Handa /*
885c3ef1500STetsuo Handa * The "\{" pattern is permitted only after '/' character.
886c3ef1500STetsuo Handa * This guarantees that below "*(p - 1)" is safe.
887c3ef1500STetsuo Handa * Also, the "\}" pattern is permitted only before '/' character
888c3ef1500STetsuo Handa * so that "\{" + "\}" pair will not break the "\-" operator.
889c3ef1500STetsuo Handa */
890c3ef1500STetsuo Handa if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' ||
891c3ef1500STetsuo Handa *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\')
892c3ef1500STetsuo Handa return false; /* Bad pattern. */
893c3ef1500STetsuo Handa do {
894c3ef1500STetsuo Handa /* Compare current component with pattern. */
895c3ef1500STetsuo Handa if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2,
896c3ef1500STetsuo Handa p_delimiter - 2))
897c3ef1500STetsuo Handa break;
898c3ef1500STetsuo Handa /* Proceed to next component. */
899c3ef1500STetsuo Handa f = f_delimiter;
900c3ef1500STetsuo Handa if (!*f)
901c3ef1500STetsuo Handa break;
902c3ef1500STetsuo Handa f++;
903c3ef1500STetsuo Handa /* Continue comparison. */
904c3ef1500STetsuo Handa if (tomoyo_path_matches_pattern2(f, p_delimiter + 1))
905c3ef1500STetsuo Handa return true;
906c3ef1500STetsuo Handa f_delimiter = strchr(f, '/');
907c3ef1500STetsuo Handa } while (f_delimiter);
908c3ef1500STetsuo Handa return false; /* Not matched. */
909c3ef1500STetsuo Handa }
910c3ef1500STetsuo Handa
911c3ef1500STetsuo Handa /**
912c3ef1500STetsuo Handa * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern.
913c3ef1500STetsuo Handa *
914c3ef1500STetsuo Handa * @filename: The filename to check.
915c3ef1500STetsuo Handa * @pattern: The pattern to compare.
916c3ef1500STetsuo Handa *
917c3ef1500STetsuo Handa * Returns true if matches, false otherwise.
918c3ef1500STetsuo Handa *
919c3ef1500STetsuo Handa * The following patterns are available.
920c3ef1500STetsuo Handa * \\ \ itself.
921c3ef1500STetsuo Handa * \ooo Octal representation of a byte.
922c3ef1500STetsuo Handa * \* Zero or more repetitions of characters other than '/'.
923c3ef1500STetsuo Handa * \@ Zero or more repetitions of characters other than '/' or '.'.
924c3ef1500STetsuo Handa * \? 1 byte character other than '/'.
925c3ef1500STetsuo Handa * \$ One or more repetitions of decimal digits.
926c3ef1500STetsuo Handa * \+ 1 decimal digit.
927c3ef1500STetsuo Handa * \X One or more repetitions of hexadecimal digits.
928c3ef1500STetsuo Handa * \x 1 hexadecimal digit.
929c3ef1500STetsuo Handa * \A One or more repetitions of alphabet characters.
930c3ef1500STetsuo Handa * \a 1 alphabet character.
931c3ef1500STetsuo Handa *
932c3ef1500STetsuo Handa * \- Subtraction operator.
933c3ef1500STetsuo Handa *
934c3ef1500STetsuo Handa * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/
935c3ef1500STetsuo Handa * /dir/dir/dir/ ).
936c3ef1500STetsuo Handa */
tomoyo_path_matches_pattern(const struct tomoyo_path_info * filename,const struct tomoyo_path_info * pattern)937c3ef1500STetsuo Handa bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
938c3ef1500STetsuo Handa const struct tomoyo_path_info *pattern)
939c3ef1500STetsuo Handa {
940c3ef1500STetsuo Handa const char *f = filename->name;
941c3ef1500STetsuo Handa const char *p = pattern->name;
942c3ef1500STetsuo Handa const int len = pattern->const_len;
943c3ef1500STetsuo Handa
944c3ef1500STetsuo Handa /* If @pattern doesn't contain pattern, I can use strcmp(). */
945c3ef1500STetsuo Handa if (!pattern->is_patterned)
946c3ef1500STetsuo Handa return !tomoyo_pathcmp(filename, pattern);
947c3ef1500STetsuo Handa /* Don't compare directory and non-directory. */
948c3ef1500STetsuo Handa if (filename->is_dir != pattern->is_dir)
949c3ef1500STetsuo Handa return false;
950c3ef1500STetsuo Handa /* Compare the initial length without patterns. */
951c3ef1500STetsuo Handa if (strncmp(f, p, len))
952c3ef1500STetsuo Handa return false;
953c3ef1500STetsuo Handa f += len;
954c3ef1500STetsuo Handa p += len;
955c3ef1500STetsuo Handa return tomoyo_path_matches_pattern2(f, p);
956c3ef1500STetsuo Handa }
957c3ef1500STetsuo Handa
958c3ef1500STetsuo Handa /**
959c3ef1500STetsuo Handa * tomoyo_get_exe - Get tomoyo_realpath() of current process.
960c3ef1500STetsuo Handa *
961c3ef1500STetsuo Handa * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
962c3ef1500STetsuo Handa *
963c3ef1500STetsuo Handa * This function uses kzalloc(), so the caller must call kfree()
964c3ef1500STetsuo Handa * if this function didn't return NULL.
965c3ef1500STetsuo Handa */
tomoyo_get_exe(void)966c3ef1500STetsuo Handa const char *tomoyo_get_exe(void)
967c3ef1500STetsuo Handa {
968d4144ea6SDavidlohr Bueso struct file *exe_file;
969d4144ea6SDavidlohr Bueso const char *cp;
970c3ef1500STetsuo Handa struct mm_struct *mm = current->mm;
971c3ef1500STetsuo Handa
972c3ef1500STetsuo Handa if (!mm)
973c3ef1500STetsuo Handa return NULL;
974d4144ea6SDavidlohr Bueso exe_file = get_mm_exe_file(mm);
975d4144ea6SDavidlohr Bueso if (!exe_file)
976d4144ea6SDavidlohr Bueso return NULL;
977d4144ea6SDavidlohr Bueso
978d4144ea6SDavidlohr Bueso cp = tomoyo_realpath_from_path(&exe_file->f_path);
979d4144ea6SDavidlohr Bueso fput(exe_file);
980c3ef1500STetsuo Handa return cp;
981c3ef1500STetsuo Handa }
982c3ef1500STetsuo Handa
983c3ef1500STetsuo Handa /**
98457c2590fSTetsuo Handa * tomoyo_get_mode - Get MAC mode.
98557c2590fSTetsuo Handa *
986bd03a3e4STetsuo Handa * @ns: Pointer to "struct tomoyo_policy_namespace".
98757c2590fSTetsuo Handa * @profile: Profile number.
98857c2590fSTetsuo Handa * @index: Index number of functionality.
98957c2590fSTetsuo Handa *
99057c2590fSTetsuo Handa * Returns mode.
99157c2590fSTetsuo Handa */
tomoyo_get_mode(const struct tomoyo_policy_namespace * ns,const u8 profile,const u8 index)992bd03a3e4STetsuo Handa int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile,
993bd03a3e4STetsuo Handa const u8 index)
99457c2590fSTetsuo Handa {
99557c2590fSTetsuo Handa u8 mode;
996d58e0da8STetsuo Handa struct tomoyo_profile *p;
997d58e0da8STetsuo Handa
99857c2590fSTetsuo Handa if (!tomoyo_policy_loaded)
99957c2590fSTetsuo Handa return TOMOYO_CONFIG_DISABLED;
1000d58e0da8STetsuo Handa p = tomoyo_profile(ns, profile);
1001d58e0da8STetsuo Handa mode = p->config[index];
100257c2590fSTetsuo Handa if (mode == TOMOYO_CONFIG_USE_DEFAULT)
1003d58e0da8STetsuo Handa mode = p->config[tomoyo_index2category[index]
1004d58e0da8STetsuo Handa + TOMOYO_MAX_MAC_INDEX];
100557c2590fSTetsuo Handa if (mode == TOMOYO_CONFIG_USE_DEFAULT)
1006d58e0da8STetsuo Handa mode = p->default_config;
100757c2590fSTetsuo Handa return mode & 3;
100857c2590fSTetsuo Handa }
100957c2590fSTetsuo Handa
101057c2590fSTetsuo Handa /**
1011c3ef1500STetsuo Handa * tomoyo_init_request_info - Initialize "struct tomoyo_request_info" members.
1012c3ef1500STetsuo Handa *
1013c3ef1500STetsuo Handa * @r: Pointer to "struct tomoyo_request_info" to initialize.
1014c3ef1500STetsuo Handa * @domain: Pointer to "struct tomoyo_domain_info". NULL for tomoyo_domain().
101557c2590fSTetsuo Handa * @index: Index number of functionality.
1016c3ef1500STetsuo Handa *
1017c3ef1500STetsuo Handa * Returns mode.
1018c3ef1500STetsuo Handa */
tomoyo_init_request_info(struct tomoyo_request_info * r,struct tomoyo_domain_info * domain,const u8 index)1019c3ef1500STetsuo Handa int tomoyo_init_request_info(struct tomoyo_request_info *r,
102057c2590fSTetsuo Handa struct tomoyo_domain_info *domain, const u8 index)
1021c3ef1500STetsuo Handa {
102257c2590fSTetsuo Handa u8 profile;
1023cdcf6723STetsuo Handa
1024c3ef1500STetsuo Handa memset(r, 0, sizeof(*r));
1025c3ef1500STetsuo Handa if (!domain)
1026c3ef1500STetsuo Handa domain = tomoyo_domain();
1027c3ef1500STetsuo Handa r->domain = domain;
102857c2590fSTetsuo Handa profile = domain->profile;
102957c2590fSTetsuo Handa r->profile = profile;
103057c2590fSTetsuo Handa r->type = index;
1031bd03a3e4STetsuo Handa r->mode = tomoyo_get_mode(domain->ns, profile, index);
1032c3ef1500STetsuo Handa return r->mode;
1033c3ef1500STetsuo Handa }
1034c3ef1500STetsuo Handa
1035c3ef1500STetsuo Handa /**
1036c3ef1500STetsuo Handa * tomoyo_domain_quota_is_ok - Check for domain's quota.
1037c3ef1500STetsuo Handa *
1038c3ef1500STetsuo Handa * @r: Pointer to "struct tomoyo_request_info".
1039c3ef1500STetsuo Handa *
1040c3ef1500STetsuo Handa * Returns true if the domain is not exceeded quota, false otherwise.
1041c3ef1500STetsuo Handa *
1042c3ef1500STetsuo Handa * Caller holds tomoyo_read_lock().
1043c3ef1500STetsuo Handa */
tomoyo_domain_quota_is_ok(struct tomoyo_request_info * r)1044c3ef1500STetsuo Handa bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
1045c3ef1500STetsuo Handa {
1046c3ef1500STetsuo Handa unsigned int count = 0;
1047c3ef1500STetsuo Handa struct tomoyo_domain_info *domain = r->domain;
1048c3ef1500STetsuo Handa struct tomoyo_acl_info *ptr;
1049c3ef1500STetsuo Handa
1050c3ef1500STetsuo Handa if (r->mode != TOMOYO_CONFIG_LEARNING)
1051c3ef1500STetsuo Handa return false;
1052c3ef1500STetsuo Handa if (!domain)
1053c3ef1500STetsuo Handa return true;
10543fe6a63bSDmitry Vyukov if (READ_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED]))
10553fe6a63bSDmitry Vyukov return false;
10566bd5ce60STetsuo Handa list_for_each_entry_rcu(ptr, &domain->acl_info_list, list,
10576bd5ce60STetsuo Handa srcu_read_lock_held(&tomoyo_ss)) {
10587c75964fSTetsuo Handa u16 perm;
1059cdcf6723STetsuo Handa
10607e3d199aSTetsuo Handa if (ptr->is_deleted)
1061237ab459STetsuo Handa continue;
10625797e861STetsuo Handa /*
10635797e861STetsuo Handa * Reading perm bitmap might race with tomoyo_merge_*() because
10645797e861STetsuo Handa * caller does not hold tomoyo_policy_lock mutex. But exceeding
10655797e861STetsuo Handa * max_learning_entry parameter by a few entries does not harm.
10665797e861STetsuo Handa */
1067c3ef1500STetsuo Handa switch (ptr->type) {
1068c3ef1500STetsuo Handa case TOMOYO_TYPE_PATH_ACL:
1069*80176f65STetsuo Handa perm = data_race(container_of(ptr, struct tomoyo_path_acl, head)->perm);
1070c3ef1500STetsuo Handa break;
1071c3ef1500STetsuo Handa case TOMOYO_TYPE_PATH2_ACL:
1072*80176f65STetsuo Handa perm = data_race(container_of(ptr, struct tomoyo_path2_acl, head)->perm);
1073c3ef1500STetsuo Handa break;
1074c3ef1500STetsuo Handa case TOMOYO_TYPE_PATH_NUMBER_ACL:
1075*80176f65STetsuo Handa perm = data_race(container_of(ptr, struct tomoyo_path_number_acl, head)
10765797e861STetsuo Handa ->perm);
1077c3ef1500STetsuo Handa break;
107875093152STetsuo Handa case TOMOYO_TYPE_MKDEV_ACL:
1079*80176f65STetsuo Handa perm = data_race(container_of(ptr, struct tomoyo_mkdev_acl, head)->perm);
1080c3ef1500STetsuo Handa break;
1081545a7260STetsuo Handa case TOMOYO_TYPE_INET_ACL:
1082*80176f65STetsuo Handa perm = data_race(container_of(ptr, struct tomoyo_inet_acl, head)->perm);
1083545a7260STetsuo Handa break;
1084545a7260STetsuo Handa case TOMOYO_TYPE_UNIX_ACL:
1085*80176f65STetsuo Handa perm = data_race(container_of(ptr, struct tomoyo_unix_acl, head)->perm);
1086545a7260STetsuo Handa break;
1087545a7260STetsuo Handa case TOMOYO_TYPE_MANUAL_TASK_ACL:
1088545a7260STetsuo Handa perm = 0;
1089545a7260STetsuo Handa break;
1090237ab459STetsuo Handa default:
10917c75964fSTetsuo Handa perm = 1;
1092c3ef1500STetsuo Handa }
1093*80176f65STetsuo Handa count += hweight16(perm);
1094c3ef1500STetsuo Handa }
1095bd03a3e4STetsuo Handa if (count < tomoyo_profile(domain->ns, domain->profile)->
1096d5ca1725STetsuo Handa pref[TOMOYO_PREF_MAX_LEARNING_ENTRY])
1097c3ef1500STetsuo Handa return true;
10983fe6a63bSDmitry Vyukov WRITE_ONCE(domain->flags[TOMOYO_DIF_QUOTA_WARNED], true);
10992c47ab93STetsuo Handa /* r->granted = false; */
11002c47ab93STetsuo Handa tomoyo_write_log(r, "%s", tomoyo_dif[TOMOYO_DIF_QUOTA_WARNED]);
11014ad98ac4STetsuo Handa #ifndef CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING
1102cdcf6723STetsuo Handa pr_warn("WARNING: Domain '%s' has too many ACLs to hold. Stopped learning mode.\n",
1103cdcf6723STetsuo Handa domain->domainname->name);
11044ad98ac4STetsuo Handa #endif
1105c3ef1500STetsuo Handa return false;
1106c3ef1500STetsuo Handa }
1107