From: Kentaro Takeda <takedakn@nttdata.co.jp>
To: akpm@linux-foundation.org
Cc: linux-kernel@vger.kernel.org,
linux-security-module@vger.kernel.org,
Kentaro Takeda <takedakn@nttdata.co.jp>,
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Subject: [TOMOYO #6 retry 13/21] environment variable name check functions.
Date: Wed, 09 Jan 2008 09:53:33 +0900 [thread overview]
Message-ID: <20080109005424.181008871@nttdata.co.jp> (raw)
In-Reply-To: 20080109005320.323184643@nttdata.co.jp
TOMOYO Linux checks environment variable's names passed to execve()
because some envorinment variables affects to the behavior of program
like argv[0].
Each permission can be automatically accumulated into
the policy of each domain using 'learning mode'.
Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
security/tomoyo/environ.c | 274 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 274 insertions(+)
--- /dev/null
+++ linux-2.6-mm/security/tomoyo/environ.c
@@ -0,0 +1,274 @@
+/*
+ * security/tomoyo/environ.c
+ *
+ * Environment variable access control functions for TOMOYO Linux.
+ */
+
+#include "tomoyo.h"
+#include "realpath.h"
+
+/************************* AUDIT FUNCTIONS *************************/
+
+static int tmy_audit_env_log(const char *env,
+ const bool is_granted,
+ const u8 profile,
+ const unsigned int mode)
+{
+ char *buf;
+ int len;
+
+ if (is_granted) {
+ if (!tmy_audit_grant())
+ return 0;
+ } else {
+ if (!tmy_audit_reject())
+ return 0;
+ }
+
+ len = strlen(env) + 8;
+ buf = tmy_init_audit_log(&len, profile, mode);
+
+ if (!buf)
+ return -ENOMEM;
+
+ tmy_sncatprintf(buf, len - 1, TMY_ALLOW_ENV "%s", env);
+
+ return tmy_write_audit_log(buf, is_granted);
+}
+
+/***** The structure for globally usable environments. *****/
+
+struct globally_usable_env_entry {
+ struct list_head list;
+ const struct path_info *env;
+ bool is_deleted;
+};
+
+/******************* GLOBALLY USABLE ENVIRONMENT HANDLER ********************/
+
+static LIST_HEAD(globally_usable_env_list);
+
+static int tmy_add_globally_usable_env_entry(const char *env,
+ const bool is_delete)
+{
+ struct globally_usable_env_entry *new_entry;
+ struct globally_usable_env_entry *ptr;
+ static DEFINE_MUTEX(lock);
+ const struct path_info *saved_env;
+ int error = -ENOMEM;
+ if (!tmy_correct_path(env, 0, 0, 0, __FUNCTION__))
+ return -EINVAL;
+ saved_env = tmy_save_name(env);
+ if (!saved_env)
+ return -ENOMEM;
+ mutex_lock(&lock);
+ list_for_each_entry(ptr, &globally_usable_env_list, list) {
+ if (ptr->env == saved_env) {
+ ptr->is_deleted = is_delete;
+ error = 0;
+ goto out;
+ }
+ }
+ if (is_delete) {
+ error = -ENOENT;
+ goto out;
+ }
+ new_entry = tmy_alloc_element(sizeof(*new_entry));
+ if (!new_entry)
+ goto out;
+ new_entry->env = saved_env;
+ list_add_tail_mb(&new_entry->list, &globally_usable_env_list);
+ error = 0;
+out:
+ mutex_unlock(&lock);
+ return error;
+}
+
+static bool tmy_is_globally_usable_env(const struct path_info *env)
+{
+ struct globally_usable_env_entry *ptr;
+ list_for_each_entry(ptr, &globally_usable_env_list, list) {
+ if (!ptr->is_deleted && tmy_path_match(env, ptr->env))
+ return 1;
+ }
+ return 0;
+}
+
+int tmy_add_globally_usable_env_policy(char *env, const bool is_delete)
+{
+ return tmy_add_globally_usable_env_entry(env, is_delete);
+}
+
+int tmy_read_globally_usable_env_policy(struct io_buffer *head)
+{
+ struct list_head *pos;
+ list_for_each_cookie(pos, head->read_var2, &globally_usable_env_list) {
+ struct globally_usable_env_entry *ptr;
+ ptr = list_entry(pos, struct globally_usable_env_entry, list);
+ if (ptr->is_deleted)
+ continue;
+ if (tmy_io_printf(head, TMY_ALLOW_ENV "%s\n",
+ ptr->env->name))
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/****************** ENVIRONMENT VARIABLE Checking HANDLER *******************/
+
+static int tmy_add_env_entry(const char *env,
+ struct domain_info *domain,
+ const struct condition_list *cond,
+ const bool is_delete)
+{
+ struct acl_info *ptr;
+ struct env_acl *acl;
+ const struct path_info *saved_env;
+ int error = -ENOMEM;
+
+ if (!tmy_correct_path(env, 0, 0, 0, __FUNCTION__))
+ return -EINVAL;
+
+ saved_env = tmy_save_name(env);
+ if (!saved_env)
+ return -ENOMEM;
+ if (!is_delete && tmy_is_globally_usable_env(saved_env))
+ return 0;
+
+ mutex_lock(&domain_acl_lock);
+
+ if (is_delete)
+ goto remove;
+
+ list_for_each_entry(ptr, &domain->acl_info_list, list) {
+ acl = container_of(ptr, struct env_acl, head);
+ if (ptr->type == TMY_TYPE_ENV_ACL && ptr->cond == cond &&
+ acl->env == saved_env) {
+ ptr->is_deleted = 0;
+ /* Found. Nothing to do. */
+ error = 0;
+ goto ok;
+ }
+ }
+
+ /* Not found. Append it to the tail. */
+ acl = tmy_alloc_element(sizeof(*acl));
+ if (!acl)
+ goto ok;
+
+ acl->head.type = TMY_TYPE_ENV_ACL;
+ acl->head.cond = cond;
+ acl->env = saved_env;
+ error = tmy_add_acl(domain, &acl->head);
+ goto ok;
+remove: ;
+ error = -ENOENT;
+ list_for_each_entry(ptr, &domain->acl_info_list, list) {
+ acl = container_of(ptr, struct env_acl, head);
+ if (ptr->type != TMY_TYPE_ENV_ACL ||
+ ptr->cond != cond || ptr->is_deleted ||
+ acl->env != saved_env)
+ continue;
+
+ error = tmy_del_acl(ptr);
+ break;
+ }
+ok: ;
+ mutex_unlock(&domain_acl_lock);
+
+ return error;
+}
+
+static int tmy_env_acl(const char *env_)
+{
+ const struct domain_info *domain = TMY_SECURITY->domain;
+ int error = -EPERM;
+ struct acl_info *ptr;
+ struct path_info env;
+
+ if (!tmy_flags(TMY_MAC_FOR_ENV))
+ return 0;
+
+ env.name = env_;
+ tmy_fill_path_info(&env);
+ if (tmy_is_globally_usable_env(&env))
+ return 0;
+
+ list_for_each_entry(ptr, &domain->acl_info_list, list) {
+ struct env_acl *acl;
+ acl = container_of(ptr, struct env_acl, head);
+
+ if (ptr->type == TMY_TYPE_ENV_ACL &&
+ ptr->is_deleted == 0 &&
+ tmy_check_condition(ptr->cond, NULL) == 0 &&
+ tmy_path_match(&env, acl->env)) {
+ error = 0;
+ break;
+ }
+ }
+
+ return error;
+}
+
+/**
+ * tmy_env_perm - check for environment variable permission.
+ * @env: pointer to environment variable.
+ *
+ * Returns zero if permission granted.
+ * Returns nonzero if permission denied.
+ */
+int tmy_env_perm(const char *env, const u8 profile, const unsigned int mode)
+{
+ int error = 0;
+ const bool is_enforce = (mode == 3);
+
+ if (!mode)
+ return 0;
+ if (!env || !*env)
+ return 0;
+
+ error = tmy_env_acl(env);
+
+ tmy_audit_env_log(env, !error, profile, mode);
+
+ if (error) {
+ struct domain_info * const domain = TMY_SECURITY->domain;
+
+ if (tmy_flags(TMY_VERBOSE))
+ tmy_audit("TOMOYO-%s: Environment variable %s "
+ "denied for %s\n",
+ tmy_getmsg(is_enforce), env,
+ tmy_lastname(domain));
+
+ if (is_enforce)
+ error = tmy_supervisor("%s\n" TMY_ALLOW_ENV "%s\n",
+ domain->domainname->name, env);
+
+ else if (mode == 1 && tmy_quota())
+ tmy_add_env_entry(env, domain, NULL, 0);
+
+ if (!is_enforce)
+ error = 0;
+ }
+
+ return error;
+}
+
+/**
+ * tmy_add_env_policy - add or delete environment variable policy.
+ * @data: a line to parse.
+ * @domain: pointer to "struct domain_info".
+ * @cond: pointer to "struct condition_list". May be NULL.
+ * @is_delete: is this delete request?
+ *
+ * Returns zero on success.
+ * Returns nonzero on failure.
+ */
+int tmy_add_env_policy(char *data,
+ struct domain_info *domain,
+ const struct condition_list *cond,
+ const bool is_delete)
+{
+ return tmy_add_env_entry(data, domain, cond,
+ is_delete);
+}
--
next prev parent reply other threads:[~2008-01-09 1:00 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-09 0:53 [TOMOYO #6 retry 00/21] TOMOYO Linux - MAC based on process invocation history Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 01/21] TOMOYO Linux documentation Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 02/21] Add struct vfsmount to struct task_struct Kentaro Takeda
2008-01-15 21:16 ` Serge E. Hallyn
2008-01-16 0:22 ` Kentaro Takeda
2008-01-16 14:39 ` Serge E. Hallyn
2008-01-17 4:55 ` Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 03/21] Add wrapper functions for VFS helper functions Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 04/21] Replace VFS with wrapper functions Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 05/21] Add packet filtering based on processs security context Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 06/21] Data structures and prototype defitions Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 07/21] Memory and pathname management functions Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 08/21] Utility functions and policy manipulation interface Kentaro Takeda
2008-01-09 4:25 ` James Morris
2008-01-09 4:29 ` James Morris
2008-01-12 2:06 ` [TOMOYO #6 retry 08/21] Utility functions and policy manipulationinterface Tetsuo Handa
2008-01-12 3:06 ` James Morris
2008-01-12 4:45 ` Greg KH
2008-01-12 7:34 ` [TOMOYO #6 retry 08/21] Utility functions and policymanipulationinterface Tetsuo Handa
2008-01-09 4:31 ` [TOMOYO #6 retry 08/21] Utility functions and policy manipulation interface Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 09/21] Domain transition functions Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 10/21] Auditing interface Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 11/21] File access control functions Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 12/21] argv0 check functions Kentaro Takeda
2008-01-09 0:53 ` Kentaro Takeda [this message]
2008-01-09 0:53 ` [TOMOYO #6 retry 14/21] Network access control functions Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 15/21] Namespace manipulation " Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 16/21] Signal " Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 17/21] Capability access " Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 18/21] LSM adapter functions Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 19/21] Conditional permission support Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 20/21] Kconfig and Makefile Kentaro Takeda
2008-01-09 0:53 ` [TOMOYO #6 retry 21/21] Add signal hooks at sleepable location Kentaro Takeda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080109005424.181008871@nttdata.co.jp \
--to=takedakn@nttdata.co.jp \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=penguin-kernel@I-love.SAKURA.ne.jp \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.