public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Kentaro Takeda <takedakn@nttdata.co.jp>
To: linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org
Subject: [TOMOYO 4/9] LSM adapter for TOMOYO.
Date: Thu, 14 Jun 2007 16:34:50 +0900	[thread overview]
Message-ID: <4670EF9A.4080506@nttdata.co.jp> (raw)
In-Reply-To: <5fb14edc0706140030x4a906178ofd35df06dfa5c192@mail.gmail.com>

This file contains wrapper functions for TOMOYO's file access control functions.
The main job is to find "struct vfsmount" that corresponds to "struct dentry"
passed to LSM hooks.

Since "struct vfsmount" is not passed to LSM hooks,
TOMOYO can't determine which pathnames was requested by the process
if bind mounts are used.

If bind mounts are used, TOMOYO requires all permissions for
all possible pathnames (whereas AppArmor requires one of possible pathnames).
If "struct vfsmount" is passed to LSM hooks as AppArmor proposes,
this file will become more simpler and "namespace_sem" can remain "static".

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>

---------------
 security/tomoyo/tomoyo.c |  283 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 283 insertions(+)

diff -ubBpErN linux-2.6.21.5/security/tomoyo/tomoyo.c linux-2.6.21.5-tomoyo/security/tomoyo/tomoyo.c
--- linux-2.6.21.5/security/tomoyo/tomoyo.c	1970-01-01 09:00:00.000000000 +0900
+++ linux-2.6.21.5-tomoyo/security/tomoyo/tomoyo.c	2007-06-14 15:11:57.000000000 +0900
@@ -0,0 +1,283 @@
+/*
+ * security/tomoyo/tomoyo.c
+ *
+ * LSM hooks for TOMOYO Linux.
+ *
+ * Copyright (C) 2005-2007  NTT DATA CORPORATION
+ *
+ * Version: 2.0   2007/06/05
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/security.h>
+#include <linux/highmem.h>
+#include <linux/namei.h>
+#include <linux/mnt_namespace.h>
+#include <linux/sysctl.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+
+#include "tomoyo.h"
+
+/* The initial domain. */
+struct domain_info KERNEL_DOMAIN = { NULL, NULL, NULL, 0, 0, 0 };
+extern struct rw_semaphore namespace_sem;
+
+static struct kmem_cache *tomoyo_cachep = NULL;
+
+static int tomoyo_task_alloc_security(struct task_struct *p)
+{
+	struct tomoyo_security *ptr = kmem_cache_alloc(tomoyo_cachep, GFP_KERNEL);
+	if (!ptr)
+		return -ENOMEM;
+	memcpy(ptr, current->security, sizeof(*ptr));
+	p->security = ptr;
+	return 0;
+}
+
+static void tomoyo_task_free_security(struct task_struct *p)
+{
+	kmem_cache_free(tomoyo_cachep, p->security);
+}
+
+static int tomoyo_bprm_alloc_security(struct linux_binprm *bprm)
+{
+	bprm->security = ((struct tomoyo_security *) current->security)->domain_info;
+	return 0;
+}
+
+static int tomoyo_bprm_check_security(struct linux_binprm * bprm)
+{
+	struct domain_info *next_domain = NULL;
+ 	int retval = 0;
+	extern void tomoyo_load_policy(const char *filename);
+	extern int tomoyo_find_next_domain(struct linux_binprm *, struct domain_info **);
+	tomoyo_load_policy(bprm->filename);
+	if (!(((struct tomoyo_security *) current->security)->flags
+	      & TOMOYO_CHECK_READ_FOR_OPEN_EXEC)) {
+		retval = tomoyo_find_next_domain(bprm, &next_domain);
+		if (retval == 0) {
+			((struct tomoyo_security *) current->security)->domain_info = next_domain;
+			((struct tomoyo_security *) current->security)->flags |=
+				TOMOYO_CHECK_READ_FOR_OPEN_EXEC;
+		}
+	}
+	
+	return retval;
+}
+
+static void tomoyo_bprm_post_apply_creds(struct linux_binprm * bprm)
+{
+	bprm->security = ((struct tomoyo_security *) current->security)->domain_info;
+}
+
+static void tomoyo_bprm_free_security(struct linux_binprm * bprm)
+{
+	((struct tomoyo_security *) current->security)->domain_info =
+		(struct domain_info *) bprm->security;
+	((struct tomoyo_security *) current->security)->flags &=
+		~TOMOYO_CHECK_READ_FOR_OPEN_EXEC;
+}
+
+static int tomoyo_inode_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+	int flag = 0;
+	if (S_ISDIR(inode->i_mode)) /* ignore because inode is directory */
+		return 0;
+	if (!nd || !nd->dentry || !nd->mnt)
+		return 0;
+	if ((mask == MAY_EXEC) && (((struct tomoyo_security *) current->security)->flags &
+	                           TOMOYO_CHECK_READ_FOR_OPEN_EXEC))
+		mask = MAY_READ;
+	if ((mask == MAY_EXEC) || (mask == 0))
+		return 0;
+
+	if (mask == (MAY_READ | MAY_EXEC)) {
+		flag |= O_RDONLY + 1;
+	} else {
+		if (mask & MAY_READ)
+			flag |= O_RDONLY + 1;
+		if (mask & MAY_WRITE)
+			flag |= O_WRONLY + 1;
+		if ((mask & MAY_APPEND))
+			flag |= O_APPEND;
+	}
+	return tomoyo_check_open_permission(nd->dentry, nd->mnt, flag);
+}
+
+static int tomoyo_do_check_single_write_permission(int operation, struct dentry *dentry)
+{
+	struct mnt_namespace *namespace = current->nsproxy->mnt_ns;
+	struct list_head *p;
+	int ret = 0, error = 0;
+	int index = 0, index2 = 0;
+	if (!dentry || !namespace)
+		return 0;
+ start:
+	index2 = 0;
+	/* lock namespace */
+	down_read(&namespace_sem);
+	list_for_each(p, &namespace->list) {
+		struct vfsmount *mnt = list_entry(p, struct vfsmount, mnt_list);
+		if (mnt->mnt_root->d_sb != dentry->d_sb) continue;
+		if (index2++ < index) continue;
+		/* unlock namespace */
+		up_read(&namespace_sem);
+		if ((error = tomoyo_check_single_write_permission(operation, dentry, mnt)) != 0)
+			ret = error;
+		index++;
+		goto start;
+	}
+	/* unlock namespace */
+	up_read(&namespace_sem);
+	return ret;
+}
+
+static int tomoyo_inode_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+	if (iattr->ia_valid & ATTR_SIZE)
+		return tomoyo_do_check_single_write_permission(TOMOYO_TYPE_TRUNCATE_ACL, dentry);
+	return 0;
+}
+
+static int tomoyo_inode_create(struct inode *dir, struct dentry *dentry, int mode)
+{
+	return tomoyo_do_check_single_write_permission(TOMOYO_TYPE_CREATE_ACL, dentry);
+}
+
+static int tomoyo_inode_unlink(struct inode *dir, struct dentry *dentry)
+{
+	return tomoyo_do_check_single_write_permission(TOMOYO_TYPE_UNLINK_ACL, dentry);
+}
+
+static int tomoyo_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	return tomoyo_do_check_single_write_permission(TOMOYO_TYPE_MKDIR_ACL, dentry);
+}
+
+static int tomoyo_inode_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	return tomoyo_do_check_single_write_permission(TOMOYO_TYPE_RMDIR_ACL, dentry);
+}
+
+static int tomoyo_inode_symlink(struct inode *dir, struct dentry *dentry, const char *old_name)
+{
+	return tomoyo_do_check_single_write_permission(TOMOYO_TYPE_SYMLINK_ACL, dentry);
+}
+
+static int tomoyo_inode_mknod(struct inode *inode, struct dentry *dentry, int mode, dev_t dev)
+{
+	if (S_ISCHR(mode))
+		return tomoyo_do_check_single_write_permission(TOMOYO_TYPE_MKCHAR_ACL, dentry);
+	if (S_ISBLK(mode))
+		return tomoyo_do_check_single_write_permission(TOMOYO_TYPE_MKBLOCK_ACL, dentry);
+	if (S_ISFIFO(mode))
+		return tomoyo_do_check_single_write_permission(TOMOYO_TYPE_MKFIFO_ACL, dentry);
+	if (S_ISSOCK(mode))
+		return tomoyo_do_check_single_write_permission(TOMOYO_TYPE_MKSOCK_ACL, dentry);
+	return 0;
+}
+
+static int tomoyo_do_check_double_write_permission(int operation,
+                                                   struct dentry *old_dentry,
+                                                   struct dentry *new_dentry)
+{
+	struct mnt_namespace *namespace = current->nsproxy->mnt_ns;
+	struct list_head *p;
+	int ret = 0, error = 0;
+	int index = 0, index2 = 0;
+	if (!old_dentry || !new_dentry)
+		return 0;
+ start:
+	index2 = 0;
+	/* lock namespace */
+	down_read(&namespace_sem);
+	list_for_each(p, &namespace->list) {
+		struct vfsmount *mnt = list_entry(p, struct vfsmount, mnt_list);
+		if (mnt->mnt_root->d_sb != old_dentry->d_sb) continue;
+		if (index2++ < index) continue;
+		/* unlock namespace */
+		up_read(&namespace_sem);
+		if ((error = tomoyo_check_double_write_permission(operation,
+		                                                  old_dentry,
+		                                                  mnt,
+		                                                  new_dentry,
+		                                                  mnt)) != 0)
+			ret = error;
+		index++;
+		goto start;
+	}
+	/* unlock namespace */
+	up_read(&namespace_sem);
+	return ret;
+}
+
+static int tomoyo_inode_link(struct dentry *old_dentry,
+                             struct inode *inode,
+                             struct dentry *new_dentry)
+{
+	return tomoyo_do_check_double_write_permission(TOMOYO_TYPE_LINK_ACL, old_dentry, new_dentry);
+}
+
+static int tomoyo_inode_rename(struct inode *old_inode,
+                               struct dentry *old_dentry,
+                               struct inode *new_inode,
+                               struct dentry *new_dentry)
+{
+	return tomoyo_do_check_double_write_permission(TOMOYO_TYPE_RENAME_ACL,
+	                                               old_dentry,
+	                                               new_dentry);
+}
+
+static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	if (!(arg & O_APPEND))
+		return tomoyo_check_rewrite_permission(file);
+	return 0;
+}
+
+struct security_operations tomoyo_security_ops = {
+	.task_alloc_security   = tomoyo_task_alloc_security,
+	.task_free_security    = tomoyo_task_free_security,
+	.bprm_alloc_security   = tomoyo_bprm_alloc_security,
+	.bprm_check_security   = tomoyo_bprm_check_security,
+	.bprm_post_apply_creds = tomoyo_bprm_post_apply_creds,
+	.bprm_free_security    = tomoyo_bprm_free_security,
+	.inode_permission      = tomoyo_inode_permission,
+	.inode_setattr         = tomoyo_inode_setattr,
+	.inode_create          = tomoyo_inode_create,
+	.inode_unlink          = tomoyo_inode_unlink,
+	.inode_mkdir           = tomoyo_inode_mkdir,
+	.inode_rmdir           = tomoyo_inode_rmdir,
+	.inode_symlink         = tomoyo_inode_symlink,
+	.inode_mknod           = tomoyo_inode_mknod,
+	.inode_link            = tomoyo_inode_link,
+	.inode_rename          = tomoyo_inode_rename,
+	.file_fcntl            = tomoyo_file_fcntl,
+};
+
+static int __init tomoyo_init(void)
+{
+	/* register ourselves with the security framework */
+	if (register_security(&tomoyo_security_ops)) {
+		printk(KERN_INFO "Failure registering TOMOYO Linux with the kernel\n");
+		return -EINVAL;
+	}
+	
+	printk ("TOMOYO Linux initialized\n");
+	{
+		extern void tomoyo_proc_init(void);
+		tomoyo_proc_init();
+	}
+	tomoyo_cachep = kmem_cache_create("tomoyo_security",
+	                                  sizeof(struct tomoyo_security),
+	                                  0, SLAB_PANIC, NULL, NULL);
+	init_task.security = kmem_cache_alloc(tomoyo_cachep, GFP_KERNEL);
+	((struct tomoyo_security *) init_task.security)->domain_info = &KERNEL_DOMAIN;
+	((struct tomoyo_security *) init_task.security)->flags = 0;
+	return 0;
+}
+
+security_initcall(tomoyo_init);
---------------


  parent reply	other threads:[~2007-06-14  9:45 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-06-14  7:30 [TOMOYO 0/9] TOMOYO Linux security module Kentaro Takeda
2007-06-14  7:32 ` [TOMOYO 1/9] Allow use of namespace_sem from LSM module Kentaro Takeda
2007-06-14 16:13   ` Pavel Machek
2007-06-15  2:53     ` Kentaro Takeda
2007-06-14  7:33 ` [TOMOYO 2/9] Kconfig and Makefile for TOMOYO Linux Kentaro Takeda
2007-06-14  7:34 ` [TOMOYO 3/9] Data structures and prototypes definition Kentaro Takeda
2007-06-14  7:34 ` Kentaro Takeda [this message]
2007-06-14  7:36 ` [TOMOYO 5/9] Memory and pathname management functions Kentaro Takeda
2007-06-14 17:34   ` Christoph Hellwig
2007-06-15  1:19     ` Toshiharu Harada
2007-06-14  7:37 ` [TOMOYO 6/9] Utility functions and /proc interface for policy manipulation Kentaro Takeda
2007-06-14  7:38 ` [TOMOYO 7/9] Auditing interface Kentaro Takeda
2007-06-14  7:38 ` [TOMOYO 8/9] File access control functions Kentaro Takeda
2007-06-14  7:39 ` [TOMOYO 9/9] Domain transition handler functions Kentaro Takeda
2007-06-14 16:15 ` [TOMOYO 0/9] TOMOYO Linux security module Pavel Machek
2007-06-15  1:27   ` 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=4670EF9A.4080506@nttdata.co.jp \
    --to=takedakn@nttdata.co.jp \
    --cc=linux-kernel@vger.kernel.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox