TOMOYO: Use stack memory for pending entry.
Tetsuo Handa [Thu, 6 May 2010 03:40:02 +0000 (12:40 +0900)]
Use stack memory for pending entry to reduce kmalloc() which will be kfree()d.

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/file.c
security/tomoyo/realpath.c

index 8f34036..62e089c 100644 (file)
@@ -1071,46 +1071,42 @@ LIST_HEAD(tomoyo_policy_manager_list);
 static int tomoyo_update_manager_entry(const char *manager,
                                       const bool is_delete)
 {
-       struct tomoyo_policy_manager_entry *entry = NULL;
        struct tomoyo_policy_manager_entry *ptr;
-       const struct tomoyo_path_info *saved_manager;
+       struct tomoyo_policy_manager_entry e = { };
        int error = is_delete ? -ENOENT : -ENOMEM;
-       bool is_domain = false;
 
        if (tomoyo_is_domain_def(manager)) {
                if (!tomoyo_is_correct_domain(manager))
                        return -EINVAL;
-               is_domain = true;
+               e.is_domain = true;
        } else {
                if (!tomoyo_is_correct_path(manager, 1, -1, -1))
                        return -EINVAL;
        }
-       saved_manager = tomoyo_get_name(manager);
-       if (!saved_manager)
+       e.manager = tomoyo_get_name(manager);
+       if (!e.manager)
                return -ENOMEM;
-       if (!is_delete)
-               entry = kmalloc(sizeof(*entry), GFP_NOFS);
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                goto out;
        list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
-               if (ptr->manager != saved_manager)
+               if (ptr->manager != e.manager)
                        continue;
                ptr->is_deleted = is_delete;
                error = 0;
                break;
        }
-       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;
+       if (!is_delete && error) {
+               struct tomoyo_policy_manager_entry *entry =
+                       tomoyo_commit_ok(&e, sizeof(e));
+               if (entry) {
+                       list_add_tail_rcu(&entry->list,
+                                         &tomoyo_policy_manager_list);
+                       error = 0;
+               }
        }
        mutex_unlock(&tomoyo_policy_lock);
  out:
-       tomoyo_put_name(saved_manager);
-       kfree(entry);
+       tomoyo_put_name(e.manager);
        return error;
 }
 
index 52c9502..c95f486 100644 (file)
@@ -616,6 +616,7 @@ char *tomoyo_realpath_from_path(struct path *path);
 
 /* Check memory quota. */
 bool tomoyo_memory_ok(void *ptr);
+void *tomoyo_commit_ok(void *data, const unsigned int size);
 
 /*
  * Keep the given name on the RAM.
@@ -735,6 +736,31 @@ static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
        return task_cred_xxx(task, security);
 }
 
+static inline bool tomoyo_is_same_domain_initializer_entry
+(const struct tomoyo_domain_initializer_entry *p1,
+ const struct tomoyo_domain_initializer_entry *p2)
+{
+       return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
+               && p1->domainname == p2->domainname
+               && p1->program == p2->program;
+}
+
+static inline bool tomoyo_is_same_domain_keeper_entry
+(const struct tomoyo_domain_keeper_entry *p1,
+ const struct tomoyo_domain_keeper_entry *p2)
+{
+       return p1->is_not == p2->is_not && p1->is_last_name == p2->is_last_name
+               && p1->domainname == p2->domainname
+               && p1->program == p2->program;
+}
+
+static inline bool tomoyo_is_same_alias_entry
+(const struct tomoyo_alias_entry *p1, const struct tomoyo_alias_entry *p2)
+{
+       return p1->original_name == p2->original_name &&
+               p1->aliased_name == p2->aliased_name;
+}
+
 /**
  * list_for_each_cookie - iterate over a list with cookie.
  * @pos:        the &struct list_head to use as a loop cursor.
index a1723bb..cd8ba44 100644 (file)
@@ -130,58 +130,47 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname,
                                                  const bool is_not,
                                                  const bool is_delete)
 {
-       struct tomoyo_domain_initializer_entry *entry = NULL;
        struct tomoyo_domain_initializer_entry *ptr;
-       const struct tomoyo_path_info *saved_program = NULL;
-       const struct tomoyo_path_info *saved_domainname = NULL;
+       struct tomoyo_domain_initializer_entry e = { .is_not = is_not };
        int error = is_delete ? -ENOENT : -ENOMEM;
-       bool is_last_name = false;
 
        if (!tomoyo_is_correct_path(program, 1, -1, -1))
                return -EINVAL; /* No patterns allowed. */
        if (domainname) {
                if (!tomoyo_is_domain_def(domainname) &&
                    tomoyo_is_correct_path(domainname, 1, -1, -1))
-                       is_last_name = true;
+                       e.is_last_name = true;
                else if (!tomoyo_is_correct_domain(domainname))
                        return -EINVAL;
-               saved_domainname = tomoyo_get_name(domainname);
-               if (!saved_domainname)
+               e.domainname = tomoyo_get_name(domainname);
+               if (!e.domainname)
                        goto out;
        }
