tty: Make get_current_tty use a kref
[safe/jmp/linux-2.6] / security / selinux / hooks.c
index f9927f0..089d61a 100644 (file)
@@ -4,27 +4,28 @@
  *  This file contains the SELinux hook function implementations.
  *
  *  Authors:  Stephen Smalley, <sds@epoch.ncsc.mil>
- *            Chris Vance, <cvance@nai.com>
- *            Wayne Salamon, <wsalamon@nai.com>
- *            James Morris <jmorris@redhat.com>
+ *           Chris Vance, <cvance@nai.com>
+ *           Wayne Salamon, <wsalamon@nai.com>
+ *           James Morris <jmorris@redhat.com>
  *
  *  Copyright (C) 2001,2002 Networks Associates Technology, Inc.
- *  Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *  Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *                                        Eric Paris <eparis@redhat.com>
  *  Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
- *                          <dgoeddel@trustedcs.com>
+ *                         <dgoeddel@trustedcs.com>
  *  Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
- *                Paul Moore <paul.moore@hp.com>
+ *             Paul Moore <paul.moore@hp.com>
  *  Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
- *                     Yuichi Nakamura <ynakam@hitachisoft.jp>
+ *                    Yuichi Nakamura <ynakam@hitachisoft.jp>
  *
  *     This program is free software; you can redistribute it and/or modify
  *     it under the terms of the GNU General Public License version 2,
- *      as published by the Free Software Foundation.
+ *     as published by the Free Software Foundation.
  */
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/ptrace.h>
+#include <linux/tracehook.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/security.h>
 #include <linux/spinlock.h>
 #include <linux/syscalls.h>
 #include <linux/file.h>
+#include <linux/fdtable.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
-#include <linux/ext2_fs.h>
 #include <linux/proc_fs.h>
-#include <linux/kd.h>
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv6.h>
 #include <linux/tty.h>
@@ -52,7 +52,7 @@
 #include <net/tcp.h>           /* struct or_callable used in sock_rcv_skb */
 #include <net/net_namespace.h>
 #include <net/netlabel.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <asm/ioctls.h>
 #include <asm/atomic.h>
 #include <linux/bitops.h>
@@ -99,11 +99,13 @@ extern struct security_operations *security_ops;
 atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
 
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
-int selinux_enforcing = 0;
+int selinux_enforcing;
 
 static int __init enforcing_setup(char *str)
 {
-       selinux_enforcing = simple_strtol(str,NULL,0);
+       unsigned long enforcing;
+       if (!strict_strtoul(str, 0, &enforcing))
+               selinux_enforcing = enforcing ? 1 : 0;
        return 1;
 }
 __setup("enforcing=", enforcing_setup);
@@ -114,7 +116,9 @@ int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
 
 static int __init selinux_enabled_setup(char *str)
 {
-       selinux_enabled = simple_strtol(str, NULL, 0);
+       unsigned long enabled;
+       if (!strict_strtoul(str, 0, &enabled))
+               selinux_enabled = enabled ? 1 : 0;
        return 1;
 }
 __setup("selinux=", selinux_enabled_setup);
@@ -122,14 +126,12 @@ __setup("selinux=", selinux_enabled_setup);
 int selinux_enabled = 1;
 #endif
 
-/* Original (dummy) security module. */
-static struct security_operations *original_ops = NULL;
 
-/* Minimal support for a secondary security module,
-   just to allow the use of the dummy or capability modules.
-   The owlsm module can alternatively be used as a secondary
  module as long as CONFIG_OWLSM_FD is not enabled. */
-static struct security_operations *secondary_ops = NULL;
+/*
+ * Minimal support for a secondary security module,
+ * just to allow the use of the capability module.
+ */
+static struct security_operations *secondary_ops;
 
 /* Lists of inode and superblock security structures initialized
    before the policy was loaded. */
@@ -575,8 +577,8 @@ static int selinux_set_mnt_opts(struct super_block *sb,
                        goto out;
                }
                rc = -EINVAL;
-               printk(KERN_WARNING "Unable to set superblock options before "
-                      "the security server is initialized\n");
+               printk(KERN_WARNING "SELinux: Unable to set superblock options "
+                       "before the security server is initialized\n");
                goto out;
        }
 
@@ -593,7 +595,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
         */
        if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
            && (num_opts == 0))
-               goto out;
+               goto out;
 
        /*
         * parse the mount options, check if they are valid sids.
@@ -755,9 +757,18 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
        int set_context =       (oldsbsec->flags & CONTEXT_MNT);
        int set_rootcontext =   (oldsbsec->flags & ROOTCONTEXT_MNT);
 
-       /* we can't error, we can't save the info, this shouldn't get called
-        * this early in the boot process. */
-       BUG_ON(!ss_initialized);
+       /*
+        * if the parent was able to be mounted it clearly had no special lsm
+        * mount options.  thus we can safely put this sb on the list and deal
+        * with it later
+        */
+       if (!ss_initialized) {
+               spin_lock(&sb_security_lock);
+               if (list_empty(&newsbsec->list))
+                       list_add(&newsbsec->list, &superblock_security_head);
+               spin_unlock(&sb_security_lock);
+               return;
+       }
 
        /* how can we clone if the old one wasn't set up?? */
        BUG_ON(!oldsbsec->initialized);
@@ -946,6 +957,62 @@ out_err:
        return rc;
 }
 
