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