-       saved_program = tomoyo_get_name(program);
-       if (!saved_program)
+       e.program = tomoyo_get_name(program);
+       if (!e.program)
                goto out;
-       if (!is_delete)
-               entry = kmalloc(sizeof(*entry), GFP_NOFS);
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                goto out;
        list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) {
-               if (ptr->is_not != is_not ||
-                   ptr->domainname != saved_domainname ||
-                   ptr->program != saved_program)
+               if (!tomoyo_is_same_domain_initializer_entry(ptr, &e))
                        continue;
                ptr->is_deleted = is_delete;
                error = 0;
                break;
        }
-       if (!is_delete && error && tomoyo_memory_ok(entry)) {
-               entry->domainname = saved_domainname;
-               saved_domainname = NULL;
-               entry->program = saved_program;
-               saved_program = NULL;
-               entry->is_not = is_not;
-               entry->is_last_name = is_last_name;
-               list_add_tail_rcu(&entry->list,
-                                 &tomoyo_domain_initializer_list);
-               entry = NULL;
-               error = 0;
+       if (!is_delete && error) {
+               struct tomoyo_domain_initializer_entry *entry =
+                       tomoyo_commit_ok(&e, sizeof(e));
+               if (entry) {
+                       list_add_tail_rcu(&entry->list,
+                                         &tomoyo_domain_initializer_list);
+                       error = 0;
+               }
        }
        mutex_unlock(&tomoyo_policy_lock);
  out:
-       tomoyo_put_name(saved_domainname);
-       tomoyo_put_name(saved_program);
-       kfree(entry);
+       tomoyo_put_name(e.domainname);
+       tomoyo_put_name(e.program);
        return error;
 }
 
@@ -351,57 +340,47 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname,
                                             const bool is_not,
                                             const bool is_delete)
 {
-       struct tomoyo_domain_keeper_entry *entry = NULL;
        struct tomoyo_domain_keeper_entry *ptr;
-       const struct tomoyo_path_info *saved_domainname = NULL;
-       const struct tomoyo_path_info *saved_program = NULL;
+       struct tomoyo_domain_keeper_entry e = { .is_not = is_not };
        int error = is_delete ? -ENOENT : -ENOMEM;
-       bool is_last_name = false;
 
        if (!tomoyo_is_domain_def(domainname) &&
            tomoyo_is_correct_path(domainname, 1, -1, -1))
-               is_last_name = true;
+               e.is_last_name = true;
        else if (!tomoyo_is_correct_domain(domainname))
                return -EINVAL;
        if (program) {
                if (!tomoyo_is_correct_path(program, 1, -1, -1))
                        return -EINVAL;
-               saved_program = tomoyo_get_name(program);
-               if (!saved_program)
+               e.program = tomoyo_get_name(program);
+               if (!e.program)
                        goto out;
        }
-       saved_domainname = tomoyo_get_name(domainname);
-       if (!saved_domainname)
+       e.domainname = tomoyo_get_name(domainname);
+       if (!e.domainname)
                goto out;
-       if (!is_delete)
-               entry = kmalloc(sizeof(*entry), GFP_NOFS);
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                goto out;
        list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) {
-               if (ptr->is_not != is_not ||
-                   ptr->domainname != saved_domainname ||
-                   ptr->program != saved_program)
+               if (!tomoyo_is_same_domain_keeper_entry(ptr, &e))
                        continue;
                ptr->is_deleted = is_delete;
                error = 0;
                break;
        }
-       if (!is_delete && error && tomoyo_memory_ok(entry)) {
-               entry->domainname = saved_domainname;
-               saved_domainname = NULL;
-               entry->program = saved_program;
-               saved_program = NULL;
-               entry->is_not = is_not;
-               entry->is_last_name = is_last_name;
-               list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list);
-               entry = NULL;
-               error = 0;
+       if (!is_delete && error) {
+               struct tomoyo_domain_keeper_entry *entry =
+                       tomoyo_commit_ok(&e, sizeof(e));
+               if (entry) {
+                       list_add_tail_rcu(&entry->list,
+                                         &tomoyo_domain_keeper_list);
+                       error = 0;
+               }
        }
        mutex_unlock(&tomoyo_policy_lock);
  out:
-       tomoyo_put_name(saved_domainname);
-       tomoyo_put_name(saved_program);
-       kfree(entry);
+       tomoyo_put_name(e.domainname);
+       tomoyo_put_name(e.program);
        return error;
 }
 
@@ -553,45 +532,38 @@ static int tomoyo_update_alias_entry(const char *original_name,
                                     const char *aliased_name,
                                     const bool is_delete)
 {
-       struct tomoyo_alias_entry *entry = NULL;
        struct tomoyo_alias_entry *ptr;
-       const struct tomoyo_path_info *saved_original_name;
-       const struct tomoyo_path_info *saved_aliased_name;
+       struct tomoyo_alias_entry e = { };
        int error = is_delete ? -ENOENT : -ENOMEM;
 
        if (!tomoyo_is_correct_path(original_name, 1, -1, -1) ||
            !tomoyo_is_correct_path(aliased_name, 1, -1, -1))
                return -EINVAL; /* No patterns allowed. */
-       saved_original_name = tomoyo_get_name(original_name);
-       saved_aliased_name = tomoyo_get_name(aliased_name);
-       if (!saved_original_name || !saved_aliased_name)
+       e.original_name = tomoyo_get_name(original_name);
+       e.aliased_name = tomoyo_get_name(aliased_name);
+       if (!e.original_name || !e.aliased_name)
                goto out;
-       if (!is_delete)
-               entry = kmalloc(sizeof(*entry), GFP_NOFS);
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                goto out;
        list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) {
-               if (ptr->original_name != saved_original_name ||
-                   ptr->aliased_name != saved_aliased_name)
+               if (!tomoyo_is_same_alias_entry(ptr, &e))
                        continue;
                ptr->is_deleted = is_delete;
                error = 0;
                break;
        }
-       if (!is_delete && error && tomoyo_memory_ok(entry)) {
-               entry->original_name = saved_original_name;
-               saved_original_name = NULL;
-               entry->aliased_name = saved_aliased_name;
-               saved_aliased_name = NULL;
-               list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
-               entry = NULL;
-               error = 0;
+       if (!is_delete && error) {
+               struct tomoyo_alias_entry *entry =
+                       tomoyo_commit_ok(&e, sizeof(e));
+               if (entry) {
+                       list_add_tail_rcu(&entry->list, &tomoyo_alias_list);
+                       error = 0;
+               }
        }
        mutex_unlock(&tomoyo_policy_lock);
  out:
-       tomoyo_put_name(saved_original_name);
-       tomoyo_put_name(saved_aliased_name);
-       kfree(entry);
+       tomoyo_put_name(e.original_name);
+       tomoyo_put_name(e.aliased_name);
        return error;
 }
 
index 060bbf3..6651cac 100644 (file)
@@ -164,38 +164,36 @@ LIST_HEAD(tomoyo_globally_readable_list);
 static int tomoyo_update_globally_readable_entry(const char *filename,
                                                 const bool is_delete)
 {
-       struct tomoyo_globally_readable_file_entry *entry = NULL;
        struct tomoyo_globally_readable_file_entry *ptr;
-       const struct tomoyo_path_info *saved_filename;
+       struct tomoyo_globally_readable_file_entry e = { };
        int error = is_delete ? -ENOENT : -ENOMEM;
 
        if (!tomoyo_is_correct_path(filename, 1, 0, -1))
                return -EINVAL;
-       saved_filename = tomoyo_get_name(filename);
-       if (!saved_filename)
+       e.filename = tomoyo_get_name(filename);
+       if (!e.filename)
                return -ENOMEM;
-       if (!is_delete)
-               entry = kmalloc(sizeof(*entry), GFP_NOFS);
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                goto out;
        list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) {
-               if (ptr->filename != saved_filename)
+               if (ptr->filename != e.filename)
                        continue;
                ptr->is_deleted = is_delete;
                error = 0;
                break;
        }
-       if (!is_delete && error && tomoyo_memory_ok(entry)) {
-               entry->filename = saved_filename;
-               saved_filename = NULL;
-               list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list);
-               entry = NULL;
-               error = 0;
+       if (!is_delete && error) {
+               struct tomoyo_globally_readable_file_entry *entry =
+                       tomoyo_commit_ok(&e, sizeof(e));
+               if (entry) {
+                       list_add_tail_rcu(&entry->list,
+                                         &tomoyo_globally_readable_list);
+                       error = 0;
+               }
        }
        mutex_unlock(&tomoyo_policy_lock);
  out:
-       tomoyo_put_name(saved_filename);
-       kfree(entry);
+       tomoyo_put_name(e.filename);
        return error;
 }
 
@@ -313,38 +311,34 @@ LIST_HEAD(tomoyo_pattern_list);
 static int tomoyo_update_file_pattern_entry(const char *pattern,
                                            const bool is_delete)
 {
-       struct tomoyo_pattern_entry *entry = NULL;
        struct tomoyo_pattern_entry *ptr;
-       const struct tomoyo_path_info *saved_pattern;
+       struct tomoyo_pattern_entry e = { .pattern = tomoyo_get_name(pattern) };
        int error = is_delete ? -ENOENT : -ENOMEM;
 
-       saved_pattern = tomoyo_get_name(pattern);
-       if (!saved_pattern)
+       if (!e.pattern)
                return error;
-       if (!saved_pattern->is_patterned)
+       if (!e.pattern->is_patterned)
                goto out;
-       if (!is_delete)
-               entry = kmalloc(sizeof(*entry), GFP_NOFS);
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                goto out;
        list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) {
-               if (saved_pattern != ptr->pattern)
+               if (e.pattern != ptr->pattern)
                        continue;
                ptr->is_deleted = is_delete;
                error = 0;
                break;
        }
-       if (!is_delete && error && tomoyo_memory_ok(entry)) {
-               entry->pattern = saved_pattern;
-               saved_pattern = NULL;
-               list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
-               entry = NULL;
-               error = 0;
+       if (!is_delete && error) {
+               struct tomoyo_pattern_entry *entry =
+                       tomoyo_commit_ok(&e, sizeof(e));
+               if (entry) {
+                       list_add_tail_rcu(&entry->list, &tomoyo_pattern_list);
+                       error = 0;
+               }
        }
        mutex_unlock(&tomoyo_policy_lock);
  out:
-       kfree(entry);
-       tomoyo_put_name(saved_pattern);
+       tomoyo_put_name(e.pattern);
        return error;
 }
 
@@ -467,38 +461,36 @@ LIST_HEAD(tomoyo_no_rewrite_list);
 static int tomoyo_update_no_rewrite_entry(const char *pattern,
                                          const bool is_delete)
 {
-       struct tomoyo_no_rewrite_entry *entry = NULL;
        struct tomoyo_no_rewrite_entry *ptr;
-       const struct tomoyo_path_info *saved_pattern;
+       struct tomoyo_no_rewrite_entry e = { };
        int error = is_delete ? -ENOENT : -ENOMEM;
 
        if (!tomoyo_is_correct_path(pattern, 0, 0, 0))
                return -EINVAL;
-       saved_pattern = tomoyo_get_name(pattern);
-       if (!saved_pattern)
+       e.pattern = tomoyo_get_name(pattern);
+       if (!e.pattern)
                return error;
-       if (!is_delete)
-               entry = kmalloc(sizeof(*entry), GFP_NOFS);
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                goto out;
        list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) {
-               if (ptr->pattern != saved_pattern)
+               if (ptr->pattern != e.pattern)
                        continue;
                ptr->is_deleted = is_delete;
                error = 0;
                break;
        }
-       if (!is_delete && error && tomoyo_memory_ok(entry)) {
-               entry->pattern = saved_pattern;
-               saved_pattern = NULL;
-               list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list);
-               entry = NULL;
-               error = 0;
+       if (!is_delete && error) {
+               struct tomoyo_no_rewrite_entry *entry =
+                       tomoyo_commit_ok(&e, sizeof(e));
+               if (entry) {
+                       list_add_tail_rcu(&entry->list,
+                                         &tomoyo_no_rewrite_list);
+                       error = 0;
+               }
        }
        mutex_unlock(&tomoyo_policy_lock);
  out:
-       tomoyo_put_name(saved_pattern);
-       kfree(entry);
+       tomoyo_put_name(e.pattern);
        return error;
 }
 
@@ -810,23 +802,26 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename,
                                  struct tomoyo_domain_info *const domain,
                                  const bool is_delete)
 {
-       static const u32 rw_mask =
+       static const u32 tomoyo_rw_mask =
                (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE);
-       const struct tomoyo_path_info *saved_filename;
+       const u32 perm = 1 << type;
        struct tomoyo_acl_info *ptr;
-       struct tomoyo_path_acl *entry = NULL;
+       struct tomoyo_path_acl e = {
+               .head.type = TOMOYO_TYPE_PATH_ACL,
+               .perm_high = perm >> 16,
+               .perm = perm
+       };
        int error = is_delete ? -ENOENT : -ENOMEM;
-       const u32 perm = 1 << type;
 
+       if (type == TOMOYO_TYPE_READ_WRITE)
+               e.perm |= tomoyo_rw_mask;
        if (!domain)
                return -EINVAL;
        if (!tomoyo_is_correct_path(filename, 0, 0, 0))
                return -EINVAL;
-       saved_filename = tomoyo_get_name(filename);
-       if (!saved_filename)
+       e.filename = tomoyo_get_name(filename);
+       if (!e.filename)
                return -ENOMEM;
-       if (!is_delete)
-               entry = kmalloc(sizeof(*entry), GFP_NOFS);
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                goto out;
        list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
@@ -834,48 +829,42 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename,
                        container_of(ptr, struct tomoyo_path_acl, head);
                if (ptr->type != TOMOYO_TYPE_PATH_ACL)
                        continue;
-               if (acl->filename != saved_filename)
+               if (acl->filename != e.filename)
                        continue;
                if (is_delete) {
                        if (perm <= 0xFFFF)
                                acl->perm &= ~perm;
                        else
                                acl->perm_high &= ~(perm >> 16);
-                       if ((acl->perm & rw_mask) != rw_mask)
+                       if ((acl->perm & tomoyo_rw_mask) != tomoyo_rw_mask)
                                acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE);
                        else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)))
-                               acl->perm &= ~rw_mask;
+                               acl->perm &= ~tomoyo_rw_mask;
                } else {
                        if (perm <= 0xFFFF)
                                acl->perm |= perm;
                        else
                                acl->perm_high |= (perm >> 16);
-                       if ((acl->perm & rw_mask) == rw_mask)
+                       if ((acl->perm & tomoyo_rw_mask) == tomoyo_rw_mask)
                                acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE;
                        else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))
-                               acl->perm |= rw_mask;
+                               acl->perm |= tomoyo_rw_mask;
                }
                error = 0;
                break;
        }
-       if (!is_delete && error && tomoyo_memory_ok(entry)) {
-               entry->head.type = TOMOYO_TYPE_PATH_ACL;
-               if (perm <= 0xFFFF)
-                       entry->perm = perm;
-               else
-                       entry->perm_high = (perm >> 16);
-               if (perm == (1 << TOMOYO_TYPE_READ_WRITE))
-                       entry->perm |= rw_mask;
-               entry->filename = saved_filename;
-               saved_filename = NULL;
-               list_add_tail_rcu(&entry->head.list, &domain->acl_info_list);
-               entry = NULL;
-               error = 0;
+       if (!is_delete && error) {
+               struct tomoyo_path_acl *entry =
+                       tomoyo_commit_ok(&e, sizeof(e));
+               if (entry) {
+                       list_add_tail_rcu(&entry->head.list,
+                                         &domain->acl_info_list);
+                       error = 0;
+               }
        }
        mutex_unlock(&tomoyo_policy_lock);
  out:
-       kfree(entry);
-       tomoyo_put_name(saved_filename);
+       tomoyo_put_name(e.filename);
        return error;
 }
 
@@ -897,24 +886,23 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
                                   struct tomoyo_domain_info *const domain,
                                   const bool is_delete)
 {
-       const struct tomoyo_path_info *saved_filename1;
-       const struct tomoyo_path_info *saved_filename2;
+       const u8 perm = 1 << type;
+       struct tomoyo_path2_acl e = {
+               .head.type = TOMOYO_TYPE_PATH2_ACL,
+               .perm = perm
+       };
        struct tomoyo_acl_info *ptr;
-       struct tomoyo_path2_acl *entry = NULL;
        int error = is_delete ? -ENOENT : -ENOMEM;
-       const u8 perm = 1 << type;
 
        if (!domain)
                return -EINVAL;
        if (!tomoyo_is_correct_path(filename1, 0, 0, 0) ||
            !tomoyo_is_correct_path(filename2, 0, 0, 0))
                return -EINVAL;
-       saved_filename1 = tomoyo_get_name(filename1);
-       saved_filename2 = tomoyo_get_name(filename2);
-       if (!saved_filename1 || !saved_filename2)
+       e.filename1 = tomoyo_get_name(filename1);
+       e.filename2 = tomoyo_get_name(filename2);
+       if (!e.filename1 || !e.filename2)
                goto out;
-       if (!is_delete)
-               entry = kmalloc(sizeof(*entry), GFP_NOFS);
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                goto out;
        list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
@@ -922,8 +910,8 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
                        container_of(ptr, struct tomoyo_path2_acl, head);
                if (ptr->type != TOMOYO_TYPE_PATH2_ACL)
                        continue;
-               if (acl->filename1 != saved_filename1 ||
-                   acl->filename2 != saved_filename2)
+               if (acl->filename1 != e.filename1 ||
+                   acl->filename2 != e.filename2)
                        continue;
                if (is_delete)
                        acl->perm &= ~perm;
@@ -932,22 +920,19 @@ static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
                error = 0;
                break;
        }
-       if (!is_delete && error && tomoyo_memory_ok(entry)) {
-               entry->head.type = TOMOYO_TYPE_PATH2_ACL;
-               entry->perm = perm;
-               entry->filename1 = saved_filename1;
-               saved_filename1 = NULL;
-               entry->filename2 = saved_filename2;
-               saved_filename2 = NULL;
-               list_add_tail_rcu(&entry->head.list, &domain->acl_info_list);
-               entry = NULL;
-               error = 0;
+       if (!is_delete && error) {
+               struct tomoyo_path2_acl *entry =
+                       tomoyo_commit_ok(&e, sizeof(e));
+               if (entry) {
+                       list_add_tail_rcu(&entry->head.list,
+                                         &domain->acl_info_list);
+                       error = 0;
+               }
        }
        mutex_unlock(&tomoyo_policy_lock);
  out:
-       tomoyo_put_name(saved_filename1);
-       tomoyo_put_name(saved_filename2);
-       kfree(entry);
+       tomoyo_put_name(e.filename1);
+       tomoyo_put_name(e.filename2);
        return error;
 }
 
index 62062a6..d1b96f0 100644 (file)
@@ -223,6 +223,25 @@ bool tomoyo_memory_ok(void *ptr)
 }
 
 /**
+ * tomoyo_commit_ok - Check memory quota.
+ *
+ * @data:   Data to copy from.
+ * @size:   Size in byte.
+ *
+ * Returns pointer to allocated memory on success, NULL otherwise.
+ */
+void *tomoyo_commit_ok(void *data, const unsigned int size)
+{
+       void *ptr = kzalloc(size, GFP_NOFS);
+       if (tomoyo_memory_ok(ptr)) {
+               memmove(ptr, data, size);
+               memset(data, 0, size);
+               return ptr;
+       }
+       return NULL;
+}
+
+/**
  * tomoyo_memory_free - Free memory for elements.
  *
  * @ptr:  Pointer to allocated memory.