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: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <jmorris@namei.org>
This commit is contained in:
parent
0df7e8b8f1
commit
a238cf5b89
|
@ -611,8 +611,11 @@ static int tomoyo_update_manager_entry(const char *manager,
|
|||
const bool is_delete)
|
||||
{
|
||||
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_correct_domain(manager))
|
||||
return -EINVAL;
|
||||
|
@ -622,12 +625,11 @@ static int tomoyo_update_manager_entry(const char *manager,
|
|||
return -EINVAL;
|
||||
}
|
||||
e.manager = tomoyo_get_name(manager);
|
||||
if (!e.manager)
|
||||
return -ENOMEM;
|
||||
error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
|
||||
&tomoyo_policy_list[TOMOYO_ID_MANAGER],
|
||||
if (e.manager) {
|
||||
error = tomoyo_update_policy(&e.head, sizeof(e), ¶m,
|
||||
tomoyo_same_manager);
|
||||
tomoyo_put_name(e.manager);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -821,18 +823,36 @@ static int tomoyo_delete_domain(char *domainname)
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
if (tomoyo_str_starts(&data, "allow_mount "))
|
||||
return tomoyo_write_mount(data, domain, is_delete);
|
||||
return tomoyo_write_file(data, domain, is_delete);
|
||||
struct tomoyo_acl_param param = {
|
||||
.list = list,
|
||||
.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(¶m.data,
|
||||
tomoyo_callback[i].keyword))
|
||||
continue;
|
||||
return tomoyo_callback[i].write(¶m);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -889,7 +909,7 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
|
|||
domain->transition_failed = !is_delete;
|
||||
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] = {
|
|||
*/
|
||||
static int tomoyo_write_exception(struct tomoyo_io_buffer *head)
|
||||
{
|
||||
char *data = head->write_buf;
|
||||
bool is_delete = tomoyo_str_starts(&data, "delete ");
|
||||
u8 i;
|
||||
static const struct {
|
||||
const char *keyword;
|
||||
int (*write) (char *, const bool);
|
||||
} tomoyo_callback[1] = {
|
||||
{ "aggregator ", tomoyo_write_aggregator },
|
||||
struct tomoyo_acl_param param = {
|
||||
.data = head->write_buf,
|
||||
};
|
||||
|
||||
u8 i;
|
||||
param.is_delete = tomoyo_str_starts(¶m.data, "delete ");
|
||||
if (tomoyo_str_starts(¶m.data, "aggregator "))
|
||||
return tomoyo_write_aggregator(¶m);
|
||||
for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++)
|
||||
if (tomoyo_str_starts(&data, tomoyo_transition_type[i]))
|
||||
return tomoyo_write_transition_control(data, is_delete,
|
||||
i);
|
||||
for (i = 0; i < 1; i++)
|
||||
if (tomoyo_str_starts(&data, tomoyo_callback[i].keyword))
|
||||
return tomoyo_callback[i].write(data, is_delete);
|
||||
if (tomoyo_str_starts(¶m.data, tomoyo_transition_type[i]))
|
||||
return tomoyo_write_transition_control(¶m, i);
|
||||
for (i = 0; i < TOMOYO_MAX_GROUP; i++)
|
||||
if (tomoyo_str_starts(&data, tomoyo_group_name[i]))
|
||||
return tomoyo_write_group(data, is_delete, i);
|
||||
if (tomoyo_str_starts(¶m.data, tomoyo_group_name[i]))
|
||||
return tomoyo_write_group(¶m, i);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1490,7 +1503,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
|
|||
vsnprintf(buffer, len - 1, fmt, args);
|
||||
va_end(args);
|
||||
tomoyo_normalize_line(buffer);
|
||||
tomoyo_write_domain2(buffer, r->domain, false);
|
||||
tomoyo_write_domain2(&r->domain->acl_info_list, buffer, false);
|
||||
kfree(buffer);
|
||||
/* fall through */
|
||||
case TOMOYO_CONFIG_PERMISSIVE:
|
||||
|
|
|
@ -397,6 +397,13 @@ struct tomoyo_mount_acl {
|
|||
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
|
||||
|
||||
/*
|
||||
|
@ -521,7 +528,7 @@ bool tomoyo_correct_domain(const unsigned char *domainname);
|
|||
bool tomoyo_correct_path(const char *filename);
|
||||
bool tomoyo_correct_word(const char *string);
|
||||
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);
|
||||
const struct tomoyo_path_info *
|
||||
tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
|
||||
|
@ -531,7 +538,8 @@ bool tomoyo_number_matches_group(const unsigned long min,
|
|||
const struct tomoyo_group *group);
|
||||
bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename,
|
||||
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_verbose_mode(const struct tomoyo_domain_info *domain);
|
||||
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,
|
||||
const char *type, unsigned long flags,
|
||||
void *data_page);
|
||||
int tomoyo_write_aggregator(char *data, const bool is_delete);
|
||||
int tomoyo_write_transition_control(char *data, const bool is_delete,
|
||||
int tomoyo_write_aggregator(struct tomoyo_acl_param *param);
|
||||
int tomoyo_write_transition_control(struct tomoyo_acl_param *param,
|
||||
const u8 type);
|
||||
int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain,
|
||||
const bool is_delete);
|
||||
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_write_file(struct tomoyo_acl_param *param);
|
||||
int tomoyo_write_group(struct tomoyo_acl_param *param, const u8 type);
|
||||
int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
|
||||
__attribute__ ((format(printf, 2, 3)));
|
||||
struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname);
|
||||
struct tomoyo_domain_info *tomoyo_assign_domain(const char *domainname,
|
||||
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,
|
||||
const u8 index);
|
||||
void tomoyo_fill_path_info(struct tomoyo_path_info *ptr);
|
||||
|
@ -587,7 +593,7 @@ void tomoyo_put_name_union(struct tomoyo_name_union *ptr);
|
|||
void tomoyo_run_gc(void);
|
||||
void tomoyo_memory_free(void *ptr);
|
||||
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
|
||||
*,
|
||||
const struct tomoyo_acl_info
|
||||
|
@ -596,7 +602,7 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
|
|||
struct tomoyo_acl_info *,
|
||||
const bool));
|
||||
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
|
||||
*,
|
||||
const struct tomoyo_acl_head
|
||||
|
@ -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,
|
||||
bool (*check_entry) (struct tomoyo_request_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. **********/
|
||||
|
||||
|
|
|
@ -20,8 +20,7 @@ struct tomoyo_domain_info tomoyo_kernel_domain;
|
|||
*
|
||||
* @new_entry: Pointer to "struct tomoyo_acl_info".
|
||||
* @size: Size of @new_entry in bytes.
|
||||
* @is_delete: True if it is a delete request.
|
||||
* @list: Pointer to "struct list_head".
|
||||
* @param: Pointer to "struct tomoyo_acl_param".
|
||||
* @check_duplicate: Callback function to find duplicated entry.
|
||||
*
|
||||
* Returns 0 on success, negative value otherwise.
|
||||
|
@ -29,25 +28,26 @@ struct tomoyo_domain_info tomoyo_kernel_domain;
|
|||
* Caller holds tomoyo_read_lock().
|
||||
*/
|
||||
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
|
||||
*,
|
||||
const struct tomoyo_acl_head
|
||||
*))
|
||||
{
|
||||
int error = is_delete ? -ENOENT : -ENOMEM;
|
||||
int error = param->is_delete ? -ENOENT : -ENOMEM;
|
||||
struct tomoyo_acl_head *entry;
|
||||
struct list_head *list = param->list;
|
||||
|
||||
if (mutex_lock_interruptible(&tomoyo_policy_lock))
|
||||
return -ENOMEM;
|
||||
list_for_each_entry_rcu(entry, list, list) {
|
||||
if (!check_duplicate(entry, new_entry))
|
||||
continue;
|
||||
entry->is_deleted = is_delete;
|
||||
entry->is_deleted = param->is_delete;
|
||||
error = 0;
|
||||
break;
|
||||
}
|
||||
if (error && !is_delete) {
|
||||
if (error && !param->is_delete) {
|
||||
entry = tomoyo_commit_ok(new_entry, size);
|
||||
if (entry) {
|
||||
list_add_tail_rcu(&entry->list, list);
|
||||
|
@ -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".
|
||||
* @size: Size of @new_entry in bytes.
|
||||
* @is_delete: True if it is a delete request.
|
||||
* @domain: Pointer to "struct tomoyo_domain_info".
|
||||
* @param: Pointer to "struct tomoyo_acl_param".
|
||||
* @check_duplicate: Callback function to find 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,
|
|||
* Caller holds tomoyo_read_lock().
|
||||
*/
|
||||
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
|
||||
*,
|
||||
const struct tomoyo_acl_info
|
||||
|
@ -96,12 +95,14 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
|
|||
struct tomoyo_acl_info *,
|
||||
const bool))
|
||||
{
|
||||
const bool is_delete = param->is_delete;
|
||||
int error = is_delete ? -ENOENT : -ENOMEM;
|
||||
struct tomoyo_acl_info *entry;
|
||||
struct list_head * const list = param->list;
|
||||
|
||||
if (mutex_lock_interruptible(&tomoyo_policy_lock))
|
||||
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) ||
|
||||
!check_duplicate(entry, new_entry))
|
||||
continue;
|
||||
|
@ -116,7 +117,7 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
|
|||
if (error && !is_delete) {
|
||||
entry = tomoyo_commit_ok(new_entry, size);
|
||||
if (entry) {
|
||||
list_add_tail_rcu(&entry->list, &domain->acl_info_list);
|
||||
list_add_tail_rcu(&entry->list, list);
|
||||
error = 0;
|
||||
}
|
||||
}
|
||||
|
@ -163,6 +164,14 @@ static const char *tomoyo_last_word(const char *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,
|
||||
const struct tomoyo_acl_head *b)
|
||||
{
|
||||
|
@ -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.
|
||||
* @program: The name of program. Maybe NULL.
|
||||
* @type: Type of transition.
|
||||
* @is_delete: True if it is a delete request.
|
||||
* @param: Pointer to "struct tomoyo_acl_param".
|
||||
* @type: Type of this entry.
|
||||
*
|
||||
* Returns 0 on success, negative value otherwise.
|
||||
*/
|
||||
static int tomoyo_update_transition_control_entry(const char *domainname,
|
||||
const char *program,
|
||||
const u8 type,
|
||||
const bool is_delete)
|
||||
int tomoyo_write_transition_control(struct tomoyo_acl_param *param,
|
||||
const u8 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 (!tomoyo_correct_path(program))
|
||||
return -EINVAL;
|
||||
|
@ -211,9 +226,8 @@ static int tomoyo_update_transition_control_entry(const char *domainname,
|
|||
if (!e.domainname)
|
||||
goto out;
|
||||
}
|
||||
error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
|
||||
&tomoyo_policy_list
|
||||
[TOMOYO_ID_TRANSITION_CONTROL],
|
||||
param->list = &tomoyo_policy_list[TOMOYO_ID_TRANSITION_CONTROL];
|
||||
error = tomoyo_update_policy(&e.head, sizeof(e), param,
|
||||
tomoyo_same_transition_control);
|
||||
out:
|
||||
tomoyo_put_name(e.domainname);
|
||||
|
@ -221,31 +235,6 @@ static int tomoyo_update_transition_control_entry(const char *domainname,
|
|||
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.
|
||||
*
|
||||
|
@ -303,34 +292,41 @@ static u8 tomoyo_transition_type(const struct tomoyo_path_info *domainname,
|
|||
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,
|
||||
const struct tomoyo_acl_head *b)
|
||||
{
|
||||
const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1), head);
|
||||
const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2), head);
|
||||
const struct tomoyo_aggregator *p1 = container_of(a, typeof(*p1),
|
||||
head);
|
||||
const struct tomoyo_aggregator *p2 = container_of(b, typeof(*p2),
|
||||
head);
|
||||
return p1->original_name == p2->original_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.
|
||||
* @aggregated_name: The program name to use.
|
||||
* @is_delete: True if it is a delete request.
|
||||
* @param: Pointer to "struct tomoyo_acl_param".
|
||||
*
|
||||
* Returns 0 on success, negative value otherwise.
|
||||
*
|
||||
* Caller holds tomoyo_read_lock().
|
||||
*/
|
||||
static int tomoyo_update_aggregator_entry(const char *original_name,
|
||||
const char *aggregated_name,
|
||||
const bool is_delete)
|
||||
int tomoyo_write_aggregator(struct tomoyo_acl_param *param)
|
||||
{
|
||||
struct tomoyo_aggregator e = { };
|
||||
int error = is_delete ? -ENOENT : -ENOMEM;
|
||||
|
||||
if (!tomoyo_correct_path(original_name) ||
|
||||
int error = param->is_delete ? -ENOENT : -ENOMEM;
|
||||
const char *original_name = tomoyo_read_token(param);
|
||||
const char *aggregated_name = tomoyo_read_token(param);
|
||||
if (!tomoyo_correct_word(original_name) ||
|
||||
!tomoyo_correct_path(aggregated_name))
|
||||
return -EINVAL;
|
||||
e.original_name = tomoyo_get_name(original_name);
|
||||
|
@ -338,8 +334,8 @@ static int tomoyo_update_aggregator_entry(const char *original_name,
|
|||
if (!e.original_name || !e.aggregated_name ||
|
||||
e.aggregated_name->is_patterned) /* No patterns allowed. */
|
||||
goto out;
|
||||
error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
|
||||
&tomoyo_policy_list[TOMOYO_ID_AGGREGATOR],
|
||||
param->list = &tomoyo_policy_list[TOMOYO_ID_AGGREGATOR];
|
||||
error = tomoyo_update_policy(&e.head, sizeof(e), param,
|
||||
tomoyo_same_aggregator);
|
||||
out:
|
||||
tomoyo_put_name(e.original_name);
|
||||
|
@ -347,26 +343,6 @@ static int tomoyo_update_aggregator_entry(const char *original_name,
|
|||
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.
|
||||
*
|
||||
|
|
|
@ -428,27 +428,25 @@ static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
|
|||
/**
|
||||
* tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list.
|
||||
*
|
||||
* @type: Type of operation.
|
||||
* @filename: Filename.
|
||||
* @domain: Pointer to "struct tomoyo_domain_info".
|
||||
* @is_delete: True if it is a delete request.
|
||||
* @perm: Permission.
|
||||
* @param: Pointer to "struct tomoyo_acl_param".
|
||||
*
|
||||
* Returns 0 on success, negative value otherwise.
|
||||
*
|
||||
* Caller holds tomoyo_read_lock().
|
||||
*/
|
||||
static int tomoyo_update_path_acl(const u8 type, const char *filename,
|
||||
struct tomoyo_domain_info * const domain,
|
||||
const bool is_delete)
|
||||
static int tomoyo_update_path_acl(const u16 perm,
|
||||
struct tomoyo_acl_param *param)
|
||||
{
|
||||
struct tomoyo_path_acl e = {
|
||||
.head.type = TOMOYO_TYPE_PATH_ACL,
|
||||
.perm = 1 << type
|
||||
.perm = perm
|
||||
};
|
||||
int error;
|
||||
if (!tomoyo_parse_name_union(filename, &e.name))
|
||||
return -EINVAL;
|
||||
error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
|
||||
if (!tomoyo_parse_name_union(param, &e.name))
|
||||
error = -EINVAL;
|
||||
else
|
||||
error = tomoyo_update_domain(&e.head, sizeof(e), param,
|
||||
tomoyo_same_path_acl,
|
||||
tomoyo_merge_path_acl);
|
||||
tomoyo_put_name_union(&e.name);
|
||||
|
@ -503,37 +501,30 @@ static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
|
|||
/**
|
||||
* tomoyo_update_mkdev_acl - Update "struct tomoyo_mkdev_acl" list.
|
||||
*
|
||||
* @type: Type of operation.
|
||||
* @filename: Filename.
|
||||
* @mode: Create mode.
|
||||
* @major: Device major number.
|
||||
* @minor: Device minor number.
|
||||
* @domain: Pointer to "struct tomoyo_domain_info".
|
||||
* @is_delete: True if it is a delete request.
|
||||
* @perm: Permission.
|
||||
* @param: Pointer to "struct tomoyo_acl_param".
|
||||
*
|
||||
* Returns 0 on success, negative value otherwise.
|
||||
*
|
||||
* Caller holds tomoyo_read_lock().
|
||||
*/
|
||||
static int tomoyo_update_mkdev_acl(const u8 type, const char *filename,
|
||||
char *mode, char *major, char *minor,
|
||||
struct tomoyo_domain_info * const domain,
|
||||
const bool is_delete)
|
||||
static int tomoyo_update_mkdev_acl(const u8 perm,
|
||||
struct tomoyo_acl_param *param)
|
||||
{
|
||||
struct tomoyo_mkdev_acl e = {
|
||||
.head.type = TOMOYO_TYPE_MKDEV_ACL,
|
||||
.perm = 1 << type
|
||||
.perm = perm
|
||||
};
|
||||
int error = is_delete ? -ENOENT : -ENOMEM;
|
||||
if (!tomoyo_parse_name_union(filename, &e.name) ||
|
||||
!tomoyo_parse_number_union(mode, &e.mode) ||
|
||||
!tomoyo_parse_number_union(major, &e.major) ||
|
||||
!tomoyo_parse_number_union(minor, &e.minor))
|
||||
goto out;
|
||||
error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
|
||||
int error;
|
||||
if (!tomoyo_parse_name_union(param, &e.name) ||
|
||||
!tomoyo_parse_number_union(param, &e.mode) ||
|
||||
!tomoyo_parse_number_union(param, &e.major) ||
|
||||
!tomoyo_parse_number_union(param, &e.minor))
|
||||
error = -EINVAL;
|
||||
else
|
||||
error = tomoyo_update_domain(&e.head, sizeof(e), param,
|
||||
tomoyo_same_mkdev_acl,
|
||||
tomoyo_merge_mkdev_acl);
|
||||
out:
|
||||
tomoyo_put_name_union(&e.name);
|
||||
tomoyo_put_number_union(&e.mode);
|
||||
tomoyo_put_number_union(&e.major);
|
||||
|
@ -586,33 +577,28 @@ static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
|
|||
/**
|
||||
* tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list.
|
||||
*
|
||||
* @type: Type of operation.
|
||||
* @filename1: First filename.
|
||||
* @filename2: Second filename.
|
||||
* @domain: Pointer to "struct tomoyo_domain_info".
|
||||
* @is_delete: True if it is a delete request.
|
||||
* @perm: Permission.
|
||||
* @param: Pointer to "struct tomoyo_acl_param".
|
||||
*
|
||||
* Returns 0 on success, negative value otherwise.
|
||||
*
|
||||
* Caller holds tomoyo_read_lock().
|
||||
*/
|
||||
static int tomoyo_update_path2_acl(const u8 type, const char *filename1,
|
||||
const char *filename2,
|
||||
struct tomoyo_domain_info * const domain,
|
||||
const bool is_delete)
|
||||
static int tomoyo_update_path2_acl(const u8 perm,
|
||||
struct tomoyo_acl_param *param)
|
||||
{
|
||||
struct tomoyo_path2_acl e = {
|
||||
.head.type = TOMOYO_TYPE_PATH2_ACL,
|
||||
.perm = 1 << type
|
||||
.perm = perm
|
||||
};
|
||||
int error = is_delete ? -ENOENT : -ENOMEM;
|
||||
if (!tomoyo_parse_name_union(filename1, &e.name1) ||
|
||||
!tomoyo_parse_name_union(filename2, &e.name2))
|
||||
goto out;
|
||||
error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
|
||||
int error;
|
||||
if (!tomoyo_parse_name_union(param, &e.name1) ||
|
||||
!tomoyo_parse_name_union(param, &e.name2))
|
||||
error = -EINVAL;
|
||||
else
|
||||
error = tomoyo_update_domain(&e.head, sizeof(e), param,
|
||||
tomoyo_same_path2_acl,
|
||||
tomoyo_merge_path2_acl);
|
||||
out:
|
||||
tomoyo_put_name_union(&e.name1);
|
||||
tomoyo_put_name_union(&e.name2);
|
||||
return error;
|
||||
|
@ -701,32 +687,26 @@ static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
|
|||
/**
|
||||
* tomoyo_update_path_number_acl - Update ioctl/chmod/chown/chgrp ACL.
|
||||
*
|
||||
* @type: Type of operation.
|
||||
* @filename: Filename.
|
||||
* @number: Number.
|
||||
* @domain: Pointer to "struct tomoyo_domain_info".
|
||||
* @is_delete: True if it is a delete request.
|
||||
* @perm: Permission.
|
||||
* @param: Pointer to "struct tomoyo_acl_param".
|
||||
*
|
||||
* Returns 0 on success, negative value otherwise.
|
||||
*/
|
||||
static int tomoyo_update_path_number_acl(const u8 type, const char *filename,
|
||||
char *number,
|
||||
struct tomoyo_domain_info * const
|
||||
domain, const bool is_delete)
|
||||
static int tomoyo_update_path_number_acl(const u8 perm,
|
||||
struct tomoyo_acl_param *param)
|
||||
{
|
||||
struct tomoyo_path_number_acl e = {
|
||||
.head.type = TOMOYO_TYPE_PATH_NUMBER_ACL,
|
||||
.perm = 1 << type
|
||||
.perm = perm
|
||||
};
|
||||
int error = is_delete ? -ENOENT : -ENOMEM;
|
||||
if (!tomoyo_parse_name_union(filename, &e.name))
|
||||
return -EINVAL;
|
||||
if (!tomoyo_parse_number_union(number, &e.number))
|
||||
goto out;
|
||||
error = tomoyo_update_domain(&e.head, sizeof(e), is_delete, domain,
|
||||
int error;
|
||||
if (!tomoyo_parse_name_union(param, &e.name) ||
|
||||
!tomoyo_parse_number_union(param, &e.number))
|
||||
error = -EINVAL;
|
||||
else
|
||||
error = tomoyo_update_domain(&e.head, sizeof(e), param,
|
||||
tomoyo_same_path_number_acl,
|
||||
tomoyo_merge_path_number_acl);
|
||||
out:
|
||||
tomoyo_put_name_union(&e.name);
|
||||
tomoyo_put_number_union(&e.number);
|
||||
return error;
|
||||
|
@ -963,53 +943,88 @@ int tomoyo_path2_perm(const u8 operation, struct path *path1,
|
|||
}
|
||||
|
||||
/**
|
||||
* tomoyo_write_file - Update file related list.
|
||||
* tomoyo_same_mount_acl - Check for duplicated "struct tomoyo_mount_acl" entry.
|
||||
*
|
||||
* @data: String to parse.
|
||||
* @domain: Pointer to "struct tomoyo_domain_info".
|
||||
* @is_delete: True if it is a delete request.
|
||||
* @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_update_mount_acl - Write "struct tomoyo_mount_acl" list.
|
||||
*
|
||||
* @param: Pointer to "struct tomoyo_acl_param".
|
||||
*
|
||||
* Returns 0 on success, negative value otherwise.
|
||||
*
|
||||
* Caller holds tomoyo_read_lock().
|
||||
*/
|
||||
int tomoyo_write_file(char *data, struct tomoyo_domain_info *domain,
|
||||
const bool is_delete)
|
||||
static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param)
|
||||
{
|
||||
char *w[5];
|
||||
struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
|
||||
int error;
|
||||
if (!tomoyo_parse_name_union(param, &e.dev_name) ||
|
||||
!tomoyo_parse_name_union(param, &e.dir_name) ||
|
||||
!tomoyo_parse_name_union(param, &e.fs_type) ||
|
||||
!tomoyo_parse_number_union(param, &e.flags))
|
||||
error = -EINVAL;
|
||||
else
|
||||
error = tomoyo_update_domain(&e.head, sizeof(e), param,
|
||||
tomoyo_same_mount_acl, NULL);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* tomoyo_write_file - Update file related list.
|
||||
*
|
||||
* @param: Pointer to "struct tomoyo_acl_param".
|
||||
*
|
||||
* Returns 0 on success, negative value otherwise.
|
||||
*
|
||||
* Caller holds tomoyo_read_lock().
|
||||
*/
|
||||
int tomoyo_write_file(struct tomoyo_acl_param *param)
|
||||
{
|
||||
u16 perm = 0;
|
||||
u8 type;
|
||||
if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
|
||||
return -EINVAL;
|
||||
if (strncmp(w[0], "allow_", 6))
|
||||
goto out;
|
||||
w[0] += 6;
|
||||
for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) {
|
||||
if (strcmp(w[0], tomoyo_path_keyword[type]))
|
||||
continue;
|
||||
return tomoyo_update_path_acl(type, w[1], domain, is_delete);
|
||||
}
|
||||
if (!w[2][0])
|
||||
goto out;
|
||||
for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) {
|
||||
if (strcmp(w[0], tomoyo_path2_keyword[type]))
|
||||
continue;
|
||||
return tomoyo_update_path2_acl(type, w[1], w[2], domain,
|
||||
is_delete);
|
||||
}
|
||||
for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++) {
|
||||
if (strcmp(w[0], tomoyo_path_number_keyword[type]))
|
||||
continue;
|
||||
return tomoyo_update_path_number_acl(type, w[1], w[2], domain,
|
||||
is_delete);
|
||||
}
|
||||
if (!w[3][0] || !w[4][0])
|
||||
goto out;
|
||||
for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++) {
|
||||
if (strcmp(w[0], tomoyo_mkdev_keyword[type]))
|
||||
continue;
|
||||
return tomoyo_update_mkdev_acl(type, w[1], w[2], w[3],
|
||||
w[4], domain, is_delete);
|
||||
}
|
||||
out:
|
||||
const char *operation = tomoyo_read_token(param);
|
||||
for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++)
|
||||
if (tomoyo_permstr(operation, tomoyo_path_keyword[type]))
|
||||
perm |= 1 << type;
|
||||
if (perm)
|
||||
return tomoyo_update_path_acl(perm, param);
|
||||
for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++)
|
||||
if (tomoyo_permstr(operation, tomoyo_path2_keyword[type]))
|
||||
perm |= 1 << type;
|
||||
if (perm)
|
||||
return tomoyo_update_path2_acl(perm, param);
|
||||
for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++)
|
||||
if (tomoyo_permstr(operation,
|
||||
tomoyo_path_number_keyword[type]))
|
||||
perm |= 1 << type;
|
||||
if (perm)
|
||||
return tomoyo_update_path_number_acl(perm, param);
|
||||
for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++)
|
||||
if (tomoyo_permstr(operation, tomoyo_mkdev_keyword[type]))
|
||||
perm |= 1 << type;
|
||||
if (perm)
|
||||
return tomoyo_update_mkdev_acl(perm, param);
|
||||
if (tomoyo_permstr(operation, "mount"))
|
||||
return tomoyo_update_mount_acl(param);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -28,45 +28,38 @@ 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.
|
||||
*
|
||||
* @data: String to parse.
|
||||
* @is_delete: True if it is a delete request.
|
||||
* @param: Pointer to "struct tomoyo_acl_param".
|
||||
* @type: Type of this group.
|
||||
*
|
||||
* 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 list_head *member;
|
||||
char *w[2];
|
||||
struct tomoyo_group *group = tomoyo_get_group(param, type);
|
||||
int error = -EINVAL;
|
||||
if (!tomoyo_tokenize(data, w, sizeof(w)) || !w[1][0])
|
||||
return -EINVAL;
|
||||
group = tomoyo_get_group(w[0], type);
|
||||
if (!group)
|
||||
return -ENOMEM;
|
||||
member = &group->member_list;
|
||||
param->list = &group->member_list;
|
||||
if (type == TOMOYO_PATH_GROUP) {
|
||||
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) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
|
||||
member, tomoyo_same_path_group);
|
||||
error = tomoyo_update_policy(&e.head, sizeof(e), param,
|
||||
tomoyo_same_path_group);
|
||||
tomoyo_put_name(e.member_name);
|
||||
} else if (type == TOMOYO_NUMBER_GROUP) {
|
||||
struct tomoyo_number_group e = { };
|
||||
if (w[1][0] == '@'
|
||||
|| !tomoyo_parse_number_union(w[1], &e.number)
|
||||
|| e.number.values[0] > e.number.values[1])
|
||||
if (param->data[0] == '@' ||
|
||||
!tomoyo_parse_number_union(param, &e.number))
|
||||
goto out;
|
||||
error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
|
||||
member, tomoyo_same_number_group);
|
||||
error = tomoyo_update_policy(&e.head, sizeof(e), param,
|
||||
tomoyo_same_number_group);
|
||||
/*
|
||||
* tomoyo_put_number_union() is not needed because
|
||||
* w[1][0] != '@'.
|
||||
* param->data[0] != '@'.
|
||||
*/
|
||||
}
|
||||
out:
|
||||
|
|
|
@ -93,15 +93,18 @@ void tomoyo_memory_free(void *ptr)
|
|||
/**
|
||||
* 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.
|
||||
*
|
||||
* 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 *group = NULL;
|
||||
struct list_head *list;
|
||||
const char *group_name = tomoyo_read_token(param);
|
||||
bool found = false;
|
||||
if (!tomoyo_correct_word(group_name) || idx >= TOMOYO_MAX_GROUP)
|
||||
return NULL;
|
||||
|
@ -110,7 +113,8 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
|
|||
return NULL;
|
||||
if (mutex_lock_interruptible(&tomoyo_policy_lock))
|
||||
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)
|
||||
continue;
|
||||
atomic_inc(&group->head.users);
|
||||
|
@ -122,8 +126,7 @@ struct tomoyo_group *tomoyo_get_group(const char *group_name, const u8 idx)
|
|||
if (entry) {
|
||||
INIT_LIST_HEAD(&entry->member_list);
|
||||
atomic_set(&entry->head.users, 1);
|
||||
list_add_tail_rcu(&entry->head.list,
|
||||
&tomoyo_group_list[idx]);
|
||||
list_add_tail_rcu(&entry->head.list, list);
|
||||
group = entry;
|
||||
found = true;
|
||||
}
|
||||
|
@ -210,6 +213,8 @@ void __init tomoyo_mm_init(void)
|
|||
idx = tomoyo_read_lock();
|
||||
if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
|
||||
panic("Can't register tomoyo_kernel_domain");
|
||||
#if 0
|
||||
/* Will be replaced with tomoyo_load_builtin_policy(). */
|
||||
{
|
||||
/* Load built-in policy. */
|
||||
tomoyo_write_transition_control("/sbin/hotplug", false,
|
||||
|
@ -217,6 +222,7 @@ void __init tomoyo_mm_init(void)
|
|||
tomoyo_write_transition_control("/sbin/modprobe", false,
|
||||
TOMOYO_TRANSITION_CONTROL_INITIALIZE);
|
||||
}
|
||||
#endif
|
||||
tomoyo_read_unlock(idx);
|
||||
}
|
||||
|
||||
|
|
|
@ -243,56 +243,3 @@ int tomoyo_mount_permission(char *dev_name, struct path *path,
|
|||
tomoyo_read_unlock(idx);
|
||||
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);
|
|||
/* Has /sbin/init started? */
|
||||
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.
|
||||
*
|
||||
|
@ -81,20 +121,23 @@ void tomoyo_print_ulong(char *buffer, const int buffer_len,
|
|||
/**
|
||||
* 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".
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
if (!tomoyo_correct_word(filename))
|
||||
return false;
|
||||
if (filename[0] == '@') {
|
||||
ptr->group = tomoyo_get_group(filename + 1, TOMOYO_PATH_GROUP);
|
||||
char *filename;
|
||||
if (param->data[0] == '@') {
|
||||
param->data++;
|
||||
ptr->group = tomoyo_get_group(param, TOMOYO_PATH_GROUP);
|
||||
return ptr->group != NULL;
|
||||
}
|
||||
filename = tomoyo_read_token(param);
|
||||
if (!tomoyo_correct_word(filename))
|
||||
return false;
|
||||
ptr->filename = tomoyo_get_name(filename);
|
||||
return ptr->filename != NULL;
|
||||
}
|
||||
|
@ -102,39 +145,41 @@ bool tomoyo_parse_name_union(const char *filename,
|
|||
/**
|
||||
* 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".
|
||||
*
|
||||
* 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;
|
||||
unsigned long v;
|
||||
memset(num, 0, sizeof(*num));
|
||||
if (data[0] == '@') {
|
||||
if (!tomoyo_correct_word(data))
|
||||
return false;
|
||||
num->group = tomoyo_get_group(data + 1, TOMOYO_NUMBER_GROUP);
|
||||
return num->group != NULL;
|
||||
memset(ptr, 0, sizeof(*ptr));
|
||||
if (param->data[0] == '@') {
|
||||
param->data++;
|
||||
ptr->group = tomoyo_get_group(param, TOMOYO_NUMBER_GROUP);
|
||||
return ptr->group != NULL;
|
||||
}
|
||||
data = tomoyo_read_token(param);
|
||||
type = tomoyo_parse_ulong(&v, &data);
|
||||
if (!type)
|
||||
if (type == TOMOYO_VALUE_TYPE_INVALID)
|
||||
return false;
|
||||
num->values[0] = v;
|
||||
num->value_type[0] = type;
|
||||
ptr->values[0] = v;
|
||||
ptr->value_type[0] = type;
|
||||
if (!*data) {
|
||||
num->values[1] = v;
|
||||
num->value_type[1] = type;
|
||||
ptr->values[1] = v;
|
||||
ptr->value_type[1] = type;
|
||||
return true;
|
||||
}
|
||||
if (*data++ != '-')
|
||||
return false;
|
||||
type = tomoyo_parse_ulong(&v, &data);
|
||||
if (!type || *data)
|
||||
if (type == TOMOYO_VALUE_TYPE_INVALID || *data || ptr->values[0] > v)
|
||||
return false;
|
||||
num->values[1] = v;
|
||||
num->value_type[1] = type;
|
||||
ptr->values[1] = v;
|
||||
ptr->value_type[1] = type;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -258,33 +303,6 @@ void tomoyo_normalize_line(unsigned char *buffer)
|
|||
*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.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue