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