summaryrefslogtreecommitdiff
path: root/security/tomoyo/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/tomoyo/common.c')
-rw-r--r--security/tomoyo/common.c430
1 files changed, 310 insertions, 120 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 283862aebdc8..0f78898bce09 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* security/tomoyo/common.c
*
@@ -7,6 +8,7 @@
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/security.h>
+#include <linux/string_helpers.h>
#include "common.h"
/* String table for operation mode. */
@@ -174,16 +176,6 @@ static bool tomoyo_manage_by_non_root;
/* Utility functions. */
/**
- * tomoyo_yesno - Return "yes" or "no".
- *
- * @value: Bool value.
- */
-const char *tomoyo_yesno(const unsigned int value)
-{
- return value ? "yes" : "no";
-}
-
-/**
* tomoyo_addprintf - strncat()-like-snprintf().
*
* @buffer: Buffer to write to. Must be '\0'-terminated.
@@ -192,10 +184,12 @@ const char *tomoyo_yesno(const unsigned int value)
*
* Returns nothing.
*/
+__printf(3, 4)
static void tomoyo_addprintf(char *buffer, int len, const char *fmt, ...)
{
va_list args;
const int pos = strlen(buffer);
+
va_start(args, fmt);
vsnprintf(buffer + pos, len - pos - 1, fmt, args);
va_end(args);
@@ -213,6 +207,7 @@ static bool tomoyo_flush(struct tomoyo_io_buffer *head)
while (head->r.w_pos) {
const char *w = head->r.w[0];
size_t len = strlen(w);
+
if (len) {
if (len > head->read_user_buf_avail)
len = head->read_user_buf_avail;
@@ -278,6 +273,7 @@ static void tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt,
size_t len;
size_t pos = head->r.avail;
int size = head->readbuf_size - pos;
+
if (size <= 0)
return;
va_start(args, fmt);
@@ -343,13 +339,14 @@ static bool tomoyo_namespace_enabled;
void tomoyo_init_policy_namespace(struct tomoyo_policy_namespace *ns)
{
unsigned int idx;
+
for (idx = 0; idx < TOMOYO_MAX_ACL_GROUPS; idx++)
INIT_LIST_HEAD(&ns->acl_group[idx]);
for (idx = 0; idx < TOMOYO_MAX_GROUP; idx++)
INIT_LIST_HEAD(&ns->group_list[idx]);
for (idx = 0; idx < TOMOYO_MAX_POLICY; idx++)
INIT_LIST_HEAD(&ns->policy_list[idx]);
- ns->profile_version = 20110903;
+ ns->profile_version = 20150505;
tomoyo_namespace_enabled = !list_empty(&tomoyo_namespace_list);
list_add_tail_rcu(&ns->namespace_list, &tomoyo_namespace_list);
}
@@ -432,6 +429,7 @@ static void tomoyo_print_number_union_nospace
u8 min_type = ptr->value_type[0];
const u8 max_type = ptr->value_type[1];
char buffer[128];
+
buffer[0] = '\0';
for (i = 0; i < 2; i++) {
switch (min_type) {
@@ -486,12 +484,13 @@ static struct tomoyo_profile *tomoyo_assign_profile
{
struct tomoyo_profile *ptr;
struct tomoyo_profile *entry;
+
if (profile >= TOMOYO_MAX_PROFILES)
return NULL;
ptr = ns->profile_ptr[profile];
if (ptr)
return ptr;
- entry = kzalloc(sizeof(*entry), GFP_NOFS);
+ entry = kzalloc(sizeof(*entry), GFP_NOFS | __GFP_NOWARN);
if (mutex_lock_interruptible(&tomoyo_policy_lock))
goto out;
ptr = ns->profile_ptr[profile];
@@ -529,6 +528,7 @@ struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns,
{
static struct tomoyo_profile tomoyo_null_profile;
struct tomoyo_profile *ptr = ns->profile_ptr[profile];
+
if (!ptr)
ptr = &tomoyo_null_profile;
return ptr;
@@ -545,6 +545,7 @@ struct tomoyo_profile *tomoyo_profile(const struct tomoyo_policy_namespace *ns,
static s8 tomoyo_find_yesno(const char *string, const char *find)
{
const char *cp = strstr(string, find);
+
if (cp) {
cp += strlen(find);
if (!strncmp(cp, "=yes", 4))
@@ -568,6 +569,7 @@ static void tomoyo_set_uint(unsigned int *i, const char *string,
const char *find)
{
const char *cp = strstr(string, find);
+
if (cp)
sscanf(cp + strlen(find), "=%u", i);
}
@@ -586,6 +588,7 @@ static int tomoyo_set_mode(char *name, const char *value,
{
u8 i;
u8 config;
+
if (!strcmp(name, "CONFIG")) {
i = TOMOYO_MAX_MAC_INDEX + TOMOYO_MAX_MAC_CATEGORY_INDEX;
config = profile->default_config;
@@ -594,10 +597,12 @@ static int tomoyo_set_mode(char *name, const char *value,
for (i = 0; i < TOMOYO_MAX_MAC_INDEX
+ TOMOYO_MAX_MAC_CATEGORY_INDEX; i++) {
int len = 0;
+
if (i < TOMOYO_MAX_MAC_INDEX) {
const u8 c = tomoyo_index2category[i];
const char *category =
tomoyo_category_keywords[c];
+
len = strlen(category);
if (strncmp(name, category, len) ||
name[len++] != ':' || name[len++] != ':')
@@ -617,11 +622,12 @@ static int tomoyo_set_mode(char *name, const char *value,
config = TOMOYO_CONFIG_USE_DEFAULT;
} else {
u8 mode;
+
for (mode = 0; mode < 4; mode++)
if (strstr(value, tomoyo_mode[mode]))
/*
* Update lower 3 bits in order to distinguish
- * 'config' from 'TOMOYO_CONFIG_USE_DEAFULT'.
+ * 'config' from 'TOMOYO_CONFIG_USE_DEFAULT'.
*/
config = (config & ~7) | mode;
if (config != TOMOYO_CONFIG_USE_DEFAULT) {
@@ -663,6 +669,7 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
unsigned int i;
char *cp;
struct tomoyo_profile *profile;
+
if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version)
== 1)
return 0;
@@ -682,6 +689,7 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head)
const struct tomoyo_path_info *new_comment
= tomoyo_get_name(cp);
const struct tomoyo_path_info *old_comment;
+
if (!new_comment)
return -ENOMEM;
spin_lock(&lock);
@@ -714,8 +722,8 @@ static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config)
{
tomoyo_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n",
tomoyo_mode[config & 3],
- tomoyo_yesno(config & TOMOYO_CONFIG_WANT_GRANT_LOG),
- tomoyo_yesno(config & TOMOYO_CONFIG_WANT_REJECT_LOG));
+ str_yes_no(config & TOMOYO_CONFIG_WANT_GRANT_LOG),
+ str_yes_no(config & TOMOYO_CONFIG_WANT_REJECT_LOG));
}
/**
@@ -731,6 +739,7 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
struct tomoyo_policy_namespace *ns =
container_of(head->r.ns, typeof(*ns), namespace_list);
const struct tomoyo_profile *profile;
+
if (head->r.eof)
return;
next:
@@ -759,6 +768,7 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
u8 i;
const struct tomoyo_path_info *comment =
profile->comment;
+
tomoyo_print_namespace(head);
tomoyo_io_printf(head, "%u-COMMENT=", index);
tomoyo_set_string(head, comment ? comment->name : "");
@@ -787,6 +797,7 @@ static void tomoyo_read_profile(struct tomoyo_io_buffer *head)
+ TOMOYO_MAX_MAC_CATEGORY_INDEX; head->r.bit++) {
const u8 i = head->r.bit;
const u8 config = profile->config[i];
+
if (config == TOMOYO_CONFIG_USE_DEFAULT)
continue;
tomoyo_print_namespace(head);
@@ -846,10 +857,10 @@ static int tomoyo_update_manager_entry(const char *manager,
struct tomoyo_acl_param param = {
/* .ns = &tomoyo_kernel_namespace, */
.is_delete = is_delete,
- .list = &tomoyo_kernel_namespace.
- policy_list[TOMOYO_ID_MANAGER],
+ .list = &tomoyo_kernel_namespace.policy_list[TOMOYO_ID_MANAGER],
};
int error = is_delete ? -ENOENT : -ENOMEM;
+
if (!tomoyo_correct_domain(manager) &&
!tomoyo_correct_word(manager))
return -EINVAL;
@@ -893,10 +904,10 @@ static void tomoyo_read_manager(struct tomoyo_io_buffer *head)
{
if (head->r.eof)
return;
- list_for_each_cookie(head->r.acl, &tomoyo_kernel_namespace.
- policy_list[TOMOYO_ID_MANAGER]) {
+ list_for_each_cookie(head->r.acl, &tomoyo_kernel_namespace.policy_list[TOMOYO_ID_MANAGER]) {
struct tomoyo_manager *ptr =
list_entry(head->r.acl, typeof(*ptr), head.list);
+
if (ptr->head.is_deleted)
continue;
if (!tomoyo_flush(head))
@@ -921,7 +932,7 @@ static bool tomoyo_manager(void)
const char *exe;
const struct task_struct *task = current;
const struct tomoyo_path_info *domainname = tomoyo_domain()->domainname;
- bool found = false;
+ bool found = IS_ENABLED(CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING);
if (!tomoyo_policy_loaded)
return true;
@@ -932,8 +943,8 @@ static bool tomoyo_manager(void)
exe = tomoyo_get_exe();
if (!exe)
return false;
- list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace.
- policy_list[TOMOYO_ID_MANAGER], head.list) {
+ list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace.policy_list[TOMOYO_ID_MANAGER], head.list,
+ srcu_read_lock_held(&tomoyo_ss)) {
if (!ptr->head.is_deleted &&
(!tomoyo_pathcmp(domainname, ptr->manager) ||
!strcmp(exe, ptr->manager->name))) {
@@ -944,9 +955,10 @@ static bool tomoyo_manager(void)
if (!found) { /* Reduce error messages. */
static pid_t last_pid;
const pid_t pid = current->pid;
+
if (last_pid != pid) {
- printk(KERN_WARNING "%s ( %s ) is not permitted to "
- "update policies.\n", domainname->name, exe);
+ pr_warn("%s ( %s ) is not permitted to update policies.\n",
+ domainname->name, exe);
last_pid = pid;
}
}
@@ -973,19 +985,21 @@ static bool tomoyo_select_domain(struct tomoyo_io_buffer *head,
unsigned int pid;
struct tomoyo_domain_info *domain = NULL;
bool global_pid = false;
+
if (strncmp(data, "select ", 7))
return false;
data += 7;
if (sscanf(data, "pid=%u", &pid) == 1 ||
(global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
struct task_struct *p;
+
rcu_read_lock();
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);
+ domain = tomoyo_task(p)->domain_info;
rcu_read_unlock();
} else if (!strncmp(data, "domain=", 7)) {
if (tomoyo_domain_def(data + 7))
@@ -1003,7 +1017,7 @@ static bool tomoyo_select_domain(struct tomoyo_io_buffer *head,
if (domain)
head->r.domain = &domain->list;
else
- head->r.eof = 1;
+ head->r.eof = true;
tomoyo_io_printf(head, "# select %s\n", data);
if (domain && domain->is_deleted)
tomoyo_io_printf(head, "# This is a deleted domain.\n");
@@ -1019,10 +1033,11 @@ static bool tomoyo_select_domain(struct tomoyo_io_buffer *head,
* Returns true if @a == @b, false otherwise.
*/
static bool tomoyo_same_task_acl(const struct tomoyo_acl_info *a,
- const struct tomoyo_acl_info *b)
+ const struct tomoyo_acl_info *b)
{
const struct tomoyo_task_acl *p1 = container_of(a, typeof(*p1), head);
const struct tomoyo_task_acl *p2 = container_of(b, typeof(*p2), head);
+
return p1->domainname == p2->domainname;
}
@@ -1038,11 +1053,13 @@ static bool tomoyo_same_task_acl(const struct tomoyo_acl_info *a,
static int tomoyo_write_task(struct tomoyo_acl_param *param)
{
int error = -EINVAL;
+
if (tomoyo_str_starts(&param->data, "manual_domain_transition ")) {
struct tomoyo_task_acl e = {
.head.type = TOMOYO_TYPE_MANUAL_TASK_ACL,
.domainname = tomoyo_get_domainname(param),
};
+
if (e.domainname)
error = tomoyo_update_domain(&e.head, sizeof(e), param,
tomoyo_same_task_acl,
@@ -1071,7 +1088,8 @@ static int tomoyo_delete_domain(char *domainname)
if (mutex_lock_interruptible(&tomoyo_policy_lock))
return -EINTR;
/* Is there an active domain? */
- list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
+ list_for_each_entry_rcu(domain, &tomoyo_domain_list, list,
+ srcu_read_lock_held(&tomoyo_ss)) {
/* Never delete tomoyo_kernel_domain */
if (domain == &tomoyo_kernel_domain)
continue;
@@ -1109,7 +1127,7 @@ static int tomoyo_write_domain2(struct tomoyo_policy_namespace *ns,
};
static const struct {
const char *keyword;
- int (*write) (struct tomoyo_acl_param *);
+ int (*write)(struct tomoyo_acl_param *param);
} tomoyo_callback[5] = {
{ "file ", tomoyo_write_file },
{ "network inet ", tomoyo_write_inet_network },
@@ -1150,9 +1168,11 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
struct tomoyo_domain_info *domain = head->w.domain;
const bool is_delete = head->w.is_delete;
bool is_select = !is_delete && tomoyo_str_starts(&data, "select ");
- unsigned int profile;
+ unsigned int idx;
+
if (*data == '<') {
int ret = 0;
+
domain = NULL;
if (is_delete)
ret = tomoyo_delete_domain(data);
@@ -1166,23 +1186,27 @@ static int tomoyo_write_domain(struct tomoyo_io_buffer *head)
if (!domain)
return -EINVAL;
ns = domain->ns;
- if (sscanf(data, "use_profile %u", &profile) == 1
- && profile < TOMOYO_MAX_PROFILES) {
- if (!tomoyo_policy_loaded || ns->profile_ptr[profile])
- domain->profile = (u8) profile;
+ if (sscanf(data, "use_profile %u", &idx) == 1
+ && idx < TOMOYO_MAX_PROFILES) {
+ if (!tomoyo_policy_loaded || ns->profile_ptr[idx])
+ if (!is_delete)
+ domain->profile = (u8) idx;
return 0;
}
- if (sscanf(data, "use_group %u\n", &profile) == 1
- && profile < TOMOYO_MAX_ACL_GROUPS) {
+ if (sscanf(data, "use_group %u\n", &idx) == 1
+ && idx < TOMOYO_MAX_ACL_GROUPS) {
if (!is_delete)
- domain->group = (u8) profile;
+ set_bit(idx, domain->group);
+ else
+ clear_bit(idx, domain->group);
return 0;
}
- for (profile = 0; profile < TOMOYO_MAX_DOMAIN_INFO_FLAGS; profile++) {
- const char *cp = tomoyo_dif[profile];
+ for (idx = 0; idx < TOMOYO_MAX_DOMAIN_INFO_FLAGS; idx++) {
+ const char *cp = tomoyo_dif[idx];
+
if (strncmp(data, cp, strlen(cp) - 1))
continue;
- domain->flags[profile] = !is_delete;
+ domain->flags[idx] = !is_delete;
return 0;
}
return tomoyo_write_domain2(ns, &domain->acl_info_list, data,
@@ -1208,7 +1232,7 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
tomoyo_set_space(head);
tomoyo_set_string(head, cond->transit->name);
}
- /* fall through */
+ fallthrough;
case 1:
{
const u16 condc = cond->condc;
@@ -1224,9 +1248,11 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
const struct tomoyo_envp *envp =
(typeof(envp)) (argv + cond->argc);
u16 skip;
+
for (skip = 0; skip < head->r.cond_index; skip++) {
const u8 left = condp->left;
const u8 right = condp->right;
+
condp++;
switch (left) {
case TOMOYO_ARGV_ENTRY:
@@ -1252,6 +1278,7 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
const u8 match = condp->equals;
const u8 left = condp->left;
const u8 right = condp->right;
+
if (!tomoyo_flush(head))
return false;
condp++;
@@ -1261,8 +1288,7 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
case TOMOYO_ARGV_ENTRY:
tomoyo_io_printf(head,
"exec.argv[%lu]%s=\"",
- argv->index, argv->
- is_not ? "!" : "");
+ argv->index, argv->is_not ? "!" : "");
tomoyo_set_string(head,
argv->value->name);
tomoyo_set_string(head, "\"");
@@ -1273,12 +1299,10 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
"exec.envp[\"");
tomoyo_set_string(head,
envp->name->name);
- tomoyo_io_printf(head, "\"]%s=", envp->
- is_not ? "!" : "");
+ tomoyo_io_printf(head, "\"]%s=", envp->is_not ? "!" : "");
if (envp->value) {
tomoyo_set_string(head, "\"");
- tomoyo_set_string(head, envp->
- value->name);
+ tomoyo_set_string(head, envp->value->name);
tomoyo_set_string(head, "\"");
} else {
tomoyo_set_string(head,
@@ -1313,17 +1337,17 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
}
}
head->r.cond_step++;
- /* fall through */
+ fallthrough;
case 2:
if (!tomoyo_flush(head))
break;
head->r.cond_step++;
- /* fall through */
+ fallthrough;
case 3:
if (cond->grant_log != TOMOYO_GRANTLOG_AUTO)
tomoyo_io_printf(head, " grant_log=%s",
- tomoyo_yesno(cond->grant_log ==
- TOMOYO_GRANTLOG_YES));
+ str_yes_no(cond->grant_log ==
+ TOMOYO_GRANTLOG_YES));
tomoyo_set_lf(head);
return true;
}
@@ -1374,6 +1398,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
struct tomoyo_path_acl *ptr =
container_of(acl, typeof(*ptr), head);
const u16 perm = ptr->perm;
+
for (bit = 0; bit < TOMOYO_MAX_PATH_OPERATION; bit++) {
if (!(perm & (1 << bit)))
continue;
@@ -1394,6 +1419,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
} else if (acl_type == TOMOYO_TYPE_MANUAL_TASK_ACL) {
struct tomoyo_task_acl *ptr =
container_of(acl, typeof(*ptr), head);
+
tomoyo_set_group(head, "task ");
tomoyo_set_string(head, "manual_domain_transition ");
tomoyo_set_string(head, ptr->domainname->name);
@@ -1403,6 +1429,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
struct tomoyo_path2_acl *ptr =
container_of(acl, typeof(*ptr), head);
const u8 perm = ptr->perm;
+
for (bit = 0; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) {
if (!(perm & (1 << bit)))
continue;
@@ -1423,6 +1450,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
struct tomoyo_path_number_acl *ptr =
container_of(acl, typeof(*ptr), head);
const u8 perm = ptr->perm;
+
for (bit = 0; bit < TOMOYO_MAX_PATH_NUMBER_OPERATION; bit++) {
if (!(perm & (1 << bit)))
continue;
@@ -1443,6 +1471,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
struct tomoyo_mkdev_acl *ptr =
container_of(acl, typeof(*ptr), head);
const u8 perm = ptr->perm;
+
for (bit = 0; bit < TOMOYO_MAX_MKDEV_OPERATION; bit++) {
if (!(perm & (1 << bit)))
continue;
@@ -1489,6 +1518,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
->name);
} else {
char buf[128];
+
tomoyo_print_ip(buf, sizeof(buf), &ptr->address);
tomoyo_io_printf(head, "%s", buf);
}
@@ -1518,6 +1548,7 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head,
} else if (acl_type == TOMOYO_TYPE_MOUNT_ACL) {
struct tomoyo_mount_acl *ptr =
container_of(acl, typeof(*ptr), head);
+
tomoyo_set_group(head, "file mount");
tomoyo_print_name_union(head, &ptr->dev_name);
tomoyo_print_name_union(head, &ptr->dir_name);
@@ -1561,6 +1592,7 @@ static bool tomoyo_read_domain2(struct tomoyo_io_buffer *head,
list_for_each_cookie(head->r.acl, list) {
struct tomoyo_acl_info *ptr =
list_entry(head->r.acl, typeof(*ptr), list);
+
if (!tomoyo_print_entry(head, ptr))
return false;
}
@@ -1582,8 +1614,9 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head)
list_for_each_cookie(head->r.domain, &tomoyo_domain_list) {
struct tomoyo_domain_info *domain =
list_entry(head->r.domain, typeof(*domain), list);
+ u8 i;
+
switch (head->r.step) {
- u8 i;
case 0:
if (domain->is_deleted &&
!head->r.print_this_domain_only)
@@ -1593,22 +1626,33 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head)
tomoyo_set_lf(head);
tomoyo_io_printf(head, "use_profile %u\n",
domain->profile);
- tomoyo_io_printf(head, "use_group %u\n",
- domain->group);
for (i = 0; i < TOMOYO_MAX_DOMAIN_INFO_FLAGS; i++)
if (domain->flags[i])
tomoyo_set_string(head, tomoyo_dif[i]);
+ head->r.index = 0;
head->r.step++;
- tomoyo_set_lf(head);
- /* fall through */
+ fallthrough;
case 1:
+ while (head->r.index < TOMOYO_MAX_ACL_GROUPS) {
+ i = head->r.index++;
+ if (!test_bit(i, domain->group))
+ continue;
+ tomoyo_io_printf(head, "use_group %u\n", i);
+ if (!tomoyo_flush(head))
+ return;
+ }
+ head->r.index = 0;
+ head->r.step++;
+ tomoyo_set_lf(head);
+ fallthrough;
+ case 2:
if (!tomoyo_read_domain2(head, &domain->acl_info_list))
return;
head->r.step++;
if (!tomoyo_set_lf(head))
return;
- /* fall through */
- case 2:
+ fallthrough;
+ case 3:
head->r.step = 0;
if (head->r.print_this_domain_only)
goto done;
@@ -1659,14 +1703,15 @@ static void tomoyo_read_pid(struct tomoyo_io_buffer *head)
head->r.eof = true;
if (tomoyo_str_starts(&buf, "global-pid "))
global_pid = true;
- pid = (unsigned int) simple_strtoul(buf, NULL, 10);
+ if (kstrtouint(buf, 10, &pid))
+ return;
rcu_read_lock();
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);
+ domain = tomoyo_task(p)->domain_info;
rcu_read_unlock();
if (!domain)
return;
@@ -1709,6 +1754,7 @@ static int tomoyo_write_exception(struct tomoyo_io_buffer *head)
.data = head->write_buf,
};
u8 i;
+
if (tomoyo_str_starts(&param.data, "aggregator "))
return tomoyo_write_aggregator(&param);
for (i = 0; i < TOMOYO_MAX_TRANSITION_TYPE; i++)
@@ -1720,6 +1766,7 @@ static int tomoyo_write_exception(struct tomoyo_io_buffer *head)
if (tomoyo_str_starts(&param.data, "acl_group ")) {
unsigned int group;
char *data;
+
group = simple_strtoul(param.data, &data, 10);
if (group < TOMOYO_MAX_ACL_GROUPS && *data++ == ' ')
return tomoyo_write_domain2
@@ -1744,12 +1791,15 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx)
struct tomoyo_policy_namespace *ns =
container_of(head->r.ns, typeof(*ns), namespace_list);
struct list_head *list = &ns->group_list[idx];
+
list_for_each_cookie(head->r.group, list) {
struct tomoyo_group *group =
list_entry(head->r.group, typeof(*group), head.list);
+
list_for_each_cookie(head->r.acl, &group->member_list) {
struct tomoyo_acl_head *ptr =
list_entry(head->r.acl, typeof(*ptr), list);
+
if (ptr->is_deleted)
continue;
if (!tomoyo_flush(head))
@@ -1769,10 +1819,10 @@ static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx)
head)->number);
} else if (idx == TOMOYO_ADDRESS_GROUP) {
char buffer[128];
-
struct tomoyo_address_group *member =
container_of(ptr, typeof(*member),
head);
+
tomoyo_print_ip(buffer, sizeof(buffer),
&member->address);
tomoyo_io_printf(head, " %s", buffer);
@@ -1800,6 +1850,7 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx)
struct tomoyo_policy_namespace *ns =
container_of(head->r.ns, typeof(*ns), namespace_list);
struct list_head *list = &ns->policy_list[idx];
+
list_for_each_cookie(head->r.acl, list) {
struct tomoyo_acl_head *acl =
container_of(head->r.acl, typeof(*acl), list);
@@ -1812,6 +1863,7 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx)
{
struct tomoyo_transition_control *ptr =
container_of(acl, typeof(*ptr), head);
+
tomoyo_print_namespace(head);
tomoyo_set_string(head, tomoyo_transition_type
[ptr->type]);
@@ -1827,6 +1879,7 @@ static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx)
{
struct tomoyo_aggregator *ptr =
container_of(acl, typeof(*ptr), head);
+
tomoyo_print_namespace(head);
tomoyo_set_string(head, "aggregator ");
tomoyo_set_string(head,
@@ -1856,6 +1909,7 @@ static void tomoyo_read_exception(struct tomoyo_io_buffer *head)
{
struct tomoyo_policy_namespace *ns =
container_of(head->r.ns, typeof(*ns), namespace_list);
+
if (head->r.eof)
return;
while (head->r.step < TOMOYO_MAX_POLICY &&
@@ -1919,6 +1973,7 @@ static atomic_t tomoyo_query_observers = ATOMIC_INIT(0);
static int tomoyo_truncate(char *str)
{
char *start = str;
+
while (*(unsigned char *) str > (unsigned char) ' ')
str++;
*str = '\0';
@@ -1926,6 +1981,114 @@ static int tomoyo_truncate(char *str)
}
/**
+ * tomoyo_numscan - sscanf() which stores the length of a decimal integer value.
+ *
+ * @str: String to scan.
+ * @head: Leading string that must start with.
+ * @width: Pointer to "int" for storing length of a decimal integer value after @head.
+ * @tail: Optional character that must match after a decimal integer value.
+ *
+ * Returns whether @str starts with @head and a decimal value follows @head.
+ */
+static bool tomoyo_numscan(const char *str, const char *head, int *width, const char tail)
+{
+ const char *cp;
+ const int n = strlen(head);
+
+ if (!strncmp(str, head, n)) {
+ cp = str + n;
+ while (*cp && *cp >= '0' && *cp <= '9')
+ cp++;
+ if (*cp == tail || !tail) {
+ *width = cp - (str + n);
+ return *width != 0;
+ }
+ }
+ *width = 0;
+ return 0;
+}
+
+/**
+ * tomoyo_patternize_path - Make patterns for file path. Used by learning mode.
+ *
+ * @buffer: Destination buffer.
+ * @len: Size of @buffer.
+ * @entry: Original line.
+ *
+ * Returns nothing.
+ */
+static void tomoyo_patternize_path(char *buffer, const int len, char *entry)
+{
+ int width;
+ char *cp = entry;
+
+ /* Nothing to do if this line is not for "file" related entry. */
+ if (strncmp(entry, "file ", 5))
+ goto flush;
+ /*
+ * Nothing to do if there is no colon in this line, for this rewriting
+ * applies to only filesystems where numeric values in the path are volatile.
+ */
+ cp = strchr(entry + 5, ':');
+ if (!cp) {
+ cp = entry;
+ goto flush;
+ }
+ /* Flush e.g. "file ioctl" part. */
+ while (*cp != ' ')
+ cp--;
+ *cp++ = '\0';
+ tomoyo_addprintf(buffer, len, "%s ", entry);
+ /* e.g. file ioctl pipe:[$INO] $CMD */
+ if (tomoyo_numscan(cp, "pipe:[", &width, ']')) {
+ cp += width + 7;
+ tomoyo_addprintf(buffer, len, "pipe:[\\$]");
+ goto flush;
+ }
+ /* e.g. file ioctl socket:[$INO] $CMD */
+ if (tomoyo_numscan(cp, "socket:[", &width, ']')) {
+ cp += width + 9;
+ tomoyo_addprintf(buffer, len, "socket:[\\$]");
+ goto flush;
+ }
+ if (!strncmp(cp, "proc:/self", 10)) {
+ /* e.g. file read proc:/self/task/$TID/fdinfo/$FD */
+ cp += 10;
+ tomoyo_addprintf(buffer, len, "proc:/self");
+ } else if (tomoyo_numscan(cp, "proc:/", &width, 0)) {
+ /* e.g. file read proc:/$PID/task/$TID/fdinfo/$FD */
+ /*
+ * Don't patternize $PID part if $PID == 1, for several
+ * programs access only files in /proc/1/ directory.
+ */
+ cp += width + 6;
+ if (width == 1 && *(cp - 1) == '1')
+ tomoyo_addprintf(buffer, len, "proc:/1");
+ else
+ tomoyo_addprintf(buffer, len, "proc:/\\$");
+ } else {
+ goto flush;
+ }
+ /* Patternize $TID part if "/task/" follows. */
+ if (tomoyo_numscan(cp, "/task/", &width, 0)) {
+ cp += width + 6;
+ tomoyo_addprintf(buffer, len, "/task/\\$");
+ }
+ /* Patternize $FD part if "/fd/" or "/fdinfo/" follows. */
+ if (tomoyo_numscan(cp, "/fd/", &width, 0)) {
+ cp += width + 4;
+ tomoyo_addprintf(buffer, len, "/fd/\\$");
+ } else if (tomoyo_numscan(cp, "/fdinfo/", &width, 0)) {
+ cp += width + 8;
+ tomoyo_addprintf(buffer, len, "/fdinfo/\\$");
+ }
+flush:
+ /* Flush remaining part if any. */
+ if (*cp)
+ tomoyo_addprintf(buffer, len, "%s", cp);
+}
+
+/**
* tomoyo_add_entry - Add an ACL to current thread's domain. Used by learning mode.
*
* @domain: Pointer to "struct tomoyo_domain_info".
@@ -1941,13 +2104,15 @@ static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header)
char *symlink = NULL;
char *cp = strchr(header, '\n');
int len;
+
if (!cp)
return;
cp = strchr(cp + 1, '\n');
if (!cp)
return;
*cp++ = '\0';
- len = strlen(cp) + 1;
+ /* Reserve some space for potentially using patterns. */
+ len = strlen(cp) + 16;
/* strstr() will return NULL if ordering is wrong. */
if (*cp == 'f') {
argv0 = strstr(header, " argv[]={ \"");
@@ -1964,10 +2129,10 @@ static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header)
if (symlink)
len += tomoyo_truncate(symlink + 1) + 1;
}
- buffer = kmalloc(len, GFP_NOFS);
+ buffer = kmalloc(len, GFP_NOFS | __GFP_ZERO);
if (!buffer)
return;
- snprintf(buffer, len - 1, "%s", cp);
+ tomoyo_patternize_path(buffer, len, cp);
if (realpath)
tomoyo_addprintf(buffer, len, " exec.%s", realpath);
if (argv0)
@@ -2000,8 +2165,9 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
static unsigned int tomoyo_serial;
struct tomoyo_query entry = { };
bool quota_exceeded = false;
+
va_start(args, fmt);
- len = vsnprintf((char *) &len, 1, fmt, args) + 1;
+ len = vsnprintf(NULL, 0, fmt, args) + 1;
va_end(args);
/* Write /sys/kernel/security/tomoyo/audit. */
va_start(args, fmt);
@@ -2023,7 +2189,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
/* Check max_learning_entry parameter. */
if (tomoyo_domain_quota_is_ok(r))
break;
- /* fall through */
+ fallthrough;
default:
return 0;
}
@@ -2038,7 +2204,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
tomoyo_add_entry(r->domain, entry.query);
goto out;
}
- len = tomoyo_round2(entry.query_len);
+ len = kmalloc_size_roundup(entry.query_len);
entry.domain = r->domain;
spin_lock(&tomoyo_query_list_lock);
if (tomoyo_memory_quota[TOMOYO_MEMORY_QUERY] &&
@@ -2061,8 +2227,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...)
(tomoyo_answer_wait, entry.answer ||
!atomic_read(&tomoyo_query_observers), HZ))
break;
- else
- entry.timer++;
+ entry.timer++;
}
spin_lock(&tomoyo_query_list_lock);
list_del(&entry.list);
@@ -2098,6 +2263,7 @@ static struct tomoyo_domain_info *tomoyo_find_domain_by_qid
{
struct tomoyo_query *ptr;
struct tomoyo_domain_info *domain = NULL;
+
spin_lock(&tomoyo_query_list_lock);
list_for_each_entry(ptr, &tomoyo_query_list, list) {
if (ptr->serial != serial)
@@ -2115,17 +2281,17 @@ static struct tomoyo_domain_info *tomoyo_find_domain_by_qid
* @file: Pointer to "struct file".
* @wait: Pointer to "poll_table".
*
- * Returns POLLIN | POLLRDNORM when ready to read, 0 otherwise.
+ * Returns EPOLLIN | EPOLLRDNORM when ready to read, 0 otherwise.
*
* Waits for access requests which violated policy in enforcing mode.
*/
-static unsigned int tomoyo_poll_query(struct file *file, poll_table *wait)
+static __poll_t tomoyo_poll_query(struct file *file, poll_table *wait)
{
if (!list_empty(&tomoyo_query_list))
- return POLLIN | POLLRDNORM;
+ return EPOLLIN | EPOLLRDNORM;
poll_wait(file, &tomoyo_query_wait, wait);
if (!list_empty(&tomoyo_query_list))
- return POLLIN | POLLRDNORM;
+ return EPOLLIN | EPOLLRDNORM;
return 0;
}
@@ -2140,15 +2306,15 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head)
unsigned int pos = 0;
size_t len = 0;
char *buf;
+
if (head->r.w_pos)
return;
- if (head->read_buf) {
- kfree(head->read_buf);
- head->read_buf = NULL;
- }
+ kfree(head->read_buf);
+ head->read_buf = NULL;
spin_lock(&tomoyo_query_list_lock);
list_for_each(tmp, &tomoyo_query_list) {
struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
+
if (pos++ != head->r.query_index)
continue;
len = ptr->query_len;
@@ -2166,6 +2332,7 @@ static void tomoyo_read_query(struct tomoyo_io_buffer *head)
spin_lock(&tomoyo_query_list_lock);
list_for_each(tmp, &tomoyo_query_list) {
struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
+
if (pos++ != head->r.query_index)
continue;
/*
@@ -2200,9 +2367,11 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
struct list_head *tmp;
unsigned int serial;
unsigned int answer;
+
spin_lock(&tomoyo_query_list_lock);
list_for_each(tmp, &tomoyo_query_list) {
struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
+
ptr->timer = 0;
}
spin_unlock(&tomoyo_query_list_lock);
@@ -2211,6 +2380,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
spin_lock(&tomoyo_query_list_lock);
list_for_each(tmp, &tomoyo_query_list) {
struct tomoyo_query *ptr = list_entry(tmp, typeof(*ptr), list);
+
if (ptr->serial != serial)
continue;
ptr->answer = answer;
@@ -2233,7 +2403,7 @@ static int tomoyo_write_answer(struct tomoyo_io_buffer *head)
static void tomoyo_read_version(struct tomoyo_io_buffer *head)
{
if (!head->r.eof) {
- tomoyo_io_printf(head, "2.5.0");
+ tomoyo_io_printf(head, "2.6.0");
head->r.eof = true;
}
}
@@ -2253,10 +2423,10 @@ static const char * const tomoyo_memory_headers[TOMOYO_MAX_MEMORY_STAT] = {
[TOMOYO_MEMORY_QUERY] = "query message:",
};
-/* Timestamp counter for last updated. */
-static unsigned int tomoyo_stat_updated[TOMOYO_MAX_POLICY_STAT];
/* Counter for number of updates. */
-static unsigned int tomoyo_stat_modified[TOMOYO_MAX_POLICY_STAT];
+static atomic_t tomoyo_stat_updated[TOMOYO_MAX_POLICY_STAT];
+/* Timestamp counter for last updated. */
+static time64_t tomoyo_stat_modified[TOMOYO_MAX_POLICY_STAT];
/**
* tomoyo_update_stat - Update statistic counters.
@@ -2267,13 +2437,8 @@ static unsigned int tomoyo_stat_modified[TOMOYO_MAX_POLICY_STAT];
*/
void tomoyo_update_stat(const u8 index)
{
- struct timeval tv;
- do_gettimeofday(&tv);
- /*
- * I don't use atomic operations because race condition is not fatal.
- */
- tomoyo_stat_updated[index]++;
- tomoyo_stat_modified[index] = tv.tv_sec;
+ atomic_inc(&tomoyo_stat_updated[index]);
+ tomoyo_stat_modified[index] = ktime_get_real_seconds();
}
/**
@@ -2287,17 +2452,18 @@ static void tomoyo_read_stat(struct tomoyo_io_buffer *head)
{
u8 i;
unsigned int total = 0;
+
if (head->r.eof)
return;
for (i = 0; i < TOMOYO_MAX_POLICY_STAT; i++) {
tomoyo_io_printf(head, "Policy %-30s %10u",
tomoyo_policy_headers[i],
- tomoyo_stat_updated[i]);
+ atomic_read(&tomoyo_stat_updated[i]));
if (tomoyo_stat_modified[i]) {
struct tomoyo_time stamp;
+
tomoyo_convert_time(tomoyo_stat_modified[i], &stamp);
- tomoyo_io_printf(head, " (Last: %04u/%02u/%02u "
- "%02u:%02u:%02u)",
+ tomoyo_io_printf(head, " (Last: %04u/%02u/%02u %02u:%02u:%02u)",
stamp.year, stamp.month, stamp.day,
stamp.hour, stamp.min, stamp.sec);
}
@@ -2305,6 +2471,7 @@ static void tomoyo_read_stat(struct tomoyo_io_buffer *head)
}
for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++) {
unsigned int used = tomoyo_memory_used[i];
+
total += used;
tomoyo_io_printf(head, "Memory used by %-22s %10u",
tomoyo_memory_headers[i], used);
@@ -2329,6 +2496,7 @@ static int tomoyo_write_stat(struct tomoyo_io_buffer *head)
{
char *data = head->write_buf;
u8 i;
+
if (tomoyo_str_starts(&data, "Memory used by "))
for (i = 0; i < TOMOYO_MAX_MEMORY_STAT; i++)
if (tomoyo_str_starts(&data, tomoyo_memory_headers[i]))
@@ -2451,15 +2619,16 @@ int tomoyo_open_control(const u8 type, struct file *file)
* @file: Pointer to "struct file".
* @wait: Pointer to "poll_table". Maybe NULL.
*
- * Returns POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM if ready to read/write,
- * POLLOUT | POLLWRNORM otherwise.
+ * Returns EPOLLIN | EPOLLRDNORM | EPOLLOUT | EPOLLWRNORM if ready to read/write,
+ * EPOLLOUT | EPOLLWRNORM otherwise.
*/
-unsigned int tomoyo_poll_control(struct file *file, poll_table *wait)
+__poll_t tomoyo_poll_control(struct file *file, poll_table *wait)
{
struct tomoyo_io_buffer *head = file->private_data;
+
if (head->poll)
- return head->poll(file, wait) | POLLOUT | POLLWRNORM;
- return POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
+ return head->poll(file, wait) | EPOLLOUT | EPOLLWRNORM;
+ return EPOLLIN | EPOLLRDNORM | EPOLLOUT | EPOLLWRNORM;
}
/**
@@ -2472,6 +2641,7 @@ unsigned int tomoyo_poll_control(struct file *file, poll_table *wait)
static inline void tomoyo_set_namespace_cursor(struct tomoyo_io_buffer *head)
{
struct list_head *ns;
+
if (head->type != TOMOYO_EXCEPTIONPOLICY &&
head->type != TOMOYO_PROFILE)
return;
@@ -2505,7 +2675,7 @@ static inline bool tomoyo_has_more_namespace(struct tomoyo_io_buffer *head)
* tomoyo_read_control - read() for /sys/kernel/security/tomoyo/ interface.
*
* @head: Pointer to "struct tomoyo_io_buffer".
- * @buffer: Poiner to buffer to write to.
+ * @buffer: Pointer to buffer to write to.
* @buffer_len: Size of @buffer.
*
* Returns bytes read on success, negative value otherwise.
@@ -2517,7 +2687,7 @@ ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer,
int idx;
if (!head->read)
- return -ENOSYS;
+ return -EINVAL;
if (mutex_lock_interruptible(&head->io_sem))
return -EINTR;
head->read_user_buf = buffer;
@@ -2539,7 +2709,7 @@ ssize_t tomoyo_read_control(struct tomoyo_io_buffer *head, char __user *buffer,
/**
* tomoyo_parse_policy - Parse a policy line.
*
- * @head: Poiter to "struct tomoyo_io_buffer".
+ * @head: Pointer to "struct tomoyo_io_buffer".
* @line: Line to parse.
*
* Returns 0 on success, negative value otherwise.
@@ -2557,6 +2727,7 @@ static int tomoyo_parse_policy(struct tomoyo_io_buffer *head, char *line)
head->type == TOMOYO_PROFILE) {
if (*line == '<') {
char *cp = strchr(line, ' ');
+
if (cp) {
*cp++ = '\0';
head->w.ns = tomoyo_assign_namespace(line);
@@ -2587,22 +2758,24 @@ ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head,
{
int error = buffer_len;
size_t avail_len = buffer_len;
- char *cp0 = head->write_buf;
+ char *cp0;
int idx;
+
if (!head->write)
- return -ENOSYS;
- if (!access_ok(VERIFY_READ, buffer, buffer_len))
- return -EFAULT;
+ return -EINVAL;
if (mutex_lock_interruptible(&head->io_sem))
return -EINTR;
+ cp0 = head->write_buf;
head->read_user_buf_avail = 0;
idx = tomoyo_read_lock();
/* Read a line and dispatch it to the policy handler. */
while (avail_len > 0) {
char c;
+
if (head->w.avail >= head->writebuf_size - 1) {
const int len = head->writebuf_size * 2;
- char *cp = kzalloc(len, GFP_NOFS);
+ char *cp = kzalloc(len, GFP_NOFS | __GFP_NOWARN);
+
if (!cp) {
error = -ENOMEM;
break;
@@ -2639,13 +2812,13 @@ ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head,
case TOMOYO_DOMAINPOLICY:
if (tomoyo_select_domain(head, cp0))
continue;
- /* fall through */
+ fallthrough;
case TOMOYO_EXCEPTIONPOLICY:
if (!strcmp(cp0, "select transition_only")) {
head->r.print_transition_related_only = true;
continue;
}
- /* fall through */
+ fallthrough;
default:
if (!tomoyo_manager()) {
error = -EPERM;
@@ -2701,30 +2874,33 @@ void tomoyo_check_profile(void)
{
struct tomoyo_domain_info *domain;
const int idx = tomoyo_read_lock();
+
tomoyo_policy_loaded = true;
- printk(KERN_INFO "TOMOYO: 2.5.0\n");
- list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
+ pr_info("TOMOYO: 2.6.0\n");
+ list_for_each_entry_rcu(domain, &tomoyo_domain_list, list,
+ srcu_read_lock_held(&tomoyo_ss)) {
const u8 profile = domain->profile;
- const struct tomoyo_policy_namespace *ns = domain->ns;
- if (ns->profile_version != 20110903)
- printk(KERN_ERR
- "Profile version %u is not supported.\n",
+ struct tomoyo_policy_namespace *ns = domain->ns;
+
+ if (ns->profile_version == 20110903) {
+ pr_info_once("Converting profile version from %u to %u.\n",
+ 20110903, 20150505);
+ ns->profile_version = 20150505;
+ }
+ if (ns->profile_version != 20150505)
+ pr_err("Profile version %u is not supported.\n",
ns->profile_version);
else if (!ns->profile_ptr[profile])
- printk(KERN_ERR
- "Profile %u (used by '%s') is not defined.\n",
+ pr_err("Profile %u (used by '%s') is not defined.\n",
profile, domain->domainname->name);
else
continue;
- printk(KERN_ERR
- "Userland tools for TOMOYO 2.5 must be installed and "
- "policy must be initialized.\n");
- printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/2.5/ "
- "for more information.\n");
+ pr_err("Userland tools for TOMOYO 2.6 must be installed and policy must be initialized.\n");
+ pr_err("Please see https://tomoyo.sourceforge.net/2.6/ for more information.\n");
panic("STOP!");
}
tomoyo_read_unlock(idx);
- printk(KERN_INFO "Mandatory Access Control activated.\n");
+ pr_info("Mandatory Access Control activated.\n");
}
/**
@@ -2734,6 +2910,16 @@ void tomoyo_check_profile(void)
*/
void __init tomoyo_load_builtin_policy(void)
{
+#ifdef CONFIG_SECURITY_TOMOYO_INSECURE_BUILTIN_SETTING
+ static char tomoyo_builtin_profile[] __initdata =
+ "PROFILE_VERSION=20150505\n"
+ "0-CONFIG={ mode=learning grant_log=no reject_log=yes }\n";
+ static char tomoyo_builtin_exception_policy[] __initdata =
+ "aggregator proc:/self/exe /proc/self/exe\n";
+ static char tomoyo_builtin_domain_policy[] __initdata = "";
+ static char tomoyo_builtin_manager[] __initdata = "";
+ static char tomoyo_builtin_stat[] __initdata = "";
+#else
/*
* This include file is manually created and contains built-in policy
* named "tomoyo_builtin_profile", "tomoyo_builtin_exception_policy",
@@ -2741,11 +2927,14 @@ void __init tomoyo_load_builtin_policy(void)
* "tomoyo_builtin_stat" in the form of "static char [] __initdata".
*/
#include "builtin-policy.h"
+#endif
u8 i;
const int idx = tomoyo_read_lock();
+
for (i = 0; i < 5; i++) {
struct tomoyo_io_buffer head = { };
char *start = "";
+
switch (i) {
case 0:
start = tomoyo_builtin_profile;
@@ -2775,6 +2964,7 @@ void __init tomoyo_load_builtin_policy(void)
}
while (1) {
char *end = strchr(start, '\n');
+
if (!end)
break;
*end = '\0';