domain.c revision a8f7640963ada66c412314c3559c11ff6946c1a5
1/* 2 * security/tomoyo/domain.c 3 * 4 * Copyright (C) 2005-2011 NTT DATA CORPORATION 5 */ 6 7#include "common.h" 8#include <linux/binfmts.h> 9#include <linux/slab.h> 10 11/* Variables definitions.*/ 12 13/* The initial domain. */ 14struct tomoyo_domain_info tomoyo_kernel_domain; 15 16/** 17 * tomoyo_update_policy - Update an entry for exception policy. 18 * 19 * @new_entry: Pointer to "struct tomoyo_acl_info". 20 * @size: Size of @new_entry in bytes. 21 * @param: Pointer to "struct tomoyo_acl_param". 22 * @check_duplicate: Callback function to find duplicated entry. 23 * 24 * Returns 0 on success, negative value otherwise. 25 * 26 * Caller holds tomoyo_read_lock(). 27 */ 28int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, 29 struct tomoyo_acl_param *param, 30 bool (*check_duplicate) (const struct tomoyo_acl_head 31 *, 32 const struct tomoyo_acl_head 33 *)) 34{ 35 int error = param->is_delete ? -ENOENT : -ENOMEM; 36 struct tomoyo_acl_head *entry; 37 struct list_head *list = param->list; 38 39 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 40 return -ENOMEM; 41 list_for_each_entry_rcu(entry, list, list) { 42 if (!check_duplicate(entry, new_entry)) 43 continue; 44 entry->is_deleted = param->is_delete; 45 error = 0; 46 break; 47 } 48 if (error && !param->is_delete) { 49 entry = tomoyo_commit_ok(new_entry, size); 50 if (entry) { 51 list_add_tail_rcu(&entry->list, list); 52 error = 0; 53 } 54 } 55 mutex_unlock(&tomoyo_policy_lock); 56 return error; 57} 58 59/** 60 * tomoyo_same_acl_head - Check for duplicated "struct tomoyo_acl_info" entry. 61 * 62 * @a: Pointer to "struct tomoyo_acl_info". 63 * @b: Pointer to "struct tomoyo_acl_info". 64 * 65 * Returns true if @a == @b, false otherwise. 66 */ 67static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a, 68 const struct tomoyo_acl_info *b) 69{ 70 return a->type == b->type && a->cond == b->cond; 71} 72 73/** 74 * tomoyo_update_domain - Update an entry for domain policy. 75 * 76 * @new_entry: Pointer to "struct tomoyo_acl_info". 77 * @size: Size of @new_entry in bytes. 78 * @param: Pointer to "struct tomoyo_acl_param". 79 * @check_duplicate: Callback function to find duplicated entry. 80 * @merge_duplicate: Callback function to merge duplicated entry. 81 * 82 * Returns 0 on success, negative value otherwise. 83 * 84 * Caller holds tomoyo_read_lock(). 85 */ 86int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, 87 struct tomoyo_acl_param *param, 88 bool (*check_duplicate) (const struct tomoyo_acl_info 89 *, 90 const struct tomoyo_acl_info 91 *), 92 bool (*merge_duplicate) (struct tomoyo_acl_info *, 93 struct tomoyo_acl_info *, 94 const bool)) 95{ 96 const bool is_delete = param->is_delete; 97 int error = is_delete ? -ENOENT : -ENOMEM; 98 struct tomoyo_acl_info *entry; 99 struct list_head * const list = param->list; 100 101 if (param->data[0]) { 102 new_entry->cond = tomoyo_get_condition(param); 103 if (!new_entry->cond) 104 return -EINVAL; 105 } 106 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 107 goto out; 108 list_for_each_entry_rcu(entry, list, list) { 109 if (!tomoyo_same_acl_head(entry, new_entry) || 110 !check_duplicate(entry, new_entry)) 111 continue; 112 if (merge_duplicate) 113 entry->is_deleted = merge_duplicate(entry, new_entry, 114 is_delete); 115 else 116 entry->is_deleted = is_delete; 117 error = 0; 118 break; 119 } 120 if (error && !is_delete) { 121 entry = tomoyo_commit_ok(new_entry, size); 122 if (entry) { 123 list_add_tail_rcu(&entry->list, list); 124 error = 0; 125 } 126 } 127 mutex_unlock(&tomoyo_policy_lock); 128out: 129 tomoyo_put_condition(new_entry->cond); 130 return error; 131} 132 133/** 134 * tomoyo_check_acl - Do permission check. 135 * 136 * @r: Pointer to "struct tomoyo_request_info". 137 * @check_entry: Callback function to check type specific parameters. 138 * 139 * Returns 0 on success, negative value otherwise. 140 * 141 * Caller holds tomoyo_read_lock(). 142 */ 143void tomoyo_check_acl(struct tomoyo_request_info *r, 144 bool (*check_entry) (struct tomoyo_request_info *, 145 const struct tomoyo_acl_info *)) 146{ 147 const struct tomoyo_domain_info *domain = r->domain; 148 struct tomoyo_acl_info *ptr; 149 bool retried = false; 150 const struct list_head *list = &domain->acl_info_list; 151 152retry: 153 list_for_each_entry_rcu(ptr, list, list) { 154 if (ptr->is_deleted || ptr->type != r->param_type) 155 continue; 156 if (!check_entry(r, ptr)) 157 continue; 158 if (!tomoyo_condition(r, ptr->cond)) 159 continue; 160 r->matched_acl = ptr; 161 r->granted = true; 162 return; 163 } 164 if (!retried) { 165 retried = true; 166 list = &domain->ns->acl_group[domain->group]; 167 goto retry; 168 } 169 r->granted = false; 170} 171 172/* The list for "struct tomoyo_domain_info". */ 173LIST_HEAD(tomoyo_domain_list); 174 175/** 176 * tomoyo_last_word - Get last component of a domainname. 177 * 178 * @name: Domainname to check. 179 * 180 * Returns the last word of @domainname. 181 */ 182static const char *tomoyo_last_word(const char *name) 183{ 184 const char *cp = strrchr(name, ' '); 185 if (cp) 186 return cp + 1; 187 return name; 188} 189 190/** 191 * tomoyo_same_transition_control - Check for duplicated "struct tomoyo_transition_control" entry. 192 * 193 * @a: Pointer to "struct tomoyo_acl_head". 194 * @b: Pointer to "struct tomoyo_acl_head". 195 * 196 * Returns true if @a == @b, false otherwise. 197 */ 198static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a, 199 const struct tomoyo_acl_head *b) 200{ 201 const struct tomoyo_transition_control *p1 = container_of(a, 202 typeof(*p1), 203 head); 204 const struct tomoyo_transition_control *p2 = container_of(b, 205 typeof(*p2), 206 head); 207 return p1->type == p2->type && p1->is_last_name == p2->is_last_name 208 && p1->domainname == p2->domainname 209 && p1->program == p2->program; 210} 211 212/** 213 * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list. 214 * 215 * @param: Pointer to "struct tomoyo_acl_param". 216 * @type: Type of this entry. 217 * 218 * Returns 0 on success, negative value otherwise. 219 */ 220int tomoyo_write_transition_control(struct tomoyo_acl_param *param, 221 const u8 type) 222{ 223 struct tomoyo_transition_control e = { .type = type }; 224 int error = param->is_delete ? -ENOENT : -ENOMEM; 225 char *program = param->data; 226 char *domainname = strstr(program, " from "); 227 if (domainname) { 228 *domainname = '\0'; 229 domainname += 6; 230 } else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP || 231 type == TOMOYO_TRANSITION_CONTROL_KEEP) { 232 domainname = program; 233 program = NULL; 234 } 235 if (program && strcmp(program, "any")) { 236 if (!tomoyo_correct_path(program)) 237 return -EINVAL; 238 e.program = tomoyo_get_name(program); 239 if (!e.program) 240 goto out; 241 } 242 if (domainname && strcmp(domainname, "any")) { 243 if (!tomoyo_correct_domain(domainname)) { 244 if (!tomoyo_correct_path(domainname)) 245 goto out; 246 e.is_last_name = true; 247 } 248 e.domainname = tomoyo_get_name(domainname); 249 if (!e.domainname) 250 goto out; 251 } 252 param->list = ¶m->ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL]; 253 error = tomoyo_update_policy(&e.head, sizeof(e), param, 254 tomoyo_same_transition_control); 255out: 256 tomoyo_put_name(e.domainname); 257 tomoyo_put_name(e.program); 258 return error; 259} 260 261/** 262 * tomoyo_scan_transition - Try to find specific domain transition type. 263 * 264 * @list: Pointer to "struct list_head". 265 * @domainname: The name of current domain. 266 * @program: The name of requested program. 267 * @last_name: The last component of @domainname. 268 * @type: One of values in "enum tomoyo_transition_type". 269 * 270 * Returns true if found one, false otherwise. 271 * 272 * Caller holds tomoyo_read_lock(). 273 */ 274static inline bool tomoyo_scan_transition 275(const struct list_head *list, const struct tomoyo_path_info *domainname, 276 const struct tomoyo_path_info *program, const char *last_name, 277 const enum tomoyo_transition_type type) 278{ 279 const struct tomoyo_transition_control *ptr; 280 list_for_each_entry_rcu(ptr, list, head.list) { 281 if (ptr->head.is_deleted || ptr->type != type) 282 continue; 283 if (ptr->domainname) { 284 if (!ptr->is_last_name) { 285 if (ptr->domainname != domainname) 286 continue; 287 } else { 288 /* 289 * Use direct strcmp() since this is 290 * unlikely used. 291 */ 292 if (strcmp(ptr->domainname->name, last_name)) 293 continue; 294 } 295 } 296 if (ptr->program && tomoyo_pathcmp(ptr->program, program)) 297 continue; 298 return true; 299 } 300 return false; 301} 302 303/** 304 * tomoyo_transition_type - Get domain transition type. 305 * 306 * @ns: Pointer to "struct tomoyo_policy_namespace". 307 * @domainname: The name of current domain. 308 * @program: The name of requested program. 309 * 310 * Returns TOMOYO_TRANSITION_CONTROL_TRANSIT if executing @program causes 311 * domain transition across namespaces, TOMOYO_TRANSITION_CONTROL_INITIALIZE if 312 * executing @program reinitializes domain transition within that namespace, 313 * TOMOYO_TRANSITION_CONTROL_KEEP if executing @program stays at @domainname , 314 * others otherwise. 315 * 316 * Caller holds tomoyo_read_lock(). 317 */ 318static enum tomoyo_transition_type tomoyo_transition_type 319(const struct tomoyo_policy_namespace *ns, 320 const struct tomoyo_path_info *domainname, 321 const struct tomoyo_path_info *program) 322{ 323 const char *last_name = tomoyo_last_word(domainname->name); 324 enum tomoyo_transition_type type = TOMOYO_TRANSITION_CONTROL_NO_RESET; 325 while (type < TOMOYO_MAX_TRANSITION_TYPE) { 326 const struct list_head * const list = 327 &ns->policy_list[TOMOYO_ID_TRANSITION_CONTROL]; 328 if (!tomoyo_scan_transition(list, domainname, program, 329 last_name, type)) { 330 type++; 331 continue; 332 } 333 if (type != TOMOYO_TRANSITION_CONTROL_NO_RESET && 334 type != TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) 335 break; 336 /* 337 * Do not check for reset_domain if no_reset_domain matched. 338 * Do not check for initialize_domain if no_initialize_domain 339 * matched. 340 */ 341 type++; 342 type++; 343 } 344 return type; 345} 346 347/** 348 * tomoyo_same_aggregator - Check for duplicated "struct tomoyo_aggregator" entry. 349 * 350 * @a: Pointer to "struct tomoyo_acl_head". 351 * @b: Pointer to "struct tomoyo_acl_head". 352 * 353 * Returns true if @a == @b, false otherwise. 354 */ 355static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a, 356 const struct tomoyo_acl_head *b) 357{ 358 const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1), 359 head); 360 const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), 361 head); 362 return p1->original_name == p2->original_name && 363 p1->aggregated_name == p2->aggregated_name; 364} 365 366/** 367 * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list. 368 * 369 * @param: Pointer to "struct tomoyo_acl_param". 370 * 371 * Returns 0 on success, negative value otherwise. 372 * 373 * Caller holds tomoyo_read_lock(). 374 */ 375int tomoyo_write_aggregator(struct tomoyo_acl_param *param) 376{ 377 struct tomoyo_aggregator e = { }; 378 int error = param->is_delete ? -ENOENT : -ENOMEM; 379 const char *original_name = tomoyo_read_token(param); 380 const char *aggregated_name = tomoyo_read_token(param); 381 if (!tomoyo_correct_word(original_name) || 382 !tomoyo_correct_path(aggregated_name)) 383 return -EINVAL; 384 e.original_name = tomoyo_get_name(original_name); 385 e.aggregated_name = tomoyo_get_name(aggregated_name); 386 if (!e.original_name || !e.aggregated_name || 387 e.aggregated_name->is_patterned) /* No patterns allowed. */ 388 goto out; 389 param->list = ¶m->ns->policy_list[TOMOYO_ID_AGGREGATOR]; 390 error = tomoyo_update_policy(&e.head, sizeof(e), param, 391 tomoyo_same_aggregator); 392out: 393 tomoyo_put_name(e.original_name); 394 tomoyo_put_name(e.aggregated_name); 395 return error; 396} 397 398/** 399 * tomoyo_find_namespace - Find specified namespace. 400 * 401 * @name: Name of namespace to find. 402 * @len: Length of @name. 403 * 404 * Returns pointer to "struct tomoyo_policy_namespace" if found, 405 * NULL otherwise. 406 * 407 * Caller holds tomoyo_read_lock(). 408 */ 409static struct tomoyo_policy_namespace *tomoyo_find_namespace 410(const char *name, const unsigned int len) 411{ 412 struct tomoyo_policy_namespace *ns; 413 list_for_each_entry(ns, &tomoyo_namespace_list, namespace_list) { 414 if (strncmp(name, ns->name, len) || 415 (name[len] && name[len] != ' ')) 416 continue; 417 return ns; 418 } 419 return NULL; 420} 421 422/** 423 * tomoyo_assign_namespace - Create a new namespace. 424 * 425 * @domainname: Name of namespace to create. 426 * 427 * Returns pointer to "struct tomoyo_policy_namespace" on success, 428 * NULL otherwise. 429 * 430 * Caller holds tomoyo_read_lock(). 431 */ 432struct tomoyo_policy_namespace *tomoyo_assign_namespace(const char *domainname) 433{ 434 struct tomoyo_policy_namespace *ptr; 435 struct tomoyo_policy_namespace *entry; 436 const char *cp = domainname; 437 unsigned int len = 0; 438 while (*cp && *cp++ != ' ') 439 len++; 440 ptr = tomoyo_find_namespace(domainname, len); 441 if (ptr) 442 return ptr; 443 if (len >= TOMOYO_EXEC_TMPSIZE - 10 || !tomoyo_domain_def(domainname)) 444 return NULL; 445 entry = kzalloc(sizeof(*entry) + len + 1, GFP_NOFS); 446 if (!entry) 447 return NULL; 448 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 449 goto out; 450 ptr = tomoyo_find_namespace(domainname, len); 451 if (!ptr && tomoyo_memory_ok(entry)) { 452 char *name = (char *) (entry + 1); 453 ptr = entry; 454 memmove(name, domainname, len); 455 name[len] = '\0'; 456 entry->name = name; 457 tomoyo_init_policy_namespace(entry); 458 entry = NULL; 459 } 460 mutex_unlock(&tomoyo_policy_lock); 461out: 462 kfree(entry); 463 return ptr; 464} 465 466/** 467 * tomoyo_namespace_jump - Check for namespace jump. 468 * 469 * @domainname: Name of domain. 470 * 471 * Returns true if namespace differs, false otherwise. 472 */ 473static bool tomoyo_namespace_jump(const char *domainname) 474{ 475 const char *namespace = tomoyo_current_namespace()->name; 476 const int len = strlen(namespace); 477 return strncmp(domainname, namespace, len) || 478 (domainname[len] && domainname[len] != ' '); 479} 480 481/** 482 * tomoyo_assign_domain - Create a domain or a namespace. 483 * 484 * @domainname: The name of domain. 485 * @transit: True if transit to domain found or created. 486 * 487 * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. 488 * 489 * Caller holds tomoyo_read_lock(). 490 */ 491struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, 492 const bool transit) 493{ 494 struct tomoyo_domain_info e = { }; 495 struct tomoyo_domain_info *entry = tomoyo_find_domain(domainname); 496 bool created = false; 497 if (entry) { 498 if (transit) { 499 /* 500 * Since namespace is created at runtime, profiles may 501 * not be created by the moment the process transits to 502 * that domain. Do not perform domain transition if 503 * profile for that domain is not yet created. 504 */ 505 if (!entry->ns->profile_ptr[entry->profile]) 506 return NULL; 507 } 508 return entry; 509 } 510 /* Requested domain does not exist. */ 511 /* Don't create requested domain if domainname is invalid. */ 512 if (strlen(domainname) >= TOMOYO_EXEC_TMPSIZE - 10 || 513 !tomoyo_correct_domain(domainname)) 514 return NULL; 515 /* 516 * Since definition of profiles and acl_groups may differ across 517 * namespaces, do not inherit "use_profile" and "use_group" settings 518 * by automatically creating requested domain upon domain transition. 519 */ 520 if (transit && tomoyo_namespace_jump(domainname)) 521 return NULL; 522 e.ns = tomoyo_assign_namespace(domainname); 523 if (!e.ns) 524 return NULL; 525 /* 526 * "use_profile" and "use_group" settings for automatically created 527 * domains are inherited from current domain. These are 0 for manually 528 * created domains. 529 */ 530 if (transit) { 531 const struct tomoyo_domain_info *domain = tomoyo_domain(); 532 e.profile = domain->profile; 533 e.group = domain->group; 534 } 535 e.domainname = tomoyo_get_name(domainname); 536 if (!e.domainname) 537 return NULL; 538 if (mutex_lock_interruptible(&tomoyo_policy_lock)) 539 goto out; 540 entry = tomoyo_find_domain(domainname); 541 if (!entry) { 542 entry = tomoyo_commit_ok(&e, sizeof(e)); 543 if (entry) { 544 INIT_LIST_HEAD(&entry->acl_info_list); 545 list_add_tail_rcu(&entry->list, &tomoyo_domain_list); 546 created = true; 547 } 548 } 549 mutex_unlock(&tomoyo_policy_lock); 550out: 551 tomoyo_put_name(e.domainname); 552 if (entry && transit) { 553 if (created) { 554 struct tomoyo_request_info r; 555 tomoyo_init_request_info(&r, entry, 556 TOMOYO_MAC_FILE_EXECUTE); 557 r.granted = false; 558 tomoyo_write_log(&r, "use_profile %u\n", 559 entry->profile); 560 tomoyo_write_log(&r, "use_group %u\n", entry->group); 561 } 562 } 563 return entry; 564} 565 566/** 567 * tomoyo_environ - Check permission for environment variable names. 568 * 569 * @ee: Pointer to "struct tomoyo_execve". 570 * 571 * Returns 0 on success, negative value otherwise. 572 */ 573static int tomoyo_environ(struct tomoyo_execve *ee) 574{ 575 struct tomoyo_request_info *r = &ee->r; 576 struct linux_binprm *bprm = ee->bprm; 577 /* env_page.data is allocated by tomoyo_dump_page(). */ 578 struct tomoyo_page_dump env_page = { }; 579 char *arg_ptr; /* Size is TOMOYO_EXEC_TMPSIZE bytes */ 580 int arg_len = 0; 581 unsigned long pos = bprm->p; 582 int offset = pos % PAGE_SIZE; 583 int argv_count = bprm->argc; 584 int envp_count = bprm->envc; 585 int error = -ENOMEM; 586 587 ee->r.type = TOMOYO_MAC_ENVIRON; 588 ee->r.profile = r->domain->profile; 589 ee->r.mode = tomoyo_get_mode(r->domain->ns, ee->r.profile, 590 TOMOYO_MAC_ENVIRON); 591 if (!r->mode || !envp_count) 592 return 0; 593 arg_ptr = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); 594 if (!arg_ptr) 595 goto out; 596 while (error == -ENOMEM) { 597 if (!tomoyo_dump_page(bprm, pos, &env_page)) 598 goto out; 599 pos += PAGE_SIZE - offset; 600 /* Read. */ 601 while (argv_count && offset < PAGE_SIZE) { 602 if (!env_page.data[offset++]) 603 argv_count--; 604 } 605 if (argv_count) { 606 offset = 0; 607 continue; 608 } 609 while (offset < PAGE_SIZE) { 610 const unsigned char c = env_page.data[offset++]; 611 612 if (c && arg_len < TOMOYO_EXEC_TMPSIZE - 10) { 613 if (c == '=') { 614 arg_ptr[arg_len++] = '\0'; 615 } else if (c == '\\') { 616 arg_ptr[arg_len++] = '\\'; 617 arg_ptr[arg_len++] = '\\'; 618 } else if (c > ' ' && c < 127) { 619 arg_ptr[arg_len++] = c; 620 } else { 621 arg_ptr[arg_len++] = '\\'; 622 arg_ptr[arg_len++] = (c >> 6) + '0'; 623 arg_ptr[arg_len++] 624 = ((c >> 3) & 7) + '0'; 625 arg_ptr[arg_len++] = (c & 7) + '0'; 626 } 627 } else { 628 arg_ptr[arg_len] = '\0'; 629 } 630 if (c) 631 continue; 632 if (tomoyo_env_perm(r, arg_ptr)) { 633 error = -EPERM; 634 break; 635 } 636 if (!--envp_count) { 637 error = 0; 638 break; 639 } 640 arg_len = 0; 641 } 642 offset = 0; 643 } 644out: 645 if (r->mode != TOMOYO_CONFIG_ENFORCING) 646 error = 0; 647 kfree(env_page.data); 648 kfree(arg_ptr); 649 return error; 650} 651 652/** 653 * tomoyo_find_next_domain - Find a domain. 654 * 655 * @bprm: Pointer to "struct linux_binprm". 656 * 657 * Returns 0 on success, negative value otherwise. 658 * 659 * Caller holds tomoyo_read_lock(). 660 */ 661int tomoyo_find_next_domain(struct linux_binprm *bprm) 662{ 663 struct tomoyo_domain_info *old_domain = tomoyo_domain(); 664 struct tomoyo_domain_info *domain = NULL; 665 const char *original_name = bprm->filename; 666 int retval = -ENOMEM; 667 bool reject_on_transition_failure = false; 668 const struct tomoyo_path_info *candidate; 669 struct tomoyo_path_info exename; 670 struct tomoyo_execve *ee = kzalloc(sizeof(*ee), GFP_NOFS); 671 672 if (!ee) 673 return -ENOMEM; 674 ee->tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS); 675 if (!ee->tmp) { 676 kfree(ee); 677 return -ENOMEM; 678 } 679 /* ee->dump->data is allocated by tomoyo_dump_page(). */ 680 tomoyo_init_request_info(&ee->r, NULL, TOMOYO_MAC_FILE_EXECUTE); 681 ee->r.ee = ee; 682 ee->bprm = bprm; 683 ee->r.obj = &ee->obj; 684 ee->obj.path1 = bprm->file->f_path; 685 /* Get symlink's pathname of program. */ 686 retval = -ENOENT; 687 exename.name = tomoyo_realpath_nofollow(original_name); 688 if (!exename.name) 689 goto out; 690 tomoyo_fill_path_info(&exename); 691retry: 692 /* Check 'aggregator' directive. */ 693 { 694 struct tomoyo_aggregator *ptr; 695 struct list_head *list = 696 &old_domain->ns->policy_list[TOMOYO_ID_AGGREGATOR]; 697 /* Check 'aggregator' directive. */ 698 candidate = &exename; 699 list_for_each_entry_rcu(ptr, list, head.list) { 700 if (ptr->head.is_deleted || 701 !tomoyo_path_matches_pattern(&exename, 702 ptr->original_name)) 703 continue; 704 candidate = ptr->aggregated_name; 705 break; 706 } 707 } 708 709 /* Check execute permission. */ 710 retval = tomoyo_path_permission(&ee->r, TOMOYO_TYPE_EXECUTE, 711 candidate); 712 if (retval == TOMOYO_RETRY_REQUEST) 713 goto retry; 714 if (retval < 0) 715 goto out; 716 /* 717 * To be able to specify domainnames with wildcards, use the 718 * pathname specified in the policy (which may contain 719 * wildcard) rather than the pathname passed to execve() 720 * (which never contains wildcard). 721 */ 722 if (ee->r.param.path.matched_path) 723 candidate = ee->r.param.path.matched_path; 724 725 /* Calculate domain to transit to. */ 726 switch (tomoyo_transition_type(old_domain->ns, old_domain->domainname, 727 candidate)) { 728 case TOMOYO_TRANSITION_CONTROL_RESET: 729 /* Transit to the root of specified namespace. */ 730 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "<%s>", 731 candidate->name); 732 /* 733 * Make do_execve() fail if domain transition across namespaces 734 * has failed. 735 */ 736 reject_on_transition_failure = true; 737 break; 738 case TOMOYO_TRANSITION_CONTROL_INITIALIZE: 739 /* Transit to the child of current namespace's root. */ 740 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", 741 old_domain->ns->name, candidate->name); 742 break; 743 case TOMOYO_TRANSITION_CONTROL_KEEP: 744 /* Keep current domain. */ 745 domain = old_domain; 746 break; 747 default: 748 if (old_domain == &tomoyo_kernel_domain && 749 !tomoyo_policy_loaded) { 750 /* 751 * Needn't to transit from kernel domain before 752 * starting /sbin/init. But transit from kernel domain 753 * if executing initializers because they might start 754 * before /sbin/init. 755 */ 756 domain = old_domain; 757 break; 758 } 759 /* Normal domain transition. */ 760 snprintf(ee->tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s", 761 old_domain->domainname->name, candidate->name); 762 break; 763 } 764 if (!domain) 765 domain = tomoyo_assign_domain(ee->tmp, true); 766 if (domain) 767 retval = 0; 768 else if (reject_on_transition_failure) { 769 printk(KERN_WARNING "ERROR: Domain '%s' not ready.\n", 770 ee->tmp); 771 retval = -ENOMEM; 772 } else if (ee->r.mode == TOMOYO_CONFIG_ENFORCING) 773 retval = -ENOMEM; 774 else { 775 retval = 0; 776 if (!old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED]) { 777 old_domain->flags[TOMOYO_DIF_TRANSITION_FAILED] = true; 778 ee->r.granted = false; 779 tomoyo_write_log(&ee->r, "%s", tomoyo_dif 780 [TOMOYO_DIF_TRANSITION_FAILED]); 781 printk(KERN_WARNING 782 "ERROR: Domain '%s' not defined.\n", ee->tmp); 783 } 784 } 785 out: 786 if (!domain) 787 domain = old_domain; 788 /* Update reference count on "struct tomoyo_domain_info". */ 789 atomic_inc(&domain->users); 790 bprm->cred->security = domain; 791 kfree(exename.name); 792 if (!retval) { 793 ee->r.domain = domain; 794 retval = tomoyo_environ(ee); 795 } 796 kfree(ee->tmp); 797 kfree(ee->dump.data); 798 kfree(ee); 799 return retval; 800} 801 802/** 803 * tomoyo_dump_page - Dump a page to buffer. 804 * 805 * @bprm: Pointer to "struct linux_binprm". 806 * @pos: Location to dump. 807 * @dump: Poiner to "struct tomoyo_page_dump". 808 * 809 * Returns true on success, false otherwise. 810 */ 811bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos, 812 struct tomoyo_page_dump *dump) 813{ 814 struct page *page; 815 816 /* dump->data is released by tomoyo_find_next_domain(). */ 817 if (!dump->data) { 818 dump->data = kzalloc(PAGE_SIZE, GFP_NOFS); 819 if (!dump->data) 820 return false; 821 } 822 /* Same with get_arg_page(bprm, pos, 0) in fs/exec.c */ 823#ifdef CONFIG_MMU 824 if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0) 825 return false; 826#else 827 page = bprm->page[pos / PAGE_SIZE]; 828#endif 829 if (page != dump->page) { 830 const unsigned int offset = pos % PAGE_SIZE; 831 /* 832 * Maybe kmap()/kunmap() should be used here. 833 * But remove_arg_zero() uses kmap_atomic()/kunmap_atomic(). 834 * So do I. 835 */ 836 char *kaddr = kmap_atomic(page, KM_USER0); 837 838 dump->page = page; 839 memcpy(dump->data + offset, kaddr + offset, 840 PAGE_SIZE - offset); 841 kunmap_atomic(kaddr, KM_USER0); 842 } 843 /* Same with put_arg_page(page) in fs/exec.c */ 844#ifdef CONFIG_MMU 845 put_page(page); 846#endif 847 return true; 848} 849