+static void selinux_write_opts(struct seq_file *m,
+                              struct security_mnt_opts *opts)
+{
+       int i;
+       char *prefix;
+
+       for (i = 0; i < opts->num_mnt_opts; i++) {
+               char *has_comma = strchr(opts->mnt_opts[i], ',');
+
+               switch (opts->mnt_opts_flags[i]) {
+               case CONTEXT_MNT:
+                       prefix = CONTEXT_STR;
+                       break;
+               case FSCONTEXT_MNT:
+                       prefix = FSCONTEXT_STR;
+                       break;
+               case ROOTCONTEXT_MNT:
+                       prefix = ROOTCONTEXT_STR;
+                       break;
+               case DEFCONTEXT_MNT:
+                       prefix = DEFCONTEXT_STR;
+                       break;
+               default:
+                       BUG();
+               };
+               /* we need a comma before each option */
+               seq_putc(m, ',');
+               seq_puts(m, prefix);
+               if (has_comma)
+                       seq_putc(m, '\"');
+               seq_puts(m, opts->mnt_opts[i]);
+               if (has_comma)
+                       seq_putc(m, '\"');
+       }
+}
+
+static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
+{
+       struct security_mnt_opts opts;
+       int rc;
+
+       rc = selinux_get_mnt_opts(sb, &opts);
+       if (rc) {
+               /* before policy load we may get EINVAL, don't show anything */
+               if (rc == -EINVAL)
+                       rc = 0;
+               return rc;
+       }
+
+       selinux_write_opts(m, &opts);
+
+       security_free_mnt_opts(&opts);
+
+       return rc;
+}
+
 static inline u16 inode_mode_to_security_class(umode_t mode)
 {
        switch (mode & S_IFMT) {
@@ -1054,7 +1121,7 @@ static int selinux_proc_get_sid(struct proc_dir_entry *de,
        int buflen, rc;
        char *buffer, *path, *end;
 
-       buffer = (char*)__get_free_page(GFP_KERNEL);
+       buffer = (char *)__get_free_page(GFP_KERNEL);
        if (!buffer)
                return -ENOMEM;
 
@@ -1135,7 +1202,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
                        dentry = d_find_alias(inode);
                }
                if (!dentry) {
-                       printk(KERN_WARNING "%s:  no dentry for dev=%s "
+                       printk(KERN_WARNING "SELinux: %s:  no dentry for dev=%s "
                               "ino=%ld\n", __func__, inode->i_sb->s_id,
                               inode->i_ino);
                        goto out_unlock;
@@ -1173,7 +1240,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
                dput(dentry);
                if (rc < 0) {
                        if (rc != -ENODATA) {
-                               printk(KERN_WARNING "%s:  getxattr returned "
+                               printk(KERN_WARNING "SELinux: %s:  getxattr returned "
                                       "%d for dev=%s ino=%ld\n", __func__,
                                       -rc, inode->i_sb->s_id, inode->i_ino);
                                kfree(context);
@@ -1187,7 +1254,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
                                                             sbsec->def_sid,
                                                             GFP_NOFS);
                        if (rc) {
-                               printk(KERN_WARNING "%s:  context_to_sid(%s) "
+                               printk(KERN_WARNING "SELinux: %s:  context_to_sid(%s) "
                                       "returned %d for dev=%s ino=%ld\n",
                                       __func__, context, -rc,
                                       inode->i_sb->s_id, inode->i_ino);
@@ -1224,7 +1291,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
                /* Default to the fs superblock SID. */
                isec->sid = sbsec->sid;
 
-               if (sbsec->proc) {
+               if (sbsec->proc && !S_ISLNK(inode->i_mode)) {
                        struct proc_inode *proci = PROC_I(inode);
                        if (proci->pde) {
                                isec->sclass = inode_mode_to_security_class(inode->i_mode);
@@ -1305,7 +1372,7 @@ static int task_has_capability(struct task_struct *tsk,
 
        tsec = tsk->security;
 
-       AVC_AUDIT_DATA_INIT(&ad,CAP);
+       AVC_AUDIT_DATA_INIT(&ad, CAP);
        ad.tsk = tsk;
        ad.u.cap = cap;
 
@@ -1348,7 +1415,7 @@ static int inode_has_perm(struct task_struct *tsk,
        struct inode_security_struct *isec;
        struct avc_audit_data ad;
 
-       if (unlikely (IS_PRIVATE (inode)))
+       if (unlikely(IS_PRIVATE(inode)))
                return 0;
 
        tsec = tsk->security;
@@ -1373,7 +1440,7 @@ static inline int dentry_has_perm(struct task_struct *tsk,
 {
        struct inode *inode = dentry->d_inode;
        struct avc_audit_data ad;
-       AVC_AUDIT_DATA_INIT(&ad,FS);
+       AVC_AUDIT_DATA_INIT(&ad, FS);
        ad.u.fs.path.mnt = mnt;
        ad.u.fs.path.dentry = dentry;
        return inode_has_perm(tsk, inode, av, &ad);
@@ -1470,9 +1537,9 @@ static int may_create_key(u32 ksid,
        return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL);
 }
 
-#define MAY_LINK   0
-#define MAY_UNLINK 1
-#define MAY_RMDIR  2
+#define MAY_LINK       0
+#define MAY_UNLINK     1
+#define MAY_RMDIR      2
 
 /* Check whether a task can link, unlink, or rmdir a file/directory. */
 static int may_link(struct inode *dir,
@@ -1510,7 +1577,8 @@ static int may_link(struct inode *dir,
                av = DIR__RMDIR;
                break;
        default:
-               printk(KERN_WARNING "may_link:  unrecognized kind %d\n", kind);
+               printk(KERN_WARNING "SELinux: %s:  unrecognized kind %d\n",
+                       __func__, kind);
                return 0;
        }
 
@@ -1640,8 +1708,8 @@ static inline u32 open_file_mask_to_av(int mode, int mask)
                else if (S_ISDIR(mode))
                        av |= DIR__OPEN;
                else
-                       printk(KERN_ERR "SELinux: WARNING: inside open_file_to_av "
-                               "with unknown mode:%x\n", mode);
+                       printk(KERN_ERR "SELinux: WARNING: inside %s with "
+                               "unknown mode:%x\n", __func__, mode);
        }
        return av;
 }
@@ -1671,19 +1739,38 @@ static inline u32 file_to_av(struct file *file)
 
 /* Hook functions begin here. */
 
-static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
+static int selinux_ptrace_may_access(struct task_struct *child,
+                                    unsigned int mode)
+{
+       int rc;
+
+       rc = secondary_ops->ptrace_may_access(child, mode);
+       if (rc)
+               return rc;
+
+       if (mode == PTRACE_MODE_READ) {
+               struct task_security_struct *tsec = current->security;
+               struct task_security_struct *csec = child->security;
+               return avc_has_perm(tsec->sid, csec->sid,
+                                   SECCLASS_FILE, FILE__READ, NULL);
+       }
+
+       return task_has_perm(current, child, PROCESS__PTRACE);
+}
+
+static int selinux_ptrace_traceme(struct task_struct *parent)
 {
        int rc;
 
-       rc = secondary_ops->ptrace(parent,child);
+       rc = secondary_ops->ptrace_traceme(parent);
        if (rc)
                return rc;
 
-       return task_has_perm(parent, child, PROCESS__PTRACE);
+       return task_has_perm(parent, current, PROCESS__PTRACE);
 }
 
 static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
-                          kernel_cap_t *inheritable, kernel_cap_t *permitted)
+                         kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
        int error;
 
@@ -1695,7 +1782,7 @@ static int selinux_capget(struct task_struct *target, kernel_cap_t *effective,
 }
 
 static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effective,
-                                kernel_cap_t *inheritable, kernel_cap_t *permitted)
+                               kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
        int error;
 
@@ -1707,7 +1794,7 @@ static int selinux_capset_check(struct task_struct *target, kernel_cap_t *effect
 }
 
 static void selinux_capset_set(struct task_struct *target, kernel_cap_t *effective,
-                               kernel_cap_t *inheritable, kernel_cap_t *permitted)
+                              kernel_cap_t *inheritable, kernel_cap_t *permitted)
 {
        secondary_ops->capset_set(target, effective, inheritable, permitted);
 }
@@ -1720,7 +1807,7 @@ static int selinux_capable(struct task_struct *tsk, int cap)
        if (rc)
                return rc;
 
-       return task_has_capability(tsk,cap);
+       return task_has_capability(tsk, cap);
 }
 
 static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
@@ -1729,7 +1816,7 @@ static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
        char *buffer, *path, *end;
 
        rc = -ENOMEM;
-       buffer = (char*)__get_free_page(GFP_KERNEL);
+       buffer = (char *)__get_free_page(GFP_KERNEL);
        if (!buffer)
                goto out;
 
@@ -1787,7 +1874,7 @@ static int selinux_sysctl(ctl_table *table, int op)
 
        /* The op values are "defined" in sysctl.c, thereby creating
         * a bad coupling between this module and sysctl.c */
-       if(op == 001) {
+       if (op == 001) {
                error = avc_has_perm(tsec->sid, tsid,
                                     SECCLASS_DIR, DIR__SEARCH, NULL);
        } else {
@@ -1799,7 +1886,7 @@ static int selinux_sysctl(ctl_table *table, int op)
                if (av)
                        error = avc_has_perm(tsec->sid, tsid,
                                             SECCLASS_FILE, av, NULL);
-        }
+       }
 
        return error;
 }
@@ -1812,25 +1899,23 @@ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
                return 0;
 
        switch (cmds) {
-               case Q_SYNC:
-               case Q_QUOTAON:
-               case Q_QUOTAOFF:
-               case Q_SETINFO:
-               case Q_SETQUOTA:
-                       rc = superblock_has_perm(current,
-                                                sb,
-                                                FILESYSTEM__QUOTAMOD, NULL);
-                       break;
-               case Q_GETFMT:
-               case Q_GETINFO:
-               case Q_GETQUOTA:
-                       rc = superblock_has_perm(current,
-                                                sb,
-                                                FILESYSTEM__QUOTAGET, NULL);
-                       break;
-               default:
-                       rc = 0;  /* let the kernel handle invalid cmds */
-                       break;
+       case Q_SYNC:
+       case Q_QUOTAON:
+       case Q_QUOTAOFF:
+       case Q_SETINFO:
+       case Q_SETQUOTA:
+               rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAMOD,
+                                        NULL);
+               break;
+       case Q_GETFMT:
+       case Q_GETINFO:
+       case Q_GETQUOTA:
+               rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAGET,
+                                        NULL);
+               break;
+       default:
+               rc = 0;  /* let the kernel handle invalid cmds */
+               break;
        }
        return rc;
 }
@@ -1849,23 +1934,23 @@ static int selinux_syslog(int type)
                return rc;
 
        switch (type) {
-               case 3:         /* Read last kernel messages */
-               case 10:        /* Return size of the log buffer */
-                       rc = task_has_system(current, SYSTEM__SYSLOG_READ);
-                       break;
-               case 6:         /* Disable logging to console */
-               case 7:         /* Enable logging to console */
-               case 8:         /* Set level of messages printed to console */
-                       rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
-                       break;
-               case 0:         /* Close log */
-               case 1:         /* Open log */
-               case 2:         /* Read from log */
-               case 4:         /* Read/clear last kernel messages */
-               case 5:         /* Clear ring buffer */
-               default:
-                       rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
-                       break;
+       case 3:         /* Read last kernel messages */
+       case 10:        /* Return size of the log buffer */
+               rc = task_has_system(current, SYSTEM__SYSLOG_READ);
+               break;
+       case 6:         /* Disable logging to console */
+       case 7:         /* Enable logging to console */
+       case 8:         /* Set level of messages printed to console */
+               rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE);
+               break;
+       case 0:         /* Close log */
+       case 1:         /* Open log */
+       case 2:         /* Read from log */
+       case 4:         /* Read/clear last kernel messages */
+       case 5:         /* Clear ring buffer */
+       default:
+               rc = task_has_system(current, SYSTEM__SYSLOG_MOD);
+               break;
        }
        return rc;
 }
@@ -1901,22 +1986,6 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
        return __vm_enough_memory(mm, pages, cap_sys_admin);
 }
 
-/**
- * task_tracer_task - return the task that is tracing the given task
- * @task:              task to consider
- *
- * Returns NULL if noone is tracing @task, or the &struct task_struct
- * pointer to its tracer.
- *
- * Must be called under rcu_read_lock().
- */
-static struct task_struct *task_tracer_task(struct task_struct *task)
-{
-       if (task->ptrace & PT_PTRACED)
-               return rcu_dereference(task->parent);
-       return NULL;
-}
-
 /* binprm security operations */
 
 static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
@@ -1971,7 +2040,7 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
        } else {
                /* Check for a default transition on this program. */
                rc = security_transition_sid(tsec->sid, isec->sid,
-                                            SECCLASS_PROCESS, &newsid);
+                                            SECCLASS_PROCESS, &newsid);
                if (rc)
                        return rc;
        }
@@ -1982,7 +2051,7 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
        if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
                newsid = tsec->sid;
 
-        if (tsec->sid == newsid) {
+       if (tsec->sid == newsid) {
                rc = avc_has_perm(tsec->sid, isec->sid,
                                  SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad);
                if (rc)
@@ -2010,13 +2079,13 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
        return 0;
 }
 
-static int selinux_bprm_check_security (struct linux_binprm *bprm)
+static int selinux_bprm_check_security(struct linux_binprm *bprm)
 {
        return secondary_ops->bprm_check_security(bprm);
 }
 
 
-static int selinux_bprm_secureexec (struct linux_binprm *bprm)
+static int selinux_bprm_secureexec(struct linux_binprm *bprm)
 {
        struct task_security_struct *tsec = current->security;
        int atsecure = 0;
@@ -2043,7 +2112,7 @@ extern struct vfsmount *selinuxfs_mount;
 extern struct dentry *selinux_null;
 
 /* Derived from fs/exec.c:flush_old_files. */
-static inline void flush_unauthorized_files(struct files_struct * files)
+static inline void flush_unauthorized_files(struct files_struct *files)
 {
        struct avc_audit_data ad;
        struct file *file, *devnull = NULL;
@@ -2054,6 +2123,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
 
        mutex_lock(&tty_mutex);
        tty = get_current_tty();
+       mutex_unlock(&tty_mutex);
        if (tty) {
                file_list_lock();
                file = list_entry(tty->tty_files.next, typeof(*file), f_u.fu_list);
@@ -2070,15 +2140,15 @@ static inline void flush_unauthorized_files(struct files_struct * files)
                        }
                }
                file_list_unlock();
+               tty_kref_put(tty);
        }
-       mutex_unlock(&tty_mutex);
        /* Reset controlling tty. */
        if (drop_tty)
                no_tty();
 
        /* Revalidate access to inherited open files. */
 
-       AVC_AUDIT_DATA_INIT(&ad,FS);
+       AVC_AUDIT_DATA_INIT(&ad, FS);
 
        spin_lock(&files->file_lock);
        for (;;) {
@@ -2094,7 +2164,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
                if (!set)
                        continue;
                spin_unlock(&files->file_lock);
-               for ( ; set ; i++,set >>= 1) {
+               for ( ; set ; i++, set >>= 1) {
                        if (set & 1) {
                                file = fget(i);
                                if (!file)
@@ -2168,7 +2238,7 @@ static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
                        u32 ptsid = 0;
 
                        rcu_read_lock();
-                       tracer = task_tracer_task(current);
+                       tracer = tracehook_tracer_task(current);
                        if (likely(tracer != NULL)) {
                                sec = tracer->security;
                                ptsid = sec->sid;
@@ -2251,7 +2321,7 @@ static void selinux_bprm_post_apply_creds(struct linux_binprm *bprm)
                for (i = 0; i < RLIM_NLIMITS; i++) {
                        rlim = current->signal->rlim + i;
                        initrlim = init_task.signal->rlim+i;
-                       rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
+                       rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur);
                }
                if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
                        /*
@@ -2306,16 +2376,15 @@ static inline void take_option(char **to, char *from, int *first, int len)
        *to += len;
 }
 
-static inline void take_selinux_option(char **to, char *from, int *first, 
-                                      int len)
+static inline void take_selinux_option(char **to, char *from, int *first,
+                                      int len)
 {
        int current_size = 0;
 
        if (!*first) {
                **to = '|';
                *to += 1;
-       }
-       else
+       } else
                *first = 0;
 
        while (current_size < len) {
@@ -2379,7 +2448,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, void *data)
        if (rc)
                return rc;
 
-       AVC_AUDIT_DATA_INIT(&ad,FS);
+       AVC_AUDIT_DATA_INIT(&ad, FS);
        ad.u.fs.path.dentry = sb->s_root;
        return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
 }
@@ -2388,29 +2457,29 @@ static int selinux_sb_statfs(struct dentry *dentry)
 {
        struct avc_audit_data ad;
 
-       AVC_AUDIT_DATA_INIT(&ad,FS);
+       AVC_AUDIT_DATA_INIT(&ad, FS);
        ad.u.fs.path.dentry = dentry->d_sb->s_root;
        return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
 }
 
-static int selinux_mount(char * dev_name,
-                         struct nameidata *nd,
-                         char * type,
-                         unsigned long flags,
-                         void * data)
+static int selinux_mount(char *dev_name,
+                        struct path *path,
+                        char *type,
+                        unsigned long flags,
+                        void *data)
 {
        int rc;
 
-       rc = secondary_ops->sb_mount(dev_name, nd, type, flags, data);
+       rc = secondary_ops->sb_mount(dev_name, path, type, flags, data);
        if (rc)
                return rc;
 
        if (flags & MS_REMOUNT)
-               return superblock_has_perm(current, nd->path.mnt->mnt_sb,
-                                          FILESYSTEM__REMOUNT, NULL);
+               return superblock_has_perm(current, path->mnt->mnt_sb,
+                                          FILESYSTEM__REMOUNT, NULL);
        else
-               return dentry_has_perm(current, nd->path.mnt, nd->path.dentry,
-                                      FILE__MOUNTON);
+               return dentry_has_perm(current, path->mnt, path->dentry,
+                                      FILE__MOUNTON);
 }
 
 static int selinux_umount(struct vfsmount *mnt, int flags)
@@ -2421,8 +2490,8 @@ static int selinux_umount(struct vfsmount *mnt, int flags)
        if (rc)
                return rc;
 
-       return superblock_has_perm(current,mnt->mnt_sb,
-                                  FILESYSTEM__UNMOUNT,NULL);
+       return superblock_has_perm(current, mnt->mnt_sb,
+                                  FILESYSTEM__UNMOUNT, NULL);
 }
 
 /* inode security operations */
@@ -2487,7 +2556,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
        }
 
        if (value && len) {
-               rc = security_sid_to_context(newsid, &context, &clen);
+               rc = security_sid_to_context_force(newsid, &context, &clen);
                if (rc) {
                        kfree(namep);
                        return rc;
@@ -2508,7 +2577,7 @@ static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, stru
 {
        int rc;
 
-       rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
+       rc = secondary_ops->inode_link(old_dentry, dir, new_dentry);
        if (rc)
                return rc;
        return may_link(dir, old_dentry, MAY_LINK);
@@ -2551,7 +2620,7 @@ static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mod
 }
 
 static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
-                                struct inode *new_inode, struct dentry *new_dentry)
+                               struct inode *new_inode, struct dentry *new_dentry)
 {
        return may_rename(old_inode, old_dentry, new_inode, new_dentry);
 }
@@ -2565,18 +2634,17 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na
 {
        int rc;
 
-       rc = secondary_ops->inode_follow_link(dentry,nameidata);
+       rc = secondary_ops->inode_follow_link(dentry, nameidata);
        if (rc)
                return rc;
        return dentry_has_perm(current, NULL, dentry, FILE__READ);
 }
 
-static int selinux_inode_permission(struct inode *inode, int mask,
-                                   struct nameidata *nd)
+static int selinux_inode_permission(struct inode *inode, int mask)
 {
        int rc;
 
-       rc = secondary_ops->inode_permission(inode, mask, nd);
+       rc = secondary_ops->inode_permission(inode, mask);
        if (rc)
                return rc;
 
@@ -2612,7 +2680,7 @@ static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
        return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
 }
 
-static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
+static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
 {
        if (!strncmp(name, XATTR_SECURITY_PREFIX,
                     sizeof XATTR_SECURITY_PREFIX - 1)) {
@@ -2631,7 +2699,8 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
        return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
 }
 
-static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
+static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
+                                 const void *value, size_t size, int flags)
 {
        struct task_security_struct *tsec = current->security;
        struct inode *inode = dentry->d_inode;
@@ -2651,7 +2720,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
        if (!is_owner_or_cap(inode))
                return -EPERM;
 
-       AVC_AUDIT_DATA_INIT(&ad,FS);
+       AVC_AUDIT_DATA_INIT(&ad, FS);
        ad.u.fs.path.dentry = dentry;
 
        rc = avc_has_perm(tsec->sid, isec->sid, isec->sclass,
@@ -2660,6 +2729,11 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
                return rc;
 
        rc = security_context_to_sid(value, size, &newsid);
+       if (rc == -EINVAL) {
+               if (!capable(CAP_MAC_ADMIN))
+                       return rc;
+               rc = security_context_to_sid_force(value, size, &newsid);
+       }
        if (rc)
                return rc;
 
@@ -2669,7 +2743,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
                return rc;
 
        rc = security_validate_transition(isec->sid, newsid, tsec->sid,
-                                         isec->sclass);
+                                         isec->sclass);
        if (rc)
                return rc;
 
@@ -2680,8 +2754,9 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
                            &ad);
 }
 
-static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
-                                        void *value, size_t size, int flags)
+static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
+                                       const void *value, size_t size,
+                                       int flags)
 {
        struct inode *inode = dentry->d_inode;
        struct inode_security_struct *isec = inode->i_security;
@@ -2693,10 +2768,11 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
                return;
        }
 
-       rc = security_context_to_sid(value, size, &newsid);
+       rc = security_context_to_sid_force(value, size, &newsid);
        if (rc) {
-               printk(KERN_WARNING "%s:  unable to obtain SID for context "
-                      "%s, rc=%d\n", __func__, (char *)value, -rc);
+               printk(KERN_ERR "SELinux:  unable to map context to SID"
+                      "for (%s, %lu), rc=%d\n",
+                      inode->i_sb->s_id, inode->i_ino, -rc);
                return;
        }
 
@@ -2704,17 +2780,17 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
        return;
 }
 
-static int selinux_inode_getxattr (struct dentry *dentry, char *name)
+static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
 {
        return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
 }
 
-static int selinux_inode_listxattr (struct dentry *dentry)
+static int selinux_inode_listxattr(struct dentry *dentry)
 {
        return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
 }
 
-static int selinux_inode_removexattr (struct dentry *dentry, char *name)
+static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
 {
        if (strcmp(name, XATTR_NAME_SELINUX))
                return selinux_inode_setotherxattr(dentry, name);
@@ -2725,9 +2801,7 @@ static int selinux_inode_removexattr (struct dentry *dentry, char *name)
 }
 
 /*
- * Copy the in-core inode security context value to the user.  If the
- * getxattr() prior to this succeeded, check to see if we need to
- * canonicalize the value to be finally returned to the user.
+ * Copy the inode security context value to the user.
  *
  * Permission check is handled by selinux_inode_getxattr hook.
  */
@@ -2736,12 +2810,33 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
        u32 size;
        int error;
        char *context = NULL;
+       struct task_security_struct *tsec = current->security;
        struct inode_security_struct *isec = inode->i_security;
 
        if (strcmp(name, XATTR_SELINUX_SUFFIX))
                return -EOPNOTSUPP;
 
-       error = security_sid_to_context(isec->sid, &context, &size);
+       /*
+        * If the caller has CAP_MAC_ADMIN, then get the raw context
+        * value even if it is not defined by current policy; otherwise,
+        * use the in-core value under current policy.
+        * Use the non-auditing forms of the permission checks since
+        * getxattr may be called by unprivileged processes commonly
+        * and lack of permission just means that we fall back to the
+        * in-core context value, not a denial.
+        */
+       error = secondary_ops->capable(current, CAP_MAC_ADMIN);
+       if (!error)
+               error = avc_has_perm_noaudit(tsec->sid, tsec->sid,
+                                            SECCLASS_CAPABILITY2,
+                                            CAPABILITY2__MAC_ADMIN,
+                                            0,
+                                            NULL);
+       if (!error)
+               error = security_sid_to_context_force(isec->sid, &context,
+                                                     &size);
+       else
+               error = security_sid_to_context(isec->sid, &context, &size);
        if (error)
                return error;
        error = size;
@@ -2755,7 +2850,7 @@ out_nofree:
 }
 
 static int selinux_inode_setsecurity(struct inode *inode, const char *name,
-                                     const void *value, size_t size, int flags)
+                                    const void *value, size_t size, int flags)
 {
        struct inode_security_struct *isec = inode->i_security;
        u32 newsid;
@@ -2767,7 +2862,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
        if (!value || !size)
                return -EACCES;
 
-       rc = security_context_to_sid((void*)value, size, &newsid);
+       rc = security_context_to_sid((void *)value, size, &newsid);
        if (rc)
                return rc;
 
@@ -2855,47 +2950,16 @@ static void selinux_file_free_security(struct file *file)
 static int selinux_file_ioctl(struct file *file, unsigned int cmd,
                              unsigned long arg)
 {
-       int error = 0;
-
-       switch (cmd) {
-               case FIONREAD:
-               /* fall through */
-               case FIBMAP:
-               /* fall through */
-               case FIGETBSZ:
-               /* fall through */
-               case EXT2_IOC_GETFLAGS:
-               /* fall through */
-               case EXT2_IOC_GETVERSION:
-                       error = file_has_perm(current, file, FILE__GETATTR);
-                       break;
-
-               case EXT2_IOC_SETFLAGS:
-               /* fall through */
-               case EXT2_IOC_SETVERSION:
-                       error = file_has_perm(current, file, FILE__SETATTR);
-                       break;
-
-               /* sys_ioctl() checks */
-               case FIONBIO:
-               /* fall through */
-               case FIOASYNC:
-                       error = file_has_perm(current, file, 0);
-                       break;
-
-               case KDSKBENT:
-               case KDSKBSENT:
-                       error = task_has_capability(current,CAP_SYS_TTY_CONFIG);
-                       break;
+       u32 av = 0;
 
-               /* default case assumes that the command will go
-                * to the file's ioctl() function.
-                */
-               default:
-                       error = file_has_perm(current, file, FILE__IOCTL);
+       if (_IOC_DIR(cmd) & _IOC_WRITE)
+               av |= FILE__WRITE;
+       if (_IOC_DIR(cmd) & _IOC_READ)
+               av |= FILE__READ;
+       if (!av)
+               av = FILE__IOCTL;
 
-       }
-       return error;
+       return file_has_perm(current, file, av);
 }
 
 static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
@@ -2934,7 +2998,7 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot,
                             unsigned long addr, unsigned long addr_only)
 {
        int rc = 0;
-       u32 sid = ((struct task_security_struct*)(current->security))->sid;
+       u32 sid = ((struct task_security_struct *)(current->security))->sid;
 
        if (addr < mmap_min_addr)
                rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT,
@@ -3003,39 +3067,39 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
        int err = 0;
 
        switch (cmd) {
-               case F_SETFL:
-                       if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
-                               err = -EINVAL;
-                               break;
-                       }
+       case F_SETFL:
+               if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
+                       err = -EINVAL;
+                       break;
+               }
 
-                       if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
-                               err = file_has_perm(current, file,FILE__WRITE);
-                               break;
-                       }
-                       /* fall through */
-               case F_SETOWN:
-               case F_SETSIG:
-               case F_GETFL:
-               case F_GETOWN:
-               case F_GETSIG:
-                       /* Just check FD__USE permission */
-                       err = file_has_perm(current, file, 0);
+               if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
+                       err = file_has_perm(current, file, FILE__WRITE);
                        break;
-               case F_GETLK:
-               case F_SETLK:
-               case F_SETLKW:
+               }
+               /* fall through */
+       case F_SETOWN:
+       case F_SETSIG:
+       case F_GETFL:
+       case F_GETOWN:
+       case F_GETSIG:
+               /* Just check FD__USE permission */
+               err = file_has_perm(current, file, 0);
+               break;
+       case F_GETLK:
+       case F_SETLK:
+       case F_SETLKW:
 #if BITS_PER_LONG == 32
-               case F_GETLK64:
-               case F_SETLK64:
-               case F_SETLKW64:
+       case F_GETLK64:
+       case F_SETLK64:
+       case F_SETLKW64:
 #endif
-                       if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
-                               err = -EINVAL;
-                               break;
-                       }
-                       err = file_has_perm(current, file, FILE__LOCK);
+               if (!file->f_path.dentry || !file->f_path.dentry->d_inode) {
+                       err = -EINVAL;
                        break;
+               }
+               err = file_has_perm(current, file, FILE__LOCK);
+               break;
        }
 
        return err;
@@ -3056,13 +3120,13 @@ static int selinux_file_set_fowner(struct file *file)
 static int selinux_file_send_sigiotask(struct task_struct *tsk,
                                       struct fown_struct *fown, int signum)
 {
-        struct file *file;
+       struct file *file;
        u32 perm;
        struct task_security_struct *tsec;
        struct file_security_struct *fsec;
 
        /* struct fown_struct is never outside the context of a struct file */
-        file = container_of(fown, struct file, f_owner);
+       file = container_of(fown, struct file, f_owner);
 
        tsec = tsk->security;
        fsec = file->f_security;
@@ -3164,7 +3228,7 @@ static int selinux_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
 
 static int selinux_task_post_setuid(uid_t id0, uid_t id1, uid_t id2, int flags)
 {
-       return secondary_ops->task_post_setuid(id0,id1,id2,flags);
+       return secondary_ops->task_post_setuid(id0, id1, id2, flags);
 }
 
 static int selinux_task_setgid(gid_t id0, gid_t id1, gid_t id2, int flags)
@@ -3208,7 +3272,7 @@ static int selinux_task_setnice(struct task_struct *p, int nice)
        if (rc)
                return rc;
 
-       return task_has_perm(current,p, PROCESS__SETSCHED);
+       return task_has_perm(current, p, PROCESS__SETSCHED);
 }
 
 static int selinux_task_setioprio(struct task_struct *p, int ioprio)
@@ -3278,9 +3342,6 @@ static int selinux_task_kill(struct task_struct *p, struct siginfo *info,
        if (rc)
                return rc;
 
-       if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
-               return 0;
-
        if (!sig)
                perm = PROCESS__SIGNULL; /* null signal; existence test */
        else
@@ -3297,12 +3358,13 @@ static int selinux_task_prctl(int option,
                              unsigned long arg2,
                              unsigned long arg3,
                              unsigned long arg4,
-                             unsigned long arg5)
+                             unsigned long arg5,
+                             long *rc_p)
 {
        /* The current prctl operations do not appear to require
           any SELinux controls since they merely observe or modify
           the state of the current process. */
-       return 0;
+       return secondary_ops->task_prctl(option, arg2, arg3, arg4, arg5, rc_p);
 }
 
 static int selinux_task_wait(struct task_struct *p)
@@ -3312,7 +3374,7 @@ static int selinux_task_wait(struct task_struct *p)
 
 static void selinux_task_reparent_to_init(struct task_struct *p)
 {
-       struct task_security_struct *tsec;
+       struct task_security_struct *tsec;
 
        secondary_ops->task_reparent_to_init(p);
 
@@ -3357,11 +3419,11 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
                *proto = ih->protocol;
 
        switch (ih->protocol) {
-        case IPPROTO_TCP: {
-               struct tcphdr _tcph, *th;
+       case IPPROTO_TCP: {
+               struct tcphdr _tcph, *th;
 
-               if (ntohs(ih->frag_off) & IP_OFFSET)
-                       break;
+               if (ntohs(ih->frag_off) & IP_OFFSET)
+                       break;
 
                offset += ihlen;
                th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
@@ -3371,23 +3433,23 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
                ad->u.net.sport = th->source;
                ad->u.net.dport = th->dest;
                break;
-        }
-        
-        case IPPROTO_UDP: {
-               struct udphdr _udph, *uh;
-               
-               if (ntohs(ih->frag_off) & IP_OFFSET)
-                       break;
-                       
+       }
+
+       case IPPROTO_UDP: {
+               struct udphdr _udph, *uh;
+
+               if (ntohs(ih->frag_off) & IP_OFFSET)
+                       break;
+
                offset += ihlen;
-               uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
+               uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
                if (uh == NULL)
-                       break;  
+                       break;
 
-               ad->u.net.sport = uh->source;
-               ad->u.net.dport = uh->dest;
-               break;
-        }
+               ad->u.net.sport = uh->source;
+               ad->u.net.dport = uh->dest;
+               break;
+       }
 
        case IPPROTO_DCCP: {
                struct dccp_hdr _dccph, *dh;
@@ -3403,11 +3465,11 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
                ad->u.net.sport = dh->dccph_sport;
                ad->u.net.dport = dh->dccph_dport;
                break;
-        }
+       }
 
-        default:
-               break;
-        }
+       default:
+               break;
+       }
 out:
        return ret;
 }
@@ -3442,7 +3504,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
 
        switch (nexthdr) {
        case IPPROTO_TCP: {
-               struct tcphdr _tcph, *th;
+               struct tcphdr _tcph, *th;
 
                th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
                if (th == NULL)
@@ -3475,7 +3537,7 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
                ad->u.net.sport = dh->dccph_sport;
                ad->u.net.dport = dh->dccph_dport;
                break;
-        }
+       }
 
        /* includes fragments */
        default:
@@ -3488,38 +3550,44 @@ out:
 #endif /* IPV6 */
 
 static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
-                            char **addrp, int src, u8 *proto)
+                            char **_addrp, int src, u8 *proto)
 {
-       int ret = 0;
+       char *addrp;
+       int ret;
 
        switch (ad->u.net.family) {
        case PF_INET:
                ret = selinux_parse_skb_ipv4(skb, ad, proto);
-               if (ret || !addrp)
-                       break;
-               *addrp = (char *)(src ? &ad->u.net.v4info.saddr :
-                                       &ad->u.net.v4info.daddr);
-               break;
+               if (ret)
+                       goto parse_error;
+               addrp = (char *)(src ? &ad->u.net.v4info.saddr :
+                                      &ad->u.net.v4info.daddr);
+               goto okay;
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        case PF_INET6:
                ret = selinux_parse_skb_ipv6(skb, ad, proto);
-               if (ret || !addrp)
-                       break;
-               *addrp = (char *)(src ? &ad->u.net.v6info.saddr :
-                                       &ad->u.net.v6info.daddr);
-               break;
+               if (ret)
+                       goto parse_error;
+               addrp = (char *)(src ? &ad->u.net.v6info.saddr :
+                                      &ad->u.net.v6info.daddr);
+               goto okay;
 #endif /* IPV6 */
        default:
-               break;
+               addrp = NULL;
+               goto okay;
        }
 
-       if (unlikely(ret))
-               printk(KERN_WARNING
-                      "SELinux: failure in selinux_parse_skb(),"
-                      " unable to parse packet\n");
-
+parse_error:
+       printk(KERN_WARNING
+              "SELinux: failure in selinux_parse_skb(),"
+              " unable to parse packet\n");
        return ret;
+
+okay:
+       if (_addrp)
+               *_addrp = addrp;
+       return 0;
 }
 
 /**
@@ -3573,7 +3641,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock,
        if (isec->sid == SECINITSID_KERNEL)
                goto out;
 
-       AVC_AUDIT_DATA_INIT(&ad,NET);
+       AVC_AUDIT_DATA_INIT(&ad, NET);
        ad.u.net.sk = sock->sk;
        err = avc_has_perm(tsec->sid, isec->sid, isec->sclass, perms, &ad);
 
@@ -3656,7 +3724,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                struct sockaddr_in6 *addr6 = NULL;
                unsigned short snum;
                struct sock *sk = sock->sk;
-               u32 sid, node_perm, addrlen;
+               u32 sid, node_perm;
 
                tsec = current->security;
                isec = SOCK_INODE(sock)->i_security;
@@ -3664,12 +3732,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                if (family == PF_INET) {
                        addr4 = (struct sockaddr_in *)address;
                        snum = ntohs(addr4->sin_port);
-                       addrlen = sizeof(addr4->sin_addr.s_addr);
                        addrp = (char *)&addr4->sin_addr.s_addr;
                } else {
                        addr6 = (struct sockaddr_in6 *)address;
                        snum = ntohs(addr6->sin6_port);
-                       addrlen = sizeof(addr6->sin6_addr.s6_addr);
                        addrp = (char *)&addr6->sin6_addr.s6_addr;
                }
 
@@ -3683,7 +3749,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                                                      snum, &sid);
                                if (err)
                                        goto out;
-                               AVC_AUDIT_DATA_INIT(&ad,NET);
+                               AVC_AUDIT_DATA_INIT(&ad, NET);
                                ad.u.net.sport = htons(snum);
                                ad.u.net.family = family;
                                err = avc_has_perm(isec->sid, sid,
@@ -3693,12 +3759,12 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                                        goto out;
                        }
                }
-               
-               switch(isec->sclass) {
+
+               switch (isec->sclass) {
                case SECCLASS_TCP_SOCKET:
                        node_perm = TCP_SOCKET__NODE_BIND;
                        break;
-                       
+
                case SECCLASS_UDP_SOCKET:
                        node_perm = UDP_SOCKET__NODE_BIND;
                        break;
@@ -3711,12 +3777,12 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                        node_perm = RAWIP_SOCKET__NODE_BIND;
                        break;
                }
-               
+
                err = sel_netnode_sid(addrp, family, &sid);
                if (err)
                        goto out;
-               
-               AVC_AUDIT_DATA_INIT(&ad,NET);
+
+               AVC_AUDIT_DATA_INIT(&ad, NET);
                ad.u.net.sport = htons(snum);
                ad.u.net.family = family;
 
@@ -3726,7 +3792,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
                        ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr);
 
                err = avc_has_perm(isec->sid, sid,
-                                  isec->sclass, node_perm, &ad);
+                                  isec->sclass, node_perm, &ad);
                if (err)
                        goto out;
        }
@@ -3775,7 +3841,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
                perm = (isec->sclass == SECCLASS_TCP_SOCKET) ?
                       TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT;
 
-               AVC_AUDIT_DATA_INIT(&ad,NET);
+               AVC_AUDIT_DATA_INIT(&ad, NET);
                ad.u.net.dport = htons(snum);
                ad.u.net.family = sk->sk_family;
                err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad);
@@ -3813,7 +3879,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock)
 }
 
 static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg,
-                                 int size)
+                                 int size)
 {
        int rc;
 
@@ -3840,7 +3906,7 @@ static int selinux_socket_getpeername(struct socket *sock)
        return socket_has_perm(current, sock, SOCKET__GETATTR);
 }
 
-static int selinux_socket_setsockopt(struct socket *sock,int level,int optname)
+static int selinux_socket_setsockopt(struct socket *sock, int level, int optname)
 {
        int err;
 
@@ -3879,7 +3945,7 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
        isec = SOCK_INODE(sock)->i_security;
        other_isec = SOCK_INODE(other)->i_security;
 
-       AVC_AUDIT_DATA_INIT(&ad,NET);
+       AVC_AUDIT_DATA_INIT(&ad, NET);
        ad.u.net.sk = other->sk;
 
        err = avc_has_perm(isec->sid, other_isec->sid,
@@ -3891,7 +3957,7 @@ static int selinux_socket_unix_stream_connect(struct socket *sock,
        /* connecting socket */
        ssec = sock->sk->sk_security;
        ssec->peer_sid = other_isec->sid;
-       
+
        /* server child socket */
        ssec = newsk->sk_security;
        ssec->peer_sid = isec->sid;
@@ -3911,7 +3977,7 @@ static int selinux_socket_unix_may_send(struct socket *sock,
        isec = SOCK_INODE(sock)->i_security;
        other_isec = SOCK_INODE(other)->i_security;
 
-       AVC_AUDIT_DATA_INIT(&ad,NET);
+       AVC_AUDIT_DATA_INIT(&ad, NET);
        ad.u.net.sk = other->sk;
 
        err = avc_has_perm(isec->sid, other_isec->sid,
@@ -3989,7 +4055,7 @@ static int selinux_sock_rcv_skb_iptables_compat(struct sock *sk,
        err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
        if (err)
                return err;
-       
+
        err = sel_netnode_sid(addrp, family, &node_sid);
        if (err)
                return err;
@@ -4140,7 +4206,7 @@ out_len:
                err = -EFAULT;
 
        kfree(scontext);
-out:   
+out:
        return err;
 }
 
@@ -4201,7 +4267,7 @@ static void selinux_sk_getsecid(struct sock *sk, u32 *secid)
        }
 }
 
-static void selinux_sock_graft(struct socksk, struct socket *parent)
+static void selinux_sock_graft(struct sock *sk, struct socket *parent)
 {
        struct inode_security_struct *isec = SOCK_INODE(parent)->i_security;
        struct sk_security_struct *sksec = sk->sk_security;
@@ -4278,13 +4344,13 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
        struct nlmsghdr *nlh;
        struct socket *sock = sk->sk_socket;
        struct inode_security_struct *isec = SOCK_INODE(sock)->i_security;
-       
+
        if (skb->len < NLMSG_SPACE(0)) {
                err = -EINVAL;
                goto out;
        }
        nlh = nlmsg_hdr(skb);
-       
+
        err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
        if (err) {
                if (err == -EINVAL) {
@@ -4410,7 +4476,7 @@ static int selinux_ip_postroute_iptables_compat(struct sock *sk,
                return err;
        err = avc_has_perm(sk_sid, if_sid, SECCLASS_NETIF, netif_perm, ad);
                return err;
-               
+
        err = sel_netnode_sid(addrp, family, &node_sid);
        if (err)
                return err;
@@ -4593,7 +4659,7 @@ static int selinux_netlink_recv(struct sk_buff *skb, int capability)
        ad.u.cap = capability;
 
        return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid,
-                           SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
+                           SECCLASS_CAPABILITY, CAP_TO_MASK(capability), &ad);
 }
 
 static int ipc_alloc_security(struct task_struct *task,
@@ -4685,7 +4751,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq)
        isec = msq->q_perm.security;
 
        AVC_AUDIT_DATA_INIT(&ad, IPC);
-       ad.u.ipc_id = msq->q_perm.key;
+       ad.u.ipc_id = msq->q_perm.key;
 
        rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_MSGQ,
                          MSGQ__CREATE, &ad);
@@ -4722,7 +4788,7 @@ static int selinux_msg_queue_msgctl(struct msg_queue *msq, int cmd)
        int err;
        int perms;
 
-       switch(cmd) {
+       switch (cmd) {
        case IPC_INFO:
        case MSG_INFO:
                /* No specific object, just general system-wide information. */
@@ -4806,7 +4872,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg,
        msec = msg->security;
 
        AVC_AUDIT_DATA_INIT(&ad, IPC);
-       ad.u.ipc_id = msq->q_perm.key;
+       ad.u.ipc_id = msq->q_perm.key;
 
        rc = avc_has_perm(tsec->sid, isec->sid,
                          SECCLASS_MSGQ, MSGQ__READ, &ad);
@@ -4832,7 +4898,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp)
        isec = shp->shm_perm.security;
 
        AVC_AUDIT_DATA_INIT(&ad, IPC);
-       ad.u.ipc_id = shp->shm_perm.key;
+       ad.u.ipc_id = shp->shm_perm.key;
 
        rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SHM,
                          SHM__CREATE, &ad);
@@ -4870,7 +4936,7 @@ static int selinux_shm_shmctl(struct shmid_kernel *shp, int cmd)
        int perms;
        int err;
 
-       switch(cmd) {
+       switch (cmd) {
        case IPC_INFO:
        case SHM_INFO:
                /* No specific object, just general system-wide information. */
@@ -4931,7 +4997,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma)
        isec = sma->sem_perm.security;
 
        AVC_AUDIT_DATA_INIT(&ad, IPC);
-       ad.u.ipc_id = sma->sem_perm.key;
+       ad.u.ipc_id = sma->sem_perm.key;
 
        rc = avc_has_perm(tsec->sid, isec->sid, SECCLASS_SEM,
                          SEM__CREATE, &ad);
@@ -4969,7 +5035,7 @@ static int selinux_sem_semctl(struct sem_array *sma, int cmd)
        int err;
        u32 perms;
 
-       switch(cmd) {
+       switch (cmd) {
        case IPC_INFO:
        case SEM_INFO:
                /* No specific object, just general system-wide information. */
@@ -5040,25 +5106,7 @@ static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
        *secid = isec->sid;
 }
 
-/* module stacking operations */
-static int selinux_register_security (const char *name, struct security_operations *ops)
-{
-       if (secondary_ops != original_ops) {
-               printk(KERN_ERR "%s:  There is already a secondary security "
-                      "module registered.\n", __func__);
-               return -EINVAL;
-       }
-
-       secondary_ops = ops;
-
-       printk(KERN_INFO "%s:  Registering secondary module %s\n",
-              __func__,
-              name);
-
-       return 0;
-}
-
-static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
+static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
 {
        if (inode)
                inode_doinit_with_dentry(inode, dentry);
@@ -5146,6 +5194,12 @@ static int selinux_setprocattr(struct task_struct *p,
                        size--;
                }
                error = security_context_to_sid(value, size, &sid);
+               if (error == -EINVAL && !strcmp(name, "fscreate")) {
+                       if (!capable(CAP_MAC_ADMIN))
+                               return error;
+                       error = security_context_to_sid_force(value, size,
+                                                             &sid);
+               }
                if (error)
                        return error;
        }
@@ -5173,24 +5227,33 @@ static int selinux_setprocattr(struct task_struct *p,
 
                if (sid == 0)
                        return -EINVAL;
-
-               /* Only allow single threaded processes to change context */
+               /*
+                * SELinux allows to change context in the following case only.
+                *  - Single threaded processes.
+                *  - Multi threaded processes intend to change its context into
+                *    more restricted domain (defined by TYPEBOUNDS statement).
+                */
                if (atomic_read(&p->mm->mm_users) != 1) {
                        struct task_struct *g, *t;
                        struct mm_struct *mm = p->mm;
                        read_lock(&tasklist_lock);
-                       do_each_thread(g, t)
+                       do_each_thread(g, t) {
                                if (t->mm == mm && t != p) {
                                        read_unlock(&tasklist_lock);
-                                       return -EPERM;
+                                       error = security_bounded_transition(tsec->sid, sid);
+                                       if (!error)
+                                               goto boundary_ok;
+
+                                       return error;
                                }
-                       while_each_thread(g, t);
+                       while_each_thread(g, t);
                        read_unlock(&tasklist_lock);
-                }
+               }
+boundary_ok:
 
                /* Check permissions for the transition. */
                error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
-                                    PROCESS__DYNTRANSITION, NULL);
+                                    PROCESS__DYNTRANSITION, NULL);
                if (error)
                        return error;
 
@@ -5198,7 +5261,7 @@ static int selinux_setprocattr(struct task_struct *p,
                   Otherwise, leave SID unchanged and fail. */
                task_lock(p);
                rcu_read_lock();
-               tracer = task_tracer_task(p);
+               tracer = tracehook_tracer_task(p);
                if (tracer != NULL) {
                        struct task_security_struct *ptsec = tracer->security;
                        u32 ptsid = ptsec->sid;
@@ -5218,8 +5281,7 @@ static int selinux_setprocattr(struct task_struct *p,
                        tsec->sid = sid;
                        task_unlock(p);
                }
-       }
-       else
+       } else
                return -EINVAL;
 
        return size;
@@ -5230,7 +5292,7 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
        return security_sid_to_context(secid, secdata, seclen);
 }
 
-static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
+static int selinux_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
 {
        return security_context_to_sid(secdata, seclen, secid);
 }
@@ -5292,12 +5354,27 @@ static int selinux_key_permission(key_ref_t key_ref,
                            SECCLASS_KEY, perm, NULL);
 }
 
+static int selinux_key_getsecurity(struct key *key, char **_buffer)
+{
+       struct key_security_struct *ksec = key->security;
+       char *context = NULL;
+       unsigned len;
+       int rc;
+
+       rc = security_sid_to_context(ksec->sid, &context, &len);
+       if (!rc)
+               rc = len;
+       *_buffer = context;
+       return rc;
+}
+
 #endif
 
 static struct security_operations selinux_ops = {
        .name =                         "selinux",
 
-       .ptrace =                       selinux_ptrace,
+       .ptrace_may_access =            selinux_ptrace_may_access,
+       .ptrace_traceme =               selinux_ptrace_traceme,
        .capget =                       selinux_capget,
        .capset_check =                 selinux_capset_check,
        .capset_set =                   selinux_capset_set,
@@ -5309,7 +5386,7 @@ static struct security_operations selinux_ops = {
        .vm_enough_memory =             selinux_vm_enough_memory,
 
        .netlink_send =                 selinux_netlink_send,
-        .netlink_recv =                        selinux_netlink_recv,
+       .netlink_recv =                 selinux_netlink_recv,
 
        .bprm_alloc_security =          selinux_bprm_alloc_security,
        .bprm_free_security =           selinux_bprm_free_security,
@@ -5322,13 +5399,13 @@ static struct security_operations selinux_ops = {
        .sb_alloc_security =            selinux_sb_alloc_security,
        .sb_free_security =             selinux_sb_free_security,
        .sb_copy_data =                 selinux_sb_copy_data,
-       .sb_kern_mount =                selinux_sb_kern_mount,
+       .sb_kern_mount =                selinux_sb_kern_mount,
+       .sb_show_options =              selinux_sb_show_options,
        .sb_statfs =                    selinux_sb_statfs,
        .sb_mount =                     selinux_mount,
        .sb_umount =                    selinux_umount,
-       .sb_get_mnt_opts =              selinux_get_mnt_opts,
        .sb_set_mnt_opts =              selinux_set_mnt_opts,
-       .sb_clone_mnt_opts =            selinux_sb_clone_mnt_opts,
+       .sb_clone_mnt_opts =            selinux_sb_clone_mnt_opts,
        .sb_parse_opts_str =            selinux_parse_opts_str,
 
 
@@ -5353,12 +5430,12 @@ static struct security_operations selinux_ops = {
        .inode_getxattr =               selinux_inode_getxattr,
        .inode_listxattr =              selinux_inode_listxattr,
        .inode_removexattr =            selinux_inode_removexattr,
-       .inode_getsecurity =            selinux_inode_getsecurity,
-       .inode_setsecurity =            selinux_inode_setsecurity,
-       .inode_listsecurity =           selinux_inode_listsecurity,
+       .inode_getsecurity =            selinux_inode_getsecurity,
+       .inode_setsecurity =            selinux_inode_setsecurity,
+       .inode_listsecurity =           selinux_inode_listsecurity,
        .inode_need_killpriv =          selinux_inode_need_killpriv,
        .inode_killpriv =               selinux_inode_killpriv,
-       .inode_getsecid =               selinux_inode_getsecid,
+       .inode_getsecid =               selinux_inode_getsecid,
 
        .file_permission =              selinux_file_permission,
        .file_alloc_security =          selinux_file_alloc_security,
@@ -5372,7 +5449,7 @@ static struct security_operations selinux_ops = {
        .file_send_sigiotask =          selinux_file_send_sigiotask,
        .file_receive =                 selinux_file_receive,
 
-       .dentry_open =                  selinux_dentry_open,
+       .dentry_open =                  selinux_dentry_open,
 
        .task_create =                  selinux_task_create,
        .task_alloc_security =          selinux_task_alloc_security,
@@ -5382,7 +5459,7 @@ static struct security_operations selinux_ops = {
        .task_setgid =                  selinux_task_setgid,
        .task_setpgid =                 selinux_task_setpgid,
        .task_getpgid =                 selinux_task_getpgid,
-       .task_getsid =                  selinux_task_getsid,
+       .task_getsid =                  selinux_task_getsid,
        .task_getsecid =                selinux_task_getsecid,
        .task_setgroups =               selinux_task_setgroups,
        .task_setnice =                 selinux_task_setnice,
@@ -5396,10 +5473,10 @@ static struct security_operations selinux_ops = {
        .task_wait =                    selinux_task_wait,
        .task_prctl =                   selinux_task_prctl,
        .task_reparent_to_init =        selinux_task_reparent_to_init,
-       .task_to_inode =                selinux_task_to_inode,
+       .task_to_inode =                selinux_task_to_inode,
 
        .ipc_permission =               selinux_ipc_permission,
-       .ipc_getsecid =                 selinux_ipc_getsecid,
+       .ipc_getsecid =                 selinux_ipc_getsecid,
 
        .msg_msg_alloc_security =       selinux_msg_msg_alloc_security,
        .msg_msg_free_security =        selinux_msg_msg_free_security,
@@ -5417,24 +5494,22 @@ static struct security_operations selinux_ops = {
        .shm_shmctl =                   selinux_shm_shmctl,
        .shm_shmat =                    selinux_shm_shmat,
 
-       .sem_alloc_security =           selinux_sem_alloc_security,
-       .sem_free_security =            selinux_sem_free_security,
+       .sem_alloc_security =           selinux_sem_alloc_security,
+       .sem_free_security =            selinux_sem_free_security,
        .sem_associate =                selinux_sem_associate,
        .sem_semctl =                   selinux_sem_semctl,
        .sem_semop =                    selinux_sem_semop,
 
-       .register_security =            selinux_register_security,
-
-       .d_instantiate =                selinux_d_instantiate,
+       .d_instantiate =                selinux_d_instantiate,
 
-       .getprocattr =                  selinux_getprocattr,
-       .setprocattr =                  selinux_setprocattr,
+       .getprocattr =                  selinux_getprocattr,
+       .setprocattr =                  selinux_setprocattr,
 
        .secid_to_secctx =              selinux_secid_to_secctx,
        .secctx_to_secid =              selinux_secctx_to_secid,
        .release_secctx =               selinux_release_secctx,
 
-        .unix_stream_connect =         selinux_socket_unix_stream_connect,
+       .unix_stream_connect =          selinux_socket_unix_stream_connect,
        .unix_may_send =                selinux_socket_unix_may_send,
 
        .socket_create =                selinux_socket_create,
@@ -5456,7 +5531,7 @@ static struct security_operations selinux_ops = {
        .sk_alloc_security =            selinux_sk_alloc_security,
        .sk_free_security =             selinux_sk_free_security,
        .sk_clone_security =            selinux_sk_clone_security,
-       .sk_getsecid =                  selinux_sk_getsecid,
+       .sk_getsecid =                  selinux_sk_getsecid,
        .sock_graft =                   selinux_sock_graft,
        .inet_conn_request =            selinux_inet_conn_request,
        .inet_csk_clone =               selinux_inet_csk_clone,
@@ -5471,15 +5546,16 @@ static struct security_operations selinux_ops = {
        .xfrm_state_alloc_security =    selinux_xfrm_state_alloc,
        .xfrm_state_free_security =     selinux_xfrm_state_free,
        .xfrm_state_delete_security =   selinux_xfrm_state_delete,
-       .xfrm_policy_lookup =           selinux_xfrm_policy_lookup,
+       .xfrm_policy_lookup =           selinux_xfrm_policy_lookup,
        .xfrm_state_pol_flow_match =    selinux_xfrm_state_pol_flow_match,
        .xfrm_decode_session =          selinux_xfrm_decode_session,
 #endif
 
 #ifdef CONFIG_KEYS
-       .key_alloc =                    selinux_key_alloc,
-       .key_free =                     selinux_key_free,
-       .key_permission =               selinux_key_permission,
+       .key_alloc =                    selinux_key_alloc,
+       .key_free =                     selinux_key_free,
+       .key_permission =               selinux_key_permission,
+       .key_getsecurity =              selinux_key_getsecurity,
 #endif
 
 #ifdef CONFIG_AUDIT
@@ -5517,25 +5593,16 @@ static __init int selinux_init(void)
                                            0, SLAB_PANIC, NULL);
        avc_init();
 
-       original_ops = secondary_ops = security_ops;
+       secondary_ops = security_ops;
        if (!secondary_ops)
-               panic ("SELinux: No initial security operations\n");
-       if (register_security (&selinux_ops))
+               panic("SELinux: No initial security operations\n");
+       if (register_security(&selinux_ops))
                panic("SELinux: Unable to register with kernel.\n");
 
-       if (selinux_enforcing) {
+       if (selinux_enforcing)
                printk(KERN_DEBUG "SELinux:  Starting in enforcing mode\n");
-       } else {
+       else
                printk(KERN_DEBUG "SELinux:  Starting in permissive mode\n");
-       }
-
-#ifdef CONFIG_KEYS
-       /* Add security information to initial keyrings */
-       selinux_key_alloc(&root_user_keyring, current,
-                         KEY_ALLOC_NOT_IN_QUOTA);
-       selinux_key_alloc(&root_session_keyring, current,
-                         KEY_ALLOC_NOT_IN_QUOTA);
-#endif
 
        return 0;
 }
@@ -5552,8 +5619,8 @@ next_sb:
        if (!list_empty(&superblock_security_head)) {
                struct superblock_security_struct *sbsec =
                                list_entry(superblock_security_head.next,
-                                          struct superblock_security_struct,
-                                          list);
+                                          struct superblock_security_struct,
+                                          list);
                struct super_block *sb = sbsec->sb;
                sb->s_count++;
                spin_unlock(&sb_security_lock);
@@ -5618,27 +5685,20 @@ static struct nf_hook_ops selinux_ipv6_ops[] = {
 static int __init selinux_nf_ip_init(void)
 {
        int err = 0;
-       u32 iter;
 
        if (!selinux_enabled)
                goto out;
 
        printk(KERN_DEBUG "SELinux:  Registering netfilter hooks\n");
 
-       for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) {
-               err = nf_register_hook(&selinux_ipv4_ops[iter]);
-               if (err)
-                       panic("SELinux: nf_register_hook for IPv4: error %d\n",
-                             err);
-       }
+       err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
+       if (err)
+               panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-       for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) {
-               err = nf_register_hook(&selinux_ipv6_ops[iter]);
-               if (err)
-                       panic("SELinux: nf_register_hook for IPv6: error %d\n",
-                             err);
-       }
+       err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
+       if (err)
+               panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
 #endif /* IPV6 */
 
 out:
@@ -5650,15 +5710,11 @@ __initcall(selinux_nf_ip_init);
 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
 static void selinux_nf_ip_exit(void)
 {
-       u32 iter;
-
        printk(KERN_DEBUG "SELinux:  Unregistering netfilter hooks\n");
 
-       for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++)
-               nf_unregister_hook(&selinux_ipv4_ops[iter]);
+       nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-       for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++)
-               nf_unregister_hook(&selinux_ipv6_ops[iter]);
+       nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
 #endif /* IPV6 */
 }
 #endif
@@ -5672,10 +5728,11 @@ static void selinux_nf_ip_exit(void)
 #endif /* CONFIG_NETFILTER */
 
 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
+static int selinux_disabled;
+
 int selinux_disable(void)
 {
        extern void exit_sel_fs(void);
-       static int selinux_disabled = 0;
 
        if (ss_initialized) {
                /* Not permitted after initial policy load. */