Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/ipvs-2.6
[pandora-kernel.git] / security / tomoyo / gc.c
index 1e1a6c8..ae135fb 100644 (file)
@@ -1,10 +1,7 @@
 /*
  * security/tomoyo/gc.c
  *
- * Implementation of the Domain-Based Mandatory Access Control.
- *
- * Copyright (C) 2005-2010  NTT DATA CORPORATION
- *
+ * Copyright (C) 2005-2011  NTT DATA CORPORATION
  */
 
 #include "common.h"
@@ -25,6 +22,7 @@ static const u8 tomoyo_element_size[TOMOYO_MAX_POLICY] = {
        [TOMOYO_ID_TRANSITION_CONTROL] =
        sizeof(struct tomoyo_transition_control),
        [TOMOYO_ID_MANAGER] = sizeof(struct tomoyo_manager),
+       /* [TOMOYO_ID_CONDITION] = "struct tomoyo_condition"->size, */
        /* [TOMOYO_ID_NAME] = "struct tomoyo_name"->size, */
        /* [TOMOYO_ID_ACL] =
           tomoyo_acl_size["struct tomoyo_acl_info"->type], */
@@ -162,6 +160,10 @@ static bool tomoyo_add_to_gc(const int type, struct list_head *element)
                entry->size = strlen(container_of(element,
                                                  typeof(struct tomoyo_name),
                                                  head.list)->entry.name) + 1;
+       else if (type == TOMOYO_ID_CONDITION)
+               entry->size =
+                       container_of(element, typeof(struct tomoyo_condition),
+                                    head.list)->size;
        else
                entry->size = tomoyo_element_size[type];
        entry->element = element;
@@ -246,6 +248,7 @@ static void tomoyo_del_acl(struct list_head *element)
 {
        struct tomoyo_acl_info *acl =
                container_of(element, typeof(*acl), list);
+       tomoyo_put_condition(acl->cond);
        switch (acl->type) {
        case TOMOYO_TYPE_PATH_ACL:
                {
@@ -338,6 +341,44 @@ static bool tomoyo_del_domain(struct list_head *element)
        return true;
 }
 
+/**
+ * tomoyo_del_condition - Delete members in "struct tomoyo_condition".
+ *
+ * @element: Pointer to "struct list_head".
+ *
+ * Returns nothing.
+ */
+void tomoyo_del_condition(struct list_head *element)
+{
+       struct tomoyo_condition *cond = container_of(element, typeof(*cond),
+                                                    head.list);
+       const u16 condc = cond->condc;
+       const u16 numbers_count = cond->numbers_count;
+       const u16 names_count = cond->names_count;
+       const u16 argc = cond->argc;
+       const u16 envc = cond->envc;
+       unsigned int i;
+       const struct tomoyo_condition_element *condp
+               = (const struct tomoyo_condition_element *) (cond + 1);
+       struct tomoyo_number_union *numbers_p
+               = (struct tomoyo_number_union *) (condp + condc);
+       struct tomoyo_name_union *names_p
+               = (struct tomoyo_name_union *) (numbers_p + numbers_count);
+       const struct tomoyo_argv *argv
+               = (const struct tomoyo_argv *) (names_p + names_count);
+       const struct tomoyo_envp *envp
+               = (const struct tomoyo_envp *) (argv + argc);
+       for (i = 0; i < numbers_count; i++)
+               tomoyo_put_number_union(numbers_p++);
+       for (i = 0; i < names_count; i++)
+               tomoyo_put_name_union(names_p++);
+       for (i = 0; i < argc; argv++, i++)
+               tomoyo_put_name(argv->value);
+       for (i = 0; i < envc; envp++, i++) {
+               tomoyo_put_name(envp->name);
+               tomoyo_put_name(envp->value);
+       }
+}
 
 /**
  * tomoyo_del_name - Delete members in "struct tomoyo_name".
@@ -411,7 +452,7 @@ static bool tomoyo_collect_member(const enum tomoyo_policy_id id,
                if (!tomoyo_add_to_gc(id, &member->list))
                        return false;
        }
-        return true;
+       return true;
 }
 
 /**
@@ -494,15 +535,18 @@ static void tomoyo_collect_entry(void)
                        }
                }
        }
-       for (i = 0; i < TOMOYO_MAX_HASH; i++) {
-               struct list_head *list = &tomoyo_name_list[i];
+       id = TOMOYO_ID_CONDITION;
+       for (i = 0; i < TOMOYO_MAX_HASH + 1; i++) {
+               struct list_head *list = !i ?
+                       &tomoyo_condition_list : &tomoyo_name_list[i - 1];
                struct tomoyo_shared_acl_head *ptr;
                list_for_each_entry(ptr, list, list) {
                        if (atomic_read(&ptr->users))
                                continue;
-                       if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list))
+                       if (!tomoyo_add_to_gc(id, &ptr->list))
                                goto unlock;
                }
+               id = TOMOYO_ID_NAME;
        }
 unlock:
        tomoyo_read_unlock(idx);
@@ -557,6 +601,9 @@ static bool tomoyo_kfree_entry(void)
                case TOMOYO_ID_MANAGER:
                        tomoyo_del_manager(element);
                        break;
+               case TOMOYO_ID_CONDITION:
+                       tomoyo_del_condition(element);
+                       break;
                case TOMOYO_ID_NAME:
                        /*
                         * Thirdly, defer until all "struct tomoyo_io_buffer"