domain.c revision a230f9e7121cbcbfe23bd5a630abf6b53cece555
1/* 2 * security/tomoyo/domain.c 3 * 4 * Domain transition functions for TOMOYO. 5 * 6 * Copyright (C) 2005-2010 NTT DATA CORPORATION 7 */ 8 9#include "common.h" 10#include <linux/binfmts.h> 11#include <linux/slab.h> 12 13/* Variables definitions.*/ 14 15/* The initial domain. */ 16struct tomoyo_domain_info tomoyo_kernel_domain; 17 18/** 19 * tomoyo_update_policy - Update an entry for exception policy. 20 * 21 * @new_entry: Pointer to "struct tomoyo_acl_info". 22 * @size: Size of @new_entry in bytes. 23 * @is_delete: True if it is a delete request. 24 * @list: Pointer to "struct list_head". 25 * @check_duplicate: Callback function to find duplicated entry. 26 * 27 * Returns 0 on success, negative value otherwise. 28 * 29 * Caller holds tomoyo_read_lock(). 30 */ 31int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, 32 bool is_delete, struct list_head *list, 33 bool (*check_duplicate) (const struct tomoyo_acl_head 34 *, 35 const struct tomoyo_acl_head 36 *)) 37{ 38 int error = is_delete ? -ENOENT : -ENOMEM; 39 struct tomoyo_acl_head *entry; 40 41 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 42 return -ENOMEM; 43 list_for_each_entry_rcu(entry, list, list) { 44 if (!check_duplicate(entry, new_entry)) 45 continue; 46 entry->is_deleted = is_delete; 47 error = 0; 48 break; 49 } 50 if (error && !is_delete) { 51 entry = tomoyo_commit_ok(new_entry, size); 52 if (entry) { 53 list_add_tail_rcu(&entry->list, list); 54 error = 0; 55 } 56 } 57 mutex_unlock(&tomoyo_policy_lock); 58 return error; 59} 60 61/** 62 * tomoyo_update_domain - Update an entry for domain policy. 63 * 64 * @new_entry: Pointer to "struct tomoyo_acl_info". 65 * @size: Size of @new_entry in bytes. 66 * @is_delete: True if it is a delete request. 67 * @domain: Pointer to "struct tomoyo_domain_info". 68 * @check_duplicate: Callback function to find duplicated entry. 69 * @merge_duplicate: Callback function to merge duplicated entry. 70 * 71 * Returns 0 on success, negative value otherwise. 72 * 73 * Caller holds tomoyo_read_lock(). 74 */ 75int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, 76 bool is_delete, struct tomoyo_domain_info *domain, 77 bool (*check_duplicate) (const struct tomoyo_acl_info 78 *, 79 const struct tomoyo_acl_info 80 *), 81 bool (*merge_duplicate) (struct tomoyo_acl_info *, 82 struct tomoyo_acl_info *, 83 const bool)) 84{ 85 int error = is_delete ? -ENOENT : -ENOMEM; 86 struct tomoyo_acl_info *entry; 87 88 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 89 return error; 90 list_for_each_entry_rcu(entry, &domain->acl_info_list, list) { 91 if (!check_duplicate(entry, new_entry)) 92 continue; 93 if (merge_duplicate) 94 entry->is_deleted = merge_duplicate(entry, new_entry, 95 is_delete); 96 else 97 entry->is_deleted = is_delete; 98 error = 0; 99 break; 100 } 101 if (error && !is_delete) { 102 entry = tomoyo_commit_ok(new_entry, size); 103 if (entry) { 104 list_add_tail_rcu(&entry->list, &domain->acl_info_list); 105 error = 0; 106 } 107 } 108 mutex_unlock(&tomoyo_policy_lock); 109 return error; 110} 111 112void tomoyo_check_acl(struct tomoyo_request_info *r, 113 bool (*check_entry) (const struct tomoyo_request_info *, 114 const struct tomoyo_acl_info *)) 115{ 116 const struct tomoyo_domain_info *domain = r->domain; 117 struct tomoyo_acl_info *ptr; 118 119 list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { 120 if (ptr->is_deleted || ptr->type != r->param_type) 121 continue; 122 if (check_entry(r, ptr)) { 123 r->granted = true; 124 return; 125 } 126 } 127 r->granted = false; 128} 129 130/* The list for "struct tomoyo_domain_info". */ 131LIST_HEAD(tomoyo_domain_list); 132 133struct list_head tomoyo_policy_list[TOMOYO_MAX_POLICY]; 134struct list_head tomoyo_group_list[TOMOYO_MAX_GROUP]; 135 136/** 137 * tomoyo_get_last_name - Get last component of a domainname. 138 * 139 * @domain: Pointer to "struct tomoyo_domain_info". 140 * 141 * Returns the last component of the domainname. 142 */ 143const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain) 144{ 145 const char *cp0 = domain->domainname->name; 146 const char *cp1 = strrchr(cp0, ' '); 147 148 if (cp1) 149 return cp1 + 1; 150 return cp0; 151} 152 153static bool tomoyo_same_domain_initializer_entry(const struct tomoyo_acl_head * 154 a, 155 const struct tomoyo_acl_head * 156 b) 157{ 158 const struct tomoyo_domain_initializer_entry *p1 = 159 container_of(a, typeof(*p1), head); 160 const struct tomoyo_domain_initializer_entry *p2 = 161 container_of(b, typeof(*p2), head); 162 return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name 163 && p1->domainname == p2->domainname 164 && p1->program == p2->program; 165} 166 167/** 168 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. 169 * 170 * @domainname: The name of domain. May be NULL. 171 * @program: The name of program. 172 * @is_not: True if it is "no_initialize_domain" entry. 173 * @is_delete: True if it is a delete request. 174 * 175 * Returns 0 on success, negative value otherwise. 176 * 177 * Caller holds tomoyo_read_lock(). 178 */ 179static int tomoyo_update_domain_initializer_entry(const char *domainname, 180 const char *program, 181 const bool is_not, 182 const bool is_delete) 183{ 184 struct tomoyo_domain_initializer_entry e = { .is_not = is_not }; 185 int error = is_delete ? -ENOENT : -ENOMEM; 186 187 if (!tomoyo_correct_path(program)) 188 return -EINVAL; 189 if (domainname) { 190 if (!tomoyo_domain_def(domainname) && 191 tomoyo_correct_path(domainname)) 192 e.is_last_name = true; 193 else if (!tomoyo_correct_domain(domainname)) 194 return -EINVAL; 195 e.domainname = tomoyo_get_name(domainname); 196 if (!e.domainname) 197 goto out; 198 } 199 e.program = tomoyo_get_name(program); 200 if (!e.program) 201 goto out; 202 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 203 &tomoyo_policy_list 204 [TOMOYO_ID_DOMAIN_INITIALIZER], 205 tomoyo_same_domain_initializer_entry); 206 out: 207 tomoyo_put_name(e.domainname); 208 tomoyo_put_name(e.program); 209 return error; 210} 211 212/** 213 * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list. 214 * 215 * @head: Pointer to "struct tomoyo_io_buffer". 216 * 217 * Returns true on success, false otherwise. 218 * 219 * Caller holds tomoyo_read_lock(). 220 */ 221bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) 222{ 223 struct list_head *pos; 224 bool done = true; 225 226 list_for_each_cookie(pos, head->read_var2, &tomoyo_policy_list 227 [TOMOYO_ID_DOMAIN_INITIALIZER]) { 228 const char *no; 229 const char *from = ""; 230 const char *domain = ""; 231 struct tomoyo_domain_initializer_entry *ptr; 232 ptr = list_entry(pos, struct tomoyo_domain_initializer_entry, 233 head.list); 234 if (ptr->head.is_deleted) 235 continue; 236 no = ptr->is_not ? "no_" : ""; 237 if (ptr->domainname) { 238 from = " from "; 239 domain = ptr->domainname->name; 240 } 241 done = tomoyo_io_printf(head, 242 "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN 243 "%s%s%s\n", no, ptr->program->name, 244 from, domain); 245 if (!done) 246 break; 247 } 248 return done; 249} 250 251/** 252 * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list. 253 * 254 * @data: String to parse. 255 * @is_not: True if it is "no_initialize_domain" entry. 256 * @is_delete: True if it is a delete request. 257 * 258 * Returns 0 on success, negative value otherwise. 259 * 260 * Caller holds tomoyo_read_lock(). 261 */ 262int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, 263 const bool is_delete) 264{ 265 char *cp = strstr(data, " from "); 266 267 if (cp) { 268 *cp = '\0'; 269 return tomoyo_update_domain_initializer_entry(cp + 6, data, 270 is_not, 271 is_delete); 272 } 273 return tomoyo_update_domain_initializer_entry(NULL, data, is_not, 274 is_delete); 275} 276 277/** 278 * tomoyo_domain_initializer - Check whether the given program causes domainname reinitialization. 279 * 280 * @domainname: The name of domain. 281 * @program: The name of program. 282 * @last_name: The last component of @domainname. 283 * 284 * Returns true if executing @program reinitializes domain transition, 285 * false otherwise. 286 * 287 * Caller holds tomoyo_read_lock(). 288 */ 289static bool tomoyo_domain_initializer(const struct tomoyo_path_info * 290 domainname, 291 const struct tomoyo_path_info *program, 292 const struct tomoyo_path_info * 293 last_name) 294{ 295 struct tomoyo_domain_initializer_entry *ptr; 296 bool flag = false; 297 298 list_for_each_entry_rcu(ptr, &tomoyo_policy_list 299 [TOMOYO_ID_DOMAIN_INITIALIZER], head.list) { 300 if (ptr->head.is_deleted) 301 continue; 302 if (ptr->domainname) { 303 if (!ptr->is_last_name) { 304 if (ptr->domainname != domainname) 305 continue; 306 } else { 307 if (tomoyo_pathcmp(ptr->domainname, last_name)) 308 continue; 309 } 310 } 311 if (tomoyo_pathcmp(ptr->program, program)) 312 continue; 313 if (ptr->is_not) { 314 flag = false; 315 break; 316 } 317 flag = true; 318 } 319 return flag; 320} 321 322static bool tomoyo_same_domain_keeper_entry(const struct tomoyo_acl_head *a, 323 const struct tomoyo_acl_head *b) 324{ 325 const struct tomoyo_domain_keeper_entry *p1 = 326 container_of(a, typeof(*p1), head); 327 const struct tomoyo_domain_keeper_entry *p2 = 328 container_of(b, typeof(*p2), head); 329 return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name 330 && p1->domainname == p2->domainname 331 && p1->program == p2->program; 332} 333 334/** 335 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. 336 * 337 * @domainname: The name of domain. 338 * @program: The name of program. May be NULL. 339 * @is_not: True if it is "no_keep_domain" entry. 340 * @is_delete: True if it is a delete request. 341 * 342 * Returns 0 on success, negative value otherwise. 343 * 344 * Caller holds tomoyo_read_lock(). 345 */ 346static int tomoyo_update_domain_keeper_entry(const char *domainname, 347 const char *program, 348 const bool is_not, 349 const bool is_delete) 350{ 351 struct tomoyo_domain_keeper_entry e = { .is_not = is_not }; 352 int error = is_delete ? -ENOENT : -ENOMEM; 353 354 if (!tomoyo_domain_def(domainname) && 355 tomoyo_correct_path(domainname)) 356 e.is_last_name = true; 357 else if (!tomoyo_correct_domain(domainname)) 358 return -EINVAL; 359 if (program) { 360 if (!tomoyo_correct_path(program)) 361 return -EINVAL; 362 e.program = tomoyo_get_name(program); 363 if (!e.program) 364 goto out; 365 } 366 e.domainname = tomoyo_get_name(domainname); 367 if (!e.domainname) 368 goto out; 369 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 370 &tomoyo_policy_list 371 [TOMOYO_ID_DOMAIN_KEEPER], 372 tomoyo_same_domain_keeper_entry); 373 out: 374 tomoyo_put_name(e.domainname); 375 tomoyo_put_name(e.program); 376 return error; 377} 378 379/** 380 * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list. 381 * 382 * @data: String to parse. 383 * @is_not: True if it is "no_keep_domain" entry. 384 * @is_delete: True if it is a delete request. 385 * 386 * Caller holds tomoyo_read_lock(). 387 */ 388int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, 389 const bool is_delete) 390{ 391 char *cp = strstr(data, " from "); 392 393 if (cp) { 394 *cp = '\0'; 395 return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not, 396 is_delete); 397 } 398 return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete); 399} 400 401/** 402 * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list. 403 * 404 * @head: Pointer to "struct tomoyo_io_buffer". 405 * 406 * Returns true on success, false otherwise. 407 * 408 * Caller holds tomoyo_read_lock(). 409 */ 410bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) 411{ 412 struct list_head *pos; 413 bool done = true; 414 415 list_for_each_cookie(pos, head->read_var2, 416 &tomoyo_policy_list[TOMOYO_ID_DOMAIN_KEEPER]) { 417 struct tomoyo_domain_keeper_entry *ptr; 418 const char *no; 419 const char *from = ""; 420 const char *program = ""; 421 422 ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, 423 head.list); 424 if (ptr->head.is_deleted) 425 continue; 426 no = ptr->is_not ? "no_" : ""; 427 if (ptr->program) { 428 from = " from "; 429 program = ptr->program->name; 430 } 431 done = tomoyo_io_printf(head, 432 "%s" TOMOYO_KEYWORD_KEEP_DOMAIN 433 "%s%s%s\n", no, program, from, 434 ptr->domainname->name); 435 if (!done) 436 break; 437 } 438 return done; 439} 440 441/** 442 * tomoyo_domain_keeper - Check whether the given program causes domain transition suppression. 443 * 444 * @domainname: The name of domain. 445 * @program: The name of program. 446 * @last_name: The last component of @domainname. 447 * 448 * Returns true if executing @program supresses domain transition, 449 * false otherwise. 450 * 451 * Caller holds tomoyo_read_lock(). 452 */ 453static bool tomoyo_domain_keeper(const struct tomoyo_path_info *domainname, 454 const struct tomoyo_path_info *program, 455 const struct tomoyo_path_info *last_name) 456{ 457 struct tomoyo_domain_keeper_entry *ptr; 458 bool flag = false; 459 460 list_for_each_entry_rcu(ptr, 461 &tomoyo_policy_list[TOMOYO_ID_DOMAIN_KEEPER], 462 head.list) { 463 if (ptr->head.is_deleted) 464 continue; 465 if (!ptr->is_last_name) { 466 if (ptr->domainname != domainname) 467 continue; 468 } else { 469 if (tomoyo_pathcmp(ptr->domainname, last_name)) 470 continue; 471 } 472 if (ptr->program && tomoyo_pathcmp(ptr->program, program)) 473 continue; 474 if (ptr->is_not) { 475 flag = false; 476 break; 477 } 478 flag = true; 479 } 480 return flag; 481} 482 483static bool tomoyo_same_aggregator_entry(const struct tomoyo_acl_head *a, 484 const struct tomoyo_acl_head *b) 485{ 486 const struct tomoyo_aggregator_entry *p1 = container_of(a, typeof(*p1), 487 head); 488 const struct tomoyo_aggregator_entry *p2 = container_of(b, typeof(*p2), 489 head); 490 return p1->original_name == p2->original_name && 491 p1->aggregated_name == p2->aggregated_name; 492} 493 494/** 495 * tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator_entry" list. 496 * 497 * @original_name: The original program's name. 498 * @aggregated_name: The program name to use. 499 * @is_delete: True if it is a delete request. 500 * 501 * Returns 0 on success, negative value otherwise. 502 * 503 * Caller holds tomoyo_read_lock(). 504 */ 505static int tomoyo_update_aggregator_entry(const char *original_name, 506 const char *aggregated_name, 507 const bool is_delete) 508{ 509 struct tomoyo_aggregator_entry e = { }; 510 int error = is_delete ? -ENOENT : -ENOMEM; 511 512 if (!tomoyo_correct_path(original_name) || 513 !tomoyo_correct_path(aggregated_name)) 514 return -EINVAL; 515 e.original_name = tomoyo_get_name(original_name); 516 e.aggregated_name = tomoyo_get_name(aggregated_name); 517 if (!e.original_name || !e.aggregated_name || 518 e.aggregated_name->is_patterned) /* No patterns allowed. */ 519 goto out; 520 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 521 &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR], 522 tomoyo_same_aggregator_entry); 523 out: 524 tomoyo_put_name(e.original_name); 525 tomoyo_put_name(e.aggregated_name); 526 return error; 527} 528 529/** 530 * tomoyo_read_aggregator_policy - Read "struct tomoyo_aggregator_entry" list. 531 * 532 * @head: Pointer to "struct tomoyo_io_buffer". 533 * 534 * Returns true on success, false otherwise. 535 * 536 * Caller holds tomoyo_read_lock(). 537 */ 538bool tomoyo_read_aggregator_policy(struct tomoyo_io_buffer *head) 539{ 540 struct list_head *pos; 541 bool done = true; 542 543 list_for_each_cookie(pos, head->read_var2, 544 &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR]) { 545 struct tomoyo_aggregator_entry *ptr; 546 547 ptr = list_entry(pos, struct tomoyo_aggregator_entry, 548 head.list); 549 if (ptr->head.is_deleted) 550 continue; 551 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_AGGREGATOR 552 "%s %s\n", ptr->original_name->name, 553 ptr->aggregated_name->name); 554 if (!done) 555 break; 556 } 557 return done; 558} 559 560/** 561 * tomoyo_write_aggregator_policy - Write "struct tomoyo_aggregator_entry" list. 562 * 563 * @data: String to parse. 564 * @is_delete: True if it is a delete request. 565 * 566 * Returns 0 on success, negative value otherwise. 567 * 568 * Caller holds tomoyo_read_lock(). 569 */ 570int tomoyo_write_aggregator_policy(char *data, const bool is_delete) 571{ 572 char *cp = strchr(data, ' '); 573 574 if (!cp) 575 return -EINVAL; 576 *cp++ = '\0'; 577 return tomoyo_update_aggregator_entry(data, cp, is_delete); 578} 579 580static bool tomoyo_same_alias_entry(const struct tomoyo_acl_head *a, 581 const struct tomoyo_acl_head *b) 582{ 583 const struct tomoyo_alias_entry *p1 = container_of(a, typeof(*p1), 584 head); 585 const struct tomoyo_alias_entry *p2 = container_of(b, typeof(*p2), 586 head); 587 return p1->original_name == p2->original_name && 588 p1->aliased_name == p2->aliased_name; 589} 590 591/** 592 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. 593 * 594 * @original_name: The original program's real name. 595 * @aliased_name: The symbolic program's symbolic link's name. 596 * @is_delete: True if it is a delete request. 597 * 598 * Returns 0 on success, negative value otherwise. 599 * 600 * Caller holds tomoyo_read_lock(). 601 */ 602static int tomoyo_update_alias_entry(const char *original_name, 603 const char *aliased_name, 604 const bool is_delete) 605{ 606 struct tomoyo_alias_entry e = { }; 607 int error = is_delete ? -ENOENT : -ENOMEM; 608 609 if (!tomoyo_correct_path(original_name) || 610 !tomoyo_correct_path(aliased_name)) 611 return -EINVAL; 612 e.original_name = tomoyo_get_name(original_name); 613 e.aliased_name = tomoyo_get_name(aliased_name); 614 if (!e.original_name || !e.aliased_name || 615 e.original_name->is_patterned || e.aliased_name->is_patterned) 616 goto out; /* No patterns allowed. */ 617 error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, 618 &tomoyo_policy_list[TOMOYO_ID_ALIAS], 619 tomoyo_same_alias_entry); 620 out: 621 tomoyo_put_name(e.original_name); 622 tomoyo_put_name(e.aliased_name); 623 return error; 624} 625 626/** 627 * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list. 628 * 629 * @head: Pointer to "struct tomoyo_io_buffer". 630 * 631 * Returns true on success, false otherwise. 632 * 633 * Caller holds tomoyo_read_lock(). 634 */ 635bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) 636{ 637 struct list_head *pos; 638 bool done = true; 639 640 list_for_each_cookie(pos, head->read_var2, 641 &tomoyo_policy_list[TOMOYO_ID_ALIAS]) { 642 struct tomoyo_alias_entry *ptr; 643 644 ptr = list_entry(pos, struct tomoyo_alias_entry, head.list); 645 if (ptr->head.is_deleted) 646 continue; 647 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n", 648 ptr->original_name->name, 649 ptr->aliased_name->name); 650 if (!done) 651 break; 652 } 653 return done; 654} 655 656/** 657 * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list. 658 * 659 * @data: String to parse. 660 * @is_delete: True if it is a delete request. 661 * 662 * Returns 0 on success, negative value otherwise. 663 * 664 * Caller holds tomoyo_read_lock(). 665 */ 666int tomoyo_write_alias_policy(char *data, const bool is_delete) 667{ 668 char *cp = strchr(data, ' '); 669 670 if (!cp) 671 return -EINVAL; 672 *cp++ = '\0'; 673 return tomoyo_update_alias_entry(data, cp, is_delete); 674} 675 676/** 677 * tomoyo_find_or_assign_new_domain - Create a domain. 678 * 679 * @domainname: The name of domain. 680 * @profile: Profile number to assign if the domain was newly created. 681 * 682 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. 683 * 684 * Caller holds tomoyo_read_lock(). 685 */ 686struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 687 domainname, 688 const u8 profile) 689{ 690 struct tomoyo_domain_info *entry; 691 struct tomoyo_domain_info *domain = NULL; 692 const struct tomoyo_path_info *saved_domainname; 693 bool found = false; 694 695 if (!tomoyo_correct_domain(domainname)) 696 return NULL; 697 saved_domainname = tomoyo_get_name(domainname); 698 if (!saved_domainname) 699 return NULL; 700 entry = kzalloc(sizeof(*entry), GFP_NOFS); 701 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 702 goto out; 703 list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { 704 if (domain->is_deleted || 705 tomoyo_pathcmp(saved_domainname, domain->domainname)) 706 continue; 707 found = true; 708 break; 709 } 710 if (!found && tomoyo_memory_ok(entry)) { 711 INIT_LIST_HEAD(&entry->acl_info_list); 712 entry->domainname = saved_domainname; 713 saved_domainname = NULL; 714 entry->profile = profile; 715 list_add_tail_rcu(&entry->list, &tomoyo_domain_list); 716 domain = entry; 717 entry = NULL; 718 found = true; 719 } 720 mutex_unlock(&tomoyo_policy_lock); 721 out: 722 tomoyo_put_name(saved_domainname); 723 kfree(entry); 724 return found ? domain : NULL; 725} 726 727/** 728 * tomoyo_find_next_domain - Find a domain. 729 * 730 * @bprm: Pointer to "struct linux_binprm". 731 * 732 * Returns 0 on success, negative value otherwise. 733 * 734 * Caller holds tomoyo_read_lock(). 735 */ 736int tomoyo_find_next_domain(struct linux_binprm *bprm) 737{ 738 struct tomoyo_request_info r; 739 char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); 740 struct tomoyo_domain_info *old_domain = tomoyo_domain(); 741 struct tomoyo_domain_info *domain = NULL; 742 const char *old_domain_name = old_domain->domainname->name; 743 const char *original_name = bprm->filename; 744 u8 mode; 745 bool is_enforce; 746 int retval = -ENOMEM; 747 bool need_kfree = false; 748 struct tomoyo_path_info rn = { }; /* real name */ 749 struct tomoyo_path_info sn = { }; /* symlink name */ 750 struct tomoyo_path_info ln; /* last name */ 751 752 ln.name = tomoyo_get_last_name(old_domain); 753 tomoyo_fill_path_info(&ln); 754 mode = tomoyo_init_request_info(&r, NULL, TOMOYO_MAC_FILE_EXECUTE); 755 is_enforce = (mode == TOMOYO_CONFIG_ENFORCING); 756 if (!tmp) 757 goto out; 758 759 retry: 760 if (need_kfree) { 761 kfree(rn.name); 762 need_kfree = false; 763 } 764 /* Get tomoyo_realpath of program. */ 765 retval = -ENOENT; 766 rn.name = tomoyo_realpath(original_name); 767 if (!rn.name) 768 goto out; 769 tomoyo_fill_path_info(&rn); 770 need_kfree = true; 771 772 /* Get tomoyo_realpath of symbolic link. */ 773 sn.name = tomoyo_realpath_nofollow(original_name); 774 if (!sn.name) 775 goto out; 776 tomoyo_fill_path_info(&sn); 777 778 /* Check 'alias' directive. */ 779 if (tomoyo_pathcmp(&rn, &sn)) { 780 struct tomoyo_alias_entry *ptr; 781 /* Is this program allowed to be called via symbolic links? */ 782 list_for_each_entry_rcu(ptr, 783 &tomoyo_policy_list[TOMOYO_ID_ALIAS], 784 head.list) { 785 if (ptr->head.is_deleted || 786 tomoyo_pathcmp(&rn, ptr->original_name) || 787 tomoyo_pathcmp(&sn, ptr->aliased_name)) 788 continue; 789 kfree(rn.name); 790 need_kfree = false; 791 /* This is OK because it is read only. */ 792 rn = *ptr->aliased_name; 793 break; 794 } 795 } 796 797 /* Check 'aggregator' directive. */ 798 { 799 struct tomoyo_aggregator_entry *ptr; 800 list_for_each_entry_rcu(ptr, &tomoyo_policy_list 801 [TOMOYO_ID_AGGREGATOR], head.list) { 802 if (ptr->head.is_deleted || 803 !tomoyo_path_matches_pattern(&rn, 804 ptr->original_name)) 805 continue; 806 if (need_kfree) 807 kfree(rn.name); 808 need_kfree = false; 809 /* This is OK because it is read only. */ 810 rn = *ptr->aggregated_name; 811 break; 812 } 813 } 814 815 /* Check execute permission. */ 816 retval = tomoyo_path_permission(&r, TOMOYO_TYPE_EXECUTE, &rn); 817 if (retval == TOMOYO_RETRY_REQUEST) 818 goto retry; 819 if (retval < 0) 820 goto out; 821 822 if (tomoyo_domain_initializer(old_domain->domainname, &rn, &ln)) { 823 /* Transit to the child of tomoyo_kernel_domain domain. */ 824 snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, 825 TOMOYO_ROOT_NAME " " "%s", rn.name); 826 } else if (old_domain == &tomoyo_kernel_domain && 827 !tomoyo_policy_loaded) { 828 /* 829 * Needn't to transit from kernel domain before starting 830 * /sbin/init. But transit from kernel domain if executing 831 * initializers because they might start before /sbin/init. 832 */ 833 domain = old_domain; 834 } else if (tomoyo_domain_keeper(old_domain->domainname, &rn, &ln)) { 835 /* Keep current domain. */ 836 domain = old_domain; 837 } else { 838 /* Normal domain transition. */ 839 snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, 840 "%s %s", old_domain_name, rn.name); 841 } 842 if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10) 843 goto done; 844 domain = tomoyo_find_domain(tmp); 845 if (domain) 846 goto done; 847 if (is_enforce) { 848 int error = tomoyo_supervisor(&r, "# wants to create domain\n" 849 "%s\n", tmp); 850 if (error == TOMOYO_RETRY_REQUEST) 851 goto retry; 852 if (error < 0) 853 goto done; 854 } 855 domain = tomoyo_find_or_assign_new_domain(tmp, old_domain->profile); 856 done: 857 if (domain) 858 goto out; 859 printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", tmp); 860 if (is_enforce) 861 retval = -EPERM; 862 else 863 old_domain->transition_failed = true; 864 out: 865 if (!domain) 866 domain = old_domain; 867 /* Update reference count on "struct tomoyo_domain_info". */ 868 atomic_inc(&domain->users); 869 bprm->cred->security = domain; 870 if (need_kfree) 871 kfree(rn.name); 872 kfree(sn.name); 873 kfree(tmp); 874 return retval; 875} 876