domain.c revision 8e2d39a1665e680c095545993aac2fcac6916eb9
1/* 2 * security/tomoyo/domain.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#include <linux/binfmts.h> 16 17/* Variables definitions.*/ 18 19/* The initial domain. */ 20struct tomoyo_domain_info tomoyo_kernel_domain; 21 22/* 23 * tomoyo_domain_list is used for holding list of domains. 24 * The ->acl_info_list of "struct tomoyo_domain_info" is used for holding 25 * permissions (e.g. "allow_read /lib/libc-2.5.so") given to each domain. 26 * 27 * An entry is added by 28 * 29 * # ( echo "<kernel>"; echo "allow_execute /sbin/init" ) > \ 30 * /sys/kernel/security/tomoyo/domain_policy 31 * 32 * and is deleted by 33 * 34 * # ( echo "<kernel>"; echo "delete allow_execute /sbin/init" ) > \ 35 * /sys/kernel/security/tomoyo/domain_policy 36 * 37 * and all entries are retrieved by 38 * 39 * # cat /sys/kernel/security/tomoyo/domain_policy 40 * 41 * A domain is added by 42 * 43 * # echo "<kernel>" > /sys/kernel/security/tomoyo/domain_policy 44 * 45 * and is deleted by 46 * 47 * # echo "delete <kernel>" > /sys/kernel/security/tomoyo/domain_policy 48 * 49 * and all domains are retrieved by 50 * 51 * # grep '^<kernel>' /sys/kernel/security/tomoyo/domain_policy 52 * 53 * Normally, a domainname is monotonically getting longer because a domainname 54 * which the process will belong to if an execve() operation succeeds is 55 * defined as a concatenation of "current domainname" + "pathname passed to 56 * execve()". 57 * See tomoyo_domain_initializer_list and tomoyo_domain_keeper_list for 58 * exceptions. 59 */ 60LIST_HEAD(tomoyo_domain_list); 61 62/* 63 * tomoyo_domain_initializer_entry is a structure which is used for holding 64 * "initialize_domain" and "no_initialize_domain" entries. 65 * It has following fields. 66 * 67 * (1) "list" which is linked to tomoyo_domain_initializer_list . 68 * (2) "domainname" which is "a domainname" or "the last component of a 69 * domainname". This field is NULL if "from" clause is not specified. 70 * (3) "program" which is a program's pathname. 71 * (4) "is_deleted" is a bool which is true if marked as deleted, false 72 * otherwise. 73 * (5) "is_not" is a bool which is true if "no_initialize_domain", false 74 * otherwise. 75 * (6) "is_last_name" is a bool which is true if "domainname" is "the last 76 * component of a domainname", false otherwise. 77 */ 78struct tomoyo_domain_initializer_entry { 79 struct list_head list; 80 const struct tomoyo_path_info *domainname; /* This may be NULL */ 81 const struct tomoyo_path_info *program; 82 bool is_deleted; 83 bool is_not; /* True if this entry is "no_initialize_domain". */ 84 /* True if the domainname is tomoyo_get_last_name(). */ 85 bool is_last_name; 86}; 87 88/* 89 * tomoyo_domain_keeper_entry is a structure which is used for holding 90 * "keep_domain" and "no_keep_domain" entries. 91 * It has following fields. 92 * 93 * (1) "list" which is linked to tomoyo_domain_keeper_list . 94 * (2) "domainname" which is "a domainname" or "the last component of a 95 * domainname". 96 * (3) "program" which is a program's pathname. 97 * This field is NULL if "from" clause is not specified. 98 * (4) "is_deleted" is a bool which is true if marked as deleted, false 99 * otherwise. 100 * (5) "is_not" is a bool which is true if "no_initialize_domain", false 101 * otherwise. 102 * (6) "is_last_name" is a bool which is true if "domainname" is "the last 103 * component of a domainname", false otherwise. 104 */ 105struct tomoyo_domain_keeper_entry { 106 struct list_head list; 107 const struct tomoyo_path_info *domainname; 108 const struct tomoyo_path_info *program; /* This may be NULL */ 109 bool is_deleted; 110 bool is_not; /* True if this entry is "no_keep_domain". */ 111 /* True if the domainname is tomoyo_get_last_name(). */ 112 bool is_last_name; 113}; 114 115/* 116 * tomoyo_alias_entry is a structure which is used for holding "alias" entries. 117 * It has following fields. 118 * 119 * (1) "list" which is linked to tomoyo_alias_list . 120 * (2) "original_name" which is a dereferenced pathname. 121 * (3) "aliased_name" which is a symlink's pathname. 122 * (4) "is_deleted" is a bool which is true if marked as deleted, false 123 * otherwise. 124 */ 125struct tomoyo_alias_entry { 126 struct list_head list; 127 const struct tomoyo_path_info *original_name; 128 const struct tomoyo_path_info *aliased_name; 129 bool is_deleted; 130}; 131 132/** 133 * tomoyo_set_domain_flag - Set or clear domain's attribute flags. 134 * 135 * @domain: Pointer to "struct tomoyo_domain_info". 136 * @is_delete: True if it is a delete request. 137 * @flags: Flags to set or clear. 138 * 139 * Returns nothing. 140 */ 141void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain, 142 const bool is_delete, const u8 flags) 143{ 144 /* We need to serialize because this is bitfield operation. */ 145 static DEFINE_SPINLOCK(lock); 146 spin_lock(&lock); 147 if (!is_delete) 148 domain->flags |= flags; 149 else 150 domain->flags &= ~flags; 151 spin_unlock(&lock); 152} 153 154/** 155 * tomoyo_get_last_name - Get last component of a domainname. 156 * 157 * @domain: Pointer to "struct tomoyo_domain_info". 158 * 159 * Returns the last component of the domainname. 160 */ 161const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain) 162{ 163 const char *cp0 = domain->domainname->name; 164 const char *cp1 = strrchr(cp0, ' '); 165 166 if (cp1) 167 return cp1 + 1; 168 return cp0; 169} 170 171/* 172 * tomoyo_domain_initializer_list is used for holding list of programs which 173 * triggers reinitialization of domainname. Normally, a domainname is 174 * monotonically getting longer. But sometimes, we restart daemon programs. 175 * It would be convenient for us that "a daemon started upon system boot" and 176 * "the daemon restarted from console" belong to the same domain. Thus, TOMOYO 177 * provides a way to shorten domainnames. 178 * 179 * An entry is added by 180 * 181 * # echo 'initialize_domain /usr/sbin/httpd' > \ 182 * /sys/kernel/security/tomoyo/exception_policy 183 * 184 * and is deleted by 185 * 186 * # echo 'delete initialize_domain /usr/sbin/httpd' > \ 187 * /sys/kernel/security/tomoyo/exception_policy 188 * 189 * and all entries are retrieved by 190 * 191 * # grep ^initialize_domain /sys/kernel/security/tomoyo/exception_policy 192 * 193 * In the example above, /usr/sbin/httpd will belong to 194 * "<kernel> /usr/sbin/httpd" domain. 195 * 196 * You may specify a domainname using "from" keyword. 197 * "initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd" 198 * will cause "/usr/sbin/httpd" executed from "<kernel> /etc/rc.d/init.d/httpd" 199 * domain to belong to "<kernel> /usr/sbin/httpd" domain. 200 * 201 * You may add "no_" prefix to "initialize_domain". 202 * "initialize_domain /usr/sbin/httpd" and 203 * "no_initialize_domain /usr/sbin/httpd from <kernel> /etc/rc.d/init.d/httpd" 204 * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain 205 * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain. 206 */ 207static LIST_HEAD(tomoyo_domain_initializer_list); 208 209/** 210 * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. 211 * 212 * @domainname: The name of domain. May be NULL. 213 * @program: The name of program. 214 * @is_not: True if it is "no_initialize_domain" entry. 215 * @is_delete: True if it is a delete request. 216 * 217 * Returns 0 on success, negative value otherwise. 218 * 219 * Caller holds tomoyo_read_lock(). 220 */ 221static int tomoyo_update_domain_initializer_entry(const char *domainname, 222 const char *program, 223 const bool is_not, 224 const bool is_delete) 225{ 226 struct tomoyo_domain_initializer_entry *new_entry; 227 struct tomoyo_domain_initializer_entry *ptr; 228 const struct tomoyo_path_info *saved_program; 229 const struct tomoyo_path_info *saved_domainname = NULL; 230 int error = -ENOMEM; 231 bool is_last_name = false; 232 233 if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) 234 return -EINVAL; /* No patterns allowed. */ 235 if (domainname) { 236 if (!tomoyo_is_domain_def(domainname) && 237 tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) 238 is_last_name = true; 239 else if (!tomoyo_is_correct_domain(domainname, __func__)) 240 return -EINVAL; 241 saved_domainname = tomoyo_save_name(domainname); 242 if (!saved_domainname) 243 return -ENOMEM; 244 } 245 saved_program = tomoyo_save_name(program); 246 if (!saved_program) 247 return -ENOMEM; 248 new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); 249 mutex_lock(&tomoyo_policy_lock); 250 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { 251 if (ptr->is_not != is_not || 252 ptr->domainname != saved_domainname || 253 ptr->program != saved_program) 254 continue; 255 ptr->is_deleted = is_delete; 256 error = 0; 257 goto out; 258 } 259 if (is_delete) { 260 error = -ENOENT; 261 goto out; 262 } 263 if (!tomoyo_memory_ok(new_entry)) 264 goto out; 265 new_entry->domainname = saved_domainname; 266 new_entry->program = saved_program; 267 new_entry->is_not = is_not; 268 new_entry->is_last_name = is_last_name; 269 list_add_tail_rcu(&new_entry->list, &tomoyo_domain_initializer_list); 270 new_entry = NULL; 271 error = 0; 272 out: 273 mutex_unlock(&tomoyo_policy_lock); 274 kfree(new_entry); 275 return error; 276} 277 278/** 279 * tomoyo_read_domain_initializer_policy - Read "struct tomoyo_domain_initializer_entry" list. 280 * 281 * @head: Pointer to "struct tomoyo_io_buffer". 282 * 283 * Returns true on success, false otherwise. 284 * 285 * Caller holds tomoyo_read_lock(). 286 */ 287bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) 288{ 289 struct list_head *pos; 290 bool done = true; 291 292 list_for_each_cookie(pos, head->read_var2, 293 &tomoyo_domain_initializer_list) { 294 const char *no; 295 const char *from = ""; 296 const char *domain = ""; 297 struct tomoyo_domain_initializer_entry *ptr; 298 ptr = list_entry(pos, struct tomoyo_domain_initializer_entry, 299 list); 300 if (ptr->is_deleted) 301 continue; 302 no = ptr->is_not ? "no_" : ""; 303 if (ptr->domainname) { 304 from = " from "; 305 domain = ptr->domainname->name; 306 } 307 done = tomoyo_io_printf(head, 308 "%s" TOMOYO_KEYWORD_INITIALIZE_DOMAIN 309 "%s%s%s\n", no, ptr->program->name, 310 from, domain); 311 if (!done) 312 break; 313 } 314 return done; 315} 316 317/** 318 * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list. 319 * 320 * @data: String to parse. 321 * @is_not: True if it is "no_initialize_domain" entry. 322 * @is_delete: True if it is a delete request. 323 * 324 * Returns 0 on success, negative value otherwise. 325 * 326 * Caller holds tomoyo_read_lock(). 327 */ 328int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, 329 const bool is_delete) 330{ 331 char *cp = strstr(data, " from "); 332 333 if (cp) { 334 *cp = '\0'; 335 return tomoyo_update_domain_initializer_entry(cp + 6, data, 336 is_not, 337 is_delete); 338 } 339 return tomoyo_update_domain_initializer_entry(NULL, data, is_not, 340 is_delete); 341} 342 343/** 344 * tomoyo_is_domain_initializer - Check whether the given program causes domainname reinitialization. 345 * 346 * @domainname: The name of domain. 347 * @program: The name of program. 348 * @last_name: The last component of @domainname. 349 * 350 * Returns true if executing @program reinitializes domain transition, 351 * false otherwise. 352 * 353 * Caller holds tomoyo_read_lock(). 354 */ 355static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * 356 domainname, 357 const struct tomoyo_path_info *program, 358 const struct tomoyo_path_info * 359 last_name) 360{ 361 struct tomoyo_domain_initializer_entry *ptr; 362 bool flag = false; 363 364 list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { 365 if (ptr->is_deleted) 366 continue; 367 if (ptr->domainname) { 368 if (!ptr->is_last_name) { 369 if (ptr->domainname != domainname) 370 continue; 371 } else { 372 if (tomoyo_pathcmp(ptr->domainname, last_name)) 373 continue; 374 } 375 } 376 if (tomoyo_pathcmp(ptr->program, program)) 377 continue; 378 if (ptr->is_not) { 379 flag = false; 380 break; 381 } 382 flag = true; 383 } 384 return flag; 385} 386 387/* 388 * tomoyo_domain_keeper_list is used for holding list of domainnames which 389 * suppresses domain transition. Normally, a domainname is monotonically 390 * getting longer. But sometimes, we want to suppress domain transition. 391 * It would be convenient for us that programs executed from a login session 392 * belong to the same domain. Thus, TOMOYO provides a way to suppress domain 393 * transition. 394 * 395 * An entry is added by 396 * 397 * # echo 'keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \ 398 * /sys/kernel/security/tomoyo/exception_policy 399 * 400 * and is deleted by 401 * 402 * # echo 'delete keep_domain <kernel> /usr/sbin/sshd /bin/bash' > \ 403 * /sys/kernel/security/tomoyo/exception_policy 404 * 405 * and all entries are retrieved by 406 * 407 * # grep ^keep_domain /sys/kernel/security/tomoyo/exception_policy 408 * 409 * In the example above, any process which belongs to 410 * "<kernel> /usr/sbin/sshd /bin/bash" domain will remain in that domain, 411 * unless explicitly specified by "initialize_domain" or "no_keep_domain". 412 * 413 * You may specify a program using "from" keyword. 414 * "keep_domain /bin/pwd from <kernel> /usr/sbin/sshd /bin/bash" 415 * will cause "/bin/pwd" executed from "<kernel> /usr/sbin/sshd /bin/bash" 416 * domain to remain in "<kernel> /usr/sbin/sshd /bin/bash" domain. 417 * 418 * You may add "no_" prefix to "keep_domain". 419 * "keep_domain <kernel> /usr/sbin/sshd /bin/bash" and 420 * "no_keep_domain /usr/bin/passwd from <kernel> /usr/sbin/sshd /bin/bash" will 421 * cause "/usr/bin/passwd" to belong to 422 * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless 423 * explicitly specified by "initialize_domain". 424 */ 425static LIST_HEAD(tomoyo_domain_keeper_list); 426 427/** 428 * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. 429 * 430 * @domainname: The name of domain. 431 * @program: The name of program. May be NULL. 432 * @is_not: True if it is "no_keep_domain" entry. 433 * @is_delete: True if it is a delete request. 434 * 435 * Returns 0 on success, negative value otherwise. 436 * 437 * Caller holds tomoyo_read_lock(). 438 */ 439static int tomoyo_update_domain_keeper_entry(const char *domainname, 440 const char *program, 441 const bool is_not, 442 const bool is_delete) 443{ 444 struct tomoyo_domain_keeper_entry *new_entry; 445 struct tomoyo_domain_keeper_entry *ptr; 446 const struct tomoyo_path_info *saved_domainname; 447 const struct tomoyo_path_info *saved_program = NULL; 448 int error = -ENOMEM; 449 bool is_last_name = false; 450 451 if (!tomoyo_is_domain_def(domainname) && 452 tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) 453 is_last_name = true; 454 else if (!tomoyo_is_correct_domain(domainname, __func__)) 455 return -EINVAL; 456 if (program) { 457 if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) 458 return -EINVAL; 459 saved_program = tomoyo_save_name(program); 460 if (!saved_program) 461 return -ENOMEM; 462 } 463 saved_domainname = tomoyo_save_name(domainname); 464 if (!saved_domainname) 465 return -ENOMEM; 466 new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); 467 mutex_lock(&tomoyo_policy_lock); 468 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { 469 if (ptr->is_not != is_not || 470 ptr->domainname != saved_domainname || 471 ptr->program != saved_program) 472 continue; 473 ptr->is_deleted = is_delete; 474 error = 0; 475 goto out; 476 } 477 if (is_delete) { 478 error = -ENOENT; 479 goto out; 480 } 481 if (!tomoyo_memory_ok(new_entry)) 482 goto out; 483 new_entry->domainname = saved_domainname; 484 new_entry->program = saved_program; 485 new_entry->is_not = is_not; 486 new_entry->is_last_name = is_last_name; 487 list_add_tail_rcu(&new_entry->list, &tomoyo_domain_keeper_list); 488 new_entry = NULL; 489 error = 0; 490 out: 491 mutex_unlock(&tomoyo_policy_lock); 492 kfree(new_entry); 493 return error; 494} 495 496/** 497 * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list. 498 * 499 * @data: String to parse. 500 * @is_not: True if it is "no_keep_domain" entry. 501 * @is_delete: True if it is a delete request. 502 * 503 * Caller holds tomoyo_read_lock(). 504 */ 505int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, 506 const bool is_delete) 507{ 508 char *cp = strstr(data, " from "); 509 510 if (cp) { 511 *cp = '\0'; 512 return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not, 513 is_delete); 514 } 515 return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete); 516} 517 518/** 519 * tomoyo_read_domain_keeper_policy - Read "struct tomoyo_domain_keeper_entry" list. 520 * 521 * @head: Pointer to "struct tomoyo_io_buffer". 522 * 523 * Returns true on success, false otherwise. 524 * 525 * Caller holds tomoyo_read_lock(). 526 */ 527bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) 528{ 529 struct list_head *pos; 530 bool done = true; 531 532 list_for_each_cookie(pos, head->read_var2, 533 &tomoyo_domain_keeper_list) { 534 struct tomoyo_domain_keeper_entry *ptr; 535 const char *no; 536 const char *from = ""; 537 const char *program = ""; 538 539 ptr = list_entry(pos, struct tomoyo_domain_keeper_entry, list); 540 if (ptr->is_deleted) 541 continue; 542 no = ptr->is_not ? "no_" : ""; 543 if (ptr->program) { 544 from = " from "; 545 program = ptr->program->name; 546 } 547 done = tomoyo_io_printf(head, 548 "%s" TOMOYO_KEYWORD_KEEP_DOMAIN 549 "%s%s%s\n", no, program, from, 550 ptr->domainname->name); 551 if (!done) 552 break; 553 } 554 return done; 555} 556 557/** 558 * tomoyo_is_domain_keeper - Check whether the given program causes domain transition suppression. 559 * 560 * @domainname: The name of domain. 561 * @program: The name of program. 562 * @last_name: The last component of @domainname. 563 * 564 * Returns true if executing @program supresses domain transition, 565 * false otherwise. 566 * 567 * Caller holds tomoyo_read_lock(). 568 */ 569static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, 570 const struct tomoyo_path_info *program, 571 const struct tomoyo_path_info *last_name) 572{ 573 struct tomoyo_domain_keeper_entry *ptr; 574 bool flag = false; 575 576 list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { 577 if (ptr->is_deleted) 578 continue; 579 if (!ptr->is_last_name) { 580 if (ptr->domainname != domainname) 581 continue; 582 } else { 583 if (tomoyo_pathcmp(ptr->domainname, last_name)) 584 continue; 585 } 586 if (ptr->program && tomoyo_pathcmp(ptr->program, program)) 587 continue; 588 if (ptr->is_not) { 589 flag = false; 590 break; 591 } 592 flag = true; 593 } 594 return flag; 595} 596 597/* 598 * tomoyo_alias_list is used for holding list of symlink's pathnames which are 599 * allowed to be passed to an execve() request. Normally, the domainname which 600 * the current process will belong to after execve() succeeds is calculated 601 * using dereferenced pathnames. But some programs behave differently depending 602 * on the name passed to argv[0]. For busybox, calculating domainname using 603 * dereferenced pathnames will cause all programs in the busybox to belong to 604 * the same domain. Thus, TOMOYO provides a way to allow use of symlink's 605 * pathname for checking execve()'s permission and calculating domainname which 606 * the current process will belong to after execve() succeeds. 607 * 608 * An entry is added by 609 * 610 * # echo 'alias /bin/busybox /bin/cat' > \ 611 * /sys/kernel/security/tomoyo/exception_policy 612 * 613 * and is deleted by 614 * 615 * # echo 'delete alias /bin/busybox /bin/cat' > \ 616 * /sys/kernel/security/tomoyo/exception_policy 617 * 618 * and all entries are retrieved by 619 * 620 * # grep ^alias /sys/kernel/security/tomoyo/exception_policy 621 * 622 * In the example above, if /bin/cat is a symlink to /bin/busybox and execution 623 * of /bin/cat is requested, permission is checked for /bin/cat rather than 624 * /bin/busybox and domainname which the current process will belong to after 625 * execve() succeeds is calculated using /bin/cat rather than /bin/busybox . 626 */ 627static LIST_HEAD(tomoyo_alias_list); 628 629/** 630 * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. 631 * 632 * @original_name: The original program's real name. 633 * @aliased_name: The symbolic program's symbolic link's name. 634 * @is_delete: True if it is a delete request. 635 * 636 * Returns 0 on success, negative value otherwise. 637 * 638 * Caller holds tomoyo_read_lock(). 639 */ 640static int tomoyo_update_alias_entry(const char *original_name, 641 const char *aliased_name, 642 const bool is_delete) 643{ 644 struct tomoyo_alias_entry *new_entry; 645 struct tomoyo_alias_entry *ptr; 646 const struct tomoyo_path_info *saved_original_name; 647 const struct tomoyo_path_info *saved_aliased_name; 648 int error = -ENOMEM; 649 650 if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || 651 !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) 652 return -EINVAL; /* No patterns allowed. */ 653 saved_original_name = tomoyo_save_name(original_name); 654 saved_aliased_name = tomoyo_save_name(aliased_name); 655 if (!saved_original_name || !saved_aliased_name) 656 return -ENOMEM; 657 new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL); 658 mutex_lock(&tomoyo_policy_lock); 659 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { 660 if (ptr->original_name != saved_original_name || 661 ptr->aliased_name != saved_aliased_name) 662 continue; 663 ptr->is_deleted = is_delete; 664 error = 0; 665 goto out; 666 } 667 if (is_delete) { 668 error = -ENOENT; 669 goto out; 670 } 671 if (!tomoyo_memory_ok(new_entry)) 672 goto out; 673 new_entry->original_name = saved_original_name; 674 new_entry->aliased_name = saved_aliased_name; 675 list_add_tail_rcu(&new_entry->list, &tomoyo_alias_list); 676 new_entry = NULL; 677 error = 0; 678 out: 679 mutex_unlock(&tomoyo_policy_lock); 680 kfree(new_entry); 681 return error; 682} 683 684/** 685 * tomoyo_read_alias_policy - Read "struct tomoyo_alias_entry" list. 686 * 687 * @head: Pointer to "struct tomoyo_io_buffer". 688 * 689 * Returns true on success, false otherwise. 690 * 691 * Caller holds tomoyo_read_lock(). 692 */ 693bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) 694{ 695 struct list_head *pos; 696 bool done = true; 697 698 list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { 699 struct tomoyo_alias_entry *ptr; 700 701 ptr = list_entry(pos, struct tomoyo_alias_entry, list); 702 if (ptr->is_deleted) 703 continue; 704 done = tomoyo_io_printf(head, TOMOYO_KEYWORD_ALIAS "%s %s\n", 705 ptr->original_name->name, 706 ptr->aliased_name->name); 707 if (!done) 708 break; 709 } 710 return done; 711} 712 713/** 714 * tomoyo_write_alias_policy - Write "struct tomoyo_alias_entry" list. 715 * 716 * @data: String to parse. 717 * @is_delete: True if it is a delete request. 718 * 719 * Returns 0 on success, negative value otherwise. 720 * 721 * Caller holds tomoyo_read_lock(). 722 */ 723int tomoyo_write_alias_policy(char *data, const bool is_delete) 724{ 725 char *cp = strchr(data, ' '); 726 727 if (!cp) 728 return -EINVAL; 729 *cp++ = '\0'; 730 return tomoyo_update_alias_entry(data, cp, is_delete); 731} 732 733/** 734 * tomoyo_find_or_assign_new_domain - Create a domain. 735 * 736 * @domainname: The name of domain. 737 * @profile: Profile number to assign if the domain was newly created. 738 * 739 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. 740 * 741 * Caller holds tomoyo_read_lock(). 742 */ 743struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * 744 domainname, 745 const u8 profile) 746{ 747 struct tomoyo_domain_info *domain; 748 const struct tomoyo_path_info *saved_domainname; 749 750 mutex_lock(&tomoyo_policy_lock); 751 domain = tomoyo_find_domain(domainname); 752 if (domain) 753 goto out; 754 if (!tomoyo_is_correct_domain(domainname, __func__)) 755 goto out; 756 saved_domainname = tomoyo_save_name(domainname); 757 if (!saved_domainname) 758 goto out; 759 domain = kmalloc(sizeof(*domain), GFP_KERNEL); 760 if (tomoyo_memory_ok(domain)) { 761 INIT_LIST_HEAD(&domain->acl_info_list); 762 domain->domainname = saved_domainname; 763 domain->profile = profile; 764 list_add_tail_rcu(&domain->list, &tomoyo_domain_list); 765 } else { 766 kfree(domain); 767 domain = NULL; 768 } 769 770 out: 771 mutex_unlock(&tomoyo_policy_lock); 772 return domain; 773} 774 775/** 776 * tomoyo_find_next_domain - Find a domain. 777 * 778 * @bprm: Pointer to "struct linux_binprm". 779 * 780 * Returns 0 on success, negative value otherwise. 781 * 782 * Caller holds tomoyo_read_lock(). 783 */ 784int tomoyo_find_next_domain(struct linux_binprm *bprm) 785{ 786 /* 787 * This function assumes that the size of buffer returned by 788 * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. 789 */ 790 struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); 791 struct tomoyo_domain_info *old_domain = tomoyo_domain(); 792 struct tomoyo_domain_info *domain = NULL; 793 const char *old_domain_name = old_domain->domainname->name; 794 const char *original_name = bprm->filename; 795 char *new_domain_name = NULL; 796 char *real_program_name = NULL; 797 char *symlink_program_name = NULL; 798 const u8 mode = tomoyo_check_flags(old_domain, TOMOYO_MAC_FOR_FILE); 799 const bool is_enforce = (mode == 3); 800 int retval = -ENOMEM; 801 struct tomoyo_path_info r; /* real name */ 802 struct tomoyo_path_info s; /* symlink name */ 803 struct tomoyo_path_info l; /* last name */ 804 static bool initialized; 805 806 if (!tmp) 807 goto out; 808 809 if (!initialized) { 810 /* 811 * Built-in initializers. This is needed because policies are 812 * not loaded until starting /sbin/init. 813 */ 814 tomoyo_update_domain_initializer_entry(NULL, "/sbin/hotplug", 815 false, false); 816 tomoyo_update_domain_initializer_entry(NULL, "/sbin/modprobe", 817 false, false); 818 initialized = true; 819 } 820 821 /* Get tomoyo_realpath of program. */ 822 retval = -ENOENT; 823 /* I hope tomoyo_realpath() won't fail with -ENOMEM. */ 824 real_program_name = tomoyo_realpath(original_name); 825 if (!real_program_name) 826 goto out; 827 /* Get tomoyo_realpath of symbolic link. */ 828 symlink_program_name = tomoyo_realpath_nofollow(original_name); 829 if (!symlink_program_name) 830 goto out; 831 832 r.name = real_program_name; 833 tomoyo_fill_path_info(&r); 834 s.name = symlink_program_name; 835 tomoyo_fill_path_info(&s); 836 l.name = tomoyo_get_last_name(old_domain); 837 tomoyo_fill_path_info(&l); 838 839 /* Check 'alias' directive. */ 840 if (tomoyo_pathcmp(&r, &s)) { 841 struct tomoyo_alias_entry *ptr; 842 /* Is this program allowed to be called via symbolic links? */ 843 list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { 844 if (ptr->is_deleted || 845 tomoyo_pathcmp(&r, ptr->original_name) || 846 tomoyo_pathcmp(&s, ptr->aliased_name)) 847 continue; 848 memset(real_program_name, 0, TOMOYO_MAX_PATHNAME_LEN); 849 strncpy(real_program_name, ptr->aliased_name->name, 850 TOMOYO_MAX_PATHNAME_LEN - 1); 851 tomoyo_fill_path_info(&r); 852 break; 853 } 854 } 855 856 /* Check execute permission. */ 857 retval = tomoyo_check_exec_perm(old_domain, &r); 858 if (retval < 0) 859 goto out; 860 861 new_domain_name = tmp->buffer; 862 if (tomoyo_is_domain_initializer(old_domain->domainname, &r, &l)) { 863 /* Transit to the child of tomoyo_kernel_domain domain. */ 864 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 865 TOMOYO_ROOT_NAME " " "%s", real_program_name); 866 } else if (old_domain == &tomoyo_kernel_domain && 867 !tomoyo_policy_loaded) { 868 /* 869 * Needn't to transit from kernel domain before starting 870 * /sbin/init. But transit from kernel domain if executing 871 * initializers because they might start before /sbin/init. 872 */ 873 domain = old_domain; 874 } else if (tomoyo_is_domain_keeper(old_domain->domainname, &r, &l)) { 875 /* Keep current domain. */ 876 domain = old_domain; 877 } else { 878 /* Normal domain transition. */ 879 snprintf(new_domain_name, TOMOYO_MAX_PATHNAME_LEN + 1, 880 "%s %s", old_domain_name, real_program_name); 881 } 882 if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) 883 goto done; 884 domain = tomoyo_find_domain(new_domain_name); 885 if (domain) 886 goto done; 887 if (is_enforce) 888 goto done; 889 domain = tomoyo_find_or_assign_new_domain(new_domain_name, 890 old_domain->profile); 891 done: 892 if (domain) 893 goto out; 894 printk(KERN_WARNING "TOMOYO-ERROR: Domain '%s' not defined.\n", 895 new_domain_name); 896 if (is_enforce) 897 retval = -EPERM; 898 else 899 tomoyo_set_domain_flag(old_domain, false, 900 TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED); 901 out: 902 if (!domain) 903 domain = old_domain; 904 bprm->cred->security = domain; 905 kfree(real_program_name); 906 kfree(symlink_program_name); 907 kfree(tmp); 908 return retval; 909} 910