All of lore.kernel.org
 help / color / mirror / Atom feed
From: penguin-kernel@I-love.SAKURA.ne.jp (Tetsuo Handa)
To: linux-security-module@vger.kernel.org
Subject: [PATCH] TOMOYO: Switch from per "struct cred" blob to per "struct task_struct" blob.
Date: Tue, 28 Mar 2017 20:02:40 +0900	[thread overview]
Message-ID: <1490698960-29861-1-git-send-email-penguin-kernel@I-love.SAKURA.ne.jp> (raw)

Now that security_task_alloc() hook and "struct task_struct"->security
field are revived, switch TOMOYO to use them because TOMOYO's security
context is defined based on "struct task_struct" rather than "struct cred".

By applying this patch, TOMOYO no longer uses "struct cred"->security
which means that TOMOYO is ready for running with other fully armored LSM
modules which use "struct cred"->security field.

Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
 security/tomoyo/common.h        |  20 +++++--
 security/tomoyo/domain.c        |   8 ++-
 security/tomoyo/gc.c            |   6 +--
 security/tomoyo/securityfs_if.c |  22 ++++----
 security/tomoyo/tomoyo.c        | 112 +++++++++++++++++++---------------------
 5 files changed, 87 insertions(+), 81 deletions(-)

diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 361e7a2..5a7623b 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -684,7 +684,7 @@ struct tomoyo_domain_info {
 	u8 group;          /* Group number to use.   */
 	bool is_deleted;   /* Delete flag.           */
 	bool flags[TOMOYO_MAX_DOMAIN_INFO_FLAGS];
-	atomic_t users; /* Number of referring credentials. */
+	atomic_t users; /* Number of referring "struct task_struct". */
 };
 
 /*
@@ -911,6 +911,11 @@ struct tomoyo_policy_namespace {
 	const char *name;
 };
 
+struct tomoyo_security {
+	struct tomoyo_domain_info *tomoyo_domain_info;
+	struct tomoyo_domain_info *saved_domain_info; /* Maybe NULL. */
+};
+
 /********** Function prototypes. **********/
 
 bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address,
@@ -1202,7 +1207,16 @@ static inline void tomoyo_put_group(struct tomoyo_group *group)
  */
 static inline struct tomoyo_domain_info *tomoyo_domain(void)
 {
-	return current_cred()->security;
+	struct tomoyo_security *ts = current->security;
+
+	if (ts->saved_domain_info && !current->in_execve) {
+		struct tomoyo_domain_info *domain = ts->tomoyo_domain_info;
+
+		ts->tomoyo_domain_info = ts->saved_domain_info;
+		ts->saved_domain_info = NULL;
+		atomic_dec(&domain->users);
+	}
+	return ts->tomoyo_domain_info;
 }
 
 /**
@@ -1215,7 +1229,7 @@ static inline struct tomoyo_domain_info *tomoyo_domain(void)
 static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
 							    *task)
 {
-	return task_cred_xxx(task, security);
+	return ((struct tomoyo_security *) task->security)->tomoyo_domain_info;
 }
 
 /**
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 00d223e..9f981d8 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -677,6 +677,7 @@ static int tomoyo_environ(struct tomoyo_execve *ee)
  */
 int tomoyo_find_next_domain(struct linux_binprm *bprm)
 {
+	struct tomoyo_security *ts = current->security;
 	struct tomoyo_domain_info *old_domain = tomoyo_domain();
 	struct tomoyo_domain_info *domain = NULL;
 	const char *original_name = bprm->filename;
@@ -841,8 +842,11 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
 	if (!domain)
 		domain = old_domain;
 	/* Update reference count on "struct tomoyo_domain_info". */
-	atomic_inc(&domain->users);
-	bprm->cred->security = domain;
+	if (domain != ts->tomoyo_domain_info) {
+		atomic_inc(&domain->users);
+		ts->saved_domain_info =	ts->tomoyo_domain_info;
+		ts->tomoyo_domain_info = domain;
+	}
 	kfree(exename.name);
 	if (!retval) {
 		ee->r.domain = domain;
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c
index 540bc29..75ae368 100644
--- a/security/tomoyo/gc.c
+++ b/security/tomoyo/gc.c
@@ -248,8 +248,8 @@ static inline void tomoyo_del_domain(struct list_head *element)
 	struct tomoyo_acl_info *tmp;
 	/*
 	 * Since this domain is referenced from neither
-	 * "struct tomoyo_io_buffer" nor "struct cred"->security, we can delete
-	 * elements without checking for is_deleted flag.
+	 * "struct tomoyo_io_buffer" nor "struct tomoyo_security",
+	 * we can delete elements without checking for is_deleted flag.
 	 */
 	list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) {
 		tomoyo_del_acl(&acl->list);
@@ -433,7 +433,7 @@ static void tomoyo_try_to_gc(const enum tomoyo_policy_id type,
 		break;
 	case TOMOYO_ID_DOMAIN:
 		/*
-		 * Don't kfree() until all "struct cred"->security forget this
+		 * Don't kfree() until all "struct tomoyo_security" forget this
 		 * element.
 		 */
 		if (atomic_read(&container_of
diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c
index 06ab41b1..988261a 100644
--- a/security/tomoyo/securityfs_if.c
+++ b/security/tomoyo/securityfs_if.c
@@ -5,6 +5,7 @@
  */
 
 #include <linux/security.h>
+#include <linux/lsm_hooks.h> /* security_module_enable() */
 #include "common.h"
 
 /**
@@ -66,18 +67,13 @@ static ssize_t tomoyo_write_self(struct file *file, const char __user *buf,
 			if (!new_domain) {
 				error = -ENOENT;
 			} else {
-				struct cred *cred = prepare_creds();
-				if (!cred) {
-					error = -ENOMEM;
-				} else {
-					struct tomoyo_domain_info *old_domain =
-						cred->security;
-					cred->security = new_domain;
-					atomic_inc(&new_domain->users);
-					atomic_dec(&old_domain->users);
-					commit_creds(cred);
-					error = 0;
-				}
+				struct tomoyo_domain_info *old_domain =
+					tomoyo_domain();
+				((struct tomoyo_security *) current->security)
+					->tomoyo_domain_info = new_domain;
+				atomic_inc(&new_domain->users);
+				atomic_dec(&old_domain->users);
+				error = 0;
 			}
 		}
 		tomoyo_read_unlock(idx);
@@ -236,7 +232,7 @@ static int __init tomoyo_initerface_init(void)
 	struct dentry *tomoyo_dir;
 
 	/* Don't create securityfs entries unless registered. */
-	if (current_cred()->security != &tomoyo_kernel_domain)
+	if (!security_module_enable("tomoyo"))
 		return 0;
 
 	tomoyo_dir = securityfs_create_dir("tomoyo", NULL);
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c
index b5fb930..0de150d 100644
--- a/security/tomoyo/tomoyo.c
+++ b/security/tomoyo/tomoyo.c
@@ -8,59 +8,42 @@
 #include "common.h"
 
 /**
- * tomoyo_cred_alloc_blank - Target for security_cred_alloc_blank().
+ * tomoyo_task_alloc - Target for security_task_alloc().
  *
- * @new: Pointer to "struct cred".
- * @gfp: Memory allocation flags.
+ * @task: Pointer to "struct task_struct".
+ * @clone_flags: Not used.
  *
- * Returns 0.
- */
-static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp)
-{
-	new->security = NULL;
-	return 0;
-}
-
-/**
- * tomoyo_cred_prepare - Target for security_prepare_creds().
- *
- * @new: Pointer to "struct cred".
- * @old: Pointer to "struct cred".
- * @gfp: Memory allocation flags.
- *
- * Returns 0.
+ * Returns 0 on success, negative value otherwise.
  */
-static int tomoyo_cred_prepare(struct cred *new, const struct cred *old,
-			       gfp_t gfp)
+static int tomoyo_task_alloc(struct task_struct *task,
+			     unsigned long clone_flags)
 {
-	struct tomoyo_domain_info *domain = old->security;
-	new->security = domain;
-	if (domain)
-		atomic_inc(&domain->users);
+	struct tomoyo_security *ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+	struct tomoyo_domain_info *domain = tomoyo_domain();
+
+	if (!ts)
+		return -ENOMEM;
+	ts->tomoyo_domain_info = domain;
+	atomic_inc(&domain->users);
+	task->security = ts;
 	return 0;
 }
 
 /**
- * tomoyo_cred_transfer - Target for security_transfer_creds().
+ * tomoyo_task_free - Target for security_task_free().
  *
- * @new: Pointer to "struct cred".
- * @old: Pointer to "struct cred".
+ * @task: Pointer to "struct task_struct".
  */
-static void tomoyo_cred_transfer(struct cred *new, const struct cred *old)
+static void tomoyo_task_free(struct task_struct *task)
 {
-	tomoyo_cred_prepare(new, old, 0);
-}
+	struct tomoyo_security *ts = task->security;
+	struct tomoyo_domain_info *domain = ts->tomoyo_domain_info;
 
-/**
- * tomoyo_cred_free - Target for security_cred_free().
- *
- * @cred: Pointer to "struct cred".
- */
-static void tomoyo_cred_free(struct cred *cred)
-{
-	struct tomoyo_domain_info *domain = cred->security;
+	atomic_dec(&domain->users);
+	domain = ts->saved_domain_info;
 	if (domain)
 		atomic_dec(&domain->users);
+	kfree(ts);
 }
 
 /**
@@ -68,7 +51,7 @@ static void tomoyo_cred_free(struct cred *cred)
  *
  * @bprm: Pointer to "struct linux_binprm".
  *
- * Returns 0 on success, negative value otherwise.
+ * Returns 0.
  */
 static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
 {
@@ -86,19 +69,8 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
 	if (!tomoyo_policy_loaded)
 		tomoyo_load_policy(bprm->filename);
 #endif
-	/*
-	 * Release reference to "struct tomoyo_domain_info" stored inside
-	 * "bprm->cred->security". New reference to "struct tomoyo_domain_info"
-	 * stored inside "bprm->cred->security" will be acquired later inside
-	 * tomoyo_find_next_domain().
-	 */
-	atomic_dec(&((struct tomoyo_domain_info *)
-		     bprm->cred->security)->users);
-	/*
-	 * Tell tomoyo_bprm_check_security() is called for the first time of an
-	 * execve operation.
-	 */
-	bprm->cred->security = NULL;
+	/* Restore and clear saved_domain_info if needed. */
+	tomoyo_domain();
 	return 0;
 }
 
@@ -111,7 +83,8 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm)
  */
 static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
 {
-	struct tomoyo_domain_info *domain = bprm->cred->security;
+	struct tomoyo_security *ts = current->security;
+	struct tomoyo_domain_info *domain = ts->saved_domain_info;
 
 	/*
 	 * Execute permission is checked against pathname passed to do_execve()
@@ -131,6 +104,24 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
 }
 
 /**
+ * tomoyo_bprm_check_security - Target for security_bprm_check().
+ *
+ * @bprm: Pointer to "struct linux_binprm".
+ */
+static void tomoyo_bprm_committed_creds(struct linux_binprm *bprm)
+{
+	struct tomoyo_security *ts = current->security;
+	struct tomoyo_domain_info *domain = ts->saved_domain_info;
+
+	/* Clear saved_domain_info if needed. */
+	if (domain) {
+		ts->saved_domain_info = NULL;
+		atomic_dec(&domain->users);
+	}
+}
+
+
+/**
  * tomoyo_inode_getattr - Target for security_inode_getattr().
  *
  * @mnt:    Pointer to "struct vfsmount".
@@ -497,12 +488,11 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg,
  * registering TOMOYO.
  */
 static struct security_hook_list tomoyo_hooks[] __lsm_ro_after_init = {
-	LSM_HOOK_INIT(cred_alloc_blank, tomoyo_cred_alloc_blank),
-	LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare),
-	LSM_HOOK_INIT(cred_transfer, tomoyo_cred_transfer),
-	LSM_HOOK_INIT(cred_free, tomoyo_cred_free),
+	LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc),
+	LSM_HOOK_INIT(task_free, tomoyo_task_free),
 	LSM_HOOK_INIT(bprm_set_creds, tomoyo_bprm_set_creds),
 	LSM_HOOK_INIT(bprm_check_security, tomoyo_bprm_check_security),
+	LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds),
 	LSM_HOOK_INIT(file_fcntl, tomoyo_file_fcntl),
 	LSM_HOOK_INIT(file_open, tomoyo_file_open),
 	LSM_HOOK_INIT(path_truncate, tomoyo_path_truncate),
@@ -537,14 +527,16 @@ static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg,
  */
 static int __init tomoyo_init(void)
 {
-	struct cred *cred = (struct cred *) current_cred();
+	static struct tomoyo_security ts = {
+		.tomoyo_domain_info = &tomoyo_kernel_domain
+	};
 
 	if (!security_module_enable("tomoyo"))
 		return 0;
 	/* register ourselves with the security framework */
 	security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), "tomoyo");
 	printk(KERN_INFO "TOMOYO Linux initialized\n");
-	cred->security = &tomoyo_kernel_domain;
+	current->security = &ts;
 	tomoyo_mm_init();
 	return 0;
 }
-- 
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

             reply	other threads:[~2017-03-28 11:02 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-28 11:02 Tetsuo Handa [this message]
2017-03-28 15:26 ` [PATCH] TOMOYO: Switch from per "struct cred" blob to per "struct task_struct" blob Casey Schaufler
2017-03-30 11:09   ` Tetsuo Handa
2017-03-30 15:06     ` Casey Schaufler
2017-03-31  0:52       ` Tetsuo Handa
2017-03-31 16:09         ` Casey Schaufler
2017-04-01  3:32           ` Tetsuo Handa
  -- strict thread matches above, loose matches on Subject: below --
2017-03-12  4:41 Tetsuo Handa
2017-03-12 21:12 ` Djalal Harouni
2017-03-12 23:17   ` James Morris
2017-03-12 23:56     ` John Johansen
2017-03-13  5:59       ` James Morris

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=1490698960-29861-1-git-send-email-penguin-kernel@I-love.SAKURA.ne.jp \
    --to=penguin-kernel@i-love.sakura.ne.jp \
    --cc=linux-security-module@vger.kernel.org \
    /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.