TOMOYO: Use common code for domain transition control.
Tetsuo Handa [Mon, 21 Jun 2010 02:14:39 +0000 (11:14 +0900)]
Use common code for "initialize_domain"/"no_initialize_domain"/"keep_domain"/
"no_keep_domain" keywords.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: James Morris <jmorris@namei.org>

security/tomoyo/common.c
security/tomoyo/common.h
security/tomoyo/domain.c
security/tomoyo/gc.c
security/tomoyo/memory.c
security/tomoyo/util.c

index 0e6b1b5..6568ef1 100644 (file)
@@ -1150,6 +1150,15 @@ static void tomoyo_read_pid(struct tomoyo_io_buffer *head)
        }
 }
 
+static const char *tomoyo_transition_type[TOMOYO_MAX_TRANSITION_TYPE] = {
+       [TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE]
+       = TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN,
+       [TOMOYO_TRANSITION_CONTROL_INITIALIZE]
+       = TOMOYO_KEYWORD_INITIALIZE_DOMAIN,
+       [TOMOYO_TRANSITION_CONTROL_NO_KEEP] = TOMOYO_KEYWORD_NO_KEEP_DOMAIN,
+       [TOMOYO_TRANSITION_CONTROL_KEEP] = TOMOYO_KEYWORD_KEEP_DOMAIN
+};
+
 /**
  * tomoyo_write_exception_policy - Write exception policy.
  *
@@ -1163,18 +1172,13 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head)
 {
        char *data = head->write_buf;
        bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE);
+       u8 i;
 
-       if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_KEEP_DOMAIN))
-               return tomoyo_write_domain_keeper_policy(data, false,
-                                                        is_delete);
-       if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_KEEP_DOMAIN))
-               return tomoyo_write_domain_keeper_policy(data, true, is_delete);
-       if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_INITIALIZE_DOMAIN))
-               return tomoyo_write_domain_initializer_policy(data, false,
-                                                             is_delete);
-       if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN))
-               return tomoyo_write_domain_initializer_policy(data, true,
-                                                             is_delete);
+       for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) {
+               if (tomoyo_str_starts(&data, tomoyo_transition_type[i]))
+                       return tomoyo_write_transition_control(data, is_delete,
+                                                              i);
+       }
        if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_AGGREGATOR))
                return tomoyo_write_aggregator_policy(data, is_delete);
        if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_READ))
@@ -1296,32 +1300,17 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx)
                if (acl->is_deleted)
                        continue;
                switch (idx) {
-               case TOMOYO_ID_DOMAIN_KEEPER:
+               case TOMOYO_ID_TRANSITION_CONTROL:
                        {
-                               struct tomoyo_domain_keeper_entry *ptr =
+                               struct tomoyo_transition_control *ptr =
                                        container_of(acl, typeof(*ptr), head);
-                               w[0] = ptr->is_not ?
-                                       TOMOYO_KEYWORD_NO_KEEP_DOMAIN :
-                                       TOMOYO_KEYWORD_KEEP_DOMAIN;
-                               if (ptr->program) {
+                               w[0] = tomoyo_transition_type[ptr->type];
+                               if (ptr->program)
                                        w[1] = ptr->program->name;
-                                       w[2] = " from ";
-                               }
-                               w[3] = ptr->domainname->name;
-                       }
-                       break;
-               case TOMOYO_ID_DOMAIN_INITIALIZER:
-                       {
-                               struct tomoyo_domain_initializer_entry *ptr =
-                                       container_of(acl, typeof(*ptr), head);
-                               w[0] = ptr->is_not ?
-                                       TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN :
-                                       TOMOYO_KEYWORD_INITIALIZE_DOMAIN;
-                               w[1] = ptr->program->name;
-                               if (ptr->domainname) {
-                                       w[2] = " from ";
+                               if (ptr->domainname)
                                        w[3] = ptr->domainname->name;
-                               }
+                               if (w[1][0] && w[3][0])
+                                       w[2] = " from ";
                        }
                        break;
                case TOMOYO_ID_GLOBALLY_READABLE:
index 12b0c5c..1277724 100644 (file)
@@ -50,8 +50,7 @@ enum tomoyo_policy_id {
        TOMOYO_ID_GROUP,
        TOMOYO_ID_PATH_GROUP,
        TOMOYO_ID_NUMBER_GROUP,
-       TOMOYO_ID_DOMAIN_INITIALIZER,
-       TOMOYO_ID_DOMAIN_KEEPER,
+       TOMOYO_ID_TRANSITION_CONTROL,
        TOMOYO_ID_AGGREGATOR,
        TOMOYO_ID_GLOBALLY_READABLE,
        TOMOYO_ID_PATTERN,
@@ -97,6 +96,15 @@ enum tomoyo_group_id {
 #define TOMOYO_VALUE_TYPE_OCTAL       2
 #define TOMOYO_VALUE_TYPE_HEXADECIMAL 3
 
+enum tomoyo_transition_type {
+       /* Do not change this order, */
+       TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE,
+       TOMOYO_TRANSITION_CONTROL_INITIALIZE,
+       TOMOYO_TRANSITION_CONTROL_NO_KEEP,
+       TOMOYO_TRANSITION_CONTROL_KEEP,
+       TOMOYO_MAX_TRANSITION_TYPE
+};
+
 /* Index numbers for Access Controls. */
 enum tomoyo_acl_entry_type_index {
        TOMOYO_TYPE_PATH_ACL,
@@ -619,50 +627,26 @@ struct tomoyo_no_rewrite_entry {
 };
 
 /*
- * tomoyo_domain_initializer_entry is a structure which is used for holding
- * "initialize_domain" and "no_initialize_domain" entries.
+ * tomoyo_transition_control is a structure which is used for holding
+ * "initialize_domain"/"no_initialize_domain"/"keep_domain"/"no_keep_domain"
+ * entries.
  * It has following fields.
  *
  *  (1) "head" is "struct tomoyo_acl_head".
- *  (2) "is_not" is a bool which is true if "no_initialize_domain", false
- *      otherwise.
- *  (3) "is_last_name" is a bool which is true if "domainname" is "the last
- *      component of a domainname", false otherwise.
- *  (4) "domainname" which is "a domainname" or "the last component of a
- *      domainname". This field is NULL if "from" clause is not specified.
- *  (5) "program" which is a program's pathname.
- */
-struct tomoyo_domain_initializer_entry {
-       struct tomoyo_acl_head head;
-       bool is_not;       /* True if this entry is "no_initialize_domain".  */
-       /* True if the domainname is tomoyo_get_last_name(). */
-       bool is_last_name;
-       const struct tomoyo_path_info *domainname;    /* This may be NULL */
-       const struct tomoyo_path_info *program;
-};
-
-/*
- * tomoyo_domain_keeper_entry is a structure which is used for holding
- * "keep_domain" and "no_keep_domain" entries.
- * It has following fields.
- *
- *  (1) "head" is "struct tomoyo_acl_head".
- *  (2) "is_not" is a bool which is true if "no_initialize_domain", false
- *      otherwise.
+ *  (2) "type" is type of this entry.
  *  (3) "is_last_name" is a bool which is true if "domainname" is "the last
  *      component of a domainname", false otherwise.
  *  (4) "domainname" which is "a domainname" or "the last component of a
  *      domainname".
  *  (5) "program" which is a program's pathname.
- *      This field is NULL if "from" clause is not specified.
  */
-struct tomoyo_domain_keeper_entry {
+struct tomoyo_transition_control {
        struct tomoyo_acl_head head;
-       bool is_not;       /* True if this entry is "no_keep_domain".        */
+       u8 type; /* One of values in "enum tomoyo_transition_type".  */
        /* True if the domainname is tomoyo_get_last_name(). */
        bool is_last_name;
-       const struct tomoyo_path_info *domainname;
-       const struct tomoyo_path_info *program;       /* This may be NULL */
+       const struct tomoyo_path_info *domainname; /* Maybe NULL */
+       const struct tomoyo_path_info *program;    /* Maybe NULL */
 };
 
 /*
@@ -793,15 +777,8 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, char *type,
                            unsigned long flags, void *data_page);
 /* Create "aggregator" entry in exception policy. */
 int tomoyo_write_aggregator_policy(char *data, const bool is_delete);
-/*
- * Create "initialize_domain" and "no_initialize_domain" entry
- * in exception policy.
- */
-int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
-                                          const bool is_delete);
-/* Create "keep_domain" and "no_keep_domain" entry in exception policy. */
-int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
-                                     const bool is_delete);
+int tomoyo_write_transition_control(char *data, const bool is_delete,
+                                   const u8 type);
 /*
  * Create "allow_read/write", "allow_execute", "allow_read", "allow_write",
  * "allow_create", "allow_unlink", "allow_mkdir", "allow_rmdir",
@@ -922,6 +899,7 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
 void tomoyo_check_acl(struct tomoyo_request_info *r,
                      bool (*check_entry) (const struct tomoyo_request_info *,
                                           const struct tomoyo_acl_info *));
+const char *tomoyo_last_word(const char *name);
 
 /********** External variable definitions. **********/
 
index 273e670..05450b1 100644 (file)
@@ -150,59 +150,60 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain)
        return cp0;
 }
 
-static bool tomoyo_same_domain_initializer_entry(const struct tomoyo_acl_head *
+static bool tomoyo_same_transition_control_entry(const struct tomoyo_acl_head *
                                                 a,
                                                 const struct tomoyo_acl_head *
                                                 b)
 {
-       const struct tomoyo_domain_initializer_entry *p1 =
-               container_of(a, typeof(*p1), head);
-       const struct tomoyo_domain_initializer_entry *p2 =
-               container_of(b, typeof(*p2), head);
-       return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
+       const struct tomoyo_transition_control *p1 = container_of(a,
+                                                                 typeof(*p1),
+                                                                 head);
+       const struct tomoyo_transition_control *p2 = container_of(b,
+                                                                 typeof(*p2),
+                                                                 head);
+       return p1->type == p2->type && p1->is_last_name == p2->is_last_name
                && p1->domainname == p2->domainname
                && p1->program == p2->program;
 }
 
 /**
- * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list.
+ * tomoyo_update_transition_control_entry - Update "struct tomoyo_transition_control" list.
  *
- * @domainname: The name of domain. May be NULL.
- * @program:    The name of program.
- * @is_not:     True if it is "no_initialize_domain" entry.
+ * @domainname: The name of domain. Maybe NULL.
+ * @program:    The name of program. Maybe NULL.
+ * @type:       Type of transition.
  * @is_delete:  True if it is a delete request.
  *
  * Returns 0 on success, negative value otherwise.
- *
- * Caller holds tomoyo_read_lock().
  */
-static int tomoyo_update_domain_initializer_entry(const char *domainname,
+static int tomoyo_update_transition_control_entry(const char *domainname,
                                                  const char *program,
-                                                 const bool is_not,
+                                                 const u8 type,
                                                  const bool is_delete)
 {
-       struct tomoyo_domain_initializer_entry e = { .is_not = is_not };
+       struct tomoyo_transition_control e = { .type = type };
        int error = is_delete ? -ENOENT : -ENOMEM;
-
-       if (!tomoyo_correct_path(program))
-               return -EINVAL;
+       if (program) {
+               if (!tomoyo_correct_path(program))
+                       return -EINVAL;
+               e.program = tomoyo_get_name(program);
+               if (!e.program)
+                       goto out;
+       }
        if (domainname) {
-               if (!tomoyo_domain_def(domainname) &&
-                   tomoyo_correct_path(domainname))
+               if (!tomoyo_correct_domain(domainname)) {
+                       if (!tomoyo_correct_path(domainname))
+                               goto out;
                        e.is_last_name = true;
-               else if (!tomoyo_correct_domain(domainname))
-                       return -EINVAL;
+               }
                e.domainname = tomoyo_get_name(domainname);
                if (!e.domainname)
                        goto out;
        }
-       e.program = tomoyo_get_name(program);
-       if (!e.program)
-               goto out;
        error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
                                     &tomoyo_policy_list
-                                    [TOMOYO_ID_DOMAIN_INITIALIZER],
-                                    tomoyo_same_domain_initializer_entry);
+                                    [TOMOYO_ID_TRANSITION_CONTROL],
+                                    tomoyo_same_transition_control_entry);
  out:
        tomoyo_put_name(e.domainname);
        tomoyo_put_name(e.program);
@@ -210,195 +211,85 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
 }
 
 /**
- * tomoyo_write_domain_initializer_policy - Write "struct tomoyo_domain_initializer_entry" list.
+ * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
  *
  * @data:      String to parse.
- * @is_not:    True if it is "no_initialize_domain" entry.
  * @is_delete: True if it is a delete request.
+ * @type:      Type of this entry.
  *
  * Returns 0 on success, negative value otherwise.
- *
- * Caller holds tomoyo_read_lock().
  */
