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