lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20080501055545.645648000@nttdata.co.jp>
Date:	Thu, 01 May 2008 14:54:07 +0900
From:	Toshiharu Harada <haradats@...data.co.jp>
To:	akpm@...ux-foundation.org, chrisw@...s-sol.org,
	viro@...IV.linux.org.uk
Cc:	linux-security-module@...r.kernel.org,
	linux-fsdevel@...r.kernel.org, linux-kernel@...r.kernel.org,
	Kentaro Takeda <takedakn@...data.co.jp>,
	Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>,
	Toshiharu Harada <haradats@...data.co.jp>
Subject: [TOMOYO #8 (2.6.25-mm1) 2/7] LSM adapter functions.

Signed-off-by: Kentaro Takeda <takedakn@...data.co.jp>
Signed-off-by: Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>
Signed-off-by: Toshiharu Harada <haradats@...data.co.jp>
---
 security/tomoyo/tomoyo.c |  279 +++++++++++++++++++++++++++++++++++++++++++++++
 security/tomoyo/tomoyo.h |  102 +++++++++++++++++
 2 files changed, 381 insertions(+)

--- /dev/null
+++ mm/security/tomoyo/tomoyo.h
@@ -0,0 +1,102 @@
+/*
+ * 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/04/30
+ *
+ */
+
+#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);
+
+#define TMY_CHECK_READ_FOR_OPEN_EXEC 1
+
+/* 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
+
+struct tmy_security {
+	struct domain_info *domain;
+	struct domain_info *prev_domain;
+	u32 flags;
+};
+
+#define TMY_SECURITY ((struct tmy_security *) current->security)
+
+#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;
+
+#endif
--- /dev/null
+++ mm/security/tomoyo/tomoyo.c
@@ -0,0 +1,279 @@
+/*
+ * security/tomoyo/tomoyo.c
+ *
+ * LSM hooks for TOMOYO Linux.
+ */
+
+#include <linux/security.h>
+#include "common.h"
+#include "tomoyo.h"
+#include "realpath.h"
+
+static struct kmem_cache *tmy_cachep;
+
+static int tmy_task_alloc_security(struct task_struct *p)
+{
+	struct tmy_security *ptr = kmem_cache_alloc(tmy_cachep, GFP_KERNEL);
+
+	if (!ptr)
+		return -ENOMEM;
+	memcpy(ptr, TMY_SECURITY, sizeof(*ptr));
+	p->security = ptr;
+	return 0;
+}
+
+static void tmy_task_free_security(struct task_struct *p)
+{
+	kmem_cache_free(tmy_cachep, p->security);
+}
+
+static int tmy_bprm_alloc_security(struct linux_binprm *bprm)
+{
+	TMY_SECURITY->prev_domain = TMY_SECURITY->domain;
+	return 0;
+}
+
+static int tmy_bprm_check_security(struct linux_binprm *bprm)
+{
+	struct domain_info *next_domain = NULL;
+	int retval = 0;
+
+	tmy_load_policy(bprm->filename);
+
+	/*
+	 * TMY_CHECK_READ_FOR_OPEN_EXEC bit indicates whether this function is
+	 * called by do_execve() or not.
+	 * If called by do_execve(), I do domain transition.
+	 */
+	if ((TMY_SECURITY->flags & TMY_CHECK_READ_FOR_OPEN_EXEC))
+		goto out;
+	retval = tmy_find_next_domain(bprm, &next_domain);
+	if (retval)
+		goto out;
+	TMY_SECURITY->domain = next_domain;
+	TMY_SECURITY->flags |= TMY_CHECK_READ_FOR_OPEN_EXEC;
+out:
+	return retval;
+}
+
+static void tmy_bprm_post_apply_creds(struct linux_binprm *bprm)
+{
+	TMY_SECURITY->prev_domain = TMY_SECURITY->domain;
+}
+
+static void tmy_bprm_free_security(struct linux_binprm *bprm)
+{
+	TMY_SECURITY->domain = TMY_SECURITY->prev_domain;
+	TMY_SECURITY->flags &= ~TMY_CHECK_READ_FOR_OPEN_EXEC;
+}
+
+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;
+}
+
+static int tmy_inode_permission(struct inode *inode, int mask,
+				struct nameidata *nd)
+{
+	if (S_ISDIR(inode->i_mode)) /* ignore because inode is directory */
+		return 0;
+	if (!nd || !nd->path.dentry || !nd->path.mnt)
+		return 0;
+
+	/*
+	 * If called by other than do_execve(), I check for read permission of
+	 * interpreter.
+	 * Unlike DAC, I don't check for read permission of pathname passed to
+	 * do_execve().
+	 * TOMOYO Linux checks for program's execute permission and
+	 * interpreter's read permission.
+	 */
+	if ((mask != MAY_EXEC) ||
+	    !(TMY_SECURITY->flags & TMY_CHECK_READ_FOR_OPEN_EXEC))
+		return 0;
+
+	/* called from open_exec() other than do_execve() */;
+	return tmy_check_open_permission(nd->path.dentry, nd->path.mnt,
+					 O_RDONLY + 1);
+}
+
+static int tmy_path_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
+{
+	return tmy_check_open_permission(dentry, mnt, flags);
+}
+
+static int tmy_path_truncate(struct path *path, loff_t length,
+			     unsigned int time_attrs, struct file *filp)
+{
+	return tmy_check_1path_perm(TMY_TYPE_TRUNCATE_ACL, path->dentry,
+				    path->mnt);
+}
+
+static int tmy_path_create(struct inode *dir, struct dentry *dentry, int mode,
+			   struct nameidata *nd)
+{
+	if (!nd || !nd->path.mnt)
+		return 0;
+	return tmy_check_1path_perm(TMY_TYPE_CREATE_ACL, dentry, nd->path.mnt);
+}
+
+static int tmy_path_unlink(struct path *dir, struct dentry *dentry)
+{
+	const int err = pre_vfs_unlink(dir->dentry->d_inode, dentry);
+	if (err)
+		return err;
+	return tmy_check_1path_perm(TMY_TYPE_UNLINK_ACL, dentry, dir->mnt);
+}
+
+static int tmy_path_mkdir(struct path *dir, struct dentry *dentry, int mode)
+{
+	const int err = pre_vfs_mkdir(dir->dentry->d_inode, dentry);
+	if (err)
+		return err;
+	return tmy_check_1path_perm(TMY_TYPE_MKDIR_ACL, dentry, dir->mnt);
+}
+
+static int tmy_path_rmdir(struct path *dir, struct dentry *dentry)
+{
+	const int err = pre_vfs_rmdir(dir->dentry->d_inode, dentry);
+	if (err)
+		return err;
+	return tmy_check_1path_perm(TMY_TYPE_RMDIR_ACL, dentry, dir->mnt);
+}
+
+static int tmy_path_symlink(struct path *dir, struct dentry *dentry,
+			    const char *old_name)
+{
+	const int err = pre_vfs_symlink(dir->dentry->d_inode, dentry);
+	if (err)
+		return err;
+	return tmy_check_1path_perm(TMY_TYPE_SYMLINK_ACL, dentry, dir->mnt);
+}
+
+static int tmy_path_mknod(struct path *dir, struct dentry *dentry, int mode,
+			  unsigned int dev)
+{
+	struct vfsmount *mnt = dir->mnt;
+	int err = 0;
+	switch (mode & S_IFMT) {
+	case S_IFCHR:
+	case S_IFBLK:
+	case S_IFIFO:
+	case S_IFSOCK:
+		break;
+	default:
+		return 0;
+	}
+	err = pre_vfs_mknod(dir->dentry->d_inode, dentry, mode);
+	if (err)
+		return err;
+	if (S_ISCHR(mode))
+		return tmy_check_1path_perm(TMY_TYPE_MKCHAR_ACL, dentry, mnt);
+	if (S_ISBLK(mode))
+		return tmy_check_1path_perm(TMY_TYPE_MKBLOCK_ACL, dentry, mnt);
+	if (S_ISFIFO(mode))
+		return tmy_check_1path_perm(TMY_TYPE_MKFIFO_ACL, dentry, mnt);
+	if (S_ISSOCK(mode))
+		return tmy_check_1path_perm(TMY_TYPE_MKSOCK_ACL, dentry, mnt);
+	return 0;
+}
+
+static int tmy_path_link(struct path *old_path, struct path *new_dir,
+			 struct dentry *new_dentry)
+{
+	const int err = pre_vfs_link(old_path->dentry, new_dir->dentry->d_inode,
+				     new_dentry);
+	if (err)
+		return err;
+	return tmy_check_2path_perm(TMY_TYPE_LINK_ACL,
+				    old_path->dentry, old_path->mnt,
+				    new_dentry, new_dir->mnt);
+}
+
+static int tmy_path_rename(struct path *old_dir, struct dentry *old_dentry,
+			   struct path *new_dir, struct dentry *new_dentry)
+{
+	const int err = pre_vfs_rename(old_dir->dentry->d_inode, old_dentry,
+				       new_dir->dentry->d_inode, new_dentry);
+	if (err)
+		return err;
+	return tmy_check_2path_perm(TMY_TYPE_RENAME_ACL,
+				    old_dentry, old_dir->mnt,
+				    new_dentry, new_dir->mnt);
+}
+
+static int tmy_path_uselib(struct nameidata *nd)
+{
+	return tmy_check_open_permission(nd->path.dentry, nd->path.mnt,
+					 O_RDONLY + 1);
+}
+
+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 struct security_operations tomoyo_security_ops = {
+	.name                      = "tomoyo",
+
+	.task_alloc_security       = tmy_task_alloc_security,
+	.task_free_security        = tmy_task_free_security,
+	.bprm_alloc_security       = tmy_bprm_alloc_security,
+	.bprm_check_security       = tmy_bprm_check_security,
+	.bprm_post_apply_creds     = tmy_bprm_post_apply_creds,
+	.bprm_free_security        = tmy_bprm_free_security,
+	.sysctl                    = tmy_sysctl,
+	.inode_permission          = tmy_inode_permission,
+	.path_truncate             = tmy_path_truncate,
+	.path_create               = tmy_path_create,
+	.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,
+	.path_open                 = tmy_path_open,
+	.path_uselib               = tmy_path_uselib,
+	.file_fcntl                = tmy_file_fcntl,
+};
+
+static int __init tmy_init(void)
+{
+	struct tmy_security *tmy_security;
+	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");
+	tmy_cachep = kmem_cache_create("tomoyo_security",
+				       sizeof(struct tmy_security),
+				       0, SLAB_PANIC, NULL);
+	tmy_security = kmem_cache_alloc(tmy_cachep, GFP_KERNEL);
+	BUG_ON(!tmy_security);
+	memset(tmy_security, 0, sizeof(*tmy_security));
+	tmy_security->domain = &KERNEL_DOMAIN;
+	init_task.security = tmy_security;
+	return 0;
+}
+
+security_initcall(tmy_init);

--

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