All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kentaro Takeda <takedakn@nttdata.co.jp>
To: linux-security-module@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, haradats@nttdata.co.jp,
	Kentaro Takeda <takedakn@nttdata.co.jp>,
	Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Subject: [TOMOYO #9 (2.6.27-rc7-mm1) 1/6] LSM adapter functions.
Date: Wed, 24 Sep 2008 18:03:18 +0900	[thread overview]
Message-ID: <20080924090338.407746083@nttdata.co.jp> (raw)
In-Reply-To: 20080924090317.359685535@nttdata.co.jp

Signed-off-by: Kentaro Takeda <takedakn@nttdata.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@nttdata.co.jp>
---
 security/tomoyo/tomoyo.c |  341 +++++++++++++++++++++++++++++++++++++++++++++++
 security/tomoyo/tomoyo.h |   97 +++++++++++++
 2 files changed, 438 insertions(+)

--- /dev/null
+++ linux-2.6.27-rc7-mm1/security/tomoyo/tomoyo.c
@@ -0,0 +1,341 @@
+/*
+ * security/tomoyo/tomoyo.c
+ *
+ * LSM hooks for TOMOYO Linux.
+ *
+ * Copyright (C) 2005-2008  NTT DATA CORPORATION
+ *
+ * Version: 2.2.0-pre   2008/09/24
+ *
+ */
+
+#include <linux/security.h>
+#include "common.h"
+#include "tomoyo.h"
+#include "realpath.h"
+#include <linux/audit.h>
+#include <linux/device_cgroup.h>
+
+static int tmy_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp)
+{
+	new->security = old->security;
+	return 0;
+}
+
+static int tmy_bprm_check_security(struct linux_binprm *bprm)
+{
+	struct domain_info *next_domain = NULL;
+	int retval;
+	/*
+	 * If called by do_execve() (i.e. bprm->sh_bang == 0),
+	 * I do execute permission check.
+	 */
+	if (bprm->sh_bang)
+		return 0;
+	tmy_load_policy(bprm->filename);
+	retval = tmy_find_next_domain(bprm, &next_domain);
+	if (!retval)
+		bprm->cred->security = next_domain;
+	return retval;
+}
+
+static int tmy_sysctl(struct ctl_table *table, int op)
+{
+	int error;
+	char *name;
+
+	if ((op & 6) == 0)
+		return 0;
+
+	name = sysctlpath_from_table(table);
+	if (!name)
+		return -ENOMEM;
+
+	error = tmy_check_file_perm(name, op & 6, "sysctl");
+	tmy_free(name);
+
+	return error;
+}
+
+/* Copied from fs/namei.c */
+static inline int may_create(struct inode *dir, struct dentry *child)
+{
+	if (child->d_inode)
+		return -EEXIST;
+	if (IS_DEADDIR(dir))
+		return -ENOENT;
+	return inode_permission(dir, MAY_WRITE | MAY_EXEC);
+}
+
+/* Copied from fs/namei.c */
+static inline int check_sticky(struct inode *dir, struct inode *inode)
+{
+	uid_t fsuid = current_fsuid();
+
+	if (!(dir->i_mode & S_ISVTX))
+		return 0;
+	if (inode->i_uid == fsuid)
+		return 0;
+	if (dir->i_uid == fsuid)
+		return 0;
+	return !capable(CAP_FOWNER);
+}
+
+/* Copied from fs/namei.c */
+static int may_delete(struct inode *dir, struct dentry *victim, int isdir)
+{
+	int error;
+
+	if (!victim->d_inode)
+		return -ENOENT;
+
+	BUG_ON(victim->d_parent->d_inode != dir);
+	audit_inode_child(victim->d_name.name, victim, dir);
+
+	error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
+	if (error)
+		return error;
+	if (IS_APPEND(dir))
+		return -EPERM;
+	if (check_sticky(dir, victim->d_inode) || IS_APPEND(victim->d_inode) ||
+	    IS_IMMUTABLE(victim->d_inode))
+		return -EPERM;
+	if (isdir) {
+		if (!S_ISDIR(victim->d_inode->i_mode))
+			return -ENOTDIR;
+		if (IS_ROOT(victim))
+			return -EBUSY;
+	} else if (S_ISDIR(victim->d_inode->i_mode))
+		return -EISDIR;
+	if (IS_DEADDIR(dir))
+		return -ENOENT;
+	if (victim->d_flags & DCACHE_NFSFS_RENAMED)
+		return -EBUSY;
+	return 0;
+}
+
+static int tmy_path_truncate(struct path *path, loff_t length,
+			     unsigned int time_attrs, struct file *filp)
+{
+	struct dentry *dentry = path->dentry;
+	int error;
+	mutex_lock(&dentry->d_inode->i_mutex);
+	error = tmy_check_1path_perm(TMY_TYPE_TRUNCATE_ACL,
+				     path->dentry, path->mnt);
+	mutex_unlock(&dentry->d_inode->i_mutex);
+	return error;
+}
+
+static int tmy_path_unlink(struct path *parent, struct dentry *dentry)
+{
+	struct inode *dir = parent->dentry->d_inode;
+	int error = may_delete(dir, dentry, 0);
+	if (error)
+		return error;
+	if (!dir->i_op || !dir->i_op->unlink)
+		return -EPERM;
+	mutex_lock(&dentry->d_inode->i_mutex);
+	error = tmy_check_1path_perm(TMY_TYPE_UNLINK_ACL, dentry, parent->mnt);
+	mutex_unlock(&dentry->d_inode->i_mutex);
+	return error;
+}
+
+static int tmy_path_mkdir(struct path *parent, struct dentry *dentry, int mode)
+{
+	struct inode *dir = parent->dentry->d_inode;
+	int error = may_create(dir, dentry);
+	if (error)
+		return error;
+	if (!dir->i_op || !dir->i_op->mkdir)
+		return -EPERM;
+	return tmy_check_1path_perm(TMY_TYPE_MKDIR_ACL, dentry, parent->mnt);
+}
+
+static int tmy_path_rmdir(struct path *parent, struct dentry *dentry)
+{
+	struct inode *dir = parent->dentry->d_inode;
+	int error = may_delete(dir, dentry, 1);
+	if (error)
+		return error;
+	if (!dir->i_op || !dir->i_op->rmdir)
+		return -EPERM;
+	mutex_lock(&dentry->d_inode->i_mutex);
+	error = tmy_check_1path_perm(TMY_TYPE_RMDIR_ACL, dentry, parent->mnt);
+	mutex_unlock(&dentry->d_inode->i_mutex);
+	return error;
+}
+
+static int tmy_path_symlink(struct path *parent, struct dentry *dentry,
+			    const char *old_name)
+{
+	struct inode *dir = parent->dentry->d_inode;
+	int error = may_create(dir, dentry);
+	if (error)
+		return error;
+	if (!dir->i_op || !dir->i_op->symlink)
+		return -EPERM;
+	return tmy_check_1path_perm(TMY_TYPE_SYMLINK_ACL, dentry, parent->mnt);
+}
+
+static int tmy_path_mknod(struct path *parent, struct dentry *dentry, int mode,
+			  unsigned int dev)
+{
+	struct vfsmount *mnt = parent->mnt;
+	struct inode *dir = parent->dentry->d_inode;
+	int error = 0;
+
+	switch (mode & S_IFMT) {
+	case S_IFREG:
+	case 0:
+		error = may_create(dir, dentry);
+		if (error)
+			return error;
+		if (!dir->i_op || !dir->i_op->create)
+			return -EACCES; /* shouldn't it be ENOSYS? */
+		break;
+	case S_IFCHR:
+	case S_IFBLK:
+	case S_IFIFO:
+	case S_IFSOCK:
+		error = may_create(dir, dentry);
+		if (error)
+			return error;
+		if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD))
+			return -EPERM;
+		if (!dir->i_op || !dir->i_op->mknod)
+			return -EPERM;
+		error = devcgroup_inode_mknod(mode, dev);
+		if (error)
+			return error;
+		break;
+	default:
+		return 0;
+	}
+	switch (mode & S_IFMT) {
+	case S_IFREG:
+	case 0:
+		error = tmy_check_1path_perm(TMY_TYPE_CREATE_ACL, dentry, mnt);
+		break;
+	case S_IFCHR:
+		error = tmy_check_1path_perm(TMY_TYPE_MKCHAR_ACL, dentry, mnt);
+		break;
+	case S_IFBLK:
+		error = tmy_check_1path_perm(TMY_TYPE_MKBLOCK_ACL, dentry, mnt);
+		break;
+	case S_IFIFO:
+		error = tmy_check_1path_perm(TMY_TYPE_MKFIFO_ACL, dentry, mnt);
+		break;
+	case S_IFSOCK:
+		error = tmy_check_1path_perm(TMY_TYPE_MKSOCK_ACL, dentry, mnt);
+		break;
+	}
+	return error;
+}
+
+static int tmy_path_link(struct dentry *old_dentry, struct path *new_dir,
+			 struct dentry *new_dentry)
+{
+	struct inode *dir = new_dir->dentry->d_inode;
+
+	struct inode *inode = old_dentry->d_inode;
+	int error;
+	if (!inode)
+		return -ENOENT;
+	error = may_create(dir, new_dentry);
+	if (error)
+		return error;
+	if (dir->i_sb != inode->i_sb)
+		return -EXDEV;
+	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
+		return -EPERM;
+	if (!dir->i_op || !dir->i_op->link)
+		return -EPERM;
+	if (S_ISDIR(inode->i_mode))
+		return -EPERM;
+
+	return tmy_check_2path_perm(TMY_TYPE_LINK_ACL,
+				    old_dentry, new_dir->mnt,
+				    new_dentry, new_dir->mnt);
+}
+
+static int tmy_path_rename(struct path *old_parent, struct dentry *old_dentry,
+			   struct path *new_parent, struct dentry *new_dentry)
+{
+	struct inode *old_dir = old_parent->dentry->d_inode;
+	struct inode *new_dir = new_parent->dentry->d_inode;
+
+	int error;
+	int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
+	if (old_dentry->d_inode == new_dentry->d_inode)
+		return 0;
+	error = may_delete(old_dir, old_dentry, is_dir);
+	if (error)
+		return error;
+	if (!new_dentry->d_inode)
+		error = may_create(new_dir, new_dentry);
+	else
+		error = may_delete(new_dir, new_dentry, is_dir);
+	if (error)
+		return error;
+	if (!old_dir->i_op || !old_dir->i_op->rename)
+		return -EPERM;
+
+	if (is_dir && new_dir != old_dir) {
+		error = inode_permission(old_dentry->d_inode, MAY_WRITE);
+		if (error)
+			return error;
+	}
+
+	return tmy_check_2path_perm(TMY_TYPE_RENAME_ACL,
+				    old_dentry, old_parent->mnt,
+				    new_dentry, new_parent->mnt);
+}
+
+static int tmy_file_fcntl(struct file *file, unsigned int cmd,
+			  unsigned long arg)
+{
+	if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))
+		return tmy_check_rewrite_permission(file);
+	return 0;
+}
+
+static int tmy_dentry_open(struct file *f, const struct cred *cred)
+{
+	int flags = f->f_flags;
+	if ((flags + 1) & O_ACCMODE)
+		flags++;
+	flags |= f->f_flags & (O_APPEND | O_TRUNC);
+	return tmy_check_open_permission(f->f_dentry, f->f_vfsmnt, flags);
+}
+
+static struct security_operations tomoyo_security_ops = {
+	.name                      = "tomoyo",
+	.cred_prepare              = tmy_cred_prepare,
+	.bprm_check_security       = tmy_bprm_check_security,
+	.sysctl                    = tmy_sysctl,
+	.file_fcntl                = tmy_file_fcntl,
+	.dentry_open               = tmy_dentry_open,
+	.path_truncate             = tmy_path_truncate,
+	.path_unlink               = tmy_path_unlink,
+	.path_mkdir                = tmy_path_mkdir,
+	.path_rmdir                = tmy_path_rmdir,
+	.path_symlink              = tmy_path_symlink,
+	.path_mknod                = tmy_path_mknod,
+	.path_link                 = tmy_path_link,
+	.path_rename               = tmy_path_rename,
+};
+
+static int __init tmy_init(void)
+{
+	struct cred *cred = (struct cred *) current->cred;
+	if (!security_module_enable(&tomoyo_security_ops))
+		return 0;
+	/* register ourselves with the security framework */
+	if (register_security(&tomoyo_security_ops))
+		panic("Failure registering TOMOYO Linux");
+	printk(KERN_INFO "TOMOYO Linux initialized\n");
+	cred->security = &KERNEL_DOMAIN;
+	return 0;
+}
+
+security_initcall(tmy_init);
--- /dev/null
+++ linux-2.6.27-rc7-mm1/security/tomoyo/tomoyo.h
@@ -0,0 +1,97 @@
+/*
+ * security/tomoyo/tomoyo.h
+ *
+ * Implementation of the Domain-Based Mandatory Access Control.
+ *
+ * Copyright (C) 2005-2008  NTT DATA CORPORATION
+ *
+ * Version: 2.2.0-pre   2008/09/24
+ *
+ */
+
+#ifndef _LINUX_TOMOYO_H
+#define _LINUX_TOMOYO_H
+
+struct path_info;
+struct dentry;
+struct vfsmount;
+struct inode;
+struct linux_binprm;
+struct pt_regs;
+struct tmy_page_buffer;
+
+char *sysctlpath_from_table(struct ctl_table *table);
+int tmy_check_file_perm(const char *filename, const u8 perm,
+			const char *operation);
+int tmy_check_exec_perm(const struct path_info *filename,
+			struct tmy_page_buffer *buf);
+int tmy_check_open_permission(struct dentry *dentry, struct vfsmount *mnt,
+			      const int flag);
+int tmy_check_1path_perm(const u8 operation,
+			 struct dentry *dentry,
+			 struct vfsmount *mnt);
+int tmy_check_2path_perm(const u8 operation,
+			 struct dentry *dentry1,
+			 struct vfsmount *mnt1,
+			 struct dentry *dentry2,
+			 struct vfsmount *mnt2);
+int tmy_check_rewrite_permission(struct file *filp);
+int tmy_find_next_domain(struct linux_binprm *bprm,
+			 struct domain_info **next_domain);
+
+/* Index numbers for Access Controls. */
+
+#define TYPE_SINGLE_PATH_ACL                 0
+#define TYPE_DOUBLE_PATH_ACL                 1
+
+/* Index numbers for File Controls. */
+
+/*
+ * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set
+ * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and
+ * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set.
+ * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or
+ * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are
+ * automatically cleared if TYPE_READ_WRITE_ACL is cleared.
+ */
+
+#define TMY_TYPE_READ_WRITE_ACL    0
+#define TMY_TYPE_EXECUTE_ACL       1
+#define TMY_TYPE_READ_ACL          2
+#define TMY_TYPE_WRITE_ACL         3
+#define TMY_TYPE_CREATE_ACL        4
+#define TMY_TYPE_UNLINK_ACL        5
+#define TMY_TYPE_MKDIR_ACL         6
+#define TMY_TYPE_RMDIR_ACL         7
+#define TMY_TYPE_MKFIFO_ACL        8
+#define TMY_TYPE_MKSOCK_ACL        9
+#define TMY_TYPE_MKBLOCK_ACL      10
+#define TMY_TYPE_MKCHAR_ACL       11
+#define TMY_TYPE_TRUNCATE_ACL     12
+#define TMY_TYPE_SYMLINK_ACL      13
+#define TMY_TYPE_REWRITE_ACL      14
+#define MAX_SINGLE_PATH_OPERATION 15
+
+#define TMY_TYPE_LINK_ACL         0
+#define TMY_TYPE_RENAME_ACL       1
+#define MAX_DOUBLE_PATH_OPERATION 2
+
+#define TMY_DOMAINPOLICY          0
+#define TMY_EXCEPTIONPOLICY       1
+#define TMY_DOMAIN_STATUS         2
+#define TMY_PROCESS_STATUS        3
+#define TMY_MEMINFO               4
+#define TMY_SELFDOMAIN            5
+#define TMY_VERSION               6
+#define TMY_PROFILE               7
+#define TMY_MANAGER               8
+#define TMY_UPDATESCOUNTER        9
+
+extern struct domain_info KERNEL_DOMAIN;
+
+static inline struct domain_info *tmy_domain(struct task_struct *task)
+{
+	return (struct domain_info *) task->cred->security;
+}
+
+#endif

--


  reply	other threads:[~2008-09-24  9:05 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-09-24  9:03 [TOMOYO #9 (2.6.27-rc7-mm1) 0/6] TOMOYO Linux Kentaro Takeda
2008-09-24  9:03 ` Kentaro Takeda [this message]
2008-09-25 16:59   ` [TOMOYO #9 (2.6.27-rc7-mm1) 1/6] LSM adapter functions Serge E. Hallyn
2008-09-26  5:38     ` Kentaro Takeda
2008-09-26 13:04       ` Serge E. Hallyn
2008-09-29  4:04         ` Kentaro Takeda
2008-09-30 15:45           ` Serge E. Hallyn
2008-09-30 16:14             ` Stephen Smalley
2008-09-30 16:23               ` Serge E. Hallyn
2008-10-01  8:19                 ` Kentaro Takeda
2008-10-01  2:33             ` Casey Schaufler
2008-10-01  5:05               ` Valdis.Kletnieks
2008-10-01  8:23                 ` Kentaro Takeda
2008-10-01 21:15                   ` Serge E. Hallyn
2008-10-02  5:04                     ` Kentaro Takeda
2008-10-02 13:39                       ` Serge E. Hallyn
2008-10-03  6:37                         ` Kentaro Takeda
2008-10-03 13:09                           ` Serge E. Hallyn
2008-10-06  2:19                             ` Kentaro Takeda
2008-10-06 16:54                               ` Serge E. Hallyn
2008-10-07  6:28                                 ` Kentaro Takeda
2008-09-24  9:03 ` [TOMOYO #9 (2.6.27-rc7-mm1) 2/6] Memory and pathname management functions Kentaro Takeda
2008-09-24  9:03 ` [TOMOYO #9 (2.6.27-rc7-mm1) 3/6] Common functions for TOMOYO Linux Kentaro Takeda
2008-09-24  9:03 ` [TOMOYO #9 (2.6.27-rc7-mm1) 4/6] Domain transition handler Kentaro Takeda
2008-09-24  9:03 ` [TOMOYO #9 (2.6.27-rc7-mm1) 5/6] File operation restriction part Kentaro Takeda
2008-09-24  9:03 ` [TOMOYO #9 (2.6.27-rc7-mm1) 6/6] Kconfig and Makefile 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=20080924090338.407746083@nttdata.co.jp \
    --to=takedakn@nttdata.co.jp \
    --cc=haradats@nttdata.co.jp \
    --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.