]> git.pld-linux.org Git - packages/kernel.git/blobdiff - kernel-apparmor.patch
- 4.9.136
[packages/kernel.git] / kernel-apparmor.patch
index 94ae2aa4f7592bf9b6a55574021d201ddb071591..9c0b815a6b50e354f3a18976f57741e2e08f7d3e 100644 (file)
-From 3f980257e048429a1f0a5dbce0b027a93c0781cc Mon Sep 17 00:00:00 2001
-From: John Johansen <john.johansen@canonical.com>
-Date: Wed, 4 Aug 2010 04:42:50 -0700
-Subject: [PATCH] AppArmor: security module v2.6 + compat patches as of 29-07-2010 (security-next)
+commit 09aa4788d6052c6dc423d939319334ebb5d00847
+Author: John Johansen <john.johansen@canonical.com>
+Date:   Mon Oct 4 15:03:36 2010 -0700
 
-AppArmor v2.6 module as synced to security-next 29-07-2010 backported to
-2.6.35 + AppArmor 2.4 compatibility patches.
+    UBUNTU: SAUCE: AppArmor: basic networking rules
+    
+    Base support for network mediation.
+    
+    Signed-off-by: John Johansen <john.johansen@canonical.com>
 
-Signed-off-by: John Johansen <john.johansen@canonical.com>
----
- Documentation/apparmor.txt                |   40 +
- Documentation/kernel-parameters.txt       |    8 +
- MAINTAINERS                               |    8 +
- include/linux/lsm_audit.h                 |   31 +
- security/Kconfig                          |    6 +
- security/Makefile                         |    2 +
- security/apparmor/.gitignore              |    5 +
- security/apparmor/Kconfig                 |   40 +
- security/apparmor/Makefile                |   30 +
- security/apparmor/apparmorfs-24.c         |  287 +++++++
- security/apparmor/apparmorfs.c            |  253 ++++++
- security/apparmor/audit.c                 |  215 ++++++
- security/apparmor/capability.c            |  141 ++++
- security/apparmor/context.c               |  216 ++++++
- security/apparmor/domain.c                |  823 ++++++++++++++++++++
- security/apparmor/file.c                  |  457 +++++++++++
- security/apparmor/include/apparmor.h      |   92 +++
- security/apparmor/include/apparmorfs.h    |   26 +
- security/apparmor/include/audit.h         |  123 +++
- security/apparmor/include/capability.h    |   45 ++
- security/apparmor/include/context.h       |  154 ++++
- security/apparmor/include/domain.h        |   36 +
- security/apparmor/include/file.h          |  217 ++++++
- security/apparmor/include/ipc.h           |   28 +
- security/apparmor/include/match.h         |  132 ++++
- security/apparmor/include/net.h           |   40 +
- security/apparmor/include/path.h          |   31 +
- security/apparmor/include/policy.h        |  308 ++++++++
- security/apparmor/include/policy_unpack.h |   20 +
- security/apparmor/include/procattr.h      |   26 +
- security/apparmor/include/resource.h      |   46 ++
- security/apparmor/include/sid.h           |   24 +
- security/apparmor/ipc.c                   |  114 +++
- security/apparmor/lib.c                   |  133 ++++
- security/apparmor/lsm.c                   | 1051 +++++++++++++++++++++++++
- security/apparmor/match.c                 |  370 +++++++++
- security/apparmor/net.c                   |  169 ++++
- security/apparmor/path.c                  |  235 ++++++
- security/apparmor/policy.c                | 1185 +++++++++++++++++++++++++++++
- security/apparmor/policy_unpack.c         |  740 ++++++++++++++++++
- security/apparmor/policy_unpack.c.rej     |   11 +
- security/apparmor/procattr.c              |  170 ++++
- security/apparmor/resource.c              |  134 ++++
- security/apparmor/sid.c                   |   55 ++
- 44 files changed, 8277 insertions(+), 0 deletions(-)
- create mode 100644 Documentation/apparmor.txt
- create mode 100644 security/apparmor/.gitignore
- create mode 100644 security/apparmor/Kconfig
- create mode 100644 security/apparmor/Makefile
- create mode 100644 security/apparmor/apparmorfs-24.c
- create mode 100644 security/apparmor/apparmorfs.c
- create mode 100644 security/apparmor/audit.c
- create mode 100644 security/apparmor/capability.c
- create mode 100644 security/apparmor/context.c
- create mode 100644 security/apparmor/domain.c
- create mode 100644 security/apparmor/file.c
- create mode 100644 security/apparmor/include/apparmor.h
- create mode 100644 security/apparmor/include/apparmorfs.h
- create mode 100644 security/apparmor/include/audit.h
- create mode 100644 security/apparmor/include/capability.h
- create mode 100644 security/apparmor/include/context.h
- create mode 100644 security/apparmor/include/domain.h
- create mode 100644 security/apparmor/include/file.h
- create mode 100644 security/apparmor/include/ipc.h
- create mode 100644 security/apparmor/include/match.h
- create mode 100644 security/apparmor/include/net.h
- create mode 100644 security/apparmor/include/path.h
- create mode 100644 security/apparmor/include/policy.h
- create mode 100644 security/apparmor/include/policy_unpack.h
- create mode 100644 security/apparmor/include/procattr.h
- create mode 100644 security/apparmor/include/resource.h
- create mode 100644 security/apparmor/include/sid.h
- create mode 100644 security/apparmor/ipc.c
- create mode 100644 security/apparmor/lib.c
- create mode 100644 security/apparmor/lsm.c
- create mode 100644 security/apparmor/match.c
- create mode 100644 security/apparmor/net.c
- create mode 100644 security/apparmor/path.c
- create mode 100644 security/apparmor/policy.c
- create mode 100644 security/apparmor/policy_unpack.c
- create mode 100644 security/apparmor/policy_unpack.c.rej
- create mode 100644 security/apparmor/procattr.c
- create mode 100644 security/apparmor/resource.c
- create mode 100644 security/apparmor/sid.c
-
-diff --git a/Documentation/apparmor.txt b/Documentation/apparmor.txt
-new file mode 100644
-index 0000000..6240438
---- /dev/null
-+++ b/Documentation/apparmor.txt
-@@ -0,0 +1,40 @@
-+--- What is AppArmor? ---
-+
-+AppArmor is MAC style security extension for the Linux kernel.  It implements
-+a task centered policy, with task "profiles" being created and loaded
-+from user space.  Tasks on the system that do not have a profile defined for
-+them run in an unconfined state which is equivalent to standard Linux DAC
-+permissions.
-+
-+--- How to enable/disable ---
-+
-+set CONFIG_SECURITY_APPARMOR=y
-+
-+If AppArmor should be selected as the default security module then
-+   set CONFIG_DEFAULT_SECURITY="apparmor"
-+   and CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1
-+
-+Build the kernel
-+
-+If AppArmor is not the default security module it can be enabled by passing
-+security=apparmor on the kernel's command line.
-+
-+If AppArmor is the default security module it can be disabled by passing
-+apparmor=0, security=XXXX (where XXX is valid security module), on the
-+kernel's command line
-+
-+For AppArmor to enforce any restrictions beyond standard Linux DAC permissions
-+policy must be loaded into the kernel from user space (see the Documentation
-+and tools links).
-+
-+--- Documentation ---
-+
-+Documentation can be found on the wiki.
-+
-+--- Links ---
-+
-+Mailing List - apparmor@lists.ubuntu.com
-+Wiki - http://apparmor.wiki.kernel.org/
-+User space tools - https://launchpad.net/apparmor
-+Kernel module - git://git.kernel.org/pub/scm/linux/kernel/git/jj/apparmor-dev.git
-+
-diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
-index 2b2407d..b61f89f 100644
---- a/Documentation/kernel-parameters.txt
-+++ b/Documentation/kernel-parameters.txt
-@@ -93,6 +93,7 @@ parameter is applicable:
-                       Documentation/scsi/.
-       SECURITY Different security models are enabled.
-       SELINUX SELinux support is enabled.
-+      APPARMOR AppArmor support is enabled.
-       SERIAL  Serial support is enabled.
-       SH      SuperH architecture is enabled.
-       SMP     The kernel is an SMP kernel.
-@@ -2312,6 +2313,13 @@ and is between 256 and 4096 characters. It is defined in the file
-                       If enabled at boot time, /selinux/disable can be used
-                       later to disable prior to initial policy load.
-+      apparmor=       [APPARMOR] Disable or enable AppArmor at boot time
-+                      Format: { "0" | "1" }
-+                      See security/apparmor/Kconfig help text
-+                      0 -- disable.
-+                      1 -- enable.
-+                      Default value is set via kernel config option.
-+
-       serialnumber    [BUGS=X86-32]
-       shapers=        [NET]
-diff --git a/MAINTAINERS b/MAINTAINERS
-index 02f75fc..a8d5851 100644
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -5061,6 +5061,14 @@ S:      Supported
- F:    include/linux/selinux*
- F:    security/selinux/
-+APPARMOR SECURITY MODULE
-+M:    John Johansen <john.johansen@canonical.com>
-+L:    apparmor@lists.ubuntu.com (subscribers-only, general discussion)
-+W:    apparmor.wiki.kernel.org
-+T:    git git://git.kernel.org/pub/scm/linux/kernel/git/jj/apparmor-dev.git
-+S:    Supported
-+F:    security/apparmor/
-+
- SENSABLE PHANTOM
- M:    Jiri Slaby <jirislaby@gmail.com>
- S:    Maintained
-diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
-index 6907251..3474e45 100644
---- a/include/linux/lsm_audit.h
-+++ b/include/linux/lsm_audit.h
-@@ -94,6 +94,37 @@ struct common_audit_data {
-                       int result;
-               } selinux_audit_data;
- #endif
-+#ifdef CONFIG_SECURITY_APPARMOR
-+              struct {
-+                      int error;
-+                      int op;
-+                      int type;
-+                      void *profile;
-+                      const char *name;
-+                      const char *info;
-+                      union {
-+                              void *target;
-+                              struct {
-+                                      long pos;
-+                                      void *target;
-+                              } iface;
-+                              struct {
-+                                      int rlim;
-+                                      unsigned long max;
-+                              } rlim;
-+                              struct {
-+                                      const char *target;
-+                                      u32 request;
-+                                      u32 denied;
-+                                      uid_t ouid;
-+                              } fs;
-+                              struct {
-+                                      int type, protocol;
-+                                      struct sock *sk;
-+                              } net;
-+                      };
-+              } apparmor_audit_data;
-+#endif
-       };
-       /* these callback will be implemented by a specific LSM */
-       void (*lsm_pre_audit)(struct audit_buffer *, void *);
-diff --git a/security/Kconfig b/security/Kconfig
-index 226b955..bd72ae6 100644
---- a/security/Kconfig
-+++ b/security/Kconfig
-@@ -140,6 +140,7 @@ config LSM_MMAP_MIN_ADDR
- source security/selinux/Kconfig
- source security/smack/Kconfig
- source security/tomoyo/Kconfig
-+source security/apparmor/Kconfig
- source security/integrity/ima/Kconfig
-@@ -148,6 +149,7 @@ choice
-       default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX
-       default DEFAULT_SECURITY_SMACK if SECURITY_SMACK
-       default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
-+      default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR
-       default DEFAULT_SECURITY_DAC
-       help
-@@ -163,6 +165,9 @@ choice
-       config DEFAULT_SECURITY_TOMOYO
-               bool "TOMOYO" if SECURITY_TOMOYO=y
+diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
+index 9cdec70..d5b291e 100644
+--- a/security/apparmor/.gitignore
++++ b/security/apparmor/.gitignore
+@@ -1,5 +1,6 @@
+ #
+ # Generated include files
+ #
++net_names.h
+ capability_names.h
+ rlim_names.h
+diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
+index d693df8..5dbb72f 100644
+--- a/security/apparmor/Makefile
++++ b/security/apparmor/Makefile
+@@ -4,10 +4,10 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
  
-+      config DEFAULT_SECURITY_APPARMOR
-+              bool "AppArmor" if SECURITY_APPARMOR=y
-+
-       config DEFAULT_SECURITY_DAC
-               bool "Unix Discretionary Access Controls"
+ apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
+               path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
+-              resource.o sid.o file.o
++              resource.o sid.o file.o net.o
+ apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
  
-@@ -173,6 +178,7 @@ config DEFAULT_SECURITY
-       default "selinux" if DEFAULT_SECURITY_SELINUX
-       default "smack" if DEFAULT_SECURITY_SMACK
-       default "tomoyo" if DEFAULT_SECURITY_TOMOYO
-+      default "apparmor" if DEFAULT_SECURITY_APPARMOR
-       default "" if DEFAULT_SECURITY_DAC
+-clean-files := capability_names.h rlim_names.h
++clean-files := capability_names.h rlim_names.h net_names.h
  
- endmenu
-diff --git a/security/Makefile b/security/Makefile
-index da20a19..8bb0fe9 100644
---- a/security/Makefile
-+++ b/security/Makefile
-@@ -6,6 +6,7 @@ obj-$(CONFIG_KEYS)                     += keys/
- subdir-$(CONFIG_SECURITY_SELINUX)     += selinux
- subdir-$(CONFIG_SECURITY_SMACK)               += smack
- subdir-$(CONFIG_SECURITY_TOMOYO)        += tomoyo
-+subdir-$(CONFIG_SECURITY_APPARMOR)    += apparmor
  
- # always enable default capabilities
- obj-y                                 += commoncap.o
-@@ -19,6 +20,7 @@ obj-$(CONFIG_SECURITY_SELINUX)               += selinux/built-in.o
- obj-$(CONFIG_SECURITY_SMACK)          += smack/built-in.o
- obj-$(CONFIG_AUDIT)                   += lsm_audit.o
- obj-$(CONFIG_SECURITY_TOMOYO)         += tomoyo/built-in.o
-+obj-$(CONFIG_SECURITY_APPARMOR)               += apparmor/built-in.o
- obj-$(CONFIG_CGROUP_DEVICE)           += device_cgroup.o
+ # Build a lower case string table of capability names
+@@ -25,6 +25,38 @@ cmd_make-caps = echo "static const char *const capability_names[] = {" > $@ ;\
+           -e 's/^\#define[ \t]+CAP_([A-Z0-9_]+)[ \t]+([0-9]+)/\L\1/p' | \
+            tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
  
- # Object integrity file lists
-diff --git a/security/apparmor/.gitignore b/security/apparmor/.gitignore
-new file mode 100644
-index 0000000..0a0a99f
---- /dev/null
-+++ b/security/apparmor/.gitignore
-@@ -0,0 +1,5 @@
-+#
-+# Generated include files
-+#
-+af_names.h
-+capability_names.h
-diff --git a/security/apparmor/Kconfig b/security/apparmor/Kconfig
-new file mode 100644
-index 0000000..fdf3022
---- /dev/null
-+++ b/security/apparmor/Kconfig
-@@ -0,0 +1,40 @@
-+config SECURITY_APPARMOR
-+      bool "AppArmor support"
-+      depends on SECURITY
-+      select AUDIT
-+      select SECURITY_PATH
-+      select SECURITYFS
-+      select SECURITY_NETWORK
-+      default n
-+      help
-+        This enables the AppArmor security module.
-+        Required userspace tools (if they are not included in your
-+        distribution) and further information may be found at
-+        http://apparmor.wiki.kernel.org
-+
-+        If you are unsure how to answer this question, answer N.
-+
-+config SECURITY_APPARMOR_BOOTPARAM_VALUE
-+      int "AppArmor boot parameter default value"
-+      depends on SECURITY_APPARMOR
-+      range 0 1
-+      default 1
-+      help
-+        This option sets the default value for the kernel parameter
-+        'apparmor', which allows AppArmor to be enabled or disabled
-+          at boot.  If this option is set to 0 (zero), the AppArmor
-+        kernel parameter will default to 0, disabling AppArmor at
-+        boot.  If this option is set to 1 (one), the AppArmor
-+        kernel parameter will default to 1, enabling AppArmor at
-+        boot.
-+
-+        If you are unsure how to answer this question, answer 1.
-+
-+config SECURITY_APPARMOR_COMPAT_24
-+      bool "Enable AppArmor 2.4 compatability"
-+      depends on SECURITY_APPARMOR
-+      default y
-+      help
-+        This option enables compatability with AppArmor 2.4.  It is
-+          recommended if compatability with older versions of AppArmor
-+          is desired.
-diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
-new file mode 100644
-index 0000000..e5e8968
---- /dev/null
-+++ b/security/apparmor/Makefile
-@@ -0,0 +1,30 @@
-+# Makefile for AppArmor Linux Security Module
++# Build a lower case string table of address family names
++# Transform lines from
++#    define AF_LOCAL  1       /* POSIX name for AF_UNIX       */
++#    #define AF_INET          2       /* Internet IP Protocol         */
++# to
++#    [1] = "local",
++#    [2] = "inet",
 +#
-+obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
-+
-+apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
-+              path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
-+              resource.o sid.o file.o net.o
-+
-+apparmor-$(CONFIG_SECURITY_APPARMOR_COMPAT_24) += apparmorfs-24.o
-+
-+clean-files: capability_names.h af_names.h
-+
-+quiet_cmd_make-caps = GEN     $@
-+cmd_make-caps = echo "static const char *capability_names[] = {" > $@ ; sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
-+
++# and build the securityfs entries for the mapping.
++# Transforms lines from
++#    #define AF_INET          2       /* Internet IP Protocol         */
++# to
++#    #define AA_FS_AF_MASK "local inet"
 +quiet_cmd_make-af = GEN     $@
-+cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ; sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@
-+
-+quiet_cmd_make-rlim = GEN     $@
-+cmd_make-rlim = echo "static const char *rlim_names[] = {" > $@ ; sed -n --e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+RLIMIT_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z >> $@ ; echo "};" >> $@ ; echo "static const int rlim_map[] = {" >> $@ ; sed -n -e "/AF_MAX/d" -e "s/^\# \\?define[ \\t]\\+\\(RLIMIT_[A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/\\1,/p" $< >> $@ ; echo "};" >> $@
-+
-+$(obj)/capability.o : $(obj)/capability_names.h
-+$(obj)/net.o : $(obj)/af_names.h
-+$(obj)/resource.o : $(obj)/rlim_names.h
-+$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
-+      $(call cmd,make-caps)
-+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
++cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
++      sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e \
++       's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
++      echo "};" >> $@ ;\
++      echo -n '\#define AA_FS_AF_MASK "' >> $@ ;\
++      sed -r -n 's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
++       $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
++
++# Build a lower case string table of sock type names
++# Transform lines from
++#    SOCK_STREAM      = 1,
++# to
++#    [1] = "stream",
++quiet_cmd_make-sock = GEN     $@
++cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
++      sed $^ >>$@ -r -n \
++      -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
++      echo "};" >> $@
+ # Build a lower case string table of rlimit names.
+ # Transforms lines from
+@@ -61,6 +93,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
+           tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
+ $(obj)/capability.o : $(obj)/capability_names.h
++$(obj)/net.o : $(obj)/net_names.h
+ $(obj)/resource.o : $(obj)/rlim_names.h
+ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
+                           $(src)/Makefile
+@@ -68,3 +101,8 @@ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
+ $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
+                     $(src)/Makefile
+       $(call cmd,make-rlim)
++$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
++                   $(srctree)/include/linux/net.h \
++                   $(src)/Makefile
 +      $(call cmd,make-af)
-+$(obj)/rlim_names.h : $(srctree)/include/asm-generic/resource.h
-+      $(call cmd,make-rlim)
-diff --git a/security/apparmor/apparmorfs-24.c b/security/apparmor/apparmorfs-24.c
++      $(call cmd,make-sock)
+diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
+index 729e595..181d961 100644
+--- a/security/apparmor/apparmorfs.c
++++ b/security/apparmor/apparmorfs.c
+@@ -807,6 +807,7 @@ static struct aa_fs_entry aa_fs_entry_features[] = {
+       AA_FS_DIR("policy",                     aa_fs_entry_policy),
+       AA_FS_DIR("domain",                     aa_fs_entry_domain),
+       AA_FS_DIR("file",                       aa_fs_entry_file),
++      AA_FS_DIR("network",                    aa_fs_entry_network),
+       AA_FS_FILE_U64("capability",            VFS_CAP_FLAGS_MASK),
+       AA_FS_DIR("rlimit",                     aa_fs_entry_rlimit),
+       AA_FS_DIR("caps",                       aa_fs_entry_caps),
+diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
+index ba3dfd1..5d3c419 100644
+--- a/security/apparmor/include/audit.h
++++ b/security/apparmor/include/audit.h
+@@ -125,6 +125,10 @@ struct apparmor_audit_data {
+                       u32 denied;
+                       kuid_t ouid;
+               } fs;
++              struct {
++                      int type, protocol;
++                      struct sock *sk;
++              } net;
+       };
+ };
+diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
 new file mode 100644
-index 0000000..dc8c744
+index 0000000..cb8a121
 --- /dev/null
-+++ b/security/apparmor/apparmorfs-24.c
-@@ -0,0 +1,287 @@
++++ b/security/apparmor/include/net.h
+@@ -0,0 +1,44 @@
 +/*
 + * AppArmor security module
 + *
-+ * This file contains AppArmor /sys/kernel/secrutiy/apparmor interface functions
++ * This file contains AppArmor network mediation definitions.
 + *
 + * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
++ * Copyright 2009-2012 Canonical Ltd.
 + *
 + * 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.
-+ *
-+ *
-+ * This file contain functions providing an interface for <= AppArmor 2.4
-+ * compatibility.  It is dependent on CONFIG_SECURITY_APPARMOR_COMPAT_24
-+ * being set (see Makefile).
 + */
 +
-+#include <linux/security.h>
-+#include <linux/vmalloc.h>
-+#include <linux/module.h>
-+#include <linux/seq_file.h>
-+#include <linux/uaccess.h>
-+#include <linux/namei.h>
++#ifndef __AA_NET_H
++#define __AA_NET_H
 +
-+#include "include/apparmor.h"
-+#include "include/audit.h"
-+#include "include/context.h"
-+#include "include/policy.h"
++#include <net/sock.h>
 +
++#include "apparmorfs.h"
 +
-+/* apparmor/matching */
-+static ssize_t aa_matching_read(struct file *file, char __user *buf,
-+                              size_t size, loff_t *ppos)
-+{
-+      const char matching[] = "pattern=aadfa audit perms=crwxamlk/ "
-+          "user::other";
++/* struct aa_net - network confinement data
++ * @allowed: basic network families permissions
++ * @audit_network: which network permissions to force audit
++ * @quiet_network: which network permissions to quiet rejects
++ */
++struct aa_net {
++      u16 allow[AF_MAX];
++      u16 audit[AF_MAX];
++      u16 quiet[AF_MAX];
++};
 +
-+      return simple_read_from_buffer(buf, size, ppos, matching,
-+                                     sizeof(matching) - 1);
-+}
++extern struct aa_fs_entry aa_fs_entry_network[];
 +
-+const struct file_operations aa_fs_matching_fops = {
-+      .read = aa_matching_read,
-+};
++extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
++                     int type, int protocol, struct sock *sk);
++extern int aa_revalidate_sk(int op, struct sock *sk);
 +
-+/* apparmor/features */
-+static ssize_t aa_features_read(struct file *file, char __user *buf,
-+                              size_t size, loff_t *ppos)
++static inline void aa_free_net_rules(struct aa_net *new)
 +{
-+      const char features[] = "file=3.1 capability=2.0 network=1.0 "
-+          "change_hat=1.5 change_profile=1.1 " "aanamespaces=1.1 rlimit=1.1";
-+
-+      return simple_read_from_buffer(buf, size, ppos, features,
-+                                     sizeof(features) - 1);
++      /* NOP */
 +}
 +
-+const struct file_operations aa_fs_features_fops = {
-+      .read = aa_features_read,
-+};
-+
-+/**
-+ * __next_namespace - find the next namespace to list
-+ * @root: root namespace to stop search at (NOT NULL)
-+ * @ns: current ns position (NOT NULL)
-+ *
-+ * Find the next namespace from @ns under @root and handle all locking needed
-+ * while switching current namespace.
-+ *
-+ * Returns: next namespace or NULL if at last namespace under @root
-+ * NOTE: will not unlock root->lock
-+ */
-+static struct aa_namespace *__next_namespace(struct aa_namespace *root,
-+                                           struct aa_namespace *ns)
++#endif /* __AA_NET_H */
+diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
+index 52275f0..4fc4dac 100644
+--- a/security/apparmor/include/policy.h
++++ b/security/apparmor/include/policy.h
+@@ -27,6 +27,7 @@
+ #include "capability.h"
+ #include "domain.h"
+ #include "file.h"
++#include "net.h"
+ #include "resource.h"
+ extern const char *const aa_profile_mode_names[];
+@@ -176,6 +177,7 @@ struct aa_replacedby {
+  * @policy: general match rules governing policy
+  * @file: The set of rules governing basic file access and domain transitions
+  * @caps: capabilities for the profile
++ * @net: network controls for the profile
+  * @rlimits: rlimits for the profile
+  *
+  * @dents: dentries for the profiles file entries in apparmorfs
+@@ -217,6 +219,7 @@ struct aa_profile {
+       struct aa_policydb policy;
+       struct aa_file_rules file;
+       struct aa_caps caps;
++      struct aa_net net;
+       struct aa_rlimit rlimits;
+       unsigned char *hash;
+diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
+index 41b8cb1..d96b5f7 100644
+--- a/security/apparmor/lsm.c
++++ b/security/apparmor/lsm.c
+@@ -32,6 +32,7 @@
+ #include "include/context.h"
+ #include "include/file.h"
+ #include "include/ipc.h"
++#include "include/net.h"
+ #include "include/path.h"
+ #include "include/policy.h"
+ #include "include/procattr.h"
+@@ -584,6 +585,104 @@ static int apparmor_task_setrlimit(struct task_struct *task,
+       return error;
+ }
++static int apparmor_socket_create(int family, int type, int protocol, int kern)
 +{
-+      struct aa_namespace *parent;
-+
-+      /* is next namespace a child */
-+      if (!list_empty(&ns->sub_ns)) {
-+              struct aa_namespace *next;
-+              next = list_first_entry(&ns->sub_ns, typeof(*ns), base.list);
-+              read_lock(&next->lock);
-+              return next;
-+      }
++      struct aa_profile *profile;
++      int error = 0;
 +
-+      /* check if the next ns is a sibling, parent, gp, .. */
-+      parent = ns->parent;
-+      while (parent) {
-+              read_unlock(&ns->lock);
-+              list_for_each_entry_continue(ns, &parent->sub_ns, base.list) {
-+                      read_lock(&ns->lock);
-+                      return ns;
-+              }
-+              if (parent == root)
-+                      return NULL;
-+              ns = parent;
-+              parent = parent->parent;
-+      }
++      if (kern)
++              return 0;
 +
-+      return NULL;
++      profile = __aa_current_profile();
++      if (!unconfined(profile))
++              error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
++                                  NULL);
++      return error;
 +}
 +
-+/**
-+ * __first_profile - find the first profile in a namespace
-+ * @root: namespace that is root of profiles being displayed (NOT NULL)
-+ * @ns: namespace to start in   (NOT NULL)
-+ *
-+ * Returns: unrefcounted profile or NULL if no profile
-+ */
-+static struct aa_profile *__first_profile(struct aa_namespace *root,
-+                                        struct aa_namespace *ns)
++static int apparmor_socket_bind(struct socket *sock,
++                              struct sockaddr *address, int addrlen)
 +{
-+      for ( ; ns; ns = __next_namespace(root, ns)) {
-+              if (!list_empty(&ns->base.profiles))
-+                      return list_first_entry(&ns->base.profiles,
-+                                              struct aa_profile, base.list);
-+      }
-+      return NULL;
++      struct sock *sk = sock->sk;
++
++      return aa_revalidate_sk(OP_BIND, sk);
 +}
 +
-+/**
-+ * __next_profile - step to the next profile in a profile tree
-+ * @profile: current profile in tree (NOT NULL)
-+ *
-+ * Perform a depth first taversal on the profile tree in a namespace
-+ *
-+ * Returns: next profile or NULL if done
-+ * Requires: profile->ns.lock to be held
-+ */
-+static struct aa_profile *__next_profile(struct aa_profile *p)
++static int apparmor_socket_connect(struct socket *sock,
++                                 struct sockaddr *address, int addrlen)
 +{
-+      struct aa_profile *parent;
-+      struct aa_namespace *ns = p->ns;
-+
-+      /* is next profile a child */
-+      if (!list_empty(&p->base.profiles))
-+              return list_first_entry(&p->base.profiles, typeof(*p),
-+                                      base.list);
-+
-+      /* is next profile a sibling, parent sibling, gp, subling, .. */
-+      parent = p->parent;
-+      while (parent) {
-+              list_for_each_entry_continue(p, &parent->base.profiles,
-+                                           base.list)
-+                              return p;
-+              p = parent;
-+              parent = parent->parent;
-+      }
-+
-+      /* is next another profile in the namespace */
-+      list_for_each_entry_continue(p, &ns->base.profiles, base.list)
-+              return p;
++      struct sock *sk = sock->sk;
 +
-+      return NULL;
++      return aa_revalidate_sk(OP_CONNECT, sk);
 +}
 +
-+/**
-+ * next_profile - step to the next profile in where ever it may be
-+ * @root: root namespace  (NOT NULL)
-+ * @profile: current profile  (NOT NULL)
-+ *
-+ * Returns: next profile or NULL if there isn't one
-+ */
-+static struct aa_profile *next_profile(struct aa_namespace *root,
-+                                     struct aa_profile *profile)
++static int apparmor_socket_listen(struct socket *sock, int backlog)
 +{
-+      struct aa_profile *next = __next_profile(profile);
-+      if (next)
-+              return next;
++      struct sock *sk = sock->sk;
 +
-+      /* finished all profiles in namespace move to next namespace */
-+      return __first_profile(root, __next_namespace(root, profile->ns));
++      return aa_revalidate_sk(OP_LISTEN, sk);
 +}
 +
-+/**
-+ * p_start - start a depth first traversal of profile tree
-+ * @f: seq_file to fill
-+ * @pos: current position
-+ *
-+ * Returns: first profile under current namespace or NULL if none found
-+ *
-+ * acquires first ns->lock
-+ */
-+static void *p_start(struct seq_file *f, loff_t *pos)
-+      __acquires(root->lock)
++static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
 +{
-+      struct aa_profile *profile = NULL;
-+      struct aa_namespace *root = aa_current_profile()->ns;
-+      loff_t l = *pos;
-+      f->private = aa_get_namespace(root);
-+
++      struct sock *sk = sock->sk;
 +
-+      /* find the first profile */
-+      read_lock(&root->lock);
-+      profile = __first_profile(root, root);
++      return aa_revalidate_sk(OP_ACCEPT, sk);
++}
 +
-+      /* skip to position */
-+      for (; profile && l > 0; l--)
-+              profile = next_profile(root, profile);
++static int apparmor_socket_sendmsg(struct socket *sock,
++                                 struct msghdr *msg, int size)
++{
++      struct sock *sk = sock->sk;
 +
-+      return profile;
++      return aa_revalidate_sk(OP_SENDMSG, sk);
 +}
 +
-+/**
-+ * p_next - read the next profile entry
-+ * @f: seq_file to fill
-+ * @p: profile previously returned
-+ * @pos: current position
-+ *
-+ * Returns: next profile after @p or NULL if none
-+ *
-+ * may acquire/release locks in namespace tree as necessary
-+ */
-+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
++static int apparmor_socket_recvmsg(struct socket *sock,
++                                 struct msghdr *msg, int size, int flags)
 +{
-+      struct aa_profile *profile = p;
-+      struct aa_namespace *root = f->private;
-+      (*pos)++;
++      struct sock *sk = sock->sk;
 +
-+      return next_profile(root, profile);
++      return aa_revalidate_sk(OP_RECVMSG, sk);
 +}
 +
-+/**
-+ * p_stop - stop depth first traversal
-+ * @f: seq_file we are filling
-+ * @p: the last profile writen
-+ *
-+ * Release all locking done by p_start/p_next on namespace tree
-+ */
-+static void p_stop(struct seq_file *f, void *p)
-+      __releases(root->lock)
++static int apparmor_socket_getsockname(struct socket *sock)
 +{
-+      struct aa_profile *profile = p;
-+      struct aa_namespace *root = f->private, *ns;
++      struct sock *sk = sock->sk;
 +
-+      if (profile) {
-+              for (ns = profile->ns; ns && ns != root; ns = ns->parent)
-+                      read_unlock(&ns->lock);
-+      }
-+      read_unlock(&root->lock);
-+      aa_put_namespace(root);
++      return aa_revalidate_sk(OP_GETSOCKNAME, sk);
 +}
 +
-+/**
-+ * seq_show_profile - show a profile entry
-+ * @f: seq_file to file
-+ * @p: current position (profile)    (NOT NULL)
-+ *
-+ * Returns: error on failure
-+ */
-+static int seq_show_profile(struct seq_file *f, void *p)
++static int apparmor_socket_getpeername(struct socket *sock)
 +{
-+      struct aa_profile *profile = (struct aa_profile *)p;
-+      struct aa_namespace *root = f->private;
-+
-+      if (profile->ns != root)
-+              seq_printf(f, ":%s://", aa_ns_name(root, profile->ns));
-+      seq_printf(f, "%s (%s)\n", profile->base.hname,
-+                 COMPLAIN_MODE(profile) ? "complain" : "enforce");
++      struct sock *sk = sock->sk;
 +
-+      return 0;
++      return aa_revalidate_sk(OP_GETPEERNAME, sk);
 +}
 +
-+static const struct seq_operations aa_fs_profiles_op = {
-+      .start = p_start,
-+      .next = p_next,
-+      .stop = p_stop,
-+      .show = seq_show_profile,
-+};
++static int apparmor_socket_getsockopt(struct socket *sock, int level,
++                                    int optname)
++{
++      struct sock *sk = sock->sk;
 +
-+static int profiles_open(struct inode *inode, struct file *file)
++      return aa_revalidate_sk(OP_GETSOCKOPT, sk);
++}
++
++static int apparmor_socket_setsockopt(struct socket *sock, int level,
++                                    int optname)
 +{
-+      return seq_open(file, &aa_fs_profiles_op);
++      struct sock *sk = sock->sk;
++
++      return aa_revalidate_sk(OP_SETSOCKOPT, sk);
 +}
 +
-+static int profiles_release(struct inode *inode, struct file *file)
++static int apparmor_socket_shutdown(struct socket *sock, int how)
 +{
-+      return seq_release(inode, file);
++      struct sock *sk = sock->sk;
++
++      return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
 +}
 +
-+const struct file_operations aa_fs_profiles_fops = {
-+      .open = profiles_open,
-+      .read = seq_read,
-+      .llseek = seq_lseek,
-+      .release = profiles_release,
-+};
-diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
+ static struct security_hook_list apparmor_hooks[] = {
+       LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
+       LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
+@@ -613,6 +712,19 @@ static struct security_hook_list apparmor_hooks[] = {
+       LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
+       LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
++      LSM_HOOK_INIT(socket_create, apparmor_socket_create),
++      LSM_HOOK_INIT(socket_bind, apparmor_socket_bind),
++      LSM_HOOK_INIT(socket_connect, apparmor_socket_connect),
++      LSM_HOOK_INIT(socket_listen, apparmor_socket_listen),
++      LSM_HOOK_INIT(socket_accept, apparmor_socket_accept),
++      LSM_HOOK_INIT(socket_sendmsg, apparmor_socket_sendmsg),
++      LSM_HOOK_INIT(socket_recvmsg, apparmor_socket_recvmsg),
++      LSM_HOOK_INIT(socket_getsockname, apparmor_socket_getsockname),
++      LSM_HOOK_INIT(socket_getpeername, apparmor_socket_getpeername),
++      LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt),
++      LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt),
++      LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown),
++
+       LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank),
+       LSM_HOOK_INIT(cred_free, apparmor_cred_free),
+       LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare),
+diff --git a/security/apparmor/net.c b/security/apparmor/net.c
 new file mode 100644
-index 0000000..0e27449
+index 0000000..003dd18
 --- /dev/null
-+++ b/security/apparmor/apparmorfs.c
-@@ -0,0 +1,253 @@
++++ b/security/apparmor/net.c
+@@ -0,0 +1,162 @@
 +/*
 + * AppArmor security module
 + *
-+ * This file contains AppArmor /sys/kernel/security/apparmor interface functions
++ * This file contains AppArmor network mediation
 + *
 + * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
++ * Copyright 2009-2012 Canonical Ltd.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License as
@@ -690,258 +354,458 @@ index 0000000..0e27449
 + * License.
 + */
 +
-+#include <linux/security.h>
-+#include <linux/vmalloc.h>
-+#include <linux/module.h>
-+#include <linux/seq_file.h>
-+#include <linux/uaccess.h>
-+#include <linux/namei.h>
-+
 +#include "include/apparmor.h"
-+#include "include/apparmorfs.h"
 +#include "include/audit.h"
 +#include "include/context.h"
++#include "include/net.h"
 +#include "include/policy.h"
 +
-+/**
-+ * aa_simple_write_to_buffer - common routine for getting policy from user
-+ * @op: operation doing the user buffer copy
-+ * @userbuf: user buffer to copy data from  (NOT NULL)
-+ * @alloc_size: size of user buffer
-+ * @copy_size: size of data to copy from user buffer
-+ * @pos: position write is at in the file (NOT NULL)
-+ *
-+ * Returns: kernel buffer containing copy of user buffer data or an
-+ *          ERR_PTR on failure.
-+ */
-+static char *aa_simple_write_to_buffer(int op, const char __user *userbuf,
-+                                     size_t alloc_size, size_t copy_size,
-+                                     loff_t *pos)
-+{
-+      char *data;
-+
-+      if (*pos != 0)
-+              /* only writes from pos 0, that is complete writes */
-+              return ERR_PTR(-ESPIPE);
++#include "net_names.h"
 +
-+      /*
-+       * Don't allow profile load/replace/remove from profiles that don't
-+       * have CAP_MAC_ADMIN
-+       */
-+      if (!aa_may_manage_policy(op))
-+              return ERR_PTR(-EACCES);
++struct aa_fs_entry aa_fs_entry_network[] = {
++      AA_FS_FILE_STRING("af_mask", AA_FS_AF_MASK),
++      { }
++};
 +
-+      /* freed by caller to simple_write_to_buffer */
-+      data = kvmalloc(alloc_size);
-+      if (data == NULL)
-+              return ERR_PTR(-ENOMEM);
++/* audit callback for net specific fields */
++static void audit_cb(struct audit_buffer *ab, void *va)
++{
++      struct common_audit_data *sa = va;
 +
-+      if (copy_from_user(data, userbuf, copy_size)) {
-+              kvfree(data);
-+              return ERR_PTR(-EFAULT);
++      audit_log_format(ab, " family=");
++      if (address_family_names[sa->u.net->family]) {
++              audit_log_string(ab, address_family_names[sa->u.net->family]);
++      } else {
++              audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
 +      }
-+
-+      return data;
++      audit_log_format(ab, " sock_type=");
++      if (sock_type_names[sa->aad->net.type]) {
++              audit_log_string(ab, sock_type_names[sa->aad->net.type]);
++      } else {
++              audit_log_format(ab, "\"unknown(%d)\"", sa->aad->net.type);
++      }
++      audit_log_format(ab, " protocol=%d", sa->aad->net.protocol);
 +}
 +
-+
-+/* .load file hook fn to load policy */
-+static ssize_t profile_load(struct file *f, const char __user *buf, size_t size,
-+                          loff_t *pos)
++/**
++ * audit_net - audit network access
++ * @profile: profile being enforced  (NOT NULL)
++ * @op: operation being checked
++ * @family: network family
++ * @type:   network type
++ * @protocol: network protocol
++ * @sk: socket auditing is being applied to
++ * @error: error code for failure else 0
++ *
++ * Returns: %0 or sa->error else other errorcode on failure
++ */
++static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
++                   int protocol, struct sock *sk, int error)
 +{
-+      char *data;
-+      ssize_t error;
-+
-+      data = aa_simple_write_to_buffer(OP_PROF_LOAD, buf, size, size, pos);
-+
-+      error = PTR_ERR(data);
-+      if (!IS_ERR(data)) {
-+              error = aa_replace_profiles(data, size, PROF_ADD);
-+              kvfree(data);
++      int audit_type = AUDIT_APPARMOR_AUTO;
++      struct common_audit_data sa;
++      struct apparmor_audit_data aad = { };
++      struct lsm_network_audit net = { };
++      if (sk) {
++              sa.type = LSM_AUDIT_DATA_NET;
++      } else {
++              sa.type = LSM_AUDIT_DATA_NONE;
 +      }
++      /* todo fill in socket addr info */
++      sa.aad = &aad;
++      sa.u.net = &net;
++      sa.aad->op = op,
++      sa.u.net->family = family;
++      sa.u.net->sk = sk;
++      sa.aad->net.type = type;
++      sa.aad->net.protocol = protocol;
++      sa.aad->error = error;
++
++      if (likely(!sa.aad->error)) {
++              u16 audit_mask = profile->net.audit[sa.u.net->family];
++              if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
++                         !(1 << sa.aad->net.type & audit_mask)))
++                      return 0;
++              audit_type = AUDIT_APPARMOR_AUDIT;
++      } else {
++              u16 quiet_mask = profile->net.quiet[sa.u.net->family];
++              u16 kill_mask = 0;
++              u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
 +
-+      return error;
-+}
-+
-+static const struct file_operations aa_fs_profile_load = {
-+      .write = profile_load
-+};
++              if (denied & kill_mask)
++                      audit_type = AUDIT_APPARMOR_KILL;
 +
-+/* .replace file hook fn to load and/or replace policy */
-+static ssize_t profile_replace(struct file *f, const char __user *buf,
-+                             size_t size, loff_t *pos)
-+{
-+      char *data;
-+      ssize_t error;
-+
-+      data = aa_simple_write_to_buffer(OP_PROF_REPL, buf, size, size, pos);
-+      error = PTR_ERR(data);
-+      if (!IS_ERR(data)) {
-+              error = aa_replace_profiles(data, size, PROF_REPLACE);
-+              kvfree(data);
++              if ((denied & quiet_mask) &&
++                  AUDIT_MODE(profile) != AUDIT_NOQUIET &&
++                  AUDIT_MODE(profile) != AUDIT_ALL)
++                      return COMPLAIN_MODE(profile) ? 0 : sa.aad->error;
 +      }
 +
-+      return error;
++      return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
 +}
 +
-+static const struct file_operations aa_fs_profile_replace = {
-+      .write = profile_replace
-+};
-+
-+/* .remove file hook fn to remove loaded policy */
-+static ssize_t profile_remove(struct file *f, const char __user *buf,
-+                            size_t size, loff_t *pos)
++/**
++ * aa_net_perm - very course network access check
++ * @op: operation being checked
++ * @profile: profile being enforced  (NOT NULL)
++ * @family: network family
++ * @type:   network type
++ * @protocol: network protocol
++ *
++ * Returns: %0 else error if permission denied
++ */
++int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
++              int protocol, struct sock *sk)
 +{
-+      char *data;
-+      ssize_t error;
-+
-+      /*
-+       * aa_remove_profile needs a null terminated string so 1 extra
-+       * byte is allocated and the copied data is null terminated.
-+       */
-+      data = aa_simple_write_to_buffer(OP_PROF_RM, buf, size + 1, size, pos);
-+
-+      error = PTR_ERR(data);
-+      if (!IS_ERR(data)) {
-+              data[size] = 0;
-+              error = aa_remove_profiles(data, size);
-+              kvfree(data);
-+      }
++      u16 family_mask;
++      int error;
 +
-+      return error;
-+}
++      if ((family < 0) || (family >= AF_MAX))
++              return -EINVAL;
 +
-+static const struct file_operations aa_fs_profile_remove = {
-+      .write = profile_remove
-+};
++      if ((type < 0) || (type >= SOCK_MAX))
++              return -EINVAL;
 +
-+/** Base file system setup **/
++      /* unix domain and netlink sockets are handled by ipc */
++      if (family == AF_UNIX || family == AF_NETLINK)
++              return 0;
 +
-+static struct dentry *aa_fs_dentry __initdata;
++      family_mask = profile->net.allow[family];
 +
-+static void __init aafs_remove(const char *name)
-+{
-+      struct dentry *dentry;
++      error = (family_mask & (1 << type)) ? 0 : -EACCES;
 +
-+      dentry = lookup_one_len(name, aa_fs_dentry, strlen(name));
-+      if (!IS_ERR(dentry)) {
-+              securityfs_remove(dentry);
-+              dput(dentry);
-+      }
++      return audit_net(profile, op, family, type, protocol, sk, error);
 +}
 +
 +/**
-+ * aafs_create - create an entry in the apparmor filesystem
-+ * @name: name of the entry (NOT NULL)
-+ * @mask: file permission mask of the file
-+ * @fops: file operations for the file (NOT NULL)
++ * aa_revalidate_sk - Revalidate access to a sock
++ * @op: operation being checked
++ * @sk: sock being revalidated  (NOT NULL)
 + *
-+ * Used aafs_remove to remove entries created with this fn.
++ * Returns: %0 else error if permission denied
 + */
-+static int __init aafs_create(const char *name, int mask,
-+                            const struct file_operations *fops)
++int aa_revalidate_sk(int op, struct sock *sk)
 +{
-+      struct dentry *dentry;
++      struct aa_profile *profile;
++      int error = 0;
 +
-+      dentry = securityfs_create_file(name, S_IFREG | mask, aa_fs_dentry,
-+                                      NULL, fops);
++      /* aa_revalidate_sk should not be called from interrupt context
++       * don't mediate these calls as they are not task related
++       */
++      if (in_interrupt())
++              return 0;
 +
-+      return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
-+}
++      profile = __aa_current_profile();
++      if (!unconfined(profile))
++              error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
++                                  sk->sk_protocol, sk);
 +
-+/**
-+ * aa_destroy_aafs - cleanup and free aafs
-+ *
-+ * releases dentries allocated by aa_create_aafs
-+ */
-+void __init aa_destroy_aafs(void)
++      return error;
++}
+diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
+index 179e68d..f1a8541 100644
+--- a/security/apparmor/policy.c
++++ b/security/apparmor/policy.c
+@@ -603,6 +603,7 @@ void aa_free_profile(struct aa_profile *profile)
+       aa_free_file_rules(&profile->file);
+       aa_free_cap_rules(&profile->caps);
++      aa_free_net_rules(&profile->net);
+       aa_free_rlimit_rules(&profile->rlimits);
+       kzfree(profile->dirname);
+diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
+index 1381206..7dc15ff 100644
+--- a/security/apparmor/policy_unpack.c
++++ b/security/apparmor/policy_unpack.c
+@@ -193,6 +193,19 @@ fail:
+       return 0;
+ }
++static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
 +{
-+      if (aa_fs_dentry) {
-+              aafs_remove(".remove");
-+              aafs_remove(".replace");
-+              aafs_remove(".load");
-+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
-+              aafs_remove("profiles");
-+              aafs_remove("matching");
-+              aafs_remove("features");
-+#endif
-+              securityfs_remove(aa_fs_dentry);
-+              aa_fs_dentry = NULL;
++      if (unpack_nameX(e, AA_U16, name)) {
++              if (!inbounds(e, sizeof(u16)))
++                      return 0;
++              if (data)
++                      *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
++              e->pos += sizeof(u16);
++              return 1;
 +      }
++      return 0;
 +}
 +
-+/**
-+ * aa_create_aafs - create the apparmor security filesystem
-+ *
-+ * dentries created here are released by aa_destroy_aafs
-+ *
-+ * Returns: error on failure
-+ */
-+int __init aa_create_aafs(void)
-+{
-+      int error;
-+
-+      if (!apparmor_initialized)
-+              return 0;
+ static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
+ {
+       if (unpack_nameX(e, AA_U32, name)) {
+@@ -476,6 +489,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
+ {
+       struct aa_profile *profile = NULL;
+       const char *name = NULL;
++      size_t size = 0;
+       int i, error = -EPROTO;
+       kernel_cap_t tmpcap;
+       u32 tmp;
+@@ -576,6 +590,38 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
+       if (!unpack_rlimits(e, profile))
+               goto fail;
++      size = unpack_array(e, "net_allowed_af");
++      if (size) {
 +
-+      if (aa_fs_dentry) {
-+              AA_ERROR("%s: AppArmor securityfs already exists\n", __func__);
-+              return -EEXIST;
++              for (i = 0; i < size; i++) {
++                      /* discard extraneous rules that this kernel will
++                       * never request
++                       */
++                      if (i >= AF_MAX) {
++                              u16 tmp;
++                              if (!unpack_u16(e, &tmp, NULL) ||
++                                  !unpack_u16(e, &tmp, NULL) ||
++                                  !unpack_u16(e, &tmp, NULL))
++                                      goto fail;
++                              continue;
++                      }
++                      if (!unpack_u16(e, &profile->net.allow[i], NULL))
++                              goto fail;
++                      if (!unpack_u16(e, &profile->net.audit[i], NULL))
++                              goto fail;
++                      if (!unpack_u16(e, &profile->net.quiet[i], NULL))
++                              goto fail;
++              }
++              if (!unpack_nameX(e, AA_ARRAYEND, NULL))
++                      goto fail;
 +      }
++      /*
++       * allow unix domain and netlink sockets they are handled
++       * by IPC
++       */
++      profile->net.allow[AF_UNIX] = 0xffff;
++      profile->net.allow[AF_NETLINK] = 0xffff;
 +
-+      aa_fs_dentry = securityfs_create_dir("apparmor", NULL);
-+      if (IS_ERR(aa_fs_dentry)) {
-+              error = PTR_ERR(aa_fs_dentry);
-+              aa_fs_dentry = NULL;
-+              goto error;
-+      }
-+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
-+      error = aafs_create("matching", 0444, &aa_fs_matching_fops);
-+      if (error)
-+              goto error;
-+      error = aafs_create("features", 0444, &aa_fs_features_fops);
-+      if (error)
-+              goto error;
-+#endif
-+      error = aafs_create("profiles", 0440, &aa_fs_profiles_fops);
-+      if (error)
-+              goto error;
-+      error = aafs_create(".load", 0640, &aa_fs_profile_load);
-+      if (error)
-+              goto error;
-+      error = aafs_create(".replace", 0640, &aa_fs_profile_replace);
-+      if (error)
-+              goto error;
-+      error = aafs_create(".remove", 0640, &aa_fs_profile_remove);
-+      if (error)
-+              goto error;
+       if (unpack_nameX(e, AA_STRUCT, "policydb")) {
+               /* generic policy dfa - optional and may be NULL */
+               profile->policy.dfa = unpack_dfa(e);
+
+commit f5c5644745201b5b7d398e841e5045d0a5d14b18
+Author: John Johansen <john.johansen@canonical.com>
+Date:   Fri Jun 29 17:34:00 2012 -0700
+
+    apparmor: Fix quieting of audit messages for network mediation
+    
+    If a profile specified a quieting of network denials for a given rule by
+    either the quiet or deny rule qualifiers, the resultant quiet mask for
+    denied requests was applied incorrectly, resulting in two potential bugs.
+    1. The misapplied quiet mask would prevent denials from being correctly
+       tested against the kill mask/mode. Thus network access requests that
+       should have resulted in the application being killed did not.
+    
+    2. The actual quieting of the denied network request was not being applied.
+       This would result in network rejections always being logged even when
+       they had been specifically marked as quieted.
+    
+    Signed-off-by: John Johansen <john.johansen@canonical.com>
+
+diff --git a/security/apparmor/net.c b/security/apparmor/net.c
+index 003dd18..6e6e5c9 100644
+--- a/security/apparmor/net.c
++++ b/security/apparmor/net.c
+@@ -88,7 +88,7 @@ static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
+       } else {
+               u16 quiet_mask = profile->net.quiet[sa.u.net->family];
+               u16 kill_mask = 0;
+-              u16 denied = (1 << sa.aad->net.type) & ~quiet_mask;
++              u16 denied = (1 << sa.aad->net.type);
+               if (denied & kill_mask)
+                       audit_type = AUDIT_APPARMOR_KILL;
+
+commit 0269f1631e1496798e5b0a319ff05b1133cfeaa3
+Author: John Johansen <john.johansen@canonical.com>
+Date:   Wed May 16 10:58:05 2012 -0700
+
+    UBUNTU: SAUCE: apparmor: Add the ability to mediate mount
+    
+    Add the ability for apparmor to do mediation of mount operations. Mount
+    rules require an updated apparmor_parser (2.8 series) for policy compilation.
+    
+    The basic form of the rules are.
+    
+      [audit] [deny] mount [conds]* [device] [ -> [conds] path],
+      [audit] [deny] remount [conds]* [path],
+      [audit] [deny] umount [conds]* [path],
+      [audit] [deny] pivotroot [oldroot=<value>] <path>
+    
+      remount is just a short cut for mount options=remount
+    
+      where [conds] can be
+        fstype=<expr>
+        options=<expr>
+    
+    Example mount commands
+      mount,                # allow all mounts, but not umount or pivotroot
+    
+      mount fstype=procfs,  # allow mounting procfs anywhere
+    
+      mount options=(bind, ro) /foo -> /bar,  # readonly bind mount
+    
+      mount /dev/sda -> /mnt,
+    
+      mount /dev/sd** -> /mnt/**,
+    
+      mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) -> /mnt/
+    
+      umount,
+    
+      umount /m*,
+    
+    See the apparmor userspace for full documentation
+    
+    Signed-off-by: John Johansen <john.johansen@canonical.com>
+    Acked-by: Kees Cook <kees@ubuntu.com>
+
+diff --git a/security/apparmor/Makefile b/security/apparmor/Makefile
+index 5dbb72f..89b3445 100644
+--- a/security/apparmor/Makefile
++++ b/security/apparmor/Makefile
+@@ -4,7 +4,7 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
+ apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
+               path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
+-              resource.o sid.o file.o net.o
++              resource.o sid.o file.o net.o mount.o
+ apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
+ clean-files := capability_names.h rlim_names.h net_names.h
+diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
+index 181d961..5fb67f6 100644
+--- a/security/apparmor/apparmorfs.c
++++ b/security/apparmor/apparmorfs.c
+@@ -800,7 +800,18 @@ static struct aa_fs_entry aa_fs_entry_domain[] = {
+ static struct aa_fs_entry aa_fs_entry_policy[] = {
+       AA_FS_FILE_BOOLEAN("set_load",          1),
+-      {}
++      { }
++};
 +
-+      /* TODO: add support for apparmorfs_null and apparmorfs_mnt */
++static struct aa_fs_entry aa_fs_entry_mount[] = {
++      AA_FS_FILE_STRING("mask", "mount umount"),
++      { }
++};
 +
-+      /* Report that AppArmor fs is enabled */
-+      aa_info_message("AppArmor Filesystem Enabled");
-+      return 0;
++static struct aa_fs_entry aa_fs_entry_namespaces[] = {
++      AA_FS_FILE_BOOLEAN("profile",           1),
++      AA_FS_FILE_BOOLEAN("pivot_root",        1),
++      { }
+ };
+ static struct aa_fs_entry aa_fs_entry_features[] = {
+@@ -808,6 +819,8 @@ static struct aa_fs_entry aa_fs_entry_features[] = {
+       AA_FS_DIR("domain",                     aa_fs_entry_domain),
+       AA_FS_DIR("file",                       aa_fs_entry_file),
+       AA_FS_DIR("network",                    aa_fs_entry_network),
++      AA_FS_DIR("mount",                      aa_fs_entry_mount),
++      AA_FS_DIR("namespaces",                 aa_fs_entry_namespaces),
+       AA_FS_FILE_U64("capability",            VFS_CAP_FLAGS_MASK),
+       AA_FS_DIR("rlimit",                     aa_fs_entry_rlimit),
+       AA_FS_DIR("caps",                       aa_fs_entry_caps),
+diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
+index 3a7f1da..c2a8b8a 100644
+--- a/security/apparmor/audit.c
++++ b/security/apparmor/audit.c
+@@ -44,6 +44,10 @@ const char *const op_table[] = {
+       "file_mmap",
+       "file_mprotect",
++      "pivotroot",
++      "mount",
++      "umount",
 +
-+error:
-+      aa_destroy_aafs();
-+      AA_ERROR("Error creating AppArmor securityfs\n");
-+      return error;
-+}
+       "create",
+       "post_create",
+       "bind",
+diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
+index fc3036b..f2a83b4 100644
+--- a/security/apparmor/domain.c
++++ b/security/apparmor/domain.c
+@@ -236,7 +236,7 @@ static const char *next_name(int xtype, const char *name)
+  *
+  * Returns: refcounted profile, or NULL on failure (MAYBE NULL)
+  */
+-static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
++struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
+ {
+       struct aa_profile *new_profile = NULL;
+       struct aa_namespace *ns = profile->ns;
+diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
+index 5d721e9..b57da7b 100644
+--- a/security/apparmor/include/apparmor.h
++++ b/security/apparmor/include/apparmor.h
+@@ -30,8 +30,9 @@
+ #define AA_CLASS_NET          4
+ #define AA_CLASS_RLIMITS      5
+ #define AA_CLASS_DOMAIN               6
++#define AA_CLASS_MOUNT                7
+-#define AA_CLASS_LAST         AA_CLASS_DOMAIN
++#define AA_CLASS_LAST         AA_CLASS_MOUNT
+ /* Control parameters settable through module/boot flags */
+ extern enum audit_mode aa_g_audit;
+diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
+index 5d3c419..b9f1d57 100644
+--- a/security/apparmor/include/audit.h
++++ b/security/apparmor/include/audit.h
+@@ -72,6 +72,10 @@ enum aa_ops {
+       OP_FMMAP,
+       OP_FMPROT,
++      OP_PIVOTROOT,
++      OP_MOUNT,
++      OP_UMOUNT,
++
+       OP_CREATE,
+       OP_POST_CREATE,
+       OP_BIND,
+@@ -120,6 +124,13 @@ struct apparmor_audit_data {
+                       unsigned long max;
+               } rlim;
+               struct {
++                      const char *src_name;
++                      const char *type;
++                      const char *trans;
++                      const char *data;
++                      unsigned long flags;
++              } mnt;
++              struct {
+                       const char *target;
+                       u32 request;
+                       u32 denied;
+diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
+index de04464..a3f70c5 100644
+--- a/security/apparmor/include/domain.h
++++ b/security/apparmor/include/domain.h
+@@ -23,6 +23,8 @@ struct aa_domain {
+       char **table;
+ };
++struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex);
 +
-+fs_initcall(aa_create_aafs);
-diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
+ int apparmor_bprm_set_creds(struct linux_binprm *bprm);
+ int apparmor_bprm_secureexec(struct linux_binprm *bprm);
+ void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
+diff --git a/security/apparmor/include/mount.h b/security/apparmor/include/mount.h
 new file mode 100644
-index 0000000..96502b2
+index 0000000..a43b1d6
 --- /dev/null
-+++ b/security/apparmor/audit.c
-@@ -0,0 +1,215 @@
++++ b/security/apparmor/include/mount.h
+@@ -0,0 +1,54 @@
 +/*
 + * AppArmor security module
 + *
-+ * This file contains AppArmor auditing functions
++ * This file contains AppArmor file mediation function definitions.
 + *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
++ * Copyright 2012 Canonical Ltd.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License as
@@ -949,220 +813,145 @@ index 0000000..96502b2
 + * License.
 + */
 +
-+#include <linux/audit.h>
-+#include <linux/socket.h>
++#ifndef __AA_MOUNT_H
++#define __AA_MOUNT_H
 +
-+#include "include/apparmor.h"
-+#include "include/audit.h"
-+#include "include/policy.h"
++#include <linux/fs.h>
++#include <linux/path.h>
 +
-+const char *op_table[] = {
-+      "null",
-+
-+      "sysctl",
-+      "capable",
-+
-+      "unlink",
-+      "mkdir",
-+      "rmdir",
-+      "mknod",
-+      "truncate",
-+      "link",
-+      "symlink",
-+      "rename_src",
-+      "rename_dest",
-+      "chmod",
-+      "chown",
-+      "getattr",
-+      "open",
-+
-+      "file_perm",
-+      "file_lock",
-+      "file_mmap",
-+      "file_mprotect",
-+
-+      "create",
-+      "post_create",
-+      "bind",
-+      "connect",
-+      "listen",
-+      "accept",
-+      "sendmsg",
-+      "recvmsg",
-+      "getsockname",
-+      "getpeername",
-+      "getsockopt",
-+      "setsockopt",
-+      "socket_shutdown",
-+
-+      "ptrace",
-+
-+      "exec",
-+      "change_hat",
-+      "change_profile",
-+      "change_onexec",
-+
-+      "setprocattr",
-+      "setrlimit",
-+
-+      "profile_replace",
-+      "profile_load",
-+      "profile_remove"
-+};
++#include "domain.h"
++#include "policy.h"
 +
-+const char *audit_mode_names[] = {
-+      "normal",
-+      "quiet_denied",
-+      "quiet",
-+      "noquiet",
-+      "all"
-+};
++/* mount perms */
++#define AA_MAY_PIVOTROOT      0x01
++#define AA_MAY_MOUNT          0x02
++#define AA_MAY_UMOUNT         0x04
++#define AA_AUDIT_DATA         0x40
++#define AA_CONT_MATCH         0x40
 +
-+static char *aa_audit_type[] = {
-+      "AUDIT",
-+      "ALLOWED",
-+      "DENIED",
-+      "HINT",
-+      "STATUS",
-+      "ERROR",
-+      "KILLED"
-+};
++#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
 +
-+/*
-+ * Currently AppArmor auditing is fed straight into the audit framework.
-+ *
-+ * TODO:
-+ * netlink interface for complain mode
-+ * user auditing, - send user auditing to netlink interface
-+ * system control of whether user audit messages go to system log
-+ */
++int aa_remount(struct aa_profile *profile, const struct path *path,
++             unsigned long flags, void *data);
 +
-+/**
-+ * audit_base - core AppArmor function.
-+ * @ab: audit buffer to fill (NOT NULL)
-+ * @ca: audit structure containing data to audit (NOT NULL)
-+ *
-+ * Record common AppArmor audit data from @sa
-+ */
-+static void audit_pre(struct audit_buffer *ab, void *ca)
-+{
-+      struct common_audit_data *sa = ca;
-+      struct task_struct *tsk = sa->tsk ? sa->tsk : current;
++int aa_bind_mount(struct aa_profile *profile, const struct path *path,
++                const char *old_name, unsigned long flags);
 +
-+      if (aa_g_audit_header) {
-+              audit_log_format(ab, "apparmor=");
-+              audit_log_string(ab, aa_audit_type[sa->aad.type]);
-+      }
 +
-+      if (sa->aad.op) {
-+              audit_log_format(ab, " operation=");
-+              audit_log_string(ab, op_table[sa->aad.op]);
-+      }
++int aa_mount_change_type(struct aa_profile *profile, const struct path *path,
++                       unsigned long flags);
 +
-+      if (sa->aad.info) {
-+              audit_log_format(ab, " info=");
-+              audit_log_string(ab, sa->aad.info);
-+              if (sa->aad.error)
-+                      audit_log_format(ab, " error=%d", sa->aad.error);
-+      }
++int aa_move_mount(struct aa_profile *profile, const struct path *path,
++                const char *old_name);
 +
-+      if (sa->aad.profile) {
-+              struct aa_profile *profile = sa->aad.profile;
-+              pid_t pid;
-+              rcu_read_lock();
-+              pid = tsk->real_parent->pid;
-+              rcu_read_unlock();
-+              audit_log_format(ab, " parent=%d", pid);
-+              if (profile->ns != root_ns) {
-+                      audit_log_format(ab, " namespace=");
-+                      audit_log_untrustedstring(ab, profile->ns->base.hname);
-+              }
-+              audit_log_format(ab, " profile=");
-+              audit_log_untrustedstring(ab, profile->base.hname);
-+      }
++int aa_new_mount(struct aa_profile *profile, const char *dev_name,
++               const struct path *path, const char *type, unsigned long flags,
++               void *data);
 +
-+      if (sa->aad.name) {
-+              audit_log_format(ab, " name=");
-+              audit_log_untrustedstring(ab, sa->aad.name);
-+      }
-+}
++int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags);
 +
-+/**
-+ * aa_audit_msg - Log a message to the audit subsystem
-+ * @sa: audit event structure (NOT NULL)
-+ * @cb: optional callback fn for type specific fields (MAYBE NULL)
-+ */
-+void aa_audit_msg(int type, struct common_audit_data *sa,
-+                void (*cb) (struct audit_buffer *, void *))
-+{
-+      sa->aad.type = type;
-+      sa->lsm_pre_audit = audit_pre;
-+      sa->lsm_post_audit = cb;
-+      common_lsm_audit(sa);
-+}
++int aa_pivotroot(struct aa_profile *profile, const struct path *old_path,
++               const struct path *new_path);
 +
-+/**
-+ * aa_audit - Log a profile based audit event to the audit subsystem
-+ * @type: audit type for the message
-+ * @profile: profile to check against (NOT NULL)
-+ * @gfp: allocation flags to use
-+ * @sa: audit event (NOT NULL)
-+ * @cb: optional callback fn for type specific fields (MAYBE NULL)
-+ *
-+ * Handle default message switching based off of audit mode flags
-+ *
-+ * Returns: error on failure
-+ */
-+int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
-+           struct common_audit_data *sa,
-+           void (*cb) (struct audit_buffer *, void *))
++#endif /* __AA_MOUNT_H */
+diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
+index d96b5f7..7a02376 100644
+--- a/security/apparmor/lsm.c
++++ b/security/apparmor/lsm.c
+@@ -36,6 +36,7 @@
+ #include "include/path.h"
+ #include "include/policy.h"
+ #include "include/procattr.h"
++#include "include/mount.h"
+ /* Flag indicating whether initialization completed */
+ int apparmor_initialized __initdata;
+@@ -469,6 +470,61 @@ static int apparmor_file_mprotect(struct vm_area_struct *vma,
+                          !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
+ }
++static int apparmor_sb_mount(const char *dev_name, const struct path *path,
++                           const char *type, unsigned long flags, void *data)
 +{
-+      BUG_ON(!profile);
-+
-+      if (type == AUDIT_APPARMOR_AUTO) {
-+              if (likely(!sa->aad.error)) {
-+                      if (AUDIT_MODE(profile) != AUDIT_ALL)
-+                              return 0;
-+                      type = AUDIT_APPARMOR_AUDIT;
-+              } else if (COMPLAIN_MODE(profile))
-+                      type = AUDIT_APPARMOR_ALLOWED;
++      struct aa_profile *profile;
++      int error = 0;
++
++      /* Discard magic */
++      if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
++              flags &= ~MS_MGC_MSK;
++
++      flags &= ~AA_MS_IGNORE_MASK;
++
++      profile = __aa_current_profile();
++      if (!unconfined(profile)) {
++              if (flags & MS_REMOUNT)
++                      error = aa_remount(profile, path, flags, data);
++              else if (flags & MS_BIND)
++                      error = aa_bind_mount(profile, path, dev_name, flags);
++              else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE |
++                                MS_UNBINDABLE))
++                      error = aa_mount_change_type(profile, path, flags);
++              else if (flags & MS_MOVE)
++                      error = aa_move_mount(profile, path, dev_name);
 +              else
-+                      type = AUDIT_APPARMOR_DENIED;
++                      error = aa_new_mount(profile, dev_name, path, type,
++                                           flags, data);
 +      }
-+      if (AUDIT_MODE(profile) == AUDIT_QUIET ||
-+          (type == AUDIT_APPARMOR_DENIED &&
-+           AUDIT_MODE(profile) == AUDIT_QUIET))
-+              return sa->aad.error;
++      return error;
++}
 +
-+      if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
-+              type = AUDIT_APPARMOR_KILL;
++static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
++{
++      struct aa_profile *profile;
++      int error = 0;
 +
++      profile = __aa_current_profile();
 +      if (!unconfined(profile))
-+              sa->aad.profile = profile;
++              error = aa_umount(profile, mnt, flags);
 +
-+      aa_audit_msg(type, sa, cb);
++      return error;
++}
 +
-+      if (sa->aad.type == AUDIT_APPARMOR_KILL)
-+              (void)send_sig_info(SIGKILL, NULL, sa->tsk ? sa->tsk : current);
++static int apparmor_sb_pivotroot(const struct path *old_path,
++                               const struct path *new_path)
++{
++      struct aa_profile *profile;
++      int error = 0;
 +
-+      if (sa->aad.type == AUDIT_APPARMOR_ALLOWED)
-+              return complain_error(sa->aad.error);
++      profile = __aa_current_profile();
++      if (!unconfined(profile))
++              error = aa_pivotroot(profile, old_path, new_path);
 +
-+      return sa->aad.error;
++      return error;
 +}
-diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
++
+ static int apparmor_getprocattr(struct task_struct *task, char *name,
+                               char **value)
+ {
+@@ -689,6 +745,10 @@ static struct security_hook_list apparmor_hooks[] = {
+       LSM_HOOK_INIT(capget, apparmor_capget),
+       LSM_HOOK_INIT(capable, apparmor_capable),
++      LSM_HOOK_INIT(sb_mount, apparmor_sb_mount),
++      LSM_HOOK_INIT(sb_umount, apparmor_sb_umount),
++      LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot),
++      
+       LSM_HOOK_INIT(path_link, apparmor_path_link),
+       LSM_HOOK_INIT(path_unlink, apparmor_path_unlink),
+       LSM_HOOK_INIT(path_symlink, apparmor_path_symlink),
+diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c
 new file mode 100644
-index 0000000..9982c48
+index 0000000..9cf9170
 --- /dev/null
-+++ b/security/apparmor/capability.c
-@@ -0,0 +1,141 @@
++++ b/security/apparmor/mount.c
+@@ -0,0 +1,620 @@
 +/*
 + * AppArmor security module
 + *
-+ * This file contains AppArmor capability mediation functions
++ * This file contains AppArmor mediation of files
 + *
 + * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
++ * Copyright 2009-2012 Canonical Ltd.
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License as
@@ -1170,7530 +959,611 @@ index 0000000..9982c48
 + * License.
 + */
 +
-+#include <linux/capability.h>
-+#include <linux/errno.h>
-+#include <linux/gfp.h>
++#include <linux/fs.h>
++#include <linux/mount.h>
++#include <linux/namei.h>
 +
 +#include "include/apparmor.h"
-+#include "include/capability.h"
++#include "include/audit.h"
 +#include "include/context.h"
++#include "include/domain.h"
++#include "include/file.h"
++#include "include/match.h"
++#include "include/mount.h"
++#include "include/path.h"
 +#include "include/policy.h"
-+#include "include/audit.h"
-+
-+/*
-+ * Table of capability names: we generate it from capabilities.h.
-+ */
-+#include "capability_names.h"
-+
-+struct audit_cache {
-+      struct aa_profile *profile;
-+      kernel_cap_t caps;
-+};
 +
-+static DEFINE_PER_CPU(struct audit_cache, audit_cache);
 +
-+/**
-+ * audit_cb - call back for capability components of audit struct
-+ * @ab - audit buffer   (NOT NULL)
-+ * @va - audit struct to audit data from  (NOT NULL)
++static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
++{
++      if (flags & MS_RDONLY)
++              audit_log_format(ab, "ro");
++      else
++              audit_log_format(ab, "rw");
++      if (flags & MS_NOSUID)
++              audit_log_format(ab, ", nosuid");
++      if (flags & MS_NODEV)
++              audit_log_format(ab, ", nodev");
++      if (flags & MS_NOEXEC)
++              audit_log_format(ab, ", noexec");
++      if (flags & MS_SYNCHRONOUS)
++              audit_log_format(ab, ", sync");
++      if (flags & MS_REMOUNT)
++              audit_log_format(ab, ", remount");
++      if (flags & MS_MANDLOCK)
++              audit_log_format(ab, ", mand");
++      if (flags & MS_DIRSYNC)
++              audit_log_format(ab, ", dirsync");
++      if (flags & MS_NOATIME)
++              audit_log_format(ab, ", noatime");
++      if (flags & MS_NODIRATIME)
++              audit_log_format(ab, ", nodiratime");
++      if (flags & MS_BIND)
++              audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
++      if (flags & MS_MOVE)
++              audit_log_format(ab, ", move");
++      if (flags & MS_SILENT)
++              audit_log_format(ab, ", silent");
++      if (flags & MS_POSIXACL)
++              audit_log_format(ab, ", acl");
++      if (flags & MS_UNBINDABLE)
++              audit_log_format(ab, flags & MS_REC ? ", runbindable" :
++                               ", unbindable");
++      if (flags & MS_PRIVATE)
++              audit_log_format(ab, flags & MS_REC ? ", rprivate" :
++                               ", private");
++      if (flags & MS_SLAVE)
++              audit_log_format(ab, flags & MS_REC ? ", rslave" :
++                               ", slave");
++      if (flags & MS_SHARED)
++              audit_log_format(ab, flags & MS_REC ? ", rshared" :
++                               ", shared");
++      if (flags & MS_RELATIME)
++              audit_log_format(ab, ", relatime");
++      if (flags & MS_I_VERSION)
++              audit_log_format(ab, ", iversion");
++      if (flags & MS_STRICTATIME)
++              audit_log_format(ab, ", strictatime");
++      if (flags & MS_NOUSER)
++              audit_log_format(ab, ", nouser");
++}
++
++/**
++ * audit_cb - call back for mount specific audit fields
++ * @ab: audit_buffer  (NOT NULL)
++ * @va: audit struct to audit values of  (NOT NULL)
 + */
 +static void audit_cb(struct audit_buffer *ab, void *va)
 +{
 +      struct common_audit_data *sa = va;
-+      audit_log_format(ab, " capname=");
-+      audit_log_untrustedstring(ab, capability_names[sa->u.cap]);
++
++      if (sa->aad->mnt.type) {
++              audit_log_format(ab, " fstype=");
++              audit_log_untrustedstring(ab, sa->aad->mnt.type);
++      }
++      if (sa->aad->mnt.src_name) {
++              audit_log_format(ab, " srcname=");
++              audit_log_untrustedstring(ab, sa->aad->mnt.src_name);
++      }
++      if (sa->aad->mnt.trans) {
++              audit_log_format(ab, " trans=");
++              audit_log_untrustedstring(ab, sa->aad->mnt.trans);
++      }
++      if (sa->aad->mnt.flags || sa->aad->op == OP_MOUNT) {
++              audit_log_format(ab, " flags=\"");
++              audit_mnt_flags(ab, sa->aad->mnt.flags);
++              audit_log_format(ab, "\"");
++      }
++      if (sa->aad->mnt.data) {
++              audit_log_format(ab, " options=");
++              audit_log_untrustedstring(ab, sa->aad->mnt.data);
++      }
 +}
 +
 +/**
-+ * audit_caps - audit a capability
-+ * @profile: profile confining task (NOT NULL)
-+ * @task: task capability test was performed against (NOT NULL)
-+ * @cap: capability tested
-+ * @error: error code returned by test
-+ *
-+ * Do auditing of capability and handle, audit/complain/kill modes switching
-+ * and duplicate message elimination.
++ * audit_mount - handle the auditing of mount operations
++ * @profile: the profile being enforced  (NOT NULL)
++ * @gfp: allocation flags
++ * @op: operation being mediated (NOT NULL)
++ * @name: name of object being mediated (MAYBE NULL)
++ * @src_name: src_name of object being mediated (MAYBE_NULL)
++ * @type: type of filesystem (MAYBE_NULL)
++ * @trans: name of trans (MAYBE NULL)
++ * @flags: filesystem idependent mount flags
++ * @data: filesystem mount flags
++ * @request: permissions requested
++ * @perms: the permissions computed for the request (NOT NULL)
++ * @info: extra information message (MAYBE NULL)
++ * @error: 0 if operation allowed else failure error code
 + *
-+ * Returns: 0 or sa->error on success,  error code on failure
++ * Returns: %0 or error on failure
 + */
-+static int audit_caps(struct aa_profile *profile, struct task_struct *task,
-+                    int cap, int error)
++static int audit_mount(struct aa_profile *profile, gfp_t gfp, int op,
++                     const char *name, const char *src_name,
++                     const char *type, const char *trans,
++                     unsigned long flags, const void *data, u32 request,
++                     struct file_perms *perms, const char *info, int error)
 +{
-+      struct audit_cache *ent;
-+      int type = AUDIT_APPARMOR_AUTO;
-+      struct common_audit_data sa;
-+      COMMON_AUDIT_DATA_INIT(&sa, CAP);
-+      sa.tsk = task;
-+      sa.u.cap = cap;
-+      sa.aad.op = OP_CAPABLE;
-+      sa.aad.error = error;
++      int audit_type = AUDIT_APPARMOR_AUTO;
++      struct common_audit_data sa = { };
++      struct apparmor_audit_data aad = { };
 +
 +      if (likely(!error)) {
-+              /* test if auditing is being forced */
-+              if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
-+                         !cap_raised(profile->caps.audit, cap)))
-+                      return 0;
-+              type = AUDIT_APPARMOR_AUDIT;
-+      } else if (KILL_MODE(profile) ||
-+                 cap_raised(profile->caps.kill, cap)) {
-+              type = AUDIT_APPARMOR_KILL;
-+      } else if (cap_raised(profile->caps.quiet, cap) &&
-+                 AUDIT_MODE(profile) != AUDIT_NOQUIET &&
-+                 AUDIT_MODE(profile) != AUDIT_ALL) {
-+              /* quiet auditing */
-+              return error;
-+      }
++              u32 mask = perms->audit;
 +
-+      /* Do simple duplicate message elimination */
-+      ent = &get_cpu_var(audit_cache);
-+      if (profile == ent->profile && cap_raised(ent->caps, cap)) {
-+              put_cpu_var(audit_cache);
-+              if (COMPLAIN_MODE(profile))
-+                      return complain_error(error);
-+              return error;
-+      } else {
-+              aa_put_profile(ent->profile);
-+              ent->profile = aa_get_profile(profile);
-+              cap_raise(ent->caps, cap);
-+      }
-+      put_cpu_var(audit_cache);
++              if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
++                      mask = 0xffff;
 +
-+      return aa_audit(type, profile, GFP_ATOMIC, &sa, audit_cb);
-+}
++              /* mask off perms that are not being force audited */
++              request &= mask;
 +
-+/**
-+ * profile_capable - test if profile allows use of capability @cap
-+ * @profile: profile being enforced    (NOT NULL, NOT unconfined)
-+ * @cap: capability to test if allowed
-+ *
-+ * Returns: 0 if allowed else -EPERM
-+ */
-+static int profile_capable(struct aa_profile *profile, int cap)
-+{
-+      return cap_raised(profile->caps.allow, cap) ? 0 : -EPERM;
-+}
++              if (likely(!request))
++                      return 0;
++              audit_type = AUDIT_APPARMOR_AUDIT;
++      } else {
++              /* only report permissions that were denied */
++              request = request & ~perms->allow;
 +
-+/**
-+ * aa_capable - test permission to use capability
-+ * @task: task doing capability test against (NOT NULL)
-+ * @profile: profile confining @task (NOT NULL)
-+ * @cap: capability to be tested
-+ * @audit: whether an audit record should be generated
-+ *
-+ * Look up capability in profile capability set.
-+ *
-+ * Returns: 0 on success, or else an error code.
-+ */
-+int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
-+             int audit)
-+{
-+      int error = profile_capable(profile, cap);
++              if (request & perms->kill)
++                      audit_type = AUDIT_APPARMOR_KILL;
 +
-+      if (!audit) {
-+              if (COMPLAIN_MODE(profile))
-+                      return complain_error(error);
-+              return error;
-+      }
++              /* quiet known rejects, assumes quiet and kill do not overlap */
++              if ((request & perms->quiet) &&
++                  AUDIT_MODE(profile) != AUDIT_NOQUIET &&
++                  AUDIT_MODE(profile) != AUDIT_ALL)
++                      request &= ~perms->quiet;
 +
-+      return audit_caps(profile, task, cap, error);
-+}
-diff --git a/security/apparmor/context.c b/security/apparmor/context.c
-new file mode 100644
-index 0000000..8a9b502
---- /dev/null
-+++ b/security/apparmor/context.c
-@@ -0,0 +1,216 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor functions used to manipulate object security
-+ * contexts.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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 sets confinement on every task, via the the aa_task_cxt and
-+ * the aa_task_cxt.profile, both of which are required and are not allowed
-+ * to be NULL.  The aa_task_cxt is not reference counted and is unique
-+ * to each cred (which is reference count).  The profile pointed to by
-+ * the task_cxt is reference counted.
-+ *
-+ * TODO
-+ * If a task uses change_hat it currently does not return to the old
-+ * cred or task context but instead creates a new one.  Ideally the task
-+ * should return to the previous cred if it has not been modified.
-+ *
-+ */
++              if (!request)
++                      return COMPLAIN_MODE(profile) ?
++                              complain_error(error) : error;
++      }
 +
-+#include "include/context.h"
-+#include "include/policy.h"
++      sa.type = LSM_AUDIT_DATA_NONE;
++      sa.aad = &aad;
++      sa.aad->op = op;
++      sa.aad->name = name;
++      sa.aad->mnt.src_name = src_name;
++      sa.aad->mnt.type = type;
++      sa.aad->mnt.trans = trans;
++      sa.aad->mnt.flags = flags;
++      if (data && (perms->audit & AA_AUDIT_DATA))
++              sa.aad->mnt.data = data;
++      sa.aad->info = info;
++      sa.aad->error = error;
 +
-+/**
-+ * aa_alloc_task_context - allocate a new task_cxt
-+ * @flags: gfp flags for allocation
-+ *
-+ * Returns: allocated buffer or NULL on failure
-+ */
-+struct aa_task_cxt *aa_alloc_task_context(gfp_t flags)
-+{
-+      return kzalloc(sizeof(struct aa_task_cxt), flags);
++      return aa_audit(audit_type, profile, gfp, &sa, audit_cb);
 +}
 +
 +/**
-+ * aa_free_task_context - free a task_cxt
-+ * @cxt: task_cxt to free (MAYBE NULL)
++ * match_mnt_flags - Do an ordered match on mount flags
++ * @dfa: dfa to match against
++ * @state: state to start in
++ * @flags: mount flags to match against
++ *
++ * Mount flags are encoded as an ordered match. This is done instead of
++ * checking against a simple bitmask, to allow for logical operations
++ * on the flags.
++ *
++ * Returns: next state after flags match
 + */
-+void aa_free_task_context(struct aa_task_cxt *cxt)
++static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
++                                  unsigned long flags)
 +{
-+      if (cxt) {
-+              aa_put_profile(cxt->profile);
-+              aa_put_profile(cxt->previous);
-+              aa_put_profile(cxt->onexec);
++      unsigned int i;
 +
-+              kzfree(cxt);
++      for (i = 0; i <= 31 ; ++i) {
++              if ((1 << i) & flags)
++                      state = aa_dfa_next(dfa, state, i + 1);
 +      }
-+}
 +
-+/**
-+ * aa_dup_task_context - duplicate a task context, incrementing reference counts
-+ * @new: a blank task context      (NOT NULL)
-+ * @old: the task context to copy  (NOT NULL)
-+ */
-+void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)
-+{
-+      *new = *old;
-+      aa_get_profile(new->profile);
-+      aa_get_profile(new->previous);
-+      aa_get_profile(new->onexec);
++      return state;
 +}
 +
 +/**
-+ * aa_replace_current_profile - replace the current tasks profiles
-+ * @profile: new profile  (NOT NULL)
++ * compute_mnt_perms - compute mount permission associated with @state
++ * @dfa: dfa to match against (NOT NULL)
++ * @state: state match finished in
 + *
-+ * Returns: 0 or error on failure
++ * Returns: mount permissions
 + */
-+int aa_replace_current_profile(struct aa_profile *profile)
++static struct file_perms compute_mnt_perms(struct aa_dfa *dfa,
++                                         unsigned int state)
 +{
-+      struct aa_task_cxt *cxt = current_cred()->security;
-+      struct cred *new;
-+      BUG_ON(!profile);
++      struct file_perms perms;
 +
-+      if (cxt->profile == profile)
-+              return 0;
++      perms.kill = 0;
++      perms.allow = dfa_user_allow(dfa, state);
++      perms.audit = dfa_user_audit(dfa, state);
++      perms.quiet = dfa_user_quiet(dfa, state);
++      perms.xindex = dfa_user_xindex(dfa, state);
 +
-+      new  = prepare_creds();
-+      if (!new)
-+              return -ENOMEM;
-+
-+      cxt = new->security;
-+      if (unconfined(profile) || (cxt->profile->ns != profile->ns)) {
-+              /* if switching to unconfined or a different profile namespace
-+               * clear out context state
-+               */
-+              aa_put_profile(cxt->previous);
-+              aa_put_profile(cxt->onexec);
-+              cxt->previous = NULL;
-+              cxt->onexec = NULL;
-+              cxt->token = 0;
-+      }
-+      /* be careful switching cxt->profile, when racing replacement it
-+       * is possible that cxt->profile->replacedby is the reference keeping
-+       * @profile valid, so make sure to get its reference before dropping
-+       * the reference on cxt->profile */
-+      aa_get_profile(profile);
-+      aa_put_profile(cxt->profile);
-+      cxt->profile = profile;
-+
-+      commit_creds(new);
-+      return 0;
++      return perms;
 +}
 +
-+/**
-+ * aa_set_current_onexec - set the tasks change_profile to happen onexec
-+ * @profile: system profile to set at exec  (MAYBE NULL to clear value)
-+ *
-+ * Returns: 0 or error on failure
++static const char const *mnt_info_table[] = {
++      "match succeeded",
++      "failed mntpnt match",
++      "failed srcname match",
++      "failed type match",
++      "failed flags match",
++      "failed data match"
++};
++
++/*
++ * Returns 0 on success else element that match failed in, this is the
++ * index into the mnt_info_table above
 + */
-+int aa_set_current_onexec(struct aa_profile *profile)
++static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
++                      const char *mntpnt, const char *devname,
++                      const char *type, unsigned long flags,
++                      void *data, bool binary, struct file_perms *perms)
 +{
-+      struct aa_task_cxt *cxt;
-+      struct cred *new = prepare_creds();
-+      if (!new)
-+              return -ENOMEM;
++      unsigned int state;
 +
-+      cxt = new->security;
-+      aa_get_profile(profile);
-+      aa_put_profile(cxt->onexec);
-+      cxt->onexec = profile;
++      state = aa_dfa_match(dfa, start, mntpnt);
++      state = aa_dfa_null_transition(dfa, state);
++      if (!state)
++              return 1;
 +
-+      commit_creds(new);
-+      return 0;
-+}
++      if (devname)
++              state = aa_dfa_match(dfa, state, devname);
++      state = aa_dfa_null_transition(dfa, state);
++      if (!state)
++              return 2;
++
++      if (type)
++              state = aa_dfa_match(dfa, state, type);
++      state = aa_dfa_null_transition(dfa, state);
++      if (!state)
++              return 3;
++
++      state = match_mnt_flags(dfa, state, flags);
++      if (!state)
++              return 4;
++      *perms = compute_mnt_perms(dfa, state);
++      if (perms->allow & AA_MAY_MOUNT)
++              return 0;
 +
-+/**
-+ * aa_set_current_hat - set the current tasks hat
-+ * @profile: profile to set as the current hat  (NOT NULL)
-+ * @token: token value that must be specified to change from the hat
-+ *
-+ * Do switch of tasks hat.  If the task is currently in a hat
-+ * validate the token to match.
-+ *
-+ * Returns: 0 or error on failure
-+ */
-+int aa_set_current_hat(struct aa_profile *profile, u64 token)
-+{
-+      struct aa_task_cxt *cxt;
-+      struct cred *new = prepare_creds();
-+      if (!new)
-+              return -ENOMEM;
-+      BUG_ON(!profile);
-+
-+      cxt = new->security;
-+      if (!cxt->previous) {
-+              /* transfer refcount */
-+              cxt->previous = cxt->profile;
-+              cxt->token = token;
-+      } else if (cxt->token == token) {
-+              aa_put_profile(cxt->profile);
-+      } else {
-+              /* previous_profile && cxt->token != token */
-+              abort_creds(new);
-+              return -EACCES;
++      /* only match data if not binary and the DFA flags data is expected */
++      if (data && !binary && (perms->allow & AA_CONT_MATCH)) {
++              state = aa_dfa_null_transition(dfa, state);
++              if (!state)
++                      return 4;
++
++              state = aa_dfa_match(dfa, state, data);
++              if (!state)
++                      return 5;
++              *perms = compute_mnt_perms(dfa, state);
++              if (perms->allow & AA_MAY_MOUNT)
++                      return 0;
 +      }
-+      cxt->profile = aa_get_profile(aa_newest_version(profile));
-+      /* clear exec on switching context */
-+      aa_put_profile(cxt->onexec);
-+      cxt->onexec = NULL;
 +
-+      commit_creds(new);
-+      return 0;
++      /* failed at end of flags match */
++      return 4;
 +}
 +
 +/**
-+ * aa_restore_previous_profile - exit from hat context restoring the profile
-+ * @token: the token that must be matched to exit hat context
++ * match_mnt - handle path matching for mount
++ * @profile: the confining profile
++ * @mntpnt: string for the mntpnt (NOT NULL)
++ * @devname: string for the devname/src_name (MAYBE NULL)
++ * @type: string for the dev type (MAYBE NULL)
++ * @flags: mount flags to match
++ * @data: fs mount data (MAYBE NULL)
++ * @binary: whether @data is binary
++ * @perms: Returns: permission found by the match
++ * @info: Returns: infomation string about the match for logging
 + *
-+ * Attempt to return out of a hat to the previous profile.  The token
-+ * must match the stored token value.
-+ *
-+ * Returns: 0 or error of failure
++ * Returns: 0 on success else error
 + */
-+int aa_restore_previous_profile(u64 token)
++static int match_mnt(struct aa_profile *profile, const char *mntpnt,
++                   const char *devname, const char *type,
++                   unsigned long flags, void *data, bool binary,
++                   struct file_perms *perms, const char **info)
 +{
-+      struct aa_task_cxt *cxt;
-+      struct cred *new = prepare_creds();
-+      if (!new)
-+              return -ENOMEM;
-+
-+      cxt = new->security;
-+      if (cxt->token != token) {
-+              abort_creds(new);
++      int pos;
++
++      if (!profile->policy.dfa)
 +              return -EACCES;
-+      }
-+      /* ignore restores when there is no saved profile */
-+      if (!cxt->previous) {
-+              abort_creds(new);
-+              return 0;
-+      }
 +
-+      aa_put_profile(cxt->profile);
-+      cxt->profile = aa_newest_version(cxt->previous);
-+      BUG_ON(!cxt->profile);
-+      if (unlikely(cxt->profile != cxt->previous)) {
-+              aa_get_profile(cxt->profile);
-+              aa_put_profile(cxt->previous);
++      pos = do_match_mnt(profile->policy.dfa,
++                         profile->policy.start[AA_CLASS_MOUNT],
++                         mntpnt, devname, type, flags, data, binary, perms);
++      if (pos) {
++              *info = mnt_info_table[pos];
++              return -EACCES;
 +      }
-+      /* clear exec && prev information when restoring to previous context */
-+      cxt->previous = NULL;
-+      cxt->token = 0;
-+      aa_put_profile(cxt->onexec);
-+      cxt->onexec = NULL;
 +
-+      commit_creds(new);
 +      return 0;
 +}
-diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
-new file mode 100644
-index 0000000..08bbe63
---- /dev/null
-+++ b/security/apparmor/domain.c
-@@ -0,0 +1,823 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor policy attachment and domain transitions
-+ *
-+ * Copyright (C) 2002-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#include <linux/errno.h>
-+#include <linux/fdtable.h>
-+#include <linux/file.h>
-+#include <linux/mount.h>
-+#include <linux/syscalls.h>
-+#include <linux/tracehook.h>
-+#include <linux/personality.h>
-+
-+#include "include/audit.h"
-+#include "include/apparmorfs.h"
-+#include "include/context.h"
-+#include "include/domain.h"
-+#include "include/file.h"
-+#include "include/ipc.h"
-+#include "include/match.h"
-+#include "include/path.h"
-+#include "include/policy.h"
 +
-+/**
-+ * aa_free_domain_entries - free entries in a domain table
-+ * @domain: the domain table to free  (MAYBE NULL)
-+ */
-+void aa_free_domain_entries(struct aa_domain *domain)
++static int path_flags(struct aa_profile *profile, const struct path *path)
 +{
-+      int i;
-+      if (domain) {
-+              if (!domain->table)
-+                      return;
-+
-+              for (i = 0; i < domain->size; i++)
-+                      kzfree(domain->table[i]);
-+              kzfree(domain->table);
-+              domain->table = NULL;
-+      }
++      return profile->path_flags |
++              S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0;
 +}
 +
-+/**
-+ * may_change_ptraced_domain - check if can change profile on ptraced task
-+ * @task: task we want to change profile of   (NOT NULL)
-+ * @to_profile: profile to change to  (NOT NULL)
-+ *
-+ * Check if the task is ptraced and if so if the tracing task is allowed
-+ * to trace the new domain
-+ *
-+ * Returns: %0 or error if change not allowed
-+ */
-+static int may_change_ptraced_domain(struct task_struct *task,
-+                                   struct aa_profile *to_profile)
++int aa_remount(struct aa_profile *profile, const struct path *path,
++             unsigned long flags, void *data)
 +{
-+      struct task_struct *tracer;
-+      struct cred *cred = NULL;
-+      struct aa_profile *tracerp = NULL;
-+      int error = 0;
++      struct file_perms perms = { };
++      const char *name, *info = NULL;
++      char *buffer = NULL;
++      int binary, error;
 +
-+      rcu_read_lock();
-+      tracer = tracehook_tracer_task(task);
-+      if (tracer) {
-+              /* released below */
-+              cred = get_task_cred(tracer);
-+              tracerp = aa_cred_profile(cred);
-+      }
-+      rcu_read_unlock();
++      binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
 +
-+      /* not ptraced */
-+      if (!tracer || unconfined(tracerp))
-+              goto out;
++      error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
++                           &info);
++      if (error)
++              goto audit;
 +
-+      error = aa_may_ptrace(tracer, tracerp, to_profile, PTRACE_MODE_ATTACH);
++      error = match_mnt(profile, name, NULL, NULL, flags, data, binary,
++                        &perms, &info);
 +
-+out:
-+      if (cred)
-+              put_cred(cred);
++audit:
++      error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
++                          NULL, flags, data, AA_MAY_MOUNT, &perms, info,
++                          error);
++      kfree(buffer);
 +
 +      return error;
 +}
 +
-+/**
-+ * change_profile_perms - find permissions for change_profile
-+ * @profile: the current profile  (NOT NULL)
-+ * @ns: the namespace being switched to  (NOT NULL)
-+ * @name: the name of the profile to change to  (NOT NULL)
-+ * @request: requested perms
-+ * @start: state to start matching in
-+ *
-+ * Returns: permission set
-+ */
-+static struct file_perms change_profile_perms(struct aa_profile *profile,
-+                                            struct aa_namespace *ns,
-+                                            const char *name, u32 request,
-+                                            unsigned int start)
++int aa_bind_mount(struct aa_profile *profile, const struct path *path,
++                const char *dev_name, unsigned long flags)
 +{
-+      struct file_perms perms;
-+      struct path_cond cond = { };
-+      unsigned int state;
++      struct file_perms perms = { };
++      char *buffer = NULL, *old_buffer = NULL;
++      const char *name, *old_name = NULL, *info = NULL;
++      struct path old_path;
++      int error;
 +
-+      if (unconfined(profile)) {
-+              perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC;
-+              perms.audit = perms.quiet = perms.kill = 0;
-+              return perms;
-+      } else if (!profile->file.dfa) {
-+              return nullperms;
-+      } else if ((ns == profile->ns)) {
-+              /* try matching against rules with out namespace prepended */
-+              aa_str_perms(profile->file.dfa, start, name, &cond, &perms);
-+              if (COMBINED_PERM_MASK(perms) & request)
-+                      return perms;
-+      }
++      if (!dev_name || !*dev_name)
++              return -EINVAL;
 +
-+      /* try matching with namespace name and then profile */
-+      state = aa_dfa_match(profile->file.dfa, start, ns->base.name);
-+      state = aa_dfa_match_len(profile->file.dfa, state, ":", 1);
-+      aa_str_perms(profile->file.dfa, state, name, &cond, &perms);
++      flags &= MS_REC | MS_BIND;
 +
-+      return perms;
-+}
++      error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
++                           &info);
++      if (error)
++              goto audit;
 +
-+/**
-+ * __attach_match_ - find an attachment match
-+ * @name - to match against  (NOT NULL)
-+ * @head - profile list to walk  (NOT NULL)
-+ *
-+ * Do a linear search on the profiles in the list.  There is a matching
-+ * preference where an exact match is preferred over a name which uses
-+ * expressions to match, and matching expressions with the greatest
-+ * xmatch_len are preferred.
-+ *
-+ * Requires: @head not be shared or have appropriate locks held
-+ *
-+ * Returns: profile or NULL if no match found
-+ */
-+static struct aa_profile *__attach_match(const char *name,
-+                                       struct list_head *head)
-+{
-+      int len = 0;
-+      struct aa_profile *profile, *candidate = NULL;
-+
-+      list_for_each_entry(profile, head, base.list) {
-+              if (profile->flags & PFLAG_NULL)
-+                      continue;
-+              if (profile->xmatch && profile->xmatch_len > len) {
-+                      unsigned int state = aa_dfa_match(profile->xmatch,
-+                                                        DFA_START, name);
-+                      u32 perm = dfa_user_allow(profile->xmatch, state);
-+                      /* any accepting state means a valid match. */
-+                      if (perm & MAY_EXEC) {
-+                              candidate = profile;
-+                              len = profile->xmatch_len;
-+                      }
-+              } else if (!strcmp(profile->base.name, name))
-+                      /* exact non-re match, no more searching required */
-+                      return profile;
-+      }
++      error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
++      if (error)
++              goto audit;
 +
-+      return candidate;
-+}
++      error = aa_path_name(&old_path, path_flags(profile, &old_path),
++                           &old_buffer, &old_name, &info);
++      path_put(&old_path);
++      if (error)
++              goto audit;
 +
-+/**
-+ * find_attach - do attachment search for unconfined processes
-+ * @ns: the current namespace  (NOT NULL)
-+ * @list: list to search  (NOT NULL)
-+ * @name: the executable name to match against  (NOT NULL)
-+ *
-+ * Returns: profile or NULL if no match found
-+ */
-+static struct aa_profile *find_attach(struct aa_namespace *ns,
-+                                    struct list_head *list, const char *name)
-+{
-+      struct aa_profile *profile;
++      error = match_mnt(profile, name, old_name, NULL, flags, NULL, 0,
++                        &perms, &info);
 +
-+      read_lock(&ns->lock);
-+      profile = aa_get_profile(__attach_match(name, list));
-+      read_unlock(&ns->lock);
++audit:
++      error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
++                          NULL, NULL, flags, NULL, AA_MAY_MOUNT, &perms,
++                          info, error);
++      kfree(buffer);
++      kfree(old_buffer);
 +
-+      return profile;
++      return error;
 +}
 +
-+/**
-+ * separate_fqname - separate the namespace and profile names
-+ * @fqname: the fqname name to split  (NOT NULL)
-+ * @ns_name: the namespace name if it exists  (NOT NULL)
-+ *
-+ * This is the xtable equivalent routine of aa_split_fqname.  It finds the
-+ * split in an xtable fqname which contains an embedded \0 instead of a :
-+ * if a namespace is specified.  This is done so the xtable is constant and
-+ * isn't re-split on every lookup.
-+ *
-+ * Either the profile or namespace name may be optional but if the namespace
-+ * is specified the profile name termination must be present.  This results
-+ * in the following possible encodings:
-+ * profile_name\0
-+ * :ns_name\0profile_name\0
-+ * :ns_name\0\0
-+ *
-+ * NOTE: the xtable fqname is pre-validated at load time in unpack_trans_table
-+ *
-+ * Returns: profile name if it is specified else NULL
-+ */
-+static const char *separate_fqname(const char *fqname, const char **ns_name)
++int aa_mount_change_type(struct aa_profile *profile, const struct path *path,
++                       unsigned long flags)
 +{
-+      const char *name;
-+
-+      if (fqname[0] == ':') {
-+              /* In this case there is guaranteed to be two \0 terminators
-+               * in the string.  They are verified at load time by
-+               * by unpack_trans_table
-+               */
-+              *ns_name = fqname + 1;          /* skip : */
-+              name = *ns_name + strlen(*ns_name) + 1;
-+              if (!*name)
-+                      name = NULL;
-+      } else {
-+              *ns_name = NULL;
-+              name = fqname;
-+      }
++      struct file_perms perms = { };
++      char *buffer = NULL;
++      const char *name, *info = NULL;
++      int error;
 +
-+      return name;
-+}
++      /* These are the flags allowed by do_change_type() */
++      flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
++                MS_UNBINDABLE);
 +
-+static const char *next_name(int xtype, const char *name)
-+{
-+      return NULL;
-+}
++      error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
++                           &info);
++      if (error)
++              goto audit;
 +
-+/**
-+ * x_table_lookup - lookup an x transition name via transition table
-+ * @profile: current profile (NOT NULL)
-+ * @xindex: index into x transition table
-+ *
-+ * Returns: refcounted profile, or NULL on failure (MAYBE NULL)
-+ */
-+static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex)
-+{
-+      struct aa_profile *new_profile = NULL;
-+      struct aa_namespace *ns = profile->ns;
-+      u32 xtype = xindex & AA_X_TYPE_MASK;
-+      int index = xindex & AA_X_INDEX_MASK;
-+      const char *name;
-+
-+      /* index is guaranteed to be in range, validated at load time */
-+      for (name = profile->file.trans.table[index]; !new_profile && name;
-+           name = next_name(xtype, name)) {
-+              struct aa_namespace *new_ns;
-+              const char *xname = NULL;
-+
-+              new_ns = NULL;
-+              if (xindex & AA_X_CHILD) {
-+                      /* release by caller */
-+                      new_profile = aa_find_child(profile, name);
-+                      continue;
-+              } else if (*name == ':') {
-+                      /* switching namespace */
-+                      const char *ns_name;
-+                      xname = name = separate_fqname(name, &ns_name);
-+                      if (!xname)
-+                              /* no name so use profile name */
-+                              xname = profile->base.hname;
-+                      if (*ns_name == '@') {
-+                              /* TODO: variable support */
-+                              ;
-+                      }
-+                      /* released below */
-+                      new_ns = aa_find_namespace(ns, ns_name);
-+                      if (!new_ns)
-+                              continue;
-+              } else if (*name == '@') {
-+                      /* TODO: variable support */
-+                      continue;
-+              } else {
-+                      /* basic namespace lookup */
-+                      xname = name;
-+              }
++      error = match_mnt(profile, name, NULL, NULL, flags, NULL, 0, &perms,
++                        &info);
 +
-+              /* released by caller */
-+              new_profile = aa_lookup_profile(new_ns ? new_ns : ns, xname);
-+              aa_put_namespace(new_ns);
-+      }
++audit:
++      error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
++                          NULL, flags, NULL, AA_MAY_MOUNT, &perms, info,
++                          error);
++      kfree(buffer);
 +
-+      /* released by caller */
-+      return new_profile;
++      return error;
 +}
 +
-+/**
-+ * x_to_profile - get target profile for a given xindex
-+ * @profile: current profile  (NOT NULL)
-+ * @name: name to lookup (NOT NULL)
-+ * @xindex: index into x transition table
-+ *
-+ * find profile for a transition index
-+ *
-+ * Returns: refcounted profile or NULL if not found available
-+ */
-+static struct aa_profile *x_to_profile(struct aa_profile *profile,
-+                                     const char *name, u32 xindex)
++int aa_move_mount(struct aa_profile *profile, const struct path *path,
++                const char *orig_name)
 +{
-+      struct aa_profile *new_profile = NULL;
-+      struct aa_namespace *ns = profile->ns;
-+      u32 xtype = xindex & AA_X_TYPE_MASK;
-+
-+      switch (xtype) {
-+      case AA_X_NONE:
-+              /* fail exec unless ix || ux fallback - handled by caller */
-+              return NULL;
-+      case AA_X_NAME:
-+              if (xindex & AA_X_CHILD)
-+                      /* released by caller */
-+                      new_profile = find_attach(ns, &profile->base.profiles,
-+                                                name);
-+              else
-+                      /* released by caller */
-+                      new_profile = find_attach(ns, &ns->base.profiles,
-+                                                name);
-+              break;
-+      case AA_X_TABLE:
-+              /* released by caller */
-+              new_profile = x_table_lookup(profile, xindex);
-+              break;
-+      }
++      struct file_perms perms = { };
++      char *buffer = NULL, *old_buffer = NULL;
++      const char *name, *old_name = NULL, *info = NULL;
++      struct path old_path;
++      int error;
 +
-+      /* released by caller */
-+      return new_profile;
-+}
++      if (!orig_name || !*orig_name)
++              return -EINVAL;
 +
-+/**
-+ * apparmor_bprm_set_creds - set the new creds on the bprm struct
-+ * @bprm: binprm for the exec  (NOT NULL)
-+ *
-+ * Returns: %0 or error on failure
-+ */
-+int apparmor_bprm_set_creds(struct linux_binprm *bprm)
-+{
-+      struct aa_task_cxt *cxt;
-+      struct aa_profile *profile, *new_profile = NULL;
-+      struct aa_namespace *ns;
-+      char *buffer = NULL;
-+      unsigned int state;
-+      struct file_perms perms = {};
-+      struct path_cond cond = {
-+              bprm->file->f_path.dentry->d_inode->i_uid,
-+              bprm->file->f_path.dentry->d_inode->i_mode
-+      };
-+      const char *name = NULL, *target = NULL, *info = NULL;
-+      int error = cap_bprm_set_creds(bprm);
++      error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
++                           &info);
 +      if (error)
-+              return error;
-+
-+      if (bprm->cred_prepared)
-+              return 0;
++              goto audit;
 +
-+      cxt = bprm->cred->security;
-+      BUG_ON(!cxt);
++      error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
++      if (error)
++              goto audit;
 +
-+      profile = aa_get_profile(aa_newest_version(cxt->profile));
-+      /*
-+       * get the namespace from the replacement profile as replacement
-+       * can change the namespace
-+       */
-+      ns = profile->ns;
-+      state = profile->file.start;
-+
-+      /* buffer freed below, name is pointer into buffer */
-+      error = aa_get_name(&bprm->file->f_path, profile->path_flags, &buffer,
-+                          &name);
-+      if (error) {
-+              if (profile->flags &
-+                  (PFLAG_IX_ON_NAME_ERROR | PFLAG_UNCONFINED))
-+                      error = 0;
-+              info = "Exec failed name resolution";
-+              name = bprm->filename;
++      error = aa_path_name(&old_path, path_flags(profile, &old_path),
++                           &old_buffer, &old_name, &info);
++      path_put(&old_path);
++      if (error)
 +              goto audit;
-+      }
 +
-+      /* Test for onexec first as onexec directives override other
-+       * x transitions.
-+       */
-+      if (unconfined(profile)) {
-+              /* unconfined task */
-+              if (cxt->onexec)
-+                      /* change_profile on exec already been granted */
-+                      new_profile = aa_get_profile(cxt->onexec);
-+              else
-+                      new_profile = find_attach(ns, &ns->base.profiles, name);
-+              if (!new_profile)
-+                      goto cleanup;
-+              goto apply;
-+      }
++      error = match_mnt(profile, name, old_name, NULL, MS_MOVE, NULL, 0,
++                        &perms, &info);
 +
-+      /* find exec permissions for name */
-+      state = aa_str_perms(profile->file.dfa, state, name, &cond, &perms);
-+      if (cxt->onexec) {
-+              struct file_perms cp;
-+              info = "change_profile onexec";
-+              if (!(perms.allow & AA_MAY_ONEXEC))
-+                      goto audit;
-+
-+              /* test if this exec can be paired with change_profile onexec.
-+               * onexec permission is linked to exec with a standard pairing
-+               * exec\0change_profile
-+               */
-+              state = aa_dfa_null_transition(profile->file.dfa, state);
-+              cp = change_profile_perms(profile, cxt->onexec->ns, name,
-+                                        AA_MAY_ONEXEC, state);
-+
-+              if (!(cp.allow & AA_MAY_ONEXEC))
-+                      goto audit;
-+              new_profile = aa_get_profile(aa_newest_version(cxt->onexec));
-+              goto apply;
-+      }
++audit:
++      error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, old_name,
++                          NULL, NULL, MS_MOVE, NULL, AA_MAY_MOUNT, &perms,
++                          info, error);
++      kfree(buffer);
++      kfree(old_buffer);
++
++      return error;
++}
++
++int aa_new_mount(struct aa_profile *profile, const char *orig_dev_name,
++               const struct path *path, const char *type, unsigned long flags,
++               void *data)
++{
++      struct file_perms perms = { };
++      char *buffer = NULL, *dev_buffer = NULL;
++      const char *name = NULL, *dev_name = NULL, *info = NULL;
++      int binary = 1;
++      int error;
++
++      dev_name = orig_dev_name;
++      if (type) {
++              int requires_dev;
++              struct file_system_type *fstype = get_fs_type(type);
++              if (!fstype)
++                      return -ENODEV;
++
++              binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
++              requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
++              put_filesystem(fstype);
++
++              if (requires_dev) {
++                      struct path dev_path;
 +
-+      if (perms.allow & MAY_EXEC) {
-+              /* exec permission determine how to transition */
-+              new_profile = x_to_profile(profile, name, perms.xindex);
-+              if (!new_profile) {
-+                      if (perms.xindex & AA_X_INHERIT) {
-+                              /* (p|c|n)ix - don't change profile but do
-+                               * use the newest version, which was picked
-+                               * up above when getting profile
-+                               */
-+                              info = "ix fallback";
-+                              new_profile = aa_get_profile(profile);
-+                              goto x_clear;
-+                      } else if (perms.xindex & AA_X_UNCONFINED) {
-+                              new_profile = aa_get_profile(ns->unconfined);
-+                              info = "ux fallback";
-+                      } else {
++                      if (!dev_name || !*dev_name) {
 +                              error = -ENOENT;
-+                              info = "profile not found";
++                              goto out;
 +                      }
-+              }
-+      } else if (COMPLAIN_MODE(profile)) {
-+              /* no exec permission - are we in learning mode */
-+              new_profile = aa_new_null_profile(profile, 0);
-+              if (!new_profile) {
-+                      error = -ENOMEM;
-+                      info = "could not create null profile";
-+              } else {
-+                      error = -EACCES;
-+                      target = new_profile->base.hname;
-+              }
-+              perms.xindex |= AA_X_UNSAFE;
-+      } else
-+              /* fail exec */
-+              error = -EACCES;
-+
-+      if (!new_profile)
-+              goto audit;
 +
-+      if (bprm->unsafe & LSM_UNSAFE_SHARE) {
-+              /* FIXME: currently don't mediate shared state */
-+              ;
-+      }
++                      error = kern_path(dev_name, LOOKUP_FOLLOW, &dev_path);
++                      if (error)
++                              goto audit;
 +
-+      if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
-+              error = may_change_ptraced_domain(current, new_profile);
-+              if (error) {
-+                      aa_put_profile(new_profile);
-+                      goto audit;
++                      error = aa_path_name(&dev_path,
++                                           path_flags(profile, &dev_path),
++                                           &dev_buffer, &dev_name, &info);
++                      path_put(&dev_path);
++                      if (error)
++                              goto audit;
 +              }
 +      }
 +
-+      /* Determine if secure exec is needed.
-+       * Can be at this point for the following reasons:
-+       * 1. unconfined switching to confined
-+       * 2. confined switching to different confinement
-+       * 3. confined switching to unconfined
-+       *
-+       * Cases 2 and 3 are marked as requiring secure exec
-+       * (unless policy specified "unsafe exec")
-+       *
-+       * bprm->unsafe is used to cache the AA_X_UNSAFE permission
-+       * to avoid having to recompute in secureexec
-+       */
-+      if (!(perms.xindex & AA_X_UNSAFE)) {
-+              AA_DEBUG("scrubbing environment variables for %s profile=%s\n",
-+                       name, new_profile->base.hname);
-+              bprm->unsafe |= AA_SECURE_X_NEEDED;
-+      }
-+apply:
-+      target = new_profile->base.hname;
-+      /* when transitioning profiles clear unsafe personality bits */
-+      bprm->per_clear |= PER_CLEAR_ON_SETID;
-+
-+x_clear:
-+      aa_put_profile(cxt->profile);
-+      /* transfer new profile reference will be released when cxt is freed */
-+      cxt->profile = new_profile;
-+
-+      /* clear out all temporary/transitional state from the context */
-+      aa_put_profile(cxt->previous);
-+      aa_put_profile(cxt->onexec);
-+      cxt->previous = NULL;
-+      cxt->onexec = NULL;
-+      cxt->token = 0;
++      error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
++                           &info);
++      if (error)
++              goto audit;
 +
-+audit:
-+      error = aa_audit_file(profile, &perms, GFP_KERNEL, OP_EXEC, MAY_EXEC,
-+                            name, target, cond.uid, info, error);
++      error = match_mnt(profile, name, dev_name, type, flags, data, binary,
++                        &perms, &info);
 +
-+cleanup:
-+      aa_put_profile(profile);
++audit:
++      error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name,  dev_name,
++                          type, NULL, flags, data, AA_MAY_MOUNT, &perms, info,
++                          error);
 +      kfree(buffer);
++      kfree(dev_buffer);
 +
++out:
 +      return error;
++
 +}
 +
-+/**
-+ * apparmor_bprm_secureexec - determine if secureexec is needed
-+ * @bprm: binprm for exec  (NOT NULL)
-+ *
-+ * Returns: %1 if secureexec is needed else %0
-+ */
-+int apparmor_bprm_secureexec(struct linux_binprm *bprm)
++int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags)
 +{
-+      int ret = cap_bprm_secureexec(bprm);
++      struct file_perms perms = { };
++      char *buffer = NULL;
++      const char *name, *info = NULL;
++      int error;
 +
-+      /* the decision to use secure exec is computed in set_creds
-+       * and stored in bprm->unsafe.
-+       */
-+      if (!ret && (bprm->unsafe & AA_SECURE_X_NEEDED))
-+              ret = 1;
++      struct path path = { mnt, mnt->mnt_root };
++      error = aa_path_name(&path, path_flags(profile, &path), &buffer, &name,
++                           &info);
++      if (error)
++              goto audit;
 +
-+      return ret;
-+}
-+
-+/**
-+ * apparmor_bprm_committing_creds - do task cleanup on committing new creds
-+ * @bprm: binprm for the exec  (NOT NULL)
-+ */
-+void apparmor_bprm_committing_creds(struct linux_binprm *bprm)
-+{
-+      struct aa_profile *profile = __aa_current_profile();
-+      struct aa_task_cxt *new_cxt = bprm->cred->security;
-+
-+      /* bail out if unconfined or not changing profile */
-+      if ((new_cxt->profile == profile) ||
-+          (unconfined(new_cxt->profile)))
-+              return;
-+
-+      current->pdeath_signal = 0;
-+
-+      /* reset soft limits and set hard limits for the new profile */
-+      __aa_transition_rlimits(profile, new_cxt->profile);
-+}
-+
-+/**
-+ * apparmor_bprm_commited_cred - do cleanup after new creds committed
-+ * @bprm: binprm for the exec  (NOT NULL)
-+ */
-+void apparmor_bprm_committed_creds(struct linux_binprm *bprm)
-+{
-+      /* TODO: cleanup signals - ipc mediation */
-+      return;
-+}
-+
-+/*
-+ * Functions for self directed profile change
-+ */
-+
-+/**
-+ * new_compound_name - create an hname with @n2 appended to @n1
-+ * @n1: base of hname  (NOT NULL)
-+ * @n2: name to append (NOT NULL)
-+ *
-+ * Returns: new name or NULL on error
-+ */
-+static char *new_compound_name(const char *n1, const char *n2)
-+{
-+      char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL);
-+      if (name)
-+              sprintf(name, "%s//%s", n1, n2);
-+      return name;
-+}
-+
-+/**
-+ * aa_change_hat - change hat to/from subprofile
-+ * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0)
-+ * @count: number of hat names in @hats
-+ * @token: magic value to validate the hat change
-+ * @permtest: true if this is just a permission test
-+ *
-+ * Change to the first profile specified in @hats that exists, and store
-+ * the @hat_magic in the current task context.  If the count == 0 and the
-+ * @token matches that stored in the current task context, return to the
-+ * top level profile.
-+ *
-+ * Returns %0 on success, error otherwise.
-+ */
-+int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
-+{
-+      const struct cred *cred;
-+      struct aa_task_cxt *cxt;
-+      struct aa_profile *profile, *previous_profile, *hat = NULL;
-+      char *name = NULL;
-+      int i;
-+      struct file_perms perms = {};
-+      const char *target = NULL, *info = NULL;
-+      int error = 0;
-+
-+      /* released below */
-+      cred = get_current_cred();
-+      cxt = cred->security;
-+      profile = aa_cred_profile(cred);
-+      previous_profile = cxt->previous;
-+
-+      if (unconfined(profile)) {
-+              info = "unconfined";
-+              error = -EPERM;
-+              goto audit;
-+      }
-+
-+      if (count) {
-+              /* attempting to change into a new hat or switch to a sibling */
-+              struct aa_profile *root;
-+              root = PROFILE_IS_HAT(profile) ? profile->parent : profile;
-+
-+              /* find first matching hat */
-+              for (i = 0; i < count && !hat; i++)
-+                      /* released below */
-+                      hat = aa_find_child(root, hats[i]);
-+              if (!hat) {
-+                      if (!COMPLAIN_MODE(root) || permtest) {
-+                              if (list_empty(&root->base.profiles))
-+                                      error = -ECHILD;
-+                              else
-+                                      error = -ENOENT;
-+                              goto out;
-+                      }
-+
-+                      /*
-+                       * In complain mode and failed to match any hats.
-+                       * Audit the failure is based off of the first hat
-+                       * supplied.  This is done due how userspace
-+                       * interacts with change_hat.
-+                       *
-+                       * TODO: Add logging of all failed hats
-+                       */
-+
-+                      /* freed below */
-+                      name = new_compound_name(root->base.hname, hats[0]);
-+                      target = name;
-+                      /* released below */
-+                      hat = aa_new_null_profile(profile, 1);
-+                      if (!hat) {
-+                              info = "failed null profile create";
-+                              error = -ENOMEM;
-+                              goto audit;
-+                      }
-+              } else {
-+                      target = hat->base.hname;
-+                      if (!PROFILE_IS_HAT(hat)) {
-+                              info = "target not hat";
-+                              error = -EPERM;
-+                              goto audit;
-+                      }
-+              }
-+
-+              error = may_change_ptraced_domain(current, hat);
-+              if (error) {
-+                      info = "ptraced";
-+                      error = -EPERM;
-+                      goto audit;
-+              }
-+
-+              if (!permtest) {
-+                      error = aa_set_current_hat(hat, token);
-+                      if (error == -EACCES)
-+                              /* kill task in case of brute force attacks */
-+                              perms.kill = AA_MAY_CHANGEHAT;
-+                      else if (name && !error)
-+                              /* reset error for learning of new hats */
-+                              error = -ENOENT;
-+              }
-+      } else if (previous_profile) {
-+              /* Return to saved profile.  Kill task if restore fails
-+               * to avoid brute force attacks
-+               */
-+              target = previous_profile->base.hname;
-+              error = aa_restore_previous_profile(token);
-+              perms.kill = AA_MAY_CHANGEHAT;
-+      } else
-+              /* ignore restores when there is no saved profile */
-+              goto out;
-+
-+audit:
-+      if (!permtest)
-+              error = aa_audit_file(profile, &perms, GFP_KERNEL,
-+                                    OP_CHANGE_HAT, AA_MAY_CHANGEHAT, NULL,
-+                                    target, 0, info, error);
-+
-+out:
-+      aa_put_profile(hat);
-+      kfree(name);
-+      put_cred(cred);
-+
-+      return error;
-+}
-+
-+/**
-+ * aa_change_profile - perform a one-way profile transition
-+ * @ns_name: name of the profile namespace to change to (MAYBE NULL)
-+ * @hname: name of profile to change to (MAYBE NULL)
-+ * @onexec: whether this transition is to take place immediately or at exec
-+ * @permtest: true if this is just a permission test
-+ *
-+ * Change to new profile @name.  Unlike with hats, there is no way
-+ * to change back.  If @name isn't specified the current profile name is
-+ * used.
-+ * If @onexec then the transition is delayed until
-+ * the next exec.
-+ *
-+ * Returns %0 on success, error otherwise.
-+ */
-+int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
-+                    bool permtest)
-+{
-+      const struct cred *cred;
-+      struct aa_task_cxt *cxt;
-+      struct aa_profile *profile, *target = NULL;
-+      struct aa_namespace *ns = NULL;
-+      struct file_perms perms = {};
-+      const char *name = NULL, *info = NULL;
-+      int op, error = 0;
-+      u32 request;
-+
-+      if (!hname && !ns_name)
-+              return -EINVAL;
-+
-+      if (onexec) {
-+              request = AA_MAY_ONEXEC;
-+              op = OP_CHANGE_ONEXEC;
-+      } else {
-+              request = AA_MAY_CHANGE_PROFILE;
-+              op = OP_CHANGE_PROFILE;
-+      }
-+
-+      cred = get_current_cred();
-+      cxt = cred->security;
-+      profile = aa_cred_profile(cred);
-+
-+      if (ns_name) {
-+              /* released below */
-+              ns = aa_find_namespace(profile->ns, ns_name);
-+              if (!ns) {
-+                      /* we don't create new namespace in complain mode */
-+                      name = ns_name;
-+                      info = "namespace not found";
-+                      error = -ENOENT;
-+                      goto audit;
-+              }
-+      } else
-+              /* released below */
-+              ns = aa_get_namespace(profile->ns);
-+
-+      /* if the name was not specified, use the name of the current profile */
-+      if (!hname) {
-+              if (unconfined(profile))
-+                      hname = ns->unconfined->base.hname;
-+              else
-+                      hname = profile->base.hname;
++      if (!error && profile->policy.dfa) {
++              unsigned int state;
++              state = aa_dfa_match(profile->policy.dfa,
++                                   profile->policy.start[AA_CLASS_MOUNT],
++                                   name);
++              perms = compute_mnt_perms(profile->policy.dfa, state);
 +      }
 +
-+      perms = change_profile_perms(profile, ns, hname, request,
-+                                   profile->file.start);
-+      if (!(perms.allow & request)) {
++      if (AA_MAY_UMOUNT & ~perms.allow)
 +              error = -EACCES;
-+              goto audit;
-+      }
-+
-+      /* released below */
-+      target = aa_lookup_profile(ns, hname);
-+      if (!target) {
-+              info = "profile not found";
-+              error = -ENOENT;
-+              if (permtest || !COMPLAIN_MODE(profile))
-+                      goto audit;
-+              /* released below */
-+              target = aa_new_null_profile(profile, 0);
-+              if (!target) {
-+                      info = "failed null profile create";
-+                      error = -ENOMEM;
-+                      goto audit;
-+              }
-+      }
-+
-+      /* check if tracing task is allowed to trace target domain */
-+      error = may_change_ptraced_domain(current, target);
-+      if (error) {
-+              info = "ptrace prevents transition";
-+              goto audit;
-+      }
-+
-+      if (permtest)
-+              goto audit;
-+
-+      if (onexec)
-+              error = aa_set_current_onexec(target);
-+      else
-+              error = aa_replace_current_profile(target);
 +
 +audit:
-+      if (!permtest)
-+              error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request,
-+                                    name, hname, 0, info, error);
-+
-+      aa_put_namespace(ns);
-+      aa_put_profile(target);
-+      put_cred(cred);
-+
-+      return error;
-+}
-diff --git a/security/apparmor/file.c b/security/apparmor/file.c
-new file mode 100644
-index 0000000..7312db7
---- /dev/null
-+++ b/security/apparmor/file.c
-@@ -0,0 +1,457 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor mediation of files
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#include "include/apparmor.h"
-+#include "include/audit.h"
-+#include "include/file.h"
-+#include "include/match.h"
-+#include "include/path.h"
-+#include "include/policy.h"
-+
-+struct file_perms nullperms;
-+
-+
-+/**
-+ * audit_file_mask - convert mask to permission string
-+ * @buffer: buffer to write string to (NOT NULL)
-+ * @mask: permission mask to convert
-+ */
-+static void audit_file_mask(struct audit_buffer *ab, u32 mask)
-+{
-+      char str[10];
-+
-+      char *m = str;
-+
-+      if (mask & AA_EXEC_MMAP)
-+              *m++ = 'm';
-+      if (mask & (MAY_READ | AA_MAY_META_READ))
-+              *m++ = 'r';
-+      if (mask & (MAY_WRITE | AA_MAY_META_WRITE | AA_MAY_CHMOD |
-+                  AA_MAY_CHOWN))
-+              *m++ = 'w';
-+      else if (mask & MAY_APPEND)
-+              *m++ = 'a';
-+      if (mask & AA_MAY_CREATE)
-+              *m++ = 'c';
-+      if (mask & AA_MAY_DELETE)
-+              *m++ = 'd';
-+      if (mask & AA_MAY_LINK)
-+              *m++ = 'l';
-+      if (mask & AA_MAY_LOCK)
-+              *m++ = 'k';
-+      if (mask & MAY_EXEC)
-+              *m++ = 'x';
-+      *m = '\0';
-+
-+      audit_log_string(ab, str);
-+}
-+
-+/**
-+ * file_audit_cb - call back for file specific audit fields
-+ * @ab: audit_buffer  (NOT NULL)
-+ * @va: audit struct to audit values of  (NOT NULL)
-+ */
-+static void file_audit_cb(struct audit_buffer *ab, void *va)
-+{
-+      struct common_audit_data *sa = va;
-+      uid_t fsuid = current_fsuid();
-+
-+      if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
-+              audit_log_format(ab, " requested_mask=");
-+              audit_file_mask(ab, sa->aad.fs.request);
-+      }
-+      if (sa->aad.fs.denied & AA_AUDIT_FILE_MASK) {
-+              audit_log_format(ab, " denied_mask=");
-+              audit_file_mask(ab, sa->aad.fs.denied);
-+      }
-+      if (sa->aad.fs.request & AA_AUDIT_FILE_MASK) {
-+              audit_log_format(ab, " fsuid=%d", fsuid);
-+              audit_log_format(ab, " ouid=%d", sa->aad.fs.ouid);
-+      }
-+
-+      if (sa->aad.fs.target) {
-+              audit_log_format(ab, " target=");
-+              audit_log_untrustedstring(ab, sa->aad.fs.target);
-+      }
-+}
-+
-+/**
-+ * aa_audit_file - handle the auditing of file operations
-+ * @profile: the profile being enforced  (NOT NULL)
-+ * @perms: the permissions computed for the request (NOT NULL)
-+ * @gfp: allocation flags
-+ * @op: operation being mediated
-+ * @request: permissions requested
-+ * @name: name of object being mediated (MAYBE NULL)
-+ * @target: name of target (MAYBE NULL)
-+ * @ouid: object uid
-+ * @info: extra information message (MAYBE NULL)
-+ * @error: 0 if operation allowed else failure error code
-+ *
-+ * Returns: %0 or error on failure
-+ */
-+int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
-+                gfp_t gfp, int op, u32 request, const char *name,
-+                const char *target, uid_t ouid, const char *info, int error)
-+{
-+      int type = AUDIT_APPARMOR_AUTO;
-+      struct common_audit_data sa;
-+      COMMON_AUDIT_DATA_INIT(&sa, NONE);
-+      sa.aad.op = op,
-+      sa.aad.fs.request = request;
-+      sa.aad.name = name;
-+      sa.aad.fs.target = target;
-+      sa.aad.fs.ouid = ouid;
-+      sa.aad.info = info;
-+      sa.aad.error = error;
-+
-+      if (likely(!sa.aad.error)) {
-+              u32 mask = perms->audit;
-+
-+              if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
-+                      mask = 0xffff;
-+
-+              /* mask off perms that are not being force audited */
-+              sa.aad.fs.request &= mask;
-+
-+              if (likely(!sa.aad.fs.request))
-+                      return 0;
-+              type = AUDIT_APPARMOR_AUDIT;
-+      } else {
-+              /* only report permissions that were denied */
-+              sa.aad.fs.request = sa.aad.fs.request & ~perms->allow;
-+
-+              if (sa.aad.fs.request & perms->kill)
-+                      type = AUDIT_APPARMOR_KILL;
-+
-+              /* quiet known rejects, assumes quiet and kill do not overlap */
-+              if ((sa.aad.fs.request & perms->quiet) &&
-+                  AUDIT_MODE(profile) != AUDIT_NOQUIET &&
-+                  AUDIT_MODE(profile) != AUDIT_ALL)
-+                      sa.aad.fs.request &= ~perms->quiet;
-+
-+              if (!sa.aad.fs.request)
-+                      return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
-+      }
-+
-+      sa.aad.fs.denied = sa.aad.fs.request & ~perms->allow;
-+      return aa_audit(type, profile, gfp, &sa, file_audit_cb);
-+}
-+
-+/**
-+ * map_old_perms - map old file perms layout to the new layout
-+ * @old: permission set in old mapping
-+ *
-+ * Returns: new permission mapping
-+ */
-+static u32 map_old_perms(u32 old)
-+{
-+      u32 new = old & 0xf;
-+      if (old & MAY_READ)
-+              new |= AA_MAY_META_READ;
-+      if (old & MAY_WRITE)
-+              new |= AA_MAY_META_WRITE | AA_MAY_CREATE | AA_MAY_DELETE |
-+                      AA_MAY_CHMOD | AA_MAY_CHOWN;
-+      if (old & 0x10)
-+              new |= AA_MAY_LINK;
-+      /* the old mapping lock and link_subset flags where overlaid
-+       * and use was determined by part of a pair that they were in
-+       */
-+      if (old & 0x20)
-+              new |= AA_MAY_LOCK | AA_LINK_SUBSET;
-+      if (old & 0x40) /* AA_EXEC_MMAP */
-+              new |= AA_EXEC_MMAP;
-+
-+      new |= AA_MAY_META_READ;
-+
-+      return new;
-+}
-+
-+/**
-+ * compute_perms - convert dfa compressed perms to internal perms
-+ * @dfa: dfa to compute perms for   (NOT NULL)
-+ * @state: state in dfa
-+ * @cond:  conditions to consider  (NOT NULL)
-+ *
-+ * TODO: convert from dfa + state to permission entry, do computation conversion
-+ *       at load time.
-+ *
-+ * Returns: computed permission set
-+ */
-+static struct file_perms compute_perms(struct aa_dfa *dfa, unsigned int state,
-+                                     struct path_cond *cond)
-+{
-+      struct file_perms perms;
-+
-+      /* FIXME: change over to new dfa format
-+       * currently file perms are encoded in the dfa, new format
-+       * splits the permissions from the dfa.  This mapping can be
-+       * done at profile load
-+       */
-+      perms.kill = 0;
-+
-+      if (current_fsuid() == cond->uid) {
-+              perms.allow = map_old_perms(dfa_user_allow(dfa, state));
-+              perms.audit = map_old_perms(dfa_user_audit(dfa, state));
-+              perms.quiet = map_old_perms(dfa_user_quiet(dfa, state));
-+              perms.xindex = dfa_user_xindex(dfa, state);
-+      } else {
-+              perms.allow = map_old_perms(dfa_other_allow(dfa, state));
-+              perms.audit = map_old_perms(dfa_other_audit(dfa, state));
-+              perms.quiet = map_old_perms(dfa_other_quiet(dfa, state));
-+              perms.xindex = dfa_other_xindex(dfa, state);
-+      }
-+
-+      /* change_profile wasn't determined by ownership in old mapping */
-+      if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
-+              perms.allow |= AA_MAY_CHANGE_PROFILE;
-+
-+      return perms;
-+}
-+
-+/**
-+ * aa_str_perms - find permission that match @name
-+ * @dfa: to match against  (MAYBE NULL)
-+ * @state: state to start matching in
-+ * @name: string to match against dfa  (NOT NULL)
-+ * @cond: conditions to consider for permission set computation  (NOT NULL)
-+ * @perms: Returns - the permissions found when matching @name
-+ *
-+ * Returns: the final state in @dfa when beginning @start and walking @name
-+ */
-+unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
-+                        const char *name, struct path_cond *cond,
-+                        struct file_perms *perms)
-+{
-+      unsigned int state;
-+      if (!dfa) {
-+              *perms = nullperms;
-+              return DFA_NOMATCH;
-+      }
-+
-+      state = aa_dfa_match(dfa, start, name);
-+      *perms = compute_perms(dfa, state, cond);
-+
-+      return state;
-+}
-+
-+/**
-+ * is_deleted - test if a file has been completely unlinked
-+ * @dentry: dentry of file to test for deletion  (NOT NULL)
-+ *
-+ * Returns: %1 if deleted else %0
-+ */
-+static inline bool is_deleted(struct dentry *dentry)
-+{
-+      if (d_unlinked(dentry) && dentry->d_inode->i_nlink == 0)
-+              return 1;
-+      return 0;
-+}
-+
-+/**
-+ * aa_path_perm - do permissions check & audit for @path
-+ * @op: operation being checked
-+ * @profile: profile being enforced  (NOT NULL)
-+ * @path: path to check permissions of  (NOT NULL)
-+ * @flags: any additional path flags beyond what the profile specifies
-+ * @request: requested permissions
-+ * @cond: conditional info for this request  (NOT NULL)
-+ *
-+ * Returns: %0 else error if access denied or other error
-+ */
-+int aa_path_perm(int op, struct aa_profile *profile, struct path *path,
-+               int flags, u32 request, struct path_cond *cond)
-+{
-+      char *buffer = NULL;
-+      struct file_perms perms = {};
-+      const char *name, *info = NULL;
-+      int error;
-+
-+      flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0);
-+      error = aa_get_name(path, flags, &buffer, &name);
-+      if (error) {
-+              if (error == -ENOENT && is_deleted(path->dentry)) {
-+                      /* Access to open files that are deleted are
-+                       * give a pass (implicit delegation)
-+                       */
-+                      error = 0;
-+                      perms.allow = request;
-+              } else if (error == -ENOENT)
-+                      info = "Failed name lookup - deleted entry";
-+              else if (error == -ESTALE)
-+                      info = "Failed name lookup - disconnected path";
-+              else if (error == -ENAMETOOLONG)
-+                      info = "Failed name lookup - name too long";
-+              else
-+                      info = "Failed name lookup";
-+      } else {
-+              aa_str_perms(profile->file.dfa, profile->file.start, name, cond,
-+                           &perms);
-+              if (request & ~perms.allow)
-+                      error = -EACCES;
-+      }
-+      error = aa_audit_file(profile, &perms, GFP_KERNEL, op, request, name,
-+                            NULL, cond->uid, info, error);
++      error = audit_mount(profile, GFP_KERNEL, OP_UMOUNT, name, NULL, NULL,
++                          NULL, 0, NULL, AA_MAY_UMOUNT, &perms, info, error);
 +      kfree(buffer);
 +
 +      return error;
 +}
 +
-+/**
-+ * xindex_is_subset - helper for aa_path_link
-+ * @link: link permission set
-+ * @target: target permission set
-+ *
-+ * test target x permissions are equal OR a subset of link x permissions
-+ * this is done as part of the subset test, where a hardlink must have
-+ * a subset of permissions that the target has.
-+ *
-+ * Returns: %1 if subset else %0
-+ */
-+static inline bool xindex_is_subset(u32 link, u32 target)
-+{
-+      if (((link & ~AA_X_UNSAFE) != (target & ~AA_X_UNSAFE)) ||
-+          ((link & AA_X_UNSAFE) && !(target & AA_X_UNSAFE)))
-+              return 0;
-+
-+      return 1;
-+}
-+
-+/**
-+ * aa_path_link - Handle hard link permission check
-+ * @profile: the profile being enforced  (NOT NULL)
-+ * @old_dentry: the target dentry  (NOT NULL)
-+ * @new_dir: directory the new link will be created in  (NOT NULL)
-+ * @new_dentry: the link being created  (NOT NULL)
-+ *
-+ * Handle the permission test for a link & target pair.  Permission
-+ * is encoded as a pair where the link permission is determined
-+ * first, and if allowed, the target is tested.  The target test
-+ * is done from the point of the link match (not start of DFA)
-+ * making the target permission dependent on the link permission match.
-+ *
-+ * The subset test if required forces that permissions granted
-+ * on link are a subset of the permission granted to target.
-+ *
-+ * Returns: %0 if allowed else error
-+ */
-+int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
-+               struct path *new_dir, struct dentry *new_dentry)
++int aa_pivotroot(struct aa_profile *profile, const struct path *old_path,
++               const struct path *new_path)
 +{
-+      struct path link = { new_dir->mnt, new_dentry };
-+      struct path target = { new_dir->mnt, old_dentry };
-+      struct path_cond cond = {
-+              old_dentry->d_inode->i_uid,
-+              old_dentry->d_inode->i_mode
-+      };
-+      char *buffer = NULL, *buffer2 = NULL;
-+      const char *lname, *tname = NULL, *info = NULL;
-+      struct file_perms lperms, perms;
-+      u32 request = AA_MAY_LINK;
-+      unsigned int state;
++      struct file_perms perms = { };
++      struct aa_profile *target = NULL;
++      char *old_buffer = NULL, *new_buffer = NULL;
++      const char *old_name, *new_name = NULL, *info = NULL;
 +      int error;
 +
-+      lperms = nullperms;
-+
-+      /* buffer freed below, lname is pointer in buffer */
-+      error = aa_get_name(&link, profile->path_flags, &buffer, &lname);
++      error = aa_path_name(old_path, path_flags(profile, old_path),
++                           &old_buffer, &old_name, &info);
 +      if (error)
 +              goto audit;
 +
-+      /* buffer2 freed below, tname is pointer in buffer2 */
-+      error = aa_get_name(&target, profile->path_flags, &buffer2, &tname);
++      error = aa_path_name(new_path, path_flags(profile, new_path),
++                           &new_buffer, &new_name, &info);
 +      if (error)
 +              goto audit;
 +
-+      error = -EACCES;
-+      /* aa_str_perms - handles the case of the dfa being NULL */
-+      state = aa_str_perms(profile->file.dfa, profile->file.start, lname,
-+                           &cond, &lperms);
-+
-+      if (!(lperms.allow & AA_MAY_LINK))
-+              goto audit;
-+
-+      /* test to see if target can be paired with link */
-+      state = aa_dfa_null_transition(profile->file.dfa, state);
-+      aa_str_perms(profile->file.dfa, state, tname, &cond, &perms);
-+
-+      /* force audit/quiet masks for link are stored in the second entry
-+       * in the link pair.
-+       */
-+      lperms.audit = perms.audit;
-+      lperms.quiet = perms.quiet;
-+      lperms.kill = perms.kill;
-+
-+      if (!(perms.allow & AA_MAY_LINK)) {
-+              info = "target restricted";
-+              goto audit;
++      if (profile->policy.dfa) {
++              unsigned int state;
++              state = aa_dfa_match(profile->policy.dfa,
++                                   profile->policy.start[AA_CLASS_MOUNT],
++                                   new_name);
++              state = aa_dfa_null_transition(profile->policy.dfa, state);
++              state = aa_dfa_match(profile->policy.dfa, state, old_name);
++              perms = compute_mnt_perms(profile->policy.dfa, state);
 +      }
 +
-+      /* done if link subset test is not required */
-+      if (!(perms.allow & AA_LINK_SUBSET))
-+              goto done_tests;
-+
-+      /* Do link perm subset test requiring allowed permission on link are a
-+       * subset of the allowed permissions on target.
-+       */
-+      aa_str_perms(profile->file.dfa, profile->file.start, tname, &cond,
-+                   &perms);
-+
-+      /* AA_MAY_LINK is not considered in the subset test */
-+      request = lperms.allow & ~AA_MAY_LINK;
-+      lperms.allow &= perms.allow | AA_MAY_LINK;
-+
-+      request |= AA_AUDIT_FILE_MASK & (lperms.allow & ~perms.allow);
-+      if (request & ~lperms.allow) {
-+              goto audit;
-+      } else if ((lperms.allow & MAY_EXEC) &&
-+                 !xindex_is_subset(lperms.xindex, perms.xindex)) {
-+              lperms.allow &= ~MAY_EXEC;
-+              request |= MAY_EXEC;
-+              info = "link not subset of target";
-+              goto audit;
-+      }
-+
-+done_tests:
-+      error = 0;
++      if (AA_MAY_PIVOTROOT & perms.allow) {
++              if ((perms.xindex & AA_X_TYPE_MASK) == AA_X_TABLE) {
++                      target = x_table_lookup(profile, perms.xindex);
++                      if (!target)
++                              error = -ENOENT;
++                      else
++                              error = aa_replace_current_profile(target);
++              }
++      } else
++              error = -EACCES;
 +
 +audit:
-+      error = aa_audit_file(profile, &lperms, GFP_KERNEL, OP_LINK, request,
-+                            lname, tname, cond.uid, info, error);
-+      kfree(buffer);
-+      kfree(buffer2);
-+
-+      return error;
-+}
-+
-+/**
-+ * aa_file_perm - do permission revalidation check & audit for @file
-+ * @op: operation being checked
-+ * @profile: profile being enforced   (NOT NULL)
-+ * @file: file to revalidate access permissions on  (NOT NULL)
-+ * @request: requested permissions
-+ *
-+ * Returns: %0 if access allowed else error
-+ */
-+int aa_file_perm(int op, struct aa_profile *profile, struct file *file,
-+               u32 request)
-+{
-+      struct path_cond cond = {
-+              .uid = file->f_path.dentry->d_inode->i_uid,
-+              .mode = file->f_path.dentry->d_inode->i_mode
-+      };
-+
-+      return aa_path_perm(op, profile, &file->f_path, PATH_DELEGATE_DELETED,
-+                          request, &cond);
-+}
-diff --git a/security/apparmor/include/apparmor.h b/security/apparmor/include/apparmor.h
-new file mode 100644
-index 0000000..38ccaea
---- /dev/null
-+++ b/security/apparmor/include/apparmor.h
-@@ -0,0 +1,92 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor basic global and lib definitions
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __APPARMOR_H
-+#define __APPARMOR_H
-+
-+#include <linux/fs.h>
-+
-+#include "match.h"
-+
-+/* Control parameters settable through module/boot flags */
-+extern enum audit_mode aa_g_audit;
-+extern int aa_g_audit_header;
-+extern int aa_g_debug;
-+extern int aa_g_lock_policy;
-+extern int aa_g_logsyscall;
-+extern int aa_g_paranoid_load;
-+extern unsigned int aa_g_path_max;
-+
-+/*
-+ * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
-+ * which is not related to profile accesses.
-+ */
-+
-+#define AA_DEBUG(fmt, args...)                                                \
-+      do {                                                            \
-+              if (aa_g_debug && printk_ratelimit())                   \
-+                      printk(KERN_DEBUG "AppArmor: " fmt, ##args);    \
-+      } while (0)
-+
-+#define AA_ERROR(fmt, args...)                                                \
-+      do {                                                            \
-+              if (printk_ratelimit())                                 \
-+                      printk(KERN_ERR "AppArmor: " fmt, ##args);      \
-+      } while (0)
-+
-+/* Flag indicating whether initialization completed */
-+extern int apparmor_initialized __initdata;
-+
-+/* fn's in lib */
-+char *aa_split_fqname(char *args, char **ns_name);
-+void aa_info_message(const char *str);
-+void *kvmalloc(size_t size);
-+void kvfree(void *buffer);
-+
-+
-+/**
-+ * aa_strneq - compare null terminated @str to a non null terminated substring
-+ * @str: a null terminated string
-+ * @sub: a substring, not necessarily null terminated
-+ * @len: length of @sub to compare
-+ *
-+ * The @str string must be full consumed for this to be considered a match
-+ */
-+static inline bool aa_strneq(const char *str, const char *sub, int len)
-+{
-+      return !strncmp(str, sub, len) && !str[len];
-+}
-+
-+/**
-+ * aa_dfa_null_transition - step to next state after null character
-+ * @dfa: the dfa to match against
-+ * @start: the state of the dfa to start matching in
-+ *
-+ * aa_dfa_null_transition transitions to the next state after a null
-+ * character which is not used in standard matching and is only
-+ * used to separate pairs.
-+ */
-+static inline unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
-+                                                unsigned int start)
-+{
-+      /* the null transition only needs the string's null terminator byte */
-+      return aa_dfa_match_len(dfa, start, "", 1);
-+}
-+
-+static inline bool mediated_filesystem(struct inode *inode)
-+{
-+      return !(inode->i_sb->s_flags & MS_NOUSER);
-+}
-+
-+#endif /* __APPARMOR_H */
-diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
-new file mode 100644
-index 0000000..14f955c
---- /dev/null
-+++ b/security/apparmor/include/apparmorfs.h
-@@ -0,0 +1,26 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor filesystem definitions.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __AA_APPARMORFS_H
-+#define __AA_APPARMORFS_H
-+
-+extern void __init aa_destroy_aafs(void);
-+
-+#ifdef CONFIG_SECURITY_APPARMOR_COMPAT_24
-+extern const struct file_operations aa_fs_matching_fops;
-+extern const struct file_operations aa_fs_features_fops;
-+extern const struct file_operations aa_fs_profiles_fops;
-+#endif
-+
-+#endif /* __AA_APPARMORFS_H */
-diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
-new file mode 100644
-index 0000000..1951786
---- /dev/null
-+++ b/security/apparmor/include/audit.h
-@@ -0,0 +1,123 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor auditing function definitions.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __AA_AUDIT_H
-+#define __AA_AUDIT_H
-+
-+#include <linux/audit.h>
-+#include <linux/fs.h>
-+#include <linux/lsm_audit.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+
-+#include "file.h"
-+
-+struct aa_profile;
-+
-+extern const char *audit_mode_names[];
-+#define AUDIT_MAX_INDEX 5
-+
-+#define AUDIT_APPARMOR_AUTO 0 /* auto choose audit message type */
-+
-+enum audit_mode {
-+      AUDIT_NORMAL,           /* follow normal auditing of accesses */
-+      AUDIT_QUIET_DENIED,     /* quiet all denied access messages */
-+      AUDIT_QUIET,            /* quiet all messages */
-+      AUDIT_NOQUIET,          /* do not quiet audit messages */
-+      AUDIT_ALL               /* audit all accesses */
-+};
-+
-+enum audit_type {
-+      AUDIT_APPARMOR_AUDIT,
-+      AUDIT_APPARMOR_ALLOWED,
-+      AUDIT_APPARMOR_DENIED,
-+      AUDIT_APPARMOR_HINT,
-+      AUDIT_APPARMOR_STATUS,
-+      AUDIT_APPARMOR_ERROR,
-+      AUDIT_APPARMOR_KILL
-+};
-+
-+extern const char *op_table[];
-+enum aa_ops {
-+      OP_NULL,
-+
-+      OP_SYSCTL,
-+      OP_CAPABLE,
-+
-+      OP_UNLINK,
-+      OP_MKDIR,
-+      OP_RMDIR,
-+      OP_MKNOD,
-+      OP_TRUNC,
-+      OP_LINK,
-+      OP_SYMLINK,
-+      OP_RENAME_SRC,
-+      OP_RENAME_DEST,
-+      OP_CHMOD,
-+      OP_CHOWN,
-+      OP_GETATTR,
-+      OP_OPEN,
-+
-+      OP_FPERM,
-+      OP_FLOCK,
-+      OP_FMMAP,
-+      OP_FMPROT,
-+
-+      OP_CREATE,
-+      OP_POST_CREATE,
-+      OP_BIND,
-+      OP_CONNECT,
-+      OP_LISTEN,
-+      OP_ACCEPT,
-+      OP_SENDMSG,
-+      OP_RECVMSG,
-+      OP_GETSOCKNAME,
-+      OP_GETPEERNAME,
-+      OP_GETSOCKOPT,
-+      OP_SETSOCKOPT,
-+      OP_SOCK_SHUTDOWN,
-+
-+      OP_PTRACE,
-+
-+      OP_EXEC,
-+      OP_CHANGE_HAT,
-+      OP_CHANGE_PROFILE,
-+      OP_CHANGE_ONEXEC,
-+
-+      OP_SETPROCATTR,
-+      OP_SETRLIMIT,
-+
-+      OP_PROF_REPL,
-+      OP_PROF_LOAD,
-+      OP_PROF_RM,
-+};
-+
-+
-+/* define a short hand for apparmor_audit_data portion of common_audit_data */
-+#define aad apparmor_audit_data
-+
-+void aa_audit_msg(int type, struct common_audit_data *sa,
-+                void (*cb) (struct audit_buffer *, void *));
-+int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
-+           struct common_audit_data *sa,
-+           void (*cb) (struct audit_buffer *, void *));
++      error = audit_mount(profile, GFP_KERNEL, OP_PIVOTROOT, new_name,
++                          old_name, NULL, target ? target->base.name : NULL,
++                          0, NULL,  AA_MAY_PIVOTROOT, &perms, info, error);
++      aa_put_profile(target);
++      kfree(old_buffer);
++      kfree(new_buffer);
 +
-+static inline int complain_error(int error)
-+{
-+      if (error == -EPERM || error == -EACCES)
-+              return 0;
 +      return error;
 +}
-+
-+#endif /* __AA_AUDIT_H */
-diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h
-new file mode 100644
-index 0000000..c24d295
---- /dev/null
-+++ b/security/apparmor/include/capability.h
-@@ -0,0 +1,45 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor capability mediation definitions.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __AA_CAPABILITY_H
-+#define __AA_CAPABILITY_H
-+
-+#include <linux/sched.h>
-+
-+struct aa_profile;
-+
-+/* aa_caps - confinement data for capabilities
-+ * @allowed: capabilities mask
-+ * @audit: caps that are to be audited
-+ * @quiet: caps that should not be audited
-+ * @kill: caps that when requested will result in the task being killed
-+ * @extended: caps that are subject finer grained mediation
-+ */
-+struct aa_caps {
-+      kernel_cap_t allow;
-+      kernel_cap_t audit;
-+      kernel_cap_t quiet;
-+      kernel_cap_t kill;
-+      kernel_cap_t extended;
-+};
-+
-+int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
-+             int audit);
-+
-+static inline void aa_free_cap_rules(struct aa_caps *caps)
-+{
-+      /* NOP */
-+}
-+
-+#endif /* __AA_CAPBILITY_H */
-diff --git a/security/apparmor/include/context.h b/security/apparmor/include/context.h
-new file mode 100644
-index 0000000..a9cbee4
---- /dev/null
-+++ b/security/apparmor/include/context.h
-@@ -0,0 +1,154 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor contexts used to associate "labels" to objects.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __AA_CONTEXT_H
-+#define __AA_CONTEXT_H
-+
-+#include <linux/cred.h>
-+#include <linux/slab.h>
-+#include <linux/sched.h>
-+
-+#include "policy.h"
-+
-+/* struct aa_file_cxt - the AppArmor context the file was opened in
-+ * @perms: the permission the file was opened with
-+ *
-+ * The file_cxt could currently be directly stored in file->f_security
-+ * as the profile reference is now stored in the f_cred.  However the
-+ * cxt struct will expand in the future so we keep the struct.
-+ */
-+struct aa_file_cxt {
-+      u16 allow;
-+};
-+
-+/**
-+ * aa_alloc_file_context - allocate file_cxt
-+ * @gfp: gfp flags for allocation
-+ *
-+ * Returns: file_cxt or NULL on failure
-+ */
-+static inline struct aa_file_cxt *aa_alloc_file_context(gfp_t gfp)
-+{
-+      return kzalloc(sizeof(struct aa_file_cxt), gfp);
-+}
-+
-+/**
-+ * aa_free_file_context - free a file_cxt
-+ * @cxt: file_cxt to free  (MAYBE_NULL)
-+ */
-+static inline void aa_free_file_context(struct aa_file_cxt *cxt)
-+{
-+      if (cxt)
-+              kzfree(cxt);
-+}
-+
-+/**
-+ * struct aa_task_cxt - primary label for confined tasks
-+ * @profile: the current profile   (NOT NULL)
-+ * @exec: profile to transition to on next exec  (MAYBE NULL)
-+ * @previous: profile the task may return to     (MAYBE NULL)
-+ * @token: magic value the task must know for returning to @previous_profile
-+ *
-+ * Contains the task's current profile (which could change due to
-+ * change_hat).  Plus the hat_magic needed during change_hat.
-+ *
-+ * TODO: make so a task can be confined by a stack of contexts
-+ */
-+struct aa_task_cxt {
-+      struct aa_profile *profile;
-+      struct aa_profile *onexec;
-+      struct aa_profile *previous;
-+      u64 token;
-+};
-+
-+struct aa_task_cxt *aa_alloc_task_context(gfp_t flags);
-+void aa_free_task_context(struct aa_task_cxt *cxt);
-+void aa_dup_task_context(struct aa_task_cxt *new,
-+                       const struct aa_task_cxt *old);
-+int aa_replace_current_profile(struct aa_profile *profile);
-+int aa_set_current_onexec(struct aa_profile *profile);
-+int aa_set_current_hat(struct aa_profile *profile, u64 token);
-+int aa_restore_previous_profile(u64 cookie);
-+
-+/**
-+ * __aa_task_is_confined - determine if @task has any confinement
-+ * @task: task to check confinement of  (NOT NULL)
-+ *
-+ * If @task != current needs to be called in RCU safe critical section
-+ */
-+static inline bool __aa_task_is_confined(struct task_struct *task)
-+{
-+      struct aa_task_cxt *cxt = __task_cred(task)->security;
-+
-+      BUG_ON(!cxt || !cxt->profile);
-+      if (unconfined(aa_newest_version(cxt->profile)))
-+              return 0;
-+
-+      return 1;
-+}
-+
-+/**
-+ * aa_cred_profile - obtain cred's profiles
-+ * @cred: cred to obtain profiles from  (NOT NULL)
-+ *
-+ * Returns: confining profile
-+ *
-+ * does NOT increment reference count
-+ */
-+static inline struct aa_profile *aa_cred_profile(const struct cred *cred)
-+{
-+      struct aa_task_cxt *cxt = cred->security;
-+      BUG_ON(!cxt || !cxt->profile);
-+      return aa_newest_version(cxt->profile);
-+}
-+
-+/**
-+ * __aa_current_profile - find the current tasks confining profile
-+ *
-+ * Returns: up to date confining profile or the ns unconfined profile (NOT NULL)
-+ *
-+ * This fn will not update the tasks cred to the most up to date version
-+ * of the profile so it is safe to call when inside of locks.
-+ */
-+static inline struct aa_profile *__aa_current_profile(void)
-+{
-+      return aa_cred_profile(current_cred());
-+}
-+
-+/**
-+ * aa_current_profile - find the current tasks confining profile and do updates
-+ *
-+ * Returns: up to date confining profile or the ns unconfined profile (NOT NULL)
-+ *
-+ * This fn will update the tasks cred structure if the profile has been
-+ * replaced.  Not safe to call inside locks
-+ */
-+static inline struct aa_profile *aa_current_profile(void)
-+{
-+      const struct aa_task_cxt *cxt = current_cred()->security;
-+      struct aa_profile *profile;
-+      BUG_ON(!cxt || !cxt->profile);
-+
-+      profile = aa_newest_version(cxt->profile);
-+      /*
-+       * Whether or not replacement succeeds, use newest profile so
-+       * there is no need to update it after replacement.
-+       */
-+      if (unlikely((cxt->profile != profile)))
-+              aa_replace_current_profile(profile);
-+
-+      return profile;
-+}
-+
-+#endif /* __AA_CONTEXT_H */
-diff --git a/security/apparmor/include/domain.h b/security/apparmor/include/domain.h
-new file mode 100644
-index 0000000..de04464
---- /dev/null
-+++ b/security/apparmor/include/domain.h
-@@ -0,0 +1,36 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor security domain transition function definitions.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#include <linux/binfmts.h>
-+#include <linux/types.h>
-+
-+#ifndef __AA_DOMAIN_H
-+#define __AA_DOMAIN_H
-+
-+struct aa_domain {
-+      int size;
-+      char **table;
-+};
-+
-+int apparmor_bprm_set_creds(struct linux_binprm *bprm);
-+int apparmor_bprm_secureexec(struct linux_binprm *bprm);
-+void apparmor_bprm_committing_creds(struct linux_binprm *bprm);
-+void apparmor_bprm_committed_creds(struct linux_binprm *bprm);
-+
-+void aa_free_domain_entries(struct aa_domain *domain);
-+int aa_change_hat(const char *hats[], int count, u64 token, bool permtest);
-+int aa_change_profile(const char *ns_name, const char *name, bool onexec,
-+                    bool permtest);
-+
-+#endif /* __AA_DOMAIN_H */
-diff --git a/security/apparmor/include/file.h b/security/apparmor/include/file.h
-new file mode 100644
-index 0000000..be36fea
---- /dev/null
-+++ b/security/apparmor/include/file.h
-@@ -0,0 +1,217 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor file mediation function definitions.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __AA_FILE_H
-+#define __AA_FILE_H
-+
-+#include <linux/path.h>
-+
-+#include "domain.h"
-+#include "match.h"
-+
-+struct aa_profile;
-+
-+/*
-+ * We use MAY_EXEC, MAY_WRITE, MAY_READ, MAY_APPEND and the following flags
-+ * for profile permissions
-+ */
-+#define AA_MAY_CREATE                  0x0010
-+#define AA_MAY_DELETE                  0x0020
-+#define AA_MAY_META_WRITE              0x0040
-+#define AA_MAY_META_READ               0x0080
-+
-+#define AA_MAY_CHMOD                   0x0100
-+#define AA_MAY_CHOWN                   0x0200
-+#define AA_MAY_LOCK                    0x0400
-+#define AA_EXEC_MMAP                   0x0800
-+
-+#define AA_MAY_LINK                   0x1000
-+#define AA_LINK_SUBSET                        AA_MAY_LOCK     /* overlaid */
-+#define AA_MAY_ONEXEC                 0x40000000      /* exec allows onexec */
-+#define AA_MAY_CHANGE_PROFILE         0x80000000
-+#define AA_MAY_CHANGEHAT              0x80000000      /* ctrl auditing only */
-+
-+#define AA_AUDIT_FILE_MASK    (MAY_READ | MAY_WRITE | MAY_EXEC | MAY_APPEND |\
-+                               AA_MAY_CREATE | AA_MAY_DELETE |        \
-+                               AA_MAY_META_READ | AA_MAY_META_WRITE | \
-+                               AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_LOCK | \
-+                               AA_EXEC_MMAP | AA_MAY_LINK)
-+
-+/*
-+ * The xindex is broken into 3 parts
-+ * - index - an index into either the exec name table or the variable table
-+ * - exec type - which determines how the executable name and index are used
-+ * - flags - which modify how the destination name is applied
-+ */
-+#define AA_X_INDEX_MASK               0x03ff
-+
-+#define AA_X_TYPE_MASK                0x0c00
-+#define AA_X_TYPE_SHIFT               10
-+#define AA_X_NONE             0x0000
-+#define AA_X_NAME             0x0400  /* use executable name px */
-+#define AA_X_TABLE            0x0800  /* use a specified name ->n# */
-+
-+#define AA_X_UNSAFE           0x1000
-+#define AA_X_CHILD            0x2000  /* make >AA_X_NONE apply to children */
-+#define AA_X_INHERIT          0x4000
-+#define AA_X_UNCONFINED               0x8000
-+
-+/* AA_SECURE_X_NEEDED - is passed in the bprm->unsafe field */
-+#define AA_SECURE_X_NEEDED    0x8000
-+
-+/* need to make conditional which ones are being set */
-+struct path_cond {
-+      uid_t uid;
-+      umode_t mode;
-+};
-+
-+/* struct file_perms - file permission
-+ * @allow: mask of permissions that are allowed
-+ * @audit: mask of permissions to force an audit message for
-+ * @quiet: mask of permissions to quiet audit messages for
-+ * @kill: mask of permissions that when matched will kill the task
-+ * @xindex: exec transition index if @allow contains MAY_EXEC
-+ *
-+ * The @audit and @queit mask should be mutually exclusive.
-+ */
-+struct file_perms {
-+      u32 allow;
-+      u32 audit;
-+      u32 quiet;
-+      u32 kill;
-+      u16 xindex;
-+};
-+
-+extern struct file_perms nullperms;
-+
-+#define COMBINED_PERM_MASK(X) ((X).allow | (X).audit | (X).quiet | (X).kill)
-+
-+/* FIXME: split perms from dfa and match this to description
-+ *        also add delegation info.
-+ */
-+static inline u16 dfa_map_xindex(u16 mask)
-+{
-+      u16 old_index = (mask >> 10) & 0xf;
-+      u16 index = 0;
-+
-+      if (mask & 0x100)
-+              index |= AA_X_UNSAFE;
-+      if (mask & 0x200)
-+              index |= AA_X_INHERIT;
-+      if (mask & 0x80)
-+              index |= AA_X_UNCONFINED;
-+
-+      if (old_index == 1) {
-+              index |= AA_X_UNCONFINED;
-+      } else if (old_index == 2) {
-+              index |= AA_X_NAME;
-+      } else if (old_index == 3) {
-+              index |= AA_X_NAME | AA_X_CHILD;
-+      } else {
-+              index |= AA_X_TABLE;
-+              index |= old_index - 4;
-+      }
-+
-+      return index;
-+}
-+
-+/*
-+ * map old dfa inline permissions to new format
-+ */
-+#define dfa_user_allow(dfa, state) (((ACCEPT_TABLE(dfa)[state]) & 0x7f) | \
-+                                  ((ACCEPT_TABLE(dfa)[state]) & 0x80000000))
-+#define dfa_user_audit(dfa, state) ((ACCEPT_TABLE2(dfa)[state]) & 0x7f)
-+#define dfa_user_quiet(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 7) & 0x7f)
-+#define dfa_user_xindex(dfa, state) \
-+      (dfa_map_xindex(ACCEPT_TABLE(dfa)[state] & 0x3fff))
-+
-+#define dfa_other_allow(dfa, state) ((((ACCEPT_TABLE(dfa)[state]) >> 14) & \
-+                                    0x7f) |                           \
-+                                   ((ACCEPT_TABLE(dfa)[state]) & 0x80000000))
-+#define dfa_other_audit(dfa, state) (((ACCEPT_TABLE2(dfa)[state]) >> 14) & 0x7f)
-+#define dfa_other_quiet(dfa, state) \
-+      ((((ACCEPT_TABLE2(dfa)[state]) >> 7) >> 14) & 0x7f)
-+#define dfa_other_xindex(dfa, state) \
-+      dfa_map_xindex((ACCEPT_TABLE(dfa)[state] >> 14) & 0x3fff)
-+
-+int aa_audit_file(struct aa_profile *profile, struct file_perms *perms,
-+                gfp_t gfp, int op, u32 request, const char *name,
-+                const char *target, uid_t ouid, const char *info, int error);
-+
-+/**
-+ * struct aa_file_rules - components used for file rule permissions
-+ * @dfa: dfa to match path names and conditionals against
-+ * @perms: permission table indexed by the matched state accept entry of @dfa
-+ * @trans: transition table for indexed by named x transitions
-+ *
-+ * File permission are determined by matching a path against @dfa and then
-+ * then using the value of the accept entry for the matching state as
-+ * an index into @perms.  If a named exec transition is required it is
-+ * looked up in the transition table.
-+ */
-+struct aa_file_rules {
-+      unsigned int start;
-+      struct aa_dfa *dfa;
-+      /* struct perms perms; */
-+      struct aa_domain trans;
-+      /* TODO: add delegate table */
-+};
-+
-+unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
-+                        const char *name, struct path_cond *cond,
-+                        struct file_perms *perms);
-+
-+int aa_path_perm(int op, struct aa_profile *profile, struct path *path,
-+               int flags, u32 request, struct path_cond *cond);
-+
-+int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
-+               struct path *new_dir, struct dentry *new_dentry);
-+
-+int aa_file_perm(int op, struct aa_profile *profile, struct file *file,
-+               u32 request);
-+
-+static inline void aa_free_file_rules(struct aa_file_rules *rules)
-+{
-+      aa_put_dfa(rules->dfa);
-+      aa_free_domain_entries(&rules->trans);
-+}
-+
-+#define ACC_FMODE(x) (("\000\004\002\006"[(x)&O_ACCMODE]) | (((x) << 1) & 0x40))
-+
-+/* from namei.c */
-+#define MAP_OPEN_FLAGS(x) ((((x) + 1) & O_ACCMODE) ? (x) + 1 : (x))
-+
-+/**
-+ * aa_map_file_perms - map file flags to AppArmor permissions
-+ * @file: open file to map flags to AppArmor permissions
-+ *
-+ * Returns: apparmor permission set for the file
-+ */
-+static inline u32 aa_map_file_to_perms(struct file *file)
-+{
-+      int flags = MAP_OPEN_FLAGS(file->f_flags);
-+      u32 perms = ACC_FMODE(file->f_mode);
-+
-+      if ((flags & O_APPEND) && (perms & MAY_WRITE))
-+              perms = (perms & ~MAY_WRITE) | MAY_APPEND;
-+      /* trunc implies write permission */
-+      if (flags & O_TRUNC)
-+              perms |= MAY_WRITE;
-+      if (flags & O_CREAT)
-+              perms |= AA_MAY_CREATE;
-+
-+      return perms;
-+}
-+
-+#endif /* __AA_FILE_H */
-diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h
-new file mode 100644
-index 0000000..aeda0fb
---- /dev/null
-+++ b/security/apparmor/include/ipc.h
-@@ -0,0 +1,28 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor ipc mediation function definitions.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __AA_IPC_H
-+#define __AA_IPC_H
-+
-+#include <linux/sched.h>
-+
-+struct aa_profile;
-+
-+int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
-+                struct aa_profile *tracee, unsigned int mode);
-+
-+int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
-+            unsigned int mode);
-+
-+#endif /* __AA_IPC_H */
-diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
-new file mode 100644
-index 0000000..734a6d3
---- /dev/null
-+++ b/security/apparmor/include/match.h
-@@ -0,0 +1,132 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor policy dfa matching engine definitions.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __AA_MATCH_H
-+#define __AA_MATCH_H
-+
-+#include <linux/workqueue.h>
-+
-+#define DFA_NOMATCH                   0
-+#define DFA_START                     1
-+
-+#define DFA_VALID_PERM_MASK           0xffffffff
-+#define DFA_VALID_PERM2_MASK          0xffffffff
-+
-+/**
-+ * The format used for transition tables is based on the GNU flex table
-+ * file format (--tables-file option; see Table File Format in the flex
-+ * info pages and the flex sources for documentation). The magic number
-+ * used in the header is 0x1B5E783D insted of 0xF13C57B1 though, because
-+ * the YY_ID_CHK (check) and YY_ID_DEF (default) tables are used
-+ * slightly differently (see the apparmor-parser package).
-+ */
-+
-+#define YYTH_MAGIC    0x1B5E783D
-+#define YYTH_DEF_RECURSE 0x1                  /* DEF Table is recursive */
-+
-+struct table_set_header {
-+      u32 th_magic;           /* YYTH_MAGIC */
-+      u32 th_hsize;
-+      u32 th_ssize;
-+      u16 th_flags;
-+      char th_version[];
-+};
-+
-+/* The YYTD_ID are one less than flex table mappings.  The flex id
-+ * has 1 subtracted at table load time, this allows us to directly use the
-+ * ID's as indexes.
-+ */
-+#define       YYTD_ID_ACCEPT  0
-+#define YYTD_ID_BASE  1
-+#define YYTD_ID_CHK   2
-+#define YYTD_ID_DEF   3
-+#define YYTD_ID_EC    4
-+#define YYTD_ID_META  5
-+#define YYTD_ID_ACCEPT2 6
-+#define YYTD_ID_NXT   7
-+#define YYTD_ID_TSIZE 8
-+
-+#define YYTD_DATA8    1
-+#define YYTD_DATA16   2
-+#define YYTD_DATA32   4
-+#define YYTD_DATA64   8
-+
-+/* Each ACCEPT2 table gets 6 dedicated flags, YYTD_DATAX define the
-+ * first flags
-+ */
-+#define ACCEPT1_FLAGS(X) ((X) & 0x3f)
-+#define ACCEPT2_FLAGS(X) ACCEPT1_FLAGS((X) >> YYTD_ID_ACCEPT2)
-+#define TO_ACCEPT1_FLAG(X) ACCEPT1_FLAGS(X)
-+#define TO_ACCEPT2_FLAG(X) (ACCEPT1_FLAGS(X) << YYTD_ID_ACCEPT2)
-+#define DFA_FLAG_VERIFY_STATES 0x1000
-+
-+struct table_header {
-+      u16 td_id;
-+      u16 td_flags;
-+      u32 td_hilen;
-+      u32 td_lolen;
-+      char td_data[];
-+};
-+
-+#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF]->td_data))
-+#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE]->td_data))
-+#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT]->td_data))
-+#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK]->td_data))
-+#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC]->td_data))
-+#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT]->td_data))
-+#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2]->td_data))
-+
-+struct aa_dfa {
-+      struct kref count;
-+      u16 flags;
-+      struct table_header *tables[YYTD_ID_TSIZE];
-+};
-+
-+#define byte_to_byte(X) (X)
-+
-+#define UNPACK_ARRAY(TABLE, BLOB, LEN, TYPE, NTOHX) \
-+      do { \
-+              typeof(LEN) __i; \
-+              TYPE *__t = (TYPE *) TABLE; \
-+              TYPE *__b = (TYPE *) BLOB; \
-+              for (__i = 0; __i < LEN; __i++) { \
-+                      __t[__i] = NTOHX(__b[__i]); \
-+              } \
-+      } while (0)
-+
-+static inline size_t table_size(size_t len, size_t el_size)
-+{
-+      return ALIGN(sizeof(struct table_header) + len * el_size, 8);
-+}
-+
-+struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags);
-+unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
-+                            const char *str, int len);
-+unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
-+                        const char *str);
-+void aa_dfa_free_kref(struct kref *kref);
-+
-+/**
-+ * aa_put_dfa - put a dfa refcount
-+ * @dfa: dfa to put refcount   (MAYBE NULL)
-+ *
-+ * Requires: if @dfa != NULL that a valid refcount be held
-+ */
-+static inline void aa_put_dfa(struct aa_dfa *dfa)
-+{
-+      if (dfa)
-+              kref_put(&dfa->count, aa_dfa_free_kref);
-+}
-+
-+#endif /* __AA_MATCH_H */
-diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
-new file mode 100644
-index 0000000..3c7d599
---- /dev/null
-+++ b/security/apparmor/include/net.h
-@@ -0,0 +1,40 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor network mediation definitions.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __AA_NET_H
-+#define __AA_NET_H
-+
-+#include <net/sock.h>
-+
-+/* struct aa_net - network confinement data
-+ * @allowed: basic network families permissions
-+ * @audit_network: which network permissions to force audit
-+ * @quiet_network: which network permissions to quiet rejects
-+ */
-+struct aa_net {
-+      u16 allow[AF_MAX];
-+      u16 audit[AF_MAX];
-+      u16 quiet[AF_MAX];
-+};
-+
-+extern int aa_net_perm(int op, struct aa_profile *profile, u16 family,
-+                     int type, int protocol, struct sock *sk);
-+extern int aa_revalidate_sk(int op, struct sock *sk);
-+
-+static inline void aa_free_net_rules(struct aa_net *new)
-+{
-+      /* NOP */
-+}
-+
-+#endif /* __AA_NET_H */
-diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h
-new file mode 100644
-index 0000000..27b327a
---- /dev/null
-+++ b/security/apparmor/include/path.h
-@@ -0,0 +1,31 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor basic path manipulation function definitions.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __AA_PATH_H
-+#define __AA_PATH_H
-+
-+
-+enum path_flags {
-+      PATH_IS_DIR = 0x1,              /* path is a directory */
-+      PATH_CONNECT_PATH = 0x4,        /* connect disconnected paths to / */
-+      PATH_CHROOT_REL = 0x8,          /* do path lookup relative to chroot */
-+      PATH_CHROOT_NSCONNECT = 0x10,   /* connect paths that are at ns root */
-+
-+      PATH_DELEGATE_DELETED = 0x08000, /* delegate deleted files */
-+      PATH_MEDIATE_DELETED = 0x10000, /* mediate deleted paths */
-+};
-+
-+int aa_get_name(struct path *path, int flags, char **buffer, const char **name);
-+
-+#endif /* __AA_PATH_H */
-diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
-new file mode 100644
-index 0000000..6776929
---- /dev/null
-+++ b/security/apparmor/include/policy.h
-@@ -0,0 +1,308 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor policy definitions.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __AA_POLICY_H
-+#define __AA_POLICY_H
-+
-+#include <linux/capability.h>
-+#include <linux/cred.h>
-+#include <linux/kref.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/socket.h>
-+
-+#include "apparmor.h"
-+#include "audit.h"
-+#include "capability.h"
-+#include "domain.h"
-+#include "file.h"
-+#include "net.h"
-+#include "resource.h"
-+
-+extern const char *profile_mode_names[];
-+#define APPARMOR_NAMES_MAX_INDEX 3
-+
-+#define COMPLAIN_MODE(_profile)       \
-+      ((aa_g_profile_mode == APPARMOR_COMPLAIN) || \
-+       ((_profile)->mode == APPARMOR_COMPLAIN))
-+
-+#define KILL_MODE(_profile) \
-+      ((aa_g_profile_mode == APPARMOR_KILL) || \
-+       ((_profile)->mode == APPARMOR_KILL))
-+
-+#define PROFILE_IS_HAT(_profile) ((_profile)->flags & PFLAG_HAT)
-+
-+/*
-+ * FIXME: currently need a clean way to replace and remove profiles as a
-+ * set.  It should be done at the namespace level.
-+ * Either, with a set of profiles loaded at the namespace level or via
-+ * a mark and remove marked interface.
-+ */
-+enum profile_mode {
-+      APPARMOR_ENFORCE,       /* enforce access rules */
-+      APPARMOR_COMPLAIN,      /* allow and log access violations */
-+      APPARMOR_KILL,          /* kill task on access violation */
-+};
-+
-+enum profile_flags {
-+      PFLAG_HAT = 1,                  /* profile is a hat */
-+      PFLAG_UNCONFINED = 2,           /* profile is an unconfined profile */
-+      PFLAG_NULL = 4,                 /* profile is null learning profile */
-+      PFLAG_IX_ON_NAME_ERROR = 8,     /* fallback to ix on name lookup fail */
-+      PFLAG_IMMUTABLE = 0x10,         /* don't allow changes/replacement */
-+      PFLAG_USER_DEFINED = 0x20,      /* user based profile - lower privs */
-+      PFLAG_NO_LIST_REF = 0x40,       /* list doesn't keep profile ref */
-+      PFLAG_OLD_NULL_TRANS = 0x100,   /* use // as the null transition */
-+
-+      /* These flags must correspond with PATH_flags */
-+      PFLAG_MEDIATE_DELETED = 0x10000, /* mediate instead delegate deleted */
-+};
-+
-+struct aa_profile;
-+
-+/* struct aa_policy - common part of both namespaces and profiles
-+ * @name: name of the object
-+ * @hname - The hierarchical name
-+ * @count: reference count of the obj
-+ * @list: list policy object is on
-+ * @profiles: head of the profiles list contained in the object
-+ */
-+struct aa_policy {
-+      char *name;
-+      char *hname;
-+      struct kref count;
-+      struct list_head list;
-+      struct list_head profiles;
-+};
-+
-+/* struct aa_ns_acct - accounting of profiles in namespace
-+ * @max_size: maximum space allowed for all profiles in namespace
-+ * @max_count: maximum number of profiles that can be in this namespace
-+ * @size: current size of profiles
-+ * @count: current count of profiles (includes null profiles)
-+ */
-+struct aa_ns_acct {
-+      int max_size;
-+      int max_count;
-+      int size;
-+      int count;
-+};
-+
-+/* struct aa_namespace - namespace for a set of profiles
-+ * @base: common policy
-+ * @parent: parent of namespace
-+ * @lock: lock for modifying the object
-+ * @acct: accounting for the namespace
-+ * @unconfined: special unconfined profile for the namespace
-+ * @sub_ns: list of namespaces under the current namespace.
-+ *
-+ * An aa_namespace defines the set profiles that are searched to determine
-+ * which profile to attach to a task.  Profiles can not be shared between
-+ * aa_namespaces and profile names within a namespace are guaranteed to be
-+ * unique.  When profiles in separate namespaces have the same name they
-+ * are NOT considered to be equivalent.
-+ *
-+ * Namespaces are hierarchical and only namespaces and profiles below the
-+ * current namespace are visible.
-+ *
-+ * Namespace names must be unique and can not contain the characters :/\0
-+ *
-+ * FIXME TODO: add vserver support of namespaces (can it all be done in
-+ *             userspace?)
-+ */
-+struct aa_namespace {
-+      struct aa_policy base;
-+      struct aa_namespace *parent;
-+      rwlock_t lock;
-+      struct aa_ns_acct acct;
-+      struct aa_profile *unconfined;
-+      struct list_head sub_ns;
-+};
-+
-+/* struct aa_profile - basic confinement data
-+ * @base - base components of the profile (name, refcount, lists, lock ...)
-+ * @parent: parent of profile
-+ * @ns: namespace the profile is in
-+ * @replacedby: is set to the profile that replaced this profile
-+ * @rename: optional profile name that this profile renamed
-+ * @xmatch: optional extended matching for unconfined executables names
-+ * @xmatch_len: xmatch prefix len, used to determine xmatch priority
-+ * @sid: the unique security id number of this profile
-+ * @audit: the auditing mode of the profile
-+ * @mode: the enforcement mode of the profile
-+ * @flags: flags controlling profile behavior
-+ * @path_flags: flags controlling path generation behavior
-+ * @size: the memory consumed by this profiles rules
-+ * @file: The set of rules governing basic file access and domain transitions
-+ * @caps: capabilities for the profile
-+ * @net: network controls for the profile
-+ * @rlimits: rlimits for the profile
-+ *
-+ * The AppArmor profile contains the basic confinement data.  Each profile
-+ * has a name, and exists in a namespace.  The @name and @exec_match are
-+ * used to determine profile attachment against unconfined tasks.  All other
-+ * attachments are determined by profile X transition rules.
-+ *
-+ * The @replacedby field is write protected by the profile lock.  Reads
-+ * are assumed to be atomic, and are done without locking.
-+ *
-+ * Profiles have a hierarchy where hats and children profiles keep
-+ * a reference to their parent.
-+ *
-+ * Profile names can not begin with a : and can not contain the \0
-+ * character.  If a profile name begins with / it will be considered when
-+ * determining profile attachment on "unconfined" tasks.
-+ */
-+struct aa_profile {
-+      struct aa_policy base;
-+      struct aa_profile *parent;
-+
-+      struct aa_namespace *ns;
-+      struct aa_profile *replacedby;
-+      const char *rename;
-+
-+      struct aa_dfa *xmatch;
-+      int xmatch_len;
-+      u32 sid;
-+      enum audit_mode audit;
-+      enum profile_mode mode;
-+      u32 flags;
-+      u32 path_flags;
-+      int size;
-+
-+      struct aa_file_rules file;
-+      struct aa_caps caps;
-+      struct aa_net net;
-+      struct aa_rlimit rlimits;
-+};
-+
-+extern struct aa_namespace *root_ns;
-+extern enum profile_mode aa_g_profile_mode;
-+
-+void aa_add_profile(struct aa_policy *common, struct aa_profile *profile);
-+
-+bool aa_ns_visible(struct aa_namespace *curr, struct aa_namespace *view);
-+const char *aa_ns_name(struct aa_namespace *parent, struct aa_namespace *child);
-+int aa_alloc_root_ns(void);
-+void aa_free_root_ns(void);
-+void aa_free_namespace_kref(struct kref *kref);
-+
-+struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
-+                                     const char *name);
-+
-+static inline struct aa_policy *aa_get_common(struct aa_policy *c)
-+{
-+      if (c)
-+              kref_get(&c->count);
-+
-+      return c;
-+}
-+
-+/**
-+ * aa_get_namespace - increment references count on @ns
-+ * @ns: namespace to increment reference count of (MAYBE NULL)
-+ *
-+ * Returns: pointer to @ns, if @ns is NULL returns NULL
-+ * Requires: @ns must be held with valid refcount when called
-+ */
-+static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
-+{
-+      if (ns)
-+              kref_get(&(ns->base.count));
-+
-+      return ns;
-+}
-+
-+/**
-+ * aa_put_namespace - decrement refcount on @ns
-+ * @ns: namespace to put reference of
-+ *
-+ * Decrement reference count of @ns and if no longer in use free it
-+ */
-+static inline void aa_put_namespace(struct aa_namespace *ns)
-+{
-+      if (ns)
-+              kref_put(&ns->base.count, aa_free_namespace_kref);
-+}
-+
-+struct aa_profile *aa_alloc_profile(const char *name);
-+struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat);
-+void aa_free_profile_kref(struct kref *kref);
-+struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name);
-+struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *name);
-+struct aa_profile *aa_match_profile(struct aa_namespace *ns, const char *name);
-+
-+ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace);
-+ssize_t aa_remove_profiles(char *name, size_t size);
-+
-+#define PROF_ADD 1
-+#define PROF_REPLACE 0
-+
-+#define unconfined(X) ((X)->flags & PFLAG_UNCONFINED)
-+
-+/**
-+ * aa_newest_version - find the newest version of @profile
-+ * @profile: the profile to check for newer versions of (NOT NULL)
-+ *
-+ * Returns: newest version of @profile, if @profile is the newest version
-+ *          return @profile.
-+ *
-+ * NOTE: the profile returned is not refcounted, The refcount on @profile
-+ * must be held until the caller decides what to do with the returned newest
-+ * version.
-+ */
-+static inline struct aa_profile *aa_newest_version(struct aa_profile *profile)
-+{
-+      while (profile->replacedby)
-+              profile = profile->replacedby;
-+
-+      return profile;
-+}
-+
-+/**
-+ * aa_get_profile - increment refcount on profile @p
-+ * @p: profile  (MAYBE NULL)
-+ *
-+ * Returns: pointer to @p if @p is NULL will return NULL
-+ * Requires: @p must be held with valid refcount when called
-+ */
-+static inline struct aa_profile *aa_get_profile(struct aa_profile *p)
-+{
-+      if (p)
-+              kref_get(&(p->base.count));
-+
-+      return p;
-+}
-+
-+/**
-+ * aa_put_profile - decrement refcount on profile @p
-+ * @p: profile  (MAYBE NULL)
-+ */
-+static inline void aa_put_profile(struct aa_profile *p)
-+{
-+      if (p)
-+              kref_put(&p->base.count, aa_free_profile_kref);
-+}
-+
-+static inline int AUDIT_MODE(struct aa_profile *profile)
-+{
-+      if (aa_g_audit != AUDIT_NORMAL)
-+              return aa_g_audit;
-+
-+      return profile->audit;
-+}
-+
-+bool aa_may_manage_policy(int op);
-+
-+#endif /* __AA_POLICY_H */
-diff --git a/security/apparmor/include/policy_unpack.h b/security/apparmor/include/policy_unpack.h
-new file mode 100644
-index 0000000..a2dccca
---- /dev/null
-+++ b/security/apparmor/include/policy_unpack.h
-@@ -0,0 +1,20 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor policy loading interface function definitions.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __POLICY_INTERFACE_H
-+#define __POLICY_INTERFACE_H
-+
-+struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns);
-+
-+#endif /* __POLICY_INTERFACE_H */
-diff --git a/security/apparmor/include/procattr.h b/security/apparmor/include/procattr.h
-new file mode 100644
-index 0000000..544aa6b
---- /dev/null
-+++ b/security/apparmor/include/procattr.h
-@@ -0,0 +1,26 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor /proc/<pid>/attr/ interface function definitions.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __AA_PROCATTR_H
-+#define __AA_PROCATTR_H
-+
-+#define AA_DO_TEST 1
-+#define AA_ONEXEC  1
-+
-+int aa_getprocattr(struct aa_profile *profile, char **string);
-+int aa_setprocattr_changehat(char *args, size_t size, int test);
-+int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test);
-+int aa_setprocattr_permipc(char *fqname);
-+
-+#endif /* __AA_PROCATTR_H */
-diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h
-new file mode 100644
-index 0000000..3c88be9
---- /dev/null
-+++ b/security/apparmor/include/resource.h
-@@ -0,0 +1,46 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor resource limits function definitions.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __AA_RESOURCE_H
-+#define __AA_RESOURCE_H
-+
-+#include <linux/resource.h>
-+#include <linux/sched.h>
-+
-+struct aa_profile;
-+
-+/* struct aa_rlimit - rlimit settings for the profile
-+ * @mask: which hard limits to set
-+ * @limits: rlimit values that override task limits
-+ *
-+ * AppArmor rlimits are used to set confined task rlimits.  Only the
-+ * limits specified in @mask will be controlled by apparmor.
-+ */
-+struct aa_rlimit {
-+      unsigned int mask;
-+      struct rlimit limits[RLIM_NLIMITS];
-+};
-+
-+int aa_map_resource(int resource);
-+int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
-+                    struct rlimit *new_rlim);
-+
-+void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new);
-+
-+static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims)
-+{
-+      /* NOP */
-+}
-+
-+#endif /* __AA_RESOURCE_H */
-diff --git a/security/apparmor/include/sid.h b/security/apparmor/include/sid.h
-new file mode 100644
-index 0000000..020db35
---- /dev/null
-+++ b/security/apparmor/include/sid.h
-@@ -0,0 +1,24 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor security identifier (sid) definitions
-+ *
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#ifndef __AA_SID_H
-+#define __AA_SID_H
-+
-+#include <linux/types.h>
-+
-+struct aa_profile;
-+
-+u32 aa_alloc_sid(void);
-+void aa_free_sid(u32 sid);
-+
-+#endif /* __AA_SID_H */
-diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c
-new file mode 100644
-index 0000000..9013a78
---- /dev/null
-+++ b/security/apparmor/ipc.c
-@@ -0,0 +1,114 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor ipc mediation
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#include <linux/gfp.h>
-+#include <linux/ptrace.h>
-+
-+#include "include/audit.h"
-+#include "include/capability.h"
-+#include "include/context.h"
-+#include "include/policy.h"
-+
-+/* call back to audit ptrace fields */
-+static void audit_cb(struct audit_buffer *ab, void *va)
-+{
-+      struct common_audit_data *sa = va;
-+      audit_log_format(ab, " target=");
-+      audit_log_untrustedstring(ab, sa->aad.target);
-+}
-+
-+/**
-+ * aa_audit_ptrace - do auditing for ptrace
-+ * @profile: profile being enforced  (NOT NULL)
-+ * @target: profile being traced (NOT NULL)
-+ * @error: error condition
-+ *
-+ * Returns: %0 or error code
-+ */
-+static int aa_audit_ptrace(struct aa_profile *profile,
-+                         struct aa_profile *target, int error)
-+{
-+      struct common_audit_data sa;
-+      COMMON_AUDIT_DATA_INIT(&sa, NONE);
-+      sa.aad.op = OP_PTRACE;
-+      sa.aad.target = target;
-+      sa.aad.error = error;
-+
-+      return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa,
-+                      audit_cb);
-+}
-+
-+/**
-+ * aa_may_ptrace - test if tracer task can trace the tracee
-+ * @tracer_task: task who will do the tracing  (NOT NULL)
-+ * @tracer: profile of the task doing the tracing  (NOT NULL)
-+ * @tracee: task to be traced
-+ * @mode: whether PTRACE_MODE_READ || PTRACE_MODE_ATTACH
-+ *
-+ * Returns: %0 else error code if permission denied or error
-+ */
-+int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
-+                struct aa_profile *tracee, unsigned int mode)
-+{
-+      /* TODO: currently only based on capability, not extended ptrace
-+       *       rules,
-+       *       Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH
-+       */
-+
-+      if (unconfined(tracer) || tracer == tracee)
-+              return 0;
-+      /* log this capability request */
-+      return aa_capable(tracer_task, tracer, CAP_SYS_PTRACE, 1);
-+}
-+
-+/**
-+ * aa_ptrace - do ptrace permission check and auditing
-+ * @tracer: task doing the tracing (NOT NULL)
-+ * @tracee: task being traced (NOT NULL)
-+ * @mode: ptrace mode either PTRACE_MODE_READ || PTRACE_MODE_ATTACH
-+ *
-+ * Returns: %0 else error code if permission denied or error
-+ */
-+int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
-+            unsigned int mode)
-+{
-+      /*
-+       * tracer can ptrace tracee when
-+       * - tracer is unconfined ||
-+       *   - tracer is in complain mode
-+       *   - tracer has rules allowing it to trace tracee currently this is:
-+       *       - confined by the same profile ||
-+       *       - tracer profile has CAP_SYS_PTRACE
-+       */
-+
-+      struct aa_profile *tracer_p;
-+      /* cred released below */
-+      const struct cred *cred = get_task_cred(tracer);
-+      int error = 0;
-+      tracer_p = aa_cred_profile(cred);
-+
-+      if (!unconfined(tracer_p)) {
-+              /* lcred released below */
-+              struct cred *lcred = get_task_cred(tracee);
-+              struct aa_profile *tracee_p = aa_cred_profile(lcred);
-+
-+              error = aa_may_ptrace(tracer, tracer_p, tracee_p, mode);
-+              error = aa_audit_ptrace(tracer_p, tracee_p, error);
-+
-+              put_cred(lcred);
-+      }
-+      put_cred(cred);
-+
-+      return error;
-+}
-diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
-new file mode 100644
-index 0000000..6e85cdb
---- /dev/null
-+++ b/security/apparmor/lib.c
-@@ -0,0 +1,133 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains basic common functions used in AppArmor
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/string.h>
-+#include <linux/vmalloc.h>
-+
-+#include "include/audit.h"
-+
-+
-+/**
-+ * aa_split_fqname - split a fqname into a profile and namespace name
-+ * @fqname: a full qualified name in namespace profile format (NOT NULL)
-+ * @ns_name: pointer to portion of the string containing the ns name (NOT NULL)
-+ *
-+ * Returns: profile name or NULL if one is not specified
-+ *
-+ * Split a namespace name from a profile name (see policy.c for naming
-+ * description).  If a portion of the name is missing it returns NULL for
-+ * that portion.
-+ *
-+ * NOTE: may modify the @fqname string.  The pointers returned point
-+ *       into the @fqname string.
-+ */
-+char *aa_split_fqname(char *fqname, char **ns_name)
-+{
-+      char *name = strim(fqname);
-+
-+      *ns_name = NULL;
-+      if (name[0] == ':') {
-+              char *split = strchr(&name[1], ':');
-+              if (split) {
-+                      /* overwrite ':' with \0 */
-+                      *split = 0;
-+                      name = skip_spaces(split + 1);
-+              } else
-+                      /* a ns name without a following profile is allowed */
-+                      name = NULL;
-+              *ns_name = &name[1];
-+      }
-+      if (name && *name == 0)
-+              name = NULL;
-+
-+      return name;
-+}
-+
-+/**
-+ * aa_info_message - log a none profile related status message
-+ * @str: message to log
-+ */
-+void aa_info_message(const char *str)
-+{
-+      if (audit_enabled) {
-+              struct common_audit_data sa;
-+              COMMON_AUDIT_DATA_INIT(&sa, NONE);
-+              sa.aad.info = str;
-+              aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
-+      }
-+      printk(KERN_INFO "AppArmor: %s\n", str);
-+}
-+
-+/**
-+ * kvmalloc - do allocation preferring kmalloc but falling back to vmalloc
-+ * @size: size of allocation
-+ *
-+ * Return: allocated buffer or NULL if failed
-+ *
-+ * It is possible that policy being loaded from the user is larger than
-+ * what can be allocated by kmalloc, in those cases fall back to vmalloc.
-+ */
-+void *kvmalloc(size_t size)
-+{
-+      void *buffer = NULL;
-+
-+      if (size == 0)
-+              return NULL;
-+
-+      /* do not attempt kmalloc if we need more than 16 pages at once */
-+      if (size <= (16*PAGE_SIZE))
-+              buffer = kmalloc(size, GFP_NOIO | __GFP_NOWARN);
-+      if (!buffer) {
-+              /* see kvfree for why size must be at least work_struct size
-+               * when allocated via vmalloc
-+               */
-+              if (size < sizeof(struct work_struct))
-+                      size = sizeof(struct work_struct);
-+              buffer = vmalloc(size);
-+      }
-+      return buffer;
-+}
-+
-+/**
-+ * do_vfree - workqueue routine for freeing vmalloced memory
-+ * @work: data to be freed
-+ *
-+ * The work_struct is overlaid to the data being freed, as at the point
-+ * the work is scheduled the data is no longer valid, be its freeing
-+ * needs to be delayed until safe.
-+ */
-+static void do_vfree(struct work_struct *work)
-+{
-+      vfree(work);
-+}
-+
-+/**
-+ * kvfree - free an allocation do by kvmalloc
-+ * @buffer: buffer to free (MAYBE_NULL)
-+ *
-+ * Free a buffer allocated by kvmalloc
-+ */
-+void kvfree(void *buffer)
-+{
-+      if (is_vmalloc_addr(buffer)) {
-+              /* Data is no longer valid so just use the allocated space
-+               * as the work_struct
-+               */
-+              struct work_struct *work = (struct work_struct *) buffer;
-+              INIT_WORK(work, do_vfree);
-+              schedule_work(work);
-+      } else
-+              kfree(buffer);
-+}
-diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
-new file mode 100644
-index 0000000..e8d0821
---- /dev/null
-+++ b/security/apparmor/lsm.c
-@@ -0,0 +1,1051 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor LSM hooks.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#include <linux/security.h>
-+#include <linux/moduleparam.h>
-+#include <linux/mm.h>
-+#include <linux/mman.h>
-+#include <linux/mount.h>
-+#include <linux/namei.h>
-+#include <linux/ptrace.h>
-+#include <linux/ctype.h>
-+#include <linux/sysctl.h>
-+#include <linux/audit.h>
-+#include <net/sock.h>
-+
-+#include "include/apparmor.h"
-+#include "include/apparmorfs.h"
-+#include "include/audit.h"
-+#include "include/capability.h"
-+#include "include/context.h"
-+#include "include/file.h"
-+#include "include/ipc.h"
-+#include "include/net.h"
-+#include "include/path.h"
-+#include "include/policy.h"
-+#include "include/procattr.h"
-+
-+/* Flag indicating whether initialization completed */
-+int apparmor_initialized __initdata;
-+
-+/*
-+ * LSM hook functions
-+ */
-+
-+/*
-+ * free the associated aa_task_cxt and put its profiles
-+ */
-+static void apparmor_cred_free(struct cred *cred)
-+{
-+      aa_free_task_context(cred->security);
-+      cred->security = NULL;
-+}
-+
-+/*
-+ * allocate the apparmor part of blank credentials
-+ */
-+static int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp)
-+{
-+      /* freed by apparmor_cred_free */
-+      struct aa_task_cxt *cxt = aa_alloc_task_context(gfp);
-+      if (!cxt)
-+              return -ENOMEM;
-+
-+      cred->security = cxt;
-+      return 0;
-+}
-+
-+/*
-+ * prepare new aa_task_cxt for modification by prepare_cred block
-+ */
-+static int apparmor_cred_prepare(struct cred *new, const struct cred *old,
-+                               gfp_t gfp)
-+{
-+      /* freed by apparmor_cred_free */
-+      struct aa_task_cxt *cxt = aa_alloc_task_context(gfp);
-+      if (!cxt)
-+              return -ENOMEM;
-+
-+      aa_dup_task_context(cxt, old->security);
-+      new->security = cxt;
-+      return 0;
-+}
-+
-+/*
-+ * transfer the apparmor data to a blank set of creds
-+ */
-+static void apparmor_cred_transfer(struct cred *new, const struct cred *old)
-+{
-+      const struct aa_task_cxt *old_cxt = old->security;
-+      struct aa_task_cxt *new_cxt = new->security;
-+
-+      aa_dup_task_context(new_cxt, old_cxt);
-+}
-+
-+static int apparmor_ptrace_access_check(struct task_struct *child,
-+                                      unsigned int mode)
-+{
-+      int error = cap_ptrace_access_check(child, mode);
-+      if (error)
-+              return error;
-+
-+      return aa_ptrace(current, child, mode);
-+}
-+
-+static int apparmor_ptrace_traceme(struct task_struct *parent)
-+{
-+      int error = cap_ptrace_traceme(parent);
-+      if (error)
-+              return error;
-+
-+      return aa_ptrace(parent, current, PTRACE_MODE_ATTACH);
-+}
-+
-+/* Derived from security/commoncap.c:cap_capget */
-+static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
-+                         kernel_cap_t *inheritable, kernel_cap_t *permitted)
-+{
-+      struct aa_profile *profile;
-+      const struct cred *cred;
-+
-+      rcu_read_lock();
-+      cred = __task_cred(target);
-+      profile = aa_cred_profile(cred);
-+
-+      *effective = cred->cap_effective;
-+      *inheritable = cred->cap_inheritable;
-+      *permitted = cred->cap_permitted;
-+
-+      if (!unconfined(profile)) {
-+              *effective = cap_intersect(*effective, profile->caps.allow);
-+              *permitted = cap_intersect(*permitted, profile->caps.allow);
-+      }
-+      rcu_read_unlock();
-+
-+      return 0;
-+}
-+
-+static int apparmor_capable(struct task_struct *task, const struct cred *cred,
-+                          int cap, int audit)
-+{
-+      struct aa_profile *profile;
-+      /* cap_capable returns 0 on success, else -EPERM */
-+      int error = cap_capable(task, cred, cap, audit);
-+      if (!error) {
-+              profile = aa_cred_profile(cred);
-+              if (!unconfined(profile))
-+                      error = aa_capable(task, profile, cap, audit);
-+      }
-+      return error;
-+}
-+
-+/**
-+ * common_perm - basic common permission check wrapper fn for paths
-+ * @op: operation being checked
-+ * @path: path to check permission of  (NOT NULL)
-+ * @mask: requested permissions mask
-+ * @cond: conditional info for the permission request  (NOT NULL)
-+ *
-+ * Returns: %0 else error code if error or permission denied
-+ */
-+static int common_perm(int op, struct path *path, u32 mask,
-+                     struct path_cond *cond)
-+{
-+      struct aa_profile *profile;
-+      int error = 0;
-+
-+      profile = __aa_current_profile();
-+      if (!unconfined(profile))
-+              error = aa_path_perm(op, profile, path, 0, mask, cond);
-+
-+      return error;
-+}
-+
-+/**
-+ * common_perm_dir_dentry - common permission wrapper when path is dir, dentry
-+ * @op: operation being checked
-+ * @dir: directory of the dentry  (NOT NULL)
-+ * @dentry: dentry to check  (NOT NULL)
-+ * @mask: requested permissions mask
-+ * @cond: conditional info for the permission request  (NOT NULL)
-+ *
-+ * Returns: %0 else error code if error or permission denied
-+ */
-+static int common_perm_dir_dentry(int op, struct path *dir,
-+                                struct dentry *dentry, u32 mask,
-+                                struct path_cond *cond)
-+{
-+      struct path path = { dir->mnt, dentry };
-+
-+      return common_perm(op, &path, mask, cond);
-+}
-+
-+/**
-+ * common_perm_mnt_dentry - common permission wrapper when mnt, dentry
-+ * @op: operation being checked
-+ * @mnt: mount point of dentry (NOT NULL)
-+ * @dentry: dentry to check  (NOT NULL)
-+ * @mask: requested permissions mask
-+ *
-+ * Returns: %0 else error code if error or permission denied
-+ */
-+static int common_perm_mnt_dentry(int op, struct vfsmount *mnt,
-+                                struct dentry *dentry, u32 mask)
-+{
-+      struct path path = { mnt, dentry };
-+      struct path_cond cond = { dentry->d_inode->i_uid,
-+                                dentry->d_inode->i_mode
-+      };
-+
-+      return common_perm(op, &path, mask, &cond);
-+}
-+
-+/**
-+ * common_perm_rm - common permission wrapper for operations doing rm
-+ * @op: operation being checked
-+ * @dir: directory that the dentry is in  (NOT NULL)
-+ * @dentry: dentry being rm'd  (NOT NULL)
-+ * @mask: requested permission mask
-+ *
-+ * Returns: %0 else error code if error or permission denied
-+ */
-+static int common_perm_rm(int op, struct path *dir,
-+                        struct dentry *dentry, u32 mask)
-+{
-+      struct inode *inode = dentry->d_inode;
-+      struct path_cond cond = { };
-+
-+      if (!inode || !dir->mnt || !mediated_filesystem(inode))
-+              return 0;
-+
-+      cond.uid = inode->i_uid;
-+      cond.mode = inode->i_mode;
-+
-+      return common_perm_dir_dentry(op, dir, dentry, mask, &cond);
-+}
-+
-+/**
-+ * common_perm_create - common permission wrapper for operations doing create
-+ * @op: operation being checked
-+ * @dir: directory that dentry will be created in  (NOT NULL)
-+ * @dentry: dentry to create   (NOT NULL)
-+ * @mask: request permission mask
-+ * @mode: created file mode
-+ *
-+ * Returns: %0 else error code if error or permission denied
-+ */
-+static int common_perm_create(int op, struct path *dir, struct dentry *dentry,
-+                            u32 mask, umode_t mode)
-+{
-+      struct path_cond cond = { current_fsuid(), mode };
-+
-+      if (!dir->mnt || !mediated_filesystem(dir->dentry->d_inode))
-+              return 0;
-+
-+      return common_perm_dir_dentry(op, dir, dentry, mask, &cond);
-+}
-+
-+static int apparmor_path_unlink(struct path *dir, struct dentry *dentry)
-+{
-+      return common_perm_rm(OP_UNLINK, dir, dentry, AA_MAY_DELETE);
-+}
-+
-+static int apparmor_path_mkdir(struct path *dir, struct dentry *dentry,
-+                             int mode)
-+{
-+      return common_perm_create(OP_MKDIR, dir, dentry, AA_MAY_CREATE,
-+                                S_IFDIR);
-+}
-+
-+static int apparmor_path_rmdir(struct path *dir, struct dentry *dentry)
-+{
-+      return common_perm_rm(OP_RMDIR, dir, dentry, AA_MAY_DELETE);
-+}
-+
-+static int apparmor_path_mknod(struct path *dir, struct dentry *dentry,
-+                             int mode, unsigned int dev)
-+{
-+      return common_perm_create(OP_MKNOD, dir, dentry, AA_MAY_CREATE, mode);
-+}
-+
-+static int apparmor_path_truncate(struct path *path, loff_t length,
-+                                unsigned int time_attrs)
-+{
-+      struct path_cond cond = { path->dentry->d_inode->i_uid,
-+                                path->dentry->d_inode->i_mode
-+      };
-+
-+      if (!path->mnt || !mediated_filesystem(path->dentry->d_inode))
-+              return 0;
-+
-+      return common_perm(OP_TRUNC, path, MAY_WRITE | AA_MAY_META_WRITE,
-+                         &cond);
-+}
-+
-+static int apparmor_path_symlink(struct path *dir, struct dentry *dentry,
-+                               const char *old_name)
-+{
-+      return common_perm_create(OP_SYMLINK, dir, dentry, AA_MAY_CREATE,
-+                                S_IFLNK);
-+}
-+
-+static int apparmor_path_link(struct dentry *old_dentry, struct path *new_dir,
-+                            struct dentry *new_dentry)
-+{
-+      struct aa_profile *profile;
-+      int error = 0;
-+
-+      if (!mediated_filesystem(old_dentry->d_inode))
-+              return 0;
-+
-+      profile = aa_current_profile();
-+      if (!unconfined(profile))
-+              error = aa_path_link(profile, old_dentry, new_dir, new_dentry);
-+      return error;
-+}
-+
-+static int apparmor_path_rename(struct path *old_dir, struct dentry *old_dentry,
-+                              struct path *new_dir, struct dentry *new_dentry)
-+{
-+      struct aa_profile *profile;
-+      int error = 0;
-+
-+      if (!mediated_filesystem(old_dentry->d_inode))
-+              return 0;
-+
-+      profile = aa_current_profile();
-+      if (!unconfined(profile)) {
-+              struct path old_path = { old_dir->mnt, old_dentry };
-+              struct path new_path = { new_dir->mnt, new_dentry };
-+              struct path_cond cond = { old_dentry->d_inode->i_uid,
-+                                        old_dentry->d_inode->i_mode
-+              };
-+
-+              error = aa_path_perm(OP_RENAME_SRC, profile, &old_path, 0,
-+                                   MAY_READ | AA_MAY_META_READ | MAY_WRITE |
-+                                   AA_MAY_META_WRITE | AA_MAY_DELETE,
-+                                   &cond);
-+              if (!error)
-+                      error = aa_path_perm(OP_RENAME_DEST, profile, &new_path,
-+                                           0, MAY_WRITE | AA_MAY_META_WRITE |
-+                                           AA_MAY_CREATE, &cond);
-+
-+      }
-+      return error;
-+}
-+
-+static int apparmor_path_chmod(struct dentry *dentry, struct vfsmount *mnt,
-+                             mode_t mode)
-+{
-+      if (!mediated_filesystem(dentry->d_inode))
-+              return 0;
-+
-+      return common_perm_mnt_dentry(OP_CHMOD, mnt, dentry, AA_MAY_CHMOD);
-+}
-+
-+static int apparmor_path_chown(struct path *path, uid_t uid, gid_t gid)
-+{
-+      struct path_cond cond =  { path->dentry->d_inode->i_uid,
-+                                 path->dentry->d_inode->i_mode
-+      };
-+
-+      if (!mediated_filesystem(path->dentry->d_inode))
-+              return 0;
-+
-+      return common_perm(OP_CHOWN, path, AA_MAY_CHOWN, &cond);
-+}
-+
-+static int apparmor_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
-+{
-+      if (!mediated_filesystem(dentry->d_inode))
-+              return 0;
-+
-+      return common_perm_mnt_dentry(OP_GETATTR, mnt, dentry,
-+                                    AA_MAY_META_READ);
-+}
-+
-+static int apparmor_dentry_open(struct file *file, const struct cred *cred)
-+{
-+      struct aa_file_cxt *fcxt = file->f_security;
-+      struct aa_profile *profile;
-+      int error = 0;
-+
-+      if (!mediated_filesystem(file->f_path.dentry->d_inode))
-+              return 0;
-+
-+      /* If in exec, permission is handled by bprm hooks.
-+       * Cache permissions granted by the previous exec check, with
-+       * implicit read and executable mmap which are required to
-+       * actually execute the image.
-+       */
-+      if (current->in_execve) {
-+              fcxt->allow = MAY_EXEC | MAY_READ | AA_EXEC_MMAP;
-+              return 0;
-+      }
-+
-+      profile = aa_cred_profile(cred);
-+      if (!unconfined(profile)) {
-+              struct inode *inode = file->f_path.dentry->d_inode;
-+              struct path_cond cond = { inode->i_uid, inode->i_mode };
-+
-+              error = aa_path_perm(OP_OPEN, profile, &file->f_path, 0,
-+                                   aa_map_file_to_perms(file), &cond);
-+              /* todo cache full allowed permissions set and state */
-+              fcxt->allow = aa_map_file_to_perms(file);
-+      }
-+
-+      return error;
-+}
-+
-+static int apparmor_file_alloc_security(struct file *file)
-+{
-+      /* freed by apparmor_file_free_security */
-+      file->f_security = aa_alloc_file_context(GFP_KERNEL);
-+      if (!file->f_security)
-+              return -ENOMEM;
-+      return 0;
-+
-+}
-+
-+static void apparmor_file_free_security(struct file *file)
-+{
-+      struct aa_file_cxt *cxt = file->f_security;
-+
-+      aa_free_file_context(cxt);
-+}
-+
-+static int common_file_perm(int op, struct file *file, u32 mask)
-+{
-+      struct aa_file_cxt *fcxt = file->f_security;
-+      struct aa_profile *profile, *fprofile = aa_cred_profile(file->f_cred);
-+      int error = 0;
-+
-+      BUG_ON(!fprofile);
-+
-+      if (!file->f_path.mnt ||
-+          !mediated_filesystem(file->f_path.dentry->d_inode))
-+              return 0;
-+
-+      profile = __aa_current_profile();
-+
-+      /* revalidate access, if task is unconfined, or the cached cred
-+       * doesn't match or if the request is for more permissions than
-+       * was granted.
-+       *
-+       * Note: the test for !unconfined(fprofile) is to handle file
-+       *       delegation from unconfined tasks
-+       */
-+      if (!unconfined(profile) && !unconfined(fprofile) &&
-+          ((fprofile != profile) || (mask & ~fcxt->allow)))
-+              error = aa_file_perm(op, profile, file, mask);
-+
-+      return error;
-+}
-+
-+static int apparmor_file_permission(struct file *file, int mask)
-+{
-+      return common_file_perm(OP_FPERM, file, mask);
-+}
-+
-+static int apparmor_file_lock(struct file *file, unsigned int cmd)
-+{
-+      u32 mask = AA_MAY_LOCK;
-+
-+      if (cmd == F_WRLCK)
-+              mask |= MAY_WRITE;
-+
-+      return common_file_perm(OP_FLOCK, file, mask);
-+}
-+
-+static int common_mmap(int op, struct file *file, 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_path.dentry;
-+      return common_file_perm(op, file, mask);
-+}
-+
-+static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
-+                            unsigned long prot, unsigned long flags,
-+                            unsigned long addr, unsigned long addr_only)
-+{
-+      int rc = 0;
-+
-+      /* do DAC check */
-+      rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
-+      if (rc || addr_only)
-+              return rc;
-+
-+      return common_mmap(OP_FMMAP, file, prot, flags);
-+}
-+
-+static int apparmor_file_mprotect(struct vm_area_struct *vma,
-+                                unsigned long reqprot, unsigned long prot)
-+{
-+      return common_mmap(OP_FMPROT, vma->vm_file, prot,
-+                         !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
-+}
-+
-+static int apparmor_getprocattr(struct task_struct *task, char *name,
-+                              char **value)
-+{
-+      int error = -ENOENT;
-+      struct aa_profile *profile;
-+      /* released below */
-+      const struct cred *cred = get_task_cred(task);
-+      struct aa_task_cxt *cxt = cred->security;
-+      profile = aa_cred_profile(cred);
-+
-+      if (strcmp(name, "current") == 0)
-+              error = aa_getprocattr(aa_newest_version(cxt->profile),
-+                                     value);
-+      else if (strcmp(name, "prev") == 0  && cxt->previous)
-+              error = aa_getprocattr(aa_newest_version(cxt->previous),
-+                                     value);
-+      else if (strcmp(name, "exec") == 0 && cxt->onexec)
-+              error = aa_getprocattr(aa_newest_version(cxt->onexec),
-+                                     value);
-+      else
-+              error = -EINVAL;
-+
-+      put_cred(cred);
-+
-+      return error;
-+}
-+
-+static int apparmor_setprocattr(struct task_struct *task, char *name,
-+                              void *value, size_t size)
-+{
-+      char *command, *args = value;
-+      size_t arg_size;
-+      int error;
-+
-+      if (size == 0)
-+              return -EINVAL;
-+      /* args points to a PAGE_SIZE buffer, AppArmor requires that
-+       * the buffer must be null terminated or have size <= PAGE_SIZE -1
-+       * so that AppArmor can null terminate them
-+       */
-+      if (args[size - 1] != '\0') {
-+              if (size == PAGE_SIZE)
-+                      return -EINVAL;
-+              args[size] = '\0';
-+      }
-+
-+      /* task can only write its own attributes */
-+      if (current != task)
-+              return -EACCES;
-+
-+      args = value;
-+      args = strim(args);
-+      command = strsep(&args, " ");
-+      if (!args)
-+              return -EINVAL;
-+      args = skip_spaces(args);
-+      if (!*args)
-+              return -EINVAL;
-+
-+      arg_size = size - (args - (char *) value);
-+      if (strcmp(name, "current") == 0) {
-+              if (strcmp(command, "changehat") == 0) {
-+                      error = aa_setprocattr_changehat(args, arg_size,
-+                                                       !AA_DO_TEST);
-+              } else if (strcmp(command, "permhat") == 0) {
-+                      error = aa_setprocattr_changehat(args, arg_size,
-+                                                       AA_DO_TEST);
-+              } else if (strcmp(command, "changeprofile") == 0) {
-+                      error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
-+                                                           !AA_DO_TEST);
-+              } else if (strcmp(command, "permprofile") == 0) {
-+                      error = aa_setprocattr_changeprofile(args, !AA_ONEXEC,
-+                                                           AA_DO_TEST);
-+              } else if (strcmp(command, "permipc") == 0) {
-+                      error = aa_setprocattr_permipc(args);
-+              } else {
-+                      struct common_audit_data sa;
-+                      COMMON_AUDIT_DATA_INIT(&sa, NONE);
-+                      sa.aad.op = OP_SETPROCATTR;
-+                      sa.aad.info = name;
-+                      sa.aad.error = -EINVAL;
-+                      return aa_audit(AUDIT_APPARMOR_DENIED, NULL, GFP_KERNEL,
-+                                      &sa, NULL);
-+              }
-+      } else if (strcmp(name, "exec") == 0) {
-+              error = aa_setprocattr_changeprofile(args, AA_ONEXEC,
-+                                                   !AA_DO_TEST);
-+      } else {
-+              /* only support the "current" and "exec" process attributes */
-+              return -EINVAL;
-+      }
-+      if (!error)
-+              error = size;
-+      return error;
-+}
-+
-+static int apparmor_task_setrlimit(unsigned int resource,
-+                                 struct rlimit *new_rlim)
-+{
-+      struct aa_profile *profile = aa_current_profile();
-+      int error = 0;
-+
-+      if (!unconfined(profile))
-+              error = aa_task_setrlimit(profile, resource, new_rlim);
-+
-+      return error;
-+}
-+
-+static int apparmor_socket_create(int family, int type, int protocol, int kern)
-+{
-+      struct aa_profile *profile;
-+      int error = 0;
-+
-+      if (kern)
-+              return 0;
-+
-+      profile = __aa_current_profile();
-+      if (!unconfined(profile))
-+              error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
-+                                  NULL);
-+      return error;
-+}
-+
-+static int apparmor_socket_bind(struct socket *sock,
-+                              struct sockaddr *address, int addrlen)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(OP_BIND, sk);
-+}
-+
-+static int apparmor_socket_connect(struct socket *sock,
-+                                 struct sockaddr *address, int addrlen)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(OP_CONNECT, sk);
-+}
-+
-+static int apparmor_socket_listen(struct socket *sock, int backlog)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(OP_LISTEN, sk);
-+}
-+
-+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(OP_ACCEPT, sk);
-+}
-+
-+static int apparmor_socket_sendmsg(struct socket *sock,
-+                                 struct msghdr *msg, int size)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(OP_SENDMSG, sk);
-+}
-+
-+static int apparmor_socket_recvmsg(struct socket *sock,
-+                                 struct msghdr *msg, int size, int flags)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(OP_RECVMSG, sk);
-+}
-+
-+static int apparmor_socket_getsockname(struct socket *sock)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(OP_GETSOCKNAME, sk);
-+}
-+
-+static int apparmor_socket_getpeername(struct socket *sock)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(OP_GETPEERNAME, sk);
-+}
-+
-+static int apparmor_socket_getsockopt(struct socket *sock, int level,
-+                                    int optname)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(OP_GETSOCKOPT, sk);
-+}
-+
-+static int apparmor_socket_setsockopt(struct socket *sock, int level,
-+                                    int optname)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(OP_SETSOCKOPT, sk);
-+}
-+
-+static int apparmor_socket_shutdown(struct socket *sock, int how)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
-+}
-+
-+static struct security_operations apparmor_ops = {
-+      .name =                         "apparmor",
-+
-+      .ptrace_access_check =          apparmor_ptrace_access_check,
-+      .ptrace_traceme =               apparmor_ptrace_traceme,
-+      .capget =                       apparmor_capget,
-+      .capable =                      apparmor_capable,
-+
-+      .path_link =                    apparmor_path_link,
-+      .path_unlink =                  apparmor_path_unlink,
-+      .path_symlink =                 apparmor_path_symlink,
-+      .path_mkdir =                   apparmor_path_mkdir,
-+      .path_rmdir =                   apparmor_path_rmdir,
-+      .path_mknod =                   apparmor_path_mknod,
-+      .path_rename =                  apparmor_path_rename,
-+      .path_chmod =                   apparmor_path_chmod,
-+      .path_chown =                   apparmor_path_chown,
-+      .path_truncate =                apparmor_path_truncate,
-+      .dentry_open =                  apparmor_dentry_open,
-+      .inode_getattr =                apparmor_inode_getattr,
-+
-+      .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,
-+
-+      .getprocattr =                  apparmor_getprocattr,
-+      .setprocattr =                  apparmor_setprocattr,
-+
-+      .socket_create =                apparmor_socket_create,
-+      .socket_bind =                  apparmor_socket_bind,
-+      .socket_connect =               apparmor_socket_connect,
-+      .socket_listen =                apparmor_socket_listen,
-+      .socket_accept =                apparmor_socket_accept,
-+      .socket_sendmsg =               apparmor_socket_sendmsg,
-+      .socket_recvmsg =               apparmor_socket_recvmsg,
-+      .socket_getsockname =           apparmor_socket_getsockname,
-+      .socket_getpeername =           apparmor_socket_getpeername,
-+      .socket_getsockopt =            apparmor_socket_getsockopt,
-+      .socket_setsockopt =            apparmor_socket_setsockopt,
-+      .socket_shutdown =              apparmor_socket_shutdown,
-+
-+      .cred_alloc_blank =             apparmor_cred_alloc_blank,
-+      .cred_free =                    apparmor_cred_free,
-+      .cred_prepare =                 apparmor_cred_prepare,
-+      .cred_transfer =                apparmor_cred_transfer,
-+
-+      .bprm_set_creds =               apparmor_bprm_set_creds,
-+      .bprm_committing_creds =        apparmor_bprm_committing_creds,
-+      .bprm_committed_creds =         apparmor_bprm_committed_creds,
-+      .bprm_secureexec =              apparmor_bprm_secureexec,
-+
-+      .task_setrlimit =               apparmor_task_setrlimit,
-+};
-+
-+/*
-+ * AppArmor sysfs module parameters
-+ */
-+
-+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)
-+
-+static int param_set_aalockpolicy(const char *val, struct kernel_param *kp);
-+static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp);
-+#define param_check_aalockpolicy(name, p) __param_check(name, p, int)
-+
-+static int param_set_audit(const char *val, struct kernel_param *kp);
-+static int param_get_audit(char *buffer, struct kernel_param *kp);
-+#define param_check_audit(name, p) __param_check(name, p, int)
-+
-+static int param_set_mode(const char *val, struct kernel_param *kp);
-+static int param_get_mode(char *buffer, struct kernel_param *kp);
-+#define param_check_mode(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.
-+ */
-+
-+/* AppArmor global enforcement switch - complain, enforce, kill */
-+enum profile_mode aa_g_profile_mode = APPARMOR_ENFORCE;
-+module_param_call(mode, param_set_mode, param_get_mode,
-+                &aa_g_profile_mode, S_IRUSR | S_IWUSR);
-+
-+/* Debug mode */
-+int aa_g_debug;
-+module_param_named(debug, aa_g_debug, aabool, S_IRUSR | S_IWUSR);
-+
-+/* Audit mode */
-+enum audit_mode aa_g_audit;
-+module_param_call(audit, param_set_audit, param_get_audit,
-+                &aa_g_audit, S_IRUSR | S_IWUSR);
-+
-+/* Determines if audit header is included in audited messages.  This
-+ * provides more context if the audit daemon is not running
-+ */
-+int aa_g_audit_header = 1;
-+module_param_named(audit_header, aa_g_audit_header, aabool,
-+                 S_IRUSR | S_IWUSR);
-+
-+/* lock out loading/removal of policy
-+ * TODO: add in at boot loading of policy, which is the only way to
-+ *       load policy, if lock_policy is set
-+ */
-+int aa_g_lock_policy;
-+module_param_named(lock_policy, aa_g_lock_policy, aalockpolicy,
-+                 S_IRUSR | S_IWUSR);
-+
-+/* Syscall logging mode */
-+int aa_g_logsyscall;
-+module_param_named(logsyscall, aa_g_logsyscall, aabool, S_IRUSR | S_IWUSR);
-+
-+/* Maximum pathname length before accesses will start getting rejected */
-+unsigned int aa_g_path_max = 2 * PATH_MAX;
-+module_param_named(path_max, aa_g_path_max, aauint, S_IRUSR | S_IWUSR);
-+
-+/* Determines how paranoid loading of policy is and how much verification
-+ * on the loaded policy is done.
-+ */
-+int aa_g_paranoid_load = 1;
-+module_param_named(paranoid_load, aa_g_paranoid_load, aabool,
-+                 S_IRUSR | S_IWUSR);
-+
-+/* Boot time disable flag */
-+static unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
-+module_param_named(enabled, apparmor_enabled, aabool, S_IRUSR);
-+
-+static int __init apparmor_enabled_setup(char *str)
-+{
-+      unsigned long enabled;
-+      int error = strict_strtoul(str, 0, &enabled);
-+      if (!error)
-+              apparmor_enabled = enabled ? 1 : 0;
-+      return 1;
-+}
-+
-+__setup("apparmor=", apparmor_enabled_setup);
-+
-+/* set global flag turning off the ability to load policy */
-+static int param_set_aalockpolicy(const char *val, struct kernel_param *kp)
-+{
-+      if (!capable(CAP_MAC_ADMIN))
-+              return -EPERM;
-+      if (aa_g_lock_policy)
-+              return -EACCES;
-+      return param_set_bool(val, kp);
-+}
-+
-+static int param_get_aalockpolicy(char *buffer, struct kernel_param *kp)
-+{
-+      if (!capable(CAP_MAC_ADMIN))
-+              return -EPERM;
-+      return param_get_bool(buffer, kp);
-+}
-+
-+static int param_set_aabool(const char *val, struct kernel_param *kp)
-+{
-+      if (!capable(CAP_MAC_ADMIN))
-+              return -EPERM;
-+      return param_set_bool(val, kp);
-+}
-+
-+static int param_get_aabool(char *buffer, struct kernel_param *kp)
-+{
-+      if (!capable(CAP_MAC_ADMIN))
-+              return -EPERM;
-+      return param_get_bool(buffer, kp);
-+}
-+
-+static int param_set_aauint(const char *val, struct kernel_param *kp)
-+{
-+      if (!capable(CAP_MAC_ADMIN))
-+              return -EPERM;
-+      return param_set_uint(val, kp);
-+}
-+
-+static int param_get_aauint(char *buffer, struct kernel_param *kp)
-+{
-+      if (!capable(CAP_MAC_ADMIN))
-+              return -EPERM;
-+      return param_get_uint(buffer, kp);
-+}
-+
-+static int param_get_audit(char *buffer, struct kernel_param *kp)
-+{
-+      if (!capable(CAP_MAC_ADMIN))
-+              return -EPERM;
-+
-+      if (!apparmor_enabled)
-+              return -EINVAL;
-+
-+      return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]);
-+}
-+
-+static int param_set_audit(const char *val, struct kernel_param *kp)
-+{
-+      int i;
-+      if (!capable(CAP_MAC_ADMIN))
-+              return -EPERM;
-+
-+      if (!apparmor_enabled)
-+              return -EINVAL;
-+
-+      if (!val)
-+              return -EINVAL;
-+
-+      for (i = 0; i < AUDIT_MAX_INDEX; i++) {
-+              if (strcmp(val, audit_mode_names[i]) == 0) {
-+                      aa_g_audit = i;
-+                      return 0;
-+              }
-+      }
-+
-+      return -EINVAL;
-+}
-+
-+static int param_get_mode(char *buffer, struct kernel_param *kp)
-+{
-+      if (!capable(CAP_MAC_ADMIN))
-+              return -EPERM;
-+
-+      if (!apparmor_enabled)
-+              return -EINVAL;
-+
-+      return sprintf(buffer, "%s", profile_mode_names[aa_g_profile_mode]);
-+}
-+
-+static int param_set_mode(const char *val, struct kernel_param *kp)
-+{
-+      int i;
-+      if (!capable(CAP_MAC_ADMIN))
-+              return -EPERM;
-+
-+      if (!apparmor_enabled)
-+              return -EINVAL;
-+
-+      if (!val)
-+              return -EINVAL;
-+
-+      for (i = 0; i < APPARMOR_NAMES_MAX_INDEX; i++) {
-+              if (strcmp(val, profile_mode_names[i]) == 0) {
-+                      aa_g_profile_mode = i;
-+                      return 0;
-+              }
-+      }
-+
-+      return -EINVAL;
-+}
-+
-+/*
-+ * AppArmor init functions
-+ */
-+
-+/**
-+ * set_init_cxt - set a task context and profile on the first task.
-+ *
-+ * TODO: allow setting an alternate profile than unconfined
-+ */
-+static int __init set_init_cxt(void)
-+{
-+      struct cred *cred = (struct cred *)current->real_cred;
-+      struct aa_task_cxt *cxt;
-+
-+      cxt = aa_alloc_task_context(GFP_KERNEL);
-+      if (!cxt)
-+              return -ENOMEM;
-+
-+      cxt->profile = aa_get_profile(root_ns->unconfined);
-+      cred->security = cxt;
-+
-+      return 0;
-+}
-+
-+static int __init apparmor_init(void)
-+{
-+      int error;
-+
-+      if (!apparmor_enabled || !security_module_enable(&apparmor_ops)) {
-+              aa_info_message("AppArmor disabled by boot time parameter");
-+              apparmor_enabled = 0;
-+              return 0;
-+      }
-+
-+      error = aa_alloc_root_ns();
-+      if (error) {
-+              AA_ERROR("Unable to allocate default profile namespace\n");
-+              goto alloc_out;
-+      }
-+
-+      error = set_init_cxt();
-+      if (error) {
-+              AA_ERROR("Failed to set context on init task\n");
-+              goto register_security_out;
-+      }
-+
-+      error = register_security(&apparmor_ops);
-+      if (error) {
-+              AA_ERROR("Unable to register AppArmor\n");
-+              goto register_security_out;
-+      }
-+
-+      /* Report that AppArmor successfully initialized */
-+      apparmor_initialized = 1;
-+      if (aa_g_profile_mode == APPARMOR_COMPLAIN)
-+              aa_info_message("AppArmor initialized: complain mode enabled");
-+      else if (aa_g_profile_mode == APPARMOR_KILL)
-+              aa_info_message("AppArmor initialized: kill mode enabled");
-+      else
-+              aa_info_message("AppArmor initialized");
-+
-+      return error;
-+
-+register_security_out:
-+      aa_free_root_ns();
-+
-+alloc_out:
-+      aa_destroy_aafs();
-+
-+      apparmor_enabled = 0;
-+      return error;
-+
-+}
-+
-+security_initcall(apparmor_init);
-diff --git a/security/apparmor/match.c b/security/apparmor/match.c
-new file mode 100644
-index 0000000..0248bb3
---- /dev/null
-+++ b/security/apparmor/match.c
-@@ -0,0 +1,370 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor dfa based regular expression matching engine
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#include <linux/errno.h>
-+#include <linux/kernel.h>
-+#include <linux/mm.h>
-+#include <linux/slab.h>
-+#include <linux/vmalloc.h>
-+#include <linux/err.h>
-+#include <linux/kref.h>
-+
-+#include "include/apparmor.h"
-+#include "include/match.h"
-+
-+/**
-+ * unpack_table - unpack a dfa table (one of accept, default, base, next check)
-+ * @blob: data to unpack (NOT NULL)
-+ * @bsize: size of blob
-+ *
-+ * Returns: pointer to table else NULL on failure
-+ *
-+ * NOTE: must be freed by kvfree (not kmalloc)
-+ */
-+static struct table_header *unpack_table(char *blob, size_t bsize)
-+{
-+      struct table_header *table = NULL;
-+      struct table_header th;
-+      size_t tsize;
-+
-+      if (bsize < sizeof(struct table_header))
-+              goto out;
-+
-+      /* loaded td_id's start at 1, subtract 1 now to avoid doing
-+       * it every time we use td_id as an index
-+       */
-+      th.td_id = be16_to_cpu(*(u16 *) (blob)) - 1;
-+      th.td_flags = be16_to_cpu(*(u16 *) (blob + 2));
-+      th.td_lolen = be32_to_cpu(*(u32 *) (blob + 8));
-+      blob += sizeof(struct table_header);
-+
-+      if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
-+            th.td_flags == YYTD_DATA8))
-+              goto out;
-+
-+      tsize = table_size(th.td_lolen, th.td_flags);
-+      if (bsize < tsize)
-+              goto out;
-+
-+      /* Pad table allocation for next/check by 256 entries to remain
-+       * backwards compatible with old (buggy) tools and remain safe without
-+       * run time checks
-+       */
-+      if (th.td_id == YYTD_ID_NXT || th.td_id == YYTD_ID_CHK)
-+              tsize += 256 * th.td_flags;
-+
-+      table = kvmalloc(tsize);
-+      if (table) {
-+              /* ensure the pad is clear, else there will be errors */
-+              memset(table, 0, tsize);
-+              *table = th;
-+              if (th.td_flags == YYTD_DATA8)
-+                      UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
-+                                   u8, byte_to_byte);
-+              else if (th.td_flags == YYTD_DATA16)
-+                      UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
-+                                   u16, be16_to_cpu);
-+              else if (th.td_flags == YYTD_DATA32)
-+                      UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
-+                                   u32, be32_to_cpu);
-+              else
-+                      goto fail;
-+      }
-+
-+out:
-+      /* if table was vmalloced make sure the page tables are synced
-+       * before it is used, as it goes live to all cpus.
-+       */
-+      if (is_vmalloc_addr(table))
-+              vm_unmap_aliases();
-+      return table;
-+fail:
-+      kvfree(table);
-+      return NULL;
-+}
-+
-+/**
-+ * verify_dfa - verify that transitions and states in the tables are in bounds.
-+ * @dfa: dfa to test  (NOT NULL)
-+ * @flags: flags controlling what type of accept table are acceptable
-+ *
-+ * Assumes dfa has gone through the first pass verification done by unpacking
-+ * NOTE: this does not valid accept table values
-+ *
-+ * Returns: %0 else error code on failure to verify
-+ */
-+static int verify_dfa(struct aa_dfa *dfa, int flags)
-+{
-+      size_t i, state_count, trans_count;
-+      int error = -EPROTO;
-+
-+      /* check that required tables exist */
-+      if (!(dfa->tables[YYTD_ID_DEF] &&
-+            dfa->tables[YYTD_ID_BASE] &&
-+            dfa->tables[YYTD_ID_NXT] && dfa->tables[YYTD_ID_CHK]))
-+              goto out;
-+
-+      /* accept.size == default.size == base.size */
-+      state_count = dfa->tables[YYTD_ID_BASE]->td_lolen;
-+      if (ACCEPT1_FLAGS(flags)) {
-+              if (!dfa->tables[YYTD_ID_ACCEPT])
-+                      goto out;
-+              if (state_count != dfa->tables[YYTD_ID_ACCEPT]->td_lolen)
-+                      goto out;
-+      }
-+      if (ACCEPT2_FLAGS(flags)) {
-+              if (!dfa->tables[YYTD_ID_ACCEPT2])
-+                      goto out;
-+              if (state_count != dfa->tables[YYTD_ID_ACCEPT2]->td_lolen)
-+                      goto out;
-+      }
-+      if (state_count != dfa->tables[YYTD_ID_DEF]->td_lolen)
-+              goto out;
-+
-+      /* next.size == chk.size */
-+      trans_count = dfa->tables[YYTD_ID_NXT]->td_lolen;
-+      if (trans_count != dfa->tables[YYTD_ID_CHK]->td_lolen)
-+              goto out;
-+
-+      /* if equivalence classes then its table size must be 256 */
-+      if (dfa->tables[YYTD_ID_EC] &&
-+          dfa->tables[YYTD_ID_EC]->td_lolen != 256)
-+              goto out;
-+
-+      if (flags & DFA_FLAG_VERIFY_STATES) {
-+              int warning = 0;
-+              for (i = 0; i < state_count; i++) {
-+                      if (DEFAULT_TABLE(dfa)[i] >= state_count)
-+                              goto out;
-+                      /* TODO: do check that DEF state recursion terminates */
-+                      if (BASE_TABLE(dfa)[i] + 255 >= trans_count) {
-+                              if (warning)
-+                                      continue;
-+                              printk(KERN_WARNING "AppArmor DFA next/check "
-+                                     "upper bounds error fixed, upgrade "
-+                                     "user space tools \n");
-+                              warning = 1;
-+                      } else if (BASE_TABLE(dfa)[i] >= trans_count) {
-+                              printk(KERN_ERR "AppArmor DFA next/check upper "
-+                                     "bounds error\n");
-+                              goto out;
-+                      }
-+              }
-+
-+              for (i = 0; i < trans_count; i++) {
-+                      if (NEXT_TABLE(dfa)[i] >= state_count)
-+                              goto out;
-+                      if (CHECK_TABLE(dfa)[i] >= state_count)
-+                              goto out;
-+              }
-+      }
-+
-+      error = 0;
-+out:
-+      return error;
-+}
-+
-+/**
-+ * dfa_free - free a dfa allocated by aa_dfa_unpack
-+ * @dfa: the dfa to free  (MAYBE NULL)
-+ *
-+ * Requires: reference count to dfa == 0
-+ */
-+static void dfa_free(struct aa_dfa *dfa)
-+{
-+      if (dfa) {
-+              int i;
-+
-+              for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
-+                      kvfree(dfa->tables[i]);
-+                      dfa->tables[i] = NULL;
-+              }
-+              kfree(dfa);
-+      }
-+}
-+
-+/**
-+ * aa_dfa_free_kref - free aa_dfa by kref (called by aa_put_dfa)
-+ * @kr: kref callback for freeing of a dfa  (NOT NULL)
-+ */
-+void aa_dfa_free_kref(struct kref *kref)
-+{
-+      struct aa_dfa *dfa = container_of(kref, struct aa_dfa, count);
-+      dfa_free(dfa);
-+}
-+
-+/**
-+ * aa_dfa_unpack - unpack the binary tables of a serialized dfa
-+ * @blob: aligned serialized stream of data to unpack  (NOT NULL)
-+ * @size: size of data to unpack
-+ * @flags: flags controlling what type of accept tables are acceptable
-+ *
-+ * Unpack a dfa that has been serialized.  To find information on the dfa
-+ * format look in Documentation/apparmor.txt
-+ * Assumes the dfa @blob stream has been aligned on a 8 byte boundry
-+ *
-+ * Returns: an unpacked dfa ready for matching or ERR_PTR on failure
-+ */
-+struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags)
-+{
-+      int hsize;
-+      int error = -ENOMEM;
-+      char *data = blob;
-+      struct table_header *table = NULL;
-+      struct aa_dfa *dfa = kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
-+      if (!dfa)
-+              goto fail;
-+
-+      kref_init(&dfa->count);
-+
-+      error = -EPROTO;
-+
-+      /* get dfa table set header */
-+      if (size < sizeof(struct table_set_header))
-+              goto fail;
-+
-+      if (ntohl(*(u32 *) data) != YYTH_MAGIC)
-+              goto fail;
-+
-+      hsize = ntohl(*(u32 *) (data + 4));
-+      if (size < hsize)
-+              goto fail;
-+
-+      dfa->flags = ntohs(*(u16 *) (data + 12));
-+      data += hsize;
-+      size -= hsize;
-+
-+      while (size > 0) {
-+              table = unpack_table(data, size);
-+              if (!table)
-+                      goto fail;
-+
-+              switch (table->td_id) {
-+              case YYTD_ID_ACCEPT:
-+                      if (!(table->td_flags & ACCEPT1_FLAGS(flags)))
-+                              goto fail;
-+                      break;
-+              case YYTD_ID_ACCEPT2:
-+                      if (!(table->td_flags & ACCEPT2_FLAGS(flags)))
-+                              goto fail;
-+                      break;
-+              case YYTD_ID_BASE:
-+                      if (table->td_flags != YYTD_DATA32)
-+                              goto fail;
-+                      break;
-+              case YYTD_ID_DEF:
-+              case YYTD_ID_NXT:
-+              case YYTD_ID_CHK:
-+                      if (table->td_flags != YYTD_DATA16)
-+                              goto fail;
-+                      break;
-+              case YYTD_ID_EC:
-+                      if (table->td_flags != YYTD_DATA8)
-+                              goto fail;
-+                      break;
-+              default:
-+                      goto fail;
-+              }
-+              /* check for duplicate table entry */
-+              if (dfa->tables[table->td_id])
-+                      goto fail;
-+              dfa->tables[table->td_id] = table;
-+              data += table_size(table->td_lolen, table->td_flags);
-+              size -= table_size(table->td_lolen, table->td_flags);
-+              table = NULL;
-+      }
-+
-+      error = verify_dfa(dfa, flags);
-+      if (error)
-+              goto fail;
-+
-+      return dfa;
-+
-+fail:
-+      kvfree(table);
-+      dfa_free(dfa);
-+      return ERR_PTR(error);
-+}
-+
-+/**
-+ * aa_dfa_match_len - traverse @dfa to find state @str stops at
-+ * @dfa: the dfa to match @str against  (NOT NULL)
-+ * @start: the state of the dfa to start matching in
-+ * @str: the string of bytes to match against the dfa  (NOT NULL)
-+ * @len: length of the string of bytes to match
-+ *
-+ * aa_dfa_match_len will match @str against the dfa and return the state it
-+ * finished matching in. The final state can be used to look up the accepting
-+ * label, or as the start state of a continuing match.
-+ *
-+ * This function will happily match again the 0 byte and only finishes
-+ * when @len input is consumed.
-+ *
-+ * Returns: final state reached after input is consumed
-+ */
-+unsigned int aa_dfa_match_len(struct aa_dfa *dfa, unsigned int start,
-+                            const char *str, int len)
-+{
-+      u16 *def = DEFAULT_TABLE(dfa);
-+      u32 *base = BASE_TABLE(dfa);
-+      u16 *next = NEXT_TABLE(dfa);
-+      u16 *check = CHECK_TABLE(dfa);
-+      unsigned int state = start, pos;
-+
-+      if (state == 0)
-+              return 0;
-+
-+      /* current state is <state>, matching character *str */
-+      if (dfa->tables[YYTD_ID_EC]) {
-+              /* Equivalence class table defined */
-+              u8 *equiv = EQUIV_TABLE(dfa);
-+              /* default is direct to next state */
-+              for (; len; len--) {
-+                      pos = base[state] + equiv[(u8) *str++];
-+                      if (check[pos] == state)
-+                              state = next[pos];
-+                      else
-+                              state = def[state];
-+              }
-+      } else {
-+              /* default is direct to next state */
-+              for (; len; len--) {
-+                      pos = base[state] + (u8) *str++;
-+                      if (check[pos] == state)
-+                              state = next[pos];
-+                      else
-+                              state = def[state];
-+              }
-+      }
-+
-+      return state;
-+}
-+
-+/**
-+ * aa_dfa_next_state - traverse @dfa to find state @str stops at
-+ * @dfa: the dfa to match @str against  (NOT NULL)
-+ * @start: the state of the dfa to start matching in
-+ * @str: the null terminated string of bytes to match against the dfa (NOT NULL)
-+ *
-+ * aa_dfa_next_state will match @str against the dfa and return the state it
-+ * finished matching in. The final state can be used to look up the accepting
-+ * label, or as the start state of a continuing match.
-+ *
-+ * Returns: final state reached after input is consumed
-+ */
-+unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
-+                        const char *str)
-+{
-+      return aa_dfa_match_len(dfa, start, str, strlen(str));
-+}
-diff --git a/security/apparmor/net.c b/security/apparmor/net.c
-new file mode 100644
-index 0000000..7c36e82
---- /dev/null
-+++ b/security/apparmor/net.c
-@@ -0,0 +1,169 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor network mediation
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#include "include/apparmor.h"
-+#include "include/audit.h"
-+#include "include/context.h"
-+#include "include/net.h"
-+#include "include/policy.h"
-+
-+#include "af_names.h"
-+
-+static const char *sock_type_names[] = {
-+      "unknown(0)",
-+      "stream",
-+      "dgram",
-+      "raw",
-+      "rdm",
-+      "seqpacket",
-+      "dccp",
-+      "unknown(7)",
-+      "unknown(8)",
-+      "unknown(9)",
-+      "packet",
-+};
-+
-+/* audit callback for net specific fields */
-+static void audit_cb(struct audit_buffer *ab, void *va)
-+{
-+      struct common_audit_data *sa = va;
-+
-+      audit_log_format(ab, " family=");
-+      if (address_family_names[sa->u.net.family]) {
-+              audit_log_string(ab, address_family_names[sa->u.net.family]);
-+      } else {
-+              audit_log_format(ab, " \"unknown(%d)\"", sa->u.net.family);
-+      }
-+
-+      audit_log_format(ab, " sock_type=");
-+      if (sock_type_names[sa->aad.net.type]) {
-+              audit_log_string(ab, sock_type_names[sa->aad.net.type]);
-+      } else {
-+              audit_log_format(ab, "\"unknown(%d)\"", sa->aad.net.type);
-+      }
-+
-+      audit_log_format(ab, " protocol=%d", sa->aad.net.protocol);
-+}
-+
-+/**
-+ * audit_net - audit network access
-+ * @profile: profile being enforced  (NOT NULL)
-+ * @op: operation being checked
-+ * @family: network family
-+ * @type:   network type
-+ * @protocol: network protocol
-+ * @sk: socket auditing is being applied to
-+ * @error: error code for failure else 0
-+ *
-+ * Returns: %0 or sa->error else other errorcode on failure
-+ */
-+static int audit_net(struct aa_profile *profile, int op, u16 family, int type,
-+                   int protocol, struct sock *sk, int error)
-+{
-+      int audit_type = AUDIT_APPARMOR_AUTO;
-+      struct common_audit_data sa;
-+      if (sk) {
-+              COMMON_AUDIT_DATA_INIT(&sa, NET);
-+      } else {
-+              COMMON_AUDIT_DATA_INIT(&sa, NONE);
-+      }
-+      /* todo fill in socket addr info */
-+
-+      sa.aad.op = op,
-+      sa.u.net.family = family;
-+      sa.u.net.sk = sk;
-+      sa.aad.net.type = type;
-+      sa.aad.net.protocol = protocol;
-+
-+      if (likely(!sa.aad.error)) {
-+              u16 audit_mask = profile->net.audit[sa.u.net.family];
-+              if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
-+                         !(1 << sa.aad.net.type & audit_mask)))
-+                      return 0;
-+              audit_type = AUDIT_APPARMOR_AUDIT;
-+      } else {
-+              u16 quiet_mask = profile->net.quiet[sa.u.net.family];
-+              u16 kill_mask = 0;
-+              u16 denied = (1 << sa.aad.net.type) & ~quiet_mask;
-+
-+              if (denied & kill_mask)
-+                      audit_type = AUDIT_APPARMOR_KILL;
-+
-+              if ((denied & quiet_mask) &&
-+                  AUDIT_MODE(profile) != AUDIT_NOQUIET &&
-+                  AUDIT_MODE(profile) != AUDIT_ALL)
-+                      return COMPLAIN_MODE(profile) ? 0 : sa.aad.error;
-+      }
-+
-+      return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
-+}
-+
-+/**
-+ * aa_net_perm - very course network access check
-+ * @op: operation being checked
-+ * @profile: profile being enforced  (NOT NULL)
-+ * @family: network family
-+ * @type:   network type
-+ * @protocol: network protocol
-+ *
-+ * Returns: %0 else error if permission denied
-+ */
-+int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
-+              int protocol, struct sock *sk)
-+{
-+      u16 family_mask;
-+      int error;
-+
-+      if ((family < 0) || (family >= AF_MAX))
-+              return -EINVAL;
-+
-+      if ((type < 0) || (type >= SOCK_MAX))
-+              return -EINVAL;
-+
-+      /* unix domain and netlink sockets are handled by ipc */
-+      if (family == AF_UNIX || family == AF_NETLINK)
-+              return 0;
-+
-+      family_mask = profile->net.allow[family];
-+
-+      error = (family_mask & (1 << type)) ? 0 : -EACCES;
-+
-+      return audit_net(profile, op, family, type, protocol, sk, error);
-+}
-+
-+/**
-+ * aa_revalidate_sk - Revalidate access to a sock
-+ * @op: operation being checked
-+ * @sk: sock being revalidated  (NOT NULL)
-+ *
-+ * Returns: %0 else error if permission denied
-+ */
-+int aa_revalidate_sk(int op, struct sock *sk)
-+{
-+      struct aa_profile *profile;
-+      int error = 0;
-+
-+      /* aa_revalidate_sk should not be called from interrupt context
-+       * don't mediate these calls as they are not task related
-+       */
-+      if (in_interrupt())
-+              return 0;
-+
-+      profile = __aa_current_profile();
-+      if (!unconfined(profile))
-+              error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
-+                                  sk->sk_protocol, sk);
-+
-+      return error;
-+}
-diff --git a/security/apparmor/path.c b/security/apparmor/path.c
-new file mode 100644
-index 0000000..96bab94
---- /dev/null
-+++ b/security/apparmor/path.c
-@@ -0,0 +1,235 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor function for pathnames
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#include <linux/magic.h>
-+#include <linux/mnt_namespace.h>
-+#include <linux/mount.h>
-+#include <linux/namei.h>
-+#include <linux/nsproxy.h>
-+#include <linux/path.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/fs_struct.h>
-+
-+#include "include/apparmor.h"
-+#include "include/path.h"
-+#include "include/policy.h"
-+
-+
-+/* modified from dcache.c */
-+static int prepend(char **buffer, int buflen, const char *str, int namelen)
-+{
-+      buflen -= namelen;
-+      if (buflen < 0)
-+              return -ENAMETOOLONG;
-+      *buffer -= namelen;
-+      memcpy(*buffer, str, namelen);
-+      return 0;
-+}
-+
-+#define CHROOT_NSCONNECT (PATH_CHROOT_REL | PATH_CHROOT_NSCONNECT)
-+
-+/**
-+ * d_namespace_path - lookup a name associated with a given path
-+ * @path: path to lookup  (NOT NULL)
-+ * @buf:  buffer to store path to  (NOT NULL)
-+ * @buflen: length of @buf
-+ * @name: Returns - pointer for start of path name with in @buf (NOT NULL)
-+ * @flags: flags controlling path lookup
-+ *
-+ * Handle path name lookup.
-+ *
-+ * Returns: %0 else error code if path lookup fails
-+ *          When no error the path name is returned in @name which points to
-+ *          to a position in @buf
-+ */
-+static int d_namespace_path(struct path *path, char *buf, int buflen,
-+                          char **name, int flags)
-+{
-+      struct path root, tmp;
-+      char *res;
-+      int deleted, connected;
-+      int error = 0;
-+
-+      /* Get the root we want to resolve too */
-+      if (flags & PATH_CHROOT_REL) {
-+              /* resolve paths relative to chroot */
-+              read_lock(&current->fs->lock);
-+              root = current->fs->root;
-+              /* released below */
-+              path_get(&root);
-+              read_unlock(&current->fs->lock);
-+      } else {
-+              /* resolve paths relative to namespace */
-+              root.mnt = current->nsproxy->mnt_ns->root;
-+              root.dentry = root.mnt->mnt_root;
-+              /* released below */
-+              path_get(&root);
-+      }
-+
-+      spin_lock(&dcache_lock);
-+      /* There is a race window between path lookup here and the
-+       * need to strip the " (deleted) string that __d_path applies
-+       * Detect the race and relookup the path
-+       *
-+       * The stripping of (deleted) is a hack that could be removed
-+       * with an updated __d_path
-+       */
-+      do {
-+              tmp = root;
-+              deleted = d_unlinked(path->dentry);
-+              res = __d_path(path, &tmp, buf, buflen);
-+
-+      } while (deleted != d_unlinked(path->dentry));
-+      spin_unlock(&dcache_lock);
-+
-+      *name = res;
-+      /* handle error conditions - and still allow a partial path to
-+       * be returned.
-+       */
-+      if (IS_ERR(res)) {
-+              error = PTR_ERR(res);
-+              *name = buf;
-+              goto out;
-+      }
-+      if (deleted) {
-+              /* On some filesystems, newly allocated dentries appear to the
-+               * security_path hooks as a deleted dentry except without an
-+               * inode allocated.
-+               *
-+               * Remove the appended deleted text and return as string for
-+               * normal mediation, or auditing.  The (deleted) string is
-+               * guaranteed to be added in this case, so just strip it.
-+               */
-+              buf[buflen - 11] = 0;   /* - (len(" (deleted)") +\0) */
-+
-+              if (path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) {
-+                      error = -ENOENT;
-+                      goto out;
-+              }
-+      }
-+
-+      /* Determine if the path is connected to the expected root */
-+      connected = tmp.dentry == root.dentry && tmp.mnt == root.mnt;
-+
-+      /* If the path is not connected,
-+       * check if it is a sysctl and handle specially else remove any
-+       * leading / that __d_path may have returned.
-+       * Unless
-+       *     specifically directed to connect the path,
-+       * OR
-+       *     if in a chroot and doing chroot relative paths and the path
-+       *     resolves to the namespace root (would be connected outside
-+       *     of chroot) and specifically directed to connect paths to
-+       *     namespace root.
-+       */
-+      if (!connected) {
-+              /* is the disconnect path a sysctl? */
-+              if (tmp.dentry->d_sb->s_magic == PROC_SUPER_MAGIC &&
-+                  strncmp(*name, "/sys/", 5) == 0) {
-+                      /* TODO: convert over to using a per namespace
-+                       * control instead of hard coded /proc
-+                       */
-+                      error = prepend(name, *name - buf, "/proc", 5);
-+              } else if (!(flags & PATH_CONNECT_PATH) &&
-+                         !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
-+                           (tmp.mnt == current->nsproxy->mnt_ns->root &&
-+                            tmp.dentry == tmp.mnt->mnt_root))) {
-+                      /* disconnected path, don't return pathname starting
-+                       * with '/'
-+                       */
-+                      error = -ESTALE;
-+                      if (*res == '/')
-+                              *name = res + 1;
-+              }
-+      }
-+
-+out:
-+      path_put(&root);
-+
-+      return error;
-+}
-+
-+/**
-+ * get_name_to_buffer - get the pathname to a buffer ensure dir / is appended
-+ * @path: path to get name for  (NOT NULL)
-+ * @flags: flags controlling path lookup
-+ * @buffer: buffer to put name in  (NOT NULL)
-+ * @size: size of buffer
-+ * @name: Returns - contains position of path name in @buffer (NOT NULL)
-+ *
-+ * Returns: %0 else error on failure
-+ */
-+static int get_name_to_buffer(struct path *path, int flags, char *buffer,
-+                            int size, char **name)
-+{
-+      int adjust = (flags & PATH_IS_DIR) ? 1 : 0;
-+      int error = d_namespace_path(path, buffer, size - adjust, name, flags);
-+
-+      if (!error && (flags & PATH_IS_DIR) && (*name)[1] != '\0')
-+              /*
-+               * Append "/" to the pathname.  The root directory is a special
-+               * case; it already ends in slash.
-+               */
-+              strcpy(&buffer[size - 2], "/");
-+
-+      return error;
-+}
-+
-+/**
-+ * aa_get_name - compute the pathname of a file
-+ * @path: path the file  (NOT NULL)
-+ * @flags: flags controlling path name generation
-+ * @buffer: buffer that aa_get_name() allocated  (NOT NULL)
-+ * @name: Returns - the generated path name if !error (NOT NULL)
-+ *
-+ * @name is a pointer to the beginning of the pathname (which usually differs
-+ * from the beginning of the buffer), or NULL.  If there is an error @name
-+ * may contain a partial or invalid name that can be used for audit purposes,
-+ * but it can not be used for mediation.
-+ *
-+ * We need PATH_IS_DIR to indicate whether the file is a directory or not
-+ * because the file may not yet exist, and so we cannot check the inode's
-+ * file type.
-+ *
-+ * Returns: %0 else error code if could retrieve name
-+ */
-+int aa_get_name(struct path *path, int flags, char **buffer, const char **name)
-+{
-+      char *buf, *str = NULL;
-+      int size = 256;
-+      int error;
-+
-+      *name = NULL;
-+      *buffer = NULL;
-+      for (;;) {
-+              /* freed by caller */
-+              buf = kmalloc(size, GFP_KERNEL);
-+              if (!buf)
-+                      return -ENOMEM;
-+
-+              error = get_name_to_buffer(path, flags, buf, size, &str);
-+              if (error != -ENAMETOOLONG)
-+                      break;
-+
-+              kfree(buf);
-+              size <<= 1;
-+              if (size > aa_g_path_max)
-+                      return -ENAMETOOLONG;
-+      }
-+      *buffer = buf;
-+      *name = str;
-+
-+      return error;
-+}
-diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
-new file mode 100644
-index 0000000..e3020ed
---- /dev/null
-+++ b/security/apparmor/policy.c
-@@ -0,0 +1,1185 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor policy manipulation functions
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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 policy is based around profiles, which contain the rules a
-+ * task is confined by.  Every task in the system has a profile attached
-+ * to it determined either by matching "unconfined" tasks against the
-+ * visible set of profiles or by following a profiles attachment rules.
-+ *
-+ * Each profile exists in a profile namespace which is a container of
-+ * visible profiles.  Each namespace contains a special "unconfined" profile,
-+ * which doesn't enforce any confinement on a task beyond DAC.
-+ *
-+ * Namespace and profile names can be written together in either
-+ * of two syntaxes.
-+ *    :namespace:profile - used by kernel interfaces for easy detection
-+ *    namespace://profile - used by policy
-+ *
-+ * Profile names can not start with : or @ or ^ and may not contain \0
-+ *
-+ * Reserved profile names
-+ *    unconfined - special automatically generated unconfined profile
-+ *    inherit - special name to indicate profile inheritance
-+ *    null-XXXX-YYYY - special automatically generated learning profiles
-+ *
-+ * Namespace names may not start with / or @ and may not contain \0 or :
-+ * Reserved namespace names
-+ *    user-XXXX - user defined profiles
-+ *
-+ * a // in a profile or namespace name indicates a hierarchical name with the
-+ * name before the // being the parent and the name after the child.
-+ *
-+ * Profile and namespace hierarchies serve two different but similar purposes.
-+ * The namespace contains the set of visible profiles that are considered
-+ * for attachment.  The hierarchy of namespaces allows for virtualizing
-+ * the namespace so that for example a chroot can have its own set of profiles
-+ * which may define some local user namespaces.
-+ * The profile hierarchy severs two distinct purposes,
-+ * -  it allows for sub profiles or hats, which allows an application to run
-+ *    subprograms under its own profile with different restriction than it
-+ *    self, and not have it use the system profile.
-+ *    eg. if a mail program starts an editor, the policy might make the
-+ *        restrictions tighter on the editor tighter than the mail program,
-+ *        and definitely different than general editor restrictions
-+ * - it allows for binary hierarchy of profiles, so that execution history
-+ *   is preserved.  This feature isn't exploited by AppArmor reference policy
-+ *   but is allowed.  NOTE: this is currently suboptimal because profile
-+ *   aliasing is not currently implemented so that a profile for each
-+ *   level must be defined.
-+ *   eg. /bin/bash///bin/ls as a name would indicate /bin/ls was started
-+ *       from /bin/bash
-+ *
-+ *   A profile or namespace name that can contain one or more // separators
-+ *   is referred to as an hname (hierarchical).
-+ *   eg.  /bin/bash//bin/ls
-+ *
-+ *   An fqname is a name that may contain both namespace and profile hnames.
-+ *   eg. :ns:/bin/bash//bin/ls
-+ *
-+ * NOTES:
-+ *   - locking of profile lists is currently fairly coarse.  All profile
-+ *     lists within a namespace use the namespace lock.
-+ * FIXME: move profile lists to using rcu_lists
-+ */
-+
-+#include <linux/slab.h>
-+#include <linux/spinlock.h>
-+#include <linux/string.h>
-+
-+#include "include/apparmor.h"
-+#include "include/capability.h"
-+#include "include/context.h"
-+#include "include/file.h"
-+#include "include/ipc.h"
-+#include "include/match.h"
-+#include "include/path.h"
-+#include "include/policy.h"
-+#include "include/policy_unpack.h"
-+#include "include/resource.h"
-+#include "include/sid.h"
-+
-+
-+/* root profile namespace */
-+struct aa_namespace *root_ns;
-+
-+const char *profile_mode_names[] = {
-+      "enforce",
-+      "complain",
-+      "kill",
-+};
-+
-+/**
-+ * hname_tail - find the last component of an hname
-+ * @name: hname to find the base profile name component of  (NOT NULL)
-+ *
-+ * Returns: the tail (base profile name) name component of an hname
-+ */
-+static const char *hname_tail(const char *hname)
-+{
-+      char *split;
-+      hname = strim((char *)hname);
-+      for (split = strstr(hname, "//"); split; split = strstr(hname, "//"))
-+              hname = split + 2;
-+
-+      return hname;
-+}
-+
-+/**
-+ * policy_init - initialize a policy structure
-+ * @policy: policy to initialize  (NOT NULL)
-+ * @prefix: prefix name if any is required.  (MAYBE NULL)
-+ * @name: name of the policy, init will make a copy of it  (NOT NULL)
-+ *
-+ * Note: this fn creates a copy of strings passed in
-+ *
-+ * Returns: true if policy init successful
-+ */
-+static bool policy_init(struct aa_policy *policy, const char *prefix,
-+                      const char *name)
-+{
-+      /* freed by policy_free */
-+      if (prefix) {
-+              policy->hname = kmalloc(strlen(prefix) + strlen(name) + 3,
-+                                      GFP_KERNEL);
-+              if (policy->hname)
-+                      sprintf(policy->hname, "%s//%s", prefix, name);
-+      } else
-+              policy->hname = kstrdup(name, GFP_KERNEL);
-+      if (!policy->hname)
-+              return 0;
-+      /* base.name is a substring of fqname */
-+      policy->name = (char *)hname_tail(policy->hname);
-+      INIT_LIST_HEAD(&policy->list);
-+      INIT_LIST_HEAD(&policy->profiles);
-+      kref_init(&policy->count);
-+
-+      return 1;
-+}
-+
-+/**
-+ * policy_destroy - free the elements referenced by @policy
-+ * @policy: policy that is to have its elements freed  (NOT NULL)
-+ */
-+static void policy_destroy(struct aa_policy *policy)
-+{
-+      /* still contains profiles -- invalid */
-+      if (!list_empty(&policy->profiles)) {
-+              AA_ERROR("%s: internal error, "
-+                       "policy '%s' still contains profiles\n",
-+                       __func__, policy->name);
-+              BUG();
-+      }
-+      if (!list_empty(&policy->list)) {
-+              AA_ERROR("%s: internal error, policy '%s' still on list\n",
-+                       __func__, policy->name);
-+              BUG();
-+      }
-+
-+      /* don't free name as its a subset of hname */
-+      kzfree(policy->hname);
-+}
-+
-+/**
-+ * __policy_find - find a policy by @name on a policy list
-+ * @head: list to search  (NOT NULL)
-+ * @name: name to search for  (NOT NULL)
-+ *
-+ * Requires: correct locks for the @head list be held
-+ *
-+ * Returns: unrefcounted policy that match @name or NULL if not found
-+ */
-+static struct aa_policy *__policy_find(struct list_head *head, const char *name)
-+{
-+      struct aa_policy *policy;
-+
-+      list_for_each_entry(policy, head, list) {
-+              if (!strcmp(policy->name, name))
-+                      return policy;
-+      }
-+      return NULL;
-+}
-+
-+/**
-+ * __policy_strn_find - find a policy that's name matches @len chars of @str
-+ * @head: list to search  (NOT NULL)
-+ * @str: string to search for  (NOT NULL)
-+ * @len: length of match required
-+ *
-+ * Requires: correct locks for the @head list be held
-+ *
-+ * Returns: unrefcounted policy that match @str or NULL if not found
-+ *
-+ * if @len == strlen(@strlen) then this is equiv to __policy_find
-+ * other wise it allows searching for policy by a partial match of name
-+ */
-+static struct aa_policy *__policy_strn_find(struct list_head *head,
-+                                          const char *str, int len)
-+{
-+      struct aa_policy *policy;
-+
-+      list_for_each_entry(policy, head, list) {
-+              if (aa_strneq(policy->name, str, len))
-+                      return policy;
-+      }
-+
-+      return NULL;
-+}
-+
-+/*
-+ * Routines for AppArmor namespaces
-+ */
-+
-+static const char *hidden_ns_name = "---";
-+/**
-+ * aa_ns_visible - test if @view is visible from @curr
-+ * @curr: namespace to treat as the parent (NOT NULL)
-+ * @view:  namespace to test if visible from @curr (NOT NULL)
-+ *
-+ * Returns: true if @view is visible from @curr else false
-+ */
-+bool aa_ns_visible(struct aa_namespace *curr, struct aa_namespace *view)
-+{
-+      if (curr == view)
-+              return true;
-+
-+      for ( ; view; view = view->parent) {
-+              if (view->parent == curr)
-+                      return true;
-+      }
-+      return false;
-+}
-+
-+/**
-+ * aa_na_name - Find the ns name to display for @view from @curr
-+ * @curr - current namespace (NOT NULL)
-+ * @view - namespace attempting to view (NOT NULL)
-+ *
-+ * Returns: name of @view visible from @curr
-+ */
-+const char *aa_ns_name(struct aa_namespace *curr, struct aa_namespace *view)
-+{
-+      /* if view == curr then the namespace name isn't displayed */
-+      if (curr == view)
-+              return "";
-+
-+      if (aa_ns_visible(curr, view)) {
-+              /* at this point if a ns is visible it is in a view ns
-+               * thus the curr ns.hname is a prefix of its name.
-+               * Only output the virtualized portion of the name
-+               * Add + 2 to skip over // separating curr hname prefix
-+               * from the visible tail of the views hname
-+               */
-+              return view->base.hname + strlen(curr->base.hname) + 2;
-+      } else
-+              return hidden_ns_name;
-+}
-+
-+/**
-+ * alloc_namespace - allocate, initialize and return a new namespace
-+ * @prefix: parent namespace name (MAYBE NULL)
-+ * @name: a preallocated name  (NOT NULL)
-+ *
-+ * Returns: refcounted namespace or NULL on failure.
-+ */
-+static struct aa_namespace *alloc_namespace(const char *prefix,
-+                                          const char *name)
-+{
-+      struct aa_namespace *ns;
-+
-+      ns = kzalloc(sizeof(*ns), GFP_KERNEL);
-+      AA_DEBUG("%s(%p)\n", __func__, ns);
-+      if (!ns)
-+              return NULL;
-+      if (!policy_init(&ns->base, prefix, name))
-+              goto fail_ns;
-+
-+      INIT_LIST_HEAD(&ns->sub_ns);
-+      rwlock_init(&ns->lock);
-+
-+      /* released by free_namespace */
-+      ns->unconfined = aa_alloc_profile("unconfined");
-+      if (!ns->unconfined)
-+              goto fail_unconfined;
-+
-+      ns->unconfined->sid = aa_alloc_sid();
-+      ns->unconfined->flags = PFLAG_UNCONFINED | PFLAG_IX_ON_NAME_ERROR |
-+          PFLAG_IMMUTABLE;
-+
-+      /*
-+       * released by free_namespace, however __remove_namespace breaks
-+       * the cyclic references (ns->unconfined, and unconfined->ns) and
-+       * replaces with refs to parent namespace unconfined
-+       */
-+      ns->unconfined->ns = aa_get_namespace(ns);
-+
-+      return ns;
-+
-+fail_unconfined:
-+      kzfree(ns->base.name);
-+fail_ns:
-+      kzfree(ns);
-+      return NULL;
-+}
-+
-+/**
-+ * free_namespace - free a profile namespace
-+ * @ns: the namespace to free  (MAYBE NULL)
-+ *
-+ * Requires: All references to the namespace must have been put, if the
-+ *           namespace was referenced by a profile confining a task,
-+ */
-+static void free_namespace(struct aa_namespace *ns)
-+{
-+      if (!ns)
-+              return;
-+
-+      policy_destroy(&ns->base);
-+      aa_put_namespace(ns->parent);
-+
-+      if (ns->unconfined && ns->unconfined->ns == ns)
-+              ns->unconfined->ns = NULL;
-+
-+      aa_put_profile(ns->unconfined);
-+      kzfree(ns);
-+}
-+
-+/**
-+ * aa_free_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
-+ * @kr: kref callback for freeing of a namespace  (NOT NULL)
-+ */
-+void aa_free_namespace_kref(struct kref *kref)
-+{
-+      free_namespace(container_of(kref, struct aa_namespace, base.count));
-+}
-+
-+/**
-+ * __aa_find_namespace - find a namespace on a list by @name
-+ * @head: list to search for namespace on  (NOT NULL)
-+ * @name: name of namespace to look for  (NOT NULL)
-+ *
-+ * Returns: unrefcounted namespace
-+ *
-+ * Requires: ns lock be held
-+ */
-+static struct aa_namespace *__aa_find_namespace(struct list_head *head,
-+                                              const char *name)
-+{
-+      return (struct aa_namespace *)__policy_find(head, name);
-+}
-+
-+/**
-+ * aa_find_namespace  -  look up a profile namespace on the namespace list
-+ * @root: namespace to search in  (NOT NULL)
-+ * @name: name of namespace to find  (NOT NULL)
-+ *
-+ * Returns: a refcounted namespace on the list, or NULL if no namespace
-+ *          called @name exists.
-+ *
-+ * refcount released by caller
-+ */
-+struct aa_namespace *aa_find_namespace(struct aa_namespace *root,
-+                                     const char *name)
-+{
-+      struct aa_namespace *ns = NULL;
-+
-+      read_lock(&root->lock);
-+      ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
-+      read_unlock(&root->lock);
-+
-+      return ns;
-+}
-+
-+/**
-+ * aa_prepare_namespace - find an existing or create a new namespace of @name
-+ * @name: the namespace to find or add  (MAYBE NULL)
-+ *
-+ * Returns: refcounted namespace or NULL if failed to create one
-+ */
-+static struct aa_namespace *aa_prepare_namespace(const char *name)
-+{
-+      struct aa_namespace *ns, *root;
-+
-+      root = aa_current_profile()->ns;
-+
-+      write_lock(&root->lock);
-+
-+      /* if name isn't specified the profile is loaded to the current ns */
-+      if (!name) {
-+              /* released by caller */
-+              ns = aa_get_namespace(root);
-+              goto out;
-+      }
-+
-+      /* try and find the specified ns and if it doesn't exist create it */
-+      /* released by caller */
-+      ns = aa_get_namespace(__aa_find_namespace(&root->sub_ns, name));
-+      if (!ns) {
-+              /* namespace not found */
-+              struct aa_namespace *new_ns;
-+              write_unlock(&root->lock);
-+              new_ns = alloc_namespace(root->base.hname, name);
-+              if (!new_ns)
-+                      return NULL;
-+              write_lock(&root->lock);
-+              /* test for race when new_ns was allocated */
-+              ns = __aa_find_namespace(&root->sub_ns, name);
-+              if (!ns) {
-+                      /* add parent ref */
-+                      new_ns->parent = aa_get_namespace(root);
-+
-+                      list_add(&new_ns->base.list, &root->sub_ns);
-+                      /* add list ref */
-+                      ns = aa_get_namespace(new_ns);
-+              } else {
-+                      /* raced so free the new one */
-+                      free_namespace(new_ns);
-+                      /* get reference on namespace */
-+                      aa_get_namespace(ns);
-+              }
-+      }
-+out:
-+      write_unlock(&root->lock);
-+
-+      /* return ref */
-+      return ns;
-+}
-+
-+/**
-+ * __list_add_profile - add a profile to a list
-+ * @list: list to add it to  (NOT NULL)
-+ * @profile: the profile to add  (NOT NULL)
-+ *
-+ * refcount @profile, should be put by __list_remove_profile
-+ *
-+ * Requires: namespace lock be held, or list not be shared
-+ */
-+static void __list_add_profile(struct list_head *list,
-+                             struct aa_profile *profile)
-+{
-+      list_add(&profile->base.list, list);
-+      /* get list reference */
-+      aa_get_profile(profile);
-+}
-+
-+/**
-+ * __list_remove_profile - remove a profile from the list it is on
-+ * @profile: the profile to remove  (NOT NULL)
-+ *
-+ * remove a profile from the list, warning generally removal should
-+ * be done with __replace_profile as most profile removals are
-+ * replacements to the unconfined profile.
-+ *
-+ * put @profile list refcount
-+ *
-+ * Requires: namespace lock be held, or list not have been live
-+ */
-+static void __list_remove_profile(struct aa_profile *profile)
-+{
-+      list_del_init(&profile->base.list);
-+      if (!(profile->flags & PFLAG_NO_LIST_REF))
-+              /* release list reference */
-+              aa_put_profile(profile);
-+}
-+
-+/**
-+ * __replace_profile - replace @old with @new on a list
-+ * @old: profile to be replaced  (NOT NULL)
-+ * @new: profile to replace @old with  (NOT NULL)
-+ *
-+ * Will duplicate and refcount elements that @new inherits from @old
-+ * and will inherit @old children.
-+ *
-+ * refcount @new for list, put @old list refcount
-+ *
-+ * Requires: namespace list lock be held, or list not be shared
-+ */
-+static void __replace_profile(struct aa_profile *old, struct aa_profile *new)
-+{
-+      struct aa_policy *policy;
-+      struct aa_profile *child, *tmp;
-+
-+      if (old->parent)
-+              policy = &old->parent->base;
-+      else
-+              policy = &old->ns->base;
-+
-+      /* released when @new is freed */
-+      new->parent = aa_get_profile(old->parent);
-+      new->ns = aa_get_namespace(old->ns);
-+      new->sid = old->sid;
-+      __list_add_profile(&policy->profiles, new);
-+      /* inherit children */
-+      list_for_each_entry_safe(child, tmp, &old->base.profiles, base.list) {
-+              aa_put_profile(child->parent);
-+              child->parent = aa_get_profile(new);
-+              /* list refcount transferred to @new*/
-+              list_move(&child->base.list, &new->base.profiles);
-+      }
-+
-+      /* released by free_profile */
-+      old->replacedby = aa_get_profile(new);
-+      __list_remove_profile(old);
-+}
-+
-+static void __profile_list_release(struct list_head *head);
-+
-+/**
-+ * __remove_profile - remove old profile, and children
-+ * @profile: profile to be replaced  (NOT NULL)
-+ *
-+ * Requires: namespace list lock be held, or list not be shared
-+ */
-+static void __remove_profile(struct aa_profile *profile)
-+{
-+      /* release any children lists first */
-+      __profile_list_release(&profile->base.profiles);
-+      /* released by free_profile */
-+      profile->replacedby = aa_get_profile(profile->ns->unconfined);
-+      __list_remove_profile(profile);
-+}
-+
-+/**
-+ * __profile_list_release - remove all profiles on the list and put refs
-+ * @head: list of profiles  (NOT NULL)
-+ *
-+ * Requires: namespace lock be held
-+ */
-+static void __profile_list_release(struct list_head *head)
-+{
-+      struct aa_profile *profile, *tmp;
-+      list_for_each_entry_safe(profile, tmp, head, base.list)
-+              __remove_profile(profile);
-+}
-+
-+static void __ns_list_release(struct list_head *head);
-+
-+/**
-+ * destroy_namespace - remove everything contained by @ns
-+ * @ns: namespace to have it contents removed  (NOT NULL)
-+ */
-+static void destroy_namespace(struct aa_namespace *ns)
-+{
-+      if (!ns)
-+              return;
-+
-+      write_lock(&ns->lock);
-+      /* release all profiles in this namespace */
-+      __profile_list_release(&ns->base.profiles);
-+
-+      /* release all sub namespaces */
-+      __ns_list_release(&ns->sub_ns);
-+
-+      write_unlock(&ns->lock);
-+}
-+
-+/**
-+ * __remove_namespace - remove a namespace and all its children
-+ * @ns: namespace to be removed  (NOT NULL)
-+ *
-+ * Requires: ns->parent->lock be held and ns removed from parent.
-+ */
-+static void __remove_namespace(struct aa_namespace *ns)
-+{
-+      struct aa_profile *unconfined = ns->unconfined;
-+
-+      /* remove ns from namespace list */
-+      list_del_init(&ns->base.list);
-+
-+      /*
-+       * break the ns, unconfined profile cyclic reference and forward
-+       * all new unconfined profiles requests to the parent namespace
-+       * This will result in all confined tasks that have a profile
-+       * being removed, inheriting the parent->unconfined profile.
-+       */
-+      if (ns->parent)
-+              ns->unconfined = aa_get_profile(ns->parent->unconfined);
-+
-+      destroy_namespace(ns);
-+
-+      /* release original ns->unconfined ref */
-+      aa_put_profile(unconfined);
-+      /* release ns->base.list ref, from removal above */
-+      aa_put_namespace(ns);
-+}
-+
-+/**
-+ * __ns_list_release - remove all profile namespaces on the list put refs
-+ * @head: list of profile namespaces  (NOT NULL)
-+ *
-+ * Requires: namespace lock be held
-+ */
-+static void __ns_list_release(struct list_head *head)
-+{
-+      struct aa_namespace *ns, *tmp;
-+      list_for_each_entry_safe(ns, tmp, head, base.list)
-+              __remove_namespace(ns);
-+
-+}
-+
-+/**
-+ * aa_alloc_root_ns - allocate the root profile namespace
-+ *
-+ * Returns: %0 on success else error
-+ *
-+ */
-+int __init aa_alloc_root_ns(void)
-+{
-+      /* released by aa_free_root_ns - used as list ref*/
-+      root_ns = alloc_namespace(NULL, "root");
-+      if (!root_ns)
-+              return -ENOMEM;
-+
-+      return 0;
-+}
-+
-+ /**
-+  * aa_free_root_ns - free the root profile namespace
-+  */
-+void __init aa_free_root_ns(void)
-+ {
-+       struct aa_namespace *ns = root_ns;
-+       root_ns = NULL;
-+
-+       destroy_namespace(ns);
-+       aa_put_namespace(ns);
-+}
-+
-+/**
-+ * aa_alloc_profile - allocate, initialize and return a new profile
-+ * @hname: name of the profile  (NOT NULL)
-+ *
-+ * Returns: refcount profile or NULL on failure
-+ */
-+struct aa_profile *aa_alloc_profile(const char *hname)
-+{
-+      struct aa_profile *profile;
-+
-+      /* freed by free_profile - usually through aa_put_profile */
-+      profile = kzalloc(sizeof(*profile), GFP_KERNEL);
-+      if (!profile)
-+              return NULL;
-+
-+      if (!policy_init(&profile->base, NULL, hname)) {
-+              kzfree(profile);
-+              return NULL;
-+      }
-+
-+      /* refcount released by caller */
-+      return profile;
-+}
-+
-+/**
-+ * aa_new_null_profile - create a new null-X learning profile
-+ * @parent: profile that caused this profile to be created (NOT NULL)
-+ * @hat: true if the null- learning profile is a hat
-+ *
-+ * Create a null- complain mode profile used in learning mode.  The name of
-+ * the profile is unique and follows the format of parent//null-sid.
-+ *
-+ * null profiles are added to the profile list but the list does not
-+ * hold a count on them so that they are automatically released when
-+ * not in use.
-+ *
-+ * Returns: new refcounted profile else NULL on failure
-+ */
-+struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat)
-+{
-+      struct aa_profile *profile = NULL;
-+      char *name;
-+      u32 sid = aa_alloc_sid();
-+
-+      /* freed below */
-+      name = kmalloc(strlen(parent->base.hname) + 2 + 7 + 8, GFP_KERNEL);
-+      if (!name)
-+              goto fail;
-+      sprintf(name, "%s//null-%x", parent->base.hname, sid);
-+
-+      profile = aa_alloc_profile(name);
-+      kfree(name);
-+      if (!profile)
-+              goto fail;
-+
-+      profile->sid = sid;
-+      profile->mode = APPARMOR_COMPLAIN;
-+      profile->flags = PFLAG_NULL;
-+      if (hat)
-+              profile->flags |= PFLAG_HAT;
-+
-+      /* released on free_profile */
-+      profile->parent = aa_get_profile(parent);
-+      profile->ns = aa_get_namespace(parent->ns);
-+
-+      write_lock(&profile->ns->lock);
-+      __list_add_profile(&parent->base.profiles, profile);
-+      write_unlock(&profile->ns->lock);
-+
-+      /* refcount released by caller */
-+      return profile;
-+
-+fail:
-+      aa_free_sid(sid);
-+      return NULL;
-+}
-+
-+/**
-+ * free_profile - free a profile
-+ * @profile: the profile to free  (MAYBE NULL)
-+ *
-+ * Free a profile, its hats and null_profile. All references to the profile,
-+ * its hats and null_profile must have been put.
-+ *
-+ * If the profile was referenced from a task context, free_profile() will
-+ * be called from an rcu callback routine, so we must not sleep here.
-+ */
-+static void free_profile(struct aa_profile *profile)
-+{
-+      AA_DEBUG("%s(%p)\n", __func__, profile);
-+
-+      if (!profile)
-+              return;
-+
-+      if (!list_empty(&profile->base.list)) {
-+              AA_ERROR("%s: internal error, "
-+                       "profile '%s' still on ns list\n",
-+                       __func__, profile->base.name);
-+              BUG();
-+      }
-+
-+      /* free children profiles */
-+      policy_destroy(&profile->base);
-+      aa_put_profile(profile->parent);
-+
-+      aa_put_namespace(profile->ns);
-+      kzfree(profile->rename);
-+
-+      aa_free_file_rules(&profile->file);
-+      aa_free_cap_rules(&profile->caps);
-+      aa_free_net_rules(&profile->net);
-+      aa_free_rlimit_rules(&profile->rlimits);
-+
-+      aa_free_sid(profile->sid);
-+      aa_put_dfa(profile->xmatch);
-+
-+      aa_put_profile(profile->replacedby);
-+
-+      kzfree(profile);
-+}
-+
-+/**
-+ * aa_free_profile_kref - free aa_profile by kref (called by aa_put_profile)
-+ * @kr: kref callback for freeing of a profile  (NOT NULL)
-+ */
-+void aa_free_profile_kref(struct kref *kref)
-+{
-+      struct aa_profile *p = container_of(kref, struct aa_profile,
-+                                          base.count);
-+
-+      free_profile(p);
-+}
-+
-+/* TODO: profile accounting - setup in remove */
-+
-+/**
-+ * __find_child - find a profile on @head list with a name matching @name
-+ * @head: list to search  (NOT NULL)
-+ * @name: name of profile (NOT NULL)
-+ *
-+ * Requires: ns lock protecting list be held
-+ *
-+ * Returns: unrefcounted profile ptr, or NULL if not found
-+ */
-+static struct aa_profile *__find_child(struct list_head *head, const char *name)
-+{
-+      return (struct aa_profile *)__policy_find(head, name);
-+}
-+
-+/**
-+ * __strn_find_child - find a profile on @head list using substring of @name
-+ * @head: list to search  (NOT NULL)
-+ * @name: name of profile (NOT NULL)
-+ * @len: length of @name substring to match
-+ *
-+ * Requires: ns lock protecting list be held
-+ *
-+ * Returns: unrefcounted profile ptr, or NULL if not found
-+ */
-+static struct aa_profile *__strn_find_child(struct list_head *head,
-+                                          const char *name, int len)
-+{
-+      return (struct aa_profile *)__policy_strn_find(head, name, len);
-+}
-+
-+/**
-+ * aa_find_child - find a profile by @name in @parent
-+ * @parent: profile to search  (NOT NULL)
-+ * @name: profile name to search for  (NOT NULL)
-+ *
-+ * Returns: a refcounted profile or NULL if not found
-+ */
-+struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name)
-+{
-+      struct aa_profile *profile;
-+
-+      read_lock(&parent->ns->lock);
-+      profile = aa_get_profile(__find_child(&parent->base.profiles, name));
-+      read_unlock(&parent->ns->lock);
-+
-+      /* refcount released by caller */
-+      return profile;
-+}
-+
-+/**
-+ * __lookup_parent - lookup the parent of a profile of name @hname
-+ * @ns: namespace to lookup profile in  (NOT NULL)
-+ * @hname: hierarchical profile name to find parent of  (NOT NULL)
-+ *
-+ * Lookups up the parent of a fully qualified profile name, the profile
-+ * that matches hname does not need to exist, in general this
-+ * is used to load a new profile.
-+ *
-+ * Requires: ns->lock be held
-+ *
-+ * Returns: unrefcounted policy or NULL if not found
-+ */
-+static struct aa_policy *__lookup_parent(struct aa_namespace *ns,
-+                                       const char *hname)
-+{
-+      struct aa_policy *policy;
-+      struct aa_profile *profile = NULL;
-+      char *split;
-+
-+      policy = &ns->base;
-+
-+      for (split = strstr(hname, "//"); split;) {
-+              profile = __strn_find_child(&policy->profiles, hname,
-+                                          split - hname);
-+              if (!profile)
-+                      return NULL;
-+              policy = &profile->base;
-+              hname = split + 2;
-+              split = strstr(hname, "//");
-+      }
-+      if (!profile)
-+              return &ns->base;
-+      return &profile->base;
-+}
-+
-+/**
-+ * __lookup_profile - lookup the profile matching @hname
-+ * @base: base list to start looking up profile name from  (NOT NULL)
-+ * @hname: hierarchical profile name  (NOT NULL)
-+ *
-+ * Requires: ns->lock be held
-+ *
-+ * Returns: unrefcounted profile pointer or NULL if not found
-+ *
-+ * Do a relative name lookup, recursing through profile tree.
-+ */
-+static struct aa_profile *__lookup_profile(struct aa_policy *base,
-+                                         const char *hname)
-+{
-+      struct aa_profile *profile = NULL;
-+      char *split;
-+
-+      for (split = strstr(hname, "//"); split;) {
-+              profile = __strn_find_child(&base->profiles, hname,
-+                                          split - hname);
-+              if (!profile)
-+                      return NULL;
-+
-+              base = &profile->base;
-+              hname = split + 2;
-+              split = strstr(hname, "//");
-+      }
-+
-+      profile = __find_child(&base->profiles, hname);
-+
-+      return profile;
-+}
-+
-+/**
-+ * aa_lookup_profile - find a profile by its full or partial name
-+ * @ns: the namespace to start from (NOT NULL)
-+ * @hname: name to do lookup on.  Does not contain namespace prefix (NOT NULL)
-+ *
-+ * Returns: refcounted profile or NULL if not found
-+ */
-+struct aa_profile *aa_lookup_profile(struct aa_namespace *ns, const char *hname)
-+{
-+      struct aa_profile *profile;
-+
-+      read_lock(&ns->lock);
-+      profile = aa_get_profile(__lookup_profile(&ns->base, hname));
-+      read_unlock(&ns->lock);
-+
-+      /* refcount released by caller */
-+      return profile;
-+}
-+
-+/**
-+ * replacement_allowed - test to see if replacement is allowed
-+ * @profile: profile to test if it can be replaced  (MAYBE NULL)
-+ * @noreplace: true if replacement shouldn't be allowed but addition is okay
-+ * @info: Returns - info about why replacement failed (NOT NULL)
-+ *
-+ * Returns: %0 if replacement allowed else error code
-+ */
-+static int replacement_allowed(struct aa_profile *profile, int noreplace,
-+                             const char **info)
-+{
-+      if (profile) {
-+              if (profile->flags & PFLAG_IMMUTABLE) {
-+                      *info = "cannot replace immutible profile";
-+                      return -EPERM;
-+              } else if (noreplace) {
-+                      *info = "profile already exists";
-+                      return -EEXIST;
-+              }
-+      }
-+      return 0;
-+}
-+
-+/**
-+ * __add_new_profile - simple wrapper around __list_add_profile
-+ * @ns: namespace that profile is being added to  (NOT NULL)
-+ * @policy: the policy container to add the profile to  (NOT NULL)
-+ * @profile: profile to add  (NOT NULL)
-+ *
-+ * add a profile to a list and do other required basic allocations
-+ */
-+static void __add_new_profile(struct aa_namespace *ns, struct aa_policy *policy,
-+                            struct aa_profile *profile)
-+{
-+      if (policy != &ns->base)
-+              /* released on profile replacement or free_profile */
-+              profile->parent = aa_get_profile((struct aa_profile *) policy);
-+      __list_add_profile(&policy->profiles, profile);
-+      /* released on free_profile */
-+      profile->sid = aa_alloc_sid();
-+      profile->ns = aa_get_namespace(ns);
-+}
-+
-+/**
-+ * aa_audit_policy - Do auditing of policy changes
-+ * @op: policy operation being performed
-+ * @gfp: memory allocation flags
-+ * @name: name of profile being manipulated (NOT NULL)
-+ * @info: any extra information to be audited (MAYBE NULL)
-+ * @error: error code
-+ *
-+ * Returns: the error to be returned after audit is done
-+ */
-+static int audit_policy(int op, gfp_t gfp, const char *name, const char *info,
-+                      int error)
-+{
-+      struct common_audit_data sa;
-+      COMMON_AUDIT_DATA_INIT(&sa, NONE);
-+      sa.aad.op = op;
-+      sa.aad.name = name;
-+      sa.aad.info = info;
-+      sa.aad.error = error;
-+
-+      return aa_audit(AUDIT_APPARMOR_STATUS, __aa_current_profile(), gfp,
-+                      &sa, NULL);
-+}
-+
-+/**
-+ * aa_may_manage_policy - can the current task manage policy
-+ * @op: the policy manipulation operation being done
-+ *
-+ * Returns: true if the task is allowed to manipulate policy
-+ */
-+bool aa_may_manage_policy(int op)
-+{
-+      /* check if loading policy is locked out */
-+      if (aa_g_lock_policy) {
-+              audit_policy(op, GFP_KERNEL, NULL, "policy_locked", -EACCES);
-+              return 0;
-+      }
-+
-+      if (!capable(CAP_MAC_ADMIN)) {
-+              audit_policy(op, GFP_KERNEL, NULL, "not policy admin", -EACCES);
-+              return 0;
-+      }
-+
-+      return 1;
-+}
-+
-+/**
-+ * aa_replace_profiles - replace profile(s) on the profile list
-+ * @udata: serialized data stream  (NOT NULL)
-+ * @size: size of the serialized data stream
-+ * @noreplace: true if only doing addition, no replacement allowed
-+ *
-+ * unpack and replace a profile on the profile list and uses of that profile
-+ * by any aa_task_cxt.  If the profile does not exist on the profile list
-+ * it is added.
-+ *
-+ * Returns: size of data consumed else error code on failure.
-+ */
-+ssize_t aa_replace_profiles(void *udata, size_t size, bool noreplace)
-+{
-+      struct aa_policy *policy;
-+      struct aa_profile *old_profile = NULL, *new_profile = NULL;
-+      struct aa_profile *rename_profile = NULL;
-+      struct aa_namespace *ns = NULL;
-+      const char *ns_name, *name = NULL, *info = NULL;
-+      int op = OP_PROF_REPL;
-+      ssize_t error;
-+
-+      /* released below */
-+      new_profile = aa_unpack(udata, size, &ns_name);
-+      if (IS_ERR(new_profile)) {
-+              error = PTR_ERR(new_profile);
-+              new_profile = NULL;
-+              goto fail;
-+      }
-+
-+      /* released below */
-+      ns = aa_prepare_namespace(ns_name);
-+      if (!ns) {
-+              info = "failed to prepare namespace";
-+              error = -ENOMEM;
-+              name = ns_name;
-+              goto fail;
-+      }
-+
-+      name = new_profile->base.hname;
-+
-+      write_lock(&ns->lock);
-+      /* no ref on policy only use inside lock */
-+      policy = __lookup_parent(ns, new_profile->base.hname);
-+
-+      if (!policy) {
-+              info = "parent does not exist";
-+              error = -ENOENT;
-+              goto audit;
-+      }
-+
-+      old_profile = __find_child(&policy->profiles, new_profile->base.name);
-+      /* released below */
-+      aa_get_profile(old_profile);
-+
-+      if (new_profile->rename) {
-+              rename_profile = __lookup_profile(&ns->base,
-+                                                new_profile->rename);
-+              /* released below */
-+              aa_get_profile(rename_profile);
-+
-+              if (!rename_profile) {
-+                      info = "profile to rename does not exist";
-+                      name = new_profile->rename;
-+                      error = -ENOENT;
-+                      goto audit;
-+              }
-+      }
-+
-+      error = replacement_allowed(old_profile, noreplace, &info);
-+      if (error)
-+              goto audit;
-+
-+      error = replacement_allowed(rename_profile, noreplace, &info);
-+      if (error)
-+              goto audit;
-+
-+audit:
-+      if (!old_profile && !rename_profile)
-+              op = OP_PROF_LOAD;
-+
-+      error = audit_policy(op, GFP_ATOMIC, name, info, error);
-+
-+      if (!error) {
-+              if (rename_profile)
-+                      __replace_profile(rename_profile, new_profile);
-+              if (old_profile) {
-+                      /* when there are both rename and old profiles
-+                       * inherit old profiles sid
-+                       */
-+                      if (rename_profile)
-+                              aa_free_sid(new_profile->sid);
-+                      __replace_profile(old_profile, new_profile);
-+              }
-+              if (!(old_profile || rename_profile))
-+                      __add_new_profile(ns, policy, new_profile);
-+      }
-+      write_unlock(&ns->lock);
-+
-+out:
-+      aa_put_namespace(ns);
-+      aa_put_profile(rename_profile);
-+      aa_put_profile(old_profile);
-+      aa_put_profile(new_profile);
-+      if (error)
-+              return error;
-+      return size;
-+
-+fail:
-+      error = audit_policy(op, GFP_KERNEL, name, info, error);
-+      goto out;
-+}
-+
-+/**
-+ * aa_remove_profiles - remove profile(s) from the system
-+ * @fqname: name of the profile or namespace to remove  (NOT NULL)
-+ * @size: size of the name
-+ *
-+ * Remove a profile or sub namespace from the current namespace, so that
-+ * they can not be found anymore and mark them as replaced by unconfined
-+ *
-+ * NOTE: removing confinement does not restore rlimits to preconfinemnet values
-+ *
-+ * Returns: size of data consume else error code if fails
-+ */
-+ssize_t aa_remove_profiles(char *fqname, size_t size)
-+{
-+      struct aa_namespace *root, *ns = NULL;
-+      struct aa_profile *profile = NULL;
-+      const char *name = fqname, *info = NULL;
-+      ssize_t error = 0;
-+
-+      if (*fqname == 0) {
-+              info = "no profile specified";
-+              error = -ENOENT;
-+              goto fail;
-+      }
-+
-+      root = aa_current_profile()->ns;
-+
-+      if (fqname[0] == ':') {
-+              char *ns_name;
-+              name = aa_split_fqname(fqname, &ns_name);
-+              if (ns_name) {
-+                      /* released below */
-+                      ns = aa_find_namespace(root, ns_name);
-+                      if (!ns) {
-+                              info = "namespace does not exist";
-+                              error = -ENOENT;
-+                              goto fail;
-+                      }
-+              }
-+      } else
-+              /* released below */
-+              ns = aa_get_namespace(root);
-+
-+      write_lock(&ns->lock);
-+      if (!name) {
-+              /* remove namespace - can only happen if fqname[0] == ':' */
-+              __remove_namespace(ns);
-+      } else {
-+              /* remove profile */
-+              profile = aa_get_profile(__lookup_profile(&ns->base, name));
-+              if (!profile) {
-+                      error = -ENOENT;
-+                      info = "profile does not exist";
-+                      goto fail_ns_lock;
-+              }
-+              name = profile->base.hname;
-+              __remove_profile(profile);
-+      }
-+      write_unlock(&ns->lock);
-+
-+      /* don't fail removal if audit fails */
-+      (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error);
-+      aa_put_namespace(ns);
-+      aa_put_profile(profile);
-+      return size;
-+
-+fail_ns_lock:
-+      write_unlock(&ns->lock);
-+      aa_put_namespace(ns);
-+
-+fail:
-+      (void) audit_policy(OP_PROF_RM, GFP_KERNEL, name, info, error);
-+      return error;
-+}
-diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
-new file mode 100644
-index 0000000..6b0637b
---- /dev/null
-+++ b/security/apparmor/policy_unpack.c
-@@ -0,0 +1,740 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor functions for unpacking policy loaded from
-+ * userspace.
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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 uses a serialized binary format for loading policy.
-+ * To find policy format documentation look in Documentation/apparmor.txt
-+ * All policy is validated before it is used.
-+ */
-+
-+#include <asm/unaligned.h>
-+#include <linux/ctype.h>
-+#include <linux/errno.h>
-+
-+#include "include/apparmor.h"
-+#include "include/audit.h"
-+#include "include/context.h"
-+#include "include/match.h"
-+#include "include/policy.h"
-+#include "include/policy_unpack.h"
-+#include "include/sid.h"
-+
-+/*
-+ * The AppArmor interface treats data as a type byte followed by the
-+ * actual data.  The interface has the notion of a a named entry
-+ * which has a name (AA_NAME typecode followed by name string) followed by
-+ * the entries typecode and data.  Named types allow for optional
-+ * elements and extensions to be added and tested for without breaking
-+ * backwards compatibility.
-+ */
-+
-+enum aa_code {
-+      AA_U8,
-+      AA_U16,
-+      AA_U32,
-+      AA_U64,
-+      AA_NAME,                /* same as string except it is items name */
-+      AA_STRING,
-+      AA_BLOB,
-+      AA_STRUCT,
-+      AA_STRUCTEND,
-+      AA_LIST,
-+      AA_LISTEND,
-+      AA_ARRAY,
-+      AA_ARRAYEND,
-+};
-+
-+/*
-+ * aa_ext is the read of the buffer containing the serialized profile.  The
-+ * data is copied into a kernel buffer in apparmorfs and then handed off to
-+ * the unpack routines.
-+ */
-+struct aa_ext {
-+      void *start;
-+      void *end;
-+      void *pos;              /* pointer to current position in the buffer */
-+      u32 version;
-+};
-+
-+/* audit callback for unpack fields */
-+static void audit_cb(struct audit_buffer *ab, void *va)
-+{
-+      struct common_audit_data *sa = va;
-+      if (sa->aad.iface.target) {
-+              struct aa_profile *name = sa->aad.iface.target;
-+              audit_log_format(ab, " name=");
-+              audit_log_untrustedstring(ab, name->base.hname);
-+      }
-+      if (sa->aad.iface.pos)
-+              audit_log_format(ab, " offset=%ld", sa->aad.iface.pos);
-+}
-+
-+/**
-+ * audit_iface - do audit message for policy unpacking/load/replace/remove
-+ * @new: profile if it has been allocated (MAYBE NULL)
-+ * @name: name of the profile being manipulated (MAYBE NULL)
-+ * @info: any extra info about the failure (MAYBE NULL)
-+ * @e: buffer position info (NOT NULL)
-+ * @error: error code
-+ *
-+ * Returns: %0 or error
-+ */
-+static int audit_iface(struct aa_profile *new, const char *name,
-+                     const char *info, struct aa_ext *e, int error)
-+{
-+      struct aa_profile *profile = __aa_current_profile();
-+      struct common_audit_data sa;
-+      COMMON_AUDIT_DATA_INIT(&sa, NONE);
-+      sa.aad.iface.pos = e->pos - e->start;
-+      sa.aad.iface.target = new;
-+      sa.aad.name = name;
-+      sa.aad.info = info;
-+      sa.aad.error = error;
-+
-+      return aa_audit(AUDIT_APPARMOR_STATUS, profile, GFP_KERNEL, &sa,
-+                      audit_cb);
-+}
-+
-+/* test if read will be in packed data bounds */
-+static bool inbounds(struct aa_ext *e, size_t size)
-+{
-+      return (size <= e->end - e->pos);
-+}
-+
-+/**
-+ * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
-+ * @e: serialized data read head (NOT NULL)
-+ * @chunk: start address for chunk of data (NOT NULL)
-+ *
-+ * Returns: the size of chunk found with the read head at the end of the chunk.
-+ */
-+static size_t unpack_u16_chunk(struct aa_ext *e, char **chunk)
-+{
-+      size_t size = 0;
-+
-+      if (!inbounds(e, sizeof(u16)))
-+              return 0;
-+      size = le16_to_cpu(get_unaligned((u16 *) e->pos));
-+      e->pos += sizeof(u16);
-+      if (!inbounds(e, size))
-+              return 0;
-+      *chunk = e->pos;
-+      e->pos += size;
-+      return size;
-+}
-+
-+/* unpack control byte */
-+static bool unpack_X(struct aa_ext *e, enum aa_code code)
-+{
-+      if (!inbounds(e, 1))
-+              return 0;
-+      if (*(u8 *) e->pos != code)
-+              return 0;
-+      e->pos++;
-+      return 1;
-+}
-+
-+/**
-+ * unpack_nameX - check is the next element is of type X with a name of @name
-+ * @e: serialized data extent information  (NOT NULL)
-+ * @code: type code
-+ * @name: name to match to the serialized element.  (MAYBE NULL)
-+ *
-+ * check that the next serialized data element is of type X and has a tag
-+ * name @name.  If @name is specified then there must be a matching
-+ * name element in the stream.  If @name is NULL any name element will be
-+ * skipped and only the typecode will be tested.
-+ *
-+ * Returns 1 on success (both type code and name tests match) and the read
-+ * head is advanced past the headers
-+ *
-+ * Returns: 0 if either match fails, the read head does not move
-+ */
-+static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name)
-+{
-+      /*
-+       * May need to reset pos if name or type doesn't match
-+       */
-+      void *pos = e->pos;
-+      /*
-+       * Check for presence of a tagname, and if present name size
-+       * AA_NAME tag value is a u16.
-+       */
-+      if (unpack_X(e, AA_NAME)) {
-+              char *tag = NULL;
-+              size_t size = unpack_u16_chunk(e, &tag);
-+              /* if a name is specified it must match. otherwise skip tag */
-+              if (name && (!size || strcmp(name, tag)))
-+                      goto fail;
-+      } else if (name) {
-+              /* if a name is specified and there is no name tag fail */
-+              goto fail;
-+      }
-+
-+      /* now check if type code matches */
-+      if (unpack_X(e, code))
-+              return 1;
-+
-+fail:
-+      e->pos = pos;
-+      return 0;
-+}
-+
-+static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
-+{
-+      if (unpack_nameX(e, AA_U16, name)) {
-+              if (!inbounds(e, sizeof(u16)))
-+                      return 0;
-+              if (data)
-+                      *data = le16_to_cpu(get_unaligned((u16 *) e->pos));
-+              e->pos += sizeof(u16);
-+              return 1;
-+      }
-+      return 0;
-+}
-+
-+static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
-+{
-+      if (unpack_nameX(e, AA_U32, name)) {
-+              if (!inbounds(e, sizeof(u32)))
-+                      return 0;
-+              if (data)
-+                      *data = le32_to_cpu(get_unaligned((u32 *) e->pos));
-+              e->pos += sizeof(u32);
-+              return 1;
-+      }
-+      return 0;
-+}
-+
-+static bool unpack_u64(struct aa_ext *e, u64 *data, const char *name)
-+{
-+      if (unpack_nameX(e, AA_U64, name)) {
-+              if (!inbounds(e, sizeof(u64)))
-+                      return 0;
-+              if (data)
-+                      *data = le64_to_cpu(get_unaligned((u64 *) e->pos));
-+              e->pos += sizeof(u64);
-+              return 1;
-+      }
-+      return 0;
-+}
-+
-+static size_t unpack_array(struct aa_ext *e, const char *name)
-+{
-+      if (unpack_nameX(e, AA_ARRAY, name)) {
-+              int size;
-+              if (!inbounds(e, sizeof(u16)))
-+                      return 0;
-+              size = (int)le16_to_cpu(get_unaligned((u16 *) e->pos));
-+              e->pos += sizeof(u16);
-+              return size;
-+      }
-+      return 0;
-+}
-+
-+static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name)
-+{
-+      if (unpack_nameX(e, AA_BLOB, name)) {
-+              u32 size;
-+              if (!inbounds(e, sizeof(u32)))
-+                      return 0;
-+              size = le32_to_cpu(get_unaligned((u32 *) e->pos));
-+              e->pos += sizeof(u32);
-+              if (inbounds(e, (size_t) size)) {
-+                      *blob = e->pos;
-+                      e->pos += size;
-+                      return size;
-+              }
-+      }
-+      return 0;
-+}
-+
-+static int unpack_str(struct aa_ext *e, const char **string, const char *name)
-+{
-+      char *src_str;
-+      size_t size = 0;
-+      void *pos = e->pos;
-+      *string = NULL;
-+      if (unpack_nameX(e, AA_STRING, name)) {
-+              size = unpack_u16_chunk(e, &src_str);
-+              if (size) {
-+                      /* strings are null terminated, length is size - 1 */
-+                      if (src_str[size - 1] != 0)
-+                              goto fail;
-+                      *string = src_str;
-+              }
-+      }
-+      return size;
-+
-+fail:
-+      e->pos = pos;
-+      return 0;
-+}
-+
-+static int unpack_strdup(struct aa_ext *e, char **string, const char *name)
-+{
-+      const char *tmp;
-+      void *pos = e->pos;
-+      int res = unpack_str(e, &tmp, name);
-+      *string = NULL;
-+
-+      if (!res)
-+              return 0;
-+
-+      *string = kmemdup(tmp, res, GFP_KERNEL);
-+      if (!*string) {
-+              e->pos = pos;
-+              return 0;
-+      }
-+
-+      return res;
-+}
-+
-+/**
-+ * verify_accept - verify the accept tables of a dfa
-+ * @dfa: dfa to verify accept tables of (NOT NULL)
-+ * @flags: flags governing dfa
-+ *
-+ * Returns: 1 if valid accept tables else 0 if error
-+ */
-+static bool verify_accept(struct aa_dfa *dfa, int flags)
-+{
-+      int i;
-+
-+      /* verify accept permissions */
-+      for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
-+              int mode = ACCEPT_TABLE(dfa)[i];
-+
-+              if (mode & ~DFA_VALID_PERM_MASK)
-+                      return 0;
-+
-+              if (ACCEPT_TABLE2(dfa)[i] & ~DFA_VALID_PERM2_MASK)
-+                      return 0;
-+      }
-+      return 1;
-+}
-+
-+/**
-+ * unpack_dfa - unpack a file rule dfa
-+ * @e: serialized data extent information (NOT NULL)
-+ *
-+ * returns dfa or ERR_PTR or NULL if no dfa
-+ */
-+static struct aa_dfa *unpack_dfa(struct aa_ext *e)
-+{
-+      char *blob = NULL;
-+      size_t size;
-+      struct aa_dfa *dfa = NULL;
-+
-+      size = unpack_blob(e, &blob, "aadfa");
-+      if (size) {
-+              /*
-+               * The dfa is aligned with in the blob to 8 bytes
-+               * from the beginning of the stream.
-+               */
-+              size_t sz = blob - (char *)e->start;
-+              size_t pad = ALIGN(sz, 8) - sz;
-+              int flags = TO_ACCEPT1_FLAG(YYTD_DATA32) |
-+                      TO_ACCEPT2_FLAG(YYTD_DATA32);
-+
-+
-+              if (aa_g_paranoid_load)
-+                      flags |= DFA_FLAG_VERIFY_STATES;
-+
-+              dfa = aa_dfa_unpack(blob + pad, size - pad, flags);
-+
-+              if (IS_ERR(dfa))
-+                      return dfa;
-+
-+              if (!verify_accept(dfa, flags))
-+                      goto fail;
-+      }
-+
-+      return dfa;
-+
-+fail:
-+      aa_put_dfa(dfa);
-+      return ERR_PTR(-EPROTO);
-+}
-+
-+/**
-+ * unpack_trans_table - unpack a profile transition table
-+ * @e: serialized data extent information  (NOT NULL)
-+ * @profile: profile to add the accept table to (NOT NULL)
-+ *
-+ * Returns: 1 if table succesfully unpacked
-+ */
-+static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
-+{
-+      void *pos = e->pos;
-+
-+      /* exec table is optional */
-+      if (unpack_nameX(e, AA_STRUCT, "xtable")) {
-+              int i, size;
-+
-+              size = unpack_array(e, NULL);
-+              /* currently 4 exec bits and entries 0-3 are reserved iupcx */
-+              if (size > 16 - 4)
-+                      goto fail;
-+              profile->file.trans.table = kzalloc(sizeof(char *) * size,
-+                                                  GFP_KERNEL);
-+              if (!profile->file.trans.table)
-+                      goto fail;
-+
-+              profile->file.trans.size = size;
-+              for (i = 0; i < size; i++) {
-+                      char *str;
-+                      int c, j, size = unpack_strdup(e, &str, NULL);
-+                      /* unpack_strdup verifies that the last character is
-+                       * null termination byte.
-+                       */
-+                      if (!size)
-+                              goto fail;
-+                      profile->file.trans.table[i] = str;
-+                      /* verify that name doesn't start with space */
-+                      if (isspace(*str))
-+                              goto fail;
-+
-+                      /* count internal #  of internal \0 */
-+                      for (c = j = 0; j < size - 2; j++) {
-+                              if (!str[j])
-+                                      c++;
-+                      }
-+                      if (*str == ':') {
-+                              /* beginning with : requires an embedded \0,
-+                               * verify that exactly 1 internal \0 exists
-+                               * trailing \0 already verified by unpack_strdup
-+                               */
-+                              if (c != 1)
-+                                      goto fail;
-+                              /* first character after : must be valid */
-+                              if (!str[1])
-+                                      goto fail;
-+                      } else if (c)
-+                              /* fail - all other cases with embedded \0 */
-+                              goto fail;
-+              }
-+              if (!unpack_nameX(e, AA_ARRAYEND, NULL))
-+                      goto fail;
-+              if (!unpack_nameX(e, AA_STRUCTEND, NULL))
-+                      goto fail;
-+      }
-+      return 1;
-+
-+fail:
-+      aa_free_domain_entries(&profile->file.trans);
-+      e->pos = pos;
-+      return 0;
-+}
-+
-+static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
-+{
-+      void *pos = e->pos;
-+
-+      /* rlimits are optional */
-+      if (unpack_nameX(e, AA_STRUCT, "rlimits")) {
-+              int i, size;
-+              u32 tmp = 0;
-+              if (!unpack_u32(e, &tmp, NULL))
-+                      goto fail;
-+              profile->rlimits.mask = tmp;
-+
-+              size = unpack_array(e, NULL);
-+              if (size > RLIM_NLIMITS)
-+                      goto fail;
-+              for (i = 0; i < size; i++) {
-+                      u64 tmp = 0;
-+                      int a = aa_map_resource(i);
-+                      if (!unpack_u64(e, &tmp, NULL))
-+                              goto fail;
-+                      profile->rlimits.limits[a].rlim_max = tmp;
-+              }
-+              if (!unpack_nameX(e, AA_ARRAYEND, NULL))
-+                      goto fail;
-+              if (!unpack_nameX(e, AA_STRUCTEND, NULL))
-+                      goto fail;
-+      }
-+      return 1;
-+
-+fail:
-+      e->pos = pos;
-+      return 0;
-+}
-+
-+/**
-+ * unpack_profile - unpack a serialized profile
-+ * @e: serialized data extent information (NOT NULL)
-+ *
-+ * NOTE: unpack profile sets audit struct if there is a failure
-+ */
-+static struct aa_profile *unpack_profile(struct aa_ext *e)
-+{
-+      struct aa_profile *profile = NULL;
-+      const char *name = NULL;
-+      size_t size = 0;
-+      int i, error = -EPROTO;
-+      kernel_cap_t tmpcap;
-+      u32 tmp;
-+
-+      /* check that we have the right struct being passed */
-+      if (!unpack_nameX(e, AA_STRUCT, "profile"))
-+              goto fail;
-+      if (!unpack_str(e, &name, NULL))
-+              goto fail;
-+
-+      profile = aa_alloc_profile(name);
-+      if (!profile)
-+              return ERR_PTR(-ENOMEM);
-+
-+      /* profile renaming is optional */
-+      (void) unpack_str(e, &profile->rename, "rename");
-+
-+      /* xmatch is optional and may be NULL */
-+      profile->xmatch = unpack_dfa(e);
-+      if (IS_ERR(profile->xmatch)) {
-+              error = PTR_ERR(profile->xmatch);
-+              profile->xmatch = NULL;
-+              goto fail;
-+      }
-+      /* xmatch_len is not optional if xmatch is set */
-+      if (profile->xmatch) {
-+              if (!unpack_u32(e, &tmp, NULL))
-+                      goto fail;
-+              profile->xmatch_len = tmp;
-+      }
-+
-+      /* per profile debug flags (complain, audit) */
-+      if (!unpack_nameX(e, AA_STRUCT, "flags"))
-+              goto fail;
-+      if (!unpack_u32(e, &tmp, NULL))
-+              goto fail;
-+      if (tmp)
-+              profile->flags |= PFLAG_HAT;
-+      if (!unpack_u32(e, &tmp, NULL))
-+              goto fail;
-+      if (tmp)
-+              profile->mode = APPARMOR_COMPLAIN;
-+      if (!unpack_u32(e, &tmp, NULL))
-+              goto fail;
-+      if (tmp)
-+              profile->audit = AUDIT_ALL;
-+
-+      if (!unpack_nameX(e, AA_STRUCTEND, NULL))
-+              goto fail;
-+
-+      /* path_flags is optional */
-+      if (unpack_u32(e, &profile->path_flags, "path_flags"))
-+              profile->path_flags |= profile->flags & PFLAG_MEDIATE_DELETED;
-+      else
-+              /* set a default value if path_flags field is not present */
-+              profile->path_flags = PFLAG_MEDIATE_DELETED;
-+
-+      if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL))
-+              goto fail;
-+      if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL))
-+              goto fail;
-+      if (!unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL))
-+              goto fail;
-+      if (!unpack_u32(e, &tmpcap.cap[0], NULL))
-+              goto fail;
-+
-+      if (unpack_nameX(e, AA_STRUCT, "caps64")) {
-+              /* optional upper half of 64 bit caps */
-+              if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL))
-+                      goto fail;
-+              if (!unpack_u32(e, &(profile->caps.audit.cap[1]), NULL))
-+                      goto fail;
-+              if (!unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL))
-+                      goto fail;
-+              if (!unpack_u32(e, &(tmpcap.cap[1]), NULL))
-+                      goto fail;
-+              if (!unpack_nameX(e, AA_STRUCTEND, NULL))
-+                      goto fail;
-+      }
-+
-+      if (unpack_nameX(e, AA_STRUCT, "capsx")) {
-+              /* optional extended caps mediation mask */
-+              if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL))
-+                      goto fail;
-+              if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL))
-+                      goto fail;
-+      }
-+
-+      if (!unpack_rlimits(e, profile))
-+              goto fail;
-+
-+      size = unpack_array(e, "net_allowed_af");
-+      if (size) {
-+              if (size > AF_MAX)
-+                      goto fail;
-+
-+              for (i = 0; i < size; i++) {
-+                      if (!unpack_u16(e, &profile->net.allow[i], NULL))
-+                              goto fail;
-+                      if (!unpack_u16(e, &profile->net.audit[i], NULL))
-+                              goto fail;
-+                      if (!unpack_u16(e, &profile->net.quiet[i], NULL))
-+                              goto fail;
-+              }
-+              if (!unpack_nameX(e, AA_ARRAYEND, NULL))
-+                      goto fail;
-+              /*
-+               * allow unix domain and netlink sockets they are handled
-+               * by IPC
-+               */
-+      }
-+      profile->net.allow[AF_UNIX] = 0xffff;
-+      profile->net.allow[AF_NETLINK] = 0xffff;
-+
-+      /* get file rules */
-+      profile->file.dfa = unpack_dfa(e);
-+      if (IS_ERR(profile->file.dfa)) {
-+              error = PTR_ERR(profile->file.dfa);
-+              profile->file.dfa = NULL;
-+              goto fail;
-+      }
-+
-+      if (!unpack_u32(e, &profile->file.start, "dfa_start"))
-+              /* default start state */
-+              profile->file.start = DFA_START;
-+
-+      if (!unpack_trans_table(e, profile))
-+              goto fail;
-+
-+      if (!unpack_nameX(e, AA_STRUCTEND, NULL))
-+              goto fail;
-+
-+      return profile;
-+
-+fail:
-+      if (profile)
-+              name = NULL;
-+      else if (!name)
-+              name = "unknown";
-+      audit_iface(profile, name, "failed to unpack profile", e, error);
-+      aa_put_profile(profile);
-+
-+      return ERR_PTR(error);
-+}
-+
-+/**
-+ * verify_head - unpack serialized stream header
-+ * @e: serialized data read head (NOT NULL)
-+ * @ns: Returns - namespace if one is specified else NULL (NOT NULL)
-+ *
-+ * Returns: error or 0 if header is good
-+ */
-+static int verify_header(struct aa_ext *e, const char **ns)
-+{
-+      int error = -EPROTONOSUPPORT;
-+      /* get the interface version */
-+      if (!unpack_u32(e, &e->version, "version")) {
-+              audit_iface(NULL, NULL, "invalid profile format", e, error);
-+              return error;
-+      }
-+
-+      /* check that the interface version is currently supported */
-+      if (e->version != 5) {
-+              audit_iface(NULL, NULL, "unsupported interface version", e,
-+                          error);
-+              return error;
-+      }
-+
-+      /* read the namespace if present */
-+      if (!unpack_str(e, ns, "namespace"))
-+              *ns = NULL;
-+
-+      return 0;
-+}
-+
-+static bool verify_xindex(int xindex, int table_size)
-+{
-+      int index, xtype;
-+      xtype = xindex & AA_X_TYPE_MASK;
-+      index = xindex & AA_X_INDEX_MASK;
-+      if (xtype == AA_X_TABLE && index > table_size)
-+              return 0;
-+      return 1;
-+}
-+
-+/* verify dfa xindexes are in range of transition tables */
-+static bool verify_dfa_xindex(struct aa_dfa *dfa, int table_size)
-+{
-+      int i;
-+      for (i = 0; i < dfa->tables[YYTD_ID_ACCEPT]->td_lolen; i++) {
-+              if (!verify_xindex(dfa_user_xindex(dfa, i), table_size))
-+                      return 0;
-+              if (!verify_xindex(dfa_other_xindex(dfa, i), table_size))
-+                      return 0;
-+      }
-+      return 1;
-+}
-+
-+/**
-+ * verify_profile - Do post unpack analysis to verify profile consistency
-+ * @profile: profile to verify (NOT NULL)
-+ *
-+ * Returns: 0 if passes verification else error
-+ */
-+static int verify_profile(struct aa_profile *profile)
-+{
-+      if (aa_g_paranoid_load) {
-+              if (profile->file.dfa &&
-+                  !verify_dfa_xindex(profile->file.dfa,
-+                                     profile->file.trans.size)) {
-+                      audit_iface(profile, NULL, "Invalid named transition",
-+                                  NULL, -EPROTO);
-+                      return -EPROTO;
-+              }
-+      }
-+
-+      return 0;
-+}
-+
-+/**
-+ * aa_unpack - unpack packed binary profile data loaded from user space
-+ * @udata: user data copied to kmem  (NOT NULL)
-+ * @size: the size of the user data
-+ * @ns: Returns namespace profile is in if specified else NULL (NOT NULL)
-+ *
-+ * Unpack user data and return refcounted allocated profile or ERR_PTR
-+ *
-+ * Returns: profile else error pointer if fails to unpack
-+ */
-+struct aa_profile *aa_unpack(void *udata, size_t size, const char **ns)
-+{
-+      struct aa_profile *profile = NULL;
-+      int error;
-+      struct aa_ext e = {
-+              .start = udata,
-+              .end = udata + size,
-+              .pos = udata,
-+      };
-+
-+      error = verify_header(&e, ns);
-+      if (error)
-+              return ERR_PTR(error);
-+
-+      profile = unpack_profile(&e);
-+      if (IS_ERR(profile))
-+              return profile;
-+
-+      error = verify_profile(profile);
-+      if (error) {
-+              aa_put_profile(profile);
-+              profile = ERR_PTR(error);
-+      }
-+
-+      /* return refcount */
-+      return profile;
-+}
-diff --git a/security/apparmor/policy_unpack.c.rej b/security/apparmor/policy_unpack.c.rej
-new file mode 100644
-index 0000000..5bddfd6
---- /dev/null
-+++ b/security/apparmor/policy_unpack.c.rej
-@@ -0,0 +1,11 @@
-+diff a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c  (rejected hunks)
-+@@ -473,7 +473,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e)
-+ {
-+      struct aa_profile *profile = NULL;
-+      const char *name = NULL, *info = NULL;
-+-     int error = -EPROTO;
-++     size_t size = 0;
-++     int i, error = -EPROTO;
-+      kernel_cap_t tmpcap;
-+      u32 tmp;
-+      u64 tmp64;
-diff --git a/security/apparmor/procattr.c b/security/apparmor/procattr.c
-new file mode 100644
-index 0000000..04a2cf8
---- /dev/null
-+++ b/security/apparmor/procattr.c
-@@ -0,0 +1,170 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor /proc/<pid>/attr/ interface functions
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#include "include/apparmor.h"
-+#include "include/context.h"
-+#include "include/policy.h"
-+#include "include/domain.h"
-+
-+
-+/**
-+ * aa_getprocattr - Return the profile information for @profile
-+ * @profile: the profile to print profile info about  (NOT NULL)
-+ * @string: Returns - string containing the profile info (NOT NULL)
-+ *
-+ * Returns: length of @string on success else error on failure
-+ *
-+ * Requires: profile != NULL
-+ *
-+ * Creates a string containing the namespace_name://profile_name for
-+ * @profile.
-+ *
-+ * Returns: size of string placed in @string else error code on failure
-+ */
-+int aa_getprocattr(struct aa_profile *profile, char **string)
-+{
-+      char *str;
-+      int len = 0, mode_len = 0, ns_len = 0, name_len;
-+      const char *mode_str = profile_mode_names[profile->mode];
-+      const char *ns_name = NULL;
-+      struct aa_namespace *ns = profile->ns;
-+      struct aa_namespace *current_ns = __aa_current_profile()->ns;
-+      char *s;
-+
-+      if (!aa_ns_visible(current_ns, ns))
-+              return -EACCES;
-+
-+      ns_name = aa_ns_name(current_ns, ns);
-+      ns_len = strlen(ns_name);
-+
-+      /* if the visible ns_name is > 0 increase size for : :// seperator */
-+      if (ns_len)
-+              ns_len += 4;
-+
-+      /* unconfined profiles don't have a mode string appended */
-+      if (!unconfined(profile))
-+              mode_len = strlen(mode_str) + 3;        /* + 3 for _() */
-+
-+      name_len = strlen(profile->base.hname);
-+      len = mode_len + ns_len + name_len + 1;     /* + 1 for \n */
-+      s = str = kmalloc(len + 1, GFP_KERNEL);     /* + 1 \0 */
-+      if (!str)
-+              return -ENOMEM;
-+
-+      if (ns_len) {
-+              /* skip over prefix current_ns->base.hname and separating // */
-+              sprintf(s, ":%s://", ns_name);
-+              s += ns_len;
-+      }
-+      if (unconfined(profile))
-+              /* mode string not being appended */
-+              sprintf(s, "%s\n", profile->base.hname);
-+      else
-+              sprintf(s, "%s (%s)\n", profile->base.hname, mode_str);
-+      *string = str;
-+
-+      /* NOTE: len does not include \0 of string, not saved as part of file */
-+      return len;
-+}
-+
-+/**
-+ * split_token_from_name - separate a string of form  <token>^<name>
-+ * @op: operation being checked
-+ * @args: string to parse  (NOT NULL)
-+ * @token: stores returned parsed token value  (NOT NULL)
-+ *
-+ * Returns: start position of name after token else NULL on failure
-+ */
-+static char *split_token_from_name(int op, char *args, u64 * token)
-+{
-+      char *name;
-+
-+      *token = simple_strtoull(args, &name, 16);
-+      if ((name == args) || *name != '^') {
-+              AA_ERROR("%s: Invalid input '%s'", op_table[op], args);
-+              return ERR_PTR(-EINVAL);
-+      }
-+
-+      name++;                 /* skip ^ */
-+      if (!*name)
-+              name = NULL;
-+      return name;
-+}
-+
-+/**
-+ * aa_setprocattr_chagnehat - handle procattr interface to change_hat
-+ * @args: args received from writing to /proc/<pid>/attr/current (NOT NULL)
-+ * @size: size of the args
-+ * @test: true if this is a test of change_hat permissions
-+ *
-+ * Returns: %0 or error code if change_hat fails
-+ */
-+int aa_setprocattr_changehat(char *args, size_t size, int test)
-+{
-+      char *hat;
-+      u64 token;
-+      const char *hats[16];           /* current hard limit on # of names */
-+      int count = 0;
-+
-+      hat = split_token_from_name(OP_CHANGE_HAT, args, &token);
-+      if (IS_ERR(hat))
-+              return PTR_ERR(hat);
-+
-+      if (!hat && !token) {
-+              AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
-+              return -EINVAL;
-+      }
-+
-+      if (hat) {
-+              /* set up hat name vector, args guaranteed null terminated
-+               * at args[size] by setprocattr.
-+               *
-+               * If there are multiple hat names in the buffer each is
-+               * separated by a \0.  Ie. userspace writes them pre tokenized
-+               */
-+              char *end = args + size;
-+              for (count = 0; (hat < end) && count < 16; ++count) {
-+                      char *next = hat + strlen(hat) + 1;
-+                      hats[count] = hat;
-+                      hat = next;
-+              }
-+      }
-+
-+      AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
-+               __func__, token, hat ? hat : NULL);
-+
-+      return aa_change_hat(hats, count, token, test);
-+}
-+
-+/**
-+ * aa_setprocattr_changeprofile - handle procattr interface to changeprofile
-+ * @fqname: args received from writting to /proc/<pid>/attr/current (NOT NULL)
-+ * @onexec: true if change_profile should be delayed until exec
-+ * @test: true if this is a test of change_profile permissions
-+ *
-+ * Returns: %0 or error code if change_profile fails
-+ */
-+int aa_setprocattr_changeprofile(char *fqname, bool onexec, int test)
-+{
-+      char *name, *ns_name;
-+
-+      name = aa_split_fqname(fqname, &ns_name);
-+      return aa_change_profile(ns_name, name, onexec, test);
-+}
-+
-+int aa_setprocattr_permipc(char *fqname)
-+{
-+      /* TODO: add ipc permission querying */
-+      return -ENOTSUPP;
-+}
-diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
-new file mode 100644
-index 0000000..4a368f1
---- /dev/null
-+++ b/security/apparmor/resource.c
-@@ -0,0 +1,134 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor resource mediation and attachment
-+ *
-+ * Copyright (C) 1998-2008 Novell/SUSE
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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.
-+ */
-+
-+#include <linux/audit.h>
-+
-+#include "include/audit.h"
-+#include "include/resource.h"
-+#include "include/policy.h"
-+
-+/*
-+ * Table of rlimit names: we generate it from resource.h.
-+ */
-+#include "rlim_names.h"
-+
-+/* audit callback for resource specific fields */
-+static void audit_cb(struct audit_buffer *ab, void *va)
-+{
-+      struct common_audit_data *sa = va;
-+
-+      audit_log_format(ab, " rlimit=%s value=%lu",
-+                       rlim_names[sa->aad.rlim.rlim], sa->aad.rlim.max);
-+}
-+
-+/**
-+ * audit_resource - audit setting resource limit
-+ * @profile: profile being enforced  (NOT NULL)
-+ * @resoure: rlimit being auditing
-+ * @value: value being set
-+ * @error: error value
-+ *
-+ * Returns: 0 or sa->error else other error code on failure
-+ */
-+static int audit_resource(struct aa_profile *profile, unsigned int resource,
-+                        unsigned long value, int error)
-+{
-+      struct common_audit_data sa;
-+
-+      COMMON_AUDIT_DATA_INIT(&sa, NONE);
-+      sa.aad.op = OP_SETRLIMIT,
-+      sa.aad.rlim.rlim = resource;
-+      sa.aad.rlim.max = value;
-+      sa.aad.error = error;
-+      return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa,
-+                      audit_cb);
-+}
-+
-+/**
-+ * aa_map_resouce - map compiled policy resource to internal #
-+ * @resource: flattened policy resource number
-+ *
-+ * Returns: resource # for the current architecture.
-+ *
-+ * rlimit resource can vary based on architecture, map the compiled policy
-+ * resource # to the internal representation for the architecture.
-+ */
-+int aa_map_resource(int resource)
-+{
-+      return rlim_map[resource];
-+}
-+
-+/**
-+ * aa_task_setrlimit - test permission to set an rlimit
-+ * @profile - profile confining the task  (NOT NULL)
-+ * @resource - the resource being set
-+ * @new_rlim - the new resource limit  (NOT NULL)
-+ *
-+ * Control raising the processes hard limit.
-+ *
-+ * Returns: 0 or error code if setting resource failed
-+ */
-+int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
-+                    struct rlimit *new_rlim)
-+{
-+      int error = 0;
-+
-+      if (profile->rlimits.mask & (1 << resource) &&
-+          new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)
-+
-+              error = audit_resource(profile, resource, new_rlim->rlim_max,
-+                      -EACCES);
-+
-+      return error;
-+}
-+
-+/**
-+ * __aa_transition_rlimits - apply new profile rlimits
-+ * @old: old profile on task  (NOT NULL)
-+ * @new: new profile with rlimits to apply  (NOT NULL)
-+ */
-+void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new)
-+{
-+      unsigned int mask = 0;
-+      struct rlimit *rlim, *initrlim;
-+      int i;
-+
-+      /* for any rlimits the profile controlled reset the soft limit
-+       * to the less of the tasks hard limit and the init tasks soft limit
-+       */
-+      if (old->rlimits.mask) {
-+              for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
-+                      if (old->rlimits.mask & mask) {
-+                              rlim = current->signal->rlim + i;
-+                              initrlim = init_task.signal->rlim + i;
-+                              rlim->rlim_cur = min(rlim->rlim_max,
-+                                                   initrlim->rlim_cur);
-+                      }
-+              }
-+      }
-+
-+      /* set any new hard limits as dictated by the new profile */
-+      if (!new->rlimits.mask)
-+              return;
-+      for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
-+              if (!(new->rlimits.mask & mask))
-+                      continue;
-+
-+              rlim = current->signal->rlim + i;
-+              rlim->rlim_max = min(rlim->rlim_max,
-+                                   new->rlimits.limits[i].rlim_max);
-+              /* soft limit should not exceed hard limit */
-+              rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max);
-+      }
-+}
-diff --git a/security/apparmor/sid.c b/security/apparmor/sid.c
-new file mode 100644
-index 0000000..f0b34f7
---- /dev/null
-+++ b/security/apparmor/sid.c
-@@ -0,0 +1,55 @@
-+/*
-+ * AppArmor security module
-+ *
-+ * This file contains AppArmor security identifier (sid) manipulation fns
-+ *
-+ * Copyright 2009-2010 Canonical Ltd.
-+ *
-+ * 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 allocates a unique sid for every profile loaded.  If a profile
-+ * is replaced it receives the sid of the profile it is replacing.
-+ *
-+ * The sid value of 0 is invalid.
-+ */
-+
-+#include <linux/spinlock.h>
-+#include <linux/errno.h>
-+#include <linux/err.h>
-+
-+#include "include/sid.h"
-+
-+/* global counter from which sids are allocated */
-+static u32 global_sid;
-+static DEFINE_SPINLOCK(sid_lock);
-+
-+/* TODO FIXME: add sid to profile mapping, and sid recycling */
-+
-+/**
-+ * aa_alloc_sid - allocate a new sid for a profile
-+ */
-+u32 aa_alloc_sid(void)
-+{
-+      u32 sid;
-+
-+      /*
-+       * TODO FIXME: sid recycling - part of profile mapping table
-+       */
-+      spin_lock(&sid_lock);
-+      sid = (++global_sid);
-+      spin_unlock(&sid_lock);
-+      return sid;
-+}
-+
-+/**
-+ * aa_free_sid - free a sid
-+ * @sid: sid to free
-+ */
-+void aa_free_sid(u32 sid)
-+{
-+      ;                       /* NOP ATM */
-+}
--- 
-1.7.1
+
 
This page took 0.499671 seconds and 4 git commands to generate.