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