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