file.c revision 5300990c0370e804e49d9a59d928c5d53fb73487
1/*
2 * security/tomoyo/file.c
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2009  NTT DATA CORPORATION
7 *
8 * Version: 2.2.0   2009/04/01
9 *
10 */
11
12#include "common.h"
13#include "tomoyo.h"
14#include "realpath.h"
15
16/*
17 * tomoyo_globally_readable_file_entry is a structure which is used for holding
18 * "allow_read" entries.
19 * It has following fields.
20 *
21 *  (1) "list" which is linked to tomoyo_globally_readable_list .
22 *  (2) "filename" is a pathname which is allowed to open(O_RDONLY).
23 *  (3) "is_deleted" is a bool which is true if marked as deleted, false
24 *      otherwise.
25 */
26struct tomoyo_globally_readable_file_entry {
27	struct list_head list;
28	const struct tomoyo_path_info *filename;
29	bool is_deleted;
30};
31
32/*
33 * tomoyo_pattern_entry is a structure which is used for holding
34 * "tomoyo_pattern_list" entries.
35 * It has following fields.
36 *
37 *  (1) "list" which is linked to tomoyo_pattern_list .
38 *  (2) "pattern" is a pathname pattern which is used for converting pathnames
39 *      to pathname patterns during learning mode.
40 *  (3) "is_deleted" is a bool which is true if marked as deleted, false
41 *      otherwise.
42 */
43struct tomoyo_pattern_entry {
44	struct list_head list;
45	const struct tomoyo_path_info *pattern;
46	bool is_deleted;
47};
48
49/*
50 * tomoyo_no_rewrite_entry is a structure which is used for holding
51 * "deny_rewrite" entries.
52 * It has following fields.
53 *
54 *  (1) "list" which is linked to tomoyo_no_rewrite_list .
55 *  (2) "pattern" is a pathname which is by default not permitted to modify
56 *      already existing content.
57 *  (3) "is_deleted" is a bool which is true if marked as deleted, false
58 *      otherwise.
59 */
60struct tomoyo_no_rewrite_entry {
61	struct list_head list;
62	const struct tomoyo_path_info *pattern;
63	bool is_deleted;
64};
65
66/* Keyword array for single path operations. */
67static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = {
68	[TOMOYO_TYPE_READ_WRITE_ACL] = "read/write",
69	[TOMOYO_TYPE_EXECUTE_ACL]    = "execute",
70	[TOMOYO_TYPE_READ_ACL]       = "read",
71	[TOMOYO_TYPE_WRITE_ACL]      = "write",
72	[TOMOYO_TYPE_CREATE_ACL]     = "create",
73	[TOMOYO_TYPE_UNLINK_ACL]     = "unlink",
74	[TOMOYO_TYPE_MKDIR_ACL]      = "mkdir",
75	[TOMOYO_TYPE_RMDIR_ACL]      = "rmdir",
76	[TOMOYO_TYPE_MKFIFO_ACL]     = "mkfifo",
77	[TOMOYO_TYPE_MKSOCK_ACL]     = "mksock",
78	[TOMOYO_TYPE_MKBLOCK_ACL]    = "mkblock",
79	[TOMOYO_TYPE_MKCHAR_ACL]     = "mkchar",
80	[TOMOYO_TYPE_TRUNCATE_ACL]   = "truncate",
81	[TOMOYO_TYPE_SYMLINK_ACL]    = "symlink",
82	[TOMOYO_TYPE_REWRITE_ACL]    = "rewrite",
83};
84
85/* Keyword array for double path operations. */
86static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = {
87	[TOMOYO_TYPE_LINK_ACL]    = "link",
88	[TOMOYO_TYPE_RENAME_ACL]  = "rename",
89};
90
91/**
92 * tomoyo_sp2keyword - Get the name of single path operation.
93 *
94 * @operation: Type of operation.
95 *
96 * Returns the name of single path operation.
97 */
98const char *tomoyo_sp2keyword(const u8 operation)
99{
100	return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION)
101		? tomoyo_sp_keyword[operation] : NULL;
102}
103
104/**
105 * tomoyo_dp2keyword - Get the name of double path operation.
106 *
107 * @operation: Type of operation.
108 *
109 * Returns the name of double path operation.
110 */
111const char *tomoyo_dp2keyword(const u8 operation)
112{
113	return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION)
114		? tomoyo_dp_keyword[operation] : NULL;
115}
116
117/**
118 * tomoyo_strendswith - Check whether the token ends with the given token.
119 *
120 * @name: The token to check.
121 * @tail: The token to find.
122 *
123 * Returns true if @name ends with @tail, false otherwise.
124 */
125static bool tomoyo_strendswith(const char *name, const char *tail)
126{
127	int len;
128
129	if (!name || !tail)
130		return false;
131	len = strlen(name) - strlen(tail);
132	return len >= 0 && !strcmp(name + len, tail);
133}
134
135/**
136 * tomoyo_get_path - Get realpath.
137 *
138 * @path: Pointer to "struct path".
139 *
140 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
141 */
142static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
143{
144	int error;
145	struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf));
146
147	if (!buf)
148		return NULL;
149	/* Reserve one byte for appending "/". */
150	error = tomoyo_realpath_from_path2(path, buf->body,
151					   sizeof(buf->body) - 2);
152	if (!error) {
153		buf->head.name = buf->body;
154		tomoyo_fill_path_info(&buf->head);
155		return &buf->head;
156	}
157	tomoyo_free(buf);
158	return NULL;
159}
160
161/* Lock for domain->acl_info_list. */
162DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock);
163
164static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
165					 const char *filename2,
166					 struct tomoyo_domain_info *
167					 const domain, const bool is_delete);
168static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
169					 struct tomoyo_domain_info *
170					 const domain, const bool is_delete);
171
172/*
173 * tomoyo_globally_readable_list is used for holding list of pathnames which
174 * are by default allowed to be open()ed for reading by any process.
175 *
176 * An entry is added by
177 *
178 * # echo 'allow_read /lib/libc-2.5.so' > \
179 *                               /sys/kernel/security/tomoyo/exception_policy
180 *
181 * and is deleted by
182 *
183 * # echo 'delete allow_read /lib/libc-2.5.so' > \
184 *                               /sys/kernel/security/tomoyo/exception_policy
185 *
186 * and all entries are retrieved by
187 *
188 * # grep ^allow_read /sys/kernel/security/tomoyo/exception_policy
189 *
190 * In the example above, any process is allowed to
191 * open("/lib/libc-2.5.so", O_RDONLY).
192 * One exception is, if the domain which current process belongs to is marked
193 * as "ignore_global_allow_read", current process can't do so unless explicitly
194 * given "allow_read /lib/libc-2.5.so" to the domain which current process
195 * belongs to.
196 */
197static LIST_HEAD(tomoyo_globally_readable_list);
198static DECLARE_RWSEM(tomoyo_globally_readable_list_lock);
199
200/**
201 * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list.
202 *
203 * @filename:  Filename unconditionally permitted to open() for reading.
204 * @is_delete: True if it is a delete request.
205 *
206 * Returns 0 on success, negative value otherwise.
207 */
208static int tomoyo_update_globally_readable_entry(const char *filename,
209						 const bool is_delete)
210{
211	struct tomoyo_globally_readable_file_entry *new_entry;
212	struct tomoyo_globally_readable_file_entry *ptr;
213	const struct tomoyo_path_info *saved_filename;
214	int error = -ENOMEM;
215
216	if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__))
217		return -EINVAL;
218	saved_filename = tomoyo_save_name(filename);
219	if (!saved_filename)
220		return -ENOMEM;
221	down_write(&tomoyo_globally_readable_list_lock);
222	list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
223		if (ptr->filename != saved_filename)
224			continue;
225		ptr->is_deleted = is_delete;
226		error = 0;
227		goto out;
228	}
229	if (is_delete) {
230		error = -ENOENT;
231		goto out;
232	}
233	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
234	if (!new_entry)
235		goto out;
236	new_entry->filename = saved_filename;
237	list_add_tail(&new_entry->list, &tomoyo_globally_readable_list);
238	error = 0;
239 out:
240	up_write(&tomoyo_globally_readable_list_lock);
241	return error;
242}
243
244/**
245 * tomoyo_is_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading.
246 *
247 * @filename: The filename to check.
248 *
249 * Returns true if any domain can open @filename for reading, false otherwise.
250 */
251static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
252					     filename)
253{
254	struct tomoyo_globally_readable_file_entry *ptr;
255	bool found = false;
256	down_read(&tomoyo_globally_readable_list_lock);
257	list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
258		if (!ptr->is_deleted &&
259		    tomoyo_path_matches_pattern(filename, ptr->filename)) {
260			found = true;
261			break;
262		}
263	}
264	up_read(&tomoyo_globally_readable_list_lock);
265	return found;
266}
267
268/**
269 * tomoyo_write_globally_readable_policy - Write "struct tomoyo_globally_readable_file_entry" list.
270 *
271 * @data:      String to parse.
272 * @is_delete: True if it is a delete request.
273 *
274 * Returns 0 on success, negative value otherwise.
275 */
276int tomoyo_write_globally_readable_policy(char *data, const bool is_delete)
277{
278	return tomoyo_update_globally_readable_entry(data, is_delete);
279}
280
281/**
282 * tomoyo_read_globally_readable_policy - Read "struct tomoyo_globally_readable_file_entry" list.
283 *
284 * @head: Pointer to "struct tomoyo_io_buffer".
285 *
286 * Returns true on success, false otherwise.
287 */
288bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
289{
290	struct list_head *pos;
291	bool done = true;
292
293	down_read(&tomoyo_globally_readable_list_lock);
294	list_for_each_cookie(pos, head->read_var2,
295			     &tomoyo_globally_readable_list) {
296		struct tomoyo_globally_readable_file_entry *ptr;
297		ptr = list_entry(pos,
298				 struct tomoyo_globally_readable_file_entry,
299				 list);
300		if (ptr->is_deleted)
301			continue;
302		done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n",
303					ptr->filename->name);
304		if (!done)
305			break;
306	}
307	up_read(&tomoyo_globally_readable_list_lock);
308	return done;
309}
310
311/* tomoyo_pattern_list is used for holding list of pathnames which are used for
312 * converting pathnames to pathname patterns during learning mode.
313 *
314 * An entry is added by
315 *
316 * # echo 'file_pattern /proc/\$/mounts' > \
317 *                             /sys/kernel/security/tomoyo/exception_policy
318 *
319 * and is deleted by
320 *
321 * # echo 'delete file_pattern /proc/\$/mounts' > \
322 *                             /sys/kernel/security/tomoyo/exception_policy
323 *
324 * and all entries are retrieved by
325 *
326 * # grep ^file_pattern /sys/kernel/security/tomoyo/exception_policy
327 *
328 * In the example above, if a process which belongs to a domain which is in
329 * learning mode requested open("/proc/1/mounts", O_RDONLY),
330 * "allow_read /proc/\$/mounts" is automatically added to the domain which that
331 * process belongs to.
332 *
333 * It is not a desirable behavior that we have to use /proc/\$/ instead of
334 * /proc/self/ when current process needs to access only current process's
335 * information. As of now, LSM version of TOMOYO is using __d_path() for
336 * calculating pathname. Non LSM version of TOMOYO is using its own function
337 * which pretends as if /proc/self/ is not a symlink; so that we can forbid
338 * current process from accessing other process's information.
339 */
340static LIST_HEAD(tomoyo_pattern_list);
341static DECLARE_RWSEM(tomoyo_pattern_list_lock);
342
343/**
344 * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list.
345 *
346 * @pattern:   Pathname pattern.
347 * @is_delete: True if it is a delete request.
348 *
349 * Returns 0 on success, negative value otherwise.
350 */
351static int tomoyo_update_file_pattern_entry(const char *pattern,
352					    const bool is_delete)
353{
354	struct tomoyo_pattern_entry *new_entry;
355	struct tomoyo_pattern_entry *ptr;
356	const struct tomoyo_path_info *saved_pattern;
357	int error = -ENOMEM;
358
359	if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__))
360		return -EINVAL;
361	saved_pattern = tomoyo_save_name(pattern);
362	if (!saved_pattern)
363		return -ENOMEM;
364	down_write(&tomoyo_pattern_list_lock);
365	list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
366		if (saved_pattern != ptr->pattern)
367			continue;
368		ptr->is_deleted = is_delete;
369		error = 0;
370		goto out;
371	}
372	if (is_delete) {
373		error = -ENOENT;
374		goto out;
375	}
376	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
377	if (!new_entry)
378		goto out;
379	new_entry->pattern = saved_pattern;
380	list_add_tail(&new_entry->list, &tomoyo_pattern_list);
381	error = 0;
382 out:
383	up_write(&tomoyo_pattern_list_lock);
384	return error;
385}
386
387/**
388 * tomoyo_get_file_pattern - Get patterned pathname.
389 *
390 * @filename: The filename to find patterned pathname.
391 *
392 * Returns pointer to pathname pattern if matched, @filename otherwise.
393 */
394static const struct tomoyo_path_info *
395tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
396{
397	struct tomoyo_pattern_entry *ptr;
398	const struct tomoyo_path_info *pattern = NULL;
399
400	down_read(&tomoyo_pattern_list_lock);
401	list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
402		if (ptr->is_deleted)
403			continue;
404		if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
405			continue;
406		pattern = ptr->pattern;
407		if (tomoyo_strendswith(pattern->name, "/\\*")) {
408			/* Do nothing. Try to find the better match. */
409		} else {
410			/* This would be the better match. Use this. */
411			break;
412		}
413	}
414	up_read(&tomoyo_pattern_list_lock);
415	if (pattern)
416		filename = pattern;
417	return filename;
418}
419
420/**
421 * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list.
422 *
423 * @data:      String to parse.
424 * @is_delete: True if it is a delete request.
425 *
426 * Returns 0 on success, negative value otherwise.
427 */
428int tomoyo_write_pattern_policy(char *data, const bool is_delete)
429{
430	return tomoyo_update_file_pattern_entry(data, is_delete);
431}
432
433/**
434 * tomoyo_read_file_pattern - Read "struct tomoyo_pattern_entry" list.
435 *
436 * @head: Pointer to "struct tomoyo_io_buffer".
437 *
438 * Returns true on success, false otherwise.
439 */
440bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
441{
442	struct list_head *pos;
443	bool done = true;
444
445	down_read(&tomoyo_pattern_list_lock);
446	list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) {
447		struct tomoyo_pattern_entry *ptr;
448		ptr = list_entry(pos, struct tomoyo_pattern_entry, list);
449		if (ptr->is_deleted)
450			continue;
451		done = tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN
452					"%s\n", ptr->pattern->name);
453		if (!done)
454			break;
455	}
456	up_read(&tomoyo_pattern_list_lock);
457	return done;
458}
459
460/*
461 * tomoyo_no_rewrite_list is used for holding list of pathnames which are by
462 * default forbidden to modify already written content of a file.
463 *
464 * An entry is added by
465 *
466 * # echo 'deny_rewrite /var/log/messages' > \
467 *                              /sys/kernel/security/tomoyo/exception_policy
468 *
469 * and is deleted by
470 *
471 * # echo 'delete deny_rewrite /var/log/messages' > \
472 *                              /sys/kernel/security/tomoyo/exception_policy
473 *
474 * and all entries are retrieved by
475 *
476 * # grep ^deny_rewrite /sys/kernel/security/tomoyo/exception_policy
477 *
478 * In the example above, if a process requested to rewrite /var/log/messages ,
479 * the process can't rewrite unless the domain which that process belongs to
480 * has "allow_rewrite /var/log/messages" entry.
481 *
482 * It is not a desirable behavior that we have to add "\040(deleted)" suffix
483 * when we want to allow rewriting already unlink()ed file. As of now,
484 * LSM version of TOMOYO is using __d_path() for calculating pathname.
485 * Non LSM version of TOMOYO is using its own function which doesn't append
486 * " (deleted)" suffix if the file is already unlink()ed; so that we don't
487 * need to worry whether the file is already unlink()ed or not.
488 */
489static LIST_HEAD(tomoyo_no_rewrite_list);
490static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock);
491
492/**
493 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
494 *
495 * @pattern:   Pathname pattern that are not rewritable by default.
496 * @is_delete: True if it is a delete request.
497 *
498 * Returns 0 on success, negative value otherwise.
499 */
500static int tomoyo_update_no_rewrite_entry(const char *pattern,
501					  const bool is_delete)
502{
503	struct tomoyo_no_rewrite_entry *new_entry, *ptr;
504	const struct tomoyo_path_info *saved_pattern;
505	int error = -ENOMEM;
506
507	if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__))
508		return -EINVAL;
509	saved_pattern = tomoyo_save_name(pattern);
510	if (!saved_pattern)
511		return -ENOMEM;
512	down_write(&tomoyo_no_rewrite_list_lock);
513	list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
514		if (ptr->pattern != saved_pattern)
515			continue;
516		ptr->is_deleted = is_delete;
517		error = 0;
518		goto out;
519	}
520	if (is_delete) {
521		error = -ENOENT;
522		goto out;
523	}
524	new_entry = tomoyo_alloc_element(sizeof(*new_entry));
525	if (!new_entry)
526		goto out;
527	new_entry->pattern = saved_pattern;
528	list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list);
529	error = 0;
530 out:
531	up_write(&tomoyo_no_rewrite_list_lock);
532	return error;
533}
534
535/**
536 * tomoyo_is_no_rewrite_file - Check if the given pathname is not permitted to be rewrited.
537 *
538 * @filename: Filename to check.
539 *
540 * Returns true if @filename is specified by "deny_rewrite" directive,
541 * false otherwise.
542 */
543static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
544{
545	struct tomoyo_no_rewrite_entry *ptr;
546	bool found = false;
547
548	down_read(&tomoyo_no_rewrite_list_lock);
549	list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
550		if (ptr->is_deleted)
551			continue;
552		if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
553			continue;
554		found = true;
555		break;
556	}
557	up_read(&tomoyo_no_rewrite_list_lock);
558	return found;
559}
560
561/**
562 * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list.
563 *
564 * @data:      String to parse.
565 * @is_delete: True if it is a delete request.
566 *
567 * Returns 0 on success, negative value otherwise.
568 */
569int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
570{
571	return tomoyo_update_no_rewrite_entry(data, is_delete);
572}
573
574/**
575 * tomoyo_read_no_rewrite_policy - Read "struct tomoyo_no_rewrite_entry" list.
576 *
577 * @head: Pointer to "struct tomoyo_io_buffer".
578 *
579 * Returns true on success, false otherwise.
580 */
581bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
582{
583	struct list_head *pos;
584	bool done = true;
585
586	down_read(&tomoyo_no_rewrite_list_lock);
587	list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) {
588		struct tomoyo_no_rewrite_entry *ptr;
589		ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list);
590		if (ptr->is_deleted)
591			continue;
592		done = tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE
593					"%s\n", ptr->pattern->name);
594		if (!done)
595			break;
596	}
597	up_read(&tomoyo_no_rewrite_list_lock);
598	return done;
599}
600
601/**
602 * tomoyo_update_file_acl - Update file's read/write/execute ACL.
603 *
604 * @filename:  Filename.
605 * @perm:      Permission (between 1 to 7).
606 * @domain:    Pointer to "struct tomoyo_domain_info".
607 * @is_delete: True if it is a delete request.
608 *
609 * Returns 0 on success, negative value otherwise.
610 *
611 * This is legacy support interface for older policy syntax.
612 * Current policy syntax uses "allow_read/write" instead of "6",
613 * "allow_read" instead of "4", "allow_write" instead of "2",
614 * "allow_execute" instead of "1".
615 */
616static int tomoyo_update_file_acl(const char *filename, u8 perm,
617				  struct tomoyo_domain_info * const domain,
618				  const bool is_delete)
619{
620	if (perm > 7 || !perm) {
621		printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n",
622		       __func__, perm, filename);
623		return -EINVAL;
624	}
625	if (filename[0] != '@' && tomoyo_strendswith(filename, "/"))
626		/*
627		 * Only 'allow_mkdir' and 'allow_rmdir' are valid for
628		 * directory permissions.
629		 */
630		return 0;
631	if (perm & 4)
632		tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename,
633					      domain, is_delete);
634	if (perm & 2)
635		tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename,
636					      domain, is_delete);
637	if (perm & 1)
638		tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL,
639					      filename, domain, is_delete);
640	return 0;
641}
642
643/**
644 * tomoyo_check_single_path_acl2 - Check permission for single path operation.
645 *
646 * @domain:          Pointer to "struct tomoyo_domain_info".
647 * @filename:        Filename to check.
648 * @perm:            Permission.
649 * @may_use_pattern: True if patterned ACL is permitted.
650 *
651 * Returns 0 on success, -EPERM otherwise.
652 */
653static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
654					 domain,
655					 const struct tomoyo_path_info *
656					 filename,
657					 const u16 perm,
658					 const bool may_use_pattern)
659{
660	struct tomoyo_acl_info *ptr;
661	int error = -EPERM;
662
663	down_read(&tomoyo_domain_acl_info_list_lock);
664	list_for_each_entry(ptr, &domain->acl_info_list, list) {
665		struct tomoyo_single_path_acl_record *acl;
666		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
667			continue;
668		acl = container_of(ptr, struct tomoyo_single_path_acl_record,
669				   head);
670		if (!(acl->perm & perm))
671			continue;
672		if (may_use_pattern || !acl->filename->is_patterned) {
673			if (!tomoyo_path_matches_pattern(filename,
674							 acl->filename))
675				continue;
676		} else {
677			continue;
678		}
679		error = 0;
680		break;
681	}
682	up_read(&tomoyo_domain_acl_info_list_lock);
683	return error;
684}
685
686/**
687 * tomoyo_check_file_acl - Check permission for opening files.
688 *
689 * @domain:    Pointer to "struct tomoyo_domain_info".
690 * @filename:  Filename to check.
691 * @operation: Mode ("read" or "write" or "read/write" or "execute").
692 *
693 * Returns 0 on success, -EPERM otherwise.
694 */
695static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
696				 const struct tomoyo_path_info *filename,
697				 const u8 operation)
698{
699	u16 perm = 0;
700
701	if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
702		return 0;
703	if (operation == 6)
704		perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL;
705	else if (operation == 4)
706		perm = 1 << TOMOYO_TYPE_READ_ACL;
707	else if (operation == 2)
708		perm = 1 << TOMOYO_TYPE_WRITE_ACL;
709	else if (operation == 1)
710		perm = 1 << TOMOYO_TYPE_EXECUTE_ACL;
711	else
712		BUG();
713	return tomoyo_check_single_path_acl2(domain, filename, perm,
714					     operation != 1);
715}
716
717/**
718 * tomoyo_check_file_perm2 - Check permission for opening files.
719 *
720 * @domain:    Pointer to "struct tomoyo_domain_info".
721 * @filename:  Filename to check.
722 * @perm:      Mode ("read" or "write" or "read/write" or "execute").
723 * @operation: Operation name passed used for verbose mode.
724 * @mode:      Access control mode.
725 *
726 * Returns 0 on success, negative value otherwise.
727 */
728static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
729				   const struct tomoyo_path_info *filename,
730				   const u8 perm, const char *operation,
731				   const u8 mode)
732{
733	const bool is_enforce = (mode == 3);
734	const char *msg = "<unknown>";
735	int error = 0;
736
737	if (!filename)
738		return 0;
739	error = tomoyo_check_file_acl(domain, filename, perm);
740	if (error && perm == 4 &&
741	    (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0
742	    && tomoyo_is_globally_readable_file(filename))
743		error = 0;
744	if (perm == 6)
745		msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL);
746	else if (perm == 4)
747		msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL);
748	else if (perm == 2)
749		msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL);
750	else if (perm == 1)
751		msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL);
752	else
753		BUG();
754	if (!error)
755		return 0;
756	if (tomoyo_verbose_mode(domain))
757		printk(KERN_WARNING "TOMOYO-%s: Access '%s(%s) %s' denied "
758		       "for %s\n", tomoyo_get_msg(is_enforce), msg, operation,
759		       filename->name, tomoyo_get_last_name(domain));
760	if (is_enforce)
761		return error;
762	if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
763		/* Don't use patterns for execute permission. */
764		const struct tomoyo_path_info *patterned_file = (perm != 1) ?
765			tomoyo_get_file_pattern(filename) : filename;
766		tomoyo_update_file_acl(patterned_file->name, perm,
767				       domain, false);
768	}
769	return 0;
770}
771
772/**
773 * tomoyo_write_file_policy - Update file related list.
774 *
775 * @data:      String to parse.
776 * @domain:    Pointer to "struct tomoyo_domain_info".
777 * @is_delete: True if it is a delete request.
778 *
779 * Returns 0 on success, negative value otherwise.
780 */
781int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
782			     const bool is_delete)
783{
784	char *filename = strchr(data, ' ');
785	char *filename2;
786	unsigned int perm;
787	u8 type;
788
789	if (!filename)
790		return -EINVAL;
791	*filename++ = '\0';
792	if (sscanf(data, "%u", &perm) == 1)
793		return tomoyo_update_file_acl(filename, (u8) perm, domain,
794					      is_delete);
795	if (strncmp(data, "allow_", 6))
796		goto out;
797	data += 6;
798	for (type = 0; type < TOMOYO_MAX_SINGLE_PATH_OPERATION; type++) {
799		if (strcmp(data, tomoyo_sp_keyword[type]))
800			continue;
801		return tomoyo_update_single_path_acl(type, filename,
802						     domain, is_delete);
803	}
804	filename2 = strchr(filename, ' ');
805	if (!filename2)
806		goto out;
807	*filename2++ = '\0';
808	for (type = 0; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION; type++) {
809		if (strcmp(data, tomoyo_dp_keyword[type]))
810			continue;
811		return tomoyo_update_double_path_acl(type, filename, filename2,
812						     domain, is_delete);
813	}
814 out:
815	return -EINVAL;
816}
817
818/**
819 * tomoyo_update_single_path_acl - Update "struct tomoyo_single_path_acl_record" list.
820 *
821 * @type:      Type of operation.
822 * @filename:  Filename.
823 * @domain:    Pointer to "struct tomoyo_domain_info".
824 * @is_delete: True if it is a delete request.
825 *
826 * Returns 0 on success, negative value otherwise.
827 */
828static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
829					 struct tomoyo_domain_info *
830					 const domain, const bool is_delete)
831{
832	static const u16 rw_mask =
833		(1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL);
834	const struct tomoyo_path_info *saved_filename;
835	struct tomoyo_acl_info *ptr;
836	struct tomoyo_single_path_acl_record *acl;
837	int error = -ENOMEM;
838	const u16 perm = 1 << type;
839
840	if (!domain)
841		return -EINVAL;
842	if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__))
843		return -EINVAL;
844	saved_filename = tomoyo_save_name(filename);
845	if (!saved_filename)
846		return -ENOMEM;
847	down_write(&tomoyo_domain_acl_info_list_lock);
848	if (is_delete)
849		goto delete;
850	list_for_each_entry(ptr, &domain->acl_info_list, list) {
851		if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
852			continue;
853		acl = container_of(ptr, struct tomoyo_single_path_acl_record,
854				   head);
855		if (acl->filename != saved_filename)
856			continue;
857		/* Special case. Clear all bits if marked as deleted. */
858		if (ptr->type & TOMOYO_ACL_DELETED)
859			acl->perm = 0;
860		acl->perm |= perm;
861		if ((acl->perm & rw_mask) == rw_mask)
862			acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL;
863		else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
864			acl->perm |= rw_mask;
865		ptr->type &= ~TOMOYO_ACL_DELETED;
866		error = 0;
867		goto out;
868	}
869	/* Not found. Append it to the tail. */
870	acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL);
871	if (!acl)
872		goto out;
873	acl->perm = perm;
874	if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
875		acl->perm |= rw_mask;
876	acl->filename = saved_filename;
877	list_add_tail(&acl->head.list, &domain->acl_info_list);
878	error = 0;
879	goto out;
880 delete:
881	error = -ENOENT;
882	list_for_each_entry(ptr, &domain->acl_info_list, list) {
883		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
884			continue;
885		acl = container_of(ptr, struct tomoyo_single_path_acl_record,
886				   head);
887		if (acl->filename != saved_filename)
888			continue;
889		acl->perm &= ~perm;
890		if ((acl->perm & rw_mask) != rw_mask)
891			acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
892		else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
893			acl->perm &= ~rw_mask;
894		if (!acl->perm)
895			ptr->type |= TOMOYO_ACL_DELETED;
896		error = 0;
897		break;
898	}
899 out:
900	up_write(&tomoyo_domain_acl_info_list_lock);
901	return error;
902}
903
904/**
905 * tomoyo_update_double_path_acl - Update "struct tomoyo_double_path_acl_record" list.
906 *
907 * @type:      Type of operation.
908 * @filename1: First filename.
909 * @filename2: Second filename.
910 * @domain:    Pointer to "struct tomoyo_domain_info".
911 * @is_delete: True if it is a delete request.
912 *
913 * Returns 0 on success, negative value otherwise.
914 */
915static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
916					 const char *filename2,
917					 struct tomoyo_domain_info *
918					 const domain, const bool is_delete)
919{
920	const struct tomoyo_path_info *saved_filename1;
921	const struct tomoyo_path_info *saved_filename2;
922	struct tomoyo_acl_info *ptr;
923	struct tomoyo_double_path_acl_record *acl;
924	int error = -ENOMEM;
925	const u8 perm = 1 << type;
926
927	if (!domain)
928		return -EINVAL;
929	if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) ||
930	    !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__))
931		return -EINVAL;
932	saved_filename1 = tomoyo_save_name(filename1);
933	saved_filename2 = tomoyo_save_name(filename2);
934	if (!saved_filename1 || !saved_filename2)
935		return -ENOMEM;
936	down_write(&tomoyo_domain_acl_info_list_lock);
937	if (is_delete)
938		goto delete;
939	list_for_each_entry(ptr, &domain->acl_info_list, list) {
940		if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
941			continue;
942		acl = container_of(ptr, struct tomoyo_double_path_acl_record,
943				   head);
944		if (acl->filename1 != saved_filename1 ||
945		    acl->filename2 != saved_filename2)
946			continue;
947		/* Special case. Clear all bits if marked as deleted. */
948		if (ptr->type & TOMOYO_ACL_DELETED)
949			acl->perm = 0;
950		acl->perm |= perm;
951		ptr->type &= ~TOMOYO_ACL_DELETED;
952		error = 0;
953		goto out;
954	}
955	/* Not found. Append it to the tail. */
956	acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL);
957	if (!acl)
958		goto out;
959	acl->perm = perm;
960	acl->filename1 = saved_filename1;
961	acl->filename2 = saved_filename2;
962	list_add_tail(&acl->head.list, &domain->acl_info_list);
963	error = 0;
964	goto out;
965 delete:
966	error = -ENOENT;
967	list_for_each_entry(ptr, &domain->acl_info_list, list) {
968		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
969			continue;
970		acl = container_of(ptr, struct tomoyo_double_path_acl_record,
971				   head);
972		if (acl->filename1 != saved_filename1 ||
973		    acl->filename2 != saved_filename2)
974			continue;
975		acl->perm &= ~perm;
976		if (!acl->perm)
977			ptr->type |= TOMOYO_ACL_DELETED;
978		error = 0;
979		break;
980	}
981 out:
982	up_write(&tomoyo_domain_acl_info_list_lock);
983	return error;
984}
985
986/**
987 * tomoyo_check_single_path_acl - Check permission for single path operation.
988 *
989 * @domain:   Pointer to "struct tomoyo_domain_info".
990 * @type:     Type of operation.
991 * @filename: Filename to check.
992 *
993 * Returns 0 on success, negative value otherwise.
994 */
995static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain,
996					const u8 type,
997					const struct tomoyo_path_info *filename)
998{
999	if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
1000		return 0;
1001	return tomoyo_check_single_path_acl2(domain, filename, 1 << type, 1);
1002}
1003
1004/**
1005 * tomoyo_check_double_path_acl - Check permission for double path operation.
1006 *
1007 * @domain:    Pointer to "struct tomoyo_domain_info".
1008 * @type:      Type of operation.
1009 * @filename1: First filename to check.
1010 * @filename2: Second filename to check.
1011 *
1012 * Returns 0 on success, -EPERM otherwise.
1013 */
1014static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
1015					const u8 type,
1016					const struct tomoyo_path_info *
1017					filename1,
1018					const struct tomoyo_path_info *
1019					filename2)
1020{
1021	struct tomoyo_acl_info *ptr;
1022	const u8 perm = 1 << type;
1023	int error = -EPERM;
1024
1025	if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
1026		return 0;
1027	down_read(&tomoyo_domain_acl_info_list_lock);
1028	list_for_each_entry(ptr, &domain->acl_info_list, list) {
1029		struct tomoyo_double_path_acl_record *acl;
1030		if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
1031			continue;
1032		acl = container_of(ptr, struct tomoyo_double_path_acl_record,
1033				   head);
1034		if (!(acl->perm & perm))
1035			continue;
1036		if (!tomoyo_path_matches_pattern(filename1, acl->filename1))
1037			continue;
1038		if (!tomoyo_path_matches_pattern(filename2, acl->filename2))
1039			continue;
1040		error = 0;
1041		break;
1042	}
1043	up_read(&tomoyo_domain_acl_info_list_lock);
1044	return error;
1045}
1046
1047/**
1048 * tomoyo_check_single_path_permission2 - Check permission for single path operation.
1049 *
1050 * @domain:    Pointer to "struct tomoyo_domain_info".
1051 * @operation: Type of operation.
1052 * @filename:  Filename to check.
1053 * @mode:      Access control mode.
1054 *
1055 * Returns 0 on success, negative value otherwise.
1056 */
1057static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
1058						const domain, u8 operation,
1059						const struct tomoyo_path_info *
1060						filename, const u8 mode)
1061{
1062	const char *msg;
1063	int error;
1064	const bool is_enforce = (mode == 3);
1065
1066	if (!mode)
1067		return 0;
1068 next:
1069	error = tomoyo_check_single_path_acl(domain, operation, filename);
1070	msg = tomoyo_sp2keyword(operation);
1071	if (!error)
1072		goto ok;
1073	if (tomoyo_verbose_mode(domain))
1074		printk(KERN_WARNING "TOMOYO-%s: Access '%s %s' denied for %s\n",
1075		       tomoyo_get_msg(is_enforce), msg, filename->name,
1076		       tomoyo_get_last_name(domain));
1077	if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
1078		const char *name = tomoyo_get_file_pattern(filename)->name;
1079		tomoyo_update_single_path_acl(operation, name, domain, false);
1080	}
1081	if (!is_enforce)
1082		error = 0;
1083 ok:
1084	/*
1085	 * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
1086	 * we need to check "allow_rewrite" permission if the filename is
1087	 * specified by "deny_rewrite" keyword.
1088	 */
1089	if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL &&
1090	    tomoyo_is_no_rewrite_file(filename)) {
1091		operation = TOMOYO_TYPE_REWRITE_ACL;
1092		goto next;
1093	}
1094	return error;
1095}
1096
1097/**
1098 * tomoyo_check_exec_perm - Check permission for "execute".
1099 *
1100 * @domain:   Pointer to "struct tomoyo_domain_info".
1101 * @filename: Check permission for "execute".
1102 *
1103 * Returns 0 on success, negativevalue otherwise.
1104 */
1105int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
1106			   const struct tomoyo_path_info *filename)
1107{
1108	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1109
1110	if (!mode)
1111		return 0;
1112	return tomoyo_check_file_perm2(domain, filename, 1, "do_execve", mode);
1113}
1114
1115/**
1116 * tomoyo_check_open_permission - Check permission for "read" and "write".
1117 *
1118 * @domain: Pointer to "struct tomoyo_domain_info".
1119 * @path:   Pointer to "struct path".
1120 * @flag:   Flags for open().
1121 *
1122 * Returns 0 on success, negative value otherwise.
1123 */
1124int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1125				 struct path *path, const int flag)
1126{
1127	const u8 acc_mode = ACC_MODE(flag);
1128	int error = -ENOMEM;
1129	struct tomoyo_path_info *buf;
1130	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1131	const bool is_enforce = (mode == 3);
1132
1133	if (!mode || !path->mnt)
1134		return 0;
1135	if (acc_mode == 0)
1136		return 0;
1137	if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))
1138		/*
1139		 * I don't check directories here because mkdir() and rmdir()
1140		 * don't call me.
1141		 */
1142		return 0;
1143	buf = tomoyo_get_path(path);
1144	if (!buf)
1145		goto out;
1146	error = 0;
1147	/*
1148	 * If the filename is specified by "deny_rewrite" keyword,
1149	 * we need to check "allow_rewrite" permission when the filename is not
1150	 * opened for append mode or the filename is truncated at open time.
1151	 */
1152	if ((acc_mode & MAY_WRITE) &&
1153	    ((flag & O_TRUNC) || !(flag & O_APPEND)) &&
1154	    (tomoyo_is_no_rewrite_file(buf))) {
1155		error = tomoyo_check_single_path_permission2(domain,
1156						     TOMOYO_TYPE_REWRITE_ACL,
1157							     buf, mode);
1158	}
1159	if (!error)
1160		error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open",
1161						mode);
1162	if (!error && (flag & O_TRUNC))
1163		error = tomoyo_check_single_path_permission2(domain,
1164						     TOMOYO_TYPE_TRUNCATE_ACL,
1165							     buf, mode);
1166 out:
1167	tomoyo_free(buf);
1168	if (!is_enforce)
1169		error = 0;
1170	return error;
1171}
1172
1173/**
1174 * tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink".
1175 *
1176 * @domain:    Pointer to "struct tomoyo_domain_info".
1177 * @operation: Type of operation.
1178 * @path:      Pointer to "struct path".
1179 *
1180 * Returns 0 on success, negative value otherwise.
1181 */
1182int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
1183			    const u8 operation, struct path *path)
1184{
1185	int error = -ENOMEM;
1186	struct tomoyo_path_info *buf;
1187	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1188	const bool is_enforce = (mode == 3);
1189
1190	if (!mode || !path->mnt)
1191		return 0;
1192	buf = tomoyo_get_path(path);
1193	if (!buf)
1194		goto out;
1195	switch (operation) {
1196	case TOMOYO_TYPE_MKDIR_ACL:
1197	case TOMOYO_TYPE_RMDIR_ACL:
1198		if (!buf->is_dir) {
1199			/*
1200			 * tomoyo_get_path() reserves space for appending "/."
1201			 */
1202			strcat((char *) buf->name, "/");
1203			tomoyo_fill_path_info(buf);
1204		}
1205	}
1206	error = tomoyo_check_single_path_permission2(domain, operation, buf,
1207						     mode);
1208 out:
1209	tomoyo_free(buf);
1210	if (!is_enforce)
1211		error = 0;
1212	return error;
1213}
1214
1215/**
1216 * tomoyo_check_rewrite_permission - Check permission for "rewrite".
1217 *
1218 * @domain: Pointer to "struct tomoyo_domain_info".
1219 * @filp: Pointer to "struct file".
1220 *
1221 * Returns 0 on success, negative value otherwise.
1222 */
1223int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
1224				    struct file *filp)
1225{
1226	int error = -ENOMEM;
1227	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1228	const bool is_enforce = (mode == 3);
1229	struct tomoyo_path_info *buf;
1230
1231	if (!mode || !filp->f_path.mnt)
1232		return 0;
1233	buf = tomoyo_get_path(&filp->f_path);
1234	if (!buf)
1235		goto out;
1236	if (!tomoyo_is_no_rewrite_file(buf)) {
1237		error = 0;
1238		goto out;
1239	}
1240	error = tomoyo_check_single_path_permission2(domain,
1241						     TOMOYO_TYPE_REWRITE_ACL,
1242						     buf, mode);
1243 out:
1244	tomoyo_free(buf);
1245	if (!is_enforce)
1246		error = 0;
1247	return error;
1248}
1249
1250/**
1251 * tomoyo_check_2path_perm - Check permission for "rename" and "link".
1252 *
1253 * @domain:    Pointer to "struct tomoyo_domain_info".
1254 * @operation: Type of operation.
1255 * @path1:      Pointer to "struct path".
1256 * @path2:      Pointer to "struct path".
1257 *
1258 * Returns 0 on success, negative value otherwise.
1259 */
1260int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain,
1261			    const u8 operation, struct path *path1,
1262			    struct path *path2)
1263{
1264	int error = -ENOMEM;
1265	struct tomoyo_path_info *buf1, *buf2;
1266	const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1267	const bool is_enforce = (mode == 3);
1268	const char *msg;
1269
1270	if (!mode || !path1->mnt || !path2->mnt)
1271		return 0;
1272	buf1 = tomoyo_get_path(path1);
1273	buf2 = tomoyo_get_path(path2);
1274	if (!buf1 || !buf2)
1275		goto out;
1276	{
1277		struct dentry *dentry = path1->dentry;
1278		if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
1279			/*
1280			 * tomoyo_get_path() reserves space for appending "/."
1281			 */
1282			if (!buf1->is_dir) {
1283				strcat((char *) buf1->name, "/");
1284				tomoyo_fill_path_info(buf1);
1285			}
1286			if (!buf2->is_dir) {
1287				strcat((char *) buf2->name, "/");
1288				tomoyo_fill_path_info(buf2);
1289			}
1290		}
1291	}
1292	error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2);
1293	msg = tomoyo_dp2keyword(operation);
1294	if (!error)
1295		goto out;
1296	if (tomoyo_verbose_mode(domain))
1297		printk(KERN_WARNING "TOMOYO-%s: Access '%s %s %s' "
1298		       "denied for %s\n", tomoyo_get_msg(is_enforce),
1299		       msg, buf1->name, buf2->name,
1300		       tomoyo_get_last_name(domain));
1301	if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
1302		const char *name1 = tomoyo_get_file_pattern(buf1)->name;
1303		const char *name2 = tomoyo_get_file_pattern(buf2)->name;
1304		tomoyo_update_double_path_acl(operation, name1, name2, domain,
1305					      false);
1306	}
1307 out:
1308	tomoyo_free(buf1);
1309	tomoyo_free(buf2);
1310	if (!is_enforce)
1311		error = 0;
1312	return error;
1313}
1314