]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - security/tomoyo/realpath.c
TOMOYO: Remove memory pool for list elements.
[net-next-2.6.git] / security / tomoyo / realpath.c
index 18369d497eb80116da1d146ddc49268ae0b07229..54226d5be493100025d962673d5ceae630c62838 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/mnt_namespace.h>
 #include <linux/fs_struct.h>
 #include <linux/hash.h>
+#include <linux/magic.h>
 
 #include "common.h"
 #include "realpath.h"
@@ -112,7 +113,7 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname,
                path_put(&ns_root);
                /* Prepend "/proc" prefix if using internal proc vfs mount. */
                if (!IS_ERR(sp) && (path->mnt->mnt_parent == path->mnt) &&
-                   (strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0)) {
+                   (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
                        sp -= 5;
                        if (sp >= newname)
                                memcpy(sp, "/proc", 5);
@@ -211,57 +212,32 @@ static unsigned int tomoyo_allocated_memory_for_elements;
 static unsigned int tomoyo_quota_for_elements;
 
 /**
- * tomoyo_alloc_element - Allocate permanent memory for structures.
+ * tomoyo_memory_ok - Check memory quota.
  *
- * @size: Size in bytes.
+ * @ptr: Pointer to allocated memory.
  *
- * Returns pointer to allocated memory on success, NULL otherwise.
+ * Returns true on success, false otherwise.
  *
- * Memory has to be zeroed.
- * The RAM is chunked, so NEVER try to kfree() the returned pointer.
+ * Caller holds tomoyo_policy_lock.
+ * Memory pointed by @ptr will be zeroed on success.
  */
-void *tomoyo_alloc_element(const unsigned int size)
+bool tomoyo_memory_ok(void *ptr)
 {
-       static char *buf;
-       static DEFINE_MUTEX(lock);
-       static unsigned int buf_used_len = PATH_MAX;
-       char *ptr = NULL;
-       /*Assumes sizeof(void *) >= sizeof(long) is true. */
-       const unsigned int word_aligned_size
-               = roundup(size, max(sizeof(void *), sizeof(long)));
-       if (word_aligned_size > PATH_MAX)
-               return NULL;
-       mutex_lock(&lock);
-       if (buf_used_len + word_aligned_size > PATH_MAX) {
-               if (!tomoyo_quota_for_elements ||
-                   tomoyo_allocated_memory_for_elements
-                   + PATH_MAX <= tomoyo_quota_for_elements)
-                       ptr = kzalloc(PATH_MAX, GFP_KERNEL);
-               if (!ptr) {
-                       printk(KERN_WARNING "ERROR: Out of memory "
-                              "for tomoyo_alloc_element().\n");
-                       if (!tomoyo_policy_loaded)
-                               panic("MAC Initialization failed.\n");
-               } else {
-                       buf = ptr;
-                       tomoyo_allocated_memory_for_elements += PATH_MAX;
-                       buf_used_len = word_aligned_size;
-                       ptr = buf;
-               }
-       } else if (word_aligned_size) {
-               int i;
-               ptr = buf + buf_used_len;
-               buf_used_len += word_aligned_size;
-               for (i = 0; i < word_aligned_size; i++) {
-                       if (!ptr[i])
-                               continue;
-                       printk(KERN_ERR "WARNING: Reserved memory was tainted! "
-                              "The system might go wrong.\n");
-                       ptr[i] = '\0';
-               }
+       int allocated_len = ptr ? ksize(ptr) : 0;
+       bool result = false;
+       if (!ptr || (tomoyo_quota_for_elements &&
+                    tomoyo_allocated_memory_for_elements
+                    + allocated_len > tomoyo_quota_for_elements)) {
+               printk(KERN_WARNING "ERROR: Out of memory "
+                      "for tomoyo_alloc_element().\n");
+               if (!tomoyo_policy_loaded)
+                       panic("MAC Initialization failed.\n");
+       } else {
+               result = true;
+               tomoyo_allocated_memory_for_elements += allocated_len;
+               memset(ptr, 0, allocated_len);
        }
-       mutex_unlock(&lock);
-       return ptr;
+       return result;
 }
 
 /* Memory allocated for string data in bytes. */
@@ -292,13 +268,6 @@ struct tomoyo_name_entry {
        struct tomoyo_path_info entry;
 };
 
-/* Structure for available memory region. */
-struct tomoyo_free_memory_block_list {
-       struct list_head list;
-       char *ptr;             /* Pointer to a free area. */
-       int len;               /* Length of the area.     */
-};
-
 /*
  * tomoyo_name_list is used for holding string data used by TOMOYO.
  * Since same string data is likely used for multiple times (e.g.
@@ -313,52 +282,32 @@ static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
  * @name: The string to store into the permernent memory.
  *
  * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
- *
- * The RAM is shared, so NEVER try to modify or kfree() the returned name.
  */
 const struct tomoyo_path_info *tomoyo_save_name(const char *name)
 {
-       static LIST_HEAD(fmb_list);
        static DEFINE_MUTEX(lock);
        struct tomoyo_name_entry *ptr;
        unsigned int hash;
-       /* fmb contains available size in bytes.
-          fmb is removed from the fmb_list when fmb->len becomes 0. */
-       struct tomoyo_free_memory_block_list *fmb;
        int len;
-       char *cp;
+       int allocated_len;
        struct list_head *head;
 
        if (!name)
                return NULL;
        len = strlen(name) + 1;
-       if (len > TOMOYO_MAX_PATHNAME_LEN) {
-               printk(KERN_WARNING "ERROR: Name too long "
-                      "for tomoyo_save_name().\n");
-               return NULL;
-       }
        hash = full_name_hash((const unsigned char *) name, len - 1);
        head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
-
        mutex_lock(&lock);
        list_for_each_entry(ptr, head, list) {
                if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name))
                        goto out;
        }
-       list_for_each_entry(fmb, &fmb_list, list) {
-               if (len <= fmb->len)
-                       goto ready;
-       }
-       if (!tomoyo_quota_for_savename ||
-           tomoyo_allocated_memory_for_savename + PATH_MAX
-           <= tomoyo_quota_for_savename)
-               cp = kzalloc(PATH_MAX, GFP_KERNEL);
-       else
-               cp = NULL;
-       fmb = kzalloc(sizeof(*fmb), GFP_KERNEL);
-       if (!cp || !fmb) {
-               kfree(cp);
-               kfree(fmb);
+       ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL);
+       allocated_len = ptr ? ksize(ptr) : 0;
+       if (!ptr || (tomoyo_quota_for_savename &&
+                    tomoyo_allocated_memory_for_savename + allocated_len
+                    > tomoyo_quota_for_savename)) {
+               kfree(ptr);
                printk(KERN_WARNING "ERROR: Out of memory "
                       "for tomoyo_save_name().\n");
                if (!tomoyo_policy_loaded)
@@ -366,24 +315,11 @@ const struct tomoyo_path_info *tomoyo_save_name(const char *name)
                ptr = NULL;
                goto out;
        }
-       tomoyo_allocated_memory_for_savename += PATH_MAX;
-       list_add(&fmb->list, &fmb_list);
-       fmb->ptr = cp;
-       fmb->len = PATH_MAX;
- ready:
-       ptr = tomoyo_alloc_element(sizeof(*ptr));
-       if (!ptr)
-               goto out;
-       ptr->entry.name = fmb->ptr;
-       memmove(fmb->ptr, name, len);
+       tomoyo_allocated_memory_for_savename += allocated_len;
+       ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
+       memmove((char *) ptr->entry.name, name, len);
        tomoyo_fill_path_info(&ptr->entry);
-       fmb->ptr += len;
-       fmb->len -= len;
        list_add_tail(&ptr->list, head);
-       if (fmb->len == 0) {
-               list_del(&fmb->list);
-               kfree(fmb);
-       }
  out:
        mutex_unlock(&lock);
        return ptr ? &ptr->entry : NULL;
@@ -401,11 +337,13 @@ void __init tomoyo_realpath_init(void)
                INIT_LIST_HEAD(&tomoyo_name_list[i]);
        INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
        tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME);
-       list_add_tail(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
-       down_read(&tomoyo_domain_list_lock);
+       /*
+        * tomoyo_read_lock() is not needed because this function is
+        * called before the first "delete" request.
+        */
+       list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
        if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
                panic("Can't register tomoyo_kernel_domain");
-       up_read(&tomoyo_domain_list_lock);
 }
 
 /* Memory allocated for temporary purpose. */