--- /dev/null
+/*
+ * security/tomoyo/tomoyo.c
+ *
+ * LSM hooks for TOMOYO Linux.
+ *
+ * Copyright (C) 2005-2009  NTT DATA CORPORATION
+ *
+ * Version: 2.2.0-pre   2009/02/01
+ *
+ */
+
+#include <linux/security.h>
+#include "common.h"
+#include "tomoyo.h"
+#include "realpath.h"
+
+static int tomoyo_cred_prepare(struct cred *new, const struct cred *old,
+                              gfp_t gfp)
+{
+       /*
+        * Since "struct tomoyo_domain_info *" is a sharable pointer,
+        * we don't need to duplicate.
+        */
+       new->security = old->security;
+       return 0;
+}
+
+static int tomoyo_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 (!tomoyo_policy_loaded)
+               tomoyo_load_policy(bprm->filename);
+       /*
+        * Tell tomoyo_bprm_check_security() is called for the first time of an
+        * execve operation.
+        */
+       bprm->cred->security = NULL;
+       return 0;
+}
+
+static int tomoyo_bprm_check_security(struct linux_binprm *bprm)
+{
+       struct tomoyo_domain_info *domain = bprm->cred->security;
+
+       /*
+        * Execute permission is checked against pathname passed to do_execve()
+        * using current domain.
+        */
+       if (!domain) {
+               struct tomoyo_domain_info *next_domain = NULL;
+               int retval = tomoyo_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 tomoyo_check_open_permission(domain, &bprm->file->f_path, 1);
+}
+
+#ifdef CONFIG_SYSCTL
+
+static int tomoyo_prepend(char **buffer, int *buflen, const char *str)
+{
+       int namelen = strlen(str);
+
+       if (*buflen < namelen)
+               return -ENOMEM;
+       *buflen -= namelen;
+       *buffer -= namelen;
+       memcpy(*buffer, str, namelen);
+       return 0;
+}
+
+/**
+ * tomoyo_sysctl_path - return the realpath of a ctl_table.
+ * @table: pointer to "struct ctl_table".
+ *
+ * Returns realpath(3) of the @table on success.
+ * Returns NULL on failure.
+ *
+ * This function uses tomoyo_alloc(), so the caller must call tomoyo_free()
+ * if this function didn't return NULL.
+ */
+static char *tomoyo_sysctl_path(struct ctl_table *table)
+{
+       int buflen = TOMOYO_MAX_PATHNAME_LEN;
+       char *buf = tomoyo_alloc(buflen);
+       char *end = buf + buflen;
+       int error = -ENOMEM;
+
+       if (!buf)
+               return NULL;
+
+       *--end = '\0';
+       buflen--;
+       while (table) {
+               char buf[32];
+               const char *sp = table->procname;
+
+               if (!sp) {
+                       memset(buf, 0, sizeof(buf));
+                       snprintf(buf, sizeof(buf) - 1, "=%d=", table->ctl_name);
+                       sp = buf;
+               }
+               if (tomoyo_prepend(&end, &buflen, sp) ||
+                   tomoyo_prepend(&end, &buflen, "/"))
+                       goto out;
+               table = table->parent;
+       }
+       if (tomoyo_prepend(&end, &buflen, "/proc/sys"))
+               goto out;
+       error = tomoyo_encode(buf, end - buf, end);
+ out:
+       if (!error)
+               return buf;
+       tomoyo_free(buf);
+       return NULL;
+}
+
+static int tomoyo_sysctl(struct ctl_table *table, int op)
+{
+       int error;
+       char *name;
+
+       op &= MAY_READ | MAY_WRITE;
+       if (!op)
+               return 0;
+       name = tomoyo_sysctl_path(table);
+       if (!name)
+               return -ENOMEM;
+       error = tomoyo_check_file_perm(tomoyo_domain(), name, op);
+       tomoyo_free(name);
+       return error;
+}
+#endif
+
+static int tomoyo_path_truncate(struct path *path, loff_t length,
+                               unsigned int time_attrs)
+{
+       return tomoyo_check_1path_perm(tomoyo_domain(),
+                                      TOMOYO_TYPE_TRUNCATE_ACL,
+                                      path);
+}
+
+static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry)
+{
+       struct path path = { parent->mnt, dentry };
+       return tomoyo_check_1path_perm(tomoyo_domain(),
+                                      TOMOYO_TYPE_UNLINK_ACL,
+                                      &path);
+}
+
+static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry,
+                            int mode)
+{
+       struct path path = { parent->mnt, dentry };
+       return tomoyo_check_1path_perm(tomoyo_domain(),
+                                      TOMOYO_TYPE_MKDIR_ACL,
+                                      &path);
+}
+
+static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry)
+{
+       struct path path = { parent->mnt, dentry };
+       return tomoyo_check_1path_perm(tomoyo_domain(),
+                                      TOMOYO_TYPE_RMDIR_ACL,
+                                      &path);
+}
+
+static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry,
+                              const char *old_name)
+{
+       struct path path = { parent->mnt, dentry };
+       return tomoyo_check_1path_perm(tomoyo_domain(),
+                                      TOMOYO_TYPE_SYMLINK_ACL,
+                                      &path);
+}
+
+static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry,
+                            int mode, unsigned int dev)
+{
+       struct path path = { parent->mnt, dentry };
+       int type = TOMOYO_TYPE_CREATE_ACL;
+
+       switch (mode & S_IFMT) {
+       case S_IFCHR:
+               type = TOMOYO_TYPE_MKCHAR_ACL;
+               break;
+       case S_IFBLK:
+               type = TOMOYO_TYPE_MKBLOCK_ACL;
+               break;
+       case S_IFIFO:
+               type = TOMOYO_TYPE_MKFIFO_ACL;
+               break;
+       case S_IFSOCK:
+               type = TOMOYO_TYPE_MKSOCK_ACL;
+               break;
+       }
+       return tomoyo_check_1path_perm(tomoyo_domain(),
+                                      type, &path);
+}
+
+static int tomoyo_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 tomoyo_check_2path_perm(tomoyo_domain(),
+                                      TOMOYO_TYPE_LINK_ACL,
+                                      &path1, &path2);
+}
+
+static int tomoyo_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 tomoyo_check_2path_perm(tomoyo_domain(),
+                                      TOMOYO_TYPE_RENAME_ACL,
+                                      &path1, &path2);
+}
+
+static int tomoyo_file_fcntl(struct file *file, unsigned int cmd,
+                            unsigned long arg)
+{
+       if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))
+               return tomoyo_check_rewrite_permission(tomoyo_domain(), file);
+       return 0;
+}
+
+static int tomoyo_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 tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags);
+}
+
+static struct security_operations tomoyo_security_ops = {
+       .name                = "tomoyo",
+       .cred_prepare        = tomoyo_cred_prepare,
+       .bprm_set_creds      = tomoyo_bprm_set_creds,
+       .bprm_check_security = tomoyo_bprm_check_security,
+#ifdef CONFIG_SYSCTL
+       .sysctl              = tomoyo_sysctl,
+#endif
+       .file_fcntl          = tomoyo_file_fcntl,
+       .dentry_open         = tomoyo_dentry_open,
+       .path_truncate       = tomoyo_path_truncate,
+       .path_unlink         = tomoyo_path_unlink,
+       .path_mkdir          = tomoyo_path_mkdir,
+       .path_rmdir          = tomoyo_path_rmdir,
+       .path_symlink        = tomoyo_path_symlink,
+       .path_mknod          = tomoyo_path_mknod,
+       .path_link           = tomoyo_path_link,
+       .path_rename         = tomoyo_path_rename,
+};
+
+static int __init tomoyo_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 = &tomoyo_kernel_domain;
+       return 0;
+}
+
+security_initcall(tomoyo_init);
 
--- /dev/null
+/*
+ * security/tomoyo/tomoyo.h
+ *
+ * Implementation of the Domain-Based Mandatory Access Control.
+ *
+ * Copyright (C) 2005-2009  NTT DATA CORPORATION
+ *
+ * Version: 2.2.0-pre   2009/02/01
+ *
+ */
+
+#ifndef _SECURITY_TOMOYO_TOMOYO_H
+#define _SECURITY_TOMOYO_TOMOYO_H
+
+struct tomoyo_path_info;
+struct path;
+struct inode;
+struct linux_binprm;
+struct pt_regs;
+struct tomoyo_page_buffer;
+
+int tomoyo_check_file_perm(struct tomoyo_domain_info *domain,
+                          const char *filename, const u8 perm);
+int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain,
+                          const struct tomoyo_path_info *filename,
+                          struct tomoyo_page_buffer *buf);
+int tomoyo_check_open_permission(struct tomoyo_domain_info *domain,
+                                struct path *path, const int flag);
+int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain,
+                           const u8 operation, struct path *path);
+int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain,
+                           const u8 operation, struct path *path1,
+                           struct path *path2);
+int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain,
+                                   struct file *filp);
+int tomoyo_find_next_domain(struct linux_binprm *bprm,
+                           struct tomoyo_domain_info **next_domain);
+
+/* Index numbers for Access Controls. */
+
+#define TOMOYO_TYPE_SINGLE_PATH_ACL                 0
+#define TOMOYO_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 TOMOYO_TYPE_READ_WRITE_ACL    0
+#define TOMOYO_TYPE_EXECUTE_ACL       1
+#define TOMOYO_TYPE_READ_ACL          2
+#define TOMOYO_TYPE_WRITE_ACL         3
+#define TOMOYO_TYPE_CREATE_ACL        4
+#define TOMOYO_TYPE_UNLINK_ACL        5
+#define TOMOYO_TYPE_MKDIR_ACL         6
+#define TOMOYO_TYPE_RMDIR_ACL         7
+#define TOMOYO_TYPE_MKFIFO_ACL        8
+#define TOMOYO_TYPE_MKSOCK_ACL        9
+#define TOMOYO_TYPE_MKBLOCK_ACL      10
+#define TOMOYO_TYPE_MKCHAR_ACL       11
+#define TOMOYO_TYPE_TRUNCATE_ACL     12
+#define TOMOYO_TYPE_SYMLINK_ACL      13
+#define TOMOYO_TYPE_REWRITE_ACL      14
+#define TOMOYO_MAX_SINGLE_PATH_OPERATION 15
+
+#define TOMOYO_TYPE_LINK_ACL         0
+#define TOMOYO_TYPE_RENAME_ACL       1
+#define TOMOYO_MAX_DOUBLE_PATH_OPERATION 2
+
+#define TOMOYO_DOMAINPOLICY          0
+#define TOMOYO_EXCEPTIONPOLICY       1
+#define TOMOYO_DOMAIN_STATUS         2
+#define TOMOYO_PROCESS_STATUS        3
+#define TOMOYO_MEMINFO               4
+#define TOMOYO_SELFDOMAIN            5
+#define TOMOYO_VERSION               6
+#define TOMOYO_PROFILE               7
+#define TOMOYO_MANAGER               8
+
+extern struct tomoyo_domain_info tomoyo_kernel_domain;
+
+static inline struct tomoyo_domain_info *tomoyo_domain(void)
+{
+       return current_cred()->security;
+}
+
+/* Caller holds tasklist_lock spinlock. */
+static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct
+                                                           *task)
+{
+       /***** CRITICAL SECTION START *****/
+       const struct cred *cred = get_task_cred(task);
+       struct tomoyo_domain_info *domain = cred->security;
+
+       put_cred(cred);
+       return domain;
+       /***** CRITICAL SECTION END *****/
+}
+
+#endif /* !defined(_SECURITY_TOMOYO_TOMOYO_H) */