Skip to content

Commit

Permalink
TOMOYO: Use stack memory for pending entry.
Browse files Browse the repository at this point in the history
Use stack memory for pending entry to reduce kmalloc() which will be kfree()d.

Signed-off-by: Tetsuo Handa <[email protected]>
Signed-off-by: James Morris <[email protected]>
  • Loading branch information
Tetsuo Handa authored and James Morris committed May 10, 2010
1 parent 83c36cc commit 9e4b50e
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 192 deletions.
32 changes: 14 additions & 18 deletions security/tomoyo/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
26 changes: 26 additions & 0 deletions security/tomoyo/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
124 changes: 48 additions & 76 deletions security/tomoyo/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down
Loading

0 comments on commit 9e4b50e

Please sign in to comment.