]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - security/tomoyo/common.c
TOMOYO: Add refcounter on string data.
[net-next-2.6.git] / security / tomoyo / common.c
index 642e0e565dfcdf7516952a6e5fa2f081d03460e7..0c7ea51e7a4521684081402be1d759ae3355b2bd 100644 (file)
@@ -12,8 +12,8 @@
 #include <linux/uaccess.h>
 #include <linux/security.h>
 #include <linux/hardirq.h>
-#include "realpath.h"
 #include "common.h"
+#include "realpath.h"
 #include "tomoyo.h"
 
 /* Lock for protecting policy. */
@@ -750,7 +750,7 @@ bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...)
  *
  * Returns the tomoyo_realpath() of current process on success, NULL otherwise.
  *
- * This function uses tomoyo_alloc(), so the caller must call tomoyo_free()
+ * This function uses kzalloc(), so the caller must call kfree()
  * if this function didn't return NULL.
  */
 static const char *tomoyo_get_exe(void)
@@ -842,9 +842,7 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain)
        if (!domain)
                return true;
        list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
-               if (ptr->type & TOMOYO_ACL_DELETED)
-                       continue;
-               switch (tomoyo_acl_type2(ptr)) {
+               switch (ptr->type) {
                        struct tomoyo_single_path_acl_record *acl;
                        u32 perm;
                        u8 i;
@@ -900,9 +898,11 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned
        ptr = tomoyo_profile_ptr[profile];
        if (ptr)
                goto ok;
-       ptr = tomoyo_alloc_element(sizeof(*ptr));
-       if (!ptr)
+       ptr = kmalloc(sizeof(*ptr), GFP_KERNEL);
+       if (!tomoyo_memory_ok(ptr)) {
+               kfree(ptr);
                goto ok;
+       }
        for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++)
                ptr->value[i] = tomoyo_control_array[i].current_value;
        mb(); /* Avoid out-of-order execution. */
@@ -943,7 +943,9 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
                return -EINVAL;
        *cp = '\0';
        if (!strcmp(data, "COMMENT")) {
-               profile->comment = tomoyo_save_name(cp + 1);
+               const struct tomoyo_path_info *old_comment = profile->comment;
+               profile->comment = tomoyo_get_name(cp + 1);
+               tomoyo_put_name(old_comment);
                return 0;
        }
        for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) {
@@ -1103,10 +1105,10 @@ static LIST_HEAD(tomoyo_policy_manager_list);
 static int tomoyo_update_manager_entry(const char *manager,
                                       const bool is_delete)
 {
-       struct tomoyo_policy_manager_entry *new_entry;
+       struct tomoyo_policy_manager_entry *entry = NULL;
        struct tomoyo_policy_manager_entry *ptr;
        const struct tomoyo_path_info *saved_manager;
-       int error = -ENOMEM;
+       int error = is_delete ? -ENOENT : -ENOMEM;
        bool is_domain = false;
 
        if (tomoyo_is_domain_def(manager)) {
@@ -1117,30 +1119,30 @@ static int tomoyo_update_manager_entry(const char *manager,
                if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__))
                        return -EINVAL;
        }
-       saved_manager = tomoyo_save_name(manager);
+       saved_manager = tomoyo_get_name(manager);
        if (!saved_manager)
                return -ENOMEM;
+       if (!is_delete)
+               entry = kmalloc(sizeof(*entry), GFP_KERNEL);
        mutex_lock(&tomoyo_policy_lock);
        list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
                if (ptr->manager != saved_manager)
                        continue;
                ptr->is_deleted = is_delete;
                error = 0;
-               goto out;
+               break;
        }
-       if (is_delete) {
-               error = -ENOENT;
-               goto out;
+       if (!is_delete && error && tomoyo_memory_ok(entry)) {
+               entry->manager = saved_manager;
+               saved_manager = NULL;
+               entry->is_domain = is_domain;
+               list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list);
+               entry = NULL;
+               error = 0;
        }
-       new_entry = tomoyo_alloc_element(sizeof(*new_entry));
-       if (!new_entry)
-               goto out;
-       new_entry->manager = saved_manager;
-       new_entry->is_domain = is_domain;
-       list_add_tail_rcu(&new_entry->list, &tomoyo_policy_manager_list);
-       error = 0;
- out:
        mutex_unlock(&tomoyo_policy_lock);
