diff options
Diffstat (limited to 'security/tomoyo')
-rw-r--r-- | security/tomoyo/common.c | 60 | ||||
-rw-r--r-- | security/tomoyo/common.h | 93 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 13 | ||||
-rw-r--r-- | security/tomoyo/file.c | 368 | ||||
-rw-r--r-- | security/tomoyo/gc.c | 30 | ||||
-rw-r--r-- | security/tomoyo/mount.c | 5 | ||||
-rw-r--r-- | security/tomoyo/tomoyo.c | 14 | ||||
-rw-r--r-- | security/tomoyo/util.c | 23 |
8 files changed, 71 insertions, 535 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index a0d09e56874b..0776173b7d2b 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -39,13 +39,13 @@ static const char *tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX | |||
39 | [TOMOYO_MAC_FILE_OPEN] = "file::open", | 39 | [TOMOYO_MAC_FILE_OPEN] = "file::open", |
40 | [TOMOYO_MAC_FILE_CREATE] = "file::create", | 40 | [TOMOYO_MAC_FILE_CREATE] = "file::create", |
41 | [TOMOYO_MAC_FILE_UNLINK] = "file::unlink", | 41 | [TOMOYO_MAC_FILE_UNLINK] = "file::unlink", |
42 | [TOMOYO_MAC_FILE_GETATTR] = "file::getattr", | ||
42 | [TOMOYO_MAC_FILE_MKDIR] = "file::mkdir", | 43 | [TOMOYO_MAC_FILE_MKDIR] = "file::mkdir", |
43 | [TOMOYO_MAC_FILE_RMDIR] = "file::rmdir", | 44 | [TOMOYO_MAC_FILE_RMDIR] = "file::rmdir", |
44 | [TOMOYO_MAC_FILE_MKFIFO] = "file::mkfifo", | 45 | [TOMOYO_MAC_FILE_MKFIFO] = "file::mkfifo", |
45 | [TOMOYO_MAC_FILE_MKSOCK] = "file::mksock", | 46 | [TOMOYO_MAC_FILE_MKSOCK] = "file::mksock", |
46 | [TOMOYO_MAC_FILE_TRUNCATE] = "file::truncate", | 47 | [TOMOYO_MAC_FILE_TRUNCATE] = "file::truncate", |
47 | [TOMOYO_MAC_FILE_SYMLINK] = "file::symlink", | 48 | [TOMOYO_MAC_FILE_SYMLINK] = "file::symlink", |
48 | [TOMOYO_MAC_FILE_REWRITE] = "file::rewrite", | ||
49 | [TOMOYO_MAC_FILE_MKBLOCK] = "file::mkblock", | 49 | [TOMOYO_MAC_FILE_MKBLOCK] = "file::mkblock", |
50 | [TOMOYO_MAC_FILE_MKCHAR] = "file::mkchar", | 50 | [TOMOYO_MAC_FILE_MKCHAR] = "file::mkchar", |
51 | [TOMOYO_MAC_FILE_LINK] = "file::link", | 51 | [TOMOYO_MAC_FILE_LINK] = "file::link", |
@@ -881,10 +881,6 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) | |||
881 | domain->profile = (u8) profile; | 881 | domain->profile = (u8) profile; |
882 | return 0; | 882 | return 0; |
883 | } | 883 | } |
884 | if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) { | ||
885 | domain->ignore_global_allow_read = !is_delete; | ||
886 | return 0; | ||
887 | } | ||
888 | if (!strcmp(data, TOMOYO_KEYWORD_QUOTA_EXCEEDED)) { | 884 | if (!strcmp(data, TOMOYO_KEYWORD_QUOTA_EXCEEDED)) { |
889 | domain->quota_warned = !is_delete; | 885 | domain->quota_warned = !is_delete; |
890 | return 0; | 886 | return 0; |
@@ -942,11 +938,6 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
942 | if (head->r.print_execute_only && | 938 | if (head->r.print_execute_only && |
943 | bit != TOMOYO_TYPE_EXECUTE) | 939 | bit != TOMOYO_TYPE_EXECUTE) |
944 | continue; | 940 | continue; |
945 | /* Print "read/write" instead of "read" and "write". */ | ||
946 | if ((bit == TOMOYO_TYPE_READ || | ||
947 | bit == TOMOYO_TYPE_WRITE) | ||
948 | && (perm & (1 << TOMOYO_TYPE_READ_WRITE))) | ||
949 | continue; | ||
950 | break; | 941 | break; |
951 | } | 942 | } |
952 | if (bit >= TOMOYO_MAX_PATH_OPERATION) | 943 | if (bit >= TOMOYO_MAX_PATH_OPERATION) |
@@ -1055,10 +1046,6 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head) | |||
1055 | tomoyo_set_string(head, "quota_exceeded\n"); | 1046 | tomoyo_set_string(head, "quota_exceeded\n"); |
1056 | if (domain->transition_failed) | 1047 | if (domain->transition_failed) |
1057 | tomoyo_set_string(head, "transition_failed\n"); | 1048 | tomoyo_set_string(head, "transition_failed\n"); |
1058 | if (domain->ignore_global_allow_read) | ||
1059 | tomoyo_set_string(head, | ||
1060 | TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ | ||
1061 | "\n"); | ||
1062 | head->r.step++; | 1049 | head->r.step++; |
1063 | tomoyo_set_lf(head); | 1050 | tomoyo_set_lf(head); |
1064 | /* fall through */ | 1051 | /* fall through */ |
@@ -1235,18 +1222,15 @@ static int tomoyo_write_exception(struct tomoyo_io_buffer *head) | |||
1235 | static const struct { | 1222 | static const struct { |
1236 | const char *keyword; | 1223 | const char *keyword; |
1237 | int (*write) (char *, const bool); | 1224 | int (*write) (char *, const bool); |
1238 | } tomoyo_callback[4] = { | 1225 | } tomoyo_callback[1] = { |
1239 | { TOMOYO_KEYWORD_AGGREGATOR, tomoyo_write_aggregator }, | 1226 | { TOMOYO_KEYWORD_AGGREGATOR, tomoyo_write_aggregator }, |
1240 | { TOMOYO_KEYWORD_FILE_PATTERN, tomoyo_write_pattern }, | ||
1241 | { TOMOYO_KEYWORD_DENY_REWRITE, tomoyo_write_no_rewrite }, | ||
1242 | { TOMOYO_KEYWORD_ALLOW_READ, tomoyo_write_globally_readable }, | ||
1243 | }; | 1227 | }; |
1244 | 1228 | ||
1245 | for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) | 1229 | for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) |
1246 | if (tomoyo_str_starts(&data, tomoyo_transition_type[i])) | 1230 | if (tomoyo_str_starts(&data, tomoyo_transition_type[i])) |
1247 | return tomoyo_write_transition_control(data, is_delete, | 1231 | return tomoyo_write_transition_control(data, is_delete, |
1248 | i); | 1232 | i); |
1249 | for (i = 0; i < 4; i++) | 1233 | for (i = 0; i < 1; i++) |
1250 | if (tomoyo_str_starts(&data, tomoyo_callback[i].keyword)) | 1234 | if (tomoyo_str_starts(&data, tomoyo_callback[i].keyword)) |
1251 | return tomoyo_callback[i].write(data, is_delete); | 1235 | return tomoyo_callback[i].write(data, is_delete); |
1252 | for (i = 0; i < TOMOYO_MAX_GROUP; i++) | 1236 | for (i = 0; i < TOMOYO_MAX_GROUP; i++) |
@@ -1336,15 +1320,6 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) | |||
1336 | name); | 1320 | name); |
1337 | } | 1321 | } |
1338 | break; | 1322 | break; |
1339 | case TOMOYO_ID_GLOBALLY_READABLE: | ||
1340 | { | ||
1341 | struct tomoyo_readable_file *ptr = | ||
1342 | container_of(acl, typeof(*ptr), head); | ||
1343 | tomoyo_set_string(head, | ||
1344 | TOMOYO_KEYWORD_ALLOW_READ); | ||
1345 | tomoyo_set_string(head, ptr->filename->name); | ||
1346 | } | ||
1347 | break; | ||
1348 | case TOMOYO_ID_AGGREGATOR: | 1323 | case TOMOYO_ID_AGGREGATOR: |
1349 | { | 1324 | { |
1350 | struct tomoyo_aggregator *ptr = | 1325 | struct tomoyo_aggregator *ptr = |
@@ -1358,24 +1333,6 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) | |||
1358 | ptr->aggregated_name->name); | 1333 | ptr->aggregated_name->name); |
1359 | } | 1334 | } |
1360 | break; | 1335 | break; |
1361 | case TOMOYO_ID_PATTERN: | ||
1362 | { | ||
1363 | struct tomoyo_no_pattern *ptr = | ||
1364 | container_of(acl, typeof(*ptr), head); | ||
1365 | tomoyo_set_string(head, | ||
1366 | TOMOYO_KEYWORD_FILE_PATTERN); | ||
1367 | tomoyo_set_string(head, ptr->pattern->name); | ||
1368 | } | ||
1369 | break; | ||
1370 | case TOMOYO_ID_NO_REWRITE: | ||
1371 | { | ||
1372 | struct tomoyo_no_rewrite *ptr = | ||
1373 | container_of(acl, typeof(*ptr), head); | ||
1374 | tomoyo_set_string(head, | ||
1375 | TOMOYO_KEYWORD_DENY_REWRITE); | ||
1376 | tomoyo_set_string(head, ptr->pattern->name); | ||
1377 | } | ||
1378 | break; | ||
1379 | default: | 1336 | default: |
1380 | continue; | 1337 | continue; |
1381 | } | 1338 | } |
@@ -1891,21 +1848,12 @@ int tomoyo_open_control(const u8 type, struct file *file) | |||
1891 | head->reader_idx = tomoyo_read_lock(); | 1848 | head->reader_idx = tomoyo_read_lock(); |
1892 | file->private_data = head; | 1849 | file->private_data = head; |
1893 | /* | 1850 | /* |
1894 | * Call the handler now if the file is | ||
1895 | * /sys/kernel/security/tomoyo/self_domain | ||
1896 | * so that the user can use | ||
1897 | * cat < /sys/kernel/security/tomoyo/self_domain" | ||
1898 | * to know the current process's domainname. | ||
1899 | */ | ||
1900 | if (type == TOMOYO_SELFDOMAIN) | ||
1901 | tomoyo_read_control(file, NULL, 0); | ||
1902 | /* | ||
1903 | * If the file is /sys/kernel/security/tomoyo/query , increment the | 1851 | * If the file is /sys/kernel/security/tomoyo/query , increment the |
1904 | * observer counter. | 1852 | * observer counter. |
1905 | * The obserber counter is used by tomoyo_supervisor() to see if | 1853 | * The obserber counter is used by tomoyo_supervisor() to see if |
1906 | * there is some process monitoring /sys/kernel/security/tomoyo/query. | 1854 | * there is some process monitoring /sys/kernel/security/tomoyo/query. |
1907 | */ | 1855 | */ |
1908 | else if (type == TOMOYO_QUERY) | 1856 | if (type == TOMOYO_QUERY) |
1909 | atomic_inc(&tomoyo_query_observers); | 1857 | atomic_inc(&tomoyo_query_observers); |
1910 | return 0; | 1858 | return 0; |
1911 | } | 1859 | } |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 7c66bd898782..a5d6e212b18f 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -52,9 +52,6 @@ enum tomoyo_policy_id { | |||
52 | TOMOYO_ID_NUMBER_GROUP, | 52 | TOMOYO_ID_NUMBER_GROUP, |
53 | TOMOYO_ID_TRANSITION_CONTROL, | 53 | TOMOYO_ID_TRANSITION_CONTROL, |
54 | TOMOYO_ID_AGGREGATOR, | 54 | TOMOYO_ID_AGGREGATOR, |
55 | TOMOYO_ID_GLOBALLY_READABLE, | ||
56 | TOMOYO_ID_PATTERN, | ||
57 | TOMOYO_ID_NO_REWRITE, | ||
58 | TOMOYO_ID_MANAGER, | 55 | TOMOYO_ID_MANAGER, |
59 | TOMOYO_ID_NAME, | 56 | TOMOYO_ID_NAME, |
60 | TOMOYO_ID_ACL, | 57 | TOMOYO_ID_ACL, |
@@ -73,8 +70,6 @@ enum tomoyo_group_id { | |||
73 | #define TOMOYO_KEYWORD_ALLOW_MOUNT "allow_mount " | 70 | #define TOMOYO_KEYWORD_ALLOW_MOUNT "allow_mount " |
74 | #define TOMOYO_KEYWORD_ALLOW_READ "allow_read " | 71 | #define TOMOYO_KEYWORD_ALLOW_READ "allow_read " |
75 | #define TOMOYO_KEYWORD_DELETE "delete " | 72 | #define TOMOYO_KEYWORD_DELETE "delete " |
76 | #define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite " | ||
77 | #define TOMOYO_KEYWORD_FILE_PATTERN "file_pattern " | ||
78 | #define TOMOYO_KEYWORD_INITIALIZE_DOMAIN "initialize_domain " | 73 | #define TOMOYO_KEYWORD_INITIALIZE_DOMAIN "initialize_domain " |
79 | #define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain " | 74 | #define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain " |
80 | #define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " | 75 | #define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " |
@@ -83,7 +78,6 @@ enum tomoyo_group_id { | |||
83 | #define TOMOYO_KEYWORD_NUMBER_GROUP "number_group " | 78 | #define TOMOYO_KEYWORD_NUMBER_GROUP "number_group " |
84 | #define TOMOYO_KEYWORD_SELECT "select " | 79 | #define TOMOYO_KEYWORD_SELECT "select " |
85 | #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " | 80 | #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " |
86 | #define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" | ||
87 | #define TOMOYO_KEYWORD_QUOTA_EXCEEDED "quota_exceeded" | 81 | #define TOMOYO_KEYWORD_QUOTA_EXCEEDED "quota_exceeded" |
88 | #define TOMOYO_KEYWORD_TRANSITION_FAILED "transition_failed" | 82 | #define TOMOYO_KEYWORD_TRANSITION_FAILED "transition_failed" |
89 | /* A domain definition starts with <kernel>. */ | 83 | /* A domain definition starts with <kernel>. */ |
@@ -115,35 +109,21 @@ enum tomoyo_acl_entry_type_index { | |||
115 | }; | 109 | }; |
116 | 110 | ||
117 | /* Index numbers for File Controls. */ | 111 | /* Index numbers for File Controls. */ |
118 | |||
119 | /* | ||
120 | * TOMOYO_TYPE_READ_WRITE is special. TOMOYO_TYPE_READ_WRITE is automatically | ||
121 | * set if both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are set. | ||
122 | * Both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are automatically set if | ||
123 | * TOMOYO_TYPE_READ_WRITE is set. | ||
124 | * TOMOYO_TYPE_READ_WRITE is automatically cleared if either TOMOYO_TYPE_READ | ||
125 | * or TOMOYO_TYPE_WRITE is cleared. | ||
126 | * Both TOMOYO_TYPE_READ and TOMOYO_TYPE_WRITE are automatically cleared if | ||
127 | * TOMOYO_TYPE_READ_WRITE is cleared. | ||
128 | */ | ||
129 | |||
130 | enum tomoyo_path_acl_index { | 112 | enum tomoyo_path_acl_index { |
131 | TOMOYO_TYPE_READ_WRITE, | ||
132 | TOMOYO_TYPE_EXECUTE, | 113 | TOMOYO_TYPE_EXECUTE, |
133 | TOMOYO_TYPE_READ, | 114 | TOMOYO_TYPE_READ, |
134 | TOMOYO_TYPE_WRITE, | 115 | TOMOYO_TYPE_WRITE, |
116 | TOMOYO_TYPE_APPEND, | ||
135 | TOMOYO_TYPE_UNLINK, | 117 | TOMOYO_TYPE_UNLINK, |
118 | TOMOYO_TYPE_GETATTR, | ||
136 | TOMOYO_TYPE_RMDIR, | 119 | TOMOYO_TYPE_RMDIR, |
137 | TOMOYO_TYPE_TRUNCATE, | 120 | TOMOYO_TYPE_TRUNCATE, |
138 | TOMOYO_TYPE_SYMLINK, | 121 | TOMOYO_TYPE_SYMLINK, |
139 | TOMOYO_TYPE_REWRITE, | ||
140 | TOMOYO_TYPE_CHROOT, | 122 | TOMOYO_TYPE_CHROOT, |
141 | TOMOYO_TYPE_UMOUNT, | 123 | TOMOYO_TYPE_UMOUNT, |
142 | TOMOYO_MAX_PATH_OPERATION | 124 | TOMOYO_MAX_PATH_OPERATION |
143 | }; | 125 | }; |
144 | 126 | ||
145 | #define TOMOYO_RW_MASK ((1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE)) | ||
146 | |||
147 | enum tomoyo_mkdev_acl_index { | 127 | enum tomoyo_mkdev_acl_index { |
148 | TOMOYO_TYPE_MKBLOCK, | 128 | TOMOYO_TYPE_MKBLOCK, |
149 | TOMOYO_TYPE_MKCHAR, | 129 | TOMOYO_TYPE_MKCHAR, |
@@ -187,13 +167,13 @@ enum tomoyo_mac_index { | |||
187 | TOMOYO_MAC_FILE_OPEN, | 167 | TOMOYO_MAC_FILE_OPEN, |
188 | TOMOYO_MAC_FILE_CREATE, | 168 | TOMOYO_MAC_FILE_CREATE, |
189 | TOMOYO_MAC_FILE_UNLINK, | 169 | TOMOYO_MAC_FILE_UNLINK, |
170 | TOMOYO_MAC_FILE_GETATTR, | ||
190 | TOMOYO_MAC_FILE_MKDIR, | 171 | TOMOYO_MAC_FILE_MKDIR, |
191 | TOMOYO_MAC_FILE_RMDIR, | 172 | TOMOYO_MAC_FILE_RMDIR, |
192 | TOMOYO_MAC_FILE_MKFIFO, | 173 | TOMOYO_MAC_FILE_MKFIFO, |
193 | TOMOYO_MAC_FILE_MKSOCK, | 174 | TOMOYO_MAC_FILE_MKSOCK, |
194 | TOMOYO_MAC_FILE_TRUNCATE, | 175 | TOMOYO_MAC_FILE_TRUNCATE, |
195 | TOMOYO_MAC_FILE_SYMLINK, | 176 | TOMOYO_MAC_FILE_SYMLINK, |
196 | TOMOYO_MAC_FILE_REWRITE, | ||
197 | TOMOYO_MAC_FILE_MKBLOCK, | 177 | TOMOYO_MAC_FILE_MKBLOCK, |
198 | TOMOYO_MAC_FILE_MKCHAR, | 178 | TOMOYO_MAC_FILE_MKCHAR, |
199 | TOMOYO_MAC_FILE_LINK, | 179 | TOMOYO_MAC_FILE_LINK, |
@@ -388,9 +368,7 @@ struct tomoyo_acl_info { | |||
388 | * "deleted", false otherwise. | 368 | * "deleted", false otherwise. |
389 | * (6) "quota_warned" is a bool which is used for suppressing warning message | 369 | * (6) "quota_warned" is a bool which is used for suppressing warning message |
390 | * when learning mode learned too much entries. | 370 | * when learning mode learned too much entries. |
391 | * (7) "ignore_global_allow_read" is a bool which is true if this domain | 371 | * (7) "transition_failed" is a bool which is set to true when this domain was |
392 | * should ignore "allow_read" directive in exception policy. | ||
393 | * (8) "transition_failed" is a bool which is set to true when this domain was | ||
394 | * unable to create a new domain at tomoyo_find_next_domain() because the | 372 | * unable to create a new domain at tomoyo_find_next_domain() because the |
395 | * name of the domain to be created was too long or it could not allocate | 373 | * name of the domain to be created was too long or it could not allocate |
396 | * memory. If set to true, more than one process continued execve() | 374 | * memory. If set to true, more than one process continued execve() |
@@ -415,7 +393,6 @@ struct tomoyo_domain_info { | |||
415 | u8 profile; /* Profile number to use. */ | 393 | u8 profile; /* Profile number to use. */ |
416 | bool is_deleted; /* Delete flag. */ | 394 | bool is_deleted; /* Delete flag. */ |
417 | bool quota_warned; /* Quota warnning flag. */ | 395 | bool quota_warned; /* Quota warnning flag. */ |
418 | bool ignore_global_allow_read; /* Ignore "allow_read" flag. */ | ||
419 | bool transition_failed; /* Domain transition failed flag. */ | 396 | bool transition_failed; /* Domain transition failed flag. */ |
420 | atomic_t users; /* Number of referring credentials. */ | 397 | atomic_t users; /* Number of referring credentials. */ |
421 | }; | 398 | }; |
@@ -429,10 +406,9 @@ struct tomoyo_domain_info { | |||
429 | * (2) "perm" which is a bitmask of permitted operations. | 406 | * (2) "perm" which is a bitmask of permitted operations. |
430 | * (3) "name" is the pathname. | 407 | * (3) "name" is the pathname. |
431 | * | 408 | * |
432 | * Directives held by this structure are "allow_read/write", "allow_execute", | 409 | * Directives held by this structure are "allow_execute", "allow_read", |
433 | * "allow_read", "allow_write", "allow_unlink", "allow_rmdir", | 410 | * "allow_write", "allow_append", "allow_unlink", "allow_rmdir", |
434 | * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_chroot" and | 411 | * "allow_truncate", "allow_symlink", "allow_chroot" and "allow_unmount". |
435 | * "allow_unmount". | ||
436 | */ | 412 | */ |
437 | struct tomoyo_path_acl { | 413 | struct tomoyo_path_acl { |
438 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ | 414 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ |
@@ -574,47 +550,6 @@ struct tomoyo_io_buffer { | |||
574 | }; | 550 | }; |
575 | 551 | ||
576 | /* | 552 | /* |
577 | * tomoyo_readable_file is a structure which is used for holding | ||
578 | * "allow_read" entries. | ||
579 | * It has following fields. | ||
580 | * | ||
581 | * (1) "head" is "struct tomoyo_acl_head". | ||
582 | * (2) "filename" is a pathname which is allowed to open(O_RDONLY). | ||
583 | */ | ||
584 | struct tomoyo_readable_file { | ||
585 | struct tomoyo_acl_head head; | ||
586 | const struct tomoyo_path_info *filename; | ||
587 | }; | ||
588 | |||
589 | /* | ||
590 | * tomoyo_no_pattern is a structure which is used for holding | ||
591 | * "file_pattern" entries. | ||
592 | * It has following fields. | ||
593 | * | ||
594 | * (1) "head" is "struct tomoyo_acl_head". | ||
595 | * (2) "pattern" is a pathname pattern which is used for converting pathnames | ||
596 | * to pathname patterns during learning mode. | ||
597 | */ | ||
598 | struct tomoyo_no_pattern { | ||
599 | struct tomoyo_acl_head head; | ||
600 | const struct tomoyo_path_info *pattern; | ||
601 | }; | ||
602 | |||
603 | /* | ||
604 | * tomoyo_no_rewrite is a structure which is used for holding | ||
605 | * "deny_rewrite" entries. | ||
606 | * It has following fields. | ||
607 | * | ||
608 | * (1) "head" is "struct tomoyo_acl_head". | ||
609 | * (2) "pattern" is a pathname which is by default not permitted to modify | ||
610 | * already existing content. | ||
611 | */ | ||
612 | struct tomoyo_no_rewrite { | ||
613 | struct tomoyo_acl_head head; | ||
614 | const struct tomoyo_path_info *pattern; | ||
615 | }; | ||
616 | |||
617 | /* | ||
618 | * tomoyo_transition_control is a structure which is used for holding | 553 | * tomoyo_transition_control is a structure which is used for holding |
619 | * "initialize_domain"/"no_initialize_domain"/"keep_domain"/"no_keep_domain" | 554 | * "initialize_domain"/"no_initialize_domain"/"keep_domain"/"no_keep_domain" |
620 | * entries. | 555 | * entries. |
@@ -764,23 +699,17 @@ int tomoyo_write_aggregator(char *data, const bool is_delete); | |||
764 | int tomoyo_write_transition_control(char *data, const bool is_delete, | 699 | int tomoyo_write_transition_control(char *data, const bool is_delete, |
765 | const u8 type); | 700 | const u8 type); |
766 | /* | 701 | /* |
767 | * Create "allow_read/write", "allow_execute", "allow_read", "allow_write", | 702 | * Create "allow_execute", "allow_read", "allow_write", "allow_append", |
768 | * "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir", | 703 | * "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir", |
769 | * "allow_mkfifo", "allow_mksock", "allow_mkblock", "allow_mkchar", | 704 | * "allow_mkfifo", "allow_mksock", "allow_mkblock", "allow_mkchar", |
770 | * "allow_truncate", "allow_symlink", "allow_rewrite", "allow_rename" and | 705 | * "allow_truncate", "allow_symlink", "allow_rename" and "allow_link" entry |
771 | * "allow_link" entry in domain policy. | 706 | * in domain policy. |
772 | */ | 707 | */ |
773 | int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, | 708 | int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, |
774 | const bool is_delete); | 709 | const bool is_delete); |
775 | /* Create "allow_read" entry in exception policy. */ | ||
776 | int tomoyo_write_globally_readable(char *data, const bool is_delete); | ||
777 | /* Create "allow_mount" entry in domain policy. */ | 710 | /* Create "allow_mount" entry in domain policy. */ |
778 | int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain, | 711 | int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain, |
779 | const bool is_delete); | 712 | const bool is_delete); |
780 | /* Create "deny_rewrite" entry in exception policy. */ | ||
781 | int tomoyo_write_no_rewrite(char *data, const bool is_delete); | ||
782 | /* Create "file_pattern" entry in exception policy. */ | ||
783 | int tomoyo_write_pattern(char *data, const bool is_delete); | ||
784 | /* Create "path_group"/"number_group" entry in exception policy. */ | 713 | /* Create "path_group"/"number_group" entry in exception policy. */ |
785 | int tomoyo_write_group(char *data, const bool is_delete, const u8 type); | 714 | int tomoyo_write_group(char *data, const bool is_delete, const u8 type); |
786 | int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) | 715 | int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) |
@@ -819,8 +748,6 @@ char *tomoyo_realpath_nofollow(const char *pathname); | |||
819 | * ignores chroot'ed root and the pathname is already solved. | 748 | * ignores chroot'ed root and the pathname is already solved. |
820 | */ | 749 | */ |
821 | char *tomoyo_realpath_from_path(struct path *path); | 750 | char *tomoyo_realpath_from_path(struct path *path); |
822 | /* Get patterned pathname. */ | ||
823 | const char *tomoyo_pattern(const struct tomoyo_path_info *filename); | ||
824 | 751 | ||
825 | /* Check memory quota. */ | 752 | /* Check memory quota. */ |
826 | bool tomoyo_memory_ok(void *ptr); | 753 | bool tomoyo_memory_ok(void *ptr); |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 35388408e475..355b536262b1 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -510,17 +510,8 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
510 | if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10) | 510 | if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10) |
511 | goto done; | 511 | goto done; |
512 | domain = tomoyo_find_domain(tmp); | 512 | domain = tomoyo_find_domain(tmp); |
513 | if (domain) | 513 | if (!domain) |
514 | goto done; | 514 | domain = tomoyo_assign_domain(tmp, old_domain->profile); |
515 | if (is_enforce) { | ||
516 | int error = tomoyo_supervisor(&r, "# wants to create domain\n" | ||
517 | "%s\n", tmp); | ||
518 | if (error == TOMOYO_RETRY_REQUEST) | ||
519 | goto retry; | ||
520 | if (error < 0) | ||
521 | goto done; | ||
522 | } | ||
523 | domain = tomoyo_assign_domain(tmp, old_domain->profile); | ||
524 | done: | 515 | done: |
525 | if (domain) | 516 | if (domain) |
526 | goto out; | 517 | goto out; |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index d64e8ecb6fb3..41ed7de44ef1 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -11,15 +11,15 @@ | |||
11 | 11 | ||
12 | /* Keyword array for operations with one pathname. */ | 12 | /* Keyword array for operations with one pathname. */ |
13 | const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { | 13 | const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { |
14 | [TOMOYO_TYPE_READ_WRITE] = "read/write", | ||
15 | [TOMOYO_TYPE_EXECUTE] = "execute", | 14 | [TOMOYO_TYPE_EXECUTE] = "execute", |
16 | [TOMOYO_TYPE_READ] = "read", | 15 | [TOMOYO_TYPE_READ] = "read", |
17 | [TOMOYO_TYPE_WRITE] = "write", | 16 | [TOMOYO_TYPE_WRITE] = "write", |
17 | [TOMOYO_TYPE_APPEND] = "append", | ||
18 | [TOMOYO_TYPE_UNLINK] = "unlink", | 18 | [TOMOYO_TYPE_UNLINK] = "unlink", |
19 | [TOMOYO_TYPE_GETATTR] = "getattr", | ||
19 | [TOMOYO_TYPE_RMDIR] = "rmdir", | 20 | [TOMOYO_TYPE_RMDIR] = "rmdir", |
20 | [TOMOYO_TYPE_TRUNCATE] = "truncate", | 21 | [TOMOYO_TYPE_TRUNCATE] = "truncate", |
21 | [TOMOYO_TYPE_SYMLINK] = "symlink", | 22 | [TOMOYO_TYPE_SYMLINK] = "symlink", |
22 | [TOMOYO_TYPE_REWRITE] = "rewrite", | ||
23 | [TOMOYO_TYPE_CHROOT] = "chroot", | 23 | [TOMOYO_TYPE_CHROOT] = "chroot", |
24 | [TOMOYO_TYPE_UMOUNT] = "unmount", | 24 | [TOMOYO_TYPE_UMOUNT] = "unmount", |
25 | }; | 25 | }; |
@@ -50,15 +50,15 @@ const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { | 52 | static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { |
53 | [TOMOYO_TYPE_READ_WRITE] = TOMOYO_MAC_FILE_OPEN, | ||
54 | [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, | 53 | [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, |
55 | [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, | 54 | [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, |
56 | [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN, | 55 | [TOMOYO_TYPE_WRITE] = TOMOYO_MAC_FILE_OPEN, |
56 | [TOMOYO_TYPE_APPEND] = TOMOYO_MAC_FILE_OPEN, | ||
57 | [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK, | 57 | [TOMOYO_TYPE_UNLINK] = TOMOYO_MAC_FILE_UNLINK, |
58 | [TOMOYO_TYPE_GETATTR] = TOMOYO_MAC_FILE_GETATTR, | ||
58 | [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR, | 59 | [TOMOYO_TYPE_RMDIR] = TOMOYO_MAC_FILE_RMDIR, |
59 | [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE, | 60 | [TOMOYO_TYPE_TRUNCATE] = TOMOYO_MAC_FILE_TRUNCATE, |
60 | [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK, | 61 | [TOMOYO_TYPE_SYMLINK] = TOMOYO_MAC_FILE_SYMLINK, |
61 | [TOMOYO_TYPE_REWRITE] = TOMOYO_MAC_FILE_REWRITE, | ||
62 | [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT, | 62 | [TOMOYO_TYPE_CHROOT] = TOMOYO_MAC_FILE_CHROOT, |
63 | [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, | 63 | [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, |
64 | }; | 64 | }; |
@@ -132,24 +132,6 @@ static void tomoyo_add_slash(struct tomoyo_path_info *buf) | |||
132 | } | 132 | } |
133 | 133 | ||
134 | /** | 134 | /** |
135 | * tomoyo_strendswith - Check whether the token ends with the given token. | ||
136 | * | ||
137 | * @name: The token to check. | ||
138 | * @tail: The token to find. | ||
139 | * | ||
140 | * Returns true if @name ends with @tail, false otherwise. | ||
141 | */ | ||
142 | static bool tomoyo_strendswith(const char *name, const char *tail) | ||
143 | { | ||
144 | int len; | ||
145 | |||
146 | if (!name || !tail) | ||
147 | return false; | ||
148 | len = strlen(name) - strlen(tail); | ||
149 | return len >= 0 && !strcmp(name + len, tail); | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * tomoyo_get_realpath - Get realpath. | 135 | * tomoyo_get_realpath - Get realpath. |
154 | * | 136 | * |
155 | * @buf: Pointer to "struct tomoyo_path_info". | 137 | * @buf: Pointer to "struct tomoyo_path_info". |
@@ -182,7 +164,7 @@ static int tomoyo_audit_path_log(struct tomoyo_request_info *r) | |||
182 | return 0; | 164 | return 0; |
183 | tomoyo_warn_log(r, "%s %s", operation, filename->name); | 165 | tomoyo_warn_log(r, "%s %s", operation, filename->name); |
184 | return tomoyo_supervisor(r, "allow_%s %s\n", operation, | 166 | return tomoyo_supervisor(r, "allow_%s %s\n", operation, |
185 | tomoyo_pattern(filename)); | 167 | filename->name); |
186 | } | 168 | } |
187 | 169 | ||
188 | /** | 170 | /** |
@@ -202,8 +184,7 @@ static int tomoyo_audit_path2_log(struct tomoyo_request_info *r) | |||
202 | tomoyo_warn_log(r, "%s %s %s", operation, filename1->name, | 184 | tomoyo_warn_log(r, "%s %s %s", operation, filename1->name, |
203 | filename2->name); | 185 | filename2->name); |
204 | return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, | 186 | return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, |
205 | tomoyo_pattern(filename1), | 187 | filename1->name, filename2->name); |
206 | tomoyo_pattern(filename2)); | ||
207 | } | 188 | } |
208 | 189 | ||
209 | /** | 190 | /** |
@@ -225,7 +206,7 @@ static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r) | |||
225 | tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode, | 206 | tomoyo_warn_log(r, "%s %s 0%o %u %u", operation, filename->name, mode, |
226 | major, minor); | 207 | major, minor); |
227 | return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation, | 208 | return tomoyo_supervisor(r, "allow_%s %s 0%o %u %u\n", operation, |
228 | tomoyo_pattern(filename), mode, major, minor); | 209 | filename->name, mode, major, minor); |
229 | } | 210 | } |
230 | 211 | ||
231 | /** | 212 | /** |
@@ -264,247 +245,7 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) | |||
264 | radix); | 245 | radix); |
265 | tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer); | 246 | tomoyo_warn_log(r, "%s %s %s", operation, filename->name, buffer); |
266 | return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, | 247 | return tomoyo_supervisor(r, "allow_%s %s %s\n", operation, |
267 | tomoyo_pattern(filename), buffer); | 248 | filename->name, buffer); |
268 | } | ||
269 | |||
270 | static bool tomoyo_same_globally_readable(const struct tomoyo_acl_head *a, | ||
271 | const struct tomoyo_acl_head *b) | ||
272 | { | ||
273 | return container_of(a, struct tomoyo_readable_file, | ||
274 | head)->filename == | ||
275 | container_of(b, struct tomoyo_readable_file, | ||
276 | head)->filename; | ||
277 | } | ||
278 | |||
279 | /** | ||
280 | * tomoyo_update_globally_readable_entry - Update "struct tomoyo_readable_file" list. | ||
281 | * | ||
282 | * @filename: Filename unconditionally permitted to open() for reading. | ||
283 | * @is_delete: True if it is a delete request. | ||
284 | * | ||
285 | * Returns 0 on success, negative value otherwise. | ||
286 | * | ||
287 | * Caller holds tomoyo_read_lock(). | ||
288 | */ | ||
289 | static int tomoyo_update_globally_readable_entry(const char *filename, | ||
290 | const bool is_delete) | ||
291 | { | ||
292 | struct tomoyo_readable_file e = { }; | ||
293 | int error; | ||
294 | |||
295 | if (!tomoyo_correct_word(filename)) | ||
296 | return -EINVAL; | ||
297 | e.filename = tomoyo_get_name(filename); | ||
298 | if (!e.filename) | ||
299 | return -ENOMEM; | ||
300 | error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, | ||
301 | &tomoyo_policy_list | ||
302 | [TOMOYO_ID_GLOBALLY_READABLE], | ||
303 | tomoyo_same_globally_readable); | ||
304 | tomoyo_put_name(e.filename); | ||
305 | return error; | ||
306 | } | ||
307 | |||
308 | /** | ||
309 | * tomoyo_globally_readable_file - Check if the file is unconditionnaly permitted to be open()ed for reading. | ||
310 | * | ||
311 | * @filename: The filename to check. | ||
312 | * | ||
313 | * Returns true if any domain can open @filename for reading, false otherwise. | ||
314 | * | ||
315 | * Caller holds tomoyo_read_lock(). | ||
316 | */ | ||
317 | static bool tomoyo_globally_readable_file(const struct tomoyo_path_info * | ||
318 | filename) | ||
319 | { | ||
320 | struct tomoyo_readable_file *ptr; | ||
321 | bool found = false; | ||
322 | |||
323 | list_for_each_entry_rcu(ptr, &tomoyo_policy_list | ||
324 | [TOMOYO_ID_GLOBALLY_READABLE], head.list) { | ||
325 | if (!ptr->head.is_deleted && | ||
326 | tomoyo_path_matches_pattern(filename, ptr->filename)) { | ||
327 | found = true; | ||
328 | break; | ||
329 | } | ||
330 | } | ||
331 | return found; | ||
332 | } | ||
333 | |||
334 | /** | ||
335 | * tomoyo_write_globally_readable - Write "struct tomoyo_readable_file" list. | ||
336 | * | ||
337 | * @data: String to parse. | ||
338 | * @is_delete: True if it is a delete request. | ||
339 | * | ||
340 | * Returns 0 on success, negative value otherwise. | ||
341 | * | ||
342 | * Caller holds tomoyo_read_lock(). | ||
343 | */ | ||
344 | int tomoyo_write_globally_readable(char *data, const bool is_delete) | ||
345 | { | ||
346 | return tomoyo_update_globally_readable_entry(data, is_delete); | ||
347 | } | ||
348 | |||
349 | static bool tomoyo_same_pattern(const struct tomoyo_acl_head *a, | ||
350 | const struct tomoyo_acl_head *b) | ||
351 | { | ||
352 | return container_of(a, struct tomoyo_no_pattern, head)->pattern == | ||
353 | container_of(b, struct tomoyo_no_pattern, head)->pattern; | ||
354 | } | ||
355 | |||
356 | /** | ||
357 | * tomoyo_update_file_pattern_entry - Update "struct tomoyo_no_pattern" list. | ||
358 | * | ||
359 | * @pattern: Pathname pattern. | ||
360 | * @is_delete: True if it is a delete request. | ||
361 | * | ||
362 | * Returns 0 on success, negative value otherwise. | ||
363 | * | ||
364 | * Caller holds tomoyo_read_lock(). | ||
365 | */ | ||
366 | static int tomoyo_update_file_pattern_entry(const char *pattern, | ||
367 | const bool is_delete) | ||
368 | { | ||
369 | struct tomoyo_no_pattern e = { }; | ||
370 | int error; | ||
371 | |||
372 | if (!tomoyo_correct_word(pattern)) | ||
373 | return -EINVAL; | ||
374 | e.pattern = tomoyo_get_name(pattern); | ||
375 | if (!e.pattern) | ||
376 | return -ENOMEM; | ||
377 | error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, | ||
378 | &tomoyo_policy_list[TOMOYO_ID_PATTERN], | ||
379 | tomoyo_same_pattern); | ||
380 | tomoyo_put_name(e.pattern); | ||
381 | return error; | ||
382 | } | ||
383 | |||
384 | /** | ||
385 | * tomoyo_pattern - Get patterned pathname. | ||
386 | * | ||
387 | * @filename: The filename to find patterned pathname. | ||
388 | * | ||
389 | * Returns pointer to pathname pattern if matched, @filename otherwise. | ||
390 | * | ||
391 | * Caller holds tomoyo_read_lock(). | ||
392 | */ | ||
393 | const char *tomoyo_pattern(const struct tomoyo_path_info *filename) | ||
394 | { | ||
395 | struct tomoyo_no_pattern *ptr; | ||
396 | const struct tomoyo_path_info *pattern = NULL; | ||
397 | |||
398 | list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_PATTERN], | ||
399 | head.list) { | ||
400 | if (ptr->head.is_deleted) | ||
401 | continue; | ||
402 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) | ||
403 | continue; | ||
404 | pattern = ptr->pattern; | ||
405 | if (tomoyo_strendswith(pattern->name, "/\\*")) { | ||
406 | /* Do nothing. Try to find the better match. */ | ||
407 | } else { | ||
408 | /* This would be the better match. Use this. */ | ||
409 | break; | ||
410 | } | ||
411 | } | ||
412 | if (pattern) | ||
413 | filename = pattern; | ||
414 | return filename->name; | ||
415 | } | ||
416 | |||
417 | /** | ||
418 | * tomoyo_write_pattern - Write "struct tomoyo_no_pattern" list. | ||
419 | * | ||
420 | * @data: String to parse. | ||
421 | * @is_delete: True if it is a delete request. | ||
422 | * | ||
423 | * Returns 0 on success, negative value otherwise. | ||
424 | * | ||
425 | * Caller holds tomoyo_read_lock(). | ||
426 | */ | ||
427 | int tomoyo_write_pattern(char *data, const bool is_delete) | ||
428 | { | ||
429 | return tomoyo_update_file_pattern_entry(data, is_delete); | ||
430 | } | ||
431 | |||
432 | static bool tomoyo_same_no_rewrite(const struct tomoyo_acl_head *a, | ||
433 | const struct tomoyo_acl_head *b) | ||
434 | { | ||
435 | return container_of(a, struct tomoyo_no_rewrite, head)->pattern | ||
436 | == container_of(b, struct tomoyo_no_rewrite, head) | ||
437 | ->pattern; | ||
438 | } | ||
439 | |||
440 | /** | ||
441 | * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite" list. | ||
442 | * | ||
443 | * @pattern: Pathname pattern that are not rewritable by default. | ||
444 | * @is_delete: True if it is a delete request. | ||
445 | * | ||
446 | * Returns 0 on success, negative value otherwise. | ||
447 | * | ||
448 | * Caller holds tomoyo_read_lock(). | ||
449 | */ | ||
450 | static int tomoyo_update_no_rewrite_entry(const char *pattern, | ||
451 | const bool is_delete) | ||
452 | { | ||
453 | struct tomoyo_no_rewrite e = { }; | ||
454 | int error; | ||
455 | |||
456 | if (!tomoyo_correct_word(pattern)) | ||
457 | return -EINVAL; | ||
458 | e.pattern = tomoyo_get_name(pattern); | ||
459 | if (!e.pattern) | ||
460 | return -ENOMEM; | ||
461 | error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, | ||
462 | &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE], | ||
463 | tomoyo_same_no_rewrite); | ||
464 | tomoyo_put_name(e.pattern); | ||
465 | return error; | ||
466 | } | ||
467 | |||
468 | /** | ||
469 | * tomoyo_no_rewrite_file - Check if the given pathname is not permitted to be rewrited. | ||
470 | * | ||
471 | * @filename: Filename to check. | ||
472 | * | ||
473 | * Returns true if @filename is specified by "deny_rewrite" directive, | ||
474 | * false otherwise. | ||
475 | * | ||
476 | * Caller holds tomoyo_read_lock(). | ||
477 | */ | ||
478 | static bool tomoyo_no_rewrite_file(const struct tomoyo_path_info *filename) | ||
479 | { | ||
480 | struct tomoyo_no_rewrite *ptr; | ||
481 | bool found = false; | ||
482 | |||
483 | list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_NO_REWRITE], | ||
484 | head.list) { | ||
485 | if (ptr->head.is_deleted) | ||
486 | continue; | ||
487 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) | ||
488 | continue; | ||
489 | found = true; | ||
490 | break; | ||
491 | } | ||
492 | return found; | ||
493 | } | ||
494 | |||
495 | /** | ||
496 | * tomoyo_write_no_rewrite - Write "struct tomoyo_no_rewrite" list. | ||
497 | * | ||
498 | * @data: String to parse. | ||
499 | * @is_delete: True if it is a delete request. | ||
500 | * | ||
501 | * Returns 0 on success, negative value otherwise. | ||
502 | * | ||
503 | * Caller holds tomoyo_read_lock(). | ||
504 | */ | ||
505 | int tomoyo_write_no_rewrite(char *data, const bool is_delete) | ||
506 | { | ||
507 | return tomoyo_update_no_rewrite_entry(data, is_delete); | ||
508 | } | 249 | } |
509 | 250 | ||
510 | static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, | 251 | static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, |
@@ -569,6 +310,15 @@ static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, | |||
569 | tomoyo_same_name_union(&p1->name, &p2->name); | 310 | tomoyo_same_name_union(&p1->name, &p2->name); |
570 | } | 311 | } |
571 | 312 | ||
313 | /** | ||
314 | * tomoyo_merge_path_acl - Merge duplicated "struct tomoyo_path_acl" entry. | ||
315 | * | ||
316 | * @a: Pointer to "struct tomoyo_acl_info". | ||
317 | * @b: Pointer to "struct tomoyo_acl_info". | ||
318 | * @is_delete: True for @a &= ~@b, false for @a |= @b. | ||
319 | * | ||
320 | * Returns true if @a is empty, false otherwise. | ||
321 | */ | ||
572 | static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, | 322 | static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, |
573 | struct tomoyo_acl_info *b, | 323 | struct tomoyo_acl_info *b, |
574 | const bool is_delete) | 324 | const bool is_delete) |
@@ -577,19 +327,10 @@ static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a, | |||
577 | ->perm; | 327 | ->perm; |
578 | u16 perm = *a_perm; | 328 | u16 perm = *a_perm; |
579 | const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; | 329 | const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm; |
580 | if (is_delete) { | 330 | if (is_delete) |
581 | perm &= ~b_perm; | 331 | perm &= ~b_perm; |
582 | if ((perm & TOMOYO_RW_MASK) != TOMOYO_RW_MASK) | 332 | else |
583 | perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); | ||
584 | else if (!(perm & (1 << TOMOYO_TYPE_READ_WRITE))) | ||
585 | perm &= ~TOMOYO_RW_MASK; | ||
586 | } else { | ||
587 | perm |= b_perm; | 333 | perm |= b_perm; |
588 | if ((perm & TOMOYO_RW_MASK) == TOMOYO_RW_MASK) | ||
589 | perm |= (1 << TOMOYO_TYPE_READ_WRITE); | ||
590 | else if (perm & (1 << TOMOYO_TYPE_READ_WRITE)) | ||
591 | perm |= TOMOYO_RW_MASK; | ||
592 | } | ||
593 | *a_perm = perm; | 334 | *a_perm = perm; |
594 | return !perm; | 335 | return !perm; |
595 | } | 336 | } |
@@ -615,8 +356,6 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, | |||
615 | .perm = 1 << type | 356 | .perm = 1 << type |
616 | }; | 357 | }; |
617 | int error; | 358 | int error; |
618 | if (e.perm == (1 << TOMOYO_TYPE_READ_WRITE)) | ||
619 | e.perm |= TOMOYO_RW_MASK; | ||
620 | if (!tomoyo_parse_name_union(filename, &e.name)) | 359 | if (!tomoyo_parse_name_union(filename, &e.name)) |
621 | return -EINVAL; | 360 | return -EINVAL; |
622 | error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, | 361 | error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain, |
@@ -775,7 +514,6 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | |||
775 | { | 514 | { |
776 | int error; | 515 | int error; |
777 | 516 | ||
778 | next: | ||
779 | r->type = tomoyo_p2mac[operation]; | 517 | r->type = tomoyo_p2mac[operation]; |
780 | r->mode = tomoyo_get_mode(r->profile, r->type); | 518 | r->mode = tomoyo_get_mode(r->profile, r->type); |
781 | if (r->mode == TOMOYO_CONFIG_DISABLED) | 519 | if (r->mode == TOMOYO_CONFIG_DISABLED) |
@@ -785,10 +523,6 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | |||
785 | r->param.path.operation = operation; | 523 | r->param.path.operation = operation; |
786 | do { | 524 | do { |
787 | tomoyo_check_acl(r, tomoyo_check_path_acl); | 525 | tomoyo_check_acl(r, tomoyo_check_path_acl); |
788 | if (!r->granted && operation == TOMOYO_TYPE_READ && | ||
789 | !r->domain->ignore_global_allow_read && | ||
790 | tomoyo_globally_readable_file(filename)) | ||
791 | r->granted = true; | ||
792 | error = tomoyo_audit_path_log(r); | 526 | error = tomoyo_audit_path_log(r); |
793 | /* | 527 | /* |
794 | * Do not retry for execute request, for alias may have | 528 | * Do not retry for execute request, for alias may have |
@@ -796,16 +530,6 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, | |||
796 | */ | 530 | */ |
797 | } while (error == TOMOYO_RETRY_REQUEST && | 531 | } while (error == TOMOYO_RETRY_REQUEST && |
798 | operation != TOMOYO_TYPE_EXECUTE); | 532 | operation != TOMOYO_TYPE_EXECUTE); |
799 | /* | ||
800 | * Since "allow_truncate" doesn't imply "allow_rewrite" permission, | ||
801 | * we need to check "allow_rewrite" permission if the filename is | ||
802 | * specified by "deny_rewrite" keyword. | ||
803 | */ | ||
804 | if (!error && operation == TOMOYO_TYPE_TRUNCATE && | ||
805 | tomoyo_no_rewrite_file(filename)) { | ||
806 | operation = TOMOYO_TYPE_REWRITE; | ||
807 | goto next; | ||
808 | } | ||
809 | return error; | 533 | return error; |
810 | } | 534 | } |
811 | 535 | ||
@@ -932,43 +656,26 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
932 | struct tomoyo_request_info r; | 656 | struct tomoyo_request_info r; |
933 | int idx; | 657 | int idx; |
934 | 658 | ||
935 | if (!path->mnt || | 659 | if (!path->mnt) |
936 | (path->dentry->d_inode && S_ISDIR(path->dentry->d_inode->i_mode))) | ||
937 | return 0; | 660 | return 0; |
938 | buf.name = NULL; | 661 | buf.name = NULL; |
939 | r.mode = TOMOYO_CONFIG_DISABLED; | 662 | r.mode = TOMOYO_CONFIG_DISABLED; |
940 | idx = tomoyo_read_lock(); | 663 | idx = tomoyo_read_lock(); |
941 | /* | 664 | if (acc_mode && |
942 | * If the filename is specified by "deny_rewrite" keyword, | 665 | tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) |
943 | * we need to check "allow_rewrite" permission when the filename is not | ||
944 | * opened for append mode or the filename is truncated at open time. | ||
945 | */ | ||
946 | if ((acc_mode & MAY_WRITE) && !(flag & O_APPEND) | ||
947 | && tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_REWRITE) | ||
948 | != TOMOYO_CONFIG_DISABLED) { | 666 | != TOMOYO_CONFIG_DISABLED) { |
949 | if (!tomoyo_get_realpath(&buf, path)) { | 667 | if (!tomoyo_get_realpath(&buf, path)) { |
950 | error = -ENOMEM; | 668 | error = -ENOMEM; |
951 | goto out; | 669 | goto out; |
952 | } | 670 | } |
953 | if (tomoyo_no_rewrite_file(&buf)) | 671 | if (acc_mode & MAY_READ) |
954 | error = tomoyo_path_permission(&r, TOMOYO_TYPE_REWRITE, | 672 | error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ, |
673 | &buf); | ||
674 | if (!error && (acc_mode & MAY_WRITE)) | ||
675 | error = tomoyo_path_permission(&r, (flag & O_APPEND) ? | ||
676 | TOMOYO_TYPE_APPEND : | ||
677 | TOMOYO_TYPE_WRITE, | ||
955 | &buf); | 678 | &buf); |
956 | } | ||
957 | if (!error && acc_mode && | ||
958 | tomoyo_init_request_info(&r, domain, TOMOYO_MAC_FILE_OPEN) | ||
959 | != TOMOYO_CONFIG_DISABLED) { | ||
960 | u8 operation; | ||
961 | if (!buf.name && !tomoyo_get_realpath(&buf, path)) { | ||
962 | error = -ENOMEM; | ||
963 | goto out; | ||
964 | } | ||
965 | if (acc_mode == (MAY_READ | MAY_WRITE)) | ||
966 | operation = TOMOYO_TYPE_READ_WRITE; | ||
967 | else if (acc_mode == MAY_READ) | ||
968 | operation = TOMOYO_TYPE_READ; | ||
969 | else | ||
970 | operation = TOMOYO_TYPE_WRITE; | ||
971 | error = tomoyo_path_permission(&r, operation, &buf); | ||
972 | } | 679 | } |
973 | out: | 680 | out: |
974 | kfree(buf.name); | 681 | kfree(buf.name); |
@@ -979,7 +686,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
979 | } | 686 | } |
980 | 687 | ||
981 | /** | 688 | /** |
982 | * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "rewrite", "chroot" and "unmount". | 689 | * tomoyo_path_perm - Check permission for "unlink", "rmdir", "truncate", "symlink", "append", "chroot" and "unmount". |
983 | * | 690 | * |
984 | * @operation: Type of operation. | 691 | * @operation: Type of operation. |
985 | * @path: Pointer to "struct path". | 692 | * @path: Pointer to "struct path". |
@@ -988,9 +695,10 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
988 | */ | 695 | */ |
989 | int tomoyo_path_perm(const u8 operation, struct path *path) | 696 | int tomoyo_path_perm(const u8 operation, struct path *path) |
990 | { | 697 | { |
991 | int error = -ENOMEM; | ||
992 | struct tomoyo_path_info buf; | ||
993 | struct tomoyo_request_info r; | 698 | struct tomoyo_request_info r; |
699 | int error; | ||
700 | struct tomoyo_path_info buf; | ||
701 | bool is_enforce; | ||
994 | int idx; | 702 | int idx; |
995 | 703 | ||
996 | if (!path->mnt) | 704 | if (!path->mnt) |
@@ -998,17 +706,13 @@ int tomoyo_path_perm(const u8 operation, struct path *path) | |||
998 | if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) | 706 | if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation]) |
999 | == TOMOYO_CONFIG_DISABLED) | 707 | == TOMOYO_CONFIG_DISABLED) |
1000 | return 0; | 708 | return 0; |
709 | is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING); | ||
710 | error = -ENOMEM; | ||
1001 | buf.name = NULL; | 711 | buf.name = NULL; |
1002 | idx = tomoyo_read_lock(); | 712 | idx = tomoyo_read_lock(); |
1003 | if (!tomoyo_get_realpath(&buf, path)) | 713 | if (!tomoyo_get_realpath(&buf, path)) |
1004 | goto out; | 714 | goto out; |
1005 | switch (operation) { | 715 | switch (operation) { |
1006 | case TOMOYO_TYPE_REWRITE: | ||
1007 | if (!tomoyo_no_rewrite_file(&buf)) { | ||
1008 | error = 0; | ||
1009 | goto out; | ||
1010 | } | ||
1011 | break; | ||
1012 | case TOMOYO_TYPE_RMDIR: | 716 | case TOMOYO_TYPE_RMDIR: |
1013 | case TOMOYO_TYPE_CHROOT: | 717 | case TOMOYO_TYPE_CHROOT: |
1014 | tomoyo_add_slash(&buf); | 718 | tomoyo_add_slash(&buf); |
@@ -1018,7 +722,7 @@ int tomoyo_path_perm(const u8 operation, struct path *path) | |||
1018 | out: | 722 | out: |
1019 | kfree(buf.name); | 723 | kfree(buf.name); |
1020 | tomoyo_read_unlock(idx); | 724 | tomoyo_read_unlock(idx); |
1021 | if (r.mode != TOMOYO_CONFIG_ENFORCING) | 725 | if (!is_enforce) |
1022 | error = 0; | 726 | error = 0; |
1023 | return error; | 727 | return error; |
1024 | } | 728 | } |
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index a877e4c3b101..ba799b49ee3a 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c | |||
@@ -32,27 +32,6 @@ static bool tomoyo_add_to_gc(const int type, struct list_head *element) | |||
32 | return true; | 32 | return true; |
33 | } | 33 | } |
34 | 34 | ||
35 | static void tomoyo_del_allow_read(struct list_head *element) | ||
36 | { | ||
37 | struct tomoyo_readable_file *ptr = | ||
38 | container_of(element, typeof(*ptr), head.list); | ||
39 | tomoyo_put_name(ptr->filename); | ||
40 | } | ||
41 | |||
42 | static void tomoyo_del_file_pattern(struct list_head *element) | ||
43 | { | ||
44 | struct tomoyo_no_pattern *ptr = | ||
45 | container_of(element, typeof(*ptr), head.list); | ||
46 | tomoyo_put_name(ptr->pattern); | ||
47 | } | ||
48 | |||
49 | static void tomoyo_del_no_rewrite(struct list_head *element) | ||
50 | { | ||
51 | struct tomoyo_no_rewrite *ptr = | ||
52 | container_of(element, typeof(*ptr), head.list); | ||
53 | tomoyo_put_name(ptr->pattern); | ||
54 | } | ||
55 | |||
56 | static void tomoyo_del_transition_control(struct list_head *element) | 35 | static void tomoyo_del_transition_control(struct list_head *element) |
57 | { | 36 | { |
58 | struct tomoyo_transition_control *ptr = | 37 | struct tomoyo_transition_control *ptr = |
@@ -290,15 +269,6 @@ static void tomoyo_kfree_entry(void) | |||
290 | case TOMOYO_ID_AGGREGATOR: | 269 | case TOMOYO_ID_AGGREGATOR: |
291 | tomoyo_del_aggregator(element); | 270 | tomoyo_del_aggregator(element); |
292 | break; | 271 | break; |
293 | case TOMOYO_ID_GLOBALLY_READABLE: | ||
294 | tomoyo_del_allow_read(element); | ||
295 | break; | ||
296 | case TOMOYO_ID_PATTERN: | ||
297 | tomoyo_del_file_pattern(element); | ||
298 | break; | ||
299 | case TOMOYO_ID_NO_REWRITE: | ||
300 | tomoyo_del_no_rewrite(element); | ||
301 | break; | ||
302 | case TOMOYO_ID_MANAGER: | 272 | case TOMOYO_ID_MANAGER: |
303 | tomoyo_del_manager(element); | 273 | tomoyo_del_manager(element); |
304 | break; | 274 | break; |
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 162a864dba24..f1d9e1a9eff4 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c | |||
@@ -55,9 +55,8 @@ static int tomoyo_audit_mount_log(struct tomoyo_request_info *r) | |||
55 | flags); | 55 | flags); |
56 | return tomoyo_supervisor(r, | 56 | return tomoyo_supervisor(r, |
57 | TOMOYO_KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n", | 57 | TOMOYO_KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n", |
58 | tomoyo_pattern(r->param.mount.dev), | 58 | r->param.mount.dev->name, |
59 | tomoyo_pattern(r->param.mount.dir), type, | 59 | r->param.mount.dir->name, type, flags); |
60 | flags); | ||
61 | } | 60 | } |
62 | 61 | ||
63 | static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r, | 62 | static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r, |
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 95d3f9572237..2615c7d43960 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
@@ -93,6 +93,12 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) | |||
93 | return tomoyo_check_open_permission(domain, &bprm->file->f_path, O_RDONLY); | 93 | return tomoyo_check_open_permission(domain, &bprm->file->f_path, O_RDONLY); |
94 | } | 94 | } |
95 | 95 | ||
96 | static int tomoyo_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | ||
97 | { | ||
98 | struct path path = { mnt, dentry }; | ||
99 | return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, &path); | ||
100 | } | ||
101 | |||
96 | static int tomoyo_path_truncate(struct path *path) | 102 | static int tomoyo_path_truncate(struct path *path) |
97 | { | 103 | { |
98 | return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path); | 104 | return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path); |
@@ -176,9 +182,10 @@ static int tomoyo_path_rename(struct path *old_parent, | |||
176 | static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, | 182 | static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, |
177 | unsigned long arg) | 183 | unsigned long arg) |
178 | { | 184 | { |
179 | if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) | 185 | if (!(cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))) |
180 | return tomoyo_path_perm(TOMOYO_TYPE_REWRITE, &file->f_path); | 186 | return 0; |
181 | return 0; | 187 | return tomoyo_check_open_permission(tomoyo_domain(), &file->f_path, |
188 | O_WRONLY | (arg & O_APPEND)); | ||
182 | } | 189 | } |
183 | 190 | ||
184 | static int tomoyo_dentry_open(struct file *f, const struct cred *cred) | 191 | static int tomoyo_dentry_open(struct file *f, const struct cred *cred) |
@@ -258,6 +265,7 @@ static struct security_operations tomoyo_security_ops = { | |||
258 | .path_mknod = tomoyo_path_mknod, | 265 | .path_mknod = tomoyo_path_mknod, |
259 | .path_link = tomoyo_path_link, | 266 | .path_link = tomoyo_path_link, |
260 | .path_rename = tomoyo_path_rename, | 267 | .path_rename = tomoyo_path_rename, |
268 | .inode_getattr = tomoyo_inode_getattr, | ||
261 | .file_ioctl = tomoyo_file_ioctl, | 269 | .file_ioctl = tomoyo_file_ioctl, |
262 | .path_chmod = tomoyo_path_chmod, | 270 | .path_chmod = tomoyo_path_chmod, |
263 | .path_chown = tomoyo_path_chown, | 271 | .path_chown = tomoyo_path_chown, |
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 6d5393204d95..7fb9bbf7021a 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c | |||
@@ -911,44 +911,33 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r) | |||
911 | if (!domain) | 911 | if (!domain) |
912 | return true; | 912 | return true; |
913 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { | 913 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
914 | u16 perm; | ||
915 | u8 i; | ||
914 | if (ptr->is_deleted) | 916 | if (ptr->is_deleted) |
915 | continue; | 917 | continue; |
916 | switch (ptr->type) { | 918 | switch (ptr->type) { |
917 | u16 perm; | ||
918 | u8 i; | ||
919 | case TOMOYO_TYPE_PATH_ACL: | 919 | case TOMOYO_TYPE_PATH_ACL: |
920 | perm = container_of(ptr, struct tomoyo_path_acl, head) | 920 | perm = container_of(ptr, struct tomoyo_path_acl, head) |
921 | ->perm; | 921 | ->perm; |
922 | for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++) | ||
923 | if (perm & (1 << i)) | ||
924 | count++; | ||
925 | if (perm & (1 << TOMOYO_TYPE_READ_WRITE)) | ||
926 | count -= 2; | ||
927 | break; | 922 | break; |
928 | case TOMOYO_TYPE_PATH2_ACL: | 923 | case TOMOYO_TYPE_PATH2_ACL: |
929 | perm = container_of(ptr, struct tomoyo_path2_acl, head) | 924 | perm = container_of(ptr, struct tomoyo_path2_acl, head) |
930 | ->perm; | 925 | ->perm; |
931 | for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++) | ||
932 | if (perm & (1 << i)) | ||
933 | count++; | ||
934 | break; | 926 | break; |
935 | case TOMOYO_TYPE_PATH_NUMBER_ACL: | 927 | case TOMOYO_TYPE_PATH_NUMBER_ACL: |
936 | perm = container_of(ptr, struct tomoyo_path_number_acl, | 928 | perm = container_of(ptr, struct tomoyo_path_number_acl, |
937 | head)->perm; | 929 | head)->perm; |
938 | for (i = 0; i < TOMOYO_MAX_PATH_NUMBER_OPERATION; i++) | ||
939 | if (perm & (1 << i)) | ||
940 | count++; | ||
941 | break; | 930 | break; |
942 | case TOMOYO_TYPE_MKDEV_ACL: | 931 | case TOMOYO_TYPE_MKDEV_ACL: |
943 | perm = container_of(ptr, struct tomoyo_mkdev_acl, | 932 | perm = container_of(ptr, struct tomoyo_mkdev_acl, |
944 | head)->perm; | 933 | head)->perm; |
945 | for (i = 0; i < TOMOYO_MAX_MKDEV_OPERATION; i++) | ||
946 | if (perm & (1 << i)) | ||
947 | count++; | ||
948 | break; | 934 | break; |
949 | default: | 935 | default: |
950 | count++; | 936 | perm = 1; |
951 | } | 937 | } |
938 | for (i = 0; i < 16; i++) | ||
939 | if (perm & (1 << i)) | ||
940 | count++; | ||
952 | } | 941 | } |
953 | if (count < tomoyo_profile(domain->profile)->learning-> | 942 | if (count < tomoyo_profile(domain->profile)->learning-> |
954 | learning_max_entry) | 943 | learning_max_entry) |