summaryrefslogtreecommitdiffstats
path: root/security/tomoyo/common.c
diff options
context:
space:
mode:
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>2011-07-08 13:23:44 +0900
committerJames Morris <jmorris@namei.org>2011-07-11 11:05:33 +1000
commit2ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563 (patch)
treeb9f6051059a2a90547a4501bf296b0cf3c9dbc76 /security/tomoyo/common.c
parent8761afd49ebff8ae04c1a7888af090177441d07d (diff)
TOMOYO: Allow using executable's realpath and symlink's target as conditions.
This patch adds support for permission checks using executable file's realpath upon execve() and symlink's target upon symlink(). Hooks are in the last patch of this pathset. Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/tomoyo/common.c')
-rw-r--r--security/tomoyo/common.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index ec02d2ab08c..69d6b59f593 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -79,6 +79,8 @@ const char * const tomoyo_condition_keyword[TOMOYO_MAX_CONDITION_KEYWORD] = {
[TOMOYO_MODE_OTHERS_READ] = "others_read",
[TOMOYO_MODE_OTHERS_WRITE] = "others_write",
[TOMOYO_MODE_OTHERS_EXECUTE] = "others_execute",
+ [TOMOYO_EXEC_REALPATH] = "exec.realpath",
+ [TOMOYO_SYMLINK_TARGET] = "symlink.target",
[TOMOYO_PATH1_UID] = "path1.uid",
[TOMOYO_PATH1_GID] = "path1.gid",
[TOMOYO_PATH1_INO] = "path1.ino",
@@ -353,6 +355,27 @@ static void tomoyo_print_name_union(struct tomoyo_io_buffer *head,
}
/**
+ * tomoyo_print_name_union_quoted - Print a tomoyo_name_union with a quote.
+ *
+ * @head: Pointer to "struct tomoyo_io_buffer".
+ * @ptr: Pointer to "struct tomoyo_name_union".
+ *
+ * Returns nothing.
+ */
+static void tomoyo_print_name_union_quoted(struct tomoyo_io_buffer *head,
+ const struct tomoyo_name_union *ptr)
+{
+ if (ptr->group) {
+ tomoyo_set_string(head, "@");
+ tomoyo_set_string(head, ptr->group->group_name->name);
+ } else {
+ tomoyo_set_string(head, "\"");
+ tomoyo_set_string(head, ptr->filename->name);
+ tomoyo_set_string(head, "\"");
+ }
+}
+
+/**
* tomoyo_print_number_union_nospace - Print a tomoyo_number_union without a space.
*
* @head: Pointer to "struct tomoyo_io_buffer".
@@ -1101,6 +1124,9 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
(typeof(condp)) (cond + 1);
const struct tomoyo_number_union *numbers_p =
(typeof(numbers_p)) (condp + condc);
+ const struct tomoyo_name_union *names_p =
+ (typeof(names_p))
+ (numbers_p + cond->numbers_count);
u16 skip;
for (skip = 0; skip < head->r.cond_index; skip++) {
const u8 left = condp->left;
@@ -1112,6 +1138,9 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
break;
}
switch (right) {
+ case TOMOYO_NAME_UNION:
+ names_p++;
+ break;
case TOMOYO_NUMBER_UNION:
numbers_p++;
break;
@@ -1138,6 +1167,10 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head,
}
tomoyo_set_string(head, match ? "=" : "!=");
switch (right) {
+ case TOMOYO_NAME_UNION:
+ tomoyo_print_name_union_quoted
+ (head, names_p++);
+ break;
case TOMOYO_NUMBER_UNION:
tomoyo_print_number_union_nospace
(head, numbers_p++);
@@ -1666,6 +1699,22 @@ static DEFINE_SPINLOCK(tomoyo_query_list_lock);
static atomic_t tomoyo_query_observers = ATOMIC_INIT(0);
/**
+ * tomoyo_truncate - Truncate a line.
+ *
+ * @str: String to truncate.
+ *
+ * Returns length of truncated @str.
+ */
+static int tomoyo_truncate(char *str)
+{
+ char *start = str;
+ while (*(unsigned char *) str > (unsigned char) ' ')
+ str++;
+ *str = '\0';
+ return strlen(start) + 1;
+}
+
+/**
* tomoyo_add_entry - Add an ACL to current thread's domain. Used by learning mode.
*
* @domain: Pointer to "struct tomoyo_domain_info".
@@ -1676,6 +1725,8 @@ static atomic_t tomoyo_query_observers = ATOMIC_INIT(0);
static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header)
{
char *buffer;
+ char *realpath = NULL;
+ char *symlink = NULL;
char *cp = strchr(header, '\n');
int len;
if (!cp)
@@ -1685,10 +1736,25 @@ static void tomoyo_add_entry(struct tomoyo_domain_info *domain, char *header)
return;
*cp++ = '\0';
len = strlen(cp) + 1;
+ /* strstr() will return NULL if ordering is wrong. */
+ if (*cp == 'f') {
+ realpath = strstr(header, " exec={ realpath=\"");
+ if (realpath) {
+ realpath += 8;
+ len += tomoyo_truncate(realpath) + 6;
+ }
+ symlink = strstr(header, " symlink.target=\"");
+ if (symlink)
+ len += tomoyo_truncate(symlink + 1) + 1;
+ }
buffer = kmalloc(len, GFP_NOFS);
if (!buffer)
return;
snprintf(buffer, len - 1, "%s", cp);
+ if (realpath)
+ tomoyo_addprintf(buffer, len, " exec.%s", realpath);
+ if (symlink)
+ tomoyo_addprintf(buffer, len, "%s", symlink);
tomoyo_normalize_line(buffer);
if (!tomoyo_write_domain2(domain->ns, &domain->acl_info_list, buffer,
false))