diff options
author | Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> | 2011-07-08 08:23:44 +0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-07-11 05:05:33 +0400 |
commit | 2ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563 (patch) | |
tree | b9f6051059a2a90547a4501bf296b0cf3c9dbc76 /security/tomoyo/common.c | |
parent | 8761afd49ebff8ae04c1a7888af090177441d07d (diff) | |
download | linux-2ca9bf453bdd478bcb6c01aa2d0bd4c2f4350563.tar.xz |
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.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index ec02d2ab08c3..69d6b59f5937 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)) |