-int tomoyo_write_domain_initializer_policy(char *data, const bool is_not,
-                                          const bool is_delete)
+int tomoyo_write_transition_control(char *data, const bool is_delete,
+                                   const u8 type)
 {
-       char *cp = strstr(data, " from ");
-
-       if (cp) {
-               *cp = '\0';
-               return tomoyo_update_domain_initializer_entry(cp + 6, data,
-                                                             is_not,
-                                                             is_delete);
+       char *domainname = strstr(data, " from ");
+       if (domainname) {
+               *domainname = '\0';
+               domainname += 6;
+       } else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
+                  type == TOMOYO_TRANSITION_CONTROL_KEEP) {
+               domainname = data;
+               data = NULL;
        }
-       return tomoyo_update_domain_initializer_entry(NULL, data, is_not,
+       return tomoyo_update_transition_control_entry(domainname, data, type,
                                                      is_delete);
 }
 
 /**
- * tomoyo_domain_initializer - Check whether the given program causes domainname reinitialization.
+ * tomoyo_transition_type - Get domain transition type.
  *
  * @domainname: The name of domain.
  * @program:    The name of program.
- * @last_name:  The last component of @domainname.
  *
- * Returns true if executing @program reinitializes domain transition,
- * false otherwise.
+ * Returns TOMOYO_TRANSITION_CONTROL_INITIALIZE if executing @program
+ * reinitializes domain transition, TOMOYO_TRANSITION_CONTROL_KEEP if executing
+ * @program suppresses domain transition, others otherwise.
  *
  * Caller holds tomoyo_read_lock().
  */
-static bool tomoyo_domain_initializer(const struct tomoyo_path_info *
-                                        domainname,
-                                        const struct tomoyo_path_info *program,
-                                        const struct tomoyo_path_info *
-                                        last_name)
+static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname,
+                                const struct tomoyo_path_info *program)
 {
-       struct tomoyo_domain_initializer_entry *ptr;
-       bool flag = false;
-
-       list_for_each_entry_rcu(ptr, &tomoyo_policy_list
-                               [TOMOYO_ID_DOMAIN_INITIALIZER], head.list) {
-               if (ptr->head.is_deleted)
-                       continue;
-               if (ptr->domainname) {
-                       if (!ptr->is_last_name) {
-                               if (ptr->domainname != domainname)
-                                       continue;
-                       } else {
-                               if (tomoyo_pathcmp(ptr->domainname, last_name))
-                                       continue;
-                       }
-               }
-               if (tomoyo_pathcmp(ptr->program, program))
-                       continue;
-               if (ptr->is_not) {
-                       flag = false;
-                       break;
-               }
-               flag = true;
-       }
-       return flag;
-}
-
-static bool tomoyo_same_domain_keeper_entry(const struct tomoyo_acl_head *a,
-                                           const struct tomoyo_acl_head *b)
-{
-       const struct tomoyo_domain_keeper_entry *p1 =
-               container_of(a, typeof(*p1), head);
-       const struct tomoyo_domain_keeper_entry *p2 =
-               container_of(b, typeof(*p2), head);
-       return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
-               && p1->domainname == p2->domainname
-               && p1->program == p2->program;
-}
-
-/**
- * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list.
- *
- * @domainname: The name of domain.
- * @program:    The name of program. May be NULL.
- * @is_not:     True if it is "no_keep_domain" entry.
- * @is_delete:  True if it is a delete request.
- *
- * Returns 0 on success, negative value otherwise.
- *
- * Caller holds tomoyo_read_lock().
- */
-static int tomoyo_update_domain_keeper_entry(const char *domainname,
-                                            const char *program,
-                                            const bool is_not,
-                                            const bool is_delete)
-{
-       struct tomoyo_domain_keeper_entry e = { .is_not = is_not };
-       int error = is_delete ? -ENOENT : -ENOMEM;
-
-       if (!tomoyo_domain_def(domainname) &&
-           tomoyo_correct_path(domainname))
-               e.is_last_name = true;
-       else if (!tomoyo_correct_domain(domainname))
-               return -EINVAL;
-       if (program) {
-               if (!tomoyo_correct_path(program))
-                       return -EINVAL;
-               e.program = tomoyo_get_name(program);
-               if (!e.program)
-                       goto out;
-       }
-       e.domainname = tomoyo_get_name(domainname);
-       if (!e.domainname)
-               goto out;
-       error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
-                                    &tomoyo_policy_list
-                                    [TOMOYO_ID_DOMAIN_KEEPER],
-                                    tomoyo_same_domain_keeper_entry);
- out:
-       tomoyo_put_name(e.domainname);
-       tomoyo_put_name(e.program);
-       return error;
-}
-
-/**
- * tomoyo_write_domain_keeper_policy - Write "struct tomoyo_domain_keeper_entry" list.
- *
- * @data:      String to parse.
- * @is_not:    True if it is "no_keep_domain" entry.
- * @is_delete: True if it is a delete request.
- *
- * Caller holds tomoyo_read_lock().
- */
-int tomoyo_write_domain_keeper_policy(char *data, const bool is_not,
-                                     const bool is_delete)
-{
-       char *cp = strstr(data, " from ");
-
-       if (cp) {
-               *cp = '\0';
-               return tomoyo_update_domain_keeper_entry(cp + 6, data, is_not,
-                                                        is_delete);
-       }
-       return tomoyo_update_domain_keeper_entry(data, NULL, is_not, is_delete);
-}
-
-/**
- * tomoyo_domain_keeper - Check whether the given program causes domain transition suppression.
- *
- * @domainname: The name of domain.
- * @program:    The name of program.
- * @last_name:  The last component of @domainname.
- *
- * Returns true if executing @program supresses domain transition,
- * false otherwise.
- *
- * Caller holds tomoyo_read_lock().
- */
-static bool tomoyo_domain_keeper(const struct tomoyo_path_info *domainname,
-                                   const struct tomoyo_path_info *program,
-                                   const struct tomoyo_path_info *last_name)
-{
-       struct tomoyo_domain_keeper_entry *ptr;
-       bool flag = false;
-
-       list_for_each_entry_rcu(ptr,
-                               &tomoyo_policy_list[TOMOYO_ID_DOMAIN_KEEPER],
-                               head.list) {
-               if (ptr->head.is_deleted)
-                       continue;
-               if (!ptr->is_last_name) {
-                       if (ptr->domainname != domainname)
+       const struct tomoyo_transition_control *ptr;
+       const char *last_name = tomoyo_last_word(domainname->name);
+       u8 type;
+       for (type = 0; type < TOMOYO_MAX_TRANSITION_TYPE; type++) {
+ next:
+               list_for_each_entry_rcu(ptr, &tomoyo_policy_list
+                                       [TOMOYO_ID_TRANSITION_CONTROL],
+                                       head.list) {
+                       if (ptr->head.is_deleted || ptr->type != type)
                                continue;
-               } else {
-                       if (tomoyo_pathcmp(ptr->domainname, last_name))
+                       if (ptr->domainname) {
+                               if (!ptr->is_last_name) {
+                                       if (ptr->domainname != domainname)
+                                               continue;
+                               } else {
+                                       /*
+                                        * Use direct strcmp() since this is
+                                        * unlikely used.
+                                        */
+                                       if (strcmp(ptr->domainname->name,
+                                                  last_name))
+                                               continue;
+                               }
+                       }
+                       if (ptr->program &&
+                           tomoyo_pathcmp(ptr->program, program))
                                continue;
+                       if (type == TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE) {
+                               /*
+                                * Do not check for initialize_domain if
+                                * no_initialize_domain matched.
+                                */
+                               type = TOMOYO_TRANSITION_CONTROL_NO_KEEP;
+                               goto next;
+                       }
+                       goto done;
                }
-               if (ptr->program && tomoyo_pathcmp(ptr->program, program))
-                       continue;
-               if (ptr->is_not) {
-                       flag = false;
-                       break;
-               }
-               flag = true;
        }
-       return flag;
+ done:
+       return type;
 }
 
 static bool tomoyo_same_aggregator_entry(const struct tomoyo_acl_head *a,
@@ -533,7 +424,6 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
        char *tmp = kzalloc(TOMOYO_EXEC_TMPSIZE, GFP_NOFS);
        struct tomoyo_domain_info *old_domain = tomoyo_domain();
        struct tomoyo_domain_info *domain = NULL;
-       const char *old_domain_name = old_domain->domainname->name;
        const char *original_name = bprm->filename;
        u8 mode;
        bool is_enforce;
@@ -586,25 +476,33 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
        if (retval < 0)
                goto out;
 
-       if (tomoyo_domain_initializer(old_domain->domainname, &rn, &ln)) {
+       /* Calculate domain to transit to. */
+       switch (tomoyo_transition_type(old_domain->domainname, &rn)) {
+       case TOMOYO_TRANSITION_CONTROL_INITIALIZE:
                /* Transit to the child of tomoyo_kernel_domain domain. */
-               snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1,
-                        TOMOYO_ROOT_NAME " " "%s", rn.name);
-       } else if (old_domain == &tomoyo_kernel_domain &&
-                  !tomoyo_policy_loaded) {
-               /*
-                * Needn't to transit from kernel domain before starting
-                * /sbin/init. But transit from kernel domain if executing
-                * initializers because they might start before /sbin/init.
-                */
-               domain = old_domain;
-       } else if (tomoyo_domain_keeper(old_domain->domainname, &rn, &ln)) {
+               snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, TOMOYO_ROOT_NAME " "
+                        "%s", rn.name);
+               break;
+       case TOMOYO_TRANSITION_CONTROL_KEEP:
                /* Keep current domain. */
                domain = old_domain;
-       } else {
-               /* Normal domain transition. */
-               snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1,
-                        "%s %s", old_domain_name, rn.name);
+               break;
+       default:
+               if (old_domain == &tomoyo_kernel_domain &&
+                   !tomoyo_policy_loaded) {
+                       /*
+                        * Needn't to transit from kernel domain before
+                        * starting /sbin/init. But transit from kernel domain
+                        * if executing initializers because they might start
+                        * before /sbin/init.
+                        */
+                       domain = old_domain;
+               } else {
+                       /* Normal domain transition. */
+                       snprintf(tmp, TOMOYO_EXEC_TMPSIZE - 1, "%s %s",
+                                old_domain->domainname->name, rn.name);
+               }
+               break;
        }
        if (domain || strlen(tmp) >= TOMOYO_EXEC_TMPSIZE - 10)
                goto done;
index 4d4ba84..254ac11 100644 (file)
@@ -53,17 +53,9 @@ static void tomoyo_del_no_rewrite(struct list_head *element)
        tomoyo_put_name(ptr->pattern);
 }
 
-static void tomoyo_del_domain_initializer(struct list_head *element)
+static void tomoyo_del_transition_control(struct list_head *element)
 {
-       struct tomoyo_domain_initializer_entry *ptr =
-               container_of(element, typeof(*ptr), head.list);
-       tomoyo_put_name(ptr->domainname);
-       tomoyo_put_name(ptr->program);
-}
-
-static void tomoyo_del_domain_keeper(struct list_head *element)
-{
-       struct tomoyo_domain_keeper_entry *ptr =
+       struct tomoyo_transition_control *ptr =
                container_of(element, typeof(*ptr), head.list);
        tomoyo_put_name(ptr->domainname);
        tomoyo_put_name(ptr->program);
@@ -292,11 +284,8 @@ static void tomoyo_kfree_entry(void)
        list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) {
                struct list_head *element = p->element;
                switch (p->type) {
-               case TOMOYO_ID_DOMAIN_INITIALIZER:
-                       tomoyo_del_domain_initializer(element);
-                       break;
-               case TOMOYO_ID_DOMAIN_KEEPER:
-                       tomoyo_del_domain_keeper(element);
+               case TOMOYO_ID_TRANSITION_CONTROL:
+                       tomoyo_del_transition_control(element);
                        break;
                case TOMOYO_ID_AGGREGATOR:
                        tomoyo_del_aggregator(element);
index a1d75df..95a7759 100644 (file)
@@ -211,10 +211,10 @@ void __init tomoyo_mm_init(void)
                panic("Can't register tomoyo_kernel_domain");
        {
                /* Load built-in policy. */
-               tomoyo_write_domain_initializer_policy("/sbin/hotplug",
-                                                      false, false);
-               tomoyo_write_domain_initializer_policy("/sbin/modprobe",
-                                                      false, false);
+               tomoyo_write_transition_control("/sbin/hotplug", false,
+                                       TOMOYO_TRANSITION_CONTROL_INITIALIZE);
+               tomoyo_write_transition_control("/sbin/modprobe", false,
+                                       TOMOYO_TRANSITION_CONTROL_INITIALIZE);
        }
        tomoyo_read_unlock(idx);
 }
index 20abba2..12a768e 100644 (file)
@@ -844,7 +844,7 @@ int tomoyo_init_request_info(struct tomoyo_request_info *r,
  *
  * Returns the last word of a line.
  */
-static const char *tomoyo_last_word(const char *name)
+const char *tomoyo_last_word(const char *name)
 {
        const char *cp = strrchr(name, ' ');
        if (cp)