head->read_eof = true;
}
-/*
- * tomoyo_policy_manager_list is used for holding list of domainnames or
- * programs which are permitted to modify configuration via
- * /sys/kernel/security/tomoyo/ interface.
- *
- * An entry is added by
- *
- * # echo '<kernel> /sbin/mingetty /bin/login /bin/bash' > \
- * /sys/kernel/security/tomoyo/manager
- * (if you want to specify by a domainname)
- *
- * or
- *
- * # echo '/usr/sbin/tomoyo-editpolicy' > /sys/kernel/security/tomoyo/manager
- * (if you want to specify by a program's location)
- *
- * and is deleted by
- *
- * # echo 'delete <kernel> /sbin/mingetty /bin/login /bin/bash' > \
- * /sys/kernel/security/tomoyo/manager
- *
- * or
- *
- * # echo 'delete /usr/sbin/tomoyo-editpolicy' > \
- * /sys/kernel/security/tomoyo/manager
- *
- * and all entries are retrieved by
- *
- * # cat /sys/kernel/security/tomoyo/manager
- */
-LIST_HEAD(tomoyo_policy_manager_list);
-
static bool tomoyo_same_manager_entry(const struct tomoyo_acl_head *a,
const struct tomoyo_acl_head *b)
{
if (!e.manager)
return -ENOMEM;
error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
- &tomoyo_policy_manager_list,
+ &tomoyo_policy_list[TOMOYO_ID_MANAGER],
tomoyo_same_manager_entry);
tomoyo_put_name(e.manager);
return error;
*/
static void tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
{
- struct list_head *pos;
bool done = true;
if (head->read_eof)
return;
- list_for_each_cookie(pos, head->read_var2,
- &tomoyo_policy_manager_list) {
- struct tomoyo_policy_manager_entry *ptr;
- ptr = list_entry(pos, struct tomoyo_policy_manager_entry,
- head.list);
+ list_for_each_cookie(head->read_var2,
+ &tomoyo_policy_list[TOMOYO_ID_MANAGER]) {
+ struct tomoyo_policy_manager_entry *ptr =
+ list_entry(head->read_var2, typeof(*ptr), head.list);
if (ptr->head.is_deleted)
continue;
done = tomoyo_io_printf(head, "%s\n", ptr->manager->name);
return true;
if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid))
return false;
- list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, head.list) {
+ list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_MANAGER],
+ head.list) {
if (!ptr->head.is_deleted && ptr->is_domain
&& !tomoyo_pathcmp(domainname, ptr->manager)) {
found = true;
exe = tomoyo_get_exe();
if (!exe)
return false;
- list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, head.list) {
+ list_for_each_entry_rcu(ptr, &tomoyo_policy_list[TOMOYO_ID_MANAGER],
+ head.list) {
if (!ptr->head.is_deleted && !ptr->is_domain
&& !strcmp(exe, ptr->manager->name)) {
found = true;
*
* Caller holds tomoyo_read_lock().
*/
-static bool tomoyo_select_one(struct tomoyo_io_buffer *head,
- const char *data)
+static bool tomoyo_select_one(struct tomoyo_io_buffer *head, const char *data)
{
unsigned int pid;
struct tomoyo_domain_info *domain = NULL;
bool global_pid = false;
+ if (!strcmp(data, "allow_execute")) {
+ head->print_execute_only = true;
+ return true;
+ }
if (sscanf(data, "pid=%u", &pid) == 1 ||
(global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
struct task_struct *p;
tomoyo_io_printf(head, "# select %s\n", data);
head->read_single_domain = true;
head->read_eof = !domain;
- if (domain) {
- struct tomoyo_domain_info *d;
- head->read_var1 = NULL;
- list_for_each_entry_rcu(d, &tomoyo_domain_list, list) {
- if (d == domain)
- break;
- head->read_var1 = &d->list;
- }
- head->read_var2 = NULL;
- head->read_bit = 0;
- head->read_step = 0;
- if (domain->is_deleted)
- tomoyo_io_printf(head, "# This is a deleted domain.\n");
- }
+ head->read_var1 = &domain->list;
+ head->read_var2 = NULL;
+ head->read_bit = 0;
+ head->read_step = 0;
+ if (domain && domain->is_deleted)
+ tomoyo_io_printf(head, "# This is a deleted domain.\n");
return true;
}
for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) {
if (!(perm & (1 << bit)))
continue;
+ if (head->print_execute_only && bit != TOMOYO_TYPE_EXECUTE)
+ continue;
/* Print "read/write" instead of "read" and "write". */
if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE)
&& (perm & (1 << TOMOYO_TYPE_READ_WRITE)))
= container_of(ptr, struct tomoyo_path_acl, head);
return tomoyo_print_path_acl(head, acl);
}
+ if (head->print_execute_only)
+ return true;
if (acl_type == TOMOYO_TYPE_PATH2_ACL) {
struct tomoyo_path2_acl *acl
= container_of(ptr, struct tomoyo_path2_acl, head);
*/
static void tomoyo_read_domain_policy(struct tomoyo_io_buffer *head)
{
- struct list_head *dpos;
- struct list_head *apos;
bool done = true;
if (head->read_eof)
return;
if (head->read_step == 0)
head->read_step = 1;
- list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) {
- struct tomoyo_domain_info *domain;
+ list_for_each_cookie(head->read_var1, &tomoyo_domain_list) {
+ struct tomoyo_domain_info *domain =
+ list_entry(head->read_var1, typeof(*domain), list);
const char *quota_exceeded = "";
const char *transition_failed = "";
const char *ignore_global_allow_read = "";
- domain = list_entry(dpos, struct tomoyo_domain_info, list);
if (head->read_step != 1)
goto acl_loop;
if (domain->is_deleted && !head->read_single_domain)
if (head->read_step == 3)
goto tail_mark;
/* Print ACL entries in the domain. */
- list_for_each_cookie(apos, head->read_var2,
+ list_for_each_cookie(head->read_var2,
&domain->acl_info_list) {
- struct tomoyo_acl_info *ptr
- = list_entry(apos, struct tomoyo_acl_info,
- list);
+ struct tomoyo_acl_info *ptr =
+ list_entry(head->read_var2, typeof(*ptr), list);
done = tomoyo_print_entry(head, ptr);
if (!done)
break;
}
if (!done)
break;
+ head->read_var2 = NULL;
head->read_step = 3;
tail_mark:
done = tomoyo_io_printf(head, "\n");
*/
static void tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
{
- struct list_head *pos;
bool done = true;
if (head->read_eof)
return;
- list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) {
- struct tomoyo_domain_info *domain;
- domain = list_entry(pos, struct tomoyo_domain_info, list);
+ list_for_each_cookie(head->read_var1, &tomoyo_domain_list) {
+ struct tomoyo_domain_info *domain =
+ list_entry(head->read_var1, typeof(*domain), list);
if (domain->is_deleted)
continue;
done = tomoyo_io_printf(head, "%u %s\n", domain->profile,
}
}
+static const char *tomoyo_transition_type[TOMOYO_MAX_TRANSITION_TYPE] = {
+ [TOMOYO_TRANSITION_CONTROL_NO_INITIALIZE]
+ = TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN,
+ [TOMOYO_TRANSITION_CONTROL_INITIALIZE]
+ = TOMOYO_KEYWORD_INITIALIZE_DOMAIN,
+ [TOMOYO_TRANSITION_CONTROL_NO_KEEP] = TOMOYO_KEYWORD_NO_KEEP_DOMAIN,
+ [TOMOYO_TRANSITION_CONTROL_KEEP] = TOMOYO_KEYWORD_KEEP_DOMAIN
+};
+
/**
* tomoyo_write_exception_policy - Write exception policy.
*
{
char *data = head->write_buf;
bool is_delete = tomoyo_str_starts(&data, TOMOYO_KEYWORD_DELETE);
+ u8 i;
- if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_KEEP_DOMAIN))
- return tomoyo_write_domain_keeper_policy(data, false,
- is_delete);
- if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_KEEP_DOMAIN))
- return tomoyo_write_domain_keeper_policy(data, true, is_delete);
- if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_INITIALIZE_DOMAIN))
- return tomoyo_write_domain_initializer_policy(data, false,
- is_delete);
- if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN))
- return tomoyo_write_domain_initializer_policy(data, true,
- is_delete);
+ 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);
+ }
if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_AGGREGATOR))
return tomoyo_write_aggregator_policy(data, is_delete);
- if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALIAS))
- return tomoyo_write_alias_policy(data, is_delete);
if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_ALLOW_READ))
return tomoyo_write_globally_readable_policy(data, is_delete);
if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_FILE_PATTERN))
if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_DENY_REWRITE))
return tomoyo_write_no_rewrite_policy(data, is_delete);
if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_PATH_GROUP))
- return tomoyo_write_path_group_policy(data, is_delete);
+ return tomoyo_write_group(data, is_delete, TOMOYO_PATH_GROUP);
if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NUMBER_GROUP))
- return tomoyo_write_number_group_policy(data, is_delete);
+ return tomoyo_write_group(data, is_delete, TOMOYO_NUMBER_GROUP);
return -EINVAL;
}
+static void tomoyo_print_number(char *buffer, int buffer_len,
+ const struct tomoyo_number_union *ptr)
+{
+ int i;
+ unsigned long min = ptr->values[0];
+ const unsigned long max = ptr->values[1];
+ u8 min_type = ptr->min_type;
+ const u8 max_type = ptr->max_type;
+ memset(buffer, 0, buffer_len);
+ buffer_len -= 2;
+ for (i = 0; i < 2; i++) {
+ int len;
+ switch (min_type) {
+ case TOMOYO_VALUE_TYPE_HEXADECIMAL:
+ snprintf(buffer, buffer_len, "0x%lX", min);
+ break;
+ case TOMOYO_VALUE_TYPE_OCTAL:
+ snprintf(buffer, buffer_len, "0%lo", min);
+ break;
+ default:
+ snprintf(buffer, buffer_len, "%lu", min);
+ break;
+ }
+ if (min == max && min_type == max_type)
+ break;
+ len = strlen(buffer);
+ buffer[len++] = '-';
+ buffer += len;
+ buffer_len -= len;
+ min_type = max_type;
+ min = max;
+ }
+}
+
+static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = {
+ [TOMOYO_PATH_GROUP] = TOMOYO_KEYWORD_PATH_GROUP,
+ [TOMOYO_NUMBER_GROUP] = TOMOYO_KEYWORD_NUMBER_GROUP
+};
+
/**
- * tomoyo_read_exception_policy - Read exception policy.
+ * tomoyo_read_group - Read "struct tomoyo_path_group"/"struct tomoyo_number_group" list.
*
* @head: Pointer to "struct tomoyo_io_buffer".
+ * @idx: Index number.
+ *
+ * Returns true on success, false otherwise.
*
* Caller holds tomoyo_read_lock().
*/
-static void tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
+static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx)
{
- if (!head->read_eof) {
- switch (head->read_step) {
- case 0:
- head->read_var2 = NULL;
- head->read_step = 1;
- case 1:
- if (!tomoyo_read_domain_keeper_policy(head))
- break;
- head->read_var2 = NULL;
- head->read_step = 2;
- case 2:
- if (!tomoyo_read_globally_readable_policy(head))
- break;
- head->read_var2 = NULL;
- head->read_step = 3;
- case 3:
- head->read_var2 = NULL;
- head->read_step = 4;
- case 4:
- if (!tomoyo_read_domain_initializer_policy(head))
- break;
- head->read_var2 = NULL;
- head->read_step = 5;
- case 5:
- if (!tomoyo_read_alias_policy(head))
- break;
- head->read_var2 = NULL;
- head->read_step = 6;
- case 6:
- if (!tomoyo_read_aggregator_policy(head))
- break;
- head->read_var2 = NULL;
- head->read_step = 7;
- case 7:
- if (!tomoyo_read_file_pattern(head))
- break;
- head->read_var2 = NULL;
- head->read_step = 8;
- case 8:
- if (!tomoyo_read_no_rewrite_policy(head))
- break;
- head->read_var2 = NULL;
- head->read_step = 9;
- case 9:
- if (!tomoyo_read_path_group_policy(head))
- break;
- head->read_var1 = NULL;
- head->read_var2 = NULL;
- head->read_step = 10;
- case 10:
- if (!tomoyo_read_number_group_policy(head))
- break;
- head->read_var1 = NULL;
- head->read_var2 = NULL;
- head->read_step = 11;
- case 11:
- head->read_eof = true;
+ const char *w[3] = { "", "", "" };
+ w[0] = tomoyo_group_name[idx];
+ list_for_each_cookie(head->read_var1, &tomoyo_group_list[idx]) {
+ struct tomoyo_group *group =
+ list_entry(head->read_var1, typeof(*group), list);
+ w[1] = group->group_name->name;
+ list_for_each_cookie(head->read_var2, &group->member_list) {
+ char buffer[128];
+ struct tomoyo_acl_head *ptr =
+ list_entry(head->read_var2, typeof(*ptr), list);
+ if (ptr->is_deleted)
+ continue;
+ if (idx == TOMOYO_PATH_GROUP) {
+ w[2] = container_of(ptr,
+ struct tomoyo_path_group,
+ head)->member_name->name;
+ } else if (idx == TOMOYO_NUMBER_GROUP) {
+ tomoyo_print_number(buffer, sizeof(buffer),
+ &container_of
+ (ptr, struct
+ tomoyo_number_group,
+ head)->number);
+ w[2] = buffer;
+ }
+ if (!tomoyo_io_printf(head, "%s%s %s\n", w[0], w[1],
+ w[2]))
+ return false;
+ }
+ head->read_var2 = NULL;
+ }
+ head->read_var1 = NULL;
+ return true;
+}
+
+/**
+ * tomoyo_read_policy - Read "struct tomoyo_..._entry" list.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ * @idx: Index number.
+ *
+ * Returns true on success, false otherwise.
+ *
+ * Caller holds tomoyo_read_lock().
+ */
+static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx)
+{
+ list_for_each_cookie(head->read_var2, &tomoyo_policy_list[idx]) {
+ const char *w[4] = { "", "", "", "" };
+ struct tomoyo_acl_head *acl =
+ container_of(head->read_var2, typeof(*acl), list);
+ if (acl->is_deleted)
+ continue;
+ switch (idx) {
+ case TOMOYO_ID_TRANSITION_CONTROL:
+ {
+ struct tomoyo_transition_control *ptr =
+ container_of(acl, typeof(*ptr), head);
+ w[0] = tomoyo_transition_type[ptr->type];
+ if (ptr->program)
+ w[1] = ptr->program->name;
+ if (ptr->domainname)
+ w[3] = ptr->domainname->name;
+ if (w[1][0] && w[3][0])
+ w[2] = " from ";
+ }
break;
+ case TOMOYO_ID_GLOBALLY_READABLE:
+ {
+ struct tomoyo_globally_readable_file_entry *ptr
+ = container_of(acl, typeof(*ptr), head);
+ w[0] = TOMOYO_KEYWORD_ALLOW_READ;
+ w[1] = ptr->filename->name;
+ }
+ break;
+ case TOMOYO_ID_AGGREGATOR:
+ {
+ struct tomoyo_aggregator_entry *ptr =
+ container_of(acl, typeof(*ptr), head);
+ w[0] = TOMOYO_KEYWORD_AGGREGATOR;
+ w[1] = ptr->original_name->name;
+ w[2] = " ";
+ w[3] = ptr->aggregated_name->name;
+ }
+ break;
+ case TOMOYO_ID_PATTERN:
+ {
+ struct tomoyo_pattern_entry *ptr =
+ container_of(acl, typeof(*ptr), head);
+ w[0] = TOMOYO_KEYWORD_FILE_PATTERN;
+ w[1] = ptr->pattern->name;
+ }
+ break;
+ case TOMOYO_ID_NO_REWRITE:
+ {
+ struct tomoyo_no_rewrite_entry *ptr =
+ container_of(acl, typeof(*ptr), head);
+ w[0] = TOMOYO_KEYWORD_DENY_REWRITE;
+ w[1] = ptr->pattern->name;
+ }
+ break;
+ default:
+ continue;
}
+ if (!tomoyo_io_printf(head, "%s%s%s%s\n", w[0], w[1], w[2],
+ w[3]))
+ return false;
}
+ head->read_var2 = NULL;
+ return true;
+}
+
+/**
+ * tomoyo_read_exception_policy - Read exception policy.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ *
+ * Caller holds tomoyo_read_lock().
+ */
+static void tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
+{
+ if (head->read_eof)
+ return;
+ while (head->read_step < TOMOYO_MAX_POLICY &&
+ tomoyo_read_policy(head, head->read_step))
+ head->read_step++;
+ if (head->read_step < TOMOYO_MAX_POLICY)
+ return;
+ while (head->read_step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP &&
+ tomoyo_read_group(head, head->read_step - TOMOYO_MAX_POLICY))
+ head->read_step++;
+ if (head->read_step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP)
+ return;
+ head->read_eof = true;
}
/**