From: Kentaro Takeda <takedakn@nttdata.co.jp>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: Toshiharu Harada <haradats@nttdata.co.jp>,
linux-security-module@vger.kernel.org,
linux-kernel@vger.kernel.org,
Kentaro Takeda <takedakn@nttdata.co.jp>,
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Subject: [TOMOYO #12 (2.6.28-rc2-mm1) 09/11] LSM adapter functions.
Date: Tue, 04 Nov 2008 15:08:56 +0900 [thread overview]
Message-ID: <20081104060956.600598373@nttdata.co.jp> (raw)
In-Reply-To: 20081104060847.086543472@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 | 376 +++++++++++++++++++++++++++++++++++++++++++++++
security/tomoyo/tomoyo.h | 105 +++++++++++++
2 files changed, 481 insertions(+)
--- /dev/null
+++ linux-2.6.28-rc2-mm1/security/tomoyo/tomoyo.c
@@ -0,0 +1,376 @@
+/*
+ * security/tomoyo/tomoyo.c
+ *
+ * LSM hooks for TOMOYO Linux.
+ *
+ * Copyright (C) 2005-2008 NTT DATA CORPORATION
+ *
+ * Version: 2.2.0-pre 2008/10/10
+ *
+ */
+
+#include <linux/security.h>
+#include "common.h"
+#include "tomoyo.h"
+#include "realpath.h"
+
+static int tmy_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp)
+{
+ /*
+ * Since "struct domain_info *" is a sharable pointer, we don't need
+ * to duplicate.
+ */
+ new->security = old->security;
+ return 0;
+}
+
+static int tmy_bprm_set_creds(struct linux_binprm *bprm)
+{
+ /*
+ * Do only if this function is called for the first time of an execve
+ * operation.
+ */
+ if (bprm->cred_prepared)
+ return 0;
+ /*
+ * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested
+ * for the first time.
+ */
+ if (!sbin_init_started)
+ tmy_load_policy(bprm->filename);
+ /*
+ * Tell tmy_bprm_check_security() is called for the first time of an
+ * execve operation.
+ */
+ bprm->cred->security = NULL;
+ return 0;
+}
+
+static int tmy_bprm_check_security(struct linux_binprm *bprm)
+{
+ struct domain_info *domain = bprm->cred->security;
+
+ /*
+ * Execute permission is checked against pathname passed to do_execve()
+ * using current domain.
+ */
+ if (!domain) {
+ struct domain_info *next_domain = NULL;
+ int retval = tmy_find_next_domain(bprm, &next_domain);
+
+ if (!retval)
+ bprm->cred->security = next_domain;
+ return retval;
+ }
+ /*
+ * Read permission is checked against interpreters using next domain.
+ * '1' is the result of open_to_namei_flags(O_RDONLY).
+ */
+ return tmy_check_open_permission(domain, &bprm->file->f_path, 1);
+}
+
+static int tmy_sysctl(struct ctl_table *table, int op)
+{
+ int error;
+ char *name;
+
+ op &= MAY_READ | MAY_WRITE;
+ if (!op)
+ return 0;
+ name = sysctlpath_from_table(table);
+ if (!name)
+ return -ENOMEM;
+ error = tmy_check_file_perm(tmy_domain(), name, op);
+ tmy_free(name);
+ return error;
+}
+
+/**
+ * tmy_update_result - Update error code.
+ *
+ * @error: Return code from security_path_*().
+ *
+ * To be able to return DAC's error (if any) to the caller instead of
+ * MAC's error, we don't return MAC's error at security_path_*().
+ *
+ * We remember MAC's error only if security_path_*() returned an error.
+ *
+ * Returns 0 on success, -ENOMEM otherwise if @error != 0.
+ * Returns previously saved error code and clears it if @error == 0.
+ */
+static int tmy_update_result(int error)
+{
+ /* Structure for holding the result of security_path_*(). */
+ struct check_result_entry {
+ struct list_head list;
+ struct task_struct *task; /* = current */
+ int error; /* != 0 */
+ };
+ static LIST_HEAD(list);
+ static DEFINE_SPINLOCK(lock);
+ struct task_struct *task = current;
+ struct check_result_entry *entry;
+ if (!error) {
+ if (!list_empty(&list)) {
+ struct check_result_entry *p;
+ entry = NULL;
+ /***** CRITICAL SECTION START *****/
+ spin_lock(&lock);
+ list_for_each_entry(p, &list, list) {
+ if (p->task != task)
+ continue;
+ list_del(&p->list);
+ entry = p;
+ break;
+ }
+ spin_unlock(&lock);
+ /***** CRITICAL SECTION END *****/
+ if (entry) {
+ error = entry->error;
+ kfree(entry);
+ }
+ }
+ return error;
+ }
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+ entry->task = task;
+ entry->error = error;
+ /***** CRITICAL SECTION START *****/
+ spin_lock(&lock);
+ list_add(&entry->list, &list);
+ spin_unlock(&lock);
+ /***** CRITICAL SECTION END *****/
+ return 0;
+}
+
+/**
+ * tmy_save_result - Remember error code for security_inode_*() if any.
+ *
+ * @error: Return code from security_path_*().
+ *
+ * Returns 0 on success, -ENOMEM otherwise.
+ *
+ * We don't save if @error == 0.
+ */
+static int tmy_save_result(const int error)
+{
+ return error ? tmy_update_result(error) : 0;
+}
+
+/**
+ * tmy_load_result - Fetch error code for security_inode_*().
+ *
+ * Returns error code saved by security_path_*().
+ */
+static int tmy_load_result(void)
+{
+ return tmy_update_result(0);
+}
+
+/* Clear error code in case security_inode_*() was not called. */
+static void tmy_path_clear(void)
+{
+ tmy_load_result();
+}
+
+static int tmy_path_truncate(struct path *path, loff_t length,
+ unsigned int time_attrs, struct file *filp)
+{
+ return tmy_save_result(tmy_check_1path_perm(tmy_domain(),
+ TMY_TYPE_TRUNCATE_ACL,
+ path));
+}
+
+static int tmy_path_unlink(struct path *parent, struct dentry *dentry)
+{
+ struct path path = { parent->mnt, dentry };
+ return tmy_save_result(tmy_check_1path_perm(tmy_domain(),
+ TMY_TYPE_UNLINK_ACL,
+ &path));
+}
+
+static int tmy_path_mkdir(struct path *parent, struct dentry *dentry, int mode)
+{
+ struct path path = { parent->mnt, dentry };
+ return tmy_save_result(tmy_check_1path_perm(tmy_domain(),
+ TMY_TYPE_MKDIR_ACL,
+ &path));
+}
+
+static int tmy_path_rmdir(struct path *parent, struct dentry *dentry)
+{
+ struct path path = { parent->mnt, dentry };
+ return tmy_save_result(tmy_check_1path_perm(tmy_domain(),
+ TMY_TYPE_RMDIR_ACL,
+ &path));
+}
+
+static int tmy_path_symlink(struct path *parent, struct dentry *dentry,
+ const char *old_name)
+{
+ struct path path = { parent->mnt, dentry };
+ return tmy_save_result(tmy_check_1path_perm(tmy_domain(),
+ TMY_TYPE_SYMLINK_ACL,
+ &path));
+}
+
+static int tmy_path_mknod(struct path *parent, struct dentry *dentry, int mode,
+ unsigned int dev)
+{
+ struct path path = { parent->mnt, dentry };
+ int type = TMY_TYPE_CREATE_ACL;
+
+ switch (mode & S_IFMT) {
+ case S_IFCHR:
+ type = TMY_TYPE_MKCHAR_ACL;
+ break;
+ case S_IFBLK:
+ type = TMY_TYPE_MKBLOCK_ACL;
+ break;
+ case S_IFIFO:
+ type = TMY_TYPE_MKFIFO_ACL;
+ break;
+ case S_IFSOCK:
+ type = TMY_TYPE_MKSOCK_ACL;
+ break;
+ }
+ return tmy_save_result(tmy_check_1path_perm(tmy_domain(),
+ type, &path));
+}
+
+static int tmy_path_link(struct dentry *old_dentry, struct path *new_dir,
+ struct dentry *new_dentry)
+{
+ struct path path1 = { new_dir->mnt, old_dentry };
+ struct path path2 = { new_dir->mnt, new_dentry };
+ return tmy_save_result(tmy_check_2path_perm(tmy_domain(),
+ TMY_TYPE_LINK_ACL,
+ &path1, &path2));
+}
+
+static int tmy_path_rename(struct path *old_parent, struct dentry *old_dentry,
+ struct path *new_parent, struct dentry *new_dentry)
+{
+ struct path path1 = { old_parent->mnt, old_dentry };
+ struct path path2 = { new_parent->mnt, new_dentry };
+ return tmy_save_result(tmy_check_2path_perm(tmy_domain(),
+ TMY_TYPE_RENAME_ACL,
+ &path1, &path2));
+}
+
+static int tmy_inode_link(struct dentry *old_dentry, struct inode *inode,
+ struct dentry *new_dentry)
+{
+ return tmy_load_result();
+}
+
+static int tmy_inode_unlink(struct inode *inode, struct dentry *dentry)
+{
+ return tmy_load_result();
+}
+
+static int tmy_inode_symlink(struct inode *inode, struct dentry *dentry,
+ const char *name)
+{
+ return tmy_load_result();
+}
+
+static int tmy_inode_mkdir(struct inode *inode, struct dentry *dentry,
+ int mask)
+{
+ return tmy_load_result();
+}
+
+static int tmy_inode_rmdir(struct inode *inode, struct dentry *dentry)
+{
+ return tmy_load_result();
+}
+
+static int tmy_inode_create(struct inode *dir, struct dentry *dentry, int mode)
+{
+ return tmy_load_result();
+}
+
+static int tmy_inode_mknod(struct inode *inode, struct dentry *dentry,
+ int mode, dev_t dev)
+{
+ return tmy_load_result();
+}
+
+static int tmy_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
+ struct inode *new_inode, struct dentry *new_dentry)
+{
+ return tmy_load_result();
+}
+
+static int tmy_inode_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+ return tmy_load_result();
+}
+
+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(tmy_domain(), 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);
+ /* Don't check read permission here if called from do_execve(). */
+ if (current->in_execve)
+ return 0;
+ return tmy_check_open_permission(tmy_domain(), &f->f_path, flags);
+}
+
+static struct security_operations tomoyo_security_ops = {
+ .name = "tomoyo",
+ .cred_prepare = tmy_cred_prepare,
+ .bprm_set_creds = tmy_bprm_set_creds,
+ .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,
+ .inode_create = tmy_inode_create,
+ .inode_setattr = tmy_inode_setattr,
+ .inode_unlink = tmy_inode_unlink,
+ .inode_mkdir = tmy_inode_mkdir,
+ .inode_rmdir = tmy_inode_rmdir,
+ .inode_symlink = tmy_inode_symlink,
+ .inode_mknod = tmy_inode_mknod,
+ .inode_link = tmy_inode_link,
+ .inode_rename = tmy_inode_rename,
+ .path_clear = tmy_path_clear,
+};
+
+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.28-rc2-mm1/security/tomoyo/tomoyo.h
@@ -0,0 +1,105 @@
+/*
+ * 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/10/10
+ *
+ */
+
+#ifndef _SECURITY_TOMOYO_TOMOYO_H
+#define _SECURITY_TOMOYO_TOMOYO_H
+
+struct path_info;
+struct path;
+struct inode;
+struct linux_binprm;
+struct pt_regs;
+struct tmy_page_buffer;
+
+int tmy_check_file_perm(struct domain_info *domain, const char *filename,
+ const u8 perm);
+int tmy_check_exec_perm(struct domain_info *domain,
+ const struct path_info *filename,
+ struct tmy_page_buffer *buf);
+int tmy_check_open_permission(struct domain_info *domain, struct path *path,
+ const int flag);
+int tmy_check_1path_perm(struct domain_info *domain, const u8 operation,
+ struct path *path);
+int tmy_check_2path_perm(struct domain_info *domain, const u8 operation,
+ struct path *path1, struct path *path2);
+int tmy_check_rewrite_permission(struct domain_info *domain,
+ 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(void)
+{
+ return current_cred()->security;
+}
+
+/* Caller holds tasklist_lock spinlock. */
+static inline struct domain_info *tmy_real_domain(struct task_struct *task)
+{
+ /***** CRITICAL SECTION START *****/
+ const struct cred *cred = get_task_cred(task);
+ struct domain_info *domain = cred->security;
+
+ put_cred(cred);
+ return domain;
+ /***** CRITICAL SECTION END *****/
+}
+
+#endif /* !defined(_SECURITY_TOMOYO_TOMOYO_H) */
--
next prev parent reply other threads:[~2008-11-04 6:13 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-11-04 6:08 [TOMOYO #12 (2.6.28-rc2-mm1) 00/11] TOMOYO Linux Kentaro Takeda
2008-11-04 6:08 ` [TOMOYO #12 (2.6.28-rc2-mm1) 01/11] Introduce security_path_clear() hook Kentaro Takeda
2008-11-04 6:08 ` [TOMOYO #12 (2.6.28-rc2-mm1) 02/11] Add in_execve flag into task_struct Kentaro Takeda
2008-11-05 23:12 ` Andrew Morton
2008-11-04 6:08 ` [TOMOYO #12 (2.6.28-rc2-mm1) 03/11] Singly linked list implementation Kentaro Takeda
2008-11-05 23:12 ` Andrew Morton
2008-11-04 6:08 ` [TOMOYO #12 (2.6.28-rc2-mm1) 04/11] Introduce d_realpath() Kentaro Takeda
2008-11-05 23:12 ` Andrew Morton
2008-11-17 6:52 ` Kentaro Takeda
2008-11-04 6:08 ` [TOMOYO #12 (2.6.28-rc2-mm1) 05/11] Memory and pathname management functions Kentaro Takeda
2008-11-05 23:12 ` Andrew Morton
2008-11-10 10:34 ` Kentaro Takeda
2008-11-11 5:04 ` Andrew Morton
2008-11-11 6:34 ` Kentaro Takeda
2008-11-11 6:46 ` Andrew Morton
2008-11-11 7:32 ` Kentaro Takeda
2008-11-04 6:08 ` [TOMOYO #12 (2.6.28-rc2-mm1) 06/11] Common functions for TOMOYO Linux Kentaro Takeda
2008-11-05 23:12 ` Andrew Morton
2008-11-06 21:46 ` [TOMOYO #12 (2.6.28-rc2-mm1) 06/11] Common functions for TOMOYOLinux Tetsuo Handa
2008-11-08 16:38 ` Tetsuo Handa
2008-11-10 0:41 ` Serge E. Hallyn
2008-11-10 2:24 ` Tetsuo Handa
2008-11-10 2:52 ` Serge E. Hallyn
2008-11-10 3:30 ` Tetsuo Handa
2008-11-10 14:00 ` Serge E. Hallyn
2008-11-10 10:35 ` [TOMOYO #12 (2.6.28-rc2-mm1) 06/11] Common functions for TOMOYO Linux Kentaro Takeda
2008-11-14 9:22 ` Kentaro Takeda
2008-11-04 6:08 ` [TOMOYO #12 (2.6.28-rc2-mm1) 07/11] File operation restriction part Kentaro Takeda
2008-11-04 6:08 ` [TOMOYO #12 (2.6.28-rc2-mm1) 08/11] Domain transition handler Kentaro Takeda
2008-11-04 6:08 ` Kentaro Takeda [this message]
2008-11-04 6:08 ` [TOMOYO #12 (2.6.28-rc2-mm1) 10/11] Kconfig and Makefile Kentaro Takeda
2008-11-04 6:08 ` [TOMOYO #12 (2.6.28-rc2-mm1) 11/11] MAINTAINERS info 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=20081104060956.600598373@nttdata.co.jp \
--to=takedakn@nttdata.co.jp \
--cc=akpm@linux-foundation.org \
--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.