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