diff options
Diffstat (limited to 'security/tomoyo/realpath.c')
-rw-r--r-- | security/tomoyo/realpath.c | 136 |
1 files changed, 37 insertions, 99 deletions
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 18369d497eb8..54226d5be493 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c @@ -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. */ |