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