2 * security/tomoyo/file.c
4 * Implementation of the Domain-Based Mandatory Access Control.
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
8 * Version: 2.2.0 2009/04/01
15 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
17 /* Structure for "allow_read" keyword. */
18 struct tomoyo_globally_readable_file_entry {
19 struct list_head list;
20 const struct tomoyo_path_info *filename;
24 /* Structure for "file_pattern" keyword. */
25 struct tomoyo_pattern_entry {
26 struct list_head list;
27 const struct tomoyo_path_info *pattern;
31 /* Structure for "deny_rewrite" keyword. */
32 struct tomoyo_no_rewrite_entry {
33 struct list_head list;
34 const struct tomoyo_path_info *pattern;
38 /* Keyword array for single path operations. */
39 static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = {
40 [TOMOYO_TYPE_READ_WRITE_ACL] = "read/write",
41 [TOMOYO_TYPE_EXECUTE_ACL] = "execute",
42 [TOMOYO_TYPE_READ_ACL] = "read",
43 [TOMOYO_TYPE_WRITE_ACL] = "write",
44 [TOMOYO_TYPE_CREATE_ACL] = "create",
45 [TOMOYO_TYPE_UNLINK_ACL] = "unlink",
46 [TOMOYO_TYPE_MKDIR_ACL] = "mkdir",
47 [TOMOYO_TYPE_RMDIR_ACL] = "rmdir",
48 [TOMOYO_TYPE_MKFIFO_ACL] = "mkfifo",
49 [TOMOYO_TYPE_MKSOCK_ACL] = "mksock",
50 [TOMOYO_TYPE_MKBLOCK_ACL] = "mkblock",
51 [TOMOYO_TYPE_MKCHAR_ACL] = "mkchar",
52 [TOMOYO_TYPE_TRUNCATE_ACL] = "truncate",
53 [TOMOYO_TYPE_SYMLINK_ACL] = "symlink",
54 [TOMOYO_TYPE_REWRITE_ACL] = "rewrite",
57 /* Keyword array for double path operations. */
58 static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = {
59 [TOMOYO_TYPE_LINK_ACL] = "link",
60 [TOMOYO_TYPE_RENAME_ACL] = "rename",
64 * tomoyo_sp2keyword - Get the name of single path operation.
66 * @operation: Type of operation.
68 * Returns the name of single path operation.
70 const char *tomoyo_sp2keyword(const u8 operation)
72 return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION)
73 ? tomoyo_sp_keyword[operation] : NULL;
77 * tomoyo_dp2keyword - Get the name of double path operation.
79 * @operation: Type of operation.
81 * Returns the name of double path operation.
83 const char *tomoyo_dp2keyword(const u8 operation)
85 return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION)
86 ? tomoyo_dp_keyword[operation] : NULL;
90 * tomoyo_strendswith - Check whether the token ends with the given token.
92 * @name: The token to check.
93 * @tail: The token to find.
95 * Returns true if @name ends with @tail, false otherwise.
97 static bool tomoyo_strendswith(const char *name, const char *tail)
103 len = strlen(name) - strlen(tail);
104 return len >= 0 && !strcmp(name + len, tail);
108 * tomoyo_get_path - Get realpath.
110 * @path: Pointer to "struct path".
112 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
114 static struct tomoyo_path_info *tomoyo_get_path(struct path *path)
117 struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf));
121 /* Reserve one byte for appending "/". */
122 error = tomoyo_realpath_from_path2(path, buf->body,
123 sizeof(buf->body) - 2);
125 buf->head.name = buf->body;
126 tomoyo_fill_path_info(&buf->head);
133 /* Lock for domain->acl_info_list. */
134 DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock);
136 static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
137 const char *filename2,
138 struct tomoyo_domain_info *
139 const domain, const bool is_delete);
140 static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
141 struct tomoyo_domain_info *
142 const domain, const bool is_delete);
144 /* The list for "struct tomoyo_globally_readable_file_entry". */
145 static LIST_HEAD(tomoyo_globally_readable_list);
146 static DECLARE_RWSEM(tomoyo_globally_readable_list_lock);
149 * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list.
151 * @filename: Filename unconditionally permitted to open() for reading.
152 * @is_delete: True if it is a delete request.
154 * Returns 0 on success, negative value otherwise.
156 static int tomoyo_update_globally_readable_entry(const char *filename,
157 const bool is_delete)
159 struct tomoyo_globally_readable_file_entry *new_entry;
160 struct tomoyo_globally_readable_file_entry *ptr;
161 const struct tomoyo_path_info *saved_filename;
164 if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__))
166 saved_filename = tomoyo_save_name(filename);
169 /***** EXCLUSIVE SECTION START *****/
170 down_write(&tomoyo_globally_readable_list_lock);
171 list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
172 if (ptr->filename != saved_filename)
174 ptr->is_deleted = is_delete;
182 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
185 new_entry->filename = saved_filename;
186 list_add_tail(&new_entry->list, &tomoyo_globally_readable_list);
189 up_write(&tomoyo_globally_readable_list_lock);
190 /***** EXCLUSIVE SECTION END *****/
195 * tomoyo_is_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading.
197 * @filename: The filename to check.
199 * Returns true if any domain can open @filename for reading, false otherwise.
201 static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info *
204 struct tomoyo_globally_readable_file_entry *ptr;
206 down_read(&tomoyo_globally_readable_list_lock);
207 list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) {
208 if (!ptr->is_deleted &&
209 tomoyo_path_matches_pattern(filename, ptr->filename)) {
214 up_read(&tomoyo_globally_readable_list_lock);
219 * tomoyo_write_globally_readable_policy - Write "struct tomoyo_globally_readable_file_entry" list.
221 * @data: String to parse.
222 * @is_delete: True if it is a delete request.
224 * Returns 0 on success, negative value otherwise.
226 int tomoyo_write_globally_readable_policy(char *data, const bool is_delete)
228 return tomoyo_update_globally_readable_entry(data, is_delete);
232 * tomoyo_read_globally_readable_policy - Read "struct tomoyo_globally_readable_file_entry" list.
234 * @head: Pointer to "struct tomoyo_io_buffer".
236 * Returns true on success, false otherwise.
238 bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head)
240 struct list_head *pos;
243 down_read(&tomoyo_globally_readable_list_lock);
244 list_for_each_cookie(pos, head->read_var2,
245 &tomoyo_globally_readable_list) {
246 struct tomoyo_globally_readable_file_entry *ptr;
247 ptr = list_entry(pos,
248 struct tomoyo_globally_readable_file_entry,
252 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_ALLOW_READ "%s\n",
253 ptr->filename->name)) {
258 up_read(&tomoyo_globally_readable_list_lock);
262 /* The list for "struct tomoyo_pattern_entry". */
263 static LIST_HEAD(tomoyo_pattern_list);
264 static DECLARE_RWSEM(tomoyo_pattern_list_lock);
267 * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list.
269 * @pattern: Pathname pattern.
270 * @is_delete: True if it is a delete request.
272 * Returns 0 on success, negative value otherwise.
274 static int tomoyo_update_file_pattern_entry(const char *pattern,
275 const bool is_delete)
277 struct tomoyo_pattern_entry *new_entry;
278 struct tomoyo_pattern_entry *ptr;
279 const struct tomoyo_path_info *saved_pattern;
282 if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__))
284 saved_pattern = tomoyo_save_name(pattern);
287 /***** EXCLUSIVE SECTION START *****/
288 down_write(&tomoyo_pattern_list_lock);
289 list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
290 if (saved_pattern != ptr->pattern)
292 ptr->is_deleted = is_delete;
300 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
303 new_entry->pattern = saved_pattern;
304 list_add_tail(&new_entry->list, &tomoyo_pattern_list);
307 up_write(&tomoyo_pattern_list_lock);
308 /***** EXCLUSIVE SECTION END *****/
313 * tomoyo_get_file_pattern - Get patterned pathname.
315 * @filename: The filename to find patterned pathname.
317 * Returns pointer to pathname pattern if matched, @filename otherwise.
319 static const struct tomoyo_path_info *
320 tomoyo_get_file_pattern(const struct tomoyo_path_info *filename)
322 struct tomoyo_pattern_entry *ptr;
323 const struct tomoyo_path_info *pattern = NULL;
325 down_read(&tomoyo_pattern_list_lock);
326 list_for_each_entry(ptr, &tomoyo_pattern_list, list) {
329 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
331 pattern = ptr->pattern;
332 if (tomoyo_strendswith(pattern->name, "/\\*")) {
333 /* Do nothing. Try to find the better match. */
335 /* This would be the better match. Use this. */
339 up_read(&tomoyo_pattern_list_lock);
346 * tomoyo_write_pattern_policy - Write "struct tomoyo_pattern_entry" list.
348 * @data: String to parse.
349 * @is_delete: True if it is a delete request.
351 * Returns 0 on success, negative value otherwise.
353 int tomoyo_write_pattern_policy(char *data, const bool is_delete)
355 return tomoyo_update_file_pattern_entry(data, is_delete);
359 * tomoyo_read_file_pattern - Read "struct tomoyo_pattern_entry" list.
361 * @head: Pointer to "struct tomoyo_io_buffer".
363 * Returns true on success, false otherwise.
365 bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head)
367 struct list_head *pos;
370 down_read(&tomoyo_pattern_list_lock);
371 list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) {
372 struct tomoyo_pattern_entry *ptr;
373 ptr = list_entry(pos, struct tomoyo_pattern_entry, list);
376 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_FILE_PATTERN "%s\n",
377 ptr->pattern->name)) {
382 up_read(&tomoyo_pattern_list_lock);
386 /* The list for "struct tomoyo_no_rewrite_entry". */
387 static LIST_HEAD(tomoyo_no_rewrite_list);
388 static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock);
391 * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list.
393 * @pattern: Pathname pattern that are not rewritable by default.
394 * @is_delete: True if it is a delete request.
396 * Returns 0 on success, negative value otherwise.
398 static int tomoyo_update_no_rewrite_entry(const char *pattern,
399 const bool is_delete)
401 struct tomoyo_no_rewrite_entry *new_entry, *ptr;
402 const struct tomoyo_path_info *saved_pattern;
405 if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__))
407 saved_pattern = tomoyo_save_name(pattern);
410 /***** EXCLUSIVE SECTION START *****/
411 down_write(&tomoyo_no_rewrite_list_lock);
412 list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
413 if (ptr->pattern != saved_pattern)
415 ptr->is_deleted = is_delete;
423 new_entry = tomoyo_alloc_element(sizeof(*new_entry));
426 new_entry->pattern = saved_pattern;
427 list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list);
430 up_write(&tomoyo_no_rewrite_list_lock);
431 /***** EXCLUSIVE SECTION END *****/
436 * tomoyo_is_no_rewrite_file - Check if the given pathname is not permitted to be rewrited.
438 * @filename: Filename to check.
440 * Returns true if @filename is specified by "deny_rewrite" directive,
443 static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename)
445 struct tomoyo_no_rewrite_entry *ptr;
448 down_read(&tomoyo_no_rewrite_list_lock);
449 list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) {
452 if (!tomoyo_path_matches_pattern(filename, ptr->pattern))
457 up_read(&tomoyo_no_rewrite_list_lock);
462 * tomoyo_write_no_rewrite_policy - Write "struct tomoyo_no_rewrite_entry" list.
464 * @data: String to parse.
465 * @is_delete: True if it is a delete request.
467 * Returns 0 on success, negative value otherwise.
469 int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete)
471 return tomoyo_update_no_rewrite_entry(data, is_delete);
475 * tomoyo_read_no_rewrite_policy - Read "struct tomoyo_no_rewrite_entry" list.
477 * @head: Pointer to "struct tomoyo_io_buffer".
479 * Returns true on success, false otherwise.
481 bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head)
483 struct list_head *pos;
486 down_read(&tomoyo_no_rewrite_list_lock);
487 list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) {
488 struct tomoyo_no_rewrite_entry *ptr;
489 ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list);
492 if (!tomoyo_io_printf(head, TOMOYO_KEYWORD_DENY_REWRITE "%s\n",
493 ptr->pattern->name)) {
498 up_read(&tomoyo_no_rewrite_list_lock);
503 * tomoyo_update_file_acl - Update file's read/write/execute ACL.
505 * @filename: Filename.
506 * @perm: Permission (between 1 to 7).
507 * @domain: Pointer to "struct tomoyo_domain_info".
508 * @is_delete: True if it is a delete request.
510 * Returns 0 on success, negative value otherwise.
512 * This is legacy support interface for older policy syntax.
513 * Current policy syntax uses "allow_read/write" instead of "6",
514 * "allow_read" instead of "4", "allow_write" instead of "2",
515 * "allow_execute" instead of "1".
517 static int tomoyo_update_file_acl(const char *filename, u8 perm,
518 struct tomoyo_domain_info * const domain,
519 const bool is_delete)
521 if (perm > 7 || !perm) {
522 printk(KERN_DEBUG "%s: Invalid permission '%d %s'\n",
523 __func__, perm, filename);
526 if (filename[0] != '@' && tomoyo_strendswith(filename, "/"))
528 * Only 'allow_mkdir' and 'allow_rmdir' are valid for
529 * directory permissions.
533 tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename,
536 tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename,
539 tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL,
540 filename, domain, is_delete);
545 * tomoyo_check_single_path_acl2 - Check permission for single path operation.
547 * @domain: Pointer to "struct tomoyo_domain_info".
548 * @filename: Filename to check.
550 * @may_use_pattern: True if patterned ACL is permitted.
552 * Returns 0 on success, -EPERM otherwise.
554 static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info *
556 const struct tomoyo_path_info *
559 const bool may_use_pattern)
561 struct tomoyo_acl_info *ptr;
564 down_read(&tomoyo_domain_acl_info_list_lock);
565 list_for_each_entry(ptr, &domain->acl_info_list, list) {
566 struct tomoyo_single_path_acl_record *acl;
567 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
569 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
571 if (!(acl->perm & perm))
573 if (may_use_pattern || !acl->filename->is_patterned) {
574 if (!tomoyo_path_matches_pattern(filename,
583 up_read(&tomoyo_domain_acl_info_list_lock);
588 * tomoyo_check_file_acl - Check permission for opening files.
590 * @domain: Pointer to "struct tomoyo_domain_info".
591 * @filename: Filename to check.
592 * @operation: Mode ("read" or "write" or "read/write" or "execute").
594 * Returns 0 on success, -EPERM otherwise.
596 static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain,
597 const struct tomoyo_path_info *filename,
602 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
605 perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL;
606 else if (operation == 4)
607 perm = 1 << TOMOYO_TYPE_READ_ACL;
608 else if (operation == 2)
609 perm = 1 << TOMOYO_TYPE_WRITE_ACL;
610 else if (operation == 1)
611 perm = 1 << TOMOYO_TYPE_EXECUTE_ACL;
614 return tomoyo_check_single_path_acl2(domain, filename, perm,
619 * tomoyo_check_file_perm2 - Check permission for opening files.
621 * @domain: Pointer to "struct tomoyo_domain_info".
622 * @filename: Filename to check.
623 * @perm: Mode ("read" or "write" or "read/write" or "execute").
624 * @operation: Operation name passed used for verbose mode.
625 * @mode: Access control mode.
627 * Returns 0 on success, negative value otherwise.
629 static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain,
630 const struct tomoyo_path_info *filename,
631 const u8 perm, const char *operation,
634 const bool is_enforce = (mode == 3);
635 const char *msg = "<unknown>";
640 error = tomoyo_check_file_acl(domain, filename, perm);
641 if (error && perm == 4 &&
642 (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0
643 && tomoyo_is_globally_readable_file(filename))
646 msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL);
648 msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL);
650 msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL);
652 msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL);
657 if (tomoyo_verbose_mode(domain))
658 printk(KERN_WARNING "TOMOYO-%s: Access '%s(%s) %s' denied "
659 "for %s\n", tomoyo_get_msg(is_enforce), msg, operation,
660 filename->name, tomoyo_get_last_name(domain));
663 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
664 /* Don't use patterns for execute permission. */
665 const struct tomoyo_path_info *patterned_file = (perm != 1) ?
666 tomoyo_get_file_pattern(filename) : filename;
667 tomoyo_update_file_acl(patterned_file->name, perm,
674 * tomoyo_write_file_policy - Update file related list.
676 * @data: String to parse.
677 * @domain: Pointer to "struct tomoyo_domain_info".
678 * @is_delete: True if it is a delete request.
680 * Returns 0 on success, negative value otherwise.
682 int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain,
683 const bool is_delete)
685 char *filename = strchr(data, ' ');
693 if (sscanf(data, "%u", &perm) == 1)
694 return tomoyo_update_file_acl(filename, (u8) perm, domain,
696 if (strncmp(data, "allow_", 6))
699 for (type = 0; type < TOMOYO_MAX_SINGLE_PATH_OPERATION; type++) {
700 if (strcmp(data, tomoyo_sp_keyword[type]))
702 return tomoyo_update_single_path_acl(type, filename,
705 filename2 = strchr(filename, ' ');
709 for (type = 0; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION; type++) {
710 if (strcmp(data, tomoyo_dp_keyword[type]))
712 return tomoyo_update_double_path_acl(type, filename, filename2,
720 * tomoyo_update_single_path_acl - Update "struct tomoyo_single_path_acl_record" list.
722 * @type: Type of operation.
723 * @filename: Filename.
724 * @domain: Pointer to "struct tomoyo_domain_info".
725 * @is_delete: True if it is a delete request.
727 * Returns 0 on success, negative value otherwise.
729 static int tomoyo_update_single_path_acl(const u8 type, const char *filename,
730 struct tomoyo_domain_info *
731 const domain, const bool is_delete)
733 static const u16 rw_mask =
734 (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL);
735 const struct tomoyo_path_info *saved_filename;
736 struct tomoyo_acl_info *ptr;
737 struct tomoyo_single_path_acl_record *acl;
739 const u16 perm = 1 << type;
743 if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__))
745 saved_filename = tomoyo_save_name(filename);
748 /***** EXCLUSIVE SECTION START *****/
749 down_write(&tomoyo_domain_acl_info_list_lock);
752 list_for_each_entry(ptr, &domain->acl_info_list, list) {
753 if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
755 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
757 if (acl->filename != saved_filename)
759 /* Special case. Clear all bits if marked as deleted. */
760 if (ptr->type & TOMOYO_ACL_DELETED)
763 if ((acl->perm & rw_mask) == rw_mask)
764 acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL;
765 else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))
766 acl->perm |= rw_mask;
767 ptr->type &= ~TOMOYO_ACL_DELETED;
771 /* Not found. Append it to the tail. */
772 acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL);
776 if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL))
777 acl->perm |= rw_mask;
778 acl->filename = saved_filename;
779 list_add_tail(&acl->head.list, &domain->acl_info_list);
784 list_for_each_entry(ptr, &domain->acl_info_list, list) {
785 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL)
787 acl = container_of(ptr, struct tomoyo_single_path_acl_record,
789 if (acl->filename != saved_filename)
792 if ((acl->perm & rw_mask) != rw_mask)
793 acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL);
794 else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)))
795 acl->perm &= ~rw_mask;
797 ptr->type |= TOMOYO_ACL_DELETED;
802 up_write(&tomoyo_domain_acl_info_list_lock);
803 /***** EXCLUSIVE SECTION END *****/
808 * tomoyo_update_double_path_acl - Update "struct tomoyo_double_path_acl_record" list.
810 * @type: Type of operation.
811 * @filename1: First filename.
812 * @filename2: Second filename.
813 * @domain: Pointer to "struct tomoyo_domain_info".
814 * @is_delete: True if it is a delete request.
816 * Returns 0 on success, negative value otherwise.
818 static int tomoyo_update_double_path_acl(const u8 type, const char *filename1,
819 const char *filename2,
820 struct tomoyo_domain_info *
821 const domain, const bool is_delete)
823 const struct tomoyo_path_info *saved_filename1;
824 const struct tomoyo_path_info *saved_filename2;
825 struct tomoyo_acl_info *ptr;
826 struct tomoyo_double_path_acl_record *acl;
828 const u8 perm = 1 << type;
832 if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) ||
833 !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__))
835 saved_filename1 = tomoyo_save_name(filename1);
836 saved_filename2 = tomoyo_save_name(filename2);
837 if (!saved_filename1 || !saved_filename2)
839 /***** EXCLUSIVE SECTION START *****/
840 down_write(&tomoyo_domain_acl_info_list_lock);
843 list_for_each_entry(ptr, &domain->acl_info_list, list) {
844 if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
846 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
848 if (acl->filename1 != saved_filename1 ||
849 acl->filename2 != saved_filename2)
851 /* Special case. Clear all bits if marked as deleted. */
852 if (ptr->type & TOMOYO_ACL_DELETED)
855 ptr->type &= ~TOMOYO_ACL_DELETED;
859 /* Not found. Append it to the tail. */
860 acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL);
864 acl->filename1 = saved_filename1;
865 acl->filename2 = saved_filename2;
866 list_add_tail(&acl->head.list, &domain->acl_info_list);
871 list_for_each_entry(ptr, &domain->acl_info_list, list) {
872 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
874 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
876 if (acl->filename1 != saved_filename1 ||
877 acl->filename2 != saved_filename2)
881 ptr->type |= TOMOYO_ACL_DELETED;
886 up_write(&tomoyo_domain_acl_info_list_lock);
887 /***** EXCLUSIVE SECTION END *****/
892 * tomoyo_check_single_path_acl - Check permission for single path operation.
894 * @domain: Pointer to "struct tomoyo_domain_info".
895 * @type: Type of operation.
896 * @filename: Filename to check.
898 * Returns 0 on success, negative value otherwise.
900 static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain,
902 const struct tomoyo_path_info *filename)
904 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
906 return tomoyo_check_single_path_acl2(domain, filename, 1 << type, 1);
910 * tomoyo_check_double_path_acl - Check permission for double path operation.
912 * @domain: Pointer to "struct tomoyo_domain_info".
913 * @type: Type of operation.
914 * @filename1: First filename to check.
915 * @filename2: Second filename to check.
917 * Returns 0 on success, -EPERM otherwise.
919 static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain,
921 const struct tomoyo_path_info *
923 const struct tomoyo_path_info *
926 struct tomoyo_acl_info *ptr;
927 const u8 perm = 1 << type;
930 if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE))
932 down_read(&tomoyo_domain_acl_info_list_lock);
933 list_for_each_entry(ptr, &domain->acl_info_list, list) {
934 struct tomoyo_double_path_acl_record *acl;
935 if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL)
937 acl = container_of(ptr, struct tomoyo_double_path_acl_record,
939 if (!(acl->perm & perm))
941 if (!tomoyo_path_matches_pattern(filename1, acl->filename1))
943 if (!tomoyo_path_matches_pattern(filename2, acl->filename2))
948 up_read(&tomoyo_domain_acl_info_list_lock);
953 * tomoyo_check_single_path_permission2 - Check permission for single path operation.
955 * @domain: Pointer to "struct tomoyo_domain_info".
956 * @operation: Type of operation.
957 * @filename: Filename to check.
958 * @mode: Access control mode.
960 * Returns 0 on success, negative value otherwise.
962 static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info *
963 const domain, u8 operation,
964 const struct tomoyo_path_info *
965 filename, const u8 mode)
969 const bool is_enforce = (mode == 3);
974 error = tomoyo_check_single_path_acl(domain, operation, filename);
975 msg = tomoyo_sp2keyword(operation);
978 if (tomoyo_verbose_mode(domain))
979 printk(KERN_WARNING "TOMOYO-%s: Access '%s %s' denied for %s\n",
980 tomoyo_get_msg(is_enforce), msg, filename->name,
981 tomoyo_get_last_name(domain));
982 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
983 const char *name = tomoyo_get_file_pattern(filename)->name;
984 tomoyo_update_single_path_acl(operation, name, domain, false);
990 * Since "allow_truncate" doesn't imply "allow_rewrite" permission,
991 * we need to check "allow_rewrite" permission if the filename is
992 * specified by "deny_rewrite" keyword.
994 if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL &&
995 tomoyo_is_no_rewrite_file(filename)) {
996 operation = TOMOYO_TYPE_REWRITE_ACL;
1003 * tomoyo_check_file_perm - Check permission for sysctl()'s "read" and "write".
1005 * @domain: Pointer to "struct tomoyo_domain_info".
1006 * @filename: Filename to check.
1007 * @perm: Mode ("read" or "write" or "read/write").
1008 * Returns 0 on success, negative value otherwise.
1010 int tomoyo_check_file_perm(struct tomoyo_domain_info *domain,
1011 const char *filename, const u8 perm)
1013 struct tomoyo_path_info name;
1014 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1018 name.name = filename;
1019 tomoyo_fill_path_info(&name);
1020 return tomoyo_check_file_perm2(domain, &name, perm, "sysctl", mode);
1024 * tomoyo_check_exec_perm - Check permission for "execute".
1026 * @domain: Pointer to "struct tomoyo_domain_info".
1027 * @filename: Check permission for "execute".
1028 * @tmp: Buffer for temporary use.
1030 * Returns 0 on success, negativevalue otherwise.
1032 int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
1033 const struct tomoyo_path_info *filename,
1034 struct tomoyo_page_buffer *tmp)
1036 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1040 return tomoyo_check_file_perm2(domain, filename, 1, "do_execve", mode);
1044 * tomoyo_check_open_permission - Check permission for "read" and "write".
1046 * @domain: Pointer to "struct tomoyo_domain_info".
1047 * @path: Pointer to "struct path".
1048 * @flag: Flags for open().
1050 * Returns 0 on success, negative value otherwise.
1052 int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
1053 struct path *path, const int flag)
1055 const u8 acc_mode = ACC_MODE(flag);
1056 int error = -ENOMEM;
1057 struct tomoyo_path_info *buf;
1058 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1059 const bool is_enforce = (mode == 3);
1061 if (!mode || !path->mnt)
1065 if (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))
1067 * I don't check directories here because mkdir() and rmdir()
1071 buf = tomoyo_get_path(path);
1076 * If the filename is specified by "deny_rewrite" keyword,
1077 * we need to check "allow_rewrite" permission when the filename is not
1078 * opened for append mode or the filename is truncated at open time.
1080 if ((acc_mode & MAY_WRITE) &&
1081 ((flag & O_TRUNC) || !(flag & O_APPEND)) &&
1082 (tomoyo_is_no_rewrite_file(buf))) {
1083 error = tomoyo_check_single_path_permission2(domain,
1084 TOMOYO_TYPE_REWRITE_ACL,
1088 error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open",
1090 if (!error && (flag & O_TRUNC))
1091 error = tomoyo_check_single_path_permission2(domain,
1092 TOMOYO_TYPE_TRUNCATE_ACL,
1102 * tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink".
1104 * @domain: Pointer to "struct tomoyo_domain_info".
1105 * @operation: Type of operation.
1106 * @path: Pointer to "struct path".
1108 * Returns 0 on success, negative value otherwise.
1110 int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
1111 const u8 operation, struct path *path)
1113 int error = -ENOMEM;
1114 struct tomoyo_path_info *buf;
1115 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1116 const bool is_enforce = (mode == 3);
1118 if (!mode || !path->mnt)
1120 buf = tomoyo_get_path(path);
1123 switch (operation) {
1124 case TOMOYO_TYPE_MKDIR_ACL:
1125 case TOMOYO_TYPE_RMDIR_ACL:
1128 * tomoyo_get_path() reserves space for appending "/."
1130 strcat((char *) buf->name, "/");
1131 tomoyo_fill_path_info(buf);
1134 error = tomoyo_check_single_path_permission2(domain, operation, buf,
1144 * tomoyo_check_rewrite_permission - Check permission for "rewrite".
1146 * @domain: Pointer to "struct tomoyo_domain_info".
1147 * @filp: Pointer to "struct file".
1149 * Returns 0 on success, negative value otherwise.
1151 int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
1154 int error = -ENOMEM;
1155 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1156 const bool is_enforce = (mode == 3);
1157 struct tomoyo_path_info *buf;
1159 if (!mode || !filp->f_path.mnt)
1161 buf = tomoyo_get_path(&filp->f_path);
1164 if (!tomoyo_is_no_rewrite_file(buf)) {
1168 error = tomoyo_check_single_path_permission2(domain,
1169 TOMOYO_TYPE_REWRITE_ACL,
1179 * tomoyo_check_2path_perm - Check permission for "rename" and "link".
1181 * @domain: Pointer to "struct tomoyo_domain_info".
1182 * @operation: Type of operation.
1183 * @path1: Pointer to "struct path".
1184 * @path2: Pointer to "struct path".
1186 * Returns 0 on success, negative value otherwise.
1188 int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain,
1189 const u8 operation, struct path *path1,
1192 int error = -ENOMEM;
1193 struct tomoyo_path_info *buf1, *buf2;
1194 const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE);
1195 const bool is_enforce = (mode == 3);
1198 if (!mode || !path1->mnt || !path2->mnt)
1200 buf1 = tomoyo_get_path(path1);
1201 buf2 = tomoyo_get_path(path2);
1205 struct dentry *dentry = path1->dentry;
1206 if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) {
1208 * tomoyo_get_path() reserves space for appending "/."
1210 if (!buf1->is_dir) {
1211 strcat((char *) buf1->name, "/");
1212 tomoyo_fill_path_info(buf1);
1214 if (!buf2->is_dir) {
1215 strcat((char *) buf2->name, "/");
1216 tomoyo_fill_path_info(buf2);
1220 error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2);
1221 msg = tomoyo_dp2keyword(operation);
1224 if (tomoyo_verbose_mode(domain))
1225 printk(KERN_WARNING "TOMOYO-%s: Access '%s %s %s' "
1226 "denied for %s\n", tomoyo_get_msg(is_enforce),
1227 msg, buf1->name, buf2->name,
1228 tomoyo_get_last_name(domain));
1229 if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) {
1230 const char *name1 = tomoyo_get_file_pattern(buf1)->name;
1231 const char *name2 = tomoyo_get_file_pattern(buf2)->name;
1232 tomoyo_update_double_path_acl(operation, name1, name2, domain,