Commit a238cf5b authored by Tetsuo Handa's avatar Tetsuo Handa Committed by James Morris

TOMOYO: Use struct for passing ACL line.

Use structure for passing ACL line, in preparation for supporting policy
namespace and conditional parameters.
Signed-off-by: default avatarTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent 0df7e8b8
...@@ -611,8 +611,11 @@ static int tomoyo_update_manager_entry(const char *manager, ...@@ -611,8 +611,11 @@ static int tomoyo_update_manager_entry(const char *manager,
const bool is_delete) const bool is_delete)
{ {
struct tomoyo_manager e = { }; struct tomoyo_manager e = { };
int error; struct tomoyo_acl_param param = {
.is_delete = is_delete,
.list = &tomoyo_policy_list[TOMOYO_ID_MANAGER],
};
int error = is_delete ? -ENOENT : -ENOMEM;
if (tomoyo_domain_def(manager)) { if (tomoyo_domain_def(manager)) {
if (!tomoyo_correct_domain(manager)) if (!tomoyo_correct_domain(manager))
return -EINVAL; return -EINVAL;
...@@ -622,12 +625,11 @@ static int tomoyo_update_manager_entry(const char *manager, ...@@ -622,12 +625,11 @@ static int tomoyo_update_manager_entry(const char *manager,
return -EINVAL; return -EINVAL;
} }
e.manager = tomoyo_get_name(manager); e.manager = tomoyo_get_name(manager);
if (!e.manager) if (e.manager) {
return -ENOMEM; error = tomoyo_update_policy(&e.head, sizeof(e), &param,
error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
&tomoyo_policy_list[TOMOYO_ID_MANAGER],
tomoyo_same_manager); tomoyo_same_manager);
tomoyo_put_name(e.manager); tomoyo_put_name(e.manager);
}
return error; return error;
} }
...@@ -821,18 +823,36 @@ static int tomoyo_delete_domain(char *domainname) ...@@ -821,18 +823,36 @@ static int tomoyo_delete_domain(char *domainname)
/** /**
* tomoyo_write_domain2 - Write domain policy. * tomoyo_write_domain2 - Write domain policy.
* *
* @head: Pointer to "struct tomoyo_io_buffer". * @list: Pointer to "struct list_head".
* @data: Policy to be interpreted.
* @is_delete: True if it is a delete request.
* *
* Returns 0 on success, negative value otherwise. * Returns 0 on success, negative value otherwise.
* *
* Caller holds tomoyo_read_lock(). * Caller holds tomoyo_read_lock().
*/ */
static int tomoyo_write_domain2(char *data, struct tomoyo_domain_info *domain, static int tomoyo_write_domain2(struct list_head *list, char *data,
const bool is_delete) const bool is_delete)
{ {
if (tomoyo_str_starts(&data, "allow_mount ")) struct tomoyo_acl_param param = {
return tomoyo_write_mount(data, domain, is_delete); .list = list,
return tomoyo_write_file(data, domain, is_delete); .data = data,
.is_delete = is_delete,
};
static const struct {
const char *keyword;
int (*write) (struct tomoyo_acl_param *);
} tomoyo_callback[1] = {
{ "file ", tomoyo_write_file },
};
u8 i;
for (i = 0; i < 1; i++) {
if (!tomoyo_str_starts(&param.data,
tomoyo_callback[i].keyword))
continue;
return tomoyo_callback[i].write(&param);
}
return -EINVAL;
} }
/** /**
...@@ -889,7 +909,7 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head) ...@@ -889,7 +909,7 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
domain->transition_failed = !is_delete; domain->transition_failed = !is_delete;
return 0; return 0;
} }
return tomoyo_write_domain2(data, domain, is_delete); return tomoyo_write_domain2(&domain->acl_info_list, data, is_delete);
} }
/** /**
...@@ -1213,26 +1233,19 @@ static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = { ...@@ -1213,26 +1233,19 @@ static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = {
*/ */
static int tomoyo_write_exception(struct tomoyo_io_buffer *head) static int tomoyo_write_exception(struct tomoyo_io_buffer *head)
{ {
char *data = head->write_buf; struct tomoyo_acl_param param = {
bool is_delete = tomoyo_str_starts(&data, "delete "); .data = head->write_buf,
u8 i;
static const struct {
const char *keyword;
int (*write) (char *, const bool);
} tomoyo_callback[1] = {
{ "aggregator ", tomoyo_write_aggregator },
}; };
u8 i;
param.is_delete = tomoyo_str_starts(&param.data, "delete ");
if (tomoyo_str_starts(&param.data, "aggregator "))
return tomoyo_write_aggregator(&param);
for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++) for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++)
if (tomoyo_str_starts(&data, tomoyo_transition_type[i])) if (tomoyo_str_starts(&param.data, tomoyo_transition_type[i]))
return tomoyo_write_transition_control(data, is_delete, return tomoyo_write_transition_control(&param, i);
i);
for (i = 0; i < 1; i++)
if (tomoyo_str_starts(&data, tomoyo_callback[i].keyword))
return tomoyo_callback[i].write(data, is_delete);
for (i = 0; i < TOMOYO_MAX_GROUP; i++) for (i = 0; i < TOMOYO_MAX_GROUP; i++)
if (tomoyo_str_starts(&data, tomoyo_group_name[i])) if (tomoyo_str_starts(&param.data, tomoyo_group_name[i]))
return tomoyo_write_group(data, is_delete, i); return tomoyo_write_group(&param, i);
return -EINVAL; return -EINVAL;
} }
...@@ -1490,7 +1503,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) ...@@ -1490,7 +1503,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
vsnprintf(buffer, len - 1, fmt, args); vsnprintf(buffer, len - 1, fmt, args);
va_end(args); va_end(args);
tomoyo_normalize_line(buffer); tomoyo_normalize_line(buffer);
tomoyo_write_domain2(buffer, r->domain, false); tomoyo_write_domain2(&r->domain->acl_info_list, buffer, false);
kfree(buffer); kfree(buffer);
/* fall through */ /* fall through */
case TOMOYO_CONFIG_PERMISSIVE: case TOMOYO_CONFIG_PERMISSIVE:
......
...@@ -397,6 +397,13 @@ struct tomoyo_mount_acl { ...@@ -397,6 +397,13 @@ struct tomoyo_mount_acl {
struct tomoyo_number_union flags; struct tomoyo_number_union flags;
}; };
/* Structure for holding a line from /sys/kernel/security/tomoyo/ interface. */
struct tomoyo_acl_param {
char *data;
struct list_head *list;
bool is_delete;
};
#define TOMOYO_MAX_IO_READ_QUEUE 32 #define TOMOYO_MAX_IO_READ_QUEUE 32
/* /*
...@@ -521,7 +528,7 @@ bool tomoyo_correct_domain(const unsigned char *domainname); ...@@ -521,7 +528,7 @@ bool tomoyo_correct_domain(const unsigned char *domainname);
bool tomoyo_correct_path(const char *filename); bool tomoyo_correct_path(const char *filename);
bool tomoyo_correct_word(const char *string); bool tomoyo_correct_word(const char *string);
bool tomoyo_domain_def(const unsigned char *buffer); bool tomoyo_domain_def(const unsigned char *buffer);
bool tomoyo_parse_name_union(const char *filename, bool tomoyo_parse_name_union(struct tomoyo_acl_param *param,
struct tomoyo_name_union *ptr); struct tomoyo_name_union *ptr);
const struct tomoyo_path_info * const struct tomoyo_path_info *
tomoyo_path_matches_group(const struct tomoyo_path_info *pathname, tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
...@@ -531,7 +538,8 @@ bool tomoyo_number_matches_group(const unsigned long min, ...@@ -531,7 +538,8 @@ bool tomoyo_number_matches_group(const unsigned long min,
const struct tomoyo_group *group); const struct tomoyo_group *group);
bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
const struct tomoyo_path_info *pattern); const struct tomoyo_path_info *pattern);
bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num); bool tomoyo_parse_number_union(struct tomoyo_acl_param *param,
struct tomoyo_number_union *ptr);
bool tomoyo_tokenize(char *buffer, char *w[], size_t size); bool tomoyo_tokenize(char *buffer, char *w[], size_t size);
bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain);
int tomoyo_init_request_info(struct tomoyo_request_info *r, int tomoyo_init_request_info(struct tomoyo_request_info *r,
...@@ -540,21 +548,19 @@ int tomoyo_init_request_info(struct tomoyo_request_info *r, ...@@ -540,21 +548,19 @@ int tomoyo_init_request_info(struct tomoyo_request_info *r,
int tomoyo_mount_permission(char *dev_name, struct path *path, int tomoyo_mount_permission(char *dev_name, struct path *path,
const char *type, unsigned long flags, const char *type, unsigned long flags,
void *data_page); void *data_page);
int tomoyo_write_aggregator(char *data, const bool is_delete); int tomoyo_write_aggregator(struct tomoyo_acl_param *param);
int tomoyo_write_transition_control(char *data, const bool is_delete, int tomoyo_write_transition_control(struct tomoyo_acl_param *param,
const u8 type); const u8 type);
int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain, int tomoyo_write_file(struct tomoyo_acl_param *param);
const bool is_delete); int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type);
int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain,
const bool is_delete);
int tomoyo_write_group(char *data, const bool is_delete, const u8 type);
int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3))); __attribute__ ((format(printf, 2, 3)));
struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname); struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname, struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
const u8 profile); const u8 profile);
struct tomoyo_profile *tomoyo_profile(const u8 profile); struct tomoyo_profile *tomoyo_profile(const u8 profile);
struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 type); struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param,
const u8 idx);
unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
const u8 index); const u8 index);
void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
...@@ -587,7 +593,7 @@ void tomoyo_put_name_union(struct tomoyo_name_union *ptr); ...@@ -587,7 +593,7 @@ void tomoyo_put_name_union(struct tomoyo_name_union *ptr);
void tomoyo_run_gc(void); void tomoyo_run_gc(void);
void tomoyo_memory_free(void *ptr); void tomoyo_memory_free(void *ptr);
int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
bool is_delete, struct tomoyo_domain_info *domain, struct tomoyo_acl_param *param,
bool (*check_duplicate) (const struct tomoyo_acl_info bool (*check_duplicate) (const struct tomoyo_acl_info
*, *,
const struct tomoyo_acl_info const struct tomoyo_acl_info
...@@ -596,7 +602,7 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, ...@@ -596,7 +602,7 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
struct tomoyo_acl_info *, struct tomoyo_acl_info *,
const bool)); const bool));
int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
bool is_delete, struct list_head *list, struct tomoyo_acl_param *param,
bool (*check_duplicate) (const struct tomoyo_acl_head bool (*check_duplicate) (const struct tomoyo_acl_head
*, *,
const struct tomoyo_acl_head const struct tomoyo_acl_head
...@@ -604,6 +610,8 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, ...@@ -604,6 +610,8 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
void tomoyo_check_acl(struct tomoyo_request_info *r, void tomoyo_check_acl(struct tomoyo_request_info *r,
bool (*check_entry) (struct tomoyo_request_info *, bool (*check_entry) (struct tomoyo_request_info *,
const struct tomoyo_acl_info *)); const struct tomoyo_acl_info *));
char *tomoyo_read_token(struct tomoyo_acl_param *param);
bool tomoyo_permstr(const char *string, const char *keyword);
/********** External variable definitions. **********/ /********** External variable definitions. **********/
......
...@@ -20,8 +20,7 @@ struct tomoyo_domain_info tomoyo_kernel_domain; ...@@ -20,8 +20,7 @@ struct tomoyo_domain_info tomoyo_kernel_domain;
* *
* @new_entry: Pointer to "struct tomoyo_acl_info". * @new_entry: Pointer to "struct tomoyo_acl_info".
* @size: Size of @new_entry in bytes. * @size: Size of @new_entry in bytes.
* @is_delete: True if it is a delete request. * @param: Pointer to "struct tomoyo_acl_param".
* @list: Pointer to "struct list_head".
* @check_duplicate: Callback function to find duplicated entry. * @check_duplicate: Callback function to find duplicated entry.
* *
* Returns 0 on success, negative value otherwise. * Returns 0 on success, negative value otherwise.
...@@ -29,25 +28,26 @@ struct tomoyo_domain_info tomoyo_kernel_domain; ...@@ -29,25 +28,26 @@ struct tomoyo_domain_info tomoyo_kernel_domain;
* Caller holds tomoyo_read_lock(). * Caller holds tomoyo_read_lock().
*/ */
int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size, int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
bool is_delete, struct list_head *list, struct tomoyo_acl_param *param,
bool (*check_duplicate) (const struct tomoyo_acl_head bool (*check_duplicate) (const struct tomoyo_acl_head
*, *,
const struct tomoyo_acl_head const struct tomoyo_acl_head
*)) *))
{ {
int error = is_delete ? -ENOENT : -ENOMEM; int error = param->is_delete ? -ENOENT : -ENOMEM;
struct tomoyo_acl_head *entry; struct tomoyo_acl_head *entry;
struct list_head *list = param->list;
if (mutex_lock_interruptible(&tomoyo_policy_lock)) if (mutex_lock_interruptible(&tomoyo_policy_lock))
return -ENOMEM; return -ENOMEM;
list_for_each_entry_rcu(entry, list, list) { list_for_each_entry_rcu(entry, list, list) {
if (!check_duplicate(entry, new_entry)) if (!check_duplicate(entry, new_entry))
continue; continue;
entry->is_deleted = is_delete; entry->is_deleted = param->is_delete;
error = 0; error = 0;
break; break;
} }
if (error && !is_delete) { if (error && !param->is_delete) {
entry = tomoyo_commit_ok(new_entry, size); entry = tomoyo_commit_ok(new_entry, size);
if (entry) { if (entry) {
list_add_tail_rcu(&entry->list, list); list_add_tail_rcu(&entry->list, list);
...@@ -77,8 +77,7 @@ static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a, ...@@ -77,8 +77,7 @@ static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a,
* *
* @new_entry: Pointer to "struct tomoyo_acl_info". * @new_entry: Pointer to "struct tomoyo_acl_info".
* @size: Size of @new_entry in bytes. * @size: Size of @new_entry in bytes.
* @is_delete: True if it is a delete request. * @param: Pointer to "struct tomoyo_acl_param".
* @domain: Pointer to "struct tomoyo_domain_info".
* @check_duplicate: Callback function to find duplicated entry. * @check_duplicate: Callback function to find duplicated entry.
* @merge_duplicate: Callback function to merge duplicated entry. * @merge_duplicate: Callback function to merge duplicated entry.
* *
...@@ -87,7 +86,7 @@ static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a, ...@@ -87,7 +86,7 @@ static inline bool tomoyo_same_acl_head(const struct tomoyo_acl_info *a,
* Caller holds tomoyo_read_lock(). * Caller holds tomoyo_read_lock().
*/ */
int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
bool is_delete, struct tomoyo_domain_info *domain, struct tomoyo_acl_param *param,
bool (*check_duplicate) (const struct tomoyo_acl_info bool (*check_duplicate) (const struct tomoyo_acl_info
*, *,
const struct tomoyo_acl_info const struct tomoyo_acl_info
...@@ -96,12 +95,14 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, ...@@ -96,12 +95,14 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
struct tomoyo_acl_info *, struct tomoyo_acl_info *,
const bool)) const bool))
{ {
const bool is_delete = param->is_delete;
int error = is_delete ? -ENOENT : -ENOMEM; int error = is_delete ? -ENOENT : -ENOMEM;
struct tomoyo_acl_info *entry; struct tomoyo_acl_info *entry;
struct list_head * const list = param->list;
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, list, list) {
if (!tomoyo_same_acl_head(entry, new_entry) || if (!tomoyo_same_acl_head(entry, new_entry) ||
!check_duplicate(entry, new_entry)) !check_duplicate(entry, new_entry))
continue; continue;
...@@ -116,7 +117,7 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size, ...@@ -116,7 +117,7 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
if (error && !is_delete) { if (error && !is_delete) {
entry = tomoyo_commit_ok(new_entry, size); entry = tomoyo_commit_ok(new_entry, size);
if (entry) { if (entry) {
list_add_tail_rcu(&entry->list, &domain->acl_info_list); list_add_tail_rcu(&entry->list, list);
error = 0; error = 0;
} }
} }
...@@ -163,6 +164,14 @@ static const char *tomoyo_last_word(const char *name) ...@@ -163,6 +164,14 @@ static const char *tomoyo_last_word(const char *name)
return name; return name;
} }
/**
* tomoyo_same_transition_control - Check for duplicated "struct tomoyo_transition_control" entry.
*
* @a: Pointer to "struct tomoyo_acl_head".
* @b: Pointer to "struct tomoyo_acl_head".
*
* Returns true if @a == @b, false otherwise.
*/
static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a, static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
const struct tomoyo_acl_head *b) const struct tomoyo_acl_head *b)
{ {
...@@ -178,22 +187,28 @@ static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a, ...@@ -178,22 +187,28 @@ static bool tomoyo_same_transition_control(const struct tomoyo_acl_head *a,
} }
/** /**
* tomoyo_update_transition_control_entry - Update "struct tomoyo_transition_control" list. * tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
* *
* @domainname: The name of domain. Maybe NULL. * @param: Pointer to "struct tomoyo_acl_param".
* @program: The name of program. Maybe NULL. * @type: Type of this entry.
* @type: Type of transition.
* @is_delete: True if it is a delete request.
* *
* Returns 0 on success, negative value otherwise. * Returns 0 on success, negative value otherwise.
*/ */
static int tomoyo_update_transition_control_entry(const char *domainname, int tomoyo_write_transition_control(struct tomoyo_acl_param *param,
const char *program, const u8 type)
const u8 type,
const bool is_delete)
{ {
struct tomoyo_transition_control e = { .type = type }; struct tomoyo_transition_control e = { .type = type };
int error = is_delete ? -ENOENT : -ENOMEM; int error = param->is_delete ? -ENOENT : -ENOMEM;
char *program = param->data;
char *domainname = strstr(program, " from ");
if (domainname) {
*domainname = '\0';
domainname += 6;
} else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
type == TOMOYO_TRANSITION_CONTROL_KEEP) {
domainname = program;
program = NULL;
}
if (program) { if (program) {
if (!tomoyo_correct_path(program)) if (!tomoyo_correct_path(program))
return -EINVAL; return -EINVAL;
...@@ -211,41 +226,15 @@ static int tomoyo_update_transition_control_entry(const char *domainname, ...@@ -211,41 +226,15 @@ static int tomoyo_update_transition_control_entry(const char *domainname,
if (!e.domainname) if (!e.domainname)
goto out; goto out;
} }
error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, param->list = &tomoyo_policy_list[TOMOYO_ID_TRANSITION_CONTROL];
&tomoyo_policy_list error = tomoyo_update_policy(&e.head, sizeof(e), param,
[TOMOYO_ID_TRANSITION_CONTROL],
tomoyo_same_transition_control); tomoyo_same_transition_control);
out: out:
tomoyo_put_name(e.domainname); tomoyo_put_name(e.domainname);
tomoyo_put_name(e.program); tomoyo_put_name(e.program);
return error; return error;
} }
/**
* tomoyo_write_transition_control - Write "struct tomoyo_transition_control" list.
*
* @data: String to parse.
* @is_delete: True if it is a delete request.
* @type: Type of this entry.
*
* Returns 0 on success, negative value otherwise.
*/
int tomoyo_write_transition_control(char *data, const bool is_delete,
const u8 type)
{
char *domainname = strstr(data, " from ");
if (domainname) {
*domainname = '\0';
domainname += 6;
} else if (type == TOMOYO_TRANSITION_CONTROL_NO_KEEP ||
type == TOMOYO_TRANSITION_CONTROL_KEEP) {
domainname = data;
data = NULL;
}
return tomoyo_update_transition_control_entry(domainname, data, type,
is_delete);
}
/** /**
* tomoyo_transition_type - Get domain transition type. * tomoyo_transition_type - Get domain transition type.
* *
...@@ -303,34 +292,41 @@ static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname, ...@@ -303,34 +292,41 @@ static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname,
return type; return type;
} }
/**
* tomoyo_same_aggregator - Check for duplicated "struct tomoyo_aggregator" entry.
*
* @a: Pointer to "struct tomoyo_acl_head".
* @b: Pointer to "struct tomoyo_acl_head".
*
* Returns true if @a == @b, false otherwise.
*/
static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a, static bool tomoyo_same_aggregator(const struct tomoyo_acl_head *a,
const struct tomoyo_acl_head *b) const struct tomoyo_acl_head *b)
{ {
const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1), head); const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1),
const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), head); head);
const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2),
head);
return p1->original_name == p2->original_name && return p1->original_name == p2->original_name &&
p1->aggregated_name == p2->aggregated_name; p1->aggregated_name == p2->aggregated_name;
} }
/** /**
* tomoyo_update_aggregator_entry - Update "struct tomoyo_aggregator" list. * tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
* *
* @original_name: The original program's name. * @param: Pointer to "struct tomoyo_acl_param".
* @aggregated_name: The program name to use.
* @is_delete: True if it is a delete request.
* *
* Returns 0 on success, negative value otherwise. * Returns 0 on success, negative value otherwise.
* *
* Caller holds tomoyo_read_lock(). * Caller holds tomoyo_read_lock().
*/ */
static int tomoyo_update_aggregator_entry(const char *original_name, int tomoyo_write_aggregator(struct tomoyo_acl_param *param)
const char *aggregated_name,
const bool is_delete)
{ {
struct tomoyo_aggregator e = { }; struct tomoyo_aggregator e = { };
int error = is_delete ? -ENOENT : -ENOMEM; int error = param->is_delete ? -ENOENT : -ENOMEM;
const char *original_name = tomoyo_read_token(param);
if (!tomoyo_correct_path(original_name) || const char *aggregated_name = tomoyo_read_token(param);
if (!tomoyo_correct_word(original_name) ||
!tomoyo_correct_path(aggregated_name)) !tomoyo_correct_path(aggregated_name))
return -EINVAL; return -EINVAL;
e.original_name = tomoyo_get_name(original_name); e.original_name = tomoyo_get_name(original_name);
...@@ -338,35 +334,15 @@ static int tomoyo_update_aggregator_entry(const char *original_name, ...@@ -338,35 +334,15 @@ static int tomoyo_update_aggregator_entry(const char *original_name,
if (!e.original_name || !e.aggregated_name || if (!e.original_name || !e.aggregated_name ||
e.aggregated_name->is_patterned) /* No patterns allowed. */ e.aggregated_name->is_patterned) /* No patterns allowed. */
goto out; goto out;
error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, param->list = &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR];
&tomoyo_policy_list[TOMOYO_ID_AGGREGATOR], error = tomoyo_update_policy(&e.head, sizeof(e), param,
tomoyo_same_aggregator); tomoyo_same_aggregator);
out: out:
tomoyo_put_name(e.original_name); tomoyo_put_name(e.original_name);
tomoyo_put_name(e.aggregated_name); tomoyo_put_name(e.aggregated_name);
return error; return error;
} }
/**
* tomoyo_write_aggregator - Write "struct tomoyo_aggregator" list.
*
* @data: String to parse.
* @is_delete: True if it is a delete request.
*
* Returns 0 on success, negative value otherwise.
*
* Caller holds tomoyo_read_lock().
*/
int tomoyo_write_aggregator(char *data, const bool is_delete)
{
char *cp = strchr(data, ' ');
if (!cp)
return -EINVAL;
*cp++ = '\0';
return tomoyo_update_aggregator_entry(data, cp, is_delete);
}
/** /**
* tomoyo_assign_domain - Create a domain. * tomoyo_assign_domain - Create a domain.
* *
......
This diff is collapsed.
...@@ -28,48 +28,41 @@ static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a, ...@@ -28,48 +28,41 @@ static bool tomoyo_same_number_group(const struct tomoyo_acl_head *a,
/** /**
* tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list. * tomoyo_write_group - Write "struct tomoyo_path_group"/"struct tomoyo_number_group" list.
* *
* @data: String to parse. * @param: Pointer to "struct tomoyo_acl_param".
* @is_delete: True if it is a delete request.
* @type: Type of this group. * @type: Type of this group.
* *
* Returns 0 on success, negative value otherwise. * Returns 0 on success, negative value otherwise.
*/ */
int tomoyo_write_group(char *data, const bool is_delete, const u8 type) int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type)
{ {
struct tomoyo_group *group; struct tomoyo_group *group = tomoyo_get_group(param, type);
struct list_head *member;
char *w[2];
int error = -EINVAL; int error = -EINVAL;
if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
return -EINVAL;
group = tomoyo_get_group(w[0], type);
if (!group) if (!group)
return -ENOMEM; return -ENOMEM;
member = &group->member_list; param->list = &group->member_list;
if (type == TOMOYO_PATH_GROUP) { if (type == TOMOYO_PATH_GROUP) {
struct tomoyo_path_group e = { }; struct tomoyo_path_group e = { };
e.member_name = tomoyo_get_name(w[1]); e.member_name = tomoyo_get_name(tomoyo_read_token(param));
if (!e.member_name) { if (!e.member_name) {
error = -ENOMEM; error = -ENOMEM;
goto out; goto out;
} }
error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, error = tomoyo_update_policy(&e.head, sizeof(e), param,
member, tomoyo_same_path_group); tomoyo_same_path_group);
tomoyo_put_name(e.member_name); tomoyo_put_name(e.member_name);
} else if (type == TOMOYO_NUMBER_GROUP) { } else if (type == TOMOYO_NUMBER_GROUP) {
struct tomoyo_number_group e = { }; struct tomoyo_number_group e = { };
if (w[1][0] == '@' if (param->data[0] == '@' ||
|| !tomoyo_parse_number_union(w[1], &e.number) !tomoyo_parse_number_union(param, &e.number))
|| e.number.values[0] > e.number.values[1])
goto out; goto out;
error = tomoyo_update_policy(&e.head, sizeof(e), is_delete, error = tomoyo_update_policy(&e.head, sizeof(e), param,
member, tomoyo_same_number_group); tomoyo_same_number_group);
/* /*
* tomoyo_put_number_union() is not needed because * tomoyo_put_number_union() is not needed because
* w[1][0] != '@'. * param->data[0] != '@'.
*/ */
} }
out: out:
tomoyo_put_group(group); tomoyo_put_group(group);
return error; return error;
} }
......
...@@ -93,15 +93,18 @@ void tomoyo_memory_free(void *ptr) ...@@ -93,15 +93,18 @@ void tomoyo_memory_free(void *ptr)
/** /**
* tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group". * tomoyo_get_group - Allocate memory for "struct tomoyo_path_group"/"struct tomoyo_number_group".
* *
* @group_name: The name of address group. * @param: Pointer to "struct tomoyo_acl_param".
* @idx: Index number. * @idx: Index number.
* *
* Returns pointer to "struct tomoyo_group" on success, NULL otherwise. * Returns pointer to "struct tomoyo_group" on success, NULL otherwise.
*/ */
struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) struct tomoyo_group *tomoyo_get_group(struct tomoyo_acl_param *param,
const u8 idx)
{ {
struct tomoyo_group e = { }; struct tomoyo_group e = { };
struct tomoyo_group *group = NULL; struct tomoyo_group *group = NULL;
struct list_head *list;
const char *group_name = tomoyo_read_token(param);
bool found = false; bool found = false;
if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP) if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP)
return NULL; return NULL;
...@@ -110,7 +113,8 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) ...@@ -110,7 +113,8 @@ 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], head.list) { list = &tomoyo_group_list[idx];
list_for_each_entry(group, list, head.list) {
if (e.group_name != group->group_name) if (e.group_name != group->group_name)
continue; continue;
atomic_inc(&group->head.users); atomic_inc(&group->head.users);
...@@ -122,14 +126,13 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx) ...@@ -122,14 +126,13 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
if (entry) { if (entry) {
INIT_LIST_HEAD(&entry->member_list); INIT_LIST_HEAD(&entry->member_list);
atomic_set(&entry->head.users, 1); atomic_set(&entry->head.users, 1);
list_add_tail_rcu(&entry->head.list, list_add_tail_rcu(&entry->head.list, list);
&tomoyo_group_list[idx]);
group = entry; group = entry;
found = true; found = true;
} }
} }
mutex_unlock(&tomoyo_policy_lock); mutex_unlock(&tomoyo_policy_lock);
out: out:
tomoyo_put_name(e.group_name); tomoyo_put_name(e.group_name);
return found ? group : NULL; return found ? group : NULL;
} }
...@@ -210,6 +213,8 @@ void __init tomoyo_mm_init(void) ...@@ -210,6 +213,8 @@ void __init tomoyo_mm_init(void)
idx = tomoyo_read_lock(); idx = tomoyo_read_lock();
if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
panic("Can't register tomoyo_kernel_domain"); panic("Can't register tomoyo_kernel_domain");
#if 0
/* Will be replaced with tomoyo_load_builtin_policy(). */
{ {
/* Load built-in policy. */ /* Load built-in policy. */
tomoyo_write_transition_control("/sbin/hotplug", false, tomoyo_write_transition_control("/sbin/hotplug", false,
...@@ -217,6 +222,7 @@ void __init tomoyo_mm_init(void) ...@@ -217,6 +222,7 @@ void __init tomoyo_mm_init(void)
tomoyo_write_transition_control("/sbin/modprobe", false, tomoyo_write_transition_control("/sbin/modprobe", false,
TOMOYO_TRANSITION_CONTROL_INITIALIZE); TOMOYO_TRANSITION_CONTROL_INITIALIZE);
} }
#endif
tomoyo_read_unlock(idx); tomoyo_read_unlock(idx);
} }
......
...@@ -243,56 +243,3 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, ...@@ -243,56 +243,3 @@ int tomoyo_mount_permission(char *dev_name, struct path *path,
tomoyo_read_unlock(idx); tomoyo_read_unlock(idx);
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,
const struct tomoyo_acl_info *b)
{
const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
return 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->fs_type, &p2->fs_type) &&
tomoyo_same_number_union(&p1->flags, &p2->flags);
}
/**
* tomoyo_write_mount - Write "struct tomoyo_mount_acl" list.
*
* @data: String to parse.
* @domain: Pointer to "struct tomoyo_domain_info".
* @is_delete: True if it is a delete request.
*
* Returns 0 on success, negative value otherwise.
*
* Caller holds tomoyo_read_lock().
*/
int tomoyo_write_mount(char *data, struct tomoyo_domain_info *domain,
const bool is_delete)
{
struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
int error = is_delete ? -ENOENT : -ENOMEM;
char *w[4];
if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[3][0])
return -EINVAL;
if (!tomoyo_parse_name_union(w[0], &e.dev_name) ||
!tomoyo_parse_name_union(w[1], &e.dir_name) ||
!tomoyo_parse_name_union(w[2], &e.fs_type) ||
!tomoyo_parse_number_union(w[3], &e.flags))
goto out;
error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
tomoyo_same_mount_acl, NULL);
out:
tomoyo_put_name_union(&e.dev_name);
tomoyo_put_name_union(&e.dir_name);
tomoyo_put_name_union(&e.fs_type);
tomoyo_put_number_union(&e.flags);
return error;
}
...@@ -15,6 +15,46 @@ DEFINE_MUTEX(tomoyo_policy_lock); ...@@ -15,6 +15,46 @@ DEFINE_MUTEX(tomoyo_policy_lock);
/* Has /sbin/init started? */ /* Has /sbin/init started? */
bool tomoyo_policy_loaded; bool tomoyo_policy_loaded;
/**
* tomoyo_permstr - Find permission keywords.
*
* @string: String representation for permissions in foo/bar/buz format.
* @keyword: Keyword to find from @string/
*
* Returns ture if @keyword was found in @string, false otherwise.
*
* This function assumes that strncmp(w1, w2, strlen(w1)) != 0 if w1 != w2.
*/
bool tomoyo_permstr(const char *string, const char *keyword)
{
const char *cp = strstr(string, keyword);
if (cp)
return cp == string || *(cp - 1) == '/';
return false;
}
/**
* tomoyo_read_token - Read a word from a line.
*
* @param: Pointer to "struct tomoyo_acl_param".
*
* Returns a word on success, "" otherwise.
*
* To allow the caller to skip NULL check, this function returns "" rather than
* NULL if there is no more words to read.
*/
char *tomoyo_read_token(struct tomoyo_acl_param *param)
{
char *pos = param->data;
char *del = strchr(pos, ' ');
if (del)
*del++ = '\0';
else
del = pos + strlen(pos);
param->data = del;
return pos;
}
/** /**
* tomoyo_parse_ulong - Parse an "unsigned long" value. * tomoyo_parse_ulong - Parse an "unsigned long" value.
* *
...@@ -81,20 +121,23 @@ void tomoyo_print_ulong(char *buffer, const int buffer_len, ...@@ -81,20 +121,23 @@ void tomoyo_print_ulong(char *buffer, const int buffer_len,
/** /**
* tomoyo_parse_name_union - Parse a tomoyo_name_union. * tomoyo_parse_name_union - Parse a tomoyo_name_union.
* *
* @filename: Name or name group. * @param: Pointer to "struct tomoyo_acl_param".
* @ptr: Pointer to "struct tomoyo_name_union". * @ptr: Pointer to "struct tomoyo_name_union".
* *
* Returns true on success, false otherwise. * Returns true on success, false otherwise.
*/ */
bool tomoyo_parse_name_union(const char *filename, bool tomoyo_parse_name_union(struct tomoyo_acl_param *param,
struct tomoyo_name_union *ptr) struct tomoyo_name_union *ptr)
{ {
if (!tomoyo_correct_word(filename)) char *filename;
return false; if (param->data[0] == '@') {
if (filename[0] == '@') { param->data++;
ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP); ptr->group = tomoyo_get_group(param, TOMOYO_PATH_GROUP);
return ptr->group != NULL; return ptr->group != NULL;
} }
filename = tomoyo_read_token(param);
if (!tomoyo_correct_word(filename))
return false;
ptr->filename = tomoyo_get_name(filename); ptr->filename = tomoyo_get_name(filename);
return ptr->filename != NULL; return ptr->filename != NULL;
} }
...@@ -102,39 +145,41 @@ bool tomoyo_parse_name_union(const char *filename, ...@@ -102,39 +145,41 @@ bool tomoyo_parse_name_union(const char *filename,
/** /**
* tomoyo_parse_number_union - Parse a tomoyo_number_union. * tomoyo_parse_number_union - Parse a tomoyo_number_union.
* *
* @data: Number or number range or number group. * @param: Pointer to "struct tomoyo_acl_param".
* @ptr: Pointer to "struct tomoyo_number_union". * @ptr: Pointer to "struct tomoyo_number_union".
* *
* Returns true on success, false otherwise. * Returns true on success, false otherwise.
*/ */
bool tomoyo_parse_number_union(char *data, struct tomoyo_number_union *num) bool tomoyo_parse_number_union(struct tomoyo_acl_param *param,
struct tomoyo_number_union *ptr)
{ {
char *data;
u8 type; u8 type;
unsigned long v; unsigned long v;
memset(num, 0, sizeof(*num)); memset(ptr, 0, sizeof(*ptr));
if (data[0] == '@') { if (param->data[0] == '@') {
if (!tomoyo_correct_word(data)) param->data++;
return false; ptr->group = tomoyo_get_group(param, TOMOYO_NUMBER_GROUP);
num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP); return ptr->group != NULL;
return num->group != NULL;
} }
data = tomoyo_read_token(param);
type = tomoyo_parse_ulong(&v, &data); type = tomoyo_parse_ulong(&v, &data);
if (!type) if (type == TOMOYO_VALUE_TYPE_INVALID)
return false; return false;
num->values[0] = v; ptr->values[0] = v;
num->value_type[0] = type; ptr->value_type[0] = type;
if (!*data) { if (!*data) {
num->values[1] = v; ptr->values[1] = v;
num->value_type[1] = type; ptr->value_type[1] = type;
return true; return true;
} }
if (*data++ != '-') if (*data++ != '-')
return false; return false;
type = tomoyo_parse_ulong(&v, &data); type = tomoyo_parse_ulong(&v, &data);
if (!type || *data) if (type == TOMOYO_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
return false; return false;
num->values[1] = v; ptr->values[1] = v;
num->value_type[1] = type; ptr->value_type[1] = type;
return true; return true;
} }
...@@ -258,33 +303,6 @@ void tomoyo_normalize_line(unsigned char *buffer) ...@@ -258,33 +303,6 @@ void tomoyo_normalize_line(unsigned char *buffer)
*dp = '\0'; *dp = '\0';
} }
/**
* tomoyo_tokenize - Tokenize string.
*
* @buffer: The line to tokenize.
* @w: Pointer to "char *".
* @size: Sizeof @w .
*
* Returns true on success, false otherwise.
*/
bool tomoyo_tokenize(char *buffer, char *w[], size_t size)
{
int count = size / sizeof(char *);
int i;
for (i = 0; i < count; i++)
w[i] = "";
for (i = 0; i < count; i++) {
char *cp = strchr(buffer, ' ');
if (cp)
*cp = '\0';
w[i] = buffer;
if (!cp)
break;
buffer = cp + 1;
}
return i < count || !*buffer;
}
/** /**
* tomoyo_correct_word2 - Validate a string. * tomoyo_correct_word2 - Validate a string.
* *
......
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