Module parameters, LSM hooks, initialization and teardown.

Signed-off-by: John Johansen <[EMAIL PROTECTED]>
Signed-off-by: Andreas Gruenbacher <[EMAIL PROTECTED]>

---
 security/apparmor/lsm.c |  815 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 815 insertions(+)

--- /dev/null
+++ b/security/apparmor/lsm.c
@@ -0,0 +1,815 @@
+/*
+ *     Copyright (C) 1998-2007 Novell/SUSE
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation, version 2 of the
+ *     License.
+ *
+ *     AppArmor LSM interface
+ */
+
+#include <linux/security.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/ctype.h>
+#include <linux/sysctl.h>
+#include <linux/audit.h>
+
+#include "apparmor.h"
+#include "inline.h"
+
+/* Boot time disable flag */
+int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
+
+static int __init apparmor_enabled_setup(char *str)
+{
+       apparmor_enabled = simple_strtol(str, NULL, 0);
+       return 1;
+}
+__setup("apparmor=", apparmor_enabled_setup);
+
+
+static int param_set_aabool(const char *val, struct kernel_param *kp);
+static int param_get_aabool(char *buffer, struct kernel_param *kp);
+#define param_check_aabool(name, p) __param_check(name, p, int)
+
+static int param_set_aauint(const char *val, struct kernel_param *kp);
+static int param_get_aauint(char *buffer, struct kernel_param *kp);
+#define param_check_aauint(name, p) __param_check(name, p, int)
+
+/* Flag values, also controllable via /sys/module/apparmor/parameters
+ * We define special types as we want to do additional mediation.
+ *
+ * Complain mode -- in complain mode access failures result in auditing only
+ * and task is allowed access.  audit events are processed by userspace to
+ * generate policy.  Default is 'enforce' (0).
+ * Value is also togglable per profile and referenced when global value is
+ * enforce.
+ */
+int apparmor_complain = 0;
+module_param_named(complain, apparmor_complain, aabool, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
+
+/* Debug mode */
+int apparmor_debug = 0;
+module_param_named(debug, apparmor_debug, aabool, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode");
+
+/* Audit mode */
+int apparmor_audit = 0;
+module_param_named(audit, apparmor_audit, aabool, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode");
+
+/* Syscall logging mode */
+int apparmor_logsyscall = 0;
+module_param_named(logsyscall, apparmor_logsyscall, aabool, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode");
+
+/* Maximum pathname length before accesses will start getting rejected */
+unsigned int apparmor_path_max = 2 * PATH_MAX;
+module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed");
+
+static int param_set_aabool(const char *val, struct kernel_param *kp)
+{
+       if (aa_task_context(current))
+               return -EPERM;
+       return param_set_bool(val, kp);
+}
+
+static int param_get_aabool(char *buffer, struct kernel_param *kp)
+{
+       if (aa_task_context(current))
+               return -EPERM;
+       return param_get_bool(buffer, kp);
+}
+
+static int param_set_aauint(const char *val, struct kernel_param *kp)
+{
+       if (aa_task_context(current))
+               return -EPERM;
+       return param_set_uint(val, kp);
+}
+
+static int param_get_aauint(char *buffer, struct kernel_param *kp)
+{
+       if (aa_task_context(current))
+               return -EPERM;
+       return param_get_uint(buffer, kp);
+}
+
+static int aa_reject_syscall(struct task_struct *task, gfp_t flags,
+                            const char *name)
+{
+       struct aa_profile *profile = aa_get_profile(task);
+       int error = 0;
+
+       if (profile) {
+               error = aa_audit_syscallreject(profile, flags, name);
+               aa_put_profile(profile);
+       }
+
+       return error;
+}
+
+static int apparmor_ptrace(struct task_struct *parent,
+                          struct task_struct *child)
+{
+       struct aa_task_context *cxt;
+       int error = 0;
+
+       /*
+        * parent can ptrace child when
+        * - parent is unconfined
+        * - parent & child are in the same namespace &&
+        *   - parent is in complain mode
+        *   - parent and child are confined by the same profile
+        *   - parent profile has CAP_SYS_PTRACE
+        */
+
+       rcu_read_lock();
+       cxt = aa_task_context(parent);
+       if (cxt) {
+               if (parent->nsproxy != child->nsproxy) {
+                       struct aa_audit sa;
+                       memset(&sa, 0, sizeof(sa));
+                       sa.operation = "ptrace";
+                       sa.gfp_mask = GFP_ATOMIC;
+                       sa.parent = parent->pid;
+                       sa.task = child->pid;
+                       sa.info = "different namespaces";
+                       aa_audit_reject(cxt->profile, &sa);
+                       error = -EPERM;
+               } else {
+                       struct aa_task_context *child_cxt =
+                               aa_task_context(child);
+
+                       error = aa_may_ptrace(cxt, child_cxt ?
+                                                  child_cxt->profile : NULL);
+                       if (PROFILE_COMPLAIN(cxt->profile)) {
+                               struct aa_audit sa;
+                               memset(&sa, 0, sizeof(sa));
+                               sa.operation = "ptrace";
+                               sa.gfp_mask = GFP_ATOMIC;
+                               sa.parent = parent->pid;
+                               sa.task = child->pid;
+                               aa_audit_hint(cxt->profile, &sa);
+                       }
+               }
+       }
+       rcu_read_unlock();
+
+       return error;
+}
+
+static int apparmor_capable(struct task_struct *task, int cap)
+{
+       int error;
+
+       /* cap_capable returns 0 on success, else -EPERM */
+       error = cap_capable(task, cap);
+
+       if (!error) {
+               struct aa_task_context *cxt;
+
+               rcu_read_lock();
+               cxt = aa_task_context(task);
+               if (cxt)
+                       error = aa_capability(cxt, cap);
+               rcu_read_unlock();
+       }
+
+       return error;
+}
+
+static int apparmor_sysctl(struct ctl_table *table, int op)
+{
+       struct aa_profile *profile = aa_get_profile(current);
+       int error = 0;
+
+       if (profile) {
+               char *buffer, *name;
+               int mask;
+
+               mask = 0;
+               if (op & 4)
+                       mask |= MAY_READ;
+               if (op & 2)
+                       mask |= MAY_WRITE;
+
+               error = -ENOMEM;
+               buffer = (char*)__get_free_page(GFP_KERNEL);
+               if (!buffer)
+                       goto out;
+               name = sysctl_pathname(table, buffer, PAGE_SIZE);
+               if (name && name - buffer >= 5) {
+                       name -= 5;
+                       memcpy(name, "/proc", 5);
+                       error = aa_perm_path(profile, "sysctl", name, mask, 0);
+               }
+               free_page((unsigned long)buffer);
+       }
+
+out:
+       return error;
+}
+
+static int apparmor_bprm_set_security(struct linux_binprm *bprm)
+{
+       /* handle capability bits with setuid, etc */
+       cap_bprm_set_security(bprm);
+       /* already set based on script name */
+       if (bprm->sh_bang)
+               return 0;
+       return aa_register(bprm);
+}
+
+static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
+{
+       int ret = cap_bprm_secureexec(bprm);
+
+       if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
+               AA_DEBUG("%s: secureexec required for %s\n",
+                        __FUNCTION__, bprm->filename);
+               ret = 1;
+       }
+
+       return ret;
+}
+
+static int apparmor_sb_mount(char *dev_name, struct nameidata *nd, char *type,
+                             unsigned long flags, void *data)
+{
+       return aa_reject_syscall(current, GFP_KERNEL, "mount");
+}
+
+static int apparmor_umount(struct vfsmount *mnt, int flags)
+{
+       return aa_reject_syscall(current, GFP_KERNEL, "umount");
+}
+
+static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,
+                               struct vfsmount *mnt, int mask)
+{
+       struct aa_profile *profile;
+       int error = 0;
+
+       if (!mnt || !mediated_filesystem(dir))
+               goto out;
+
+       profile = aa_get_profile(current);
+
+       if (profile)
+               error = aa_perm_dir(profile, "inode_mkdir", dentry, mnt,
+                                   MAY_WRITE);
+
+       aa_put_profile(profile);
+
+out:
+       return error;
+}
+
+static int apparmor_inode_rmdir(struct inode *dir, struct dentry *dentry,
+                               struct vfsmount *mnt)
+{
+       struct aa_profile *profile;
+       int error = 0;
+
+       if (!mnt || !mediated_filesystem(dir))
+               goto out;
+
+       profile = aa_get_profile(current);
+
+       if (profile)
+               error = aa_perm_dir(profile, "inode_rmdir", dentry, mnt,
+                                   MAY_WRITE);
+
+       aa_put_profile(profile);
+
+out:
+       return error;
+}
+
+static int aa_permission(const char *operation, struct inode *inode,
+                        struct dentry *dentry, struct vfsmount *mnt,
+                        int mask, int check)
+{
+       int error = 0;
+
+       if (mnt && mediated_filesystem(inode)) {
+               struct aa_profile *profile;
+
+               profile = aa_get_profile(current);
+               if (profile)
+                       error = aa_perm(profile, operation, dentry, mnt, mask,
+                                       check);
+               aa_put_profile(profile);
+       }
+       return error;
+}
+
+static inline int aa_mask_permissions(int mask)
+{
+       if (mask & MAY_APPEND)
+               mask &= (MAY_READ | MAY_APPEND | MAY_EXEC);
+       else
+               mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
+       return mask;
+}
+
+static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
+                                struct vfsmount *mnt, int mask)
+{
+       /* FIXME: may move to MAY_APPEND later */
+       return aa_permission("inode_create", dir, dentry, mnt, MAY_WRITE, 0);
+}
+
+static int apparmor_inode_link(struct dentry *old_dentry,
+                              struct vfsmount *old_mnt, struct inode *dir,
+                              struct dentry *new_dentry,
+                              struct vfsmount *new_mnt)
+{
+       int error = 0;
+       struct aa_profile *profile;
+
+       if (!old_mnt || !new_mnt || !mediated_filesystem(dir))
+               goto out;
+
+       profile = aa_get_profile(current);
+
+       if (profile)
+               error = aa_link(profile, new_dentry, new_mnt,
+                               old_dentry, old_mnt);
+
+       aa_put_profile(profile);
+
+out:
+       return error;
+}
+
+static int apparmor_inode_unlink(struct inode *dir, struct dentry *dentry,
+                                struct vfsmount *mnt)
+{
+       int check = 0;
+
+       if (S_ISDIR(dentry->d_inode->i_mode))
+               check |= AA_CHECK_DIR;
+       return aa_permission("inode_unlink", dir, dentry, mnt, MAY_WRITE,
+                            check);
+}
+
+static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry,
+                                 struct vfsmount *mnt, const char *old_name)
+{
+       return aa_permission("inode_symlink", dir, dentry, mnt, MAY_WRITE, 0);
+}
+
+static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry,
+                               struct vfsmount *mnt, int mode, dev_t dev)
+{
+       return aa_permission("inode_mknod", dir, dentry, mnt, MAY_WRITE, 0);
+}
+
+static int apparmor_inode_rename(struct inode *old_dir,
+                                struct dentry *old_dentry,
+                                struct vfsmount *old_mnt,
+                                struct inode *new_dir,
+                                struct dentry *new_dentry,
+                                struct vfsmount *new_mnt)
+{
+       struct aa_profile *profile;
+       int error = 0;
+
+       if ((!old_mnt && !new_mnt) || !mediated_filesystem(old_dir))
+               goto out;
+
+       profile = aa_get_profile(current);
+
+       if (profile) {
+               struct inode *inode = old_dentry->d_inode;
+               int check = 0;
+
+               if (inode && S_ISDIR(inode->i_mode))
+                       check |= AA_CHECK_DIR;
+               if (old_mnt)
+                       error = aa_perm(profile, "inode_rename", old_dentry,
+                                       old_mnt, MAY_READ | MAY_WRITE, check);
+
+               if (!error && new_mnt) {
+                       error = aa_perm(profile, "inode_rename", new_dentry,
+                                       new_mnt, MAY_WRITE, check);
+               }
+       }
+
+       aa_put_profile(profile);
+
+out:
+       return error;
+}
+
+static int apparmor_inode_permission(struct inode *inode, int mask,
+                                    struct nameidata *nd)
+{
+       int check = 0;
+
+       if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE))
+               return 0;
+       mask = aa_mask_permissions(mask);
+       if (S_ISDIR(inode->i_mode)) {
+               check |= AA_CHECK_DIR;
+               /* allow traverse accesses to directories */
+               mask &= ~MAY_EXEC;
+       }
+       return aa_permission("inode_permission", inode, nd->path.dentry,
+                            nd->path.mnt, mask, check);
+}
+
+static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
+                                 struct iattr *iattr)
+{
+       int error = 0;
+
+       if (!mnt)
+               goto out;
+
+       if (mediated_filesystem(dentry->d_inode)) {
+               struct aa_profile *profile;
+
+               profile = aa_get_profile(current);
+               /*
+                * Mediate any attempt to change attributes of a file
+                * (chmod, chown, chgrp, etc)
+                */
+               if (profile)
+                       error = aa_attr(profile, dentry, mnt, iattr);
+
+               aa_put_profile(profile);
+       }
+
+out:
+       return error;
+}
+
+static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
+                              const char *operation, int mask,
+                              struct file *file)
+{
+       int error = 0;
+
+       if (mnt && mediated_filesystem(dentry->d_inode)) {
+               struct aa_profile *profile = aa_get_profile(current);
+               int check = file ? AA_CHECK_FD : 0;
+
+               if (profile)
+                       error = aa_perm_xattr(profile, operation, dentry, mnt,
+                                             mask, check);
+               aa_put_profile(profile);
+       }
+
+       return error;
+}
+
+static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
+                                  char *name, void *value, size_t size,
+                                  int flags, struct file *file)
+{
+       return aa_xattr_permission(dentry, mnt, "xattr set", MAY_WRITE, file);
+}
+
+static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
+                                  char *name, struct file *file)
+{
+       return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
+}
+
+static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount 
*mnt,
+                                   struct file *file)
+{
+       return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
+}
+
+static int apparmor_inode_removexattr(struct dentry *dentry,
+                                     struct vfsmount *mnt, char *name,
+                                     struct file *file)
+{
+       return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
+                                  file);
+}
+
+static int aa_file_permission(const char *op, struct file *file, int mask)
+{
+       struct aa_profile *profile;
+       struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
+       int error = 0;
+
+       if (!file_profile)
+               goto out;
+
+       /*
+        * If this file was opened under a different profile, we
+        * revalidate the access against the current profile.
+        */
+       profile = aa_get_profile(current);
+       if (profile && (file_profile != profile || mask & AA_MAY_LOCK)) {
+               struct dentry *dentry = file->f_dentry;
+               struct vfsmount *mnt = file->f_vfsmnt;
+               struct inode *inode = dentry->d_inode;
+               int check = AA_CHECK_FD;
+
+               /*
+                * FIXME: We should remember which profiles we revalidated
+                *        against.
+                */
+               if (S_ISDIR(inode->i_mode))
+                       check |= AA_CHECK_DIR;
+               error = aa_permission(op, inode, dentry, mnt, mask, check);
+       }
+       aa_put_profile(profile);
+
+out:
+       return error;
+}
+
+static int apparmor_file_permission(struct file *file, int mask)
+{
+       return aa_file_permission("file_permission", file,
+                                 aa_mask_permissions(mask));
+}
+
+static inline int apparmor_file_lock (struct file *file, unsigned int cmd)
+{
+       int mask = AA_MAY_LOCK;
+       if (cmd == F_WRLCK)
+               mask |= MAY_WRITE;
+       return aa_file_permission("file_lock", file, mask);
+}
+
+static int apparmor_file_alloc_security(struct file *file)
+{
+       struct aa_profile *profile;
+
+       profile = aa_get_profile(current);
+       if (profile)
+               file->f_security = profile;
+
+       return 0;
+}
+
+static void apparmor_file_free_security(struct file *file)
+{
+       struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
+
+       aa_put_profile(file_profile);
+}
+
+static inline int aa_mmap(struct file *file, const char *operation,
+                         unsigned long prot, unsigned long flags)
+{
+       struct dentry *dentry;
+       int mask = 0;
+
+       if (!file || !file->f_security)
+               return 0;
+
+       if (prot & PROT_READ)
+               mask |= MAY_READ;
+       /* Private mappings don't require write perms since they don't
+        * write back to the files */
+       if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
+               mask |= MAY_WRITE;
+       if (prot & PROT_EXEC)
+               mask |= AA_EXEC_MMAP;
+
+       dentry = file->f_dentry;
+       return aa_permission(operation, dentry->d_inode, dentry,
+                            file->f_vfsmnt, mask, AA_CHECK_FD);
+}
+
+static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
+                             unsigned long prot, unsigned long flags,
+                             unsigned long addr, unsigned long addr_only)
+{
+       return aa_mmap(file, "file_mmap", prot, flags);
+}
+
+static int apparmor_file_mprotect(struct vm_area_struct *vma,
+                                 unsigned long reqprot, unsigned long prot)
+{
+       return aa_mmap(vma->vm_file, "file_mprotect", prot,
+                      !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
+}
+
+static int apparmor_task_alloc_security(struct task_struct *task)
+{
+       return aa_clone(task);
+}
+
+/*
+ * Called from IRQ context from RCU callback.
+ */
+static void apparmor_task_free_security(struct task_struct *task)
+{
+       aa_release(task);
+}
+
+static int apparmor_getprocattr(struct task_struct *task, char *name,
+                               char **value)
+{
+       unsigned len;
+       int error;
+       struct aa_profile *profile;
+
+       /* AppArmor only supports the "current" process attribute */
+       if (strcmp(name, "current") != 0)
+               return -EINVAL;
+
+       /* must be task querying itself or admin */
+       if (current != task && !capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       profile = aa_get_profile(task);
+       error = aa_getprocattr(profile, value, &len);
+       aa_put_profile(profile);
+       if (!error)
+               error = len;
+
+       return error;
+}
+
+static int apparmor_setprocattr(struct task_struct *task, char *name,
+                               void *value, size_t size)
+{
+       char *command, *args;
+       int error;
+
+       if (strcmp(name, "current") != 0 || size == 0 || size >= PAGE_SIZE)
+               return -EINVAL;
+       args = value;
+       args[size] = '\0';
+       args = strstrip(args);
+       command = strsep(&args, " ");
+       if (!args)
+               return -EINVAL;
+       while (isspace(*args))
+               args++;
+       if (!*args)
+               return -EINVAL;
+
+       if (strcmp(command, "changehat") == 0) {
+               if (current != task)
+                       return -EACCES;
+               error = aa_setprocattr_changehat(args);
+       } else if (strcmp(command, "changeprofile") == 0) {
+               if (current != task)
+                       return -EACCES;
+               error = aa_setprocattr_changeprofile(args);
+       } else if (strcmp(command, "setprofile") == 0) {
+               struct aa_profile *profile;
+
+               /* Only an unconfined process with admin capabilities
+                * may change the profile of another task.
+                */
+
+               if (!capable(CAP_SYS_ADMIN))
+                       return -EACCES;
+
+               profile = aa_get_profile(current);
+               if (profile) {
+                       struct aa_audit sa;
+                       memset(&sa, 0, sizeof(sa));
+                       sa.operation = "profile_set";
+                       sa.gfp_mask = GFP_KERNEL;
+                       sa.task = task->pid;
+                       sa.info = "from confined process";
+                       aa_audit_reject(profile, &sa);
+                       aa_put_profile(profile);
+                       return -EACCES;
+               }
+               error = aa_setprocattr_setprofile(task, args);
+       } else {
+               struct aa_audit sa;
+               memset(&sa, 0, sizeof(sa));
+               sa.operation = "setprocattr";
+               sa.gfp_mask = GFP_KERNEL;
+               sa.info = "invalid command";
+               sa.name = command;
+               sa.task = task->pid;
+               aa_audit_reject(NULL, &sa);
+               return -EINVAL;
+       }
+
+       if (!error)
+               error = size;
+       return error;
+}
+
+struct security_operations apparmor_ops = {
+       .ptrace =                       apparmor_ptrace,
+       .capget =                       cap_capget,
+       .capset_check =                 cap_capset_check,
+       .capset_set =                   cap_capset_set,
+       .sysctl =                       apparmor_sysctl,
+       .capable =                      apparmor_capable,
+       .syslog =                       cap_syslog,
+
+       .netlink_send =                 cap_netlink_send,
+       .netlink_recv =                 cap_netlink_recv,
+
+       .bprm_apply_creds =             cap_bprm_apply_creds,
+       .bprm_set_security =            apparmor_bprm_set_security,
+       .bprm_secureexec =              apparmor_bprm_secureexec,
+
+       .sb_mount =                     apparmor_sb_mount,
+       .sb_umount =                    apparmor_umount,
+
+       .inode_mkdir =                  apparmor_inode_mkdir,
+       .inode_rmdir =                  apparmor_inode_rmdir,
+       .inode_create =                 apparmor_inode_create,
+       .inode_link =                   apparmor_inode_link,
+       .inode_unlink =                 apparmor_inode_unlink,
+       .inode_symlink =                apparmor_inode_symlink,
+       .inode_mknod =                  apparmor_inode_mknod,
+       .inode_rename =                 apparmor_inode_rename,
+       .inode_permission =             apparmor_inode_permission,
+       .inode_setattr =                apparmor_inode_setattr,
+       .inode_setxattr =               apparmor_inode_setxattr,
+       .inode_getxattr =               apparmor_inode_getxattr,
+       .inode_listxattr =              apparmor_inode_listxattr,
+       .inode_removexattr =            apparmor_inode_removexattr,
+       .file_permission =              apparmor_file_permission,
+       .file_alloc_security =          apparmor_file_alloc_security,
+       .file_free_security =           apparmor_file_free_security,
+       .file_mmap =                    apparmor_file_mmap,
+       .file_mprotect =                apparmor_file_mprotect,
+       .file_lock =                    apparmor_file_lock,
+
+       .task_alloc_security =          apparmor_task_alloc_security,
+       .task_free_security =           apparmor_task_free_security,
+       .task_post_setuid =             cap_task_post_setuid,
+       .task_reparent_to_init =        cap_task_reparent_to_init,
+
+       .getprocattr =                  apparmor_getprocattr,
+       .setprocattr =                  apparmor_setprocattr,
+};
+
+static void info_message(const char *str)
+{
+       struct aa_audit sa;
+       memset(&sa, 0, sizeof(sa));
+       sa.gfp_mask = GFP_KERNEL;
+       sa.info = str;
+       printk(KERN_INFO "AppArmor: %s", str);
+       aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
+}
+
+static int __init apparmor_init(void)
+{
+       int error;
+
+       if (!apparmor_enabled) {
+               info_message("AppArmor disabled by boottime parameter\n");
+               return 0;
+       }
+
+       if ((error = create_apparmorfs())) {
+               AA_ERROR("Unable to activate AppArmor filesystem\n");
+               goto createfs_out;
+       }
+
+       if ((error = alloc_default_namespace())){
+               AA_ERROR("Unable to allocate default profile namespace\n");
+               goto alloc_out;
+       }
+
+       if ((error = register_security(&apparmor_ops))) {
+               AA_ERROR("Unable to register AppArmor\n");
+               goto register_security_out;
+       }
+
+       if (apparmor_complain)
+               info_message("AppArmor initialized: complainmode enabled");
+       else
+               info_message("AppArmor initialized");
+
+       return error;
+
+register_security_out:
+       free_default_namespace();
+
+alloc_out:
+       destroy_apparmorfs();
+
+createfs_out:
+       return error;
+
+}
+
+module_init(apparmor_init);
+
+MODULE_DESCRIPTION("AppArmor process confinement");
+MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org";);
+MODULE_LICENSE("GPL");

-- 

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

Reply via email to