#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/security.h>
-#include <linux/hardirq.h>
#include "common.h"
+static struct tomoyo_profile tomoyo_default_profile = {
+ .learning = &tomoyo_default_profile.preference,
+ .permissive = &tomoyo_default_profile.preference,
+ .enforcing = &tomoyo_default_profile.preference,
+ .preference.enforcing_verbose = true,
+ .preference.learning_max_entry = 2048,
+ .preference.learning_verbose = false,
+ .preference.permissive_verbose = true
+};
+
+/* Profile version. Currently only 20090903 is defined. */
+static unsigned int tomoyo_profile_version;
+
+/* Profile table. Memory is allocated as needed. */
+static struct tomoyo_profile *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES];
+
/* String table for functionality that takes 4 modes. */
static const char *tomoyo_mode_4[4] = {
"disabled", "learning", "permissive", "enforcing"
};
-/* String table for functionality that takes 2 modes. */
-static const char *tomoyo_mode_2[4] = {
- "disabled", "enabled", "enabled", "enabled"
-};
-/*
- * tomoyo_control_array is a static data which contains
- *
- * (1) functionality name used by /sys/kernel/security/tomoyo/profile .
- * (2) initial values for "struct tomoyo_profile".
- * (3) max values for "struct tomoyo_profile".
- */
-static struct {
- const char *keyword;
- unsigned int current_value;
- const unsigned int max_value;
-} tomoyo_control_array[TOMOYO_MAX_CONTROL_INDEX] = {
- [TOMOYO_MAC_FOR_FILE] = { "MAC_FOR_FILE", 0, 3 },
- [TOMOYO_MAX_ACCEPT_ENTRY] = { "MAX_ACCEPT_ENTRY", 2048, INT_MAX },
- [TOMOYO_VERBOSE] = { "TOMOYO_VERBOSE", 1, 1 },
+/* String table for /sys/kernel/security/tomoyo/profile */
+static const char *tomoyo_mac_keywords[TOMOYO_MAX_MAC_INDEX
+ + TOMOYO_MAX_MAC_CATEGORY_INDEX] = {
+ [TOMOYO_MAC_FILE_EXECUTE] = "file::execute",
+ [TOMOYO_MAC_FILE_OPEN] = "file::open",
+ [TOMOYO_MAC_FILE_CREATE] = "file::create",
+ [TOMOYO_MAC_FILE_UNLINK] = "file::unlink",
+ [TOMOYO_MAC_FILE_MKDIR] = "file::mkdir",
+ [TOMOYO_MAC_FILE_RMDIR] = "file::rmdir",
+ [TOMOYO_MAC_FILE_MKFIFO] = "file::mkfifo",
+ [TOMOYO_MAC_FILE_MKSOCK] = "file::mksock",
+ [TOMOYO_MAC_FILE_TRUNCATE] = "file::truncate",
+ [TOMOYO_MAC_FILE_SYMLINK] = "file::symlink",
+ [TOMOYO_MAC_FILE_REWRITE] = "file::rewrite",
+ [TOMOYO_MAC_FILE_MKBLOCK] = "file::mkblock",
+ [TOMOYO_MAC_FILE_MKCHAR] = "file::mkchar",
+ [TOMOYO_MAC_FILE_LINK] = "file::link",
+ [TOMOYO_MAC_FILE_RENAME] = "file::rename",
+ [TOMOYO_MAC_FILE_CHMOD] = "file::chmod",
+ [TOMOYO_MAC_FILE_CHOWN] = "file::chown",
+ [TOMOYO_MAC_FILE_CHGRP] = "file::chgrp",
+ [TOMOYO_MAC_FILE_IOCTL] = "file::ioctl",
+ [TOMOYO_MAC_FILE_CHROOT] = "file::chroot",
+ [TOMOYO_MAC_FILE_MOUNT] = "file::mount",
+ [TOMOYO_MAC_FILE_UMOUNT] = "file::umount",
+ [TOMOYO_MAC_FILE_PIVOT_ROOT] = "file::pivot_root",
+ [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file",
};
-/*
- * tomoyo_profile is a structure which is used for holding the mode of access
- * controls. TOMOYO has 4 modes: disabled, learning, permissive, enforcing.
- * An administrator can define up to 256 profiles.
- * The ->profile of "struct tomoyo_domain_info" is used for remembering
- * the profile's number (0 - 255) assigned to that domain.
- */
-static struct tomoyo_profile {
- unsigned int value[TOMOYO_MAX_CONTROL_INDEX];
- const struct tomoyo_path_info *comment;
-} *tomoyo_profile_ptr[TOMOYO_MAX_PROFILES];
-
/* Permit policy management by non-root user? */
static bool tomoyo_manage_by_non_root;
/* Utility functions. */
+/**
+ * tomoyo_yesno - Return "yes" or "no".
+ *
+ * @value: Bool value.
+ */
+static const char *tomoyo_yesno(const unsigned int value)
+{
+ return value ? "yes" : "no";
+}
+
/**
* tomoyo_print_name_union - Print a tomoyo_name_union.
*
return true;
}
-/**
- * tomoyo_check_flags - Check mode for specified functionality.
- *
- * @domain: Pointer to "struct tomoyo_domain_info".
- * @index: The functionality to check mode.
- *
- * TOMOYO checks only process context.
- * This code disables TOMOYO's enforcement in case the function is called from
- * interrupt context.
- */
-unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain,
- const u8 index)
-{
- const u8 profile = domain->profile;
-
- if (WARN_ON(in_interrupt()))
- return 0;
- return tomoyo_policy_loaded && index < TOMOYO_MAX_CONTROL_INDEX
-#if TOMOYO_MAX_PROFILES != 256
- && profile < TOMOYO_MAX_PROFILES
-#endif
- && tomoyo_profile_ptr[profile] ?
- tomoyo_profile_ptr[profile]->value[index] : 0;
-}
-
-/**
- * tomoyo_verbose_mode - Check whether TOMOYO is verbose mode.
- *
- * @domain: Pointer to "struct tomoyo_domain_info".
- *
- * Returns true if domain policy violation warning should be printed to
- * console.
- */
-bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain)
-{
- return tomoyo_check_flags(domain, TOMOYO_VERBOSE) != 0;
-}
-
/**
* tomoyo_find_or_assign_new_profile - Create a new profile.
*
*
* Returns pointer to "struct tomoyo_profile" on success, NULL otherwise.
*/
-static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned
- int profile)
+static struct tomoyo_profile *tomoyo_find_or_assign_new_profile
+(const unsigned int profile)
{
- struct tomoyo_profile *ptr = NULL;
- int i;
-
+ struct tomoyo_profile *ptr;
+ struct tomoyo_profile *entry;
if (profile >= TOMOYO_MAX_PROFILES)
return NULL;
- if (mutex_lock_interruptible(&tomoyo_policy_lock))
- return NULL;
ptr = tomoyo_profile_ptr[profile];
if (ptr)
- goto ok;
- ptr = kmalloc(sizeof(*ptr), GFP_NOFS);
- if (!tomoyo_memory_ok(ptr)) {
- kfree(ptr);
- ptr = NULL;
- goto ok;
+ return ptr;
+ entry = kzalloc(sizeof(*entry), GFP_NOFS);
+ if (mutex_lock_interruptible(&tomoyo_policy_lock))
+ goto out;
+ ptr = tomoyo_profile_ptr[profile];
+ if (!ptr && tomoyo_memory_ok(entry)) {
+ ptr = entry;
+ ptr->learning = &tomoyo_default_profile.preference;
+ ptr->permissive = &tomoyo_default_profile.preference;
+ ptr->enforcing = &tomoyo_default_profile.preference;
+ ptr->default_config = TOMOYO_CONFIG_DISABLED;
+ memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT,
+ sizeof(ptr->config));
+ mb(); /* Avoid out-of-order execution. */
+ tomoyo_profile_ptr[profile] = ptr;
+ entry = NULL;
}
- for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++)
- ptr->value[i] = tomoyo_control_array[i].current_value;
- mb(); /* Avoid out-of-order execution. */
- tomoyo_profile_ptr[profile] = ptr;
- ok:
mutex_unlock(&tomoyo_policy_lock);
+ out:
+ kfree(entry);
+ return ptr;
+}
+
+/**
+ * tomoyo_profile - Find a profile.
+ *
+ * @profile: Profile number to find.
+ *
+ * Returns pointer to "struct tomoyo_profile".
+ */
+struct tomoyo_profile *tomoyo_profile(const u8 profile)
+{
+ struct tomoyo_profile *ptr = tomoyo_profile_ptr[profile];
+ if (!tomoyo_policy_loaded)
+ return &tomoyo_default_profile;
+ BUG_ON(!ptr);
return ptr;
}
/**
- * tomoyo_write_profile - Write to profile table.
+ * tomoyo_write_profile - Write profile table.
*
* @head: Pointer to "struct tomoyo_io_buffer".
*
{
char *data = head->write_buf;
unsigned int i;
- unsigned int value;
+ int value;
+ int mode;
+ u8 config;
+ bool use_default = false;
char *cp;
struct tomoyo_profile *profile;
- unsigned long num;
-
- cp = strchr(data, '-');
- if (cp)
- *cp = '\0';
- if (strict_strtoul(data, 10, &num))
- return -EINVAL;
- if (cp)
+ if (sscanf(data, "PROFILE_VERSION=%u", &tomoyo_profile_version) == 1)
+ return 0;
+ i = simple_strtoul(data, &cp, 10);
+ if (data == cp) {
+ profile = &tomoyo_default_profile;
+ } else {
+ if (*cp != '-')
+ return -EINVAL;
data = cp + 1;
- profile = tomoyo_find_or_assign_new_profile(num);
- if (!profile)
- return -EINVAL;
+ profile = tomoyo_find_or_assign_new_profile(i);
+ if (!profile)
+ return -EINVAL;
+ }
cp = strchr(data, '=');
if (!cp)
return -EINVAL;
- *cp = '\0';
+ *cp++ = '\0';
+ if (profile != &tomoyo_default_profile)
+ use_default = strstr(cp, "use_default") != NULL;
+ if (strstr(cp, "verbose=yes"))
+ value = 1;
+ else if (strstr(cp, "verbose=no"))
+ value = 0;
+ else
+ value = -1;
+ if (!strcmp(data, "PREFERENCE::enforcing")) {
+ if (use_default) {
+ profile->enforcing = &tomoyo_default_profile.preference;
+ return 0;
+ }
+ profile->enforcing = &profile->preference;
+ if (value >= 0)
+ profile->preference.enforcing_verbose = value;
+ return 0;
+ }
+ if (!strcmp(data, "PREFERENCE::permissive")) {
+ if (use_default) {
+ profile->permissive = &tomoyo_default_profile.preference;
+ return 0;
+ }
+ profile->permissive = &profile->preference;
+ if (value >= 0)
+ profile->preference.permissive_verbose = value;
+ return 0;
+ }
+ if (!strcmp(data, "PREFERENCE::learning")) {
+ char *cp2;
+ if (use_default) {
+ profile->learning = &tomoyo_default_profile.preference;
+ return 0;
+ }
+ profile->learning = &profile->preference;
+ if (value >= 0)
+ profile->preference.learning_verbose = value;
+ cp2 = strstr(cp, "max_entry=");
+ if (cp2)
+ sscanf(cp2 + 10, "%u",
+ &profile->preference.learning_max_entry);
+ return 0;
+ }
+ if (profile == &tomoyo_default_profile)
+ return -EINVAL;
if (!strcmp(data, "COMMENT")) {
const struct tomoyo_path_info *old_comment = profile->comment;
- profile->comment = tomoyo_get_name(cp + 1);
+ profile->comment = tomoyo_get_name(cp);
tomoyo_put_name(old_comment);
return 0;
}
- for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) {
- if (strcmp(data, tomoyo_control_array[i].keyword))
- continue;
- if (sscanf(cp + 1, "%u", &value) != 1) {
- int j;
- const char **modes;
- switch (i) {
- case TOMOYO_VERBOSE:
- modes = tomoyo_mode_2;
- break;
- default:
- modes = tomoyo_mode_4;
- break;
- }
- for (j = 0; j < 4; j++) {
- if (strcmp(cp + 1, modes[j]))
- continue;
- value = j;
- break;
- }
- if (j == 4)
- return -EINVAL;
- } else if (value > tomoyo_control_array[i].max_value) {
- value = tomoyo_control_array[i].max_value;
+ if (!strcmp(data, "CONFIG")) {
+ i = TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX;
+ config = profile->default_config;
+ } else if (tomoyo_str_starts(&data, "CONFIG::")) {
+ config = 0;
+ for (i = 0; i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) {
+ if (strcmp(data, tomoyo_mac_keywords[i]))
+ continue;
+ config = profile->config[i];
+ break;
}
- profile->value[i] = value;
- return 0;
+ if (i == TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX)
+ return -EINVAL;
+ } else {
+ return -EINVAL;
}
- return -EINVAL;
+ if (use_default) {
+ config = TOMOYO_CONFIG_USE_DEFAULT;
+ } else {
+ for (mode = 3; mode >= 0; mode--)
+ if (strstr(cp, tomoyo_mode_4[mode]))
+ /*
+ * Update lower 3 bits in order to distinguish
+ * 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'.
+ */
+ config = (config & ~7) | mode;
+ }
+ if (i < TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX)
+ profile->config[i] = config;
+ else if (config != TOMOYO_CONFIG_USE_DEFAULT)
+ profile->default_config = config;
+ return 0;
}
/**
- * tomoyo_read_profile - Read from profile table.
+ * tomoyo_read_profile - Read profile table.
*
* @head: Pointer to "struct tomoyo_io_buffer".
- *
- * Returns 0.
*/
-static int tomoyo_read_profile(struct tomoyo_io_buffer *head)
+static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
{
- static const int total = TOMOYO_MAX_CONTROL_INDEX + 1;
- int step;
-
+ int index;
if (head->read_eof)
- return 0;
- for (step = head->read_step; step < TOMOYO_MAX_PROFILES * total;
- step++) {
- const u8 index = step / total;
- u8 type = step % total;
+ return;
+ if (head->read_bit)
+ goto body;
+ tomoyo_io_printf(head, "PROFILE_VERSION=%s\n", "20090903");
+ tomoyo_io_printf(head, "PREFERENCE::learning={ verbose=%s "
+ "max_entry=%u }\n",
+ tomoyo_yesno(tomoyo_default_profile.preference.
+ learning_verbose),
+ tomoyo_default_profile.preference.learning_max_entry);
+ tomoyo_io_printf(head, "PREFERENCE::permissive={ verbose=%s }\n",
+ tomoyo_yesno(tomoyo_default_profile.preference.
+ permissive_verbose));
+ tomoyo_io_printf(head, "PREFERENCE::enforcing={ verbose=%s }\n",
+ tomoyo_yesno(tomoyo_default_profile.preference.
+ enforcing_verbose));
+ head->read_bit = 1;
+ body:
+ for (index = head->read_step; index < TOMOYO_MAX_PROFILES; index++) {
+ bool done;
+ u8 config;
+ int i;
+ int pos;
const struct tomoyo_profile *profile
= tomoyo_profile_ptr[index];
- head->read_step = step;
+ const struct tomoyo_path_info *comment;
+ head->read_step = index;
if (!profile)
continue;
- if (!type) { /* Print profile' comment tag. */
- if (!tomoyo_io_printf(head, "%u-COMMENT=%s\n",
- index, profile->comment ?
- profile->comment->name : ""))
- break;
- continue;
- }
- type--;
- if (type < TOMOYO_MAX_CONTROL_INDEX) {
- const unsigned int value = profile->value[type];
- const char **modes = NULL;
- const char *keyword
- = tomoyo_control_array[type].keyword;
- switch (tomoyo_control_array[type].max_value) {
- case 3:
- modes = tomoyo_mode_4;
- break;
- case 1:
- modes = tomoyo_mode_2;
- break;
- }
- if (modes) {
- if (!tomoyo_io_printf(head, "%u-%s=%s\n", index,
- keyword, modes[value]))
- break;
- } else {
- if (!tomoyo_io_printf(head, "%u-%s=%u\n", index,
- keyword, value))
- break;
- }
+ pos = head->read_avail;
+ comment = profile->comment;
+ done = tomoyo_io_printf(head, "%u-COMMENT=%s\n", index,
+ comment ? comment->name : "");
+ if (!done)
+ goto out;
+ config = profile->default_config;
+ if (!tomoyo_io_printf(head, "%u-CONFIG={ mode=%s }\n", index,
+ tomoyo_mode_4[config & 3]))
+ goto out;
+ for (i = 0; i < TOMOYO_MAX_MAC_INDEX +
+ TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) {
+ config = profile->config[i];
+ if (config == TOMOYO_CONFIG_USE_DEFAULT)
+ continue;
+ if (!tomoyo_io_printf(head,
+ "%u-CONFIG::%s={ mode=%s }\n",
+ index, tomoyo_mac_keywords[i],
+ tomoyo_mode_4[config & 3]))
+ goto out;
}
+ if (profile->learning != &tomoyo_default_profile.preference &&
+ !tomoyo_io_printf(head, "%u-PREFERENCE::learning={ "
+ "verbose=%s max_entry=%u }\n", index,
+ tomoyo_yesno(profile->preference.
+ learning_verbose),
+ profile->preference.learning_max_entry))
+ goto out;
+ if (profile->permissive != &tomoyo_default_profile.preference
+ && !tomoyo_io_printf(head, "%u-PREFERENCE::permissive={ "
+ "verbose=%s }\n", index,
+ tomoyo_yesno(profile->preference.
+ permissive_verbose)))
+ goto out;
+ if (profile->enforcing != &tomoyo_default_profile.preference &&
+ !tomoyo_io_printf(head, "%u-PREFERENCE::enforcing={ "
+ "verbose=%s }\n", index,
+ tomoyo_yesno(profile->preference.
+ enforcing_verbose)))
+ goto out;
+ continue;
+ out:
+ head->read_avail = pos;
+ break;
}
- if (step == TOMOYO_MAX_PROFILES * total)
+ if (index == TOMOYO_MAX_PROFILES)
head->read_eof = true;
- return 0;
}
/*
*
* or
*
- * # echo '/usr/lib/ccs/editpolicy' > /sys/kernel/security/tomoyo/manager
+ * # echo '/usr/sbin/tomoyo-editpolicy' > /sys/kernel/security/tomoyo/manager
* (if you want to specify by a program's location)
*
* and is deleted by
*
* or
*
- * # echo 'delete /usr/lib/ccs/editpolicy' > \
+ * # echo 'delete /usr/sbin/tomoyo-editpolicy' > \
* /sys/kernel/security/tomoyo/manager
*
* and all entries are retrieved by
*/
LIST_HEAD(tomoyo_policy_manager_list);
+static bool tomoyo_same_manager_entry(const struct tomoyo_acl_head *a,
+ const struct tomoyo_acl_head *b)
+{
+ return container_of(a, struct tomoyo_policy_manager_entry, head)
+ ->manager ==
+ container_of(b, struct tomoyo_policy_manager_entry, head)
+ ->manager;
+}
+
/**
* tomoyo_update_manager_entry - Add a manager entry.
*
static int tomoyo_update_manager_entry(const char *manager,
const bool is_delete)
{
- struct tomoyo_policy_manager_entry *ptr;
struct tomoyo_policy_manager_entry e = { };
- int error = is_delete ? -ENOENT : -ENOMEM;
+ int error;
- if (tomoyo_is_domain_def(manager)) {
- if (!tomoyo_is_correct_domain(manager))
+ if (tomoyo_domain_def(manager)) {
+ if (!tomoyo_correct_domain(manager))
return -EINVAL;
e.is_domain = true;
} else {
- if (!tomoyo_is_correct_path(manager, 1, -1, -1))
+ if (!tomoyo_correct_path(manager))
return -EINVAL;
}
e.manager = tomoyo_get_name(manager);
if (!e.manager)
return -ENOMEM;
- if (mutex_lock_interruptible(&tomoyo_policy_lock))
- goto out;
- list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
- if (ptr->manager != e.manager)
- continue;
- ptr->is_deleted = is_delete;
- error = 0;
- break;
- }
- if (!is_delete && error) {
- struct tomoyo_policy_manager_entry *entry =
- tomoyo_commit_ok(&e, sizeof(e));
- if (entry) {
- list_add_tail_rcu(&entry->list,
- &tomoyo_policy_manager_list);
- error = 0;
- }
- }
- mutex_unlock(&tomoyo_policy_lock);
- out:
+ error = tomoyo_update_policy(&e.head, sizeof(e), is_delete,
+ &tomoyo_policy_manager_list,
+ tomoyo_same_manager_entry);
tomoyo_put_name(e.manager);
return error;
}
*
* @head: Pointer to "struct tomoyo_io_buffer".
*
- * Returns 0.
- *
* Caller holds tomoyo_read_lock().
*/
-static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
+static void tomoyo_read_manager_policy(struct tomoyo_io_buffer *head)
{
struct list_head *pos;
bool done = true;
if (head->read_eof)
- return 0;
+ 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,
- list);
- if (ptr->is_deleted)
+ head.list);
+ if (ptr->head.is_deleted)
continue;
done = tomoyo_io_printf(head, "%s\n", ptr->manager->name);
if (!done)
break;
}
head->read_eof = done;
- return 0;
}
/**
- * tomoyo_is_policy_manager - Check whether the current process is a policy manager.
+ * tomoyo_policy_manager - Check whether the current process is a policy manager.
*
* Returns true if the current process is permitted to modify policy
* via /sys/kernel/security/tomoyo/ interface.
*
* Caller holds tomoyo_read_lock().
*/
-static bool tomoyo_is_policy_manager(void)
+static bool tomoyo_policy_manager(void)
{
struct tomoyo_policy_manager_entry *ptr;
const char *exe;
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, list) {
- if (!ptr->is_deleted && ptr->is_domain
+ list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, head.list) {
+ if (!ptr->head.is_deleted && ptr->is_domain
&& !tomoyo_pathcmp(domainname, ptr->manager)) {
found = true;
break;
exe = tomoyo_get_exe();
if (!exe)
return false;
- list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) {
- if (!ptr->is_deleted && !ptr->is_domain
+ list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, head.list) {
+ if (!ptr->head.is_deleted && !ptr->is_domain
&& !strcmp(exe, ptr->manager->name)) {
found = true;
break;
}
/**
- * tomoyo_is_select_one - Parse select command.
+ * tomoyo_select_one - Parse select command.
*
* @head: Pointer to "struct tomoyo_io_buffer".
* @data: String to parse.
*
* Caller holds tomoyo_read_lock().
*/
-static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head,
+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 (sscanf(data, "pid=%u", &pid) == 1) {
+ if (sscanf(data, "pid=%u", &pid) == 1 ||
+ (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
struct task_struct *p;
rcu_read_lock();
read_lock(&tasklist_lock);
- p = find_task_by_vpid(pid);
+ if (global_pid)
+ p = find_task_by_pid_ns(pid, &init_pid_ns);
+ else
+ p = find_task_by_vpid(pid);
if (p)
domain = tomoyo_real_domain(p);
read_unlock(&tasklist_lock);
rcu_read_unlock();
} else if (!strncmp(data, "domain=", 7)) {
- if (tomoyo_is_domain_def(data + 7))
+ if (tomoyo_domain_def(data + 7))
domain = tomoyo_find_domain(data + 7);
} else
return false;
is_delete = true;
else if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_SELECT))
is_select = true;
- if (is_select && tomoyo_is_select_one(head, data))
+ if (is_select && tomoyo_select_one(head, data))
return 0;
/* Don't allow updating policies by non manager programs. */
- if (!tomoyo_is_policy_manager())
+ if (!tomoyo_policy_manager())
return -EPERM;
- if (tomoyo_is_domain_def(data)) {
+ if (tomoyo_domain_def(data)) {
domain = NULL;
if (is_delete)
tomoyo_delete_domain(data);
domain->ignore_global_allow_read = !is_delete;
return 0;
}
+ if (!strcmp(data, TOMOYO_KEYWORD_QUOTA_EXCEEDED)) {
+ domain->quota_warned = !is_delete;
+ return 0;
+ }
+ if (!strcmp(data, TOMOYO_KEYWORD_TRANSITION_FAILED)) {
+ domain->transition_failed = !is_delete;
+ return 0;
+ }
return tomoyo_write_domain_policy2(data, domain, is_delete);
}
continue;
pos = head->read_avail;
if (!tomoyo_io_printf(head, "allow_%s ",
- tomoyo_path2keyword(bit)) ||
+ tomoyo_path_keyword[bit]) ||
!tomoyo_print_name_union(head, &ptr->name) ||
!tomoyo_io_printf(head, "\n"))
goto out;
continue;
pos = head->read_avail;
if (!tomoyo_io_printf(head, "allow_%s ",
- tomoyo_path22keyword(bit)) ||
+ tomoyo_path2_keyword[bit]) ||
!tomoyo_print_name_union(head, &ptr->name1) ||
!tomoyo_print_name_union(head, &ptr->name2) ||
!tomoyo_io_printf(head, "\n"))
continue;
pos = head->read_avail;
if (!tomoyo_io_printf(head, "allow_%s",
- tomoyo_path_number2keyword(bit)) ||
+ tomoyo_path_number_keyword[bit]) ||
!tomoyo_print_name_union(head, &ptr->name) ||
!tomoyo_print_number_union(head, &ptr->number) ||
!tomoyo_io_printf(head, "\n"))
}
/**
- * tomoyo_print_path_number3_acl - Print a path_number3 ACL entry.
+ * tomoyo_print_mkdev_acl - Print a mkdev ACL entry.
*
* @head: Pointer to "struct tomoyo_io_buffer".
- * @ptr: Pointer to "struct tomoyo_path_number3_acl".
+ * @ptr: Pointer to "struct tomoyo_mkdev_acl".
*
* Returns true on success, false otherwise.
*/
-static bool tomoyo_print_path_number3_acl(struct tomoyo_io_buffer *head,
- struct tomoyo_path_number3_acl *ptr)
+static bool tomoyo_print_mkdev_acl(struct tomoyo_io_buffer *head,
+ struct tomoyo_mkdev_acl *ptr)
{
int pos;
u8 bit;
const u16 perm = ptr->perm;
- for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_NUMBER3_OPERATION;
+ for (bit = head->read_bit; bit < TOMOYO_MAX_MKDEV_OPERATION;
bit++) {
if (!(perm & (1 << bit)))
continue;
pos = head->read_avail;
if (!tomoyo_io_printf(head, "allow_%s",
- tomoyo_path_number32keyword(bit)) ||
+ tomoyo_mkdev_keyword[bit]) ||
!tomoyo_print_name_union(head, &ptr->name) ||
!tomoyo_print_number_union(head, &ptr->mode) ||
!tomoyo_print_number_union(head, &ptr->major) ||
{
const u8 acl_type = ptr->type;
+ if (ptr->is_deleted)
+ return true;
if (acl_type == TOMOYO_TYPE_PATH_ACL) {
struct tomoyo_path_acl *acl
= container_of(ptr, struct tomoyo_path_acl, head);
head);
return tomoyo_print_path_number_acl(head, acl);
}
- if (acl_type == TOMOYO_TYPE_PATH_NUMBER3_ACL) {
- struct tomoyo_path_number3_acl *acl
- = container_of(ptr, struct tomoyo_path_number3_acl,
+ if (acl_type == TOMOYO_TYPE_MKDEV_ACL) {
+ struct tomoyo_mkdev_acl *acl
+ = container_of(ptr, struct tomoyo_mkdev_acl,
head);
- return tomoyo_print_path_number3_acl(head, acl);
+ return tomoyo_print_mkdev_acl(head, acl);
}
if (acl_type == TOMOYO_TYPE_MOUNT_ACL) {
struct tomoyo_mount_acl *acl
*
* @head: Pointer to "struct tomoyo_io_buffer".
*
- * Returns 0.
- *
* Caller holds tomoyo_read_lock().
*/
-static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *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 0;
+ return;
if (head->read_step == 0)
head->read_step = 1;
list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) {
break;
}
head->read_eof = done;
- return 0;
}
/**
* This is equivalent to doing
*
* ( echo "select " $domainname; echo "use_profile " $profile ) |
- * /usr/lib/ccs/loadpolicy -d
+ * /usr/sbin/tomoyo-loadpolicy -d
*
* Caller holds tomoyo_read_lock().
*/
*
* Caller holds tomoyo_read_lock().
*/
-static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
+static void tomoyo_read_domain_profile(struct tomoyo_io_buffer *head)
{
struct list_head *pos;
bool done = true;
if (head->read_eof)
- return 0;
+ 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);
break;
}
head->read_eof = done;
- return 0;
}
/**
* The PID is specified by tomoyo_write_pid() so that the user can obtain
* using read()/write() interface rather than sysctl() interface.
*/
-static int tomoyo_read_pid(struct tomoyo_io_buffer *head)
+static void tomoyo_read_pid(struct tomoyo_io_buffer *head)
{
if (head->read_avail == 0 && !head->read_eof) {
const int pid = head->read_step;
domain->domainname->name);
head->read_eof = true;
}
- return 0;
}
/**
if (tomoyo_str_starts(&data, TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN))
return tomoyo_write_domain_initializer_policy(data, true,
is_delete);
+ 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))
*
* @head: Pointer to "struct tomoyo_io_buffer".
*
- * Returns 0 on success, -EINVAL otherwise.
- *
* Caller holds tomoyo_read_lock().
*/
-static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
+static void tomoyo_read_exception_policy(struct tomoyo_io_buffer *head)
{
if (!head->read_eof) {
switch (head->read_step) {
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:
case 11:
head->read_eof = true;
break;
- default:
- return -EINVAL;
}
}
- return 0;
}
/**
* tomoyo_read_query - Read access requests which violated policy in enforcing mode.
*
* @head: Pointer to "struct tomoyo_io_buffer".
- *
- * Returns 0.
*/
-static int tomoyo_read_query(struct tomoyo_io_buffer *head)
+static void tomoyo_read_query(struct tomoyo_io_buffer *head)
{
struct list_head *tmp;
int pos = 0;
int len = 0;
char *buf;
if (head->read_avail)
- return 0;
+ return;
if (head->read_buf) {
kfree(head->read_buf);
head->read_buf = NULL;
spin_unlock(&tomoyo_query_list_lock);
if (!len) {
head->read_step = 0;
- return 0;
+ return;
}
buf = kzalloc(len, GFP_NOFS);
if (!buf)
- return 0;
+ return;
pos = 0;
spin_lock(&tomoyo_query_list_lock);
list_for_each(tmp, &tomoyo_query_list) {
} else {
kfree(buf);
}
- return 0;
}
/**
*
* Returns version information.
*/
-static int tomoyo_read_version(struct tomoyo_io_buffer *head)
+static void tomoyo_read_version(struct tomoyo_io_buffer *head)
{
if (!head->read_eof) {
- tomoyo_io_printf(head, "2.2.0");
+ tomoyo_io_printf(head, "2.3.0-pre");
head->read_eof = true;
}
- return 0;
}
/**
*
* Returns the current process's domainname.
*/
-static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
+static void tomoyo_read_self_domain(struct tomoyo_io_buffer *head)
{
if (!head->read_eof) {
/*
tomoyo_io_printf(head, "%s", tomoyo_domain()->domainname->name);
head->read_eof = true;
}
- return 0;
}
/**
if (mutex_lock_interruptible(&head->io_sem))
return -EINTR;
/* Call the policy handler. */
- len = head->read(head);
+ head->read(head);
if (len < 0)
goto out;
/* Write to buffer. */
/* Don't allow updating policies by non manager programs. */
if (head->write != tomoyo_write_pid &&
head->write != tomoyo_write_domain_policy &&
- !tomoyo_is_policy_manager())
+ !tomoyo_policy_manager())
return -EPERM;
if (mutex_lock_interruptible(&head->io_sem))
return -EINTR;
profile, domain->domainname->name);
}
tomoyo_read_unlock(idx);
- printk(KERN_INFO "TOMOYO: 2.2.0 2009/04/01\n");
+ if (tomoyo_profile_version != 20090903)
+ panic("Profile version %u is not supported.\n",
+ tomoyo_profile_version);
+ printk(KERN_INFO "TOMOYO: 2.3.0-pre 2010/06/03\n");
printk(KERN_INFO "Mandatory Access Control activated.\n");
}