xref: /openbmc/linux/security/tomoyo/file.c (revision a09d2831)
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  */
26 struct 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  */
43 struct 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  */
60 struct 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. */
67 static 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. */
86 static 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  */
98 const 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  */
111 const 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  */
125 static 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  */
142 static 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. */
162 DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock);
163 
164 static 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);
168 static 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  */
197 static LIST_HEAD(tomoyo_globally_readable_list);
198 static 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  */
208 static 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  */
251 static 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  */
276 int 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  */
288 bool 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  */
340 static LIST_HEAD(tomoyo_pattern_list);
341 static 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  */
351 static 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  */
394 static const struct tomoyo_path_info *
395 tomoyo_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  */
428 int 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  */
440 bool 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  */
489 static LIST_HEAD(tomoyo_no_rewrite_list);
490 static 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  */
500 static 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  */
543 static 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  */
569 int 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  */
581 bool 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  */
616 static 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  */
653 static 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  */
695 static 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  */
728 static 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  */
781 int 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  */
828 static 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  */
915 static 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  */
995 static 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  */
1014 static 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  */
1057 static 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  */
1105 int 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  */
1124 int 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  */
1182 int 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  */
1223 int 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  */
1260 int 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