+       tomoyo_put_name(saved_manager);
+       kfree(entry);
        return error;
 }
 
@@ -1244,7 +1246,7 @@ static bool tomoyo_is_policy_manager(void)
                        last_pid = pid;
                }
        }
-       tomoyo_free(exe);
+       kfree(exe);
        return found;
 }
 
@@ -1380,8 +1382,7 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head)
                return 0;
        }
        if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
-               tomoyo_set_domain_flag(domain, is_delete,
-                              TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ);
+               domain->ignore_global_allow_read = !is_delete;
                return 0;
        }
        return tomoyo_write_file_policy(data, domain, is_delete);
@@ -1482,10 +1483,8 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head,
 static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
                               struct tomoyo_acl_info *ptr)
 {
-       const u8 acl_type = tomoyo_acl_type2(ptr);
+       const u8 acl_type = ptr->type;
 
-       if (acl_type & TOMOYO_ACL_DELETED)
-               return true;
        if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) {
                struct tomoyo_single_path_acl_record *acl
                        = container_of(ptr,
@@ -1536,10 +1535,9 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
                /* Print domainname and flags. */
                if (domain->quota_warned)
                        quota_exceeded = "quota_exceeded\n";
-               if (domain->flags & TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED)
+               if (domain->transition_failed)
                        transition_failed = "transition_failed\n";
-               if (domain->flags &
-                   TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ)
+               if (domain->ignore_global_allow_read)
                        ignore_global_allow_read
                                = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
                done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE
@@ -1927,7 +1925,7 @@ static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
  */
 static int tomoyo_open_control(const u8 type, struct file *file)
 {
-       struct tomoyo_io_buffer *head = tomoyo_alloc(sizeof(*head));
+       struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL);
 
        if (!head)
                return -ENOMEM;
@@ -1988,9 +1986,9 @@ static int tomoyo_open_control(const u8 type, struct file *file)
        } else {
                if (!head->readbuf_size)
                        head->readbuf_size = 4096 * 2;
-               head->read_buf = tomoyo_alloc(head->readbuf_size);
+               head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);
                if (!head->read_buf) {
-                       tomoyo_free(head);
+                       kfree(head);
                        return -ENOMEM;
                }
        }
@@ -2002,10 +2000,10 @@ static int tomoyo_open_control(const u8 type, struct file *file)
                head->write = NULL;
        } else if (head->write) {
                head->writebuf_size = 4096 * 2;
-               head->write_buf = tomoyo_alloc(head->writebuf_size);
+               head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);
                if (!head->write_buf) {
-                       tomoyo_free(head->read_buf);
-                       tomoyo_free(head);
+                       kfree(head->read_buf);
+                       kfree(head);
                        return -ENOMEM;
                }
        }
@@ -2137,45 +2135,16 @@ static int tomoyo_close_control(struct file *file)
 
        tomoyo_read_unlock(head->reader_idx);
        /* Release memory used for policy I/O. */
-       tomoyo_free(head->read_buf);
+       kfree(head->read_buf);
        head->read_buf = NULL;
-       tomoyo_free(head->write_buf);
+       kfree(head->write_buf);
        head->write_buf = NULL;
-       tomoyo_free(head);
+       kfree(head);
        head = NULL;
        file->private_data = NULL;
        return 0;
 }
 
-/**
- * tomoyo_alloc_acl_element - Allocate permanent memory for ACL entry.
- *
- * @acl_type:  Type of ACL entry.
- *
- * Returns pointer to the ACL entry on success, NULL otherwise.
- */
-void *tomoyo_alloc_acl_element(const u8 acl_type)
-{
-       int len;
-       struct tomoyo_acl_info *ptr;
-
-       switch (acl_type) {
-       case TOMOYO_TYPE_SINGLE_PATH_ACL:
-               len = sizeof(struct tomoyo_single_path_acl_record);
-               break;
-       case TOMOYO_TYPE_DOUBLE_PATH_ACL:
-               len = sizeof(struct tomoyo_double_path_acl_record);
-               break;
-       default:
-               return NULL;
-       }
-       ptr = tomoyo_alloc_element(len);
-       if (!ptr)
-               return NULL;
-       ptr->type = acl_type;
-       return ptr;
-}
-
 /**
  * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface.
  *