security/talpa/Kconfig | 15 ++++ security/talpa/Makefile | 1 + security/talpa/talpa.h | 20 ++++++- security/talpa/talpa_common.c | 19 +++++- security/talpa/talpa_evaluation_calls.h | 7 ++ security/talpa/talpa_interceptor.c | 2 + security/talpa/talpa_path_exclude.c | 108 +++++++++++++++++++++++++++++++ 7 files changed, 170 insertions(+), 2 deletions(-) diff --git a/security/talpa/Kconfig b/security/talpa/Kconfig index 4fc22ad..7b45eaf 100644 --- a/security/talpa/Kconfig +++ b/security/talpa/Kconfig @@ -68,3 +68,18 @@ config TALPA_THREAD_EXCLUSION on a corresponding device node. If you are unsure how to answer this question, answer Y. + + +config TALPA_PATH_EXCLUDE + bool "Filesystem path exclusions" + depends on TALPA + default y + help + Path exclusion filter enables marking certain filesystem paths + as excluded from vetting operations. + + This is generally useful for trusted areas or for content not + handled well by the userspace vetting daemon. Typical examples + include mail spools and database stores. + + If you are unsure how to answer this question, answer Y. diff --git a/security/talpa/Makefile b/security/talpa/Makefile index 2abaaa2..a275788 100644 --- a/security/talpa/Makefile +++ b/security/talpa/Makefile @@ -12,3 +12,4 @@ talpa-$(CONFIG_TALPA_CACHE) += talpa_cache.o talpa-$(CONFIG_TALPA_OPERATION_EXCLUSION) += talpa_operation_exclude.o talpa-$(CONFIG_TALPA_FS_EXCLUDE) += talpa_fs_exclude.o talpa-$(CONFIG_TALPA_THREAD_EXCLUSION) += talpa_thread_exclude.o +talpa-$(CONFIG_TALPA_PATH_EXCLUDE) += talpa_path_exclude.o diff --git a/security/talpa/talpa.h b/security/talpa/talpa.h index b151723..86949d5 100644 --- a/security/talpa/talpa.h +++ b/security/talpa/talpa.h @@ -51,9 +51,14 @@ enum talpa_action { * @flags: as passed to open(2) * @authoritative: set to non-zero when decision has been made based on file content * @code: error code if applicable + * @path: internal use only - do not touch + * @path_len: internal use only - do not touch + * @page: internal use only - do not touch * * This object is created by the interceptor and passed to all filters * to do the vetting. + * Internal fields must not be used!!!!111one one!!! + * To get the file path use the talpa_get_path helper function. */ struct talpa_file_vetting { enum talpa_operation operation; @@ -62,6 +67,9 @@ struct talpa_file_vetting { unsigned int authoritative; int code; long cache_seqno; + char *path; + size_t path_len; + char *page; }; /** @@ -113,7 +121,7 @@ extern ssize_t talpa_generic_get_ulong(struct talpa_configuration *cfg, char *bu extern ssize_t talpa_generic_set_ulong(struct talpa_configuration *cfg, char *buf, size_t len); extern ssize_t talpa_generic_get_long(struct talpa_configuration *cfg, char *buf, size_t len); -#if defined CONFIG_TALPA_FS_EXCLUDE +#if defined CONFIG_TALPA_FS_EXCLUDE || defined CONFIG_TALPA_PATH_EXCLUDE /** * struct talpa_path_inclexcl - internal path inclusion or exclusion record * @path_len:length of this path @@ -145,6 +153,16 @@ struct talpa_path_list { } /** + * talpa_get_path - get the path associated with vetting details + * @tfv: vetting details + * + * Filter should use this helper to obtain the absolute path name for the + * vetting in question. + * Returns a pointer to a string or ERR_PTR. + */ +extern char *talpa_get_path(struct talpa_file_vetting *tfv); + +/** * talpa_match_path - tries to match a path in a list * @path: path to match * @list: list of paths to match agains diff --git a/security/talpa/talpa_common.c b/security/talpa/talpa_common.c index 7114428..17207d8 100644 --- a/security/talpa/talpa_common.c +++ b/security/talpa/talpa_common.c @@ -17,6 +17,7 @@ */ #include #include +#include #include #include #include @@ -57,7 +58,23 @@ ssize_t talpa_generic_get_long(struct talpa_configuration *cfg, char *buf, size_ return ret; } -#if defined CONFIG_TALPA_FS_EXCLUDE +char *talpa_get_path(struct talpa_file_vetting *tfv) +{ + /* Allocate a page of memory on first invocation. */ + if (!tfv->page) { + tfv->page = (char *)__get_free_page(GFP_KERNEL); + if (!tfv->page) + return ERR_PTR(-ENOMEM); + } + + /* Generate a path on first invocation. */ + if (!tfv->path) + tfv->path = d_path(&tfv->file->f_path, tfv->page, PAGE_SIZE); + + return tfv->path; +} + +#if defined CONFIG_TALPA_FS_EXCLUDE || defined CONFIG_TALPA_PATH_EXCLUDE static struct kmem_cache *path_list_cache; unsigned int talpa_match_path(const char *path, struct talpa_path_list *list) diff --git a/security/talpa/talpa_evaluation_calls.h b/security/talpa/talpa_evaluation_calls.h index 8612430..7b49ec9 100644 --- a/security/talpa/talpa_evaluation_calls.h +++ b/security/talpa/talpa_evaluation_calls.h @@ -5,6 +5,7 @@ enum talpa_action talpa_opexcl_examine(struct talpa_file_vetting *tfv); enum talpa_action talpa_fs_exclude_examine(struct talpa_file_vetting *tfv); +enum talpa_action talpa_path_exclude_examine(struct talpa_file_vetting *tfv); static inline int talpa_evaluation_calls(struct talpa_file_vetting *tfv) { @@ -41,5 +42,11 @@ static inline int talpa_evaluation_calls(struct talpa_file_vetting *tfv) return ret; #endif /* CONFIG_TALPA_FS_EXCLUDE */ +#ifdef CONFIG_TALPA_PATH_EXCLUDE + ret = talpa_path_exclude_examine(tfv); + if (ret != TALPA_NEXT) + return ret; +#endif /* CONFIG_TALPA_PATH_EXCLUDE */ + return ret; } diff --git a/security/talpa/talpa_interceptor.c b/security/talpa/talpa_interceptor.c index 4c0cf94..a487813 100644 --- a/security/talpa/talpa_interceptor.c +++ b/security/talpa/talpa_interceptor.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -104,6 +105,7 @@ static int talpa_vet_file(struct file *file, int flags, enum talpa_operation op) } /* Free stuff we have (or might have) allocated. */ + free_page((unsigned long)tfv->page); kmem_cache_free(tfv_cache, tfv); return ret; diff --git a/security/talpa/talpa_path_exclude.c b/security/talpa/talpa_path_exclude.c new file mode 100644 index 0000000..dbfa959 --- /dev/null +++ b/security/talpa/talpa_path_exclude.c @@ -0,0 +1,108 @@ +/* + * Copyright 2008 Sophos Plc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "talpa.h" + + +static unsigned long enabled; +static TALPA_PATH_LIST(exclusions); +static unsigned long authoritative = 1; + +/* Filter examine function. */ +enum talpa_action talpa_path_exclude_examine(struct talpa_file_vetting *tfv) +{ + char *path; + unsigned int matched = 0; + + if (!enabled || talpa_path_list_empty(&exclusions)) + return TALPA_NEXT; + + path = talpa_get_path(tfv); + if (!IS_ERR(path)) + matched = talpa_match_path(path, &exclusions); + + /* If path matches any of our exclusions stop + the vetting process right now. */ + if (matched) { + tfv->authoritative = authoritative; + return TALPA_ALLOW; + } + + return TALPA_NEXT; +} + +static struct talpa_configuration talpa_exclude_cfg[] = { + { + .name = "enabled", + .mode = S_IRUSR|S_IWUSR|S_IRGRP, + .data = &enabled, + .get = talpa_generic_get_ulong, + .set = talpa_generic_set_ulong, + }, + { + .name = "authoritative", + .mode = S_IRUSR|S_IWUSR|S_IRGRP, + .data = &authoritative, + .get = talpa_generic_get_ulong, + .set = talpa_generic_set_ulong, + }, + { + .name = "list", + .data = &exclusions, + .mode = S_IRUSR|S_IRGRP, + .get = talpa_path_list, + }, + { + .name = "add", + .data = &exclusions, + .mode = S_IWUSR|S_IWGRP, + .set = talpa_path_add, + }, + { + .name = "remove", + .data = &exclusions, + .mode = S_IWUSR|S_IWGRP, + .set = talpa_path_remove, + }, + { + }, +}; + +static __init int talpa_exclude_init(void) +{ + int ret; + + ret = talpa_register_configuration("path_exclusions", talpa_exclude_cfg); + if (ret) + pr_err("talpa: Failed to register path exclusion filter!\n"); + + return ret; +} + +__initcall(talpa_exclude_init);