Commit 0df7e8b8 authored by Tetsuo Handa's avatar Tetsuo Handa Committed by James Morris

TOMOYO: Cleanup part 3.

Use common structure for ACL with "struct list_head" + "atomic_t".
Use array/struct where possible.
Remove is_group from "struct tomoyo_name_union"/"struct tomoyo_number_union".
Pass "struct file"->private_data rather than "struct file".
Update some of comments.
Bring tomoyo_same_acl_head() from common.h to domain.c .
Bring tomoyo_invalid()/tomoyo_valid() from common.h to util.c .
Signed-off-by: default avatarTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent b5bc60b4
...@@ -192,7 +192,7 @@ static void tomoyo_print_name_union(struct tomoyo_io_buffer *head, ...@@ -192,7 +192,7 @@ static void tomoyo_print_name_union(struct tomoyo_io_buffer *head,
const struct tomoyo_name_union *ptr) const struct tomoyo_name_union *ptr)
{ {
tomoyo_set_space(head); tomoyo_set_space(head);
if (ptr->is_group) { if (ptr->group) {
tomoyo_set_string(head, "@"); tomoyo_set_string(head, "@");
tomoyo_set_string(head, ptr->group->group_name->name); tomoyo_set_string(head, ptr->group->group_name->name);
} else { } else {
...@@ -210,15 +210,15 @@ static void tomoyo_print_number_union(struct tomoyo_io_buffer *head, ...@@ -210,15 +210,15 @@ static void tomoyo_print_number_union(struct tomoyo_io_buffer *head,
const struct tomoyo_number_union *ptr) const struct tomoyo_number_union *ptr)
{ {
tomoyo_set_space(head); tomoyo_set_space(head);
if (ptr->is_group) { if (ptr->group) {
tomoyo_set_string(head, "@"); tomoyo_set_string(head, "@");
tomoyo_set_string(head, ptr->group->group_name->name); tomoyo_set_string(head, ptr->group->group_name->name);
} else { } else {
int i; int i;
unsigned long min = ptr->values[0]; unsigned long min = ptr->values[0];
const unsigned long max = ptr->values[1]; const unsigned long max = ptr->values[1];
u8 min_type = ptr->min_type; u8 min_type = ptr->value_type[0];
const u8 max_type = ptr->max_type; const u8 max_type = ptr->value_type[1];
char buffer[128]; char buffer[128];
buffer[0] = '\0'; buffer[0] = '\0';
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
...@@ -769,7 +769,7 @@ static bool tomoyo_select_one(struct tomoyo_io_buffer *head, const char *data) ...@@ -769,7 +769,7 @@ static bool tomoyo_select_one(struct tomoyo_io_buffer *head, const char *data)
domain = tomoyo_find_domain(data + 7); domain = tomoyo_find_domain(data + 7);
} else } else
return false; return false;
head->write_var1 = domain; head->w.domain = domain;
/* Accessing read_buf is safe because head->io_sem is held. */ /* Accessing read_buf is safe because head->io_sem is held. */
if (!head->read_buf) if (!head->read_buf)
return true; /* Do nothing if open(O_WRONLY). */ return true; /* Do nothing if open(O_WRONLY). */
...@@ -847,7 +847,7 @@ static int tomoyo_write_domain2(char *data, struct tomoyo_domain_info *domain, ...@@ -847,7 +847,7 @@ static int tomoyo_write_domain2(char *data, struct tomoyo_domain_info *domain,
static int tomoyo_write_domain(struct tomoyo_io_buffer *head) static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
{ {
char *data = head->write_buf; char *data = head->write_buf;
struct tomoyo_domain_info *domain = head->write_var1; struct tomoyo_domain_info *domain = head->w.domain;
bool is_delete = false; bool is_delete = false;
bool is_select = false; bool is_select = false;
unsigned int profile; unsigned int profile;
...@@ -869,7 +869,7 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) ...@@ -869,7 +869,7 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
domain = tomoyo_find_domain(data); domain = tomoyo_find_domain(data);
else else
domain = tomoyo_assign_domain(data, 0); domain = tomoyo_assign_domain(data, 0);
head->write_var1 = domain; head->w.domain = domain;
return 0; return 0;
} }
if (!domain) if (!domain)
...@@ -1250,7 +1250,7 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx) ...@@ -1250,7 +1250,7 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx)
{ {
list_for_each_cookie(head->r.group, &tomoyo_group_list[idx]) { list_for_each_cookie(head->r.group, &tomoyo_group_list[idx]) {
struct tomoyo_group *group = struct tomoyo_group *group =
list_entry(head->r.group, typeof(*group), list); list_entry(head->r.group, typeof(*group), head.list);
list_for_each_cookie(head->r.acl, &group->member_list) { list_for_each_cookie(head->r.acl, &group->member_list) {
struct tomoyo_acl_head *ptr = struct tomoyo_acl_head *ptr =
list_entry(head->r.acl, typeof(*ptr), list); list_entry(head->r.acl, typeof(*ptr), list);
...@@ -1874,7 +1874,7 @@ int tomoyo_poll_control(struct file *file, poll_table *wait) ...@@ -1874,7 +1874,7 @@ int tomoyo_poll_control(struct file *file, poll_table *wait)
/** /**
* tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface. * tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface.
* *
* @file: Pointer to "struct file". * @head: Pointer to "struct tomoyo_io_buffer".
* @buffer: Poiner to buffer to write to. * @buffer: Poiner to buffer to write to.
* @buffer_len: Size of @buffer. * @buffer_len: Size of @buffer.
* *
...@@ -1882,11 +1882,10 @@ int tomoyo_poll_control(struct file *file, poll_table *wait) ...@@ -1882,11 +1882,10 @@ int tomoyo_poll_control(struct file *file, poll_table *wait)
* *
* Caller holds tomoyo_read_lock(). * Caller holds tomoyo_read_lock().
*/ */
int tomoyo_read_control(struct file *file, char __user *buffer, int tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer,
const int buffer_len) const int buffer_len)
{ {
int len; int len;
struct tomoyo_io_buffer *head = file->private_data;
if (!head->read) if (!head->read)
return -ENOSYS; return -ENOSYS;
...@@ -1906,7 +1905,7 @@ int tomoyo_read_control(struct file *file, char __user *buffer, ...@@ -1906,7 +1905,7 @@ int tomoyo_read_control(struct file *file, char __user *buffer,
/** /**
* tomoyo_write_control - write() for /sys/kernel/security/tomoyo/ interface. * tomoyo_write_control - write() for /sys/kernel/security/tomoyo/ interface.
* *
* @file: Pointer to "struct file". * @head: Pointer to "struct tomoyo_io_buffer".
* @buffer: Pointer to buffer to read from. * @buffer: Pointer to buffer to read from.
* @buffer_len: Size of @buffer. * @buffer_len: Size of @buffer.
* *
...@@ -1914,10 +1913,9 @@ int tomoyo_read_control(struct file *file, char __user *buffer, ...@@ -1914,10 +1913,9 @@ int tomoyo_read_control(struct file *file, char __user *buffer,
* *
* Caller holds tomoyo_read_lock(). * Caller holds tomoyo_read_lock().
*/ */
int tomoyo_write_control(struct file *file, const char __user *buffer, int tomoyo_write_control(struct tomoyo_io_buffer *head,
const int buffer_len) const char __user *buffer, const int buffer_len)
{ {
struct tomoyo_io_buffer *head = file->private_data;
int error = buffer_len; int error = buffer_len;
int avail_len = buffer_len; int avail_len = buffer_len;
char *cp0 = head->write_buf; char *cp0 = head->write_buf;
...@@ -1935,7 +1933,7 @@ int tomoyo_write_control(struct file *file, const char __user *buffer, ...@@ -1935,7 +1933,7 @@ int tomoyo_write_control(struct file *file, const char __user *buffer,
/* Read a line and dispatch it to the policy handler. */ /* Read a line and dispatch it to the policy handler. */
while (avail_len > 0) { while (avail_len > 0) {
char c; char c;
if (head->write_avail >= head->writebuf_size - 1) { if (head->w.avail >= head->writebuf_size - 1) {
error = -ENOMEM; error = -ENOMEM;
break; break;
} else if (get_user(c, buffer)) { } else if (get_user(c, buffer)) {
...@@ -1944,11 +1942,11 @@ int tomoyo_write_control(struct file *file, const char __user *buffer, ...@@ -1944,11 +1942,11 @@ int tomoyo_write_control(struct file *file, const char __user *buffer,
} }
buffer++; buffer++;
avail_len--; avail_len--;
cp0[head->write_avail++] = c; cp0[head->w.avail++] = c;
if (c != '\n') if (c != '\n')
continue; continue;
cp0[head->write_avail - 1] = '\0'; cp0[head->w.avail - 1] = '\0';
head->write_avail = 0; head->w.avail = 0;
tomoyo_normalize_line(cp0); tomoyo_normalize_line(cp0);
head->write(head); head->write(head);
} }
...@@ -1959,15 +1957,14 @@ int tomoyo_write_control(struct file *file, const char __user *buffer, ...@@ -1959,15 +1957,14 @@ int tomoyo_write_control(struct file *file, const char __user *buffer,
/** /**
* tomoyo_close_control - close() for /sys/kernel/security/tomoyo/ interface. * tomoyo_close_control - close() for /sys/kernel/security/tomoyo/ interface.
* *
* @file: Pointer to "struct file". * @head: Pointer to "struct tomoyo_io_buffer".
* *
* Releases memory and returns 0. * Releases memory and returns 0.
* *
* Caller looses tomoyo_read_lock(). * Caller looses tomoyo_read_lock().
*/ */
int tomoyo_close_control(struct file *file) int tomoyo_close_control(struct tomoyo_io_buffer *head)
{ {
struct tomoyo_io_buffer *head = file->private_data;
const bool is_write = !!head->write_buf; const bool is_write = !!head->write_buf;
/* /*
...@@ -1984,8 +1981,6 @@ int tomoyo_close_control(struct file *file) ...@@ -1984,8 +1981,6 @@ int tomoyo_close_control(struct file *file)
kfree(head->write_buf); kfree(head->write_buf);
head->write_buf = NULL; head->write_buf = NULL;
kfree(head); kfree(head);
head = NULL;
file->private_data = NULL;
if (is_write) if (is_write)
tomoyo_run_gc(); tomoyo_run_gc();
return 0; return 0;
......
...@@ -219,6 +219,12 @@ struct tomoyo_acl_head { ...@@ -219,6 +219,12 @@ struct tomoyo_acl_head {
bool is_deleted; bool is_deleted;
} __packed; } __packed;
/* Common header for shared entries. */
struct tomoyo_shared_acl_head {
struct list_head list;
atomic_t users;
} __packed;
/* Structure for request info. */ /* Structure for request info. */
struct tomoyo_request_info { struct tomoyo_request_info {
struct tomoyo_domain_info *domain; struct tomoyo_domain_info *domain;
...@@ -281,8 +287,7 @@ struct tomoyo_path_info { ...@@ -281,8 +287,7 @@ struct tomoyo_path_info {
/* Structure for holding string data. */ /* Structure for holding string data. */
struct tomoyo_name { struct tomoyo_name {
struct list_head list; struct tomoyo_shared_acl_head head;
atomic_t users;
struct tomoyo_path_info entry; struct tomoyo_path_info entry;
}; };
...@@ -291,8 +296,6 @@ struct tomoyo_name_union { ...@@ -291,8 +296,6 @@ struct tomoyo_name_union {
/* Either @filename or @group is NULL. */ /* Either @filename or @group is NULL. */
const struct tomoyo_path_info *filename; const struct tomoyo_path_info *filename;
struct tomoyo_group *group; struct tomoyo_group *group;
/* True if @group != NULL, false if @filename != NULL. */
u8 is_group;
}; };
/* Structure for holding a number. */ /* Structure for holding a number. */
...@@ -300,18 +303,14 @@ struct tomoyo_number_union { ...@@ -300,18 +303,14 @@ struct tomoyo_number_union {
unsigned long values[2]; unsigned long values[2];
struct tomoyo_group *group; /* Maybe NULL. */ struct tomoyo_group *group; /* Maybe NULL. */
/* One of values in "enum tomoyo_value_type". */ /* One of values in "enum tomoyo_value_type". */
u8 min_type; u8 value_type[2];
u8 max_type;
/* True if @group != NULL, false otherwise. */
u8 is_group;
}; };
/* Structure for "path_group"/"number_group" directive. */ /* Structure for "path_group"/"number_group" directive. */
struct tomoyo_group { struct tomoyo_group {
struct list_head list; struct tomoyo_shared_acl_head head;
const struct tomoyo_path_info *group_name; const struct tomoyo_path_info *group_name;
struct list_head member_list; struct list_head member_list;
atomic_t users;
}; };
/* Structure for "path_group" directive. */ /* Structure for "path_group" directive. */
...@@ -429,16 +428,18 @@ struct tomoyo_io_buffer { ...@@ -429,16 +428,18 @@ struct tomoyo_io_buffer {
bool print_execute_only; bool print_execute_only;
const char *w[TOMOYO_MAX_IO_READ_QUEUE]; const char *w[TOMOYO_MAX_IO_READ_QUEUE];
} r; } r;
/* The position currently writing to. */ struct {
struct tomoyo_domain_info *write_var1; /* The position currently writing to. */
struct tomoyo_domain_info *domain;
/* Bytes available for writing. */
int avail;
} w;
/* Buffer for reading. */ /* Buffer for reading. */
char *read_buf; char *read_buf;
/* Size of read buffer. */ /* Size of read buffer. */
int readbuf_size; int readbuf_size;
/* Buffer for writing. */ /* Buffer for writing. */
char *write_buf; char *write_buf;
/* Bytes available for writing. */
int write_avail;
/* Size of write buffer. */ /* Size of write buffer. */
int writebuf_size; int writebuf_size;
/* Type of this interface. */ /* Type of this interface. */
...@@ -500,12 +501,12 @@ void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...) ...@@ -500,12 +501,12 @@ void tomoyo_warn_log(struct tomoyo_request_info *r, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3))); __attribute__ ((format(printf, 2, 3)));
void tomoyo_check_profile(void); void tomoyo_check_profile(void);
int tomoyo_open_control(const u8 type, struct file *file); int tomoyo_open_control(const u8 type, struct file *file);
int tomoyo_close_control(struct file *file); int tomoyo_close_control(struct tomoyo_io_buffer *head);
int tomoyo_poll_control(struct file *file, poll_table *wait); int tomoyo_poll_control(struct file *file, poll_table *wait);
int tomoyo_read_control(struct file *file, char __user *buffer, int tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer,
const int buffer_len); const int buffer_len);
int tomoyo_write_control(struct file *file, const char __user *buffer, int tomoyo_write_control(struct tomoyo_io_buffer *head,
const int buffer_len); const char __user *buffer, const int buffer_len);
bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r); bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r);
void tomoyo_warn_oom(const char *function); void tomoyo_warn_oom(const char *function);
const struct tomoyo_path_info * const struct tomoyo_path_info *
...@@ -671,30 +672,6 @@ static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, ...@@ -671,30 +672,6 @@ static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a,
return a->hash != b->hash || strcmp(a->name, b->name); return a->hash != b->hash || strcmp(a->name, b->name);
} }
/**
* tomoyo_valid - Check whether the character is a valid char.
*
* @c: The character to check.
*
* Returns true if @c is a valid character, false otherwise.
*/
static inline bool tomoyo_valid(const unsigned char c)
{
return c > ' ' && c < 127;
}
/**
* tomoyo_invalid - Check whether the character is an invalid char.
*
* @c: The character to check.
*
* Returns true if @c is an invalid character, false otherwise.
*/
static inline bool tomoyo_invalid(const unsigned char c)
{
return c && (c <= ' ' || c >= 127);
}
/** /**
* tomoyo_put_name - Drop reference on "struct tomoyo_name". * tomoyo_put_name - Drop reference on "struct tomoyo_name".
* *
...@@ -707,7 +684,7 @@ static inline void tomoyo_put_name(const struct tomoyo_path_info *name) ...@@ -707,7 +684,7 @@ static inline void tomoyo_put_name(const struct tomoyo_path_info *name)
if (name) { if (name) {
struct tomoyo_name *ptr = struct tomoyo_name *ptr =
container_of(name, typeof(*ptr), entry); container_of(name, typeof(*ptr), entry);
atomic_dec(&ptr->users); atomic_dec(&ptr->head.users);
} }
} }
...@@ -721,7 +698,7 @@ static inline void tomoyo_put_name(const struct tomoyo_path_info *name) ...@@ -721,7 +698,7 @@ static inline void tomoyo_put_name(const struct tomoyo_path_info *name)
static inline void tomoyo_put_group(struct tomoyo_group *group) static inline void tomoyo_put_group(struct tomoyo_group *group)
{ {
if (group) if (group)
atomic_dec(&group->users); atomic_dec(&group->head.users);
} }
/** /**
...@@ -747,12 +724,6 @@ static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct ...@@ -747,12 +724,6 @@ static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
return task_cred_xxx(task, security); return task_cred_xxx(task, security);
} }
static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *p1,
const struct tomoyo_acl_info *p2)
{
return p1->type == p2->type;
}
/** /**
* tomoyo_same_name_union - Check for duplicated "struct tomoyo_name_union" entry. * tomoyo_same_name_union - Check for duplicated "struct tomoyo_name_union" entry.
* *
...@@ -764,8 +735,7 @@ static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *p1, ...@@ -764,8 +735,7 @@ static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *p1,
static inline bool tomoyo_same_name_union static inline bool tomoyo_same_name_union
(const struct tomoyo_name_union *a, const struct tomoyo_name_union *b) (const struct tomoyo_name_union *a, const struct tomoyo_name_union *b)
{ {
return a->filename == b->filename && a->group == b->group && return a->filename == b->filename && a->group == b->group;
a->is_group == b->is_group;
} }
/** /**
...@@ -780,8 +750,8 @@ static inline bool tomoyo_same_number_union ...@@ -780,8 +750,8 @@ static inline bool tomoyo_same_number_union
(const struct tomoyo_number_union *a, const struct tomoyo_number_union *b) (const struct tomoyo_number_union *a, const struct tomoyo_number_union *b)
{ {
return a->values[0] == b->values[0] && a->values[1] == b->values[1] && return a->values[0] == b->values[0] && a->values[1] == b->values[1] &&
a->group == b->group && a->min_type == b->min_type && a->group == b->group && a->value_type[0] == b->value_type[0] &&
a->max_type == b->max_type && a->is_group == b->is_group; a->value_type[1] == b->value_type[1];
} }
/** /**
......
...@@ -58,6 +58,20 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, ...@@ -58,6 +58,20 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
return error; return error;
} }
/**
* tomoyo_same_acl_head - Check for duplicated "struct tomoyo_acl_info" entry.
*
* @a: Pointer to "struct tomoyo_acl_info".
* @b: Pointer to "struct tomoyo_acl_info".
*
* Returns true if @a == @b, false otherwise.
*/
static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a,
const struct tomoyo_acl_info *b)
{
return a->type == b->type;
}
/** /**
* tomoyo_update_domain - Update an entry for domain policy. * tomoyo_update_domain - Update an entry for domain policy.
* *
...@@ -88,7 +102,8 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, ...@@ -88,7 +102,8 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
if (mutex_lock_interruptible(&tomoyo_policy_lock)) if (mutex_lock_interruptible(&tomoyo_policy_lock))
return error; return error;
list_for_each_entry_rcu(entry, &domain->acl_info_list, list) { list_for_each_entry_rcu(entry, &domain->acl_info_list, list) {
if (!check_duplicate(entry, new_entry)) if (!tomoyo_same_acl_head(entry, new_entry) ||
!check_duplicate(entry, new_entry))
continue; continue;
if (merge_duplicate) if (merge_duplicate)
entry->is_deleted = merge_duplicate(entry, new_entry, entry->is_deleted = merge_duplicate(entry, new_entry,
......
...@@ -49,6 +49,9 @@ const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { ...@@ -49,6 +49,9 @@ const char *tomoyo_path_number_keyword[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
[TOMOYO_TYPE_CHGRP] = "chgrp", [TOMOYO_TYPE_CHGRP] = "chgrp",
}; };
/*
* Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index".
*/
static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
[TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE, [TOMOYO_TYPE_EXECUTE] = TOMOYO_MAC_FILE_EXECUTE,
[TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN, [TOMOYO_TYPE_READ] = TOMOYO_MAC_FILE_OPEN,
...@@ -63,17 +66,27 @@ static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = { ...@@ -63,17 +66,27 @@ static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
[TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT, [TOMOYO_TYPE_UMOUNT] = TOMOYO_MAC_FILE_UMOUNT,
}; };
/*
* Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index".
*/
static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = { static const u8 tomoyo_pnnn2mac[TOMOYO_MAX_MKDEV_OPERATION] = {
[TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK, [TOMOYO_TYPE_MKBLOCK] = TOMOYO_MAC_FILE_MKBLOCK,
[TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR, [TOMOYO_TYPE_MKCHAR] = TOMOYO_MAC_FILE_MKCHAR,
}; };
/*
* Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index".
*/
static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = { static const u8 tomoyo_pp2mac[TOMOYO_MAX_PATH2_OPERATION] = {
[TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK, [TOMOYO_TYPE_LINK] = TOMOYO_MAC_FILE_LINK,
[TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME, [TOMOYO_TYPE_RENAME] = TOMOYO_MAC_FILE_RENAME,
[TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT, [TOMOYO_TYPE_PIVOT_ROOT] = TOMOYO_MAC_FILE_PIVOT_ROOT,
}; };
/*
* Mapping table from "enum tomoyo_path_number_acl_index" to
* "enum tomoyo_mac_index".
*/
static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
[TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE, [TOMOYO_TYPE_CREATE] = TOMOYO_MAC_FILE_CREATE,
[TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR, [TOMOYO_TYPE_MKDIR] = TOMOYO_MAC_FILE_MKDIR,
...@@ -85,41 +98,76 @@ static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = { ...@@ -85,41 +98,76 @@ static const u8 tomoyo_pn2mac[TOMOYO_MAX_PATH_NUMBER_OPERATION] = {
[TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP, [TOMOYO_TYPE_CHGRP] = TOMOYO_MAC_FILE_CHGRP,
}; };
/**
* tomoyo_put_name_union - Drop reference on "struct tomoyo_name_union".
*
* @ptr: Pointer to "struct tomoyo_name_union".
*
* Returns nothing.
*/
void tomoyo_put_name_union(struct tomoyo_name_union *ptr) void tomoyo_put_name_union(struct tomoyo_name_union *ptr)
{ {
if (!ptr) tomoyo_put_group(ptr->group);
return; tomoyo_put_name(ptr->filename);
if (ptr->is_group)
tomoyo_put_group(ptr->group);
else
tomoyo_put_name(ptr->filename);
} }
/**
* tomoyo_compare_name_union - Check whether a name matches "struct tomoyo_name_union" or not.
*
* @name: Pointer to "struct tomoyo_path_info".
* @ptr: Pointer to "struct tomoyo_name_union".
*
* Returns "struct tomoyo_path_info" if @name matches @ptr, NULL otherwise.
*/
const struct tomoyo_path_info * const struct tomoyo_path_info *
tomoyo_compare_name_union(const struct tomoyo_path_info *name, tomoyo_compare_name_union(const struct tomoyo_path_info *name,
const struct tomoyo_name_union *ptr) const struct tomoyo_name_union *ptr)
{ {
if (ptr->is_group) if (ptr->group)
return tomoyo_path_matches_group(name, ptr->group); return tomoyo_path_matches_group(name, ptr->group);
if (tomoyo_path_matches_pattern(name, ptr->filename)) if (tomoyo_path_matches_pattern(name, ptr->filename))
return ptr->filename; return ptr->filename;
return NULL; return NULL;
} }
/**
* tomoyo_put_number_union - Drop reference on "struct tomoyo_number_union".
*
* @ptr: Pointer to "struct tomoyo_number_union".
*
* Returns nothing.
*/
void tomoyo_put_number_union(struct tomoyo_number_union *ptr) void tomoyo_put_number_union(struct tomoyo_number_union *ptr)
{ {
if (ptr && ptr->is_group) tomoyo_put_group(ptr->group);
tomoyo_put_group(ptr->group);
} }
/**
* tomoyo_compare_number_union - Check whether a value matches "struct tomoyo_number_union" or not.
*
* @value: Number to check.
* @ptr: Pointer to "struct tomoyo_number_union".
*
* Returns true if @value matches @ptr, false otherwise.
*/
bool tomoyo_compare_number_union(const unsigned long value, bool tomoyo_compare_number_union(const unsigned long value,
const struct tomoyo_number_union *ptr) const struct tomoyo_number_union *ptr)
{ {
if (ptr->is_group) if (ptr->group)
return tomoyo_number_matches_group(value, value, ptr->group); return tomoyo_number_matches_group(value, value, ptr->group);
return value >= ptr->values[0] && value <= ptr->values[1]; return value >= ptr->values[0] && value <= ptr->values[1];
} }
/**
* tomoyo_add_slash - Add trailing '/' if needed.
*
* @buf: Pointer to "struct tomoyo_path_info".
*
* Returns nothing.
*
* @buf must be generated by tomoyo_encode() because this function does not
* allocate memory for adding '/'.
*/
static void tomoyo_add_slash(struct tomoyo_path_info *buf) static void tomoyo_add_slash(struct tomoyo_path_info *buf)
{ {
if (buf->is_dir) if (buf->is_dir)
...@@ -247,6 +295,18 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r) ...@@ -247,6 +295,18 @@ static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
filename->name, buffer); filename->name, buffer);
} }
/**
* tomoyo_check_path_acl - Check permission for path operation.
*
* @r: Pointer to "struct tomoyo_request_info".
* @ptr: Pointer to "struct tomoyo_acl_info".
*
* Returns true if granted, false otherwise.
*
* To be able to use wildcard for domain transition, this function sets
* matching entry on success. Since the caller holds tomoyo_read_lock(),
* it is safe to set matching entry.
*/
static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
const struct tomoyo_acl_info *ptr) const struct tomoyo_acl_info *ptr)
{ {
...@@ -261,6 +321,14 @@ static bool tomoyo_check_path_acl(struct tomoyo_request_info *r, ...@@ -261,6 +321,14 @@ static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
return false; return false;
} }
/**
* tomoyo_check_path_number_acl - Check permission for path number operation.
*
* @r: Pointer to "struct tomoyo_request_info".
* @ptr: Pointer to "struct tomoyo_acl_info".
*
* Returns true if granted, false otherwise.
*/
static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r, static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
const struct tomoyo_acl_info *ptr) const struct tomoyo_acl_info *ptr)
{ {
...@@ -273,6 +341,14 @@ static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r, ...@@ -273,6 +341,14 @@ static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
&acl->name); &acl->name);
} }
/**
* tomoyo_check_path2_acl - Check permission for path path operation.
*
* @r: Pointer to "struct tomoyo_request_info".
* @ptr: Pointer to "struct tomoyo_acl_info".
*
* Returns true if granted, false otherwise.
*/
static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r, static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
const struct tomoyo_acl_info *ptr) const struct tomoyo_acl_info *ptr)
{ {
...@@ -284,8 +360,16 @@ static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r, ...@@ -284,8 +360,16 @@ static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
&acl->name2); &acl->name2);
} }
/**
* tomoyo_check_mkdev_acl - Check permission for path number number number operation.
*
* @r: Pointer to "struct tomoyo_request_info".
* @ptr: Pointer to "struct tomoyo_acl_info".
*
* Returns true if granted, false otherwise.
*/
static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
const struct tomoyo_acl_info *ptr) const struct tomoyo_acl_info *ptr)
{ {
const struct tomoyo_mkdev_acl *acl = const struct tomoyo_mkdev_acl *acl =
container_of(ptr, typeof(*acl), head); container_of(ptr, typeof(*acl), head);
...@@ -300,13 +384,20 @@ static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r, ...@@ -300,13 +384,20 @@ static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
&acl->name); &acl->name);
} }
/**
* tomoyo_same_path_acl - Check for duplicated "struct tomoyo_path_acl" entry.
*
* @a: Pointer to "struct tomoyo_acl_info".
* @b: Pointer to "struct tomoyo_acl_info".
*
* Returns true if @a == @b except permission bits, false otherwise.
*/
static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a, static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
const struct tomoyo_acl_info *b) const struct tomoyo_acl_info *b)
{ {
const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head); const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head); const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
return tomoyo_same_acl_head(&p1->head, &p2->head) && return tomoyo_same_name_union(&p1->name, &p2->name);
tomoyo_same_name_union(&p1->name, &p2->name);
} }
/** /**
...@@ -364,23 +455,37 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename, ...@@ -364,23 +455,37 @@ static int tomoyo_update_path_acl(const u8 type, const char *filename,
return error; return error;
} }
/**
* tomoyo_same_mkdev_acl - Check for duplicated "struct tomoyo_mkdev_acl" entry.
*
* @a: Pointer to "struct tomoyo_acl_info".
* @b: Pointer to "struct tomoyo_acl_info".
*
* Returns true if @a == @b except permission bits, false otherwise.
*/
static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a, static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
const struct tomoyo_acl_info *b) const struct tomoyo_acl_info *b)
{ {
const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head);
head); const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head);
const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), return tomoyo_same_name_union(&p1->name, &p2->name) &&
head); tomoyo_same_number_union(&p1->mode, &p2->mode) &&
return tomoyo_same_acl_head(&p1->head, &p2->head) tomoyo_same_number_union(&p1->major, &p2->major) &&
&& tomoyo_same_name_union(&p1->name, &p2->name) tomoyo_same_number_union(&p1->minor, &p2->minor);
&& tomoyo_same_number_union(&p1->mode, &p2->mode)
&& tomoyo_same_number_union(&p1->major, &p2->major)
&& tomoyo_same_number_union(&p1->minor, &p2->minor);
} }
/**
* tomoyo_merge_mkdev_acl - Merge duplicated "struct tomoyo_mkdev_acl" entry.
*
* @a: Pointer to "struct tomoyo_acl_info".
* @b: Pointer to "struct tomoyo_acl_info".
* @is_delete: True for @a &= ~@b, false for @a |= @b.
*
* Returns true if @a is empty, false otherwise.
*/
static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
struct tomoyo_acl_info *b, struct tomoyo_acl_info *b,
const bool is_delete) const bool is_delete)
{ {
u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl, u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
head)->perm; head)->perm;
...@@ -411,9 +516,9 @@ static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a, ...@@ -411,9 +516,9 @@ static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
* Caller holds tomoyo_read_lock(). * Caller holds tomoyo_read_lock().
*/ */
static int tomoyo_update_mkdev_acl(const u8 type, const char *filename, static int tomoyo_update_mkdev_acl(const u8 type, const char *filename,
char *mode, char *major, char *minor, char *mode, char *major, char *minor,
struct tomoyo_domain_info * const struct tomoyo_domain_info * const domain,
domain, const bool is_delete) const bool is_delete)
{ {
struct tomoyo_mkdev_acl e = { struct tomoyo_mkdev_acl e = {
.head.type = TOMOYO_TYPE_MKDEV_ACL, .head.type = TOMOYO_TYPE_MKDEV_ACL,
...@@ -436,16 +541,32 @@ static int tomoyo_update_mkdev_acl(const u8 type, const char *filename, ...@@ -436,16 +541,32 @@ static int tomoyo_update_mkdev_acl(const u8 type, const char *filename,
return error; return error;
} }
/**
* tomoyo_same_path2_acl - Check for duplicated "struct tomoyo_path2_acl" entry.
*
* @a: Pointer to "struct tomoyo_acl_info".
* @b: Pointer to "struct tomoyo_acl_info".
*
* Returns true if @a == @b except permission bits, false otherwise.
*/
static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a, static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
const struct tomoyo_acl_info *b) const struct tomoyo_acl_info *b)
{ {
const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head); const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head); const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
return tomoyo_same_acl_head(&p1->head, &p2->head) return tomoyo_same_name_union(&p1->name1, &p2->name1) &&
&& tomoyo_same_name_union(&p1->name1, &p2->name1) tomoyo_same_name_union(&p1->name2, &p2->name2);
&& tomoyo_same_name_union(&p1->name2, &p2->name2);
} }
/**
* tomoyo_merge_path2_acl - Merge duplicated "struct tomoyo_path2_acl" entry.
*
* @a: Pointer to "struct tomoyo_acl_info".
* @b: Pointer to "struct tomoyo_acl_info".
* @is_delete: True for @a &= ~@b, false for @a |= @b.
*
* Returns true if @a is empty, false otherwise.
*/
static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a, static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
struct tomoyo_acl_info *b, struct tomoyo_acl_info *b,
const bool is_delete) const bool is_delete)
...@@ -532,6 +653,14 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation, ...@@ -532,6 +653,14 @@ int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
return error; return error;
} }
/**
* tomoyo_same_path_number_acl - Check for duplicated "struct tomoyo_path_number_acl" entry.
*
* @a: Pointer to "struct tomoyo_acl_info".
* @b: Pointer to "struct tomoyo_acl_info".
*
* Returns true if @a == @b except permission bits, false otherwise.
*/
static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
const struct tomoyo_acl_info *b) const struct tomoyo_acl_info *b)
{ {
...@@ -539,11 +668,19 @@ static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a, ...@@ -539,11 +668,19 @@ static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
head); head);
const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2), const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
head); head);
return tomoyo_same_acl_head(&p1->head, &p2->head) return tomoyo_same_name_union(&p1->name, &p2->name) &&
&& tomoyo_same_name_union(&p1->name, &p2->name) tomoyo_same_number_union(&p1->number, &p2->number);
&& tomoyo_same_number_union(&p1->number, &p2->number);
} }
/**
* tomoyo_merge_path_number_acl - Merge duplicated "struct tomoyo_path_number_acl" entry.
*
* @a: Pointer to "struct tomoyo_acl_info".
* @b: Pointer to "struct tomoyo_acl_info".
* @is_delete: True for @a &= ~@b, false for @a |= @b.
*
* Returns true if @a is empty, false otherwise.
*/
static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
struct tomoyo_acl_info *b, struct tomoyo_acl_info *b,
const bool is_delete) const bool is_delete)
...@@ -575,8 +712,7 @@ static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a, ...@@ -575,8 +712,7 @@ static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
static int tomoyo_update_path_number_acl(const u8 type, const char *filename, static int tomoyo_update_path_number_acl(const u8 type, const char *filename,
char *number, char *number,
struct tomoyo_domain_info * const struct tomoyo_domain_info * const
domain, domain, const bool is_delete)
const bool is_delete)
{ {
struct tomoyo_path_number_acl e = { struct tomoyo_path_number_acl e = {
.head.type = TOMOYO_TYPE_PATH_NUMBER_ACL, .head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
...@@ -737,7 +873,7 @@ int tomoyo_path_perm(const u8 operation, struct path *path) ...@@ -737,7 +873,7 @@ int tomoyo_path_perm(const u8 operation, struct path *path)
* Returns 0 on success, negative value otherwise. * Returns 0 on success, negative value otherwise.
*/ */
int tomoyo_mkdev_perm(const u8 operation, struct path *path, int tomoyo_mkdev_perm(const u8 operation, struct path *path,
const unsigned int mode, unsigned int dev) const unsigned int mode, unsigned int dev)
{ {
struct tomoyo_request_info r; struct tomoyo_request_info r;
int error = -ENOMEM; int error = -ENOMEM;
......
...@@ -13,13 +13,30 @@ ...@@ -13,13 +13,30 @@
struct tomoyo_gc { struct tomoyo_gc {
struct list_head list; struct list_head list;
int type; enum tomoyo_policy_id type;
struct list_head *element; struct list_head *element;
}; };
static LIST_HEAD(tomoyo_gc_queue); static LIST_HEAD(tomoyo_gc_queue);
static DEFINE_MUTEX(tomoyo_gc_mutex); static DEFINE_MUTEX(tomoyo_gc_mutex);
/* Caller holds tomoyo_policy_lock mutex. */ /**
* tomoyo_add_to_gc - Add an entry to to be deleted list.
*
* @type: One of values in "enum tomoyo_policy_id".
* @element: Pointer to "struct list_head".
*
* Returns true on success, false otherwise.
*
* Caller holds tomoyo_policy_lock mutex.
*
* Adding an entry needs kmalloc(). Thus, if we try to add thousands of
* entries at once, it will take too long time. Thus, do not add more than 128
* entries per a scan. But to be able to handle worst case where all entries
* are in-use, we accept one more entry per a scan.
*
* If we use singly linked list using "struct list_head"->prev (which is
* LIST_POISON2), we can avoid kmalloc().
*/
static bool tomoyo_add_to_gc(const int type, struct list_head *element) static bool tomoyo_add_to_gc(const int type, struct list_head *element)
{ {
struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); struct tomoyo_gc *entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
...@@ -32,6 +49,13 @@ static bool tomoyo_add_to_gc(const int type, struct list_head *element) ...@@ -32,6 +49,13 @@ static bool tomoyo_add_to_gc(const int type, struct list_head *element)
return true; return true;
} }
/**
* tomoyo_del_transition_control - Delete members in "struct tomoyo_transition_control".
*
* @element: Pointer to "struct list_head".
*
* Returns nothing.
*/
static void tomoyo_del_transition_control(struct list_head *element) static void tomoyo_del_transition_control(struct list_head *element)
{ {
struct tomoyo_transition_control *ptr = struct tomoyo_transition_control *ptr =
...@@ -40,6 +64,13 @@ static void tomoyo_del_transition_control(struct list_head *element) ...@@ -40,6 +64,13 @@ static void tomoyo_del_transition_control(struct list_head *element)
tomoyo_put_name(ptr->program); tomoyo_put_name(ptr->program);
} }
/**
* tomoyo_del_aggregator - Delete members in "struct tomoyo_aggregator".
*
* @element: Pointer to "struct list_head".
*
* Returns nothing.
*/
static void tomoyo_del_aggregator(struct list_head *element) static void tomoyo_del_aggregator(struct list_head *element)
{ {
struct tomoyo_aggregator *ptr = struct tomoyo_aggregator *ptr =
...@@ -48,6 +79,13 @@ static void tomoyo_del_aggregator(struct list_head *element) ...@@ -48,6 +79,13 @@ static void tomoyo_del_aggregator(struct list_head *element)
tomoyo_put_name(ptr->aggregated_name); tomoyo_put_name(ptr->aggregated_name);
} }
/**
* tomoyo_del_manager - Delete members in "struct tomoyo_manager".
*
* @element: Pointer to "struct list_head".
*
* Returns nothing.
*/
static void tomoyo_del_manager(struct list_head *element) static void tomoyo_del_manager(struct list_head *element)
{ {
struct tomoyo_manager *ptr = struct tomoyo_manager *ptr =
...@@ -55,6 +93,13 @@ static void tomoyo_del_manager(struct list_head *element) ...@@ -55,6 +93,13 @@ static void tomoyo_del_manager(struct list_head *element)
tomoyo_put_name(ptr->manager); tomoyo_put_name(ptr->manager);
} }
/**
* tomoyo_del_acl - Delete members in "struct tomoyo_acl_info".
*
* @element: Pointer to "struct list_head".
*
* Returns nothing.
*/
static void tomoyo_del_acl(struct list_head *element) static void tomoyo_del_acl(struct list_head *element)
{ {
struct tomoyo_acl_info *acl = struct tomoyo_acl_info *acl =
...@@ -145,12 +190,26 @@ static bool tomoyo_del_domain(struct list_head *element) ...@@ -145,12 +190,26 @@ static bool tomoyo_del_domain(struct list_head *element)
} }
/**
* tomoyo_del_name - Delete members in "struct tomoyo_name".
*
* @element: Pointer to "struct list_head".
*
* Returns nothing.
*/
static void tomoyo_del_name(struct list_head *element) static void tomoyo_del_name(struct list_head *element)
{ {
const struct tomoyo_name *ptr = const struct tomoyo_name *ptr =
container_of(element, typeof(*ptr), list); container_of(element, typeof(*ptr), head.list);
} }
/**
* tomoyo_del_path_group - Delete members in "struct tomoyo_path_group".
*
* @element: Pointer to "struct list_head".
*
* Returns nothing.
*/
static void tomoyo_del_path_group(struct list_head *element) static void tomoyo_del_path_group(struct list_head *element)
{ {
struct tomoyo_path_group *member = struct tomoyo_path_group *member =
...@@ -158,20 +217,43 @@ static void tomoyo_del_path_group(struct list_head *element) ...@@ -158,20 +217,43 @@ static void tomoyo_del_path_group(struct list_head *element)
tomoyo_put_name(member->member_name); tomoyo_put_name(member->member_name);
} }
/**
* tomoyo_del_group - Delete "struct tomoyo_group".
*
* @element: Pointer to "struct list_head".
*
* Returns nothing.
*/
static void tomoyo_del_group(struct list_head *element) static void tomoyo_del_group(struct list_head *element)
{ {
struct tomoyo_group *group = struct tomoyo_group *group =
container_of(element, typeof(*group), list); container_of(element, typeof(*group), head.list);
tomoyo_put_name(group->group_name); tomoyo_put_name(group->group_name);
} }
/**
* tomoyo_del_number_group - Delete members in "struct tomoyo_number_group".
*
* @element: Pointer to "struct list_head".
*
* Returns nothing.
*/
static void tomoyo_del_number_group(struct list_head *element) static void tomoyo_del_number_group(struct list_head *element)
{ {
struct tomoyo_number_group *member = struct tomoyo_number_group *member =
container_of(element, typeof(*member), head.list); container_of(element, typeof(*member), head.list);
} }
static bool tomoyo_collect_member(struct list_head *member_list, int id) /**
* tomoyo_collect_member - Delete elements with "struct tomoyo_acl_head".
*
* @id: One of values in "enum tomoyo_policy_id".
* @member_list: Pointer to "struct list_head".
*
* Returns true if some elements are deleted, false otherwise.
*/
static bool tomoyo_collect_member(const enum tomoyo_policy_id id,
struct list_head *member_list)
{ {
struct tomoyo_acl_head *member; struct tomoyo_acl_head *member;
list_for_each_entry(member, member_list, list) { list_for_each_entry(member, member_list, list) {
...@@ -195,13 +277,18 @@ static bool tomoyo_collect_acl(struct tomoyo_domain_info *domain) ...@@ -195,13 +277,18 @@ static bool tomoyo_collect_acl(struct tomoyo_domain_info *domain)
return true; return true;
} }
/**
* tomoyo_collect_entry - Scan lists for deleted elements.
*
* Returns nothing.
*/
static void tomoyo_collect_entry(void) static void tomoyo_collect_entry(void)
{ {
int i; int i;
if (mutex_lock_interruptible(&tomoyo_policy_lock)) if (mutex_lock_interruptible(&tomoyo_policy_lock))
return; return;
for (i = 0; i < TOMOYO_MAX_POLICY; i++) { for (i = 0; i < TOMOYO_MAX_POLICY; i++) {
if (!tomoyo_collect_member(&tomoyo_policy_list[i], i)) if (!tomoyo_collect_member(i, &tomoyo_policy_list[i]))
goto unlock; goto unlock;
} }
{ {
...@@ -222,10 +309,10 @@ static void tomoyo_collect_entry(void) ...@@ -222,10 +309,10 @@ static void tomoyo_collect_entry(void)
} }
for (i = 0; i < TOMOYO_MAX_HASH; i++) { for (i = 0; i < TOMOYO_MAX_HASH; i++) {
struct tomoyo_name *ptr; struct tomoyo_name *ptr;
list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], list) { list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], head.list) {
if (atomic_read(&ptr->users)) if (atomic_read(&ptr->head.users))
continue; continue;
if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->list)) if (!tomoyo_add_to_gc(TOMOYO_ID_NAME, &ptr->head.list))
goto unlock; goto unlock;
} }
} }
...@@ -241,13 +328,14 @@ static void tomoyo_collect_entry(void) ...@@ -241,13 +328,14 @@ static void tomoyo_collect_entry(void)
id = TOMOYO_ID_NUMBER_GROUP; id = TOMOYO_ID_NUMBER_GROUP;
break; break;
} }
list_for_each_entry(group, list, list) { list_for_each_entry(group, list, head.list) {
if (!tomoyo_collect_member(&group->member_list, id)) if (!tomoyo_collect_member(id, &group->member_list))
goto unlock; goto unlock;
if (!list_empty(&group->member_list) || if (!list_empty(&group->member_list) ||
atomic_read(&group->users)) atomic_read(&group->head.users))
continue; continue;
if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP, &group->list)) if (!tomoyo_add_to_gc(TOMOYO_ID_GROUP,
&group->head.list))
goto unlock; goto unlock;
} }
} }
...@@ -291,6 +379,8 @@ static void tomoyo_kfree_entry(void) ...@@ -291,6 +379,8 @@ static void tomoyo_kfree_entry(void)
case TOMOYO_ID_NUMBER_GROUP: case TOMOYO_ID_NUMBER_GROUP:
tomoyo_del_number_group(element); tomoyo_del_number_group(element);
break; break;
case TOMOYO_MAX_POLICY:
break;
} }
tomoyo_memory_free(element); tomoyo_memory_free(element);
list_del(&p->list); list_del(&p->list);
...@@ -298,6 +388,17 @@ static void tomoyo_kfree_entry(void) ...@@ -298,6 +388,17 @@ static void tomoyo_kfree_entry(void)
} }
} }
/**
* tomoyo_gc_thread - Garbage collector thread function.
*
* @unused: Unused.
*
* In case OOM-killer choose this thread for termination, we create this thread
* as a short live thread whenever /sys/kernel/security/tomoyo/ interface was
* close()d.
*
* Returns 0.
*/
static int tomoyo_gc_thread(void *unused) static int tomoyo_gc_thread(void *unused)
{ {
daemonize("GC for TOMOYO"); daemonize("GC for TOMOYO");
......
...@@ -110,10 +110,10 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) ...@@ -110,10 +110,10 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
return NULL; return NULL;
if (mutex_lock_interruptible(&tomoyo_policy_lock)) if (mutex_lock_interruptible(&tomoyo_policy_lock))
goto out; goto out;
list_for_each_entry(group, &tomoyo_group_list[idx], list) { list_for_each_entry(group, &tomoyo_group_list[idx], head.list) {
if (e.group_name != group->group_name) if (e.group_name != group->group_name)
continue; continue;
atomic_inc(&group->users); atomic_inc(&group->head.users);
found = true; found = true;
break; break;
} }
...@@ -121,8 +121,8 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) ...@@ -121,8 +121,8 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e)); struct tomoyo_group *entry = tomoyo_commit_ok(&e, sizeof(e));
if (entry) { if (entry) {
INIT_LIST_HEAD(&entry->member_list); INIT_LIST_HEAD(&entry->member_list);
atomic_set(&entry->users, 1); atomic_set(&entry->head.users, 1);
list_add_tail_rcu(&entry->list, list_add_tail_rcu(&entry->head.list,
&tomoyo_group_list[idx]); &tomoyo_group_list[idx]);
group = entry; group = entry;
found = true; found = true;
...@@ -164,10 +164,10 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) ...@@ -164,10 +164,10 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name)
head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
if (mutex_lock_interruptible(&tomoyo_policy_lock)) if (mutex_lock_interruptible(&tomoyo_policy_lock))
return NULL; return NULL;
list_for_each_entry(ptr, head, list) { list_for_each_entry(ptr, head, head.list) {
if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
continue; continue;
atomic_inc(&ptr->users); atomic_inc(&ptr->head.users);
goto out; goto out;
} }
ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS); ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS);
...@@ -183,9 +183,9 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name) ...@@ -183,9 +183,9 @@ const struct tomoyo_path_info *tomoyo_get_name(const char *name)
atomic_add(allocated_len, &tomoyo_policy_memory_size); atomic_add(allocated_len, &tomoyo_policy_memory_size);
ptr->entry.name = ((char *) ptr) + sizeof(*ptr); ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
memmove((char *) ptr->entry.name, name, len); memmove((char *) ptr->entry.name, name, len);
atomic_set(&ptr->users, 1); atomic_set(&ptr->head.users, 1);
tomoyo_fill_path_info(&ptr->entry); tomoyo_fill_path_info(&ptr->entry);
list_add_tail(&ptr->list, head); list_add_tail(&ptr->head.list, head);
out: out:
mutex_unlock(&tomoyo_policy_lock); mutex_unlock(&tomoyo_policy_lock);
return ptr ? &ptr->entry : NULL; return ptr ? &ptr->entry : NULL;
......
...@@ -52,16 +52,28 @@ static int tomoyo_audit_mount_log(struct tomoyo_request_info *r) ...@@ -52,16 +52,28 @@ static int tomoyo_audit_mount_log(struct tomoyo_request_info *r)
r->param.mount.dir->name, type, flags); r->param.mount.dir->name, type, flags);
} }
/**
* tomoyo_check_mount_acl - Check permission for path path path number operation.
*
* @r: Pointer to "struct tomoyo_request_info".
* @ptr: Pointer to "struct tomoyo_acl_info".
*
* Returns true if granted, false otherwise.
*/
static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r, static bool tomoyo_check_mount_acl(struct tomoyo_request_info *r,
const struct tomoyo_acl_info *ptr) const struct tomoyo_acl_info *ptr)
{ {
const struct tomoyo_mount_acl *acl = const struct tomoyo_mount_acl *acl =
container_of(ptr, typeof(*acl), head); container_of(ptr, typeof(*acl), head);
return tomoyo_compare_number_union(r->param.mount.flags, &acl->flags) && return tomoyo_compare_number_union(r->param.mount.flags,
tomoyo_compare_name_union(r->param.mount.type, &acl->fs_type) && &acl->flags) &&
tomoyo_compare_name_union(r->param.mount.dir, &acl->dir_name) && tomoyo_compare_name_union(r->param.mount.type,
&acl->fs_type) &&
tomoyo_compare_name_union(r->param.mount.dir,
&acl->dir_name) &&
(!r->param.mount.need_dev || (!r->param.mount.need_dev ||
tomoyo_compare_name_union(r->param.mount.dev, &acl->dev_name)); tomoyo_compare_name_union(r->param.mount.dev,
&acl->dev_name));
} }
/** /**
...@@ -232,13 +244,20 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, ...@@ -232,13 +244,20 @@ int tomoyo_mount_permission(char *dev_name, struct path *path,
return error; return error;
} }
/**
* tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry.
*
* @a: Pointer to "struct tomoyo_acl_info".
* @b: Pointer to "struct tomoyo_acl_info".
*
* Returns true if @a == @b, false otherwise.
*/
static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a, static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
const struct tomoyo_acl_info *b) const struct tomoyo_acl_info *b)
{ {
const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head); const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head); const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
return tomoyo_same_acl_head(&p1->head, &p2->head) && return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) && tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) && tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
tomoyo_same_number_union(&p1->flags, &p2->flags); tomoyo_same_number_union(&p1->flags, &p2->flags);
......
...@@ -34,7 +34,7 @@ static int tomoyo_open(struct inode *inode, struct file *file) ...@@ -34,7 +34,7 @@ static int tomoyo_open(struct inode *inode, struct file *file)
*/ */
static int tomoyo_release(struct inode *inode, struct file *file) static int tomoyo_release(struct inode *inode, struct file *file)
{ {
return tomoyo_close_control(file); return tomoyo_close_control(file->private_data);
} }
/** /**
...@@ -63,7 +63,7 @@ static unsigned int tomoyo_poll(struct file *file, poll_table *wait) ...@@ -63,7 +63,7 @@ static unsigned int tomoyo_poll(struct file *file, poll_table *wait)
static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count, static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos) loff_t *ppos)
{ {
return tomoyo_read_control(file, buf, count); return tomoyo_read_control(file->private_data, buf, count);
} }
/** /**
...@@ -79,7 +79,7 @@ static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count, ...@@ -79,7 +79,7 @@ static ssize_t tomoyo_read(struct file *file, char __user *buf, size_t count,
static ssize_t tomoyo_write(struct file *file, const char __user *buf, static ssize_t tomoyo_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
return tomoyo_write_control(file, buf, count); return tomoyo_write_control(file->private_data, buf, count);
} }
/* /*
......
...@@ -21,7 +21,7 @@ bool tomoyo_policy_loaded; ...@@ -21,7 +21,7 @@ bool tomoyo_policy_loaded;
* @result: Pointer to "unsigned long". * @result: Pointer to "unsigned long".
* @str: Pointer to string to parse. * @str: Pointer to string to parse.
* *
* Returns value type on success, 0 otherwise. * Returns one of values in "enum tomoyo_value_type".
* *
* The @src is updated to point the first character after the value * The @src is updated to point the first character after the value
* on success. * on success.
...@@ -43,7 +43,7 @@ static u8 tomoyo_parse_ulong(unsigned long *result, char **str) ...@@ -43,7 +43,7 @@ static u8 tomoyo_parse_ulong(unsigned long *result, char **str)
} }
*result = simple_strtoul(cp, &ep, base); *result = simple_strtoul(cp, &ep, base);
if (cp == ep) if (cp == ep)
return 0; return TOMOYO_VALUE_TYPE_INVALID;
*str = ep; *str = ep;
switch (base) { switch (base) {
case 16: case 16:
...@@ -93,11 +93,9 @@ bool tomoyo_parse_name_union(const char *filename, ...@@ -93,11 +93,9 @@ bool tomoyo_parse_name_union(const char *filename,
return false; return false;
if (filename[0] == '@') { if (filename[0] == '@') {
ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP); ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP);
ptr->is_group = true;
return ptr->group != NULL; return ptr->group != NULL;
} }
ptr->filename = tomoyo_get_name(filename); ptr->filename = tomoyo_get_name(filename);
ptr->is_group = false;
return ptr->filename != NULL; return ptr->filename != NULL;
} }
...@@ -118,17 +116,16 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num) ...@@ -118,17 +116,16 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num)
if (!tomoyo_correct_word(data)) if (!tomoyo_correct_word(data))
return false; return false;
num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP); num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP);
num->is_group = true;
return num->group != NULL; return num->group != NULL;
} }
type = tomoyo_parse_ulong(&v, &data); type = tomoyo_parse_ulong(&v, &data);
if (!type) if (!type)
return false; return false;
num->values[0] = v; num->values[0] = v;
num->min_type = type; num->value_type[0] = type;
if (!*data) { if (!*data) {
num->values[1] = v; num->values[1] = v;
num->max_type = type; num->value_type[1] = type;
return true; return true;
} }
if (*data++ != '-') if (*data++ != '-')
...@@ -137,7 +134,7 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num) ...@@ -137,7 +134,7 @@ bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num)
if (!type || *data) if (!type || *data)
return false; return false;
num->values[1] = v; num->values[1] = v;
num->max_type = type; num->value_type[1] = type;
return true; return true;
} }
...@@ -184,6 +181,30 @@ static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3) ...@@ -184,6 +181,30 @@ static inline u8 tomoyo_make_byte(const u8 c1, const u8 c2, const u8 c3)
return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0'); return ((c1 - '0') << 6) + ((c2 - '0') << 3) + (c3 - '0');
} }
/**
* tomoyo_valid - Check whether the character is a valid char.
*
* @c: The character to check.
*
* Returns true if @c is a valid character, false otherwise.
*/
static inline bool tomoyo_valid(const unsigned char c)
{
return c > ' ' && c < 127;
}
/**
* tomoyo_invalid - Check whether the character is an invalid char.
*
* @c: The character to check.
*
* Returns true if @c is an invalid character, false otherwise.
*/
static inline bool tomoyo_invalid(const unsigned char c)
{
return c && (c <= ' ' || c >= 127);
}
/** /**
* tomoyo_str_starts - Check whether the given string starts with the given keyword. * tomoyo_str_starts - Check whether the given string starts with the given keyword.
* *
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment