]> git.pld-linux.org Git - packages/kernel.git/blobdiff - kernel-apparmor.patch
- 4.9.8
[packages/kernel.git] / kernel-apparmor.patch
index 049b85887818f177745d497b2588108fef263663..9c0b815a6b50e354f3a18976f57741e2e08f7d3e 100644 (file)
-diff -uprN e/fs/afs/dir.c f/fs/afs/dir.c
---- e/fs/afs/dir.c     2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/afs/dir.c     2008-05-28 20:29:29.410207000 +0000
-@@ -45,6 +45,7 @@ const struct file_operations afs_dir_fil
-       .release        = afs_release,
-       .readdir        = afs_readdir,
-       .lock           = afs_lock,
-+      .fsetattr       = afs_fsetattr,
- };
- const struct inode_operations afs_dir_inode_operations = {
-diff -uprN e/fs/afs/file.c f/fs/afs/file.c
---- e/fs/afs/file.c    2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/afs/file.c    2008-05-28 20:29:29.410207000 +0000
-@@ -36,6 +36,7 @@ const struct file_operations afs_file_op
-       .fsync          = afs_fsync,
-       .lock           = afs_lock,
-       .flock          = afs_flock,
-+      .fsetattr       = afs_fsetattr,
- };
- const struct inode_operations afs_file_inode_operations = {
-diff -uprN e/fs/afs/inode.c f/fs/afs/inode.c
---- e/fs/afs/inode.c   2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/afs/inode.c   2008-05-28 20:29:29.410207000 +0000
-@@ -358,7 +358,8 @@ void afs_clear_inode(struct inode *inode
- /*
-  * set the attributes of an inode
-  */
--int afs_setattr(struct dentry *dentry, struct iattr *attr)
-+static int afs_do_setattr(struct dentry *dentry, struct iattr *attr,
-+                 struct file *file)
- {
-       struct afs_vnode *vnode = AFS_FS_I(dentry->d_inode);
-       struct key *key;
-@@ -380,8 +381,8 @@ int afs_setattr(struct dentry *dentry, s
-               afs_writeback_all(vnode);
-       }
--      if (attr->ia_valid & ATTR_FILE) {
--              key = attr->ia_file->private_data;
-+      if (file) {
-+              key = file->private_data;
-       } else {
-               key = afs_request_key(vnode->volume->cell);
-               if (IS_ERR(key)) {
-@@ -391,10 +392,20 @@ int afs_setattr(struct dentry *dentry, s
-       }
-       ret = afs_vnode_setattr(vnode, key, attr);
--      if (!(attr->ia_valid & ATTR_FILE))
-+      if (!file)
-               key_put(key);
- error:
-       _leave(" = %d", ret);
-       return ret;
- }
-+
-+int afs_setattr(struct dentry *dentry, struct iattr *attr)
-+{
-+      return afs_do_setattr(dentry, attr, NULL);
-+}
-+
-+int afs_fsetattr(struct file *file, struct iattr *attr)
-+{
-+      return afs_do_setattr(file->f_path.dentry, attr, file);
-+}
-diff -uprN e/fs/afs/internal.h f/fs/afs/internal.h
---- e/fs/afs/internal.h        2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/afs/internal.h        2008-05-28 20:29:29.410207000 +0000
-@@ -550,6 +550,7 @@ extern void afs_zap_data(struct afs_vnod
- extern int afs_validate(struct afs_vnode *, struct key *);
- extern int afs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
- extern int afs_setattr(struct dentry *, struct iattr *);
-+extern int afs_fsetattr(struct file *, struct iattr *);
- extern void afs_clear_inode(struct inode *);
- /*
-diff -uprN e/fs/attr.c f/fs/attr.c
---- e/fs/attr.c        2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/attr.c        2008-05-28 20:29:29.410207000 +0000
-@@ -100,7 +100,8 @@ int inode_setattr(struct inode * inode, 
- }
- EXPORT_SYMBOL(inode_setattr);
--int notify_change(struct dentry * dentry, struct iattr * attr)
-+int fnotify_change(struct dentry *dentry, struct vfsmount *mnt,
-+                 struct iattr *attr, struct file *file)
- {
-       struct inode *inode = dentry->d_inode;
-       mode_t mode = inode->i_mode;
-@@ -158,13 +159,17 @@ int notify_change(struct dentry * dentry
-               down_write(&dentry->d_inode->i_alloc_sem);
-       if (inode->i_op && inode->i_op->setattr) {
--              error = security_inode_setattr(dentry, attr);
--              if (!error)
--                      error = inode->i_op->setattr(dentry, attr);
-+              error = security_inode_setattr(dentry, mnt, attr);
-+              if (!error) {
-+                      if (file && file->f_op && file->f_op->fsetattr)
-+                              error = file->f_op->fsetattr(file, attr);
-+                      else
-+                              error = inode->i_op->setattr(dentry, attr);
-+              }
-       } else {
-               error = inode_change_ok(inode, attr);
-               if (!error)
--                      error = security_inode_setattr(dentry, attr);
-+                      error = security_inode_setattr(dentry, mnt, attr);
-               if (!error) {
-                       if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
-                           (ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid))
-@@ -182,5 +187,12 @@ int notify_change(struct dentry * dentry
-       return error;
- }
-+EXPORT_SYMBOL_GPL(fnotify_change);
-+
-+int notify_change(struct dentry *dentry, struct vfsmount *mnt,
-+                struct iattr *attr)
-+{
-+      return fnotify_change(dentry, mnt, attr, NULL);
-+}
- EXPORT_SYMBOL(notify_change);
-diff -uprN e/fs/dcache.c f/fs/dcache.c
---- e/fs/dcache.c      2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/dcache.c      2008-05-28 20:29:29.410207000 +0000
-@@ -1747,86 +1747,118 @@ shouldnt_be_hashed:
- }
- /**
-- * d_path - return the path of a dentry
-+ * __d_path - return the path of a dentry
-  * @dentry: dentry to report
-  * @vfsmnt: vfsmnt to which the dentry belongs
-  * @root: root dentry
-  * @rootmnt: vfsmnt to which the root dentry belongs
-  * @buffer: buffer to return value in
-  * @buflen: buffer length
-+ * @fail_deleted: what to return for deleted files
-+ * @disconnect: don't return a path starting with / when disconnected
-  *
-- * Convert a dentry into an ASCII path name. If the entry has been deleted
-+ * Convert a dentry into an ASCII path name. If the entry has been deleted,
-+ * then if @fail_deleted is true, ERR_PTR(-ENOENT) is returned. Otherwise,
-  * the string " (deleted)" is appended. Note that this is ambiguous.
-  *
-  * Returns the buffer or an error code if the path was too long.
-+ * If @dentry is not connected to @root, the path returned will be relative
-+ * (i.e., it will not start with a slash).
-  *
-- * "buflen" should be positive. Caller holds the dcache_lock.
-+ * Returns the buffer or an error code.
-  */
--static char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
--                     struct path *root, char *buffer, int buflen)
-+char *__d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
-+             struct path *root, char *buffer, int buflen,
-+             int fail_deleted, int disconnect)
- {
--      char * end = buffer+buflen;
--      char * retval;
--      int namelen;
-+      int namelen, vfsmount_locked = 0;
-+      const unsigned char *name;
-+
-+      if (buflen < 2)
-+              return ERR_PTR(-ENAMETOOLONG);
-+      buffer += --buflen;
-+      *buffer = '\0';
--      *--end = '\0';
--      buflen--;
-+      spin_lock(&dcache_lock);
-       if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
--              buflen -= 10;
--              end -= 10;
--              if (buflen < 0)
-+              if (fail_deleted) {
-+                      buffer = ERR_PTR(-ENOENT);
-+                      goto out;
-+              }
-+              if (buflen < 10)
-                       goto Elong;
--              memcpy(end, " (deleted)", 10);
-+              buflen -= 10;
-+              buffer -= 10;
-+              memcpy(buffer, " (deleted)", 10);
-       }
--      if (buflen < 1)
--              goto Elong;
--      /* Get '/' right */
--      retval = end-1;
--      *retval = '/';
--
--      for (;;) {
-+      while (dentry != root->dentry || vfsmnt != root->mnt) {
-               struct dentry * parent;
--              if (dentry == root->dentry && vfsmnt == root->mnt)
--                      break;
-               if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
--                      /* Global root? */
--                      spin_lock(&vfsmount_lock);
--                      if (vfsmnt->mnt_parent == vfsmnt) {
--                              spin_unlock(&vfsmount_lock);
--                              goto global_root;
-+                      if (!vfsmount_locked) {
-+                              spin_lock(&vfsmount_lock);
-+                              vfsmount_locked = 1;
-                       }
-+                      if (vfsmnt->mnt_parent == vfsmnt)
-+                              goto global_root;
-                       dentry = vfsmnt->mnt_mountpoint;
-                       vfsmnt = vfsmnt->mnt_parent;
--                      spin_unlock(&vfsmount_lock);
-                       continue;
-               }
-               parent = dentry->d_parent;
-               prefetch(parent);
-               namelen = dentry->d_name.len;
--              buflen -= namelen + 1;
--              if (buflen < 0)
-+              if (buflen < namelen + 1)
-                       goto Elong;
--              end -= namelen;
--              memcpy(end, dentry->d_name.name, namelen);
--              *--end = '/';
--              retval = end;
-+              buflen -= namelen + 1;
-+              buffer -= namelen;
-+              memcpy(buffer, dentry->d_name.name, namelen);
-+              *--buffer = '/';
-               dentry = parent;
-       }
-+      /* Get '/' right. */
-+      if (*buffer != '/')
-+              *--buffer = '/';
--      return retval;
-+out:
-+      if (vfsmount_locked)
-+              spin_unlock(&vfsmount_lock);
-+      spin_unlock(&dcache_lock);
-+      return buffer;
- global_root:
-+      /*
-+       * We went past the (vfsmount, dentry) we were looking for and have
-+       * either hit a root dentry, a lazily unmounted dentry, an
-+       * unconnected dentry, or the file is on a pseudo filesystem.
-+       */
-       namelen = dentry->d_name.len;
--      buflen -= namelen;
--      if (buflen < 0)
-+      name = dentry->d_name.name;
-+
-+      /*
-+       * If this is a root dentry, then overwrite the slash.  This
-+       * will also DTRT with pseudo filesystems which have root
-+       * dentries named "foo:".
-+       */
-+      if (IS_ROOT(dentry)) {
-+              buffer++;
-+              buflen++;
-+      }
-+      if (disconnect && *name == '/') {
-+          /* Make sure we won't return a pathname starting with '/' */
-+              name++;
-+              namelen--;
-+      }
-+      if (buflen < namelen)
-               goto Elong;
--      retval -= namelen-1;    /* hit the slash */
--      memcpy(retval, dentry->d_name.name, namelen);
--      return retval;
-+      buffer -= namelen;
-+      memcpy(buffer, dentry->d_name.name, namelen);
-+      goto out;
-+
- Elong:
--      return ERR_PTR(-ENAMETOOLONG);
-+      buffer = ERR_PTR(-ENAMETOOLONG);
-+      goto out;
- }
- /**
-@@ -1861,9 +1893,7 @@ char *d_path(struct path *path, char *bu
-       root = current->fs->root;
-       path_get(&current->fs->root);
-       read_unlock(&current->fs->lock);
--      spin_lock(&dcache_lock);
--      res = __d_path(path->dentry, path->mnt, &root, buf, buflen);
--      spin_unlock(&dcache_lock);
-+      res = __d_path(path->dentry, path->mnt, &root, buf, buflen, 0, 0);
-       path_put(&root);
-       return res;
- }
-@@ -1909,9 +1939,9 @@ char *dynamic_dname(struct dentry *dentr
-  */
- asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
- {
--      int error;
-+      int error, len;
-       struct path pwd, root;
--      char *page = (char *) __get_free_page(GFP_USER);
-+      char *page = (char *) __get_free_page(GFP_USER), *cwd;
-       if (!page)
-               return -ENOMEM;
-@@ -1923,29 +1953,18 @@ asmlinkage long sys_getcwd(char __user *
-       path_get(&current->fs->root);
-       read_unlock(&current->fs->lock);
--      error = -ENOENT;
--      /* Has the current directory has been unlinked? */
--      spin_lock(&dcache_lock);
--      if (pwd.dentry->d_parent == pwd.dentry || !d_unhashed(pwd.dentry)) {
--              unsigned long len;
--              char * cwd;
--
--              cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE);
--              spin_unlock(&dcache_lock);
--
--              error = PTR_ERR(cwd);
--              if (IS_ERR(cwd))
--                      goto out;
--
--              error = -ERANGE;
--              len = PAGE_SIZE + page - cwd;
--              if (len <= size) {
--                      error = len;
--                      if (copy_to_user(buf, cwd, len))
--                              error = -EFAULT;
--              }
--      } else
--              spin_unlock(&dcache_lock);
-+      cwd = __d_path(pwd.dentry, pwd.mnt, &root, page, PAGE_SIZE, 1, 0);
-+      error = PTR_ERR(cwd);
-+      if (IS_ERR(cwd))
-+              goto out;
-+
-+      error = -ERANGE;
-+      len = PAGE_SIZE + page - cwd;
-+      if (len <= size) {
-+              error = len;
-+              if (copy_to_user(buf, cwd, len))
-+                      error = -EFAULT;
-+      }
- out:
-       path_put(&pwd);
-diff -uprN e/fs/ecryptfs/inode.c f/fs/ecryptfs/inode.c
---- e/fs/ecryptfs/inode.c      2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/ecryptfs/inode.c      2008-05-28 20:29:28.910241000 +0000
-@@ -388,19 +388,24 @@ static int ecryptfs_link(struct dentry *
-                        struct dentry *new_dentry)
- {
-       struct dentry *lower_old_dentry;
-+      struct vfsmount *lower_old_mnt;
-       struct dentry *lower_new_dentry;
-+      struct vfsmount *lower_new_mnt;
-       struct dentry *lower_dir_dentry;
-       u64 file_size_save;
-       int rc;
-       file_size_save = i_size_read(old_dentry->d_inode);
-       lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
-+      lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
-       lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
-+      lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
-       dget(lower_old_dentry);
-       dget(lower_new_dentry);
-       lower_dir_dentry = lock_parent(lower_new_dentry);
--      rc = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode,
--                    lower_new_dentry, NULL);
-+      rc = vfs_link(lower_old_dentry, lower_old_mnt,
-+                    lower_dir_dentry->d_inode, lower_new_dentry,
-+                    lower_new_mnt, NULL);
-       if (rc || !lower_new_dentry->d_inode)
-               goto out_lock;
-       rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb, 0);
-@@ -425,10 +430,11 @@ static int ecryptfs_unlink(struct inode 
-       int rc = 0;
-       struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
-+      struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
-       struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir);
-       struct dentry *lower_dir_dentry;
-       lower_dir_dentry = lock_parent(lower_dentry);
--      rc = vfs_unlink(lower_dir_inode, lower_dentry, NULL);
-+      rc = vfs_unlink(lower_dir_inode, lower_dentry, NULL, lower_mnt);
-       if (rc) {
-               printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc);
-               goto out_unlock;
-@@ -448,6 +454,7 @@ static int ecryptfs_symlink(struct inode
- {
-       int rc;
-       struct dentry *lower_dentry;
-+      struct vfsmount *lower_mnt;
-       struct dentry *lower_dir_dentry;
-       umode_t mode;
-       char *encoded_symname;
-@@ -456,6 +463,7 @@ static int ecryptfs_symlink(struct inode
-       lower_dentry = ecryptfs_dentry_to_lower(dentry);
-       dget(lower_dentry);
-+      lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
-       lower_dir_dentry = lock_parent(lower_dentry);
-       mode = S_IALLUGO;
-       encoded_symlen = ecryptfs_encode_filename(crypt_stat, symname,
-@@ -465,7 +473,7 @@ static int ecryptfs_symlink(struct inode
-               rc = encoded_symlen;
-               goto out_lock;
-       }
--      rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry,
-+      rc = vfs_symlink(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
-                        encoded_symname, mode, NULL);
-       kfree(encoded_symname);
-       if (rc || !lower_dentry->d_inode)
-@@ -487,11 +495,14 @@ static int ecryptfs_mkdir(struct inode *
- {
-       int rc;
-       struct dentry *lower_dentry;
-+      struct vfsmount *lower_mnt;
-       struct dentry *lower_dir_dentry;
-       lower_dentry = ecryptfs_dentry_to_lower(dentry);
-+      lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
-       lower_dir_dentry = lock_parent(lower_dentry);
--      rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, mode, NULL);
-+      rc = vfs_mkdir(lower_dir_dentry->d_inode, lower_dentry, lower_mnt,
-+                     mode, NULL);
-       if (rc || !lower_dentry->d_inode)
-               goto out;
-       rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
-@@ -510,14 +521,16 @@ out:
- static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
- {
-       struct dentry *lower_dentry;
-+      struct vfsmount *lower_mnt;
-       struct dentry *lower_dir_dentry;
-       int rc;
-       lower_dentry = ecryptfs_dentry_to_lower(dentry);
-+      lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
-       dget(dentry);
-       lower_dir_dentry = lock_parent(lower_dentry);
-       dget(lower_dentry);
--      rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry, NULL);
-+      rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry, NULL, lower_mnt);
-       dput(lower_dentry);
-       if (!rc)
-               d_delete(lower_dentry);
-@@ -535,11 +548,14 @@ ecryptfs_mknod(struct inode *dir, struct
- {
-       int rc;
-       struct dentry *lower_dentry;
-+      struct vfsmount *lower_mnt;
-       struct dentry *lower_dir_dentry;
-       lower_dentry = ecryptfs_dentry_to_lower(dentry);
-+      lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
-       lower_dir_dentry = lock_parent(lower_dentry);
--      rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, mode, dev, NULL);
-+      rc = vfs_mknod(lower_dir_dentry->d_inode, lower_dentry, lower_mnt, mode,
-+                     dev, NULL);
-       if (rc || !lower_dentry->d_inode)
-               goto out;
-       rc = ecryptfs_interpose(lower_dentry, dentry, dir->i_sb, 0);
-@@ -560,19 +576,24 @@ ecryptfs_rename(struct inode *old_dir, s
- {
-       int rc;
-       struct dentry *lower_old_dentry;
-+      struct vfsmount *lower_old_mnt;
-       struct dentry *lower_new_dentry;
-+      struct vfsmount *lower_new_mnt;
-       struct dentry *lower_old_dir_dentry;
-       struct dentry *lower_new_dir_dentry;
-       lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
-+      lower_old_mnt = ecryptfs_dentry_to_lower_mnt(old_dentry);
-       lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
-+      lower_new_mnt = ecryptfs_dentry_to_lower_mnt(new_dentry);
-       dget(lower_old_dentry);
-       dget(lower_new_dentry);
-       lower_old_dir_dentry = dget_parent(lower_old_dentry);
-       lower_new_dir_dentry = dget_parent(lower_new_dentry);
-       lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
-       rc = vfs_rename(lower_old_dir_dentry->d_inode, lower_old_dentry,
--                      lower_new_dir_dentry->d_inode, lower_new_dentry);
-+                      lower_old_mnt, lower_new_dir_dentry->d_inode,
-+                      lower_new_dentry, lower_new_mnt);
-       if (rc)
-               goto out_lock;
-       fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode, NULL);
-@@ -848,6 +869,7 @@ static int ecryptfs_setattr(struct dentr
- {
-       int rc = 0;
-       struct dentry *lower_dentry;
-+      struct vfsmount *lower_mnt;
-       struct inode *inode;
-       struct inode *lower_inode;
-       struct ecryptfs_crypt_stat *crypt_stat;
-@@ -858,6 +880,7 @@ static int ecryptfs_setattr(struct dentr
-       inode = dentry->d_inode;
-       lower_inode = ecryptfs_inode_to_lower(inode);
-       lower_dentry = ecryptfs_dentry_to_lower(dentry);
-+      lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
-       mutex_lock(&crypt_stat->cs_mutex);
-       if (S_ISDIR(dentry->d_inode->i_mode))
-               crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
-@@ -927,7 +927,7 @@
-               ia->ia_valid &= ~ATTR_MODE;
-       mutex_lock(&lower_dentry->d_inode->i_mutex);
--      rc = notify_change(lower_dentry, ia);
-+      rc = notify_change(lower_dentry, lower_mnt, ia);
-       mutex_unlock(&lower_dentry->d_inode->i_mutex);
- out:
-       fsstack_copy_attr_all(inode, lower_inode);
-diff -uprN e/fs/exec.c f/fs/exec.c
---- e/fs/exec.c        2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/exec.c        2008-05-28 20:29:28.910241000 +0000
-@@ -1777,7 +1777,8 @@ int do_coredump(long signr, int exit_cod
-               goto close_fail;
-       if (!file->f_op->write)
-               goto close_fail;
--      if (!ispipe && do_truncate(file->f_path.dentry, 0, 0, file) != 0)
-+      if (!ispipe &&
-+          do_truncate(file->f_path.dentry, file->f_path.mnt, 0, 0, file) != 0)
-               goto close_fail;
-       retval = binfmt->core_dump(signr, regs, file, core_limit);
-diff -uprN e/fs/fat/file.c f/fs/fat/file.c
---- e/fs/fat/file.c    2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/fat/file.c    2008-05-28 20:29:28.910241000 +0000
-@@ -92,7 +92,7 @@ int fat_generic_ioctl(struct inode *inod
-               }
-               /* This MUST be done before doing anything irreversible... */
--              err = notify_change(filp->f_path.dentry, &ia);
-+              err = notify_change(filp->f_path.dentry, filp->f_path.mnt, &ia);
-               if (err)
-                       goto up;
-diff -uprN e/fs/fuse/dir.c f/fs/fuse/dir.c
---- e/fs/fuse/dir.c    2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/fuse/dir.c    2008-05-28 20:29:29.410207000 +0000
-@@ -1064,21 +1064,22 @@ static int fuse_dir_fsync(struct file *f
-       return file ? fuse_fsync_common(file, de, datasync, 1) : 0;
- }
--static bool update_mtime(unsigned ivalid)
-+static bool update_mtime(unsigned ivalid, bool have_file)
- {
-       /* Always update if mtime is explicitly set  */
-       if (ivalid & ATTR_MTIME_SET)
-               return true;
-       /* If it's an open(O_TRUNC) or an ftruncate(), don't update */
--      if ((ivalid & ATTR_SIZE) && (ivalid & (ATTR_OPEN | ATTR_FILE)))
-+      if ((ivalid & ATTR_SIZE) && ((ivalid & ATTR_OPEN) || have_file))
-               return false;
-       /* In all other cases update */
-       return true;
- }
--static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg)
-+static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg,
-+                         bool have_file)
- {
-       unsigned ivalid = iattr->ia_valid;
-@@ -1097,7 +1098,7 @@ static void iattr_to_fattr(struct iattr 
-               if (!(ivalid & ATTR_ATIME_SET))
-                       arg->valid |= FATTR_ATIME_NOW;
-       }
--      if ((ivalid & ATTR_MTIME) && update_mtime(ivalid)) {
-+      if ((ivalid & ATTR_MTIME) && update_mtime(ivalid, have_file)) {
-               arg->valid |= FATTR_MTIME;
-               arg->mtime = iattr->ia_mtime.tv_sec;
-               arg->mtimensec = iattr->ia_mtime.tv_nsec;
-@@ -1114,8 +1115,8 @@ static void iattr_to_fattr(struct iattr 
-  * vmtruncate() doesn't allow for this case, so do the rlimit checking
-  * and the actual truncation by hand.
-  */
--static int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
--                         struct file *file)
-+int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
-+                  struct file *file)
- {
-       struct inode *inode = entry->d_inode;
-       struct fuse_conn *fc = get_fuse_conn(inode);
-@@ -1153,7 +1154,7 @@ static int fuse_do_setattr(struct dentry
-       memset(&inarg, 0, sizeof(inarg));
-       memset(&outarg, 0, sizeof(outarg));
--      iattr_to_fattr(attr, &inarg);
-+      iattr_to_fattr(attr, &inarg, file != NULL);
-       if (file) {
-               struct fuse_file *ff = file->private_data;
-               inarg.valid |= FATTR_FH;
-@@ -1195,10 +1196,7 @@ static int fuse_do_setattr(struct dentry
- static int fuse_setattr(struct dentry *entry, struct iattr *attr)
- {
--      if (attr->ia_valid & ATTR_FILE)
--              return fuse_do_setattr(entry, attr, attr->ia_file);
--      else
--              return fuse_do_setattr(entry, attr, NULL);
-+      return fuse_do_setattr(entry, attr, NULL);
- }
- static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry,
-diff -uprN e/fs/fuse/file.c f/fs/fuse/file.c
---- e/fs/fuse/file.c   2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/fuse/file.c   2008-05-28 20:29:29.410207000 +0000
-@@ -909,6 +909,11 @@ static sector_t fuse_bmap(struct address
-       return err ? 0 : outarg.block;
- }
-+static int fuse_fsetattr(struct file *file, struct iattr *attr)
-+{
-+      return fuse_do_setattr(file->f_path.dentry, attr, file);
-+}
-+
- static const struct file_operations fuse_file_operations = {
-       .llseek         = generic_file_llseek,
-       .read           = do_sync_read,
-@@ -922,6 +927,7 @@ static const struct file_operations fuse
-       .fsync          = fuse_fsync,
-       .lock           = fuse_file_lock,
-       .flock          = fuse_file_flock,
-+      .fsetattr       = fuse_fsetattr,
-       .splice_read    = generic_file_splice_read,
- };
-@@ -935,6 +941,7 @@ static const struct file_operations fuse
-       .fsync          = fuse_fsync,
-       .lock           = fuse_file_lock,
-       .flock          = fuse_file_flock,
-+      .fsetattr       = fuse_fsetattr,
-       /* no mmap and splice_read */
+commit 09aa4788d6052c6dc423d939319334ebb5d00847
+Author: John Johansen <john.johansen@canonical.com>
+Date:   Mon Oct 4 15:03:36 2010 -0700
+
+    UBUNTU: SAUCE: AppArmor: basic networking rules
+    
+    Base support for network mediation.
+    
+    Signed-off-by: John Johansen <john.johansen@canonical.com>
+
+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
+ 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
+-clean-files := capability_names.h rlim_names.h
++clean-files := capability_names.h rlim_names.h net_names.h
+ # 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/' >> $@
++# 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",
++#
++# 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 $< >>$@ -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)
++      $(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 -uprN e/fs/fuse/fuse_i.h f/fs/fuse/fuse_i.h
---- e/fs/fuse/fuse_i.h 2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/fuse/fuse_i.h 2008-05-28 20:29:29.410207000 +0000
-@@ -509,6 +509,10 @@ void fuse_change_attributes(struct inode
-  */
- int fuse_dev_init(void);
-+
-+int fuse_do_setattr(struct dentry *entry, struct iattr *attr,
-+                  struct file *file);
-+
- /**
-  * Cleanup the client device
-  */
-diff -uprN e/fs/hpfs/namei.c f/fs/hpfs/namei.c
---- e/fs/hpfs/namei.c  2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/hpfs/namei.c  2008-05-28 20:29:28.910241000 +0000
-@@ -426,7 +426,7 @@ again:
-                       /*printk("HPFS: truncating file before delete.\n");*/
-                       newattrs.ia_size = 0;
-                       newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
--                      err = notify_change(dentry, &newattrs);
-+                      err = notify_change(dentry, NULL, &newattrs);
-                       put_write_access(inode);
-                       if (!err)
-                               goto again;
-diff -uprN e/fs/namei.c f/fs/namei.c
---- e/fs/namei.c       2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/namei.c       2008-05-28 20:29:29.410207000 +0000
-@@ -313,7 +313,12 @@ int vfs_permission(struct nameidata *nd,
-  */
- int file_permission(struct file *file, int mask)
- {
--      return permission(file->f_path.dentry->d_inode, mask, NULL);
-+      struct nameidata nd;
-+
-+      nd.path = file->f_path;
-+      nd.flags = LOOKUP_ACCESS;
-+
-+      return permission(nd.path.dentry->d_inode, mask, &nd);
- }
- /*
-@@ -1150,24 +1155,21 @@ static int do_path_lookup(int dfd, const
-               path_get(&fs->pwd);
-               read_unlock(&fs->lock);
-       } else {
--              struct dentry *dentry;
--
-               file = fget_light(dfd, &fput_needed);
-               retval = -EBADF;
-               if (!file)
-                       goto out_fail;
--              dentry = file->f_path.dentry;
-+              nd->path = file->f_path;
-               retval = -ENOTDIR;
--              if (!S_ISDIR(dentry->d_inode->i_mode))
-+              if (!S_ISDIR(nd->path.dentry->d_inode->i_mode))
-                       goto fput_fail;
-               retval = file_permission(file, MAY_EXEC);
-               if (retval)
-                       goto fput_fail;
--              nd->path = file->f_path;
-               path_get(&file->f_path);
-               fput_light(file, fput_needed);
-@@ -1511,6 +1513,8 @@ static inline int may_create(struct inod
-               return -EEXIST;
-       if (IS_DEADDIR(dir))
-               return -ENOENT;
-+      if (nd)
-+              nd->flags |= LOOKUP_CONTINUE;
-       return permission(dir,MAY_WRITE | MAY_EXEC, nd);
- }
-@@ -1586,7 +1590,7 @@ int vfs_create(struct inode *dir, struct
-               return -EACCES; /* shouldn't it be ENOSYS? */
-       mode &= S_IALLUGO;
-       mode |= S_IFREG;
--      error = security_inode_create(dir, dentry, mode);
-+      error = security_inode_create(dir, dentry, nd ? nd->path.mnt : NULL, mode);
-       if (error)
-               return error;
-       DQUOT_INIT(dir);
-@@ -1663,7 +1667,7 @@ int may_open(struct nameidata *nd, int a
-               if (!error) {
-                       DQUOT_INIT(inode);
--                      error = do_truncate(dentry, 0,
-+                      error = do_truncate(dentry, nd->path.mnt, 0,
-                                           ATTR_MTIME|ATTR_CTIME|ATTR_OPEN,
-                                           NULL);
-               }
-@@ -1921,8 +1925,8 @@ fail:
- }
- EXPORT_SYMBOL_GPL(lookup_create);
--int vfs_mknod(struct inode *dir, struct dentry *dentry,
--      int mode, dev_t dev, struct nameidata *nd)
-+int vfs_mknod(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
-+      int mode, dev_t dev, struct nameidata *nd)
- {
-       int error = may_create(dir, dentry, NULL);
-@@ -1934,7 +1939,7 @@ int vfs_mknod(struct inode *dir, struct 
-       if (!dir->i_op || !dir->i_op->mknod)
-               return -EPERM;
--      error = security_inode_mknod(dir, dentry, mode, dev);
-+      error = security_inode_mknod(dir, dentry, mnt, mode, dev);
-       if (error)
-               return error;
-@@ -1973,12 +1978,12 @@ asmlinkage long sys_mknodat(int dfd, con
-                       error = vfs_create(nd.path.dentry->d_inode,dentry,mode,&nd);
-                       break;
-               case S_IFCHR: case S_IFBLK:
--                      error = vfs_mknod(nd.path.dentry->d_inode, dentry, mode,
--                                      new_decode_dev(dev), &nd);
-+                      error = vfs_mknod(nd.path.dentry->d_inode, dentry,
-+                                        nd.path.mnt, mode, new_decode_dev(dev), &nd);
-                       break;
-               case S_IFIFO: case S_IFSOCK:
--                      error = vfs_mknod(nd.path.dentry->d_inode, dentry, mode,
--                                      0, &nd);
-+                      error = vfs_mknod(nd.path.dentry->d_inode, dentry,
-+                                        nd.path.mnt, mode, 0, &nd);
-                       break;
-               case S_IFDIR:
-                       error = -EPERM;
-@@ -2000,8 +2006,8 @@ asmlinkage long sys_mknod(const char __u
-       return sys_mknodat(AT_FDCWD, filename, mode, dev);
- }
--int vfs_mkdir(struct inode *dir, struct dentry *dentry,
--      int mode, struct nameidata *nd)
-+int vfs_mkdir(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
-+            int mode, struct nameidata *nd)
- {
-       int error = may_create(dir, dentry, nd);
-@@ -2011,7 +2018,7 @@ int vfs_mkdir(struct inode *dir, struct 
-               return -EPERM;
-       mode &= (S_IRWXUGO|S_ISVTX);
--      error = security_inode_mkdir(dir, dentry, mode);
-+      error = security_inode_mkdir(dir, dentry, mnt, mode);
-       if (error)
-               return error;
-@@ -2044,7 +2051,7 @@ asmlinkage long sys_mkdirat(int dfd, con
-       if (!IS_POSIXACL(nd.path.dentry->d_inode))
-               mode &= ~current->fs->umask;
--      error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode, &nd);
-+      error = vfs_mkdir(nd.path.dentry->d_inode, dentry, nd.path.mnt, mode, &nd);
-       dput(dentry);
- out_unlock:
-       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-@@ -2087,8 +2094,8 @@ void dentry_unhash(struct dentry *dentry
-       spin_unlock(&dcache_lock);
- }
--int vfs_rmdir(struct inode *dir, struct dentry *dentry,
--      struct nameidata *nd)
-+int vfs_rmdir(struct inode *dir, struct dentry *dentry,
-+      struct nameidata *nd, struct vfsmount *mnt)
- {
-       int error = may_delete(dir, dentry, 1);
-@@ -2097,6 +2104,10 @@ int vfs_rmdir(struct inode *dir, struct 
-       if (!dir->i_op || !dir->i_op->rmdir)
-               return -EPERM;
-+      error = security_inode_rmdir(dir, dentry, mnt);
-+      if (error)
-+              return error;
-+
-       DQUOT_INIT(dir);
-       mutex_lock(&dentry->d_inode->i_mutex);
-@@ -2104,12 +2115,9 @@ int vfs_rmdir(struct inode *dir, struct 
-       if (d_mountpoint(dentry))
-               error = -EBUSY;
-       else {
--              error = security_inode_rmdir(dir, dentry);
--              if (!error) {
--                      error = dir->i_op->rmdir(dir, dentry);
--                      if (!error)
--                              dentry->d_inode->i_flags |= S_DEAD;
--              }
-+              error = dir->i_op->rmdir(dir, dentry);
-+              if (!error)
-+                      dentry->d_inode->i_flags |= S_DEAD;
-       }
-       mutex_unlock(&dentry->d_inode->i_mutex);
-       if (!error) {
-@@ -2151,7 +2159,7 @@ static long do_rmdir(int dfd, const char
-       error = PTR_ERR(dentry);
-       if (IS_ERR(dentry))
-               goto exit2;
--      error = vfs_rmdir(nd.path.dentry->d_inode, dentry, &nd);
-+      error = vfs_rmdir(nd.path.dentry->d_inode, dentry, &nd, nd.path.mnt);
-       dput(dentry);
- exit2:
-       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-@@ -2167,8 +2175,8 @@ asmlinkage long sys_rmdir(const char __u
-       return do_rmdir(AT_FDCWD, pathname);
- }
--int vfs_unlink(struct inode *dir, struct dentry *dentry,
--      struct nameidata *nd)
-+int vfs_unlink(struct inode *dir, struct dentry *dentry, 
-+      struct nameidata *nd, struct vfsmount *mnt)
- {
-       int error = may_delete(dir, dentry, 0, nd);
-@@ -2183,7 +2191,7 @@ int vfs_unlink(struct inode *dir, struct
-       if (d_mountpoint(dentry))
-               error = -EBUSY;
-       else {
--              error = security_inode_unlink(dir, dentry);
-+              error = security_inode_unlink(dir, dentry, mnt);
-               if (!error)
-                       error = dir->i_op->unlink(dir, dentry);
-       }
-@@ -2232,7 +2240,7 @@ static long do_unlinkat(int dfd, const c
-               inode = dentry->d_inode;
-               if (inode)
-                       atomic_inc(&inode->i_count);
--              error = vfs_unlink(nd.path.dentry->d_inode, dentry, &nd);
-+              error = vfs_unlink(nd.path.dentry->d_inode, dentry, &nd, nd.path.mnt);
-       exit2:
-               dput(dentry);
-       }
-@@ -2267,7 +2275,7 @@ asmlinkage long sys_unlink(const char __
-       return do_unlinkat(AT_FDCWD, pathname);
- }
--int vfs_symlink(struct inode *dir, struct dentry *dentry,
-+int vfs_symlink(struct inode *dir, struct dentry *dentry, struct vfsmount *mnt,
-       const char *oldname, int mode, struct nameidata *nd)
-       const char *oldname, int mode, struct nameidata *nd)
- {
-@@ -2277,7 +2286,7 @@ int vfs_symlink(struct inode *dir, struc
-       if (!dir->i_op || !dir->i_op->symlink)
-               return -EPERM;
--      error = security_inode_symlink(dir, dentry, oldname);
-+      error = security_inode_symlink(dir, dentry, mnt, oldname);
-       if (error)
-               return error;
-@@ -2313,8 +2322,8 @@ asmlinkage long sys_symlinkat(const char
-       if (IS_ERR(dentry))
-               goto out_unlock;
--      error = vfs_symlink(nd.path.dentry->d_inode, dentry, from,
--              S_IALLUGO, &nd);
-+      error = vfs_symlink(nd.path.dentry->d_inode, dentry, nd.path.mnt, from,
-+                          S_IALLUGO, &nd);
-       dput(dentry);
- out_unlock:
-       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-@@ -2330,8 +2340,8 @@ asmlinkage long sys_symlink(const char _
-       return sys_symlinkat(oldname, AT_FDCWD, newname);
- }
--int vfs_link(struct dentry *old_dentry, struct inode *dir,
--      struct dentry *new_dentry, struct nameidata *nd)
-+int vfs_link(struct dentry *old_dentry, struct vfsmount *old_mnt, struct inode *dir,
-+      struct dentry *new_dentry, struct vfsmount *new_mnt, struct nameidata *nd)
- {
-       struct inode *inode = old_dentry->d_inode;
-       int error;
-@@ -2355,7 +2365,8 @@ int vfs_link(struct dentry *old_dentry, 
-       if (S_ISDIR(old_dentry->d_inode->i_mode))
-               return -EPERM;
--      error = security_inode_link(old_dentry, dir, new_dentry);
-+      error = security_inode_link(old_dentry, old_mnt, dir, new_dentry,
-+                                  new_mnt);
-       if (error)
-               return error;
-@@ -2408,8 +2419,8 @@ asmlinkage long sys_linkat(int olddfd, c
-               goto out_unlock_dput;
-       }
--      error = vfs_link(old_nd.path.dentry, nd.path.dentry->d_inode,
--              new_dentry, &nd);
-+      error = vfs_link(old_nd.path.dentry, old_nd.path.mnt, nd.path.dentry->d_inode,
-+                       new_dentry, nd.path.mnt, &nd);
- out_unlock_dput:
-       dput(new_dentry);
- out_unlock:
-@@ -2460,7 +2472,8 @@ asmlinkage long sys_link(const char __us
-  *       locking].
-  */
- static int vfs_rename_dir(struct inode *old_dir, struct dentry *old_dentry,
--                        struct inode *new_dir, struct dentry *new_dentry)
-+                        struct vfsmount *old_mnt, struct inode *new_dir,
-+                        struct dentry *new_dentry, struct vfsmount *new_mnt)
- {
-       int error = 0;
-       struct inode *target;
-@@ -2475,7 +2488,8 @@ static int vfs_rename_dir(struct inode *
-                       return error;
-       }
--      error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
-+      error = security_inode_rename(old_dir, old_dentry, old_mnt,
-+                                    new_dir, new_dentry, new_mnt);
-       if (error)
-               return error;
-@@ -2503,12 +2517,14 @@ static int vfs_rename_dir(struct inode *
- }
- static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
--                          struct inode *new_dir, struct dentry *new_dentry)
-+                          struct vfsmount *old_mnt, struct inode *new_dir,
-+                          struct dentry *new_dentry, struct vfsmount *new_mnt)
- {
-       struct inode *target;
-       int error;
--      error = security_inode_rename(old_dir, old_dentry, new_dir, new_dentry);
-+      error = security_inode_rename(old_dir, old_dentry, old_mnt,
-+                                    new_dir, new_dentry, new_mnt);
-       if (error)
-               return error;
-@@ -2531,7 +2547,8 @@ static int vfs_rename_other(struct inode
- }
- int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
--             struct inode *new_dir, struct dentry *new_dentry)
-+              struct vfsmount *old_mnt, struct inode *new_dir,
-+              struct dentry *new_dentry, struct vfsmount *new_mnt)
- {
-       int error;
-       int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
-@@ -2560,9 +2577,11 @@ int vfs_rename(struct inode *old_dir, st
-       old_name = fsnotify_oldname_init(old_dentry->d_name.name);
-       if (is_dir)
--              error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
-+              error = vfs_rename_dir(old_dir, old_dentry, old_mnt,
-+                                     new_dir, new_dentry, new_mnt);
-       else
--              error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
-+              error = vfs_rename_other(old_dir, old_dentry, old_mnt,
-+                                       new_dir, new_dentry, new_mnt);
-       if (!error) {
-               const char *new_name = old_dentry->d_name.name;
-               fsnotify_move(old_dir, new_dir, old_name, new_name, is_dir,
-@@ -2634,8 +2653,8 @@ static int do_rename(int olddfd, const c
-       if (new_dentry == trap)
-               goto exit5;
--      error = vfs_rename(old_dir->d_inode, old_dentry,
--                                 new_dir->d_inode, new_dentry);
-+      error = vfs_rename(old_dir->d_inode, old_dentry, oldnd.path.mnt,
-+                         new_dir->d_inode, new_dentry, newnd.path.mnt);
- exit5:
-       dput(new_dentry);
- exit4:
-diff -uprN e/fs/namespace.c f/fs/namespace.c
---- e/fs/namespace.c   2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/namespace.c   2008-05-28 20:29:29.410207000 +0000
-@@ -1852,3 +1852,30 @@ void __put_mnt_ns(struct mnt_namespace *
-       release_mounts(&umount_list);
-       kfree(ns);
- }
-+
-+char *d_namespace_path(struct dentry *dentry, struct vfsmount *vfsmnt,
-+                     char *buf, int buflen)
-+{
-+      struct path root, ns_root = { };
-+      char *res;
-+
-+      read_lock(&current->fs->lock);
-+      root = current->fs->root;
-+      path_get(&current->fs->root);
-+      read_unlock(&current->fs->lock);
-+      spin_lock(&vfsmount_lock);
-+      if (root.mnt)
-+              ns_root.mnt = mntget(root.mnt->mnt_ns->root);
-+      if (ns_root.mnt)
-+              ns_root.dentry = dget(ns_root.mnt->mnt_root);
-+      spin_unlock(&vfsmount_lock);
-+      res = __d_path(dentry, vfsmnt, &ns_root, buf, buflen, 1, 1);
-+      path_put(&root);
-+      path_put(&ns_root);
-+
-+      /* Prevent empty path for lazily unmounted filesystems. */
-+      if (!IS_ERR(res) && *res == '\0')
-+              *--res = '.';
-+      return res;
-+}
-+EXPORT_SYMBOL(d_namespace_path);
-diff -uprN e/fs/nfsd/nfs4recover.c f/fs/nfsd/nfs4recover.c
---- e/fs/nfsd/nfs4recover.c    2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/nfsd/nfs4recover.c    2008-05-28 20:29:28.910241000 +0000
-@@ -154,7 +154,8 @@ nfsd4_create_clid_dir(struct nfs4_client
-               dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
-               goto out_put;
-       }
--      status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry, S_IRWXU, NULL);
-+      status = vfs_mkdir(rec_dir.path.dentry->d_inode, dentry,
-+                         rec_dir.path.mnt, S_IRWXU, NULL);
- out_put:
-       dput(dentry);
- out_unlock:
-@@ -258,7 +259,7 @@ nfsd4_remove_clid_file(struct dentry *di
-               return -EINVAL;
-       }
-       mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
--      status = vfs_unlink(dir->d_inode, dentry, NULL);
-+      status = vfs_unlink(dir->d_inode, dentry, NULL, rec_dir.path.mnt);
-       mutex_unlock(&dir->d_inode->i_mutex);
-       return status;
- }
-@@ -273,7 +274,7 @@ nfsd4_clear_clid_dir(struct dentry *dir,
-        * a kernel from the future.... */
-       nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
-       mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
--      status = vfs_rmdir(dir->d_inode, dentry, NULL);
-+      status = vfs_rmdir(dir->d_inode, dentry, NULL, rec_dir.path.mnt);
-       mutex_unlock(&dir->d_inode->i_mutex);
-       return status;
- }
-diff -uprN e/fs/nfsd/nfs4xdr.c f/fs/nfsd/nfs4xdr.c
---- e/fs/nfsd/nfs4xdr.c        2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/nfsd/nfs4xdr.c        2008-05-28 20:29:28.910241000 +0000
-@@ -1501,7 +1501,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, s
-       }
-       if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
-                       | FATTR4_WORD0_SUPPORTED_ATTRS)) {
--              err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
-+              err = nfsd4_get_nfs4_acl(rqstp, dentry, exp->ex_path.mnt, &acl);
-               aclsupport = (err == 0);
-               if (bmval0 & FATTR4_WORD0_ACL) {
-                       if (err == -EOPNOTSUPP)
-diff -uprN e/fs/nfsd/vfs.c f/fs/nfsd/vfs.c
---- e/fs/nfsd/vfs.c    2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/nfsd/vfs.c    2008-05-28 20:29:29.410207000 +0000
-@@ -388,7 +388,7 @@ nfsd_setattr(struct svc_rqst *rqstp, str
-       err = nfserr_notsync;
-       if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
-               fh_lock(fhp);
--              host_err = notify_change(dentry, iap);
-+              host_err = notify_change(dentry, fhp->fh_export->ex_path.mnt, iap);
-               err = nfserrno(host_err);
-               fh_unlock(fhp);
-       }
-@@ -408,11 +408,12 @@ out_nfserr:
- #if defined(CONFIG_NFSD_V2_ACL) || \
-     defined(CONFIG_NFSD_V3_ACL) || \
-     defined(CONFIG_NFSD_V4)
--static ssize_t nfsd_getxattr(struct dentry *dentry, char *key, void **buf)
-+static ssize_t nfsd_getxattr(struct dentry *dentry, struct vfsmount *mnt,
-+                           char *key, void **buf)
- {
-       ssize_t buflen;
--      buflen = vfs_getxattr(dentry, key, NULL, 0);
-+      buflen = vfs_getxattr(dentry, mnt, key, NULL, 0, NULL);
-       if (buflen <= 0)
-               return buflen;
-@@ -420,13 +421,14 @@ static ssize_t nfsd_getxattr(struct dent
-       if (!*buf)
-               return -ENOMEM;
--      return vfs_getxattr(dentry, key, *buf, buflen);
-+      return vfs_getxattr(dentry, mnt, key, *buf, buflen, NULL);
- }
- #endif
- #if defined(CONFIG_NFSD_V4)
- static int
--set_nfsv4_acl_one(struct dentry *dentry, struct posix_acl *pacl, char *key)
-+set_nfsv4_acl_one(struct dentry *dentry, struct vfsmount *mnt,
-+                struct posix_acl *pacl, char *key)
- {
-       int len;
-       size_t buflen;
-@@ -445,7 +447,7 @@ set_nfsv4_acl_one(struct dentry *dentry,
-               goto out;
-       }
--      error = vfs_setxattr(dentry, key, buf, len, 0);
-+      error = vfs_setxattr(dentry, mnt, key, buf, len, 0, NULL);
- out:
-       kfree(buf);
-       return error;
-@@ -458,6 +460,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
-       __be32 error;
-       int host_error;
-       struct dentry *dentry;
-+      struct vfsmount *mnt;
-       struct inode *inode;
-       struct posix_acl *pacl = NULL, *dpacl = NULL;
-       unsigned int flags = 0;
-@@ -468,6 +471,7 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
-               return error;
-       dentry = fhp->fh_dentry;
-+      mnt = fhp->fh_export->ex_path.mnt;
-       inode = dentry->d_inode;
-       if (S_ISDIR(inode->i_mode))
-               flags = NFS4_ACL_DIR;
-@@ -478,12 +482,14 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqst
-       } else if (host_error < 0)
-               goto out_nfserr;
--      host_error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
-+      host_error = set_nfsv4_acl_one(dentry, mnt, pacl,
-+                                     POSIX_ACL_XATTR_ACCESS);
-       if (host_error < 0)
-               goto out_release;
-       if (S_ISDIR(inode->i_mode))
--              host_error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
-+              host_error = set_nfsv4_acl_one(dentry, mnt, dpacl,
-+                                             POSIX_ACL_XATTR_DEFAULT);
- out_release:
-       posix_acl_release(pacl);
-@@ -496,13 +502,13 @@ out_nfserr:
- }
- static struct posix_acl *
--_get_posix_acl(struct dentry *dentry, char *key)
-+_get_posix_acl(struct dentry *dentry, struct vfsmount *mnt, char *key)
- {
-       void *buf = NULL;
-       struct posix_acl *pacl = NULL;
-       int buflen;
--      buflen = nfsd_getxattr(dentry, key, &buf);
-+      buflen = nfsd_getxattr(dentry, mnt, key, &buf);
-       if (!buflen)
-               buflen = -ENODATA;
-       if (buflen <= 0)
-@@ -514,14 +520,15 @@ _get_posix_acl(struct dentry *dentry, ch
- }
- int
--nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry, struct nfs4_acl **acl)
-+nfsd4_get_nfs4_acl(struct svc_rqst *rqstp, struct dentry *dentry,
-+                 struct vfsmount *mnt, struct nfs4_acl **acl)
- {
-       struct inode *inode = dentry->d_inode;
-       int error = 0;
-       struct posix_acl *pacl = NULL, *dpacl = NULL;
-       unsigned int flags = 0;
--      pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
-+      pacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_ACCESS);
-       if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
-               pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
-       if (IS_ERR(pacl)) {
-@@ -531,7 +538,7 @@ nfsd4_get_nfs4_acl(struct svc_rqst *rqst
-       }
-       if (S_ISDIR(inode->i_mode)) {
--              dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
-+              dpacl = _get_posix_acl(dentry, mnt, POSIX_ACL_XATTR_DEFAULT);
-               if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
-                       dpacl = NULL;
-               else if (IS_ERR(dpacl)) {
-@@ -944,13 +951,13 @@ out:
-       return err;
- }
--static void kill_suid(struct dentry *dentry)
-+static void kill_suid(struct dentry *dentry, struct vfsmount *mnt)
- {
-       struct iattr    ia;
-       ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
-       mutex_lock(&dentry->d_inode->i_mutex);
--      notify_change(dentry, &ia);
-+      notify_change(dentry, mnt, &ia);
-       mutex_unlock(&dentry->d_inode->i_mutex);
- }
-@@ -1009,7 +1016,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, s
-       /* clear setuid/setgid flag after write */
-       if (host_err >= 0 && (inode->i_mode & (S_ISUID | S_ISGID)))
--              kill_suid(dentry);
-+              kill_suid(dentry, exp->ex_path.mnt);
-       if (host_err >= 0 && stable) {
-               static ino_t    last_ino;
-@@ -1186,6 +1193,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
-               int type, dev_t rdev, struct svc_fh *resfhp)
- {
-       struct dentry   *dentry, *dchild = NULL;
-+      struct svc_export *exp;
-       struct inode    *dirp;
-       __be32          err;
-       __be32          err2;
-@@ -1203,6 +1211,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
-               goto out;
-       dentry = fhp->fh_dentry;
-+      exp = fhp->fh_export;
-       dirp = dentry->d_inode;
-       err = nfserr_notdir;
-@@ -1219,7 +1228,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
-               host_err = PTR_ERR(dchild);
-               if (IS_ERR(dchild))
-                       goto out_nfserr;
--              err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
-+              err = fh_compose(resfhp, exp, dchild, fhp);
-               if (err)
-                       goto out;
-       } else {
-@@ -1258,13 +1267,14 @@ nfsd_create(struct svc_rqst *rqstp, stru
-               host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
-               break;
-       case S_IFDIR:
--              host_err = vfs_mkdir(dirp, dchild, iap->ia_mode, NULL);
-+              host_err = vfs_mkdir(dirp, dchild, exp->ex_path.mnt, iap->ia_mode, NULL);
-               break;
-       case S_IFCHR:
-       case S_IFBLK:
-       case S_IFIFO:
-       case S_IFSOCK:
--              host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev, NULL);
-+              host_err = vfs_mknod(dirp, dchild, exp->ex_path.mnt,
-+                                   iap->ia_mode, rdev, NULL);
-               break;
-       default:
-               printk("nfsd: bad file type %o in nfsd_create\n", type);
-@@ -1273,7 +1283,7 @@ nfsd_create(struct svc_rqst *rqstp, stru
-       if (host_err < 0)
-               goto out_nfserr;
--      if (EX_ISSYNC(fhp->fh_export)) {
-+      if (EX_ISSYNC(exp)) {
-               err = nfserrno(nfsd_sync_dir(dentry));
-               write_inode_now(dchild->d_inode, 1);
-       }
-@@ -1496,6 +1506,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
-                               struct iattr *iap)
- {
-       struct dentry   *dentry, *dnew;
-+      struct svc_export *exp;
-       __be32          err, cerr;
-       int             host_err;
-       umode_t         mode;
-@@ -1522,6 +1533,7 @@ nfsd_symlink(struct svc_rqst *rqstp, str
-       if (iap && (iap->ia_valid & ATTR_MODE))
-               mode = iap->ia_mode & S_IALLUGO;
-+      exp = fhp->fh_export;
-       if (unlikely(path[plen] != 0)) {
-               char *path_alloced = kmalloc(plen+1, GFP_KERNEL);
-               if (path_alloced == NULL)
-@@ -1529,21 +1541,21 @@ nfsd_symlink(struct svc_rqst *rqstp, str
-                       strncpy(path_alloced, path, plen);
-                       path_alloced[plen] = 0;
-                       host_err = vfs_symlink(dentry->d_inode, dnew,
--                              path_alloced, mode, NULL);
-+                              exp->ex_path.mnt, path_alloced, mode, NULL);
-                       kfree(path_alloced);
-               }
-       } else
--              host_err = vfs_symlink(dentry->d_inode, dnew,
--                      path, mode, NULL);
-+              host_err = vfs_symlink(dentry->d_inode, dnew, exp->ex_path.mnt,
-+                                     path, mode, NULL);
-       if (!host_err) {
--              if (EX_ISSYNC(fhp->fh_export))
-+              if (EX_ISSYNC(exp))
-                       host_err = nfsd_sync_dir(dentry);
-       }
-       err = nfserrno(host_err);
-       fh_unlock(fhp);
--      cerr = fh_compose(resfhp, fhp->fh_export, dnew, fhp);
-+      cerr = fh_compose(resfhp, exp, dnew, fhp);
-       dput(dnew);
-       if (err==0) err = cerr;
- out:
-@@ -1592,7 +1606,8 @@ nfsd_link(struct svc_rqst *rqstp, struct
-       dold = tfhp->fh_dentry;
-       dest = dold->d_inode;
--      host_err = vfs_link(dold, dirp, dnew, NULL);
-+      host_err = vfs_link(dold, tfhp->fh_export->ex_path.mnt, dirp,
-+                          dnew, ffhp->fh_export->ex_path.mnt, NULL);
-       if (!host_err) {
-               if (EX_ISSYNC(ffhp->fh_export)) {
-                       err = nfserrno(nfsd_sync_dir(ddir));
-@@ -1685,7 +1700,8 @@ nfsd_rename(struct svc_rqst *rqstp, stru
-                       host_err = -EPERM;
-       } else
- #endif
--      host_err = vfs_rename(fdir, odentry, tdir, ndentry);
-+      host_err = vfs_rename(fdir, odentry, ffhp->fh_export->ex_path.mnt,
-+                            tdir, ndentry, tfhp->fh_export->ex_path.mnt);
-       if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
-               host_err = nfsd_sync_dir(tdentry);
-               if (!host_err)
-@@ -1721,6 +1737,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
-                               char *fname, int flen)
- {
-       struct dentry   *dentry, *rdentry;
-+      struct svc_export *exp;
-       struct inode    *dirp;
-       __be32          err;
-       int             host_err;
-@@ -1735,6 +1752,7 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
-       fh_lock_nested(fhp, I_MUTEX_PARENT);
-       dentry = fhp->fh_dentry;
-       dirp = dentry->d_inode;
-+      exp = fhp->fh_export;
-       rdentry = lookup_one_len(fname, dentry, flen);
-       host_err = PTR_ERR(rdentry);
-@@ -1752,21 +1770,21 @@ nfsd_unlink(struct svc_rqst *rqstp, stru
-       if (type != S_IFDIR) { /* It's UNLINK */
- #ifdef MSNFS
--              if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
-+              if ((exp->ex_flags & NFSEXP_MSNFS) &&
-                       (atomic_read(&rdentry->d_count) > 1)) {
-                       host_err = -EPERM;
-               } else
- #endif
--              host_err = vfs_unlink(dirp, rdentry, NULL);
-+              host_err = vfs_unlink(dirp, rdentry, NULL, exp->ex_path.mnt);
-       } else { /* It's RMDIR */
--              host_err = vfs_rmdir(dirp, rdentry, NULL);
-+              host_err = vfs_rmdir(dirp, rdentry, NULL, exp->ex_path.mnt);
-       }
-       dput(rdentry);
-       if (host_err)
-               goto out_nfserr;
--      if (EX_ISSYNC(fhp->fh_export))
-+      if (EX_ISSYNC(exp))
-               host_err = nfsd_sync_dir(dentry);
- out_nfserr:
-@@ -1995,7 +2013,8 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
-               return ERR_PTR(-EOPNOTSUPP);
-       }
--      size = nfsd_getxattr(fhp->fh_dentry, name, &value);
-+      size = nfsd_getxattr(fhp->fh_dentry, fhp->fh_export->ex_path.mnt, name,
-+                           &value);
-       if (size < 0)
-               return ERR_PTR(size);
-@@ -2007,6 +2026,7 @@ nfsd_get_posix_acl(struct svc_fh *fhp, i
- int
- nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
- {
-+      struct vfsmount *mnt;
-       struct inode *inode = fhp->fh_dentry->d_inode;
-       char *name;
-       void *value = NULL;
-@@ -2039,13 +2059,16 @@ nfsd_set_posix_acl(struct svc_fh *fhp, i
-       } else
-               size = 0;
-+      mnt = fhp->fh_export->ex_path.mnt;
-       if (size)
--              error = vfs_setxattr(fhp->fh_dentry, name, value, size, 0);
-+              error = vfs_setxattr(fhp->fh_dentry, mnt, name, value, size, 0,
-+                                   NULL);
-       else {
-               if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
-                       error = 0;
-               else {
--                      error = vfs_removexattr(fhp->fh_dentry, name);
-+                      error = vfs_removexattr(fhp->fh_dentry, mnt, name,
-+                                              NULL);
-                       if (error == -ENODATA)
-                               error = 0;
-               }
-diff -uprN e/fs/ntfs/file.c f/fs/ntfs/file.c
---- e/fs/ntfs/file.c   2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/ntfs/file.c   2008-05-28 20:29:28.910241000 +0000
-@@ -2118,7 +2118,7 @@ static ssize_t ntfs_file_aio_write_noloc
-               goto out;
-       if (!count)
-               goto out;
--      err = remove_suid(file->f_path.dentry);
-+      err = remove_suid(&file->f_path);
-       if (err)
-               goto out;
-       file_update_time(file);
-diff -uprN e/fs/open.c f/fs/open.c
---- e/fs/open.c        2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/open.c        2008-05-28 20:29:29.410207000 +0000
-@@ -194,8 +194,8 @@ out:
-       return error;
- }
--int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
--      struct file *filp)
-+int do_truncate(struct dentry *dentry, struct vfsmount *mnt, loff_t length,
-+              unsigned int time_attrs, struct file *filp)
- {
-       int err;
-       struct iattr newattrs;
-@@ -206,16 +206,15 @@ int do_truncate(struct dentry *dentry, l
-       newattrs.ia_size = length;
-       newattrs.ia_valid = ATTR_SIZE | time_attrs;
--      if (filp) {
--              newattrs.ia_file = filp;
-+
-+      if (filp)
-               newattrs.ia_valid |= ATTR_FILE;
--      }
-       /* Remove suid/sgid on truncate too */
-       newattrs.ia_valid |= should_remove_suid(dentry);
-       mutex_lock(&dentry->d_inode->i_mutex);
--      err = notify_change(dentry, &newattrs);
-+      err = fnotify_change(dentry, mnt, &newattrs, filp);
-       mutex_unlock(&dentry->d_inode->i_mutex);
-       return err;
- }
-@@ -271,7 +270,7 @@ static long do_sys_truncate(const char _
-       error = locks_verify_truncate(inode, NULL, length);
-       if (!error) {
-               DQUOT_INIT(inode);
--              error = do_truncate(nd.path.dentry, length, 0, NULL);
-+              error = do_truncate(nd.path.dentry, nd.path.mnt, length, 0, NULL);
-       }
- put_write_and_out:
-@@ -324,7 +323,8 @@ static long do_sys_ftruncate(unsigned in
-       error = locks_verify_truncate(inode, file, length);
-       if (!error)
--              error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file);
-+              error = do_truncate(dentry, file->f_path.mnt, length,
-+                                  ATTR_MTIME|ATTR_CTIME, file);
- out_putf:
-       fput(file);
- out:
-@@ -500,8 +500,8 @@ out:
- asmlinkage long sys_fchdir(unsigned int fd)
- {
-+      struct nameidata nd = { .flags = 0 };
-       struct file *file;
--      struct inode *inode;
-       int error;
-       error = -EBADF;
-@@ -509,12 +509,11 @@ asmlinkage long sys_fchdir(unsigned int 
-       if (!file)
-               goto out;
--      inode = file->f_path.dentry->d_inode;
--
-       error = -ENOTDIR;
--      if (!S_ISDIR(inode->i_mode))
-+      if (!S_ISDIR(file->f_path.dentry->d_inode->i_mode))
-               goto out_putf;
-+      nd.path = file->f_path;
-       error = file_permission(file, MAY_EXEC);
-       if (!error)
-               set_fs_pwd(current->fs, &file->f_path);
-@@ -577,8 +576,8 @@ asmlinkage long sys_fchmod(unsigned int 
-       if (mode == (mode_t) -1)
-               mode = inode->i_mode;
-       newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
--      newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
--      err = notify_change(dentry, &newattrs);
-+      newattrs.ia_valid = ATTR_MODE | ATTR_CTIME | ATTR_FILE;
-+      err = fnotify_change(dentry, file->f_path.mnt, &newattrs, file);
-       mutex_unlock(&inode->i_mutex);
- out_putf:
-@@ -613,7 +612,7 @@ asmlinkage long sys_fchmodat(int dfd, co
-               mode = inode->i_mode;
-       newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
-       newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
--      error = notify_change(nd.path.dentry, &newattrs);
-+      error = notify_change(nd.path.dentry, nd.path.mnt, &newattrs);
-       mutex_unlock(&inode->i_mutex);
- dput_and_out:
-@@ -627,7 +626,7 @@ asmlinkage long sys_chmod(const char __u
- }
- static int chown_common(struct dentry *dentry, struct vfsmount *mnt,
--      uid_t user, gid_t group)
-+                      uid_t user, gid_t group, struct file *file)
- {
-       struct inode * inode;
-       int error;
-@@ -666,8 +666,11 @@ static int chown_common(struct dentry * 
-       if (!S_ISDIR(inode->i_mode))
-               newattrs.ia_valid |=
-                       ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
-+      if (file)
-+              newattrs.ia_valid |= ATTR_FILE;
-+
-       mutex_lock(&inode->i_mutex);
--      error = notify_change(dentry, &newattrs);
-+      error = fnotify_change(dentry, mnt, &newattrs, file);
-       mutex_unlock(&inode->i_mutex);
- out:
-       return error;
-@@ -671,7 +686,7 @@ asmlinkage long sys_chown(const char __u
-       error = cow_check_and_break(&nd);
-       if (!error)
- #endif
--              error = chown_common(nd.path.dentry, nd.path.mnt, user, group);
-+              error = chown_common(nd.path.dentry, nd.path.mnt, user, group, NULL);
-       path_put(&nd.path);
- out:
-       return error;
-@@ -691,7 +710,7 @@ asmlinkage long sys_fchownat(int dfd, co
-       error = __user_walk_fd(dfd, filename, follow, &nd);
-       if (!error)
- #endif
--              error = chown_common(nd.path.dentry, nd.path.mnt, user, group);
-+              error = chown_common(nd.path.dentry, nd.path.mnt, user, group, NULL);
-       path_put(&nd.path);
- out:
-       return error;
-@@ -705,7 +708,7 @@ asmlinkage long sys_lchown(const char __
-       error = cow_check_and_break(&nd);
-       if (!error)
- #endif
--              error = chown_common(nd.path.dentry, nd.path.mnt, user, group);
-+              error = chown_common(nd.path.dentry, nd.path.mnt, user, group, NULL);
-       path_put(&nd.path);
- out:
-       return error;
-@@ -724,7 +727,7 @@ asmlinkage long sys_fchown(unsigned int 
-       dentry = file->f_path.dentry;
-       audit_inode(NULL, dentry);
--      error = chown_common(dentry, file->f_vfsmnt, user, group);
-+      error = chown_common(dentry, file->f_path.mnt, user, group, file);
-       fput(file);
- out:
-       return error;
-diff -uprN e/fs/reiserfs/xattr.c f/fs/reiserfs/xattr.c
---- e/fs/reiserfs/xattr.c      2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/reiserfs/xattr.c      2008-05-28 20:29:28.910241000 +0000
-@@ -460,7 +460,7 @@ reiserfs_xattr_set(struct inode *inode, 
-       newattrs.ia_size = buffer_size;
-       newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
-       mutex_lock_nested(&xinode->i_mutex, I_MUTEX_XATTR);
--      err = notify_change(dentry, &newattrs);
-+      err = notify_change(dentry, NULL, &newattrs);
-       if (err)
-               goto out_filp;
-@@ -747,7 +747,7 @@ int reiserfs_delete_xattrs(struct inode 
-       if (dir->d_inode->i_nlink <= 2) {
-               root = get_xa_root(inode->i_sb, XATTR_REPLACE);
-               reiserfs_write_lock_xattrs(inode->i_sb);
--              err = vfs_rmdir(root->d_inode, dir, NULL);
-+              err = vfs_rmdir(root->d_inode, dir, NULL, NULL);
-               reiserfs_write_unlock_xattrs(inode->i_sb);
-               dput(root);
-       } else {
-@@ -791,7 +791,7 @@ reiserfs_chown_xattrs_filler(void *buf, 
-       }
-       if (!S_ISDIR(xafile->d_inode->i_mode))
--              err = notify_change(xafile, attrs);
-+              err = notify_change(xafile, NULL, attrs);
-       dput(xafile);
-       return err;
-@@ -835,7 +835,7 @@ int reiserfs_chown_xattrs(struct inode *
-               goto out_dir;
-       }
--      err = notify_change(dir, attrs);
-+      err = notify_change(dir, NULL, attrs);
-       unlock_kernel();
-       out_dir:
-diff -uprN e/fs/splice.c f/fs/splice.c
---- e/fs/splice.c      2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/splice.c      2008-05-28 20:29:28.910241000 +0000
-@@ -762,7 +762,7 @@ generic_file_splice_write_nolock(struct 
-       ssize_t ret;
-       int err;
--      err = remove_suid(out->f_path.dentry);
-+      err = remove_suid(&out->f_path);
-       if (unlikely(err))
-               return err;
-@@ -822,7 +822,7 @@ generic_file_splice_write(struct pipe_in
-               if (killpriv)
-                       err = security_inode_killpriv(out->f_path.dentry);
-               if (!err && killsuid)
--                      err = __remove_suid(out->f_path.dentry, killsuid);
-+                      err = __remove_suid(&out->f_path, killsuid);
-               mutex_unlock(&inode->i_mutex);
-               if (err)
-                       return err;
-diff -uprN e/fs/stat.c f/fs/stat.c
---- e/fs/stat.c        2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/stat.c        2008-05-28 20:29:28.910241000 +0000
-@@ -306,7 +306,7 @@ asmlinkage long sys_readlinkat(int dfd, 
-               error = -EINVAL;
-               if (inode->i_op && inode->i_op->readlink) {
--                      error = security_inode_readlink(nd.path.dentry);
-+                      error = security_inode_readlink(nd.path.dentry, nd.path.mnt);
-                       if (!error) {
-                               touch_atime(nd.path.mnt, nd.path.dentry);
-                               error = inode->i_op->readlink(nd.path.dentry,
-diff -uprN e/fs/sysfs/file.c f/fs/sysfs/file.c
---- e/fs/sysfs/file.c  2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/sysfs/file.c  2008-05-28 20:29:28.910241000 +0000
-@@ -579,7 +579,7 @@ int sysfs_chmod_file(struct kobject *kob
-       newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
-       newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
--      rc = notify_change(victim, &newattrs);
-+      rc = notify_change(victim, NULL, &newattrs);
-       if (rc == 0) {
-               mutex_lock(&sysfs_mutex);
-diff -uprN e/fs/utimes.c f/fs/utimes.c
---- e/fs/utimes.c      2008-05-28 20:32:27.897940261 +0000
-+++ f/fs/utimes.c      2008-05-28 20:29:29.410207000 +0000
-@@ -60,7 +60,7 @@ long do_utimes(int dfd, char __user *fil
- {
-       int error;
-       struct nameidata nd;
--      struct dentry *dentry;
-+      struct path path;
-       struct inode *inode;
-       struct iattr newattrs;
-       struct file *f = NULL;
-@@ -83,19 +83,19 @@ long do_utimes(int dfd, char __user *fil
-               f = fget(dfd);
-               if (!f)
-                       goto out;
--              dentry = f->f_path.dentry;
-+              path = f->f_path;
-       } else {
-               error = __user_walk_fd(dfd, filename, (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW, &nd);
-               if (error)
-                       goto out;
-               error = cow_check_and_break(&nd);
-               if (error)
-                       goto dput_and_out;
--              dentry = nd.path.dentry;
-+              path = nd.path;
-       }
--      inode = dentry->d_inode;
-+      inode = path.dentry->d_inode;
-       error = -EROFS;
-       if (IS_RDONLY(inode))
-@@ -145,7 +145,7 @@ long do_utimes(int dfd, char __user *fil
-               }
-       }
-       mutex_lock(&inode->i_mutex);
--      error = notify_change(dentry, &newattrs);
-+      error = fnotify_change(path.dentry, path.mnt, &newattrs, f);
-       mutex_unlock(&inode->i_mutex);
- dput_and_out:
-       if (f)
-diff -uprN e/fs/xattr.c f/fs/xattr.c
---- e/fs/xattr.c       2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/xattr.c       2008-05-28 20:29:29.410207000 +0000
-@@ -68,8 +68,8 @@ xattr_permission(struct inode *inode, co
- }
- int
--vfs_setxattr(struct dentry *dentry, char *name, void *value,
--              size_t size, int flags)
-+vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
-+           void *value, size_t size, int flags, struct file *file)
- {
-       struct inode *inode = dentry->d_inode;
-       int error;
-@@ -79,7 +79,7 @@ vfs_setxattr(struct dentry *dentry, char
-               return error;
-       mutex_lock(&inode->i_mutex);
--      error = security_inode_setxattr(dentry, name, value, size, flags);
-+      error = security_inode_setxattr(dentry, mnt, name, value, size, flags,                                          file);
-       if (error)
-               goto out;
-       error = -EOPNOTSUPP;
-@@ -87,7 +87,7 @@ vfs_setxattr(struct dentry *dentry, char
-               error = inode->i_op->setxattr(dentry, name, value, size, flags);
-               if (!error) {
-                       fsnotify_xattr(dentry);
--                      security_inode_post_setxattr(dentry, name, value,
-+                      security_inode_post_setxattr(dentry, mnt, name, value,
-                                                    size, flags);
-               }
-       } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
-@@ -132,7 +132,8 @@ out_noalloc:
- EXPORT_SYMBOL_GPL(xattr_getsecurity);
- ssize_t
--vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
-+vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
-+           void *value, size_t size, struct file *file)
- {
-       struct inode *inode = dentry->d_inode;
-       int error;
-@@ -141,7 +142,7 @@ vfs_getxattr(struct dentry *dentry, char
-       if (error)
-               return error;
--      error = security_inode_getxattr(dentry, name);
-+      error = security_inode_getxattr(dentry, mnt, name, file);
-       if (error)
-               return error;
-@@ -168,18 +169,20 @@ nolsm:
- EXPORT_SYMBOL_GPL(vfs_getxattr);
- ssize_t
--vfs_listxattr(struct dentry *d, char *list, size_t size)
-+vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
-+            size_t size, struct file *file)
- {
-+      struct inode *inode = dentry->d_inode;
-       ssize_t error;
--      error = security_inode_listxattr(d);
-+      error = security_inode_listxattr(dentry, mnt, file);
-       if (error)
-               return error;
-       error = -EOPNOTSUPP;
--      if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
--              error = d->d_inode->i_op->listxattr(d, list, size);
--      } else {
--              error = security_inode_listsecurity(d->d_inode, list, size);
-+      if (inode->i_op && inode->i_op->listxattr)
-+              error = inode->i_op->listxattr(dentry, list, size);
-+      else {
-+              error = security_inode_listsecurity(inode, list, size);
-               if (size && error > size)
-                       error = -ERANGE;
-       }
-@@ -188,7 +191,8 @@ vfs_listxattr(struct dentry *d, char *li
- EXPORT_SYMBOL_GPL(vfs_listxattr);
- int
--vfs_removexattr(struct dentry *dentry, char *name)
-+vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
-+              struct file *file)
- {
-       struct inode *inode = dentry->d_inode;
-       int error;
-@@ -200,7 +204,7 @@ vfs_removexattr(struct dentry *dentry, c
-       if (error)
-               return error;
--      error = security_inode_removexattr(dentry, name);
-+      error = security_inode_removexattr(dentry, mnt, name, file);
-       if (error)
-               return error;
-@@ -219,7 +223,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
-  */
- static long
- setxattr(struct dentry *d, char __user *name, void __user *value,
--       size_t size, int flags, struct vfsmount *mnt)
-+       size_t size, int flags, struct vfsmount *mnt, struct file *file)
- {
-       int error;
-       void *kvalue = NULL;
-@@ -247,7 +251,7 @@ setxattr(struct dentry *d, char __user *
-               }
-       }
--      error = vfs_setxattr(d, kname, kvalue, size, flags);
-+      error = vfs_setxattr(d, mnt, kname, kvalue, size, flags, file);
-       kfree(kvalue);
-       return error;
- }
-@@ -262,7 +266,7 @@ sys_setxattr(char __user *path, char __u
-       error = user_path_walk(path, &nd);
-       if (error)
-               return error;
--      error = setxattr(nd.path.dentry, name, value, size, flags, nd.path.mnt);
-+      error = setxattr(nd.path.dentry, name, value, size, flags, nd.path.mnt, NULL);
-       path_put(&nd.path);
-       return error;
- }
-@@ -277,7 +281,7 @@ sys_lsetxattr(char __user *path, char __
-       error = user_path_walk_link(path, &nd);
-       if (error)
-               return error;
--      error = setxattr(nd.path.dentry, name, value, size, flags, nd.path.mnt);
-+      error = setxattr(nd.path.dentry, name, value, size, flags, nd.path.mnt, NULL);
-       path_put(&nd.path);
-       return error;
- }
-@@ -295,7 +299,7 @@ sys_fsetxattr(int fd, char __user *name,
-               return error;
-       dentry = f->f_path.dentry;
-       audit_inode(NULL, dentry);
--      error = setxattr(dentry, name, value, size, flags, f->f_vfsmnt);
-+      error = setxattr(dentry, name, value, size, flags, f->f_vfsmnt, f);
-       fput(f);
-       return error;
- }
-@@ -304,7 +308,8 @@ sys_fsetxattr(int fd, char __user *name,
-  * Extended attribute GET operations
-  */
- static ssize_t
--getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
-+getxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *name,
-+       void __user *value, size_t size, struct file *file)
- {
-       ssize_t error;
-       void *kvalue = NULL;
-@@ -324,7 +329,7 @@ getxattr(struct dentry *d, char __user *
-                       return -ENOMEM;
-       }
--      error = vfs_getxattr(d, kname, kvalue, size);
-+      error = vfs_getxattr(dentry, mnt, kname, kvalue, size, file);
-       if (error > 0) {
-               if (size && copy_to_user(value, kvalue, error))
-                       error = -EFAULT;
-@@ -347,7 +352,7 @@ sys_getxattr(char __user *path, char __u
-       error = user_path_walk(path, &nd);
-       if (error)
-               return error;
--      error = getxattr(nd.path.dentry, name, value, size);
-+      error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size, NULL);
-       path_put(&nd.path);
-       return error;
- }
-@@ -362,7 +367,7 @@ sys_lgetxattr(char __user *path, char __
-       error = user_path_walk_link(path, &nd);
-       if (error)
-               return error;
--      error = getxattr(nd.path.dentry, name, value, size);
-+      error = getxattr(nd.path.dentry, nd.path.mnt, name, value, size, NULL);
-       path_put(&nd.path);
-       return error;
- }
-@@ -377,7 +382,7 @@ sys_fgetxattr(int fd, char __user *name,
-       if (!f)
-               return error;
-       audit_inode(NULL, f->f_path.dentry);
--      error = getxattr(f->f_path.dentry, name, value, size);
-+      error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size, f);
-       fput(f);
-       return error;
- }
-@@ -386,7 +391,8 @@ sys_fgetxattr(int fd, char __user *name,
-  * Extended attribute LIST operations
-  */
- static ssize_t
--listxattr(struct dentry *d, char __user *list, size_t size)
-+listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
-+        size_t size, struct file *file)
- {
-       ssize_t error;
-       char *klist = NULL;
-@@ -399,7 +405,7 @@ listxattr(struct dentry *d, char __user 
-                       return -ENOMEM;
-       }
--      error = vfs_listxattr(d, klist, size);
-+      error = vfs_listxattr(dentry, mnt, klist, size, file);
-       if (error > 0) {
-               if (size && copy_to_user(list, klist, error))
-                       error = -EFAULT;
-@@ -421,7 +427,7 @@ sys_listxattr(char __user *path, char __
-       error = user_path_walk(path, &nd);
-       if (error)
-               return error;
--      error = listxattr(nd.path.dentry, list, size);
-+      error = listxattr(nd.path.dentry, nd.path.mnt, list, size, NULL);
-       path_put(&nd.path);
-       return error;
- }
-@@ -435,7 +441,7 @@ sys_llistxattr(char __user *path, char _
-       error = user_path_walk_link(path, &nd);
-       if (error)
-               return error;
--      error = listxattr(nd.path.dentry, list, size);
-+      error = listxattr(nd.path.dentry, nd.path.mnt, list, size, NULL);
-       path_put(&nd.path);
-       return error;
- }
-@@ -450,7 +456,7 @@ sys_flistxattr(int fd, char __user *list
-       if (!f)
-               return error;
-       audit_inode(NULL, f->f_path.dentry);
--      error = listxattr(f->f_path.dentry, list, size);
-+      error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size, f);
-       fput(f);
-       return error;
- }
-@@ -459,7 +465,8 @@ sys_flistxattr(int fd, char __user *list
-  * Extended attribute REMOVE operations
-  */
- static long
--removexattr(struct dentry *d, char __user *name, struct vfsmount *mnt)
-+removexattr(struct dentry *dentry, char __user *name, struct vfsmount *mnt,
-+          struct file *file)
- {
-       int error;
-       char kname[XATTR_NAME_MAX + 1];
-@@ -470,7 +477,7 @@ removexattr(struct dentry *d, char __use
-       if (error < 0)
-               return error;
--      return vfs_removexattr(d, kname);
-+      return vfs_removexattr(dentry, mnt, kname, file);
- }
- asmlinkage long
-@@ -482,7 +489,7 @@ sys_removexattr(char __user *path, char 
-       error = user_path_walk(path, &nd);
-       if (error)
-               return error;
--      error = removexattr(nd.path.dentry, name, nd.path.mnt);
-+      error = removexattr(nd.path.dentry, name, nd.path.mnt, NULL);
-       path_put(&nd.path);
-       return error;
- }
-@@ -496,7 +503,7 @@ sys_lremovexattr(char __user *path, char
-       error = user_path_walk_link(path, &nd);
-       if (error)
-               return error;
--      error = removexattr(nd.path.dentry, name, nd.path.mnt);
-+      error = removexattr(nd.path.dentry, name, nd.path.mnt, NULL);
-       path_put(&nd.path);
-       return error;
- }
-@@ -513,7 +520,7 @@ sys_fremovexattr(int fd, char __user *na
-               return error;
-       dentry = f->f_path.dentry;
-       audit_inode(NULL, dentry);
--      error = removexattr(dentry, name, f->f_vfsmnt);
-+      error = removexattr(dentry, name, f->f_path.mnt, f);
-       fput(f);
-       return error;
- }
-diff -uprN e/fs/xfs/linux-2.6/xfs_lrw.c f/fs/xfs/linux-2.6/xfs_lrw.c
---- e/fs/xfs/linux-2.6/xfs_lrw.c       2008-04-17 02:49:44.000000000 +0000
-+++ f/fs/xfs/linux-2.6/xfs_lrw.c       2008-05-28 20:29:28.910241000 +0000
-@@ -716,7 +716,7 @@ start:
-            !capable(CAP_FSETID)) {
-               error = xfs_write_clear_setuid(xip);
-               if (likely(!error))
--                      error = -remove_suid(file->f_path.dentry);
-+                      error = -remove_suid(&file->f_path);
-               if (unlikely(error)) {
-                       goto out_unlock_internal;
-               }
-diff -uprN e/include/linux/audit.h f/include/linux/audit.h
---- e/include/linux/audit.h    2008-04-17 02:49:44.000000000 +0000
-+++ f/include/linux/audit.h    2008-05-28 20:29:29.410207000 +0000
-@@ -33,7 +33,7 @@
-  * 1200 - 1299 messages internal to the audit daemon
-  * 1300 - 1399 audit event messages
-  * 1400 - 1499 SE Linux use
-- * 1500 - 1599 kernel LSPP events
-+ * 1500 - 1599 AppArmor use
-  * 1600 - 1699 kernel crypto events
-  * 1700 - 1799 kernel anomaly records
-  * 1800 - 1999 future kernel use (maybe integrity labels and related events)
-@@ -119,6 +119,13 @@
- #define AUDIT_MAC_UNLBL_STCADD        1416    /* NetLabel: add a static label */
- #define AUDIT_MAC_UNLBL_STCDEL        1417    /* NetLabel: del a static label */
-+#define AUDIT_APPARMOR_AUDIT  1501    /* AppArmor audited grants */
-+#define AUDIT_APPARMOR_ALLOWED        1502    /* Allowed Access for learning */
-+#define AUDIT_APPARMOR_DENIED 1503
-+#define AUDIT_APPARMOR_HINT   1504    /* Process Tracking information */
-+#define AUDIT_APPARMOR_STATUS 1505    /* Changes in config */
-+#define AUDIT_APPARMOR_ERROR  1506    /* Internal AppArmor Errors */
-+
- #define AUDIT_FIRST_KERN_ANOM_MSG   1700
- #define AUDIT_LAST_KERN_ANOM_MSG    1799
- #define AUDIT_ANOM_PROMISCUOUS      1700 /* Device changed promiscuous mode */
-@@ -518,6 +525,9 @@ extern void                    audit_log(struct audit_
-                                     __attribute__((format(printf,4,5)));
- extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
-+extern void               audit_log_vformat(struct audit_buffer *ab,
-+                                            const char *fmt, va_list args)
-+                          __attribute__((format(printf,2,0)));
- extern void               audit_log_format(struct audit_buffer *ab,
-                                            const char *fmt, ...)
-                           __attribute__((format(printf,2,3)));
-diff -uprN e/include/linux/dcache.h f/include/linux/dcache.h
---- e/include/linux/dcache.h   2008-04-17 02:49:44.000000000 +0000
-+++ f/include/linux/dcache.h   2008-05-28 20:29:29.410207000 +0000
-@@ -300,7 +300,8 @@ extern int d_validate(struct dentry *, s
-  * helper function for dentry_operations.d_dname() members
-  */
- extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
--
-+extern char *__d_path(struct dentry *, struct vfsmount *, struct path *,
-+                    char *, int, int, int);
- extern char *d_path(struct path *, char *, int);
- /* Allocation counts.. */
-diff -uprN e/include/linux/fs.h f/include/linux/fs.h
---- e/include/linux/fs.h       2008-04-17 02:49:44.000000000 +0000
-+++ f/include/linux/fs.h       2008-05-28 20:29:29.410207000 +0000
-@@ -353,13 +353,6 @@ struct iattr {
-       struct timespec ia_atime;
-       struct timespec ia_mtime;
-       struct timespec ia_ctime;
--
--      /*
--       * Not an attribute, but an auxilary info for filesystems wanting to
--       * implement an ftruncate() like method.  NOTE: filesystem should
--       * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL).
--       */
--      struct file     *ia_file;
- };
- /*
-@@ -1076,13 +1069,13 @@ extern void unlock_super(struct super_bl
-  */
- extern int vfs_permission(struct nameidata *, int);
- extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
--extern int vfs_mkdir(struct inode *, struct dentry *, int, struct nameidata *);
--extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t, struct nameidata *);
--extern int vfs_symlink(struct inode *, struct dentry *, const char *, int, struct nameidata *);
--extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct nameidata *);
--extern int vfs_rmdir(struct inode *, struct dentry *, struct nameidata *);
--extern int vfs_unlink(struct inode *, struct dentry *, struct nameidata *);
--extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
-+extern int vfs_mkdir(struct inode *, struct dentry *, struct vfsmount *, int, struct nameidata *);
-+extern int vfs_mknod(struct inode *, struct dentry *, struct vfsmount *, int, dev_t, struct nameidata *);
-+extern int vfs_symlink(struct inode *, struct dentry *, struct vfsmount *, const char *, int, struct nameidata *);
-+extern int vfs_link(struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *, struct nameidata *);
-+extern int vfs_rmdir(struct inode *, struct dentry *, struct nameidata *, struct vfsmount *);
-+extern int vfs_unlink(struct inode *, struct dentry *, struct nameidata *, struct vfsmount *);
-+extern int vfs_rename(struct inode *, struct dentry *, struct vfsmount *, struct inode *, struct dentry *, struct vfsmount *);
- /*
-  * VFS dentry helper functions.
-@@ -1196,6 +1189,7 @@ struct file_operations {
-       ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
-       ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
-       int (*setlease)(struct file *, long, struct file_lock **);
-+      int (*fsetattr)(struct file *, struct iattr *);
- };
- struct inode_operations {
-@@ -1559,8 +1553,8 @@ static inline int break_lease(struct ino
- /* fs/open.c */
--extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
--                     struct file *filp);
-+extern int do_truncate(struct dentry *, struct vfsmount *, loff_t start,
-+                     unsigned int time_attrs, struct file *filp);
- extern long do_sys_open(int dfd, const char __user *filename, int flags,
-                       int mode);
- extern struct file *filp_open(const char *, int, int);
-@@ -1714,7 +1708,8 @@ extern int do_remount_sb(struct super_bl
- #ifdef CONFIG_BLOCK
- extern sector_t bmap(struct inode *, sector_t);
- #endif
--extern int notify_change(struct dentry *, struct iattr *);
-+extern int notify_change(struct dentry *, struct vfsmount *, struct iattr *);
-+extern int fnotify_change(struct dentry *, struct vfsmount *, struct iattr *, struct file *);
- extern int permission(struct inode *, int, struct nameidata *);
- extern int generic_permission(struct inode *, int,
-               int (*check_acl)(struct inode *, int));
-@@ -1776,9 +1771,9 @@ extern void iget_failed(struct inode *);
- extern void clear_inode(struct inode *);
- extern void destroy_inode(struct inode *);
- extern struct inode *new_inode(struct super_block *);
--extern int __remove_suid(struct dentry *, int);
-+extern int __remove_suid(struct path *, int);
- extern int should_remove_suid(struct dentry *);
--extern int remove_suid(struct dentry *);
-+extern int remove_suid(struct path *);
- extern void __insert_inode_hash(struct inode *, unsigned long hashval);
- extern void remove_inode_hash(struct inode *);
-diff -uprN e/include/linux/mount.h f/include/linux/mount.h
---- e/include/linux/mount.h    2008-04-17 02:49:44.000000000 +0000
-+++ f/include/linux/mount.h    2008-05-28 20:29:29.410207000 +0000
-@@ -103,5 +103,7 @@ extern void mark_mounts_for_expiry(struc
- extern spinlock_t vfsmount_lock;
- extern dev_t name_to_dev_t(char *name);
-+extern char *d_namespace_path(struct dentry *, struct vfsmount *, char *, int);
-+
- #endif
- #endif /* _LINUX_MOUNT_H */
-diff -uprN e/include/linux/nfsd/nfsd.h f/include/linux/nfsd/nfsd.h
---- e/include/linux/nfsd/nfsd.h        2008-04-17 02:49:44.000000000 +0000
-+++ f/include/linux/nfsd/nfsd.h        2008-05-28 20:29:28.910241000 +0000
-@@ -78,7 +78,8 @@ __be32               nfsd_setattr(struct svc_rqst *, 
- #ifdef CONFIG_NFSD_V4
- __be32          nfsd4_set_nfs4_acl(struct svc_rqst *, struct svc_fh *,
-                     struct nfs4_acl *);
--int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *, struct nfs4_acl **);
-+int             nfsd4_get_nfs4_acl(struct svc_rqst *, struct dentry *,
-+                              struct vfsmount *mnt, struct nfs4_acl **);
- #endif /* CONFIG_NFSD_V4 */
- __be32                nfsd_create(struct svc_rqst *, struct svc_fh *,
-                               char *name, int len, struct iattr *attrs,
-diff -uprN e/include/linux/security.h f/include/linux/security.h
---- e/include/linux/security.h 2008-04-17 02:49:44.000000000 +0000
-+++ f/include/linux/security.h 2008-05-28 20:29:29.410207000 +0000
-@@ -51,8 +51,8 @@ extern void cap_capset_set (struct task_
- extern int cap_bprm_set_security (struct linux_binprm *bprm);
- extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
- extern int cap_bprm_secureexec(struct linux_binprm *bprm);
--extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags);
--extern int cap_inode_removexattr(struct dentry *dentry, char *name);
-+extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name, void *value, size_t size, int flags, struct file *file);
-+extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt, char *name, struct file *file);
- extern int cap_inode_need_killpriv(struct dentry *dentry);
- extern int cap_inode_killpriv(struct dentry *dentry);
- extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
-@@ -330,23 +330,28 @@ static inline void security_free_mnt_opt
-  *    Check permission to create a regular file.
-  *    @dir contains inode structure of the parent of the new file.
-  *    @dentry contains the dentry structure for the file to be created.
-+ *    @mnt is the vfsmount corresponding to @dentry (may be NULL).
-  *    @mode contains the file mode of the file to be created.
-  *    Return 0 if permission is granted.
-  * @inode_link:
-  *    Check permission before creating a new hard link to a file.
-  *    @old_dentry contains the dentry structure for an existing link to the file.
-+ *    @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
-  *    @dir contains the inode structure of the parent directory of the new link.
-  *    @new_dentry contains the dentry structure for the new link.
-+ *    @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
-  *    Return 0 if permission is granted.
-  * @inode_unlink:
-  *    Check the permission to remove a hard link to a file. 
-  *    @dir contains the inode structure of parent directory of the file.
-  *    @dentry contains the dentry structure for file to be unlinked.
-+ *    @mnt is the vfsmount corresponding to @dentry (may be NULL).
-  *    Return 0 if permission is granted.
-  * @inode_symlink:
-  *    Check the permission to create a symbolic link to a file.
-  *    @dir contains the inode structure of parent directory of the symbolic link.
-  *    @dentry contains the dentry structure of the symbolic link.
-+ *    @mnt is the vfsmount corresponding to @dentry (may be NULL).
-  *    @old_name contains the pathname of file.
-  *    Return 0 if permission is granted.
-  * @inode_mkdir:
-@@ -354,12 +359,14 @@ static inline void security_free_mnt_opt
-  *    associated with inode strcture @dir. 
-  *    @dir containst the inode structure of parent of the directory to be created.
-  *    @dentry contains the dentry structure of new directory.
-+ *    @mnt is the vfsmount corresponding to @dentry (may be NULL).
-  *    @mode contains the mode of new directory.
-  *    Return 0 if permission is granted.
-  * @inode_rmdir:
-  *    Check the permission to remove a directory.
-  *    @dir contains the inode structure of parent of the directory to be removed.
-  *    @dentry contains the dentry structure of directory to be removed.
-+ *    @mnt is the vfsmount corresponding to @dentry (may be NULL).
-  *    Return 0 if permission is granted.
-  * @inode_mknod:
-  *    Check permissions when creating a special file (or a socket or a fifo
-@@ -368,6 +375,7 @@ static inline void security_free_mnt_opt
-  *    and not this hook.
-  *    @dir contains the inode structure of parent of the new file.
-  *    @dentry contains the dentry structure of the new file.
-+ *    @mnt is the vfsmount corresponding to @dentry (may be NULL).
-  *    @mode contains the mode of the new file.
-  *    @dev contains the device number.
-  *    Return 0 if permission is granted.
-@@ -375,12 +383,15 @@ static inline void security_free_mnt_opt
-  *    Check for permission to rename a file or directory.
-  *    @old_dir contains the inode structure for parent of the old link.
-  *    @old_dentry contains the dentry structure of the old link.
-+ *    @old_mnt is the vfsmount corresponding to @old_dentry (may be NULL).
-  *    @new_dir contains the inode structure for parent of the new link.
-  *    @new_dentry contains the dentry structure of the new link.
-+ *    @new_mnt is the vfsmount corresponding to @new_dentry (may be NULL).
-  *    Return 0 if permission is granted.
-  * @inode_readlink:
-  *    Check the permission to read the symbolic link.
-  *    @dentry contains the dentry structure for the file link.
-+ *    @mnt is the vfsmount corresponding to @dentry (may be NULL).
-  *    Return 0 if permission is granted.
-  * @inode_follow_link:
-  *    Check permission to follow a symbolic link when looking up a pathname.
-@@ -404,6 +415,7 @@ static inline void security_free_mnt_opt
-  *    file attributes change (such as when a file is truncated, chown/chmod
-  *    operations, transferring disk quotas, etc).
-  *    @dentry contains the dentry structure for the file.
-+ *    @mnt is the vfsmount corresponding to @dentry (may be NULL).
-  *    @attr is the iattr structure containing the new file attributes.
-  *    Return 0 if permission is granted.
-  * @inode_getattr:
-@@ -419,18 +431,18 @@ static inline void security_free_mnt_opt
-  *    inode.
-  * @inode_setxattr:
-  *    Check permission before setting the extended attributes
-- *    @value identified by @name for @dentry.
-+ *    @value identified by @name for @dentry and @mnt.
-  *    Return 0 if permission is granted.
-  * @inode_post_setxattr:
-  *    Update inode security field after successful setxattr operation.
-- *    @value identified by @name for @dentry.
-+ *    @value identified by @name for @dentry and @mnt.
-  * @inode_getxattr:
-  *    Check permission before obtaining the extended attributes
-- *    identified by @name for @dentry.
-+ *    identified by @name for @dentry and @mnt.
-  *    Return 0 if permission is granted.
-  * @inode_listxattr:
-  *    Check permission before obtaining the list of extended attribute 
-- *    names for @dentry.
-+ *    names for @dentry and @mnt.
-  *    Return 0 if permission is granted.
-  * @inode_removexattr:
-  *    Check permission before removing the extended attribute
-@@ -1286,32 +1298,45 @@ struct security_operations {
-       void (*inode_free_security) (struct inode *inode);
-       int (*inode_init_security) (struct inode *inode, struct inode *dir,
-                                   char **name, void **value, size_t *len);
--      int (*inode_create) (struct inode *dir,
--                           struct dentry *dentry, int mode);
--      int (*inode_link) (struct dentry *old_dentry,
--                         struct inode *dir, struct dentry *new_dentry);
--      int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
--      int (*inode_symlink) (struct inode *dir,
--                            struct dentry *dentry, const char *old_name);
--      int (*inode_mkdir) (struct inode *dir, struct dentry *dentry, int mode);
--      int (*inode_rmdir) (struct inode *dir, struct dentry *dentry);
-+      int (*inode_create) (struct inode *dir, struct dentry *dentry,
-+                           struct vfsmount *mnt, int mode);
-+      int (*inode_link) (struct dentry *old_dentry, struct vfsmount *old_mnt,
-+                         struct inode *dir, struct dentry *new_dentry,
-+                         struct vfsmount *new_mnt);
-+      int (*inode_unlink) (struct inode *dir, struct dentry *dentry,
-+                           struct vfsmount *mnt);
-+      int (*inode_symlink) (struct inode *dir, struct dentry *dentry,
-+                            struct vfsmount *mnt, const char *old_name);
-+      int (*inode_mkdir) (struct inode *dir, struct dentry *dentry,
-+                          struct vfsmount *mnt, int mode);
-+      int (*inode_rmdir) (struct inode *dir, struct dentry *dentry,
-+                          struct vfsmount *mnt);
-       int (*inode_mknod) (struct inode *dir, struct dentry *dentry,
--                          int mode, dev_t dev);
-+                          struct vfsmount *mnt, int mode, dev_t dev);
-       int (*inode_rename) (struct inode *old_dir, struct dentry *old_dentry,
--                           struct inode *new_dir, struct dentry *new_dentry);
--      int (*inode_readlink) (struct dentry *dentry);
-+                           struct vfsmount *old_mnt,
-+                           struct inode *new_dir, struct dentry *new_dentry,
-+                           struct vfsmount *new_mnt);
-+      int (*inode_readlink) (struct dentry *dentry, struct vfsmount *mnt);
-       int (*inode_follow_link) (struct dentry *dentry, struct nameidata *nd);
-       int (*inode_permission) (struct inode *inode, int mask, struct nameidata *nd);
--      int (*inode_setattr)    (struct dentry *dentry, struct iattr *attr);
-+      int (*inode_setattr) (struct dentry *dentry, struct vfsmount *mnt,
-+                            struct iattr *attr);
-       int (*inode_getattr) (struct vfsmount *mnt, struct dentry *dentry);
-         void (*inode_delete) (struct inode *inode);
--      int (*inode_setxattr) (struct dentry *dentry, char *name, void *value,
--                             size_t size, int flags);
--      void (*inode_post_setxattr) (struct dentry *dentry, char *name, void *value,
-+      int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
-+                             char *name, void *value, size_t size, int flags,
-+                             struct file *file);
-+      void (*inode_post_setxattr) (struct dentry *dentry,
-+                                   struct vfsmount *mnt,
-+                                   char *name, void *value,
-                                    size_t size, int flags);
--      int (*inode_getxattr) (struct dentry *dentry, char *name);
--      int (*inode_listxattr) (struct dentry *dentry);
--      int (*inode_removexattr) (struct dentry *dentry, char *name);
-+      int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
-+                             char *name, struct file *file);
-+      int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt,
-+                              struct file *file);
-+      int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
-+                                char *name, struct file *file);
-       int (*inode_need_killpriv) (struct dentry *dentry);
-       int (*inode_killpriv) (struct dentry *dentry);
-       int (*inode_getsecurity)(const struct inode *inode, const char *name, void **buffer, bool alloc);
-@@ -1549,30 +1574,43 @@ int security_inode_alloc(struct inode *i
- void security_inode_free(struct inode *inode);
- int security_inode_init_security(struct inode *inode, struct inode *dir,
-                                 char **name, void **value, size_t *len);
--int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
--int security_inode_link(struct dentry *old_dentry, struct inode *dir,
--                       struct dentry *new_dentry);
--int security_inode_unlink(struct inode *dir, struct dentry *dentry);
-+int security_inode_create(struct inode *dir, struct dentry *dentry,
-+                        struct vfsmount *mnt, int mode);
-+int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
-+                      struct inode *dir, struct dentry *new_dentry,
-+                      struct vfsmount *new_mnt);
-+int security_inode_unlink(struct inode *dir, struct dentry *dentry,
-+                        struct vfsmount *mnt);
- int security_inode_symlink(struct inode *dir, struct dentry *dentry,
--                          const char *old_name);
--int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode);
--int security_inode_rmdir(struct inode *dir, struct dentry *dentry);
--int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev);
-+                         struct vfsmount *mnt, const char *old_name);
-+int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
-+                       struct vfsmount *mnt, int mode);
-+int security_inode_rmdir(struct inode *dir, struct dentry *dentry,
-+                       struct vfsmount *mnt);
-+int security_inode_mknod(struct inode *dir, struct dentry *dentry,
-+                       struct vfsmount *mnt, int mode, dev_t dev);
- int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
--                         struct inode *new_dir, struct dentry *new_dentry);
--int security_inode_readlink(struct dentry *dentry);
-+                        struct vfsmount *old_mnt, struct inode *new_dir,
-+                        struct dentry *new_dentry, struct vfsmount *new_mnt);
-+int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt);
- int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd);
- int security_inode_permission(struct inode *inode, int mask, struct nameidata *nd);
--int security_inode_setattr(struct dentry *dentry, struct iattr *attr);
-+int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
-+                         struct iattr *attr);
- int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry);
- void security_inode_delete(struct inode *inode);
--int security_inode_setxattr(struct dentry *dentry, char *name,
--                           void *value, size_t size, int flags);
--void security_inode_post_setxattr(struct dentry *dentry, char *name,
--                                 void *value, size_t size, int flags);
--int security_inode_getxattr(struct dentry *dentry, char *name);
--int security_inode_listxattr(struct dentry *dentry);
--int security_inode_removexattr(struct dentry *dentry, char *name);
-+int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
-+                          char *name, void *value, size_t size, int flags,
-+                          struct file *file);
-+void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
-+                                char *name, void *value, size_t size,
-+                                int flags);
-+int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
-+                          char *name, struct file *file);
-+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
-+                           struct file *file);
-+int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
-+                             char *name, struct file *file);
- int security_inode_need_killpriv(struct dentry *dentry);
- int security_inode_killpriv(struct dentry *dentry);
- int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
-@@ -1887,26 +1925,31 @@ static inline int security_inode_init_se
-       
- static inline int security_inode_create (struct inode *dir,
-                                        struct dentry *dentry,
-+                                       struct vfsmount *mnt,
-                                        int mode)
- {
-       return 0;
- }
- static inline int security_inode_link (struct dentry *old_dentry,
-+                                     struct vfsmount *old_mnt,
-                                      struct inode *dir,
--                                     struct dentry *new_dentry)
-+                                     struct dentry *new_dentry,
-+                                     struct vfsmount *new_mnt)
- {
-       return 0;
- }
- static inline int security_inode_unlink (struct inode *dir,
--                                       struct dentry *dentry)
-+                                       struct dentry *dentry,
-+                                       struct vfsmount *mnt)
- {
-       return 0;
- }
- static inline int security_inode_symlink (struct inode *dir,
-                                         struct dentry *dentry,
-+                                        struct vfsmount *mnt,
-                                         const char *old_name)
- {
-       return 0;
-@@ -1914,19 +1957,22 @@ static inline int security_inode_symlink
- static inline int security_inode_mkdir (struct inode *dir,
-                                       struct dentry *dentry,
-+                                      struct vfsmount *mnt,
-                                       int mode)
- {
-       return 0;
- }
- static inline int security_inode_rmdir (struct inode *dir,
--                                      struct dentry *dentry)
-+                                      struct dentry *dentry,
-+                                      struct vfsmount *mnt)
- {
-       return 0;
- }
- static inline int security_inode_mknod (struct inode *dir,
-                                       struct dentry *dentry,
-+                                      struct vfsmount *mnt,
-                                       int mode, dev_t dev)
- {
-       return 0;
-@@ -1934,13 +1980,16 @@ static inline int security_inode_mknod (
- static inline int security_inode_rename (struct inode *old_dir,
-                                        struct dentry *old_dentry,
-+                                       struct vfsmount *old_mnt,
-                                        struct inode *new_dir,
--                                       struct dentry *new_dentry)
-+                                       struct dentry *new_dentry,
-+                                       struct vfsmount *new_mnt)
- {
-       return 0;
- }
--static inline int security_inode_readlink (struct dentry *dentry)
-+static inline int security_inode_readlink(struct dentry *dentry,
-+                                         struct vfsmount *mnt)
- {
-       return 0;
- }
-@@ -1958,6 +2007,7 @@ static inline int security_inode_permiss
- }
- static inline int security_inode_setattr (struct dentry *dentry,
-+                                        struct vfsmount *mnt,
-                                         struct iattr *attr)
- {
-       return 0;
-@@ -1972,29 +2022,40 @@ static inline int security_inode_getattr
- static inline void security_inode_delete (struct inode *inode)
- { }
--static inline int security_inode_setxattr (struct dentry *dentry, char *name,
--                                         void *value, size_t size, int flags)
--{
--      return cap_inode_setxattr(dentry, name, value, size, flags);
-+static inline int security_inode_setxattr (struct dentry *dentry,
-+                                         struct vfsmount *mnt, char *name,
-+                                         void *value, size_t size, int flags,
-+                                         struct file *file)
-+{
-+      return cap_inode_setxattr(dentry, mnt, name, value, size, flags, file);
- }
--static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
--                                               void *value, size_t size, int flags)
-+static inline void security_inode_post_setxattr (struct dentry *dentry,
-+                                               struct vfsmount *mnt,
-+                                               char *name,
-+                                               void *value, size_t size,
-+                                               int flags)
- { }
--static inline int security_inode_getxattr (struct dentry *dentry, char *name)
-+static inline int security_inode_getxattr (struct dentry *dentry,
-+                                         struct vfsmount *mnt, char *name,
-+                                         struct file *file)
- {
-       return 0;
- }
--static inline int security_inode_listxattr (struct dentry *dentry)
-+static inline int security_inode_listxattr (struct dentry *dentry,
-+                                         struct vfsmount *mnt,
-+                                         struct file *file)
- {
-       return 0;
- }
--static inline int security_inode_removexattr (struct dentry *dentry, char *name)
-+static inline int security_inode_removexattr (struct dentry *dentry,
-+                                           struct vfsmount *mnt, char *name,
-+                                           struct file *file)
- {
--      return cap_inode_removexattr(dentry, name);
-+      return cap_inode_removexattr(dentry, mnt, name, file);
- }
- static inline int security_inode_need_killpriv(struct dentry *dentry)
-diff -uprN e/include/linux/sysctl.h f/include/linux/sysctl.h
---- e/include/linux/sysctl.h   2008-04-17 02:49:44.000000000 +0000
-+++ f/include/linux/sysctl.h   2008-05-28 20:29:29.410207000 +0000
-@@ -977,6 +977,8 @@ extern int proc_doulongvec_minmax(struct
- extern int proc_doulongvec_ms_jiffies_minmax(struct ctl_table *table, int,
-                                     struct file *, void __user *, size_t *, loff_t *);
-+extern char *sysctl_pathname(ctl_table *, char *, int);
-+
- extern int do_sysctl (int __user *name, int nlen,
-                     void __user *oldval, size_t __user *oldlenp,
-                     void __user *newval, size_t newlen);
-diff -uprN e/include/linux/xattr.h f/include/linux/xattr.h
---- e/include/linux/xattr.h    2008-04-17 02:49:44.000000000 +0000
-+++ f/include/linux/xattr.h    2008-05-28 20:29:29.410207000 +0000
-@@ -47,10 +47,13 @@ struct xattr_handler {
- };
- ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
--ssize_t vfs_getxattr(struct dentry *, char *, void *, size_t);
--ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
--int vfs_setxattr(struct dentry *, char *, void *, size_t, int);
--int vfs_removexattr(struct dentry *, char *);
-+ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, char *, void *,
-+                   size_t, struct file *);
-+ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list,
-+                    size_t size, struct file *);
-+int vfs_setxattr(struct dentry *, struct vfsmount *, char *, void *, size_t,
-+               int, struct file *);
-+int vfs_removexattr(struct dentry *, struct vfsmount *, char *, struct file *);
- ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
- ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
-diff -uprN e/ipc/mqueue.c f/ipc/mqueue.c
---- e/ipc/mqueue.c     2008-04-17 02:49:44.000000000 +0000
-+++ f/ipc/mqueue.c     2008-05-28 20:29:28.910241000 +0000
-@@ -743,7 +743,7 @@ asmlinkage long sys_mq_unlink(const char
-       if (inode)
-               atomic_inc(&inode->i_count);
--      err = vfs_unlink(dentry->d_parent->d_inode, dentry, NULL);
-+      err = vfs_unlink(dentry->d_parent->d_inode, dentry, NULL, mqueue_mnt);
- out_err:
-       dput(dentry);
-diff -uprN e/kernel/audit.c f/kernel/audit.c
---- e/kernel/audit.c   2008-04-17 02:49:44.000000000 +0000
-+++ f/kernel/audit.c   2008-05-28 20:29:29.410207000 +0000
-@@ -1136,8 +1136,7 @@ static inline int audit_expand(struct au
-  * will be called a second time.  Currently, we assume that a printk
-  * can't format message larger than 1024 bytes, so we don't either.
-  */
--static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
--                            va_list args)
-+void audit_log_vformat(struct audit_buffer *ab, const char *fmt, va_list args)
- {
-       int len, avail;
-       struct sk_buff *skb;
-@@ -1407,3 +1406,6 @@ EXPORT_SYMBOL(audit_log_start);
- EXPORT_SYMBOL(audit_log_end);
- EXPORT_SYMBOL(audit_log_format);
- EXPORT_SYMBOL(audit_log);
-+EXPORT_SYMBOL_GPL(audit_log_vformat);
-+EXPORT_SYMBOL_GPL(audit_log_untrustedstring);
-+EXPORT_SYMBOL_GPL(audit_log_d_path);
-diff -uprN e/kernel/cgroup.c f/kernel/cgroup.c
---- e/kernel/cgroup.c  2008-05-28 20:32:27.897940261 +0000
-+++ f/kernel/cgroup.c  2008-05-28 20:29:28.910241000 +0000
-@@ -2833,7 +2833,7 @@ int cgroup_clone(struct task_struct *tsk
-       }
-       /* Create the cgroup directory, which also creates the cgroup */
--      ret = vfs_mkdir(inode, dentry, S_IFDIR | 0755, NULL);
-+      ret = vfs_mkdir(inode, dentry, NULL, S_IFDIR | 0755, NULL);
-       child = __d_cgrp(dentry);
-       dput(dentry);
-       if (ret) {
-diff -uprN e/kernel/sysctl.c f/kernel/sysctl.c
---- e/kernel/sysctl.c  2008-04-17 02:49:44.000000000 +0000
-+++ f/kernel/sysctl.c  2008-05-28 20:29:29.410207000 +0000
-@@ -1440,6 +1440,33 @@ void register_sysctl_root(struct ctl_tab
-       spin_unlock(&sysctl_lock);
- }
-+char *sysctl_pathname(struct ctl_table *table, char *buffer, int buflen)
-+{
-+      if (buflen < 1)
-+              return NULL;
-+      buffer += --buflen;
-+      *buffer = '\0';
-+
-+      while (table) {
-+              int namelen = strlen(table->procname);
-+
-+              if (buflen < namelen + 1)
-+                      return NULL;
-+              buflen -= namelen + 1;
-+              buffer -= namelen;
-+              memcpy(buffer, table->procname, namelen);
-+              *--buffer = '/';
-+              table = table->parent;
-+      }
-+      if (buflen < 4)
-+              return NULL;
-+      buffer -= 4;
-+      memcpy(buffer, "/sys", 4);
-+
-+      return buffer;
-+}
-+EXPORT_SYMBOL_GPL(sysctl_pathname);
-+
- #ifdef CONFIG_SYSCTL_SYSCALL
- int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
-              void __user *newval, size_t newlen)
-diff -uprN e/mm/filemap.c f/mm/filemap.c
---- e/mm/filemap.c     2008-04-17 02:49:44.000000000 +0000
-+++ f/mm/filemap.c     2008-05-28 20:29:28.910241000 +0000
-@@ -1653,26 +1653,26 @@ int should_remove_suid(struct dentry *de
- }
- EXPORT_SYMBOL(should_remove_suid);
--int __remove_suid(struct dentry *dentry, int kill)
-+int __remove_suid(struct path *path, int kill)
- {
-       struct iattr newattrs;
-       newattrs.ia_valid = ATTR_FORCE | kill;
--      return notify_change(dentry, &newattrs);
-+      return notify_change(path->dentry, path->mnt, &newattrs);
- }
--int remove_suid(struct dentry *dentry)
-+int remove_suid(struct path *path)
- {
--      int killsuid = should_remove_suid(dentry);
--      int killpriv = security_inode_need_killpriv(dentry);
-+      int killsuid = should_remove_suid(path->dentry);
-+      int killpriv = security_inode_need_killpriv(path->dentry);
-       int error = 0;
-       if (killpriv < 0)
-               return killpriv;
-       if (killpriv)
--              error = security_inode_killpriv(dentry);
-+              error = security_inode_killpriv(path->dentry);
-       if (!error && killsuid)
--              error = __remove_suid(dentry, killsuid);
-+              error = __remove_suid(path, killsuid);
-       return error;
- }
-@@ -2387,7 +2387,7 @@ __generic_file_aio_write_nolock(struct k
-       if (count == 0)
-               goto out;
--      err = remove_suid(file->f_path.dentry);
-+      err = remove_suid(&file->f_path);
-       if (err)
-               goto out;
-diff -uprN e/mm/filemap_xip.c f/mm/filemap_xip.c
---- e/mm/filemap_xip.c 2008-04-17 02:49:44.000000000 +0000
-+++ f/mm/filemap_xip.c 2008-05-28 20:29:28.910241000 +0000
-@@ -380,7 +380,7 @@ xip_file_write(struct file *filp, const 
-       if (count == 0)
-               goto out_backing;
--      ret = remove_suid(filp->f_path.dentry);
-+      ret = remove_suid(&filp->f_path);
-       if (ret)
-               goto out_backing;
-diff -uprN e/mm/tiny-shmem.c f/mm/tiny-shmem.c
---- e/mm/tiny-shmem.c  2008-04-17 02:49:44.000000000 +0000
-+++ f/mm/tiny-shmem.c  2008-05-28 20:29:28.910241000 +0000
-@@ -80,7 +80,7 @@ struct file *shmem_file_setup(char *name
-       inode->i_nlink = 0;     /* It is unlinked */
-       /* notify everyone as to the change of file size */
--      error = do_truncate(dentry, size, 0, file);
-+      error = do_truncate(dentry, file->f_path.mnt, size, 0, file);
-       if (error < 0)
-               goto close_file;
-diff -uprN e/net/unix/af_unix.c f/net/unix/af_unix.c
---- e/net/unix/af_unix.c       2008-04-17 02:49:44.000000000 +0000
-+++ f/net/unix/af_unix.c       2008-05-28 20:29:28.910241000 +0000
-@@ -819,7 +819,8 @@ static int unix_bind(struct socket *sock
-                */
-               mode = S_IFSOCK |
-                      (SOCK_INODE(sock)->i_mode & ~current->fs->umask);
--              err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0, NULL);
-+              err = vfs_mknod(nd.path.dentry->d_inode, dentry, nd.path.mnt,
-+                              mode, 0, NULL);
-               if (err)
-                       goto out_mknod_dput;
-               mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-diff -uprN e/security/Kconfig f/security/Kconfig
---- e/security/Kconfig 2008-04-17 02:49:44.000000000 +0000
-+++ f/security/Kconfig 2008-05-28 20:29:29.410207000 +0000
-@@ -124,6 +124,7 @@ config SECURITY_DEFAULT_MMAP_MIN_ADDR
- source security/selinux/Kconfig
- source security/smack/Kconfig
-+source security/apparmor/Kconfig
- endmenu
-diff -uprN e/security/Makefile f/security/Makefile
---- e/security/Makefile        2008-04-17 02:49:44.000000000 +0000
-+++ f/security/Makefile        2008-05-28 20:29:29.410207000 +0000
-@@ -16,5 +16,6 @@ obj-$(CONFIG_SECURITY)                       += security.o d
- # Must precede capability.o in order to stack properly.
- obj-$(CONFIG_SECURITY_SELINUX)                += selinux/built-in.o
- obj-$(CONFIG_SECURITY_SMACK)          += commoncap.o smack/built-in.o
-+obj-$(CONFIG_SECURITY_APPARMOR)               += commoncap.o apparmor/
- obj-$(CONFIG_SECURITY_CAPABILITIES)   += commoncap.o capability.o
- obj-$(CONFIG_SECURITY_ROOTPLUG)               += commoncap.o root_plug.o
-diff -uprN e/security/apparmor/Kconfig f/security/apparmor/Kconfig
---- e/security/apparmor/Kconfig        1970-01-01 00:00:00.000000000 +0000
-+++ f/security/apparmor/Kconfig        2008-05-28 20:29:29.410207000 +0000
-@@ -0,0 +1,42 @@
-+config SECURITY_APPARMOR
-+      bool "AppArmor support"
-+      depends on SECURITY
-+      select AUDIT
-+      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://forge.novell.com/modules/xfmod/project/?apparmor>
-+
-+        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
-+        bootup.  If this option is set to 1 (one), the AppArmor
-+        kernel parameter will default to 1, enabling AppArmor at
-+        bootup.
-+
-+        If you are unsure how to answer this question, answer 1.
-+
-+config SECURITY_APPARMOR_DISABLE
-+      bool "AppArmor runtime disable"
-+      depends on SECURITY_APPARMOR
-+      default n
-+      help
-+        This option enables writing to a apparmorfs node 'disable', which
-+        allows AppArmor to be disabled at runtime prior to the policy load.
-+        AppArmor will then remain disabled until the next boot.
-+        This option is similar to the apparmor.enabled=0 boot parameter,
-+        but is to support runtime disabling of AppArmor, e.g. from
-+        /sbin/init, for portability across platforms where boot
-+        parameters are difficult to employ.
-+
-+        If you are unsure how to answer this question, answer N.
-diff -uprN e/security/apparmor/Makefile f/security/apparmor/Makefile
---- e/security/apparmor/Makefile       1970-01-01 00:00:00.000000000 +0000
-+++ f/security/apparmor/Makefile       2008-05-28 20:29:29.410207000 +0000
-@@ -0,0 +1,18 @@
-+# Makefile for AppArmor Linux Security Module
-+#
-+obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
-+
-+apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o \
-+            module_interface.o match.o
-+
-+quiet_cmd_make-caps = GEN     $@
-+cmd_make-caps = 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 > $@
-+
-+quiet_cmd_make-af = GEN     $@
-+cmd_make-af = 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 > $@
-+
-+$(obj)/main.o : $(obj)/capability_names.h $(obj)/af_names.h
-+$(obj)/capability_names.h : $(srctree)/include/linux/capability.h
-+      $(call cmd,make-caps)
-+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
-+      $(call cmd,make-af)
-diff -uprN e/security/apparmor/apparmor.h f/security/apparmor/apparmor.h
---- e/security/apparmor/apparmor.h     1970-01-01 00:00:00.000000000 +0000
-+++ f/security/apparmor/apparmor.h     2008-05-28 20:29:29.410207000 +0000
-@@ -0,0 +1,403 @@
-+/*
-+ *    Copyright (C) 1998-2007 Novell/SUSE
-+ *
-+ *    This program is free software; you can redistribute it and/or
-+ *    modify it under the terms of the GNU General Public License as
-+ *    published by the Free Software Foundation, version 2 of the
-+ *    License.
-+ *
-+ *    AppArmor internal prototypes
-+ */
-+
-+#ifndef __APPARMOR_H
-+#define __APPARMOR_H
-+
-+#include <linux/sched.h>
-+#include <linux/fs.h>
-+#include <linux/binfmts.h>
-+#include <linux/rcupdate.h>
-+#include <linux/resource.h>
-+#include <linux/socket.h>
-+#include <net/sock.h>
-+
-+/*
-+ * We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
-+ * for profile permissions
-+ */
-+#define AA_MAY_LINK                   0x0010
-+#define AA_MAY_LOCK                   0x0020
-+#define AA_EXEC_MMAP                  0x0040
-+#define AA_MAY_MOUNT                  0x0080  /* no direct audit mapping */
-+#define AA_EXEC_UNSAFE                        0x0100
-+#define AA_EXEC_INHERIT                       0x0200
-+#define AA_EXEC_MOD_0                 0x0400
-+#define AA_EXEC_MOD_1                 0x0800
-+#define AA_EXEC_MOD_2                 0x1000
-+#define AA_EXEC_MOD_3                 0x2000
-+
-+#define AA_BASE_PERMS                 (MAY_READ | MAY_WRITE | MAY_EXEC | \
-+                                       MAY_APPEND | AA_MAY_LINK | \
-+                                       AA_MAY_LOCK | AA_EXEC_MMAP | \
-+                                       AA_MAY_MOUNT | AA_EXEC_UNSAFE | \
-+                                       AA_EXEC_INHERIT | AA_EXEC_MOD_0 | \
-+                                       AA_EXEC_MOD_1 | AA_EXEC_MOD_2 | \
-+                                       AA_EXEC_MOD_3)
-+
-+#define AA_EXEC_MODIFIERS             (AA_EXEC_MOD_0 | AA_EXEC_MOD_1 | \
-+                                       AA_EXEC_MOD_2 | AA_EXEC_MOD_3)
-+
-+#define AA_EXEC_TYPE                  (AA_EXEC_UNSAFE | AA_EXEC_INHERIT | \
-+                                       AA_EXEC_MODIFIERS)
-+
-+#define AA_EXEC_UNCONFINED            AA_EXEC_MOD_0
-+#define AA_EXEC_PROFILE                       AA_EXEC_MOD_1
-+#define AA_EXEC_CHILD                 (AA_EXEC_MOD_0 | AA_EXEC_MOD_1)
-+/* remaining exec modes are index into profile name table */
-+#define AA_EXEC_INDEX(mode)           ((mode & AA_EXEC_MODIFIERS) >> 10)
-+
-+#define AA_USER_SHIFT                 0
-+#define AA_OTHER_SHIFT                        14
-+
-+#define AA_USER_PERMS                 (AA_BASE_PERMS << AA_USER_SHIFT)
-+#define AA_OTHER_PERMS                        (AA_BASE_PERMS << AA_OTHER_SHIFT)
-+
-+#define AA_FILE_PERMS                 (AA_USER_PERMS | AA_OTHER_PERMS)
-+
-+#define AA_LINK_BITS                  ((AA_MAY_LINK << AA_USER_SHIFT) | \
-+                                       (AA_MAY_LINK << AA_OTHER_SHIFT))
-+
-+#define AA_USER_EXEC                  (MAY_EXEC << AA_USER_SHIFT)
-+#define AA_OTHER_EXEC                 (MAY_EXEC << AA_OTHER_SHIFT)
-+
-+#define AA_USER_EXEC_TYPE             (AA_EXEC_TYPE << AA_USER_SHIFT)
-+#define AA_OTHER_EXEC_TYPE            (AA_EXEC_TYPE << AA_OTHER_SHIFT)
-+
-+#define AA_EXEC_BITS                  (AA_USER_EXEC | AA_OTHER_EXEC)
-+
-+#define ALL_AA_EXEC_UNSAFE            ((AA_EXEC_UNSAFE << AA_USER_SHIFT) | \
-+                                       (AA_EXEC_UNSAFE << AA_OTHER_SHIFT))
-+
-+#define ALL_AA_EXEC_TYPE              (AA_USER_EXEC_TYPE | AA_OTHER_EXEC_TYPE)
-+
-+/* overloaded permissions for link pairs */
-+#define AA_LINK_SUBSET_TEST           0x0020
-+
-+#define AA_USER_PTRACE                        0x10000000
-+#define AA_OTHER_PTRACE                       0x20000000
-+#define AA_PTRACE_PERMS                       (AA_USER_PTRACE | AA_OTHER_PTRACE)
-+
-+/* shared permissions that are not duplicated in user::other */
-+#define AA_CHANGE_HAT                 0x40000000
-+#define AA_CHANGE_PROFILE             0x80000000
-+
-+#define AA_SHARED_PERMS                       (AA_CHANGE_HAT | AA_CHANGE_PROFILE)
-+
-+#define AA_VALID_PERM_MASK            (AA_FILE_PERMS | AA_PTRACE_PERMS | \
-+                                       AA_SHARED_PERMS)
-+
-+/* audit bits for the second accept field */
-+#define AUDIT_FILE_MASK 0x1fc07f
-+#define AUDIT_QUIET_MASK(mask)                ((mask >> 7) & AUDIT_FILE_MASK)
-+#define AA_VALID_PERM2_MASK           0x0fffffff
-+
-+#define AA_SECURE_EXEC_NEEDED         1
-+
-+/* Control parameters (0 or 1), settable thru module/boot flags or
-+ * via /sys/kernel/security/apparmor/control */
-+extern int apparmor_complain;
-+extern int apparmor_debug;
-+extern int apparmor_audit;
-+extern int apparmor_logsyscall;
-+extern unsigned int apparmor_path_max;
-+
-+#define PROFILE_COMPLAIN(_profile) \
-+      (apparmor_complain == 1 || ((_profile) && (_profile)->flags.complain))
-+
-+#define APPARMOR_COMPLAIN(_cxt) \
-+      (apparmor_complain == 1 || \
-+       ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.complain))
-+
-+#define PROFILE_AUDIT(_profile) \
-+      (apparmor_audit == 1 || ((_profile) && (_profile)->flags.audit))
-+
-+#define APPARMOR_AUDIT(_cxt) \
-+      (apparmor_audit == 1 || \
-+       ((_cxt) && (_cxt)->profile && (_cxt)->profile->flags.audit))
-+
-+#define PROFILE_IS_HAT(_profile) \
-+      ((_profile) && (_profile)->flags.hat)
-+
-+/*
-+ * 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 (apparmor_debug)                                     \
-+                      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)
-+
-+/* struct aa_rlimit - rlimits 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];
-+};
-+
-+struct aa_profile;
-+
-+/* struct aa_namespace - namespace for a set of profiles
-+ * @name: the name of the namespace
-+ * @list: list the namespace is on
-+ * @profiles: list of profile in the namespace
-+ * @profile_count: the number of profiles in the namespace
-+ * @null_complain_profile: special profile used for learning in this namespace
-+ * @count: reference count on the namespace
-+ * @lock: lock for adding/removing profile to the namespace
-+ */
-+struct aa_namespace {
-+      char *name;
-+      struct list_head list;
-+      struct list_head profiles;
-+      int profile_count;
-+      struct aa_profile *null_complain_profile;
-+
-+      struct kref count;
-+      rwlock_t lock;
-+};
-+
-+/* struct aa_profile - basic confinement data
-+ * @name: the profiles name
-+ * @list: list this profile is on
-+ * @ns: namespace the profile is in
-+ * @file_rules: dfa containing the profiles file rules
-+ * @flags: flags controlling profile behavior
-+ * @isstale: flag indicating if profile is stale
-+ * @set_caps: capabilities that are being set
-+ * @capabilities: capabilities mask
-+ * @audit_caps: caps that are to be audited
-+ * @quiet_caps: caps that should not be audited
-+ * @capabilities: capabilities granted by the process
-+ * @rlimits: rlimits for the profile
-+ * @task_count: how many tasks the profile is attached to
-+ * @count: reference count of the profile
-+ * @task_contexts: list of tasks confined by profile
-+ * @lock: lock for the task_contexts list
-+ * @network_families: basic network permissions
-+ * @audit_network: which network permissions to force audit
-+ * @quiet_network: which network permissions to quiet rejects
-+ *
-+ * The AppArmor profile contains the basic confinement data.  Each profile
-+ * has a name, and all nonstale profile are in a profile namespace.
-+ *
-+ * The task_contexts list and the isstale flag are protected by the
-+ * profile lock.
-+ *
-+ * If a task context is moved between two profiles, we first need to grab
-+ * both profile locks. lock_both_profiles() does that in a deadlock-safe
-+ * way.
-+ */
-+struct aa_profile {
-+      char *name;
-+      struct list_head list;
-+      struct aa_namespace *ns;
-+
-+      int exec_table_size;
-+      char **exec_table;
-+      struct aa_dfa *file_rules;
-+      struct {
-+              int hat;
-+              int complain;
-+              int audit;
-+      } flags;
-+      int isstale;
-+
-+      kernel_cap_t set_caps;
-+      kernel_cap_t capabilities;
-+      kernel_cap_t audit_caps;
-+      kernel_cap_t quiet_caps;
-+
-+      struct aa_rlimit rlimits;
-+      unsigned int task_count;
-+
-+      struct kref count;
-+      struct list_head task_contexts;
-+      spinlock_t lock;
-+      unsigned long int_flags;
-+      u16 network_families[AF_MAX];
-+      u16 audit_network[AF_MAX];
-+      u16 quiet_network[AF_MAX];
-+};
-+
-+extern struct list_head profile_ns_list;
-+extern rwlock_t profile_ns_list_lock;
-+extern struct mutex aa_interface_lock;
-+
-+/**
-+ * struct aa_task_context - primary label for confined tasks
-+ * @profile: the current profile
-+ * @previous_profile: profile the task may return to
-+ * @cookie: magic value the task must know for returning to @previous_profile
-+ * @list: list this aa_task_context is on
-+ * @task: task that the aa_task_context confines
-+ * @rcu: rcu head used when freeing the aa_task_context
-+ * @caps_logged: caps that have previously generated log entries
-+ *
-+ * Contains the task's current profile (which could change due to
-+ * change_hat).  Plus the hat_magic needed during change_hat.
-+ */
-+struct aa_task_context {
-+      struct aa_profile *profile;
-+      struct aa_profile *previous_profile;
-+      u64 cookie;
-+      struct list_head list;
-+      struct task_struct *task;
-+      struct rcu_head rcu;
-+      kernel_cap_t caps_logged;
-+};
-+
-+extern struct aa_namespace *default_namespace;
-+
-+/* aa_audit - AppArmor auditing structure
-+ * Structure is populated by access control code and passed to aa_audit which
-+ * provides for a single point of logging.
-+ */
-+
-+struct aa_audit {
-+      const char *operation;
-+      gfp_t gfp_mask;
-+      const char *info;
-+      const char *name;
-+      const char *name2;
-+      const char *name3;
-+      int request_mask, denied_mask, audit_mask;
-+      int rlimit;
-+      struct iattr *iattr;
-+      pid_t task, parent;
-+      int family, type, protocol;
-+      int error_code;
-+};
-+
-+/* Flags for the permission check functions */
-+#define AA_CHECK_FD   1  /* coming from a file descriptor */
-+#define AA_CHECK_DIR  2  /* file type is directory */
-+
-+/* lock subtypes so lockdep does not raise false dependencies */
-+enum aa_lock_class {
-+      aa_lock_normal,
-+      aa_lock_nested,
-+      aa_lock_task_release
-+};
-+
-+/* main.c */
-+extern int alloc_default_namespace(void);
-+extern void free_default_namespace(void);
-+extern int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa,
-+                          int type);
-+void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa);
-+void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa);
-+int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa);
-+extern int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
-+                                const char *);
-+extern int aa_audit(struct aa_profile *profile, struct aa_audit *);
-+
-+extern int aa_attr(struct aa_profile *profile, struct dentry *dentry,
-+                 struct vfsmount *mnt, struct iattr *iattr);
-+extern int aa_perm_xattr(struct aa_profile *profile, const char *operation,
-+                       struct dentry *dentry, struct vfsmount *mnt,
-+                       int mask, int check);
-+extern int aa_capability(struct aa_task_context *cxt, int cap);
-+extern int aa_perm(struct aa_profile *profile, const char *operation,
-+                 struct dentry *dentry, struct vfsmount *mnt, int mask,
-+                 int check);
-+extern int aa_perm_dir(struct aa_profile *profile, const char *operation,
-+                     struct dentry *dentry, struct vfsmount *mnt,
-+                     int mask);
-+extern int aa_perm_path(struct aa_profile *, const char *operation,
-+                      const char *name, int mask, uid_t uid);
-+extern int aa_link(struct aa_profile *profile,
-+                 struct dentry *link, struct vfsmount *link_mnt,
-+                 struct dentry *target, struct vfsmount *target_mnt);
-+extern int aa_clone(struct task_struct *task);
-+extern int aa_register(struct linux_binprm *bprm);
-+extern void aa_release(struct task_struct *task);
-+extern int aa_change_hat(const char *id, u64 hat_magic);
-+extern int aa_change_profile(const char *ns_name, const char *name);
-+extern struct aa_profile *__aa_replace_profile(struct task_struct *task,
-+                                             struct aa_profile *profile);
-+extern struct aa_task_context *lock_task_and_profiles(struct task_struct *task,
-+                                                    struct aa_profile *profile);
-+extern void unlock_task_and_profiles(struct task_struct *task,
-+                                   struct aa_task_context *cxt,
-+                                   struct aa_profile *profile);
-+extern void aa_change_task_context(struct task_struct *task,
-+                                 struct aa_task_context *new_cxt,
-+                                 struct aa_profile *profile, u64 cookie,
-+                                 struct aa_profile *previous_profile);
-+extern int aa_may_ptrace(struct aa_task_context *cxt,
-+                       struct aa_profile *tracee);
-+extern int aa_net_perm(struct aa_profile *profile, char *operation,
-+                      int family, int type, int protocol);
-+extern int aa_revalidate_sk(struct sock *sk, char *operation);
-+extern int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
-+                           struct rlimit *new_rlim);
-+extern void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile);
-+
-+
-+/* lsm.c */
-+extern int apparmor_initialized;
-+extern void info_message(const char *str, const char *name);
-+extern void apparmor_disable(void);
-+
-+/* list.c */
-+extern struct aa_namespace *__aa_find_namespace(const char *name,
-+                                              struct list_head *list);
-+extern struct aa_profile *__aa_find_profile(const char *name,
-+                                          struct list_head *list);
-+extern void aa_profile_ns_list_release(void);
-+
-+/* module_interface.c */
-+extern ssize_t aa_add_profile(void *, size_t);
-+extern ssize_t aa_replace_profile(void *, size_t);
-+extern ssize_t aa_remove_profile(char *, size_t);
-+extern struct aa_namespace *alloc_aa_namespace(char *name);
-+extern void free_aa_namespace(struct aa_namespace *ns);
-+extern void free_aa_namespace_kref(struct kref *kref);
-+extern struct aa_profile *alloc_aa_profile(void);
-+extern void free_aa_profile(struct aa_profile *profile);
-+extern void free_aa_profile_kref(struct kref *kref);
-+extern void aa_unconfine_tasks(struct aa_profile *profile);
-+
-+/* procattr.c */
-+extern int aa_getprocattr(struct aa_profile *profile, char **string,
-+                        unsigned *len);
-+extern int aa_setprocattr_changehat(char *args);
-+extern int aa_setprocattr_changeprofile(char *args);
-+extern int aa_setprocattr_setprofile(struct task_struct *task, char *args);
-+
-+/* apparmorfs.c */
-+extern int create_apparmorfs(void);
-+extern void destroy_apparmorfs(void);
-+
-+/* match.c */
-+extern struct aa_dfa *aa_match_alloc(void);
-+extern void aa_match_free(struct aa_dfa *dfa);
-+extern int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size);
-+extern int verify_dfa(struct aa_dfa *dfa);
-+extern unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *);
-+extern unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
-+                                    const char *str);
-+extern unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
-+                                 const char *str, unsigned int *final);
-+extern unsigned int aa_dfa_null_transition(struct aa_dfa *dfa,
-+                                         unsigned int start);
-+
-+#endif  /* __APPARMOR_H */
-diff -uprN e/security/apparmor/apparmorfs.c f/security/apparmor/apparmorfs.c
---- e/security/apparmor/apparmorfs.c   1970-01-01 00:00:00.000000000 +0000
-+++ f/security/apparmor/apparmorfs.c   2008-05-28 20:29:29.410207000 +0000
-@@ -0,0 +1,279 @@
-+/*
-+ *    Copyright (C) 1998-2007 Novell/SUSE
-+ *
-+ *    This program is free software; you can redistribute it and/or
-+ *    modify it under the terms of the GNU General Public License as
-+ *    published by the Free Software Foundation, version 2 of the
-+ *
-+ *    AppArmor filesystem (part of securityfs)
-+ */
-+
-+#include <linux/security.h>
-+#include <linux/vmalloc.h>
-+#include <linux/module.h>
-+#include <linux/seq_file.h>
-+#include <asm/uaccess.h>
-+
-+#include "apparmor.h"
-+#include "inline.h"
-+
-+static char *aa_simple_write_to_buffer(const char __user *userbuf,
-+                                     size_t alloc_size, size_t copy_size,
-+                                     loff_t *pos, const char *operation)
-+{
-+      struct aa_profile *profile;
-+      char *data;
-+
-+      if (*pos != 0) {
-+              /* only writes from pos 0, that is complete writes */
-+              data = ERR_PTR(-ESPIPE);
-+              goto out;
-+      }
-+
-+      /*
-+       * Don't allow confined processes to load/replace/remove profiles.
-+       * No sane person would add rules allowing this to a profile
-+       * but we enforce the restriction anyways.
-+       */
-+      profile = aa_get_profile(current);
-+      if (profile) {
-+              struct aa_audit sa;
-+              memset(&sa, 0, sizeof(sa));
-+              sa.operation = operation;
-+              sa.gfp_mask = GFP_KERNEL;
-+              sa.error_code = -EACCES;
-+              data = ERR_PTR(aa_audit_reject(profile, &sa));
-+              aa_put_profile(profile);
-+              goto out;
-+      }
-+
-+      data = vmalloc(alloc_size);
-+      if (data == NULL) {
-+              data = ERR_PTR(-ENOMEM);
-+              goto out;
-+      }
-+
-+      if (copy_from_user(data, userbuf, copy_size)) {
-+              vfree(data);
-+              data = ERR_PTR(-EFAULT);
-+              goto out;
-+      }
-+
-+out:
-+      return data;
-+}
-+
-+/* apparmor/profiles */
-+extern struct seq_operations apparmorfs_profiles_op;
-+
-+static int aa_profiles_open(struct inode *inode, struct file *file)
-+{
-+      return seq_open(file, &apparmorfs_profiles_op);
-+}
-+
-+
-+static int aa_profiles_release(struct inode *inode, struct file *file)
-+{
-+      return seq_release(inode, file);
-+}
-+
-+static struct file_operations apparmorfs_profiles_fops = {
-+      .open =         aa_profiles_open,
-+      .read =         seq_read,
-+      .llseek =       seq_lseek,
-+      .release =      aa_profiles_release,
-+};
-+
-+/* 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=rwxamlk/ user::other";
-+
-+      return simple_read_from_buffer(buf, size, ppos, matching,
-+                                     strlen(matching));
-+}
-+
-+static struct file_operations apparmorfs_matching_fops = {
-+      .read =         aa_matching_read,
-+};
-+
-+/* apparmor/features */
-+static ssize_t aa_features_read(struct file *file, char __user *buf,
-+                              size_t size, loff_t *ppos)
-+{
-+      const char *features = "file=3.0 capability=2.0 network=1.0 "
-+                             "change_hat=1.4 change_profile=1.0 "
-+                             "aanamespaces=1.0 rlimit=1.0";
-+
-+      return simple_read_from_buffer(buf, size, ppos, features,
-+                                     strlen(features));
-+}
-+
-+static struct file_operations apparmorfs_features_fops = {
-+      .read =         aa_features_read,
-+};
-+
-+/* apparmor/.load */
-+static ssize_t aa_profile_load(struct file *f, const char __user *buf,
-+                             size_t size, loff_t *pos)
-+{
-+      char *data;
-+      ssize_t error;
-+
-+      data = aa_simple_write_to_buffer(buf, size, size, pos, "profile_load");
-+
-+      error = PTR_ERR(data);
-+      if (!IS_ERR(data)) {
-+              error = aa_add_profile(data, size);
-+              vfree(data);
-+      }
-+
-+      return error;
-+}
-+
-+
-+static struct file_operations apparmorfs_profile_load = {
-+      .write = aa_profile_load
-+};
-+
-+/* apparmor/.replace */
-+static ssize_t aa_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(buf, size, size, pos,
-+                                       "profile_replace");
-+
-+      error = PTR_ERR(data);
-+      if (!IS_ERR(data)) {
-+              error = aa_replace_profile(data, size);
-+              vfree(data);
-+      }
-+
-+      return error;
-+}
-+
-+
-+static struct file_operations apparmorfs_profile_replace = {
-+      .write = aa_profile_replace
-+};
-+
-+/* apparmor/.remove */
-+static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
-+                                size_t size, loff_t *pos)
-+{
-+      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(buf, size + 1, size, pos,
-+                                       "profile_remove");
-+
-+      error = PTR_ERR(data);
-+      if (!IS_ERR(data)) {
-+              data[size] = 0;
-+              error = aa_remove_profile(data, size);
-+              vfree(data);
-+      }
-+
-+      return error;
-+}
-+
-+static struct file_operations apparmorfs_profile_remove = {
-+      .write = aa_profile_remove
-+};
-+
-+static struct dentry *apparmor_dentry;
-+
-+static void aafs_remove(const char *name)
-+{
-+      struct dentry *dentry;
-+
-+      dentry = lookup_one_len(name, apparmor_dentry, strlen(name));
-+      if (!IS_ERR(dentry)) {
-+              securityfs_remove(dentry);
-+              dput(dentry);
-+      }
-+}
-+
-+static int aafs_create(const char *name, int mask, struct file_operations *fops)
-+{
-+      struct dentry *dentry;
-+
-+      dentry = securityfs_create_file(name, S_IFREG | mask, apparmor_dentry,
-+                                      NULL, fops);
-+
-+      return IS_ERR(dentry) ? PTR_ERR(dentry) : 0;
-+}
-+
-+void destroy_apparmorfs(void)
-+{
-+      if (apparmor_dentry) {
-+              aafs_remove(".remove");
-+              aafs_remove(".replace");
-+              aafs_remove(".load");
-+              aafs_remove("matching");
-+              aafs_remove("features");
-+              aafs_remove("profiles");
-+              securityfs_remove(apparmor_dentry);
-+              apparmor_dentry = NULL;
-+      }
-+}
-+
-+int create_apparmorfs(void)
-+{
-+      int error;
-+
-+      if (!apparmor_initialized)
-+              return 0;
-+
-+      if (apparmor_dentry) {
-+              AA_ERROR("%s: AppArmor securityfs already exists\n",
-+                      __FUNCTION__);
-+              return -EEXIST;
-+      }
-+
-+      apparmor_dentry = securityfs_create_dir("apparmor", NULL);
-+      if (IS_ERR(apparmor_dentry)) {
-+              error = PTR_ERR(apparmor_dentry);
-+              apparmor_dentry = NULL;
-+              goto error;
-+      }
-+      error = aafs_create("profiles", 0440, &apparmorfs_profiles_fops);
-+      if (error)
-+              goto error;
-+      error = aafs_create("matching", 0444, &apparmorfs_matching_fops);
-+      if (error)
-+              goto error;
-+      error = aafs_create("features", 0444, &apparmorfs_features_fops);
-+      if (error)
-+              goto error;
-+      error = aafs_create(".load", 0640, &apparmorfs_profile_load);
-+      if (error)
-+              goto error;
-+      error = aafs_create(".replace", 0640, &apparmorfs_profile_replace);
-+      if (error)
-+              goto error;
-+      error = aafs_create(".remove", 0640, &apparmorfs_profile_remove);
-+      if (error)
-+              goto error;
-+
-+      /* Report that AppArmor fs is enabled */
-+      info_message("AppArmor Filesystem Enabled", "");
-+      return 0;
-+
-+error:
-+      destroy_apparmorfs();
-+      AA_ERROR("Error creating AppArmor securityfs\n");
-+      apparmor_disable();
-+      return error;
-+}
-+
-+fs_initcall(create_apparmorfs);
-+
-diff -uprN e/security/apparmor/inline.h f/security/apparmor/inline.h
---- e/security/apparmor/inline.h       1970-01-01 00:00:00.000000000 +0000
-+++ f/security/apparmor/inline.h       2008-05-28 20:29:29.410207000 +0000
-@@ -0,0 +1,250 @@
-+/*
-+ *    Copyright (C) 1998-2007 Novell/SUSE
-+ *
-+ *    This program is free software; you can redistribute it and/or
-+ *    modify it under the terms of the GNU General Public License as
-+ *    published by the Free Software Foundation, version 2 of the
-+ *    License.
-+ */
-+
-+#ifndef __INLINE_H
-+#define __INLINE_H
-+
-+#include <linux/sched.h>
-+
-+#include "match.h"
-+
-+static inline int mediated_filesystem(struct inode *inode)
-+{
-+      return !(inode->i_sb->s_flags & MS_NOUSER);
-+}
-+
-+static inline struct aa_task_context *aa_task_context(struct task_struct *task)
-+{
-+      return (struct aa_task_context *) rcu_dereference(task->security);
-+}
-+
-+static inline struct aa_namespace *aa_get_namespace(struct aa_namespace *ns)
-+{
-+      if (ns)
-+              kref_get(&(ns->count));
-+
-+      return ns;
-+}
-+
-+static inline void aa_put_namespace(struct aa_namespace *ns)
-+{
-+      if (ns)
-+              kref_put(&ns->count, free_aa_namespace_kref);
-+}
-+
-+
-+static inline struct aa_namespace *aa_find_namespace(const char *name)
-+{
-+      struct aa_namespace *ns = NULL;
-+
-+      read_lock(&profile_ns_list_lock);
-+      ns = aa_get_namespace(__aa_find_namespace(name, &profile_ns_list));
-+      read_unlock(&profile_ns_list_lock);
-+
-+      return ns;
-+}
-+
-+/**
-+ * aa_dup_profile - increment refcount on profile @p
-+ * @p: profile
-+ */
-+static inline struct aa_profile *aa_dup_profile(struct aa_profile *p)
-+{
-+      if (p)
-+              kref_get(&(p->count));
-+
-+      return p;
-+}
-+
-+/**
-+ * aa_put_profile - decrement refcount on profile @p
-+ * @p: profile
-+ */
-+static inline void aa_put_profile(struct aa_profile *p)
-+{
-+      if (p)
-+              kref_put(&p->count, free_aa_profile_kref);
-+}
-+
-+static inline struct aa_profile *aa_get_profile(struct task_struct *task)
-+{
-+      struct aa_task_context *cxt;
-+      struct aa_profile *profile = NULL;
-+
-+      rcu_read_lock();
-+      cxt = aa_task_context(task);
-+      if (cxt) {
-+              profile = cxt->profile;
-+              aa_dup_profile(profile);
-+      }
-+      rcu_read_unlock();
-+
-+      return profile;
-+}
-+
-+static inline struct aa_profile *aa_find_profile(struct aa_namespace *ns,
-+                                               const char *name)
-+{
-+      struct aa_profile *profile = NULL;
-+
-+      read_lock(&ns->lock);
-+      profile = aa_dup_profile(__aa_find_profile(name, &ns->profiles));
-+      read_unlock(&ns->lock);
-+
-+      return profile;
-+}
-+
-+static inline struct aa_task_context *aa_alloc_task_context(gfp_t flags)
-+{
-+      struct aa_task_context *cxt;
-+
-+      cxt = kzalloc(sizeof(*cxt), flags);
-+      if (cxt) {
-+              INIT_LIST_HEAD(&cxt->list);
-+              INIT_RCU_HEAD(&cxt->rcu);
-+      }
-+
-+      return cxt;
-+}
-+
-+static inline void aa_free_task_context(struct aa_task_context *cxt)
-+{
-+      if (cxt) {
-+              aa_put_profile(cxt->profile);
-+              aa_put_profile(cxt->previous_profile);
-+              kfree(cxt);
-+      }
-+}
-+
-+/**
-+ * lock_profile - lock a profile
-+ * @profile: the profile to lock
-+ *
-+ * While the profile is locked, local interrupts are disabled. This also
-+ * gives us RCU reader safety.
-+ */
-+static inline void lock_profile_nested(struct aa_profile *profile,
-+                                     enum aa_lock_class lock_class)
-+{
-+      /*
-+       * Lock the profile.
-+       *
-+       * Need to disable interrupts here because this lock is used in
-+       * the task_free_security hook, which may run in RCU context.
-+       */
-+      if (profile)
-+              spin_lock_irqsave_nested(&profile->lock, profile->int_flags,
-+                                       lock_class);
-+}
-+
-+static inline void lock_profile(struct aa_profile *profile)
-+{
-+      lock_profile_nested(profile, aa_lock_normal);
-+}
-+
-+/**
-+ * unlock_profile - unlock a profile
-+ * @profile: the profile to unlock
-+ */
-+static inline void unlock_profile(struct aa_profile *profile)
-+{
-+      /* Unlock the profile. */
-+      if (profile)
-+              spin_unlock_irqrestore(&profile->lock, profile->int_flags);
-+}
-+
-+/**
-+ * lock_both_profiles  -  lock two profiles in a deadlock-free way
-+ * @profile1: profile to lock (may be NULL)
-+ * @profile2: profile to lock (may be NULL)
-+ *
-+ * The order in which profiles are passed into lock_both_profiles() /
-+ * unlock_both_profiles() does not matter.
-+ * While the profile is locked, local interrupts are disabled. This also
-+ * gives us RCU reader safety.
-+ */
-+static inline void lock_both_profiles(struct aa_profile *profile1,
-+                                    struct aa_profile *profile2)
-+{
-+      /*
-+       * Lock the two profiles.
-+       *
-+       * We need to disable interrupts because the profile locks are
-+       * used in the task_free_security hook, which may run in RCU
-+       * context.
-+       *
-+       * Do not nest spin_lock_irqsave()/spin_unlock_irqresore():
-+       * interrupts only need to be turned off once.
-+       */
-+      if (!profile1 || profile1 == profile2) {
-+              if (profile2)
-+                      spin_lock_irqsave_nested(&profile2->lock,
-+                                               profile2->int_flags,
-+                                               aa_lock_normal);
-+      } else if (profile1 > profile2) {
-+              /* profile1 cannot be NULL here. */
-+              spin_lock_irqsave_nested(&profile1->lock, profile1->int_flags,
-+                                       aa_lock_normal);
-+              if (profile2)
-+                      spin_lock_nested(&profile2->lock, aa_lock_nested);
-+
-+      } else {
-+              /* profile2 cannot be NULL here. */
-+              spin_lock_irqsave_nested(&profile2->lock, profile2->int_flags,
-+                                       aa_lock_normal);
-+              spin_lock_nested(&profile1->lock, aa_lock_nested);
-+      }
-+}
-+
-+/**
-+ * unlock_both_profiles  -  unlock two profiles in a deadlock-free way
-+ * @profile1: profile to unlock (may be NULL)
-+ * @profile2: profile to unlock (may be NULL)
-+ *
-+ * The order in which profiles are passed into lock_both_profiles() /
-+ * unlock_both_profiles() does not matter.
-+ * While the profile is locked, local interrupts are disabled. This also
-+ * gives us RCU reader safety.
-+ */
-+static inline void unlock_both_profiles(struct aa_profile *profile1,
-+                                      struct aa_profile *profile2)
-+{
-+      /* Unlock the two profiles. */
-+      if (!profile1 || profile1 == profile2) {
-+              if (profile2)
-+                      spin_unlock_irqrestore(&profile2->lock,
-+                                             profile2->int_flags);
-+      } else if (profile1 > profile2) {
-+              /* profile1 cannot be NULL here. */
-+              if (profile2)
-+                      spin_unlock(&profile2->lock);
-+              spin_unlock_irqrestore(&profile1->lock, profile1->int_flags);
-+      } else {
-+              /* profile2 cannot be NULL here. */
-+              spin_unlock(&profile1->lock);
-+              spin_unlock_irqrestore(&profile2->lock, profile2->int_flags);
-+      }
-+}
-+
-+static inline unsigned int aa_match(struct aa_dfa *dfa, const char *pathname,
-+                                  int *audit_mask)
-+{
-+      if (dfa)
-+              return aa_dfa_match(dfa, pathname, audit_mask);
-+      if (audit_mask)
-+              *audit_mask = 0;
-+      return 0;
-+}
-+
-+static inline int dfa_audit_mask(struct aa_dfa *dfa, unsigned int state)
-+{
-+      return  ACCEPT_TABLE2(dfa)[state];
-+}
-+
-+#endif /* __INLINE_H__ */
-diff -uprN e/security/apparmor/list.c f/security/apparmor/list.c
---- e/security/apparmor/list.c 1970-01-01 00:00:00.000000000 +0000
-+++ f/security/apparmor/list.c 2008-05-28 20:29:29.410207000 +0000
-@@ -0,0 +1,172 @@
-+/*
-+ *    Copyright (C) 1998-2007 Novell/SUSE
-+ *
-+ *    This program is free software; you can redistribute it and/or
-+ *    modify it under the terms of the GNU General Public License as
-+ *    published by the Free Software Foundation, version 2 of the
-+ *    License.
-+ *
-+ *    AppArmor Profile List Management
-+ */
-+
-+#include <linux/seq_file.h>
-+#include "apparmor.h"
-+#include "inline.h"
-+
-+/* list of profile namespaces and lock */
-+LIST_HEAD(profile_ns_list);
-+rwlock_t profile_ns_list_lock = RW_LOCK_UNLOCKED;
-+
-+/**
-+ * __aa_find_namespace  -  look up a profile namespace on the namespace list
-+ * @name: name of namespace to find
-+ * @head: list to search
-+ *
-+ * Returns a pointer to the namespace on the list, or NULL if no namespace
-+ * called @name exists. The caller must hold the profile_ns_list_lock.
-+ */
-+struct aa_namespace *__aa_find_namespace(const char *name,
-+                                     struct list_head *head)
-+{
-+      struct aa_namespace *ns;
-+
-+      list_for_each_entry(ns, head, list) {
-+              if (!strcmp(ns->name, name))
-+                      return ns;
-+      }
-+
-+      return NULL;
-+}
-+
-+/**
-+ * __aa_find_profile  -  look up a profile on the profile list
-+ * @name: name of profile to find
-+ * @head: list to search
-+ *
-+ * Returns a pointer to the profile on the list, or NULL if no profile
-+ * called @name exists. The caller must hold the profile_list_lock.
-+ */
-+struct aa_profile *__aa_find_profile(const char *name, struct list_head *head)
-+{
-+      struct aa_profile *profile;
-+
-+      list_for_each_entry(profile, head, list) {
-+              if (!strcmp(profile->name, name))
-+                      return profile;
-+      }
-+
-+      return NULL;
-+}
-+
-+static void aa_profile_list_release(struct list_head *head)
-+{
-+      struct aa_profile *profile, *tmp;
-+      list_for_each_entry_safe(profile, tmp, head, list) {
-+              /* Remove the profile from each task context it is on. */
-+              lock_profile(profile);
-+              profile->isstale = 1;
-+              aa_unconfine_tasks(profile);
-+              list_del_init(&profile->list);
-+              unlock_profile(profile);
-+              aa_put_profile(profile);
-+      }
-+}
-+
-+/**
-+ * aa_profilelist_release - Remove all profiles from profile_list
-+ */
-+void aa_profile_ns_list_release(void)
-+{
-+      struct aa_namespace *ns, *tmp;
-+
-+      /* Remove and release all the profiles on namespace profile lists. */
-+      write_lock(&profile_ns_list_lock);
-+      list_for_each_entry_safe(ns, tmp, &profile_ns_list, list) {
-+              write_lock(&ns->lock);
-+              aa_profile_list_release(&ns->profiles);
-+              list_del_init(&ns->list);
-+              write_unlock(&ns->lock);
-+              aa_put_namespace(ns);
-+      }
-+      write_unlock(&profile_ns_list_lock);
-+}
-+
-+static struct aa_profile *next_profile(struct aa_profile *profile)
-+{
-+      struct aa_profile *next = profile;
-+      struct aa_namespace *ns;
-+
-+      list_for_each_entry_continue(next, &profile->ns->profiles, list)
-+              return next;
-+
-+      ns = profile->ns;
-+      read_unlock(&ns->lock);
-+      list_for_each_entry_continue(ns, &profile_ns_list, list) {
-+              read_lock(&ns->lock);
-+              list_for_each_entry(profile, &ns->profiles, list)
-+                      return profile;
-+              read_unlock(&ns->lock);
-+      }
-+      return NULL;
-+}
-+
-+static void *p_start(struct seq_file *f, loff_t *pos)
-+{
-+      struct aa_namespace *ns;
-+      loff_t l = *pos;
-+
-+      read_lock(&profile_ns_list_lock);
-+      if (!list_empty(&profile_ns_list)) {
-+              struct aa_profile *profile = NULL;
-+              ns = list_first_entry(&profile_ns_list, typeof(*ns), list);
-+              read_lock(&ns->lock);
-+              if (!list_empty(&ns->profiles))
-+                      profile = list_first_entry(&ns->profiles,
-+                                                 typeof(*profile), list);
-+              else
-+                      read_unlock(&ns->lock);
-+              for ( ; profile && l > 0; l--)
-+                      profile = next_profile(profile);
-+              return profile;
-+      }
-+      return NULL;
-+}
-+
-+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
-+{
-+      struct aa_profile *profile = (struct aa_profile *) p;
-+
-+      (*pos)++;
-+      profile = next_profile(profile);
-+
-+      return profile;
-+}
-+
-+static void p_stop(struct seq_file *f, void *p)
-+{
-+      struct aa_profile *profile = (struct aa_profile *) p;
-+
-+      if (profile)
-+              read_unlock(&profile->ns->lock);
-+      read_unlock(&profile_ns_list_lock);
-+}
-+
-+static int seq_show_profile(struct seq_file *f, void *p)
-+{
-+      struct aa_profile *profile = (struct aa_profile *)p;
-+      if (profile->ns == default_namespace)
-+          seq_printf(f, "%s (%s)\n", profile->name,
-+                     PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
-+      else
-+          seq_printf(f, ":%s:%s (%s)\n", profile->ns->name, profile->name,
-+                     PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
-+      return 0;
-+}
-+
-+/* Used in apparmorfs.c */
-+struct seq_operations apparmorfs_profiles_op = {
-+      .start =        p_start,
-+      .next =         p_next,
-+      .stop =         p_stop,
-+      .show =         seq_show_profile,
-+};
-diff -uprN e/security/apparmor/locking.txt f/security/apparmor/locking.txt
---- e/security/apparmor/locking.txt    1970-01-01 00:00:00.000000000 +0000
-+++ f/security/apparmor/locking.txt    2008-05-28 20:29:29.410207000 +0000
-@@ -0,0 +1,68 @@
-+Locking in AppArmor
-+===================
-+
-+Lock hierarchy:
-+
-+      aa_interface_lock
-+        profile_list_lock
-+          aa_profile->lock
-+            task_lock()
-+
-+
-+Which lock protects what?
-+
-+      /-----------------------+-------------------------------\
-+      | Variable              | Lock                          |
-+      >-----------------------+-------------------------------<
-+      | profile_list          | profile_list_lock             |
-+      +-----------------------+-------------------------------+
-+      | aa_profile            | (reference count)             |
-+      +-----------------------+-------------------------------+
-+      | aa_profile->          | aa_profile->lock              |
-+      |   isstale,            |                               |
-+      |   task_contexts       |                               |
-+      +-----------------------+-------------------------------+
-+      | task_struct->security | read: RCU                     |
-+      |                       | write: task_lock()            |
-+      +-----------------------+-------------------------------+
-+      | aa_profile->sub       | handle on the profile (list   |
-+      |                       | is never modified)            |
-+      \-----------------------+-------------------------------/
-+
-+(Obviously, the list_heads embedded in data structures are always
-+protected with the lock that also protects the list.)
-+
-+When moving a task context from one profile to another, we grab both
-+profile locks with lock_both_profiles(). This ensures that both locks
-+are always taken in the same order, and so we won't deadlock.
-+
-+Since task_struct->security is RCU protected the aa_task_struct it
-+references is only guarenteed to exist for the rcu cycle.  Where
-+aa_task_context->profile is needed in blocking operations the
-+profile's reference count is incremented and the profile reference
-+is used.
-+
-+Profiles on profile_list are never stale: when a profile becomes stale,
-+it is removed from profile_list at the same time (under profile_list_lock
-+and aa_profile->lock).
-+
-+The aa_interface_lock is taken whenever user-space modifies the profile
-+list, and can sleep. This ensures that profile loading/replacement/removal
-+won't race with itself. We release the profile_list_lock as soon as
-+possible to avoid stalling exec during profile loading/replacement/removal.
-+
-+AppArmor uses lock subtyping to avoid false positives from lockdep.  The
-+profile lock is often taken nested, but it is guaranteed to be in a lock
-+safe order and not the same lock when done, so it is safe.
-+
-+A third lock type (aa_lock_task_release) is given to the profile lock
-+when it is taken in soft irq context during task release (aa_release).
-+This is to avoid a false positive between the task lock and the profile
-+lock.  In task context the profile lock wraps the task lock with irqs
-+off, but the kernel takes the task lock with irqs enabled.  This won't
-+result in a deadlock because for a deadlock to occur the kernel must
-+take dead task A's lock (irqs on), the rcu callback hook freeing
-+dead task A must be run and AppArmor must be changing the profile on
-+dead task A.  The kernel should not be taking a dead task's task_lock
-+at the same time the task is being freed by task rcu cleanup other wise
-+the task would not be out of its quiescent period.
-diff -uprN e/security/apparmor/lsm.c f/security/apparmor/lsm.c
---- e/security/apparmor/lsm.c  1970-01-01 00:00:00.000000000 +0000
-+++ f/security/apparmor/lsm.c  2008-05-28 20:29:29.410207000 +0000
-@@ -0,0 +1,1108 @@
-+/*
-+ *    Copyright (C) 1998-2007 Novell/SUSE
-+ *
-+ *    This program is free software; you can redistribute it and/or
-+ *    modify it under the terms of the GNU General Public License as
-+ *    published by the Free Software Foundation, version 2 of the
-+ *    License.
-+ *
-+ *    AppArmor LSM interface
-+ */
-+#include <linux/security.h>
-+#include <linux/module.h>
-+#include <linux/mm.h>
-+#include <linux/mman.h>
-+#include <linux/mount.h>
-+#include <linux/namei.h>
-+#include <linux/ctype.h>
-+#include <linux/sysctl.h>
-+#include <linux/audit.h>
-+#include <net/sock.h>
-+
-+#include "apparmor.h"
-+#include "inline.h"
-+
-+/* Flag indicating whether initialization completed */
-+int apparmor_initialized = 0;
-+
-+/* point to the apparmor module */
-+struct module *aa_module = NULL;
-+
-+/* secondary ops if apparmor is stacked */
-+static struct security_operations *aa_secondary_ops = NULL;
-+static DEFINE_MUTEX(aa_secondary_lock);
-+
-+#define AA_SECONDARY(FN, ARGS...) \
-+       ({ \
-+               struct security_operations *__f1; \
-+               __f1 = rcu_dereference(aa_secondary_ops); \
-+               (unlikely(__f1) && __f1->FN) ? __f1->FN(ARGS) : 0; \
-+       })
-+
-+static int param_set_aabool(const char *val, struct kernel_param *kp);
-+static int param_get_aabool(char *buffer, struct kernel_param *kp);
-+#define param_check_aabool(name, p) __param_check(name, p, int)
-+
-+static int param_set_aauint(const char *val, struct kernel_param *kp);
-+static int param_get_aauint(char *buffer, struct kernel_param *kp);
-+#define param_check_aauint(name, p) __param_check(name, p, int)
-+
-+/* Flag values, also controllable via /sys/module/apparmor/parameters
-+ * We define special types as we want to do additional mediation.
-+ *
-+ * Complain mode -- in complain mode access failures result in auditing only
-+ * and task is allowed access.  audit events are processed by userspace to
-+ * generate policy.  Default is 'enforce' (0).
-+ * Value is also togglable per profile and referenced when global value is
-+ * enforce.
-+ */
-+int apparmor_complain = 0;
-+module_param_named(complain, apparmor_complain, aabool, S_IRUSR | S_IWUSR);
-+MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
-+
-+/* Debug mode */
-+int apparmor_debug = 0;
-+module_param_named(debug, apparmor_debug, aabool, S_IRUSR | S_IWUSR);
-+MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode");
-+
-+/* Audit mode */
-+int apparmor_audit = 0;
-+module_param_named(audit, apparmor_audit, aabool, S_IRUSR | S_IWUSR);
-+MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode");
-+
-+/* Syscall logging mode */
-+int apparmor_logsyscall = 0;
-+module_param_named(logsyscall, apparmor_logsyscall, aabool, S_IRUSR | S_IWUSR);
-+MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode");
-+
-+/* Maximum pathname length before accesses will start getting rejected */
-+unsigned int apparmor_path_max = 2 * PATH_MAX;
-+module_param_named(path_max, apparmor_path_max, aauint, S_IRUSR | S_IWUSR);
-+MODULE_PARM_DESC(apparmor_path_max, "Maximum pathname length allowed");
-+
-+/* Boot time disable flag */
-+#ifdef CONFIG_SECURITY_APPARMOR_DISABLE
-+#define AA_ENABLED_PERMS 0600
-+#else
-+#define AA_ENABLED_PERMS 0400
-+#endif
-+static int param_set_aa_enabled(const char *val, struct kernel_param *kp);
-+unsigned int apparmor_enabled = CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE;
-+module_param_call(enabled, param_set_aa_enabled, param_get_aauint,
-+                &apparmor_enabled, AA_ENABLED_PERMS);
-+MODULE_PARM_DESC(apparmor_enabled, "Enable/Disable Apparmor on boot");
-+
-+static int __init apparmor_enabled_setup(char *str)
-+{
-+      apparmor_enabled = simple_strtol(str, NULL, 0);
-+      return 1;
-+}
-+__setup("apparmor=", apparmor_enabled_setup);
-+
-+static int param_set_aabool(const char *val, struct kernel_param *kp)
-+{
-+      if (aa_task_context(current))
-+              return -EPERM;
-+      return param_set_bool(val, kp);
-+}
-+
-+static int param_get_aabool(char *buffer, struct kernel_param *kp)
-+{
-+      if (aa_task_context(current))
-+              return -EPERM;
-+      return param_get_bool(buffer, kp);
-+}
-+
-+static int param_set_aauint(const char *val, struct kernel_param *kp)
-+{
-+      if (aa_task_context(current))
-+              return -EPERM;
-+      return param_set_uint(val, kp);
-+}
-+
-+static int param_get_aauint(char *buffer, struct kernel_param *kp)
-+{
-+      if (aa_task_context(current))
-+              return -EPERM;
-+      return param_get_uint(buffer, kp);
-+}
-+
-+/* allow run time disabling of apparmor */
-+static int param_set_aa_enabled(const char *val, struct kernel_param *kp)
-+{
-+      char *endp;
-+      unsigned long l;
-+
-+      if (!apparmor_initialized) {
-+              apparmor_enabled = 0;
-+              return 0;
-+      }
-+
-+      if (aa_task_context(current))
-+              return -EPERM;
-+
-+      if (!apparmor_enabled)
-+              return -EINVAL;
-+
-+      if (!val)
-+              return -EINVAL;
-+
-+      l = simple_strtoul(val, &endp, 0);
-+      if (endp == val || l != 0)
-+              return -EINVAL;
-+
-+      apparmor_enabled = 0;
-+      apparmor_disable();
-+      return 0;
-+}
-+
-+static int aa_reject_syscall(struct task_struct *task, gfp_t flags,
-+                           const char *name)
-+{
-+      struct aa_profile *profile = aa_get_profile(task);
-+      int error = 0;
-+
-+      if (profile) {
-+              error = aa_audit_syscallreject(profile, flags, name);
-+              aa_put_profile(profile);
-+      }
-+
-+      return error;
-+}
-+
-+static int apparmor_ptrace(struct task_struct *parent,
-+                         struct task_struct *child)
-+{
-+      struct aa_task_context *cxt;
-+      int error = 0;
-+
-+      /*
-+       * parent can ptrace child when
-+       * - parent is unconfined
-+       * - parent & child are in the same namespace &&
-+       *   - parent is in complain mode
-+       *   - parent and child are confined by the same profile
-+       *   - parent profile has CAP_SYS_PTRACE
-+       */
-+
-+      rcu_read_lock();
-+      cxt = aa_task_context(parent);
-+      if (cxt) {
-+              if (parent->nsproxy != child->nsproxy) {
-+                      struct aa_audit sa;
-+                      memset(&sa, 0, sizeof(sa));
-+                      sa.operation = "ptrace";
-+                      sa.gfp_mask = GFP_ATOMIC;
-+                      sa.parent = parent->pid;
-+                      sa.task = child->pid;
-+                      sa.info = "different namespaces";
-+                      aa_audit_reject(cxt->profile, &sa);
-+                      error = -EPERM;
-+              } else {
-+                      struct aa_task_context *child_cxt =
-+                              aa_task_context(child);
-+
-+                      error = aa_may_ptrace(cxt, child_cxt ?
-+                                                 child_cxt->profile : NULL);
-+                      if (PROFILE_COMPLAIN(cxt->profile)) {
-+                              struct aa_audit sa;
-+                              memset(&sa, 0, sizeof(sa));
-+                              sa.operation = "ptrace";
-+                              sa.gfp_mask = GFP_ATOMIC;
-+                              sa.parent = parent->pid;
-+                              sa.task = child->pid;
-+                              aa_audit_hint(cxt->profile, &sa);
-+                      }
-+              }
-+      }
-+      rcu_read_unlock();
-+
-+      return error;
-+}
-+
-+static int apparmor_capable(struct task_struct *task, int cap)
-+{
-+      int error;
-+      struct aa_task_context *cxt;
-+
-+      /* cap_capable returns 0 on success, else -EPERM */
-+      error = cap_capable(task, cap);
-+
-+      rcu_read_lock();
-+      cxt = aa_task_context(task);
-+      if (cxt && (!error || cap_raised(cxt->profile->set_caps, cap)))
-+              error = aa_capability(cxt, cap);
-+      rcu_read_unlock();
-+
-+      return error;
-+}
-+
-+static int apparmor_sysctl(struct ctl_table *table, int op)
-+{
-+      struct aa_profile *profile = aa_get_profile(current);
-+      int error = 0;
-+
-+      if (profile) {
-+              char *buffer, *name;
-+              int mask;
-+
-+              mask = 0;
-+              if (op & 4)
-+                      mask |= MAY_READ;
-+              if (op & 2)
-+                      mask |= MAY_WRITE;
-+
-+              error = -ENOMEM;
-+              buffer = (char*)__get_free_page(GFP_KERNEL);
-+              if (!buffer)
-+                      goto out;
-+              name = sysctl_pathname(table, buffer, PAGE_SIZE);
-+              if (name && name - buffer >= 5) {
-+                      name -= 5;
-+                      memcpy(name, "/proc", 5);
-+                      error = aa_perm_path(profile, "sysctl", name, mask, 0);
-+              }
-+              free_page((unsigned long)buffer);
-+      }
-+
-+out:
-+      aa_put_profile(profile);
-+      return error;
-+}
-+
-+static int apparmor_bprm_set_security(struct linux_binprm *bprm)
-+{
-+      /* handle capability bits with setuid, etc */
-+      cap_bprm_set_security(bprm);
-+      /* already set based on script name */
-+      if (bprm->sh_bang)
-+              return 0;
-+      return aa_register(bprm);
-+}
-+
-+static int apparmor_bprm_secureexec(struct linux_binprm *bprm)
-+{
-+      int ret = cap_bprm_secureexec(bprm);
-+
-+      if (!ret && (unsigned long)bprm->security & AA_SECURE_EXEC_NEEDED) {
-+              AA_DEBUG("%s: secureexec required for %s\n",
-+                       __FUNCTION__, bprm->filename);
-+              ret = 1;
-+      }
-+
-+      return ret;
-+}
-+
-+static int apparmor_sb_mount(char *dev_name, struct nameidata *nd, char *type,
-+                            unsigned long flags, void *data)
-+{
-+      return aa_reject_syscall(current, GFP_KERNEL, "mount");
-+}
-+
-+static int apparmor_umount(struct vfsmount *mnt, int flags)
-+{
-+      return aa_reject_syscall(current, GFP_KERNEL, "umount");
-+}
-+
-+static int apparmor_inode_mkdir(struct inode *dir, struct dentry *dentry,
-+                              struct vfsmount *mnt, int mask)
-+{
-+      struct aa_profile *profile;
-+      int error = 0;
-+
-+      if (!mnt || !mediated_filesystem(dir))
-+              goto out;
-+
-+      profile = aa_get_profile(current);
-+
-+      if (profile)
-+              error = aa_perm_dir(profile, "inode_mkdir", dentry, mnt,
-+                                  MAY_WRITE);
-+
-+      aa_put_profile(profile);
-+
-+out:
-+      return error;
-+}
-+
-+static int apparmor_inode_rmdir(struct inode *dir, struct dentry *dentry,
-+                              struct vfsmount *mnt)
-+{
-+      struct aa_profile *profile;
-+      int error = 0;
-+
-+      if (!mnt || !mediated_filesystem(dir))
-+              goto out;
-+
-+      profile = aa_get_profile(current);
-+
-+      if (profile)
-+              error = aa_perm_dir(profile, "inode_rmdir", dentry, mnt,
-+                                  MAY_WRITE);
-+
-+      aa_put_profile(profile);
-+
-+out:
-+      return error;
-+}
-+
-+static int aa_permission(const char *operation, struct inode *inode,
-+                       struct dentry *dentry, struct vfsmount *mnt,
-+                       int mask, int check)
-+{
-+      int error = 0;
-+
-+      if (mnt && mediated_filesystem(inode)) {
-+              struct aa_profile *profile;
-+
-+              profile = aa_get_profile(current);
-+              if (profile)
-+                      error = aa_perm(profile, operation, dentry, mnt, mask,
-+                                      check);
-+              aa_put_profile(profile);
-+      }
-+      return error;
-+}
-+
-+static inline int aa_mask_permissions(int mask)
-+{
-+      if (mask & MAY_APPEND)
-+              mask &= (MAY_READ | MAY_APPEND | MAY_EXEC);
-+      else
-+              mask &= (MAY_READ | MAY_WRITE | MAY_EXEC);
-+      return mask;
-+}
-+
-+static int apparmor_inode_create(struct inode *dir, struct dentry *dentry,
-+                               struct vfsmount *mnt, int mask)
-+{
-+      return aa_permission("inode_create", dir, dentry, mnt, MAY_APPEND, 0);
-+}
-+
-+static int apparmor_inode_link(struct dentry *old_dentry,
-+                             struct vfsmount *old_mnt, struct inode *dir,
-+                             struct dentry *new_dentry,
-+                             struct vfsmount *new_mnt)
-+{
-+      int error = 0;
-+      struct aa_profile *profile;
-+
-+      if (!old_mnt || !new_mnt || !mediated_filesystem(dir))
-+              goto out;
-+
-+      profile = aa_get_profile(current);
-+
-+      if (profile)
-+              error = aa_link(profile, new_dentry, new_mnt,
-+                              old_dentry, old_mnt);
-+
-+      aa_put_profile(profile);
-+
-+out:
-+      return error;
-+}
-+
-+static int apparmor_inode_unlink(struct inode *dir, struct dentry *dentry,
-+                               struct vfsmount *mnt)
-+{
-+      int check = 0;
-+
-+      if (S_ISDIR(dentry->d_inode->i_mode))
-+              check |= AA_CHECK_DIR;
-+      return aa_permission("inode_unlink", dir, dentry, mnt, MAY_WRITE,
-+                           check);
-+}
-+
-+static int apparmor_inode_symlink(struct inode *dir, struct dentry *dentry,
-+                                struct vfsmount *mnt, const char *old_name)
-+{
-+      return aa_permission("inode_symlink", dir, dentry, mnt, MAY_WRITE, 0);
-+}
-+
-+static int apparmor_inode_mknod(struct inode *dir, struct dentry *dentry,
-+                              struct vfsmount *mnt, int mode, dev_t dev)
-+{
-+      return aa_permission("inode_mknod", dir, dentry, mnt, MAY_WRITE, 0);
-+}
-+
-+static int apparmor_inode_rename(struct inode *old_dir,
-+                               struct dentry *old_dentry,
-+                               struct vfsmount *old_mnt,
-+                               struct inode *new_dir,
-+                               struct dentry *new_dentry,
-+                               struct vfsmount *new_mnt)
-+{
-+      struct aa_profile *profile;
-+      int error = 0;
-+
-+      if ((!old_mnt && !new_mnt) || !mediated_filesystem(old_dir))
-+              goto out;
-+
-+      profile = aa_get_profile(current);
-+
-+      if (profile) {
-+              struct inode *inode = old_dentry->d_inode;
-+              int check = 0;
-+
-+              if (inode && S_ISDIR(inode->i_mode))
-+                      check |= AA_CHECK_DIR;
-+              if (old_mnt)
-+                      error = aa_perm(profile, "inode_rename", old_dentry,
-+                                      old_mnt, MAY_READ | MAY_WRITE, check);
-+
-+              if (!error && new_mnt) {
-+                      error = aa_perm(profile, "inode_rename", new_dentry,
-+                                      new_mnt, MAY_WRITE, check);
-+              }
-+      }
-+
-+      aa_put_profile(profile);
-+
-+out:
-+      return error;
-+}
-+
-+static int apparmor_inode_permission(struct inode *inode, int mask,
-+                                   struct nameidata *nd)
-+{
-+      int check = 0, error = 0;
-+
-+      if (!nd || nd->flags & (LOOKUP_PARENT | LOOKUP_CONTINUE))
-+              goto out;
-+      mask = aa_mask_permissions(mask);
-+      if (S_ISDIR(inode->i_mode)) {
-+              check |= AA_CHECK_DIR;
-+              /* allow traverse accesses to directories */
-+              mask &= ~MAY_EXEC;
-+      }
-+      error = aa_permission("inode_permission", inode, nd->path.dentry,
-+                            nd->path.mnt,
-+                            mask, check);
-+
-+out:
-+      if (!error)
-+              error = AA_SECONDARY(inode_permission, inode, mask, nd);
-+
-+      return error;
-+}
-+
-+static int apparmor_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
-+                                struct iattr *iattr)
-+{
-+      int error = 0;
-+
-+      if (!mnt)
-+              goto out;
-+
-+      if (mediated_filesystem(dentry->d_inode)) {
-+              struct aa_profile *profile;
-+
-+              profile = aa_get_profile(current);
-+              /*
-+               * Mediate any attempt to change attributes of a file
-+               * (chmod, chown, chgrp, etc)
-+               */
-+              if (profile)
-+                      error = aa_attr(profile, dentry, mnt, iattr);
-+
-+              aa_put_profile(profile);
-+      }
-+
-+out:
-+      return error;
-+}
-+
-+static int aa_xattr_permission(struct dentry *dentry, struct vfsmount *mnt,
-+                             const char *operation, int mask,
-+                             struct file *file)
-+{
-+      int error = 0;
-+
-+      if (mnt && mediated_filesystem(dentry->d_inode)) {
-+              struct aa_profile *profile = aa_get_profile(current);
-+              int check = file ? AA_CHECK_FD : 0;
-+
-+              if (profile)
-+                      error = aa_perm_xattr(profile, operation, dentry, mnt,
-+                                            mask, check);
-+              aa_put_profile(profile);
-+      }
-+
-+      return error;
-+}
-+
-+static int apparmor_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
-+                                 char *name, void *value, size_t size,
-+                                 int flags, struct file *file)
-+{
-+      return aa_xattr_permission(dentry, mnt, "xattr set", MAY_WRITE, file);
-+}
-+
-+static int apparmor_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
-+                                 char *name, struct file *file)
-+{
-+      return aa_xattr_permission(dentry, mnt, "xattr get", MAY_READ, file);
-+}
-+
-+static int apparmor_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
-+                                  struct file *file)
-+{
-+      return aa_xattr_permission(dentry, mnt, "xattr list", MAY_READ, file);
-+}
-+
-+static int apparmor_inode_removexattr(struct dentry *dentry,
-+                                    struct vfsmount *mnt, char *name,
-+                                    struct file *file)
-+{
-+      return aa_xattr_permission(dentry, mnt, "xattr remove", MAY_WRITE,
-+                                 file);
-+}
-+
-+static int aa_file_permission(const char *op, struct file *file, int mask)
-+{
-+      struct aa_profile *profile;
-+      struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
-+      int error = 0;
-+
-+      if (!file_profile)
-+              goto out;
-+
-+      /*
-+       * If this file was opened under a different profile, we
-+       * revalidate the access against the current profile.
-+       */
-+      profile = aa_get_profile(current);
-+      if (profile && (file_profile != profile || mask & AA_MAY_LOCK)) {
-+              struct dentry *dentry = file->f_dentry;
-+              struct vfsmount *mnt = file->f_vfsmnt;
-+              struct inode *inode = dentry->d_inode;
-+              int check = AA_CHECK_FD;
-+
-+              /*
-+               * FIXME: We should remember which profiles we revalidated
-+               *        against.
-+               */
-+              if (S_ISDIR(inode->i_mode))
-+                      check |= AA_CHECK_DIR;
-+              error = aa_permission(op, inode, dentry, mnt, mask, check);
-+      }
-+      aa_put_profile(profile);
-+
-+out:
-+      return error;
-+}
-+
-+static int apparmor_file_permission(struct file *file, int mask)
-+{
-+      return aa_file_permission("file_permission", file,
-+                                aa_mask_permissions(mask));
-+}
-+
-+static inline int apparmor_file_lock (struct file *file, unsigned int cmd)
-+{
-+      int mask = AA_MAY_LOCK;
-+      if (cmd == F_WRLCK)
-+              mask |= MAY_WRITE;
-+      return aa_file_permission("file_lock", file, mask);
-+}
-+
-+static int apparmor_file_alloc_security(struct file *file)
-+{
-+      struct aa_profile *profile;
-+
-+      profile = aa_get_profile(current);
-+      if (profile)
-+              file->f_security = profile;
-+
-+      return 0;
-+}
-+
-+static void apparmor_file_free_security(struct file *file)
-+{
-+      struct aa_profile *file_profile = (struct aa_profile*)file->f_security;
-+
-+      aa_put_profile(file_profile);
-+}
-+
-+static inline int aa_mmap(struct file *file, const char *operation,
-+                        unsigned long prot, unsigned long flags)
-+{
-+      struct dentry *dentry;
-+      int mask = 0;
-+
-+      if (!file || !file->f_security)
-+              return 0;
-+
-+      if (prot & PROT_READ)
-+              mask |= MAY_READ;
-+      /* Private mappings don't require write perms since they don't
-+       * write back to the files */
-+      if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE))
-+              mask |= MAY_WRITE;
-+      if (prot & PROT_EXEC)
-+              mask |= AA_EXEC_MMAP;
-+
-+      dentry = file->f_dentry;
-+      return aa_permission(operation, dentry->d_inode, dentry,
-+                           file->f_vfsmnt, mask, AA_CHECK_FD);
-+}
-+
-+static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
-+                            unsigned long prot, unsigned long flags,
-+                            unsigned long addr, unsigned long addr_only)
-+{
-+      if ((addr < mmap_min_addr) && !capable(CAP_SYS_RAWIO)) {
-+              struct aa_profile *profile = aa_get_profile(current);
-+              if (profile)
-+                      /* future control check here */
-+                      return -EACCES;
-+              else
-+                      return -EACCES;
-+              aa_put_profile(profile);
-+      }
-+
-+      return aa_mmap(file, "file_mmap", prot, flags);
-+}
-+
-+static int apparmor_file_mprotect(struct vm_area_struct *vma,
-+                                unsigned long reqprot, unsigned long prot)
-+{
-+      return aa_mmap(vma->vm_file, "file_mprotect", prot,
-+                     !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0);
-+}
-+
-+static int apparmor_task_alloc_security(struct task_struct *task)
-+{
-+      return aa_clone(task);
-+}
-+
-+/*
-+ * Called from IRQ context from RCU callback.
-+ */
-+static void apparmor_task_free_security(struct task_struct *task)
-+{
-+      aa_release(task);
-+}
-+
-+static int apparmor_socket_create(int family, int type, int protocol, int kern)
-+{
-+      struct aa_profile *profile;
-+      int error = 0;
-+
-+      if (kern)
-+              return 0;
-+
-+      profile = aa_get_profile(current);
-+      if (profile)
-+              error = aa_net_perm(profile, "socket_create", family,
-+                                                      type, protocol);
-+      aa_put_profile(profile);
-+
-+      return error;
-+}
-+
-+static int apparmor_socket_post_create(struct socket *sock, int family,
-+                                      int type, int protocol, int kern)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      if (kern)
-+              return 0;
-+
-+      return aa_revalidate_sk(sk, "socket_post_create");
-+}
-+
-+static int apparmor_socket_bind(struct socket *sock,
-+                              struct sockaddr *address, int addrlen)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(sk, "socket_bind");
-+}
-+
-+static int apparmor_socket_connect(struct socket *sock,
-+                                      struct sockaddr *address, int addrlen)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(sk, "socket_connect");
-+}
-+
-+static int apparmor_socket_listen(struct socket *sock, int backlog)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(sk, "socket_listen");
-+}
-+
-+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(sk, "socket_accept");
-+}
-+
-+static int apparmor_socket_sendmsg(struct socket *sock,
-+                                      struct msghdr *msg, int size)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(sk, "socket_sendmsg");
-+}
-+
-+static int apparmor_socket_recvmsg(struct socket *sock,
-+                                 struct msghdr *msg, int size, int flags)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(sk, "socket_recvmsg");
-+}
-+
-+static int apparmor_socket_getsockname(struct socket *sock)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(sk, "socket_getsockname");
-+}
-+
-+static int apparmor_socket_getpeername(struct socket *sock)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(sk, "socket_getpeername");
-+}
-+
-+static int apparmor_socket_getsockopt(struct socket *sock, int level,
-+                                      int optname)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(sk, "socket_getsockopt");
-+}
-+
-+static int apparmor_socket_setsockopt(struct socket *sock, int level,
-+                                      int optname)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(sk, "socket_setsockopt");
-+}
-+
-+static int apparmor_socket_shutdown(struct socket *sock, int how)
-+{
-+      struct sock *sk = sock->sk;
-+
-+      return aa_revalidate_sk(sk, "socket_shutdown");
-+}
-+
-+static int apparmor_getprocattr(struct task_struct *task, char *name,
-+                              char **value)
-+{
-+      unsigned len;
-+      int error;
-+      struct aa_profile *profile;
-+
-+      /* AppArmor only supports the "current" process attribute */
-+      if (strcmp(name, "current") != 0)
-+              return -EINVAL;
-+
-+      /* must be task querying itself or admin */
-+      if (current != task && !capable(CAP_SYS_ADMIN))
-+              return -EPERM;
-+
-+      profile = aa_get_profile(task);
-+      error = aa_getprocattr(profile, value, &len);
-+      aa_put_profile(profile);
-+      if (!error)
-+              error = len;
-+
-+      return error;
-+}
-+
-+static int apparmor_setprocattr(struct task_struct *task, char *name,
-+                              void *value, size_t size)
-+{
-+      char *command, *args;
-+      int error;
-+
-+      if (strcmp(name, "current") != 0 || size == 0 || size >= PAGE_SIZE)
-+              return -EINVAL;
-+      args = value;
-+      args[size] = '\0';
-+      args = strstrip(args);
-+      command = strsep(&args, " ");
-+      if (!args)
-+              return -EINVAL;
-+      while (isspace(*args))
-+              args++;
-+      if (!*args)
-+              return -EINVAL;
-+
-+      if (strcmp(command, "changehat") == 0) {
-+              if (current != task)
-+                      return -EACCES;
-+              error = aa_setprocattr_changehat(args);
-+      } else if (strcmp(command, "changeprofile") == 0) {
-+              if (current != task)
-+                      return -EACCES;
-+              error = aa_setprocattr_changeprofile(args);
-+      } else if (strcmp(command, "setprofile") == 0) {
-+              struct aa_profile *profile;
-+
-+              /* Only an unconfined process with admin capabilities
-+               * may change the profile of another task.
-+               */
-+
-+              if (!capable(CAP_SYS_ADMIN))
-+                      return -EACCES;
-+
-+              profile = aa_get_profile(current);
-+              if (profile) {
-+                      struct aa_audit sa;
-+                      memset(&sa, 0, sizeof(sa));
-+                      sa.operation = "profile_set";
-+                      sa.gfp_mask = GFP_KERNEL;
-+                      sa.task = task->pid;
-+                      sa.info = "from confined process";
-+                      aa_audit_reject(profile, &sa);
-+                      aa_put_profile(profile);
-+                      return -EACCES;
-+              }
-+              error = aa_setprocattr_setprofile(task, args);
-+      } else {
-+              struct aa_audit sa;
-+              memset(&sa, 0, sizeof(sa));
-+              sa.operation = "setprocattr";
-+              sa.gfp_mask = GFP_KERNEL;
-+              sa.info = "invalid command";
-+              sa.name = command;
-+              sa.task = task->pid;
-+              aa_audit_reject(NULL, &sa);
-+              return -EINVAL;
-+      }
-+
-+      if (!error)
-+              error = size;
-+      return error;
-+}
-+
-+static int apparmor_task_setrlimit(unsigned int resource,
-+                                 struct rlimit *new_rlim)
-+{
-+      struct aa_profile *profile;
-+      int error = 0;
-+
-+      profile = aa_get_profile(current);
-+      if (profile) {
-+              error = aa_task_setrlimit(profile, resource, new_rlim);
-+      }
-+      aa_put_profile(profile);
-+
-+      return error;
-+}
-+
-+int apparmor_register_subsecurity(const char *name,
-+                                 struct security_operations *ops)
-+{
-+       int error = 0;
-+
-+       if (mutex_lock_interruptible(&aa_secondary_lock))
-+               return -ERESTARTSYS;
-+
-+       /* allow dazuko and capability to stack.  The stacking with
-+        * capability is not needed since apparmor already composes
-+        * capability using common cap.
-+        */
-+       if (!aa_secondary_ops && (strcmp(name, "dazuko") == 0 ||
-+                                 strcmp(name, "capability") == 0)){
-+               /* The apparmor module needs to be pinned while a secondary is
-+                * registered
-+                */
-+               if (try_module_get(aa_module)) {
-+                       aa_secondary_ops = ops;
-+                       info_message("Registered secondary security module",
-+                                    name);
-+               } else {
-+                       error = -EINVAL;
-+               }
-+       } else {
-+               info_message("Unable to register %s as a secondary security "
-+                            "module", name);
-+               error = -EPERM;
-+       }
-+       mutex_unlock(&aa_secondary_lock);
-+       return error;
-+}
-+
-+int apparmor_unregister_subsecurity(const char *name,
-+                                   struct security_operations *ops)
-+{
-+       int error = 0;
-+
-+       if (mutex_lock_interruptible(&aa_secondary_lock))
-+               return -ERESTARTSYS;
-+
-+       if (aa_secondary_ops && aa_secondary_ops == ops) {
-+               rcu_assign_pointer(aa_secondary_ops, NULL);
-+               synchronize_rcu();
-+               module_put(aa_module);
-+               info_message("Unregistered secondary security module", name);
-+       } else {
-+               info_message("Unable to unregister secondary security module",
-+                            name);
-+               error = -EPERM;
-+       }
-+       mutex_unlock(&aa_secondary_lock);
-+       return error;
-+}
-+
-+struct security_operations apparmor_ops = {
-+      .name =                         "apparmor",
-+      .ptrace =                       apparmor_ptrace,
-+      .capget =                       cap_capget,
-+      .capset_check =                 cap_capset_check,
-+      .capset_set =                   cap_capset_set,
-+      .sysctl =                       apparmor_sysctl,
-+      .capable =                      apparmor_capable,
-+      .syslog =                       cap_syslog,
-+
-+      .bprm_apply_creds =             cap_bprm_apply_creds,
-+      .bprm_set_security =            apparmor_bprm_set_security,
-+      .bprm_secureexec =              apparmor_bprm_secureexec,
-+
-+      .sb_mount =                     apparmor_sb_mount,
-+      .sb_umount =                    apparmor_umount,
-+
-+      .inode_mkdir =                  apparmor_inode_mkdir,
-+      .inode_rmdir =                  apparmor_inode_rmdir,
-+      .inode_create =                 apparmor_inode_create,
-+      .inode_link =                   apparmor_inode_link,
-+      .inode_unlink =                 apparmor_inode_unlink,
-+      .inode_symlink =                apparmor_inode_symlink,
-+      .inode_mknod =                  apparmor_inode_mknod,
-+      .inode_rename =                 apparmor_inode_rename,
-+      .inode_permission =             apparmor_inode_permission,
-+      .inode_setattr =                apparmor_inode_setattr,
-+      .inode_setxattr =               apparmor_inode_setxattr,
-+      .inode_getxattr =               apparmor_inode_getxattr,
-+      .inode_listxattr =              apparmor_inode_listxattr,
-+      .inode_removexattr =            apparmor_inode_removexattr,
-+      .file_permission =              apparmor_file_permission,
-+      .file_alloc_security =          apparmor_file_alloc_security,
-+      .file_free_security =           apparmor_file_free_security,
-+      .file_mmap =                    apparmor_file_mmap,
-+      .file_mprotect =                apparmor_file_mprotect,
-+      .file_lock =                    apparmor_file_lock,
-+
-+      .task_alloc_security =          apparmor_task_alloc_security,
-+      .task_free_security =           apparmor_task_free_security,
-+      .task_post_setuid =             cap_task_post_setuid,
-+      .task_reparent_to_init =        cap_task_reparent_to_init,
-+      .task_setrlimit =               apparmor_task_setrlimit,
-+
-+      .getprocattr =                  apparmor_getprocattr,
-+      .setprocattr =                  apparmor_setprocattr,
-+
-+      .register_security =            apparmor_register_subsecurity,
-+
-+      .socket_create =                apparmor_socket_create,
-+      .socket_post_create =           apparmor_socket_post_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,
-+};
-+
-+void info_message(const char *str, const char *name)
-+{
-+      struct aa_audit sa;
-+      memset(&sa, 0, sizeof(sa));
-+      sa.gfp_mask = GFP_KERNEL;
-+      sa.info = str;
-+      sa.name = name;
-+      printk(KERN_INFO "AppArmor: %s %s\n", str, name);
-+      if (audit_enabled)
-+              aa_audit_message(NULL, &sa, AUDIT_APPARMOR_STATUS);
-+}
-+
-+static int __init apparmor_init(void)
-+{
-+      int error;
-+
-+      if (!apparmor_enabled) {
-+              info_message("AppArmor disabled by boottime parameter", "");
-+              return 0;
-+      }
-+
-+      if ((error = create_apparmorfs())) {
-+              AA_ERROR("Unable to activate AppArmor filesystem\n");
-+              goto createfs_out;
-+      }
-+
-+      if ((error = alloc_default_namespace())){
-+              AA_ERROR("Unable to allocate default profile namespace\n");
-+              goto alloc_out;
-+      }
-+
-+      if ((error = register_security(&apparmor_ops))) {
-+              AA_ERROR("Unable to register AppArmor\n");
-+              goto register_security_out;
-+      }
-+
-+      /* Report that AppArmor successfully initialized */
-+      apparmor_initialized = 1;
-+      if (apparmor_complain)
-+              info_message("AppArmor initialized: complainmode enabled",
-+                           NULL);
-+      else
-+              info_message("AppArmor initialized", NULL);
-+
-+      return error;
-+
-+register_security_out:
-+      free_default_namespace();
-+
-+alloc_out:
-+      destroy_apparmorfs();
-+
-+createfs_out:
-+      return error;
-+
-+}
-+
-+security_initcall(apparmor_init);
-+
-+void apparmor_disable(void)
-+{
-+      /* Remove and release all the profiles on the profile list. */
-+      mutex_lock(&aa_interface_lock);
-+      aa_profile_ns_list_release();
-+
-+      /* FIXME: cleanup profiles references on files */
-+      free_default_namespace();
-+
-+      /*
-+       * Delay for an rcu cycle to make sure that all active task
-+       * context readers have finished, and all profiles have been
-+       * freed by their rcu callbacks.
-+       */
-+      synchronize_rcu();
-+
-+      destroy_apparmorfs();
-+      mutex_unlock(&aa_interface_lock);
-+
-+      apparmor_initialized = 0;
-+
-+      info_message("AppArmor protection removed", NULL);
-+}
-+
-+MODULE_DESCRIPTION("AppArmor process confinement");
-+MODULE_AUTHOR("Novell/Immunix, http://bugs.opensuse.org");
-+MODULE_LICENSE("GPL");
-diff -uprN e/security/apparmor/main.c f/security/apparmor/main.c
---- e/security/apparmor/main.c 1970-01-01 00:00:00.000000000 +0000
-+++ f/security/apparmor/main.c 2008-05-28 20:29:29.410207000 +0000
-@@ -0,0 +1,1689 @@
-+/*
-+ *    Copyright (C) 2002-2007 Novell/SUSE
-+ *
-+ *    This program is free software; you can redistribute it and/or
-+ *    modify it under the terms of the GNU General Public License as
-+ *    published by the Free Software Foundation, version 2 of the
-+ *    License.
-+ *
-+ *    AppArmor Core
-+ */
-+
-+#include <linux/security.h>
-+#include <linux/namei.h>
-+#include <linux/audit.h>
-+#include <linux/mount.h>
-+#include <linux/ptrace.h>
-+#include <linux/socket.h>
-+#include <linux/net.h>
-+#include <net/sock.h>
-+
-+#include "apparmor.h"
-+
-+#include "inline.h"
-+
-+/*
-+ * Table of capability names: we generate it from capabilities.h.
-+ */
-+static const char *capability_names[] = {
-+#include "capability_names.h"
-+};
-+
-+struct aa_namespace *default_namespace;
-+
-+static int aa_inode_mode(struct inode *inode)
-+{
-+      /* if the inode doesn't exist the user is creating it */
-+      if (!inode || current->fsuid == inode->i_uid)
-+              return AA_USER_SHIFT;
-+      return AA_OTHER_SHIFT;
-+}
-+
-+int alloc_default_namespace(void)
-+{
-+      struct aa_namespace *ns;
-+      char *name = kstrdup("default", GFP_KERNEL);
-+      if (!name)
-+              return -ENOMEM;
-+      ns = alloc_aa_namespace(name);
-+      if (!ns) {
-+              kfree(name);
-+              return -ENOMEM;
-+      }
-+
-+      write_lock(&profile_ns_list_lock);
-+      default_namespace = ns;
-+      aa_get_namespace(ns);
-+      list_add(&ns->list, &profile_ns_list);
-+      write_unlock(&profile_ns_list_lock);
-+
-+      return 0;
-+}
-+
-+void free_default_namespace(void)
-+{
-+      write_lock(&profile_ns_list_lock);
-+      list_del_init(&default_namespace->list);
-+      write_unlock(&profile_ns_list_lock);
-+      aa_put_namespace(default_namespace);
-+      default_namespace = NULL;
-+}
-+
-+static void aa_audit_file_sub_mask(struct audit_buffer *ab, char *buffer,
-+                                 int mask)
-+{
-+      const char unsafex[] = "upcn";
-+      const char safex[] = "UPCN";
-+      char *m = buffer;
-+
-+      if (mask & AA_EXEC_MMAP)
-+              *m++ = 'm';
-+      if (mask & MAY_READ)
-+              *m++ = 'r';
-+      if (mask & MAY_WRITE)
-+              *m++ = 'w';
-+      else if (mask & MAY_APPEND)
-+              *m++ = 'a';
-+      if (mask & MAY_EXEC) {
-+              int index = AA_EXEC_INDEX(mask);
-+              /* all indexes > 4 are also named transitions */
-+              if (index > 4)
-+                      index = 4;
-+              if (index > 0) {
-+                      if (mask & AA_EXEC_UNSAFE)
-+                              *m++ = unsafex[index - 1];
-+                      else
-+                              *m++ = safex[index - 1];
-+              }
-+              if (mask & AA_EXEC_INHERIT)
-+                      *m++ = 'i';
-+              *m++ = 'x';
-+      }
-+      if (mask & AA_MAY_LINK)
-+              *m++ = 'l';
-+      if (mask & AA_MAY_LOCK)
-+              *m++ = 'k';
-+      *m++ = '\0';
-+}
-+
-+static void aa_audit_file_mask(struct audit_buffer *ab, const char *name,
-+                             int mask)
-+{
-+      char user[10], other[10];
-+
-+      aa_audit_file_sub_mask(ab, user,
-+                             (mask & AA_USER_PERMS) >> AA_USER_SHIFT);
-+      aa_audit_file_sub_mask(ab, other,
-+                             (mask & AA_OTHER_PERMS) >> AA_OTHER_SHIFT);
-+
-+      audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
-+}
-+
-+static const char *address_families[] = {
-+#include "af_names.h"
-+};
-+
-+static const char *sock_types[] = {
-+      "unknown(0)",
-+      "stream",
-+      "dgram",
-+      "raw",
-+      "rdm",
-+      "seqpacket",
-+      "dccp",
-+      "unknown(7)",
-+      "unknown(8)",
-+      "unknown(9)",
-+      "packet",
-+};
-+
-+/**
-+ * aa_audit - Log an audit event to the audit subsystem
-+ * @profile: profile to check against
-+ * @sa: audit event
-+ * @audit_cxt: audit context to log message to
-+ * @type: audit event number
-+ */
-+static int aa_audit_base(struct aa_profile *profile, struct aa_audit *sa,
-+                       struct audit_context *audit_cxt, int type)
-+{
-+      struct audit_buffer *ab = NULL;
-+
-+      ab = audit_log_start(audit_cxt, sa->gfp_mask, type);
-+
-+      if (!ab) {
-+              AA_ERROR("Unable to log event (%d) to audit subsys\n",
-+                       type);
-+               /* don't fail operations in complain mode even if logging
-+                * fails */
-+              return type == AUDIT_APPARMOR_ALLOWED ? 0 : -ENOMEM;
-+      }
-+
-+      if (sa->operation)
-+              audit_log_format(ab, "operation=\"%s\"", sa->operation);
-+
-+      if (sa->info) {
-+              audit_log_format(ab, " info=\"%s\"", sa->info);
-+              if (sa->error_code)
-+                      audit_log_format(ab, " error=%d", sa->error_code);
-+      }
-+
-+      if (sa->request_mask)
-+              aa_audit_file_mask(ab, "requested_mask", sa->request_mask);
-+
-+      if (sa->denied_mask)
-+              aa_audit_file_mask(ab, "denied_mask", sa->denied_mask);
-+
-+      if (sa->request_mask)
-+              audit_log_format(ab, " fsuid=%d", current->fsuid);
-+
-+      if (sa->rlimit)
-+              audit_log_format(ab, " rlimit=%d", sa->rlimit - 1);
-+
-+      if (sa->iattr) {
-+              struct iattr *iattr = sa->iattr;
-+
-+              audit_log_format(ab, " attribute=\"%s%s%s%s%s%s%s\"",
-+                      iattr->ia_valid & ATTR_MODE ? "mode," : "",
-+                      iattr->ia_valid & ATTR_UID ? "uid," : "",
-+                      iattr->ia_valid & ATTR_GID ? "gid," : "",
-+                      iattr->ia_valid & ATTR_SIZE ? "size," : "",
-+                      iattr->ia_valid & (ATTR_ATIME | ATTR_ATIME_SET) ?
-+                              "atime," : "",
-+                      iattr->ia_valid & (ATTR_MTIME | ATTR_MTIME_SET) ?
-+                              "mtime," : "",
-+                      iattr->ia_valid & ATTR_CTIME ? "ctime," : "");
-+      }
-+
-+      if (sa->task)
-+              audit_log_format(ab, " task=%d", sa->task);
-+
-+      if (sa->parent)
-+              audit_log_format(ab, " parent=%d", sa->parent);
-+
-+      if (sa->name) {
-+              audit_log_format(ab, " name=");
-+              audit_log_untrustedstring(ab, sa->name);
-+      }
-+
-+      if (sa->name2) {
-+              audit_log_format(ab, " name2=");
-+              audit_log_untrustedstring(ab, sa->name2);
-+      }
-+
-+      if (sa->family || sa->type) {
-+              if (address_families[sa->family])
-+                      audit_log_format(ab, " family=\"%s\"",
-+                                       address_families[sa->family]);
-+              else
-+                      audit_log_format(ab, " family=\"unknown(%d)\"",
-+                                       sa->family);
-+
-+              if (sock_types[sa->type])
-+                      audit_log_format(ab, " sock_type=\"%s\"",
-+                                       sock_types[sa->type]);
-+              else
-+                      audit_log_format(ab, " sock_type=\"unknown(%d)\"",
-+                                       sa->type);
-+
-+              audit_log_format(ab, " protocol=%d", sa->protocol);
-+      }
-+
-+        audit_log_format(ab, " pid=%d", current->pid);
-+
-+      if (profile) {
-+              audit_log_format(ab, " profile=");
-+              audit_log_untrustedstring(ab, profile->name);
-+
-+              if (profile->ns != default_namespace) {
-+                      audit_log_format(ab, " namespace=");
-+                      audit_log_untrustedstring(ab, profile->ns->name);
-+              }
-+      }
-+
-+      audit_log_end(ab);
-+
-+      return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error_code;
-+}
-+
-+/**
-+ * aa_audit_syscallreject - Log a syscall rejection to the audit subsystem
-+ * @profile: profile to check against
-+ * @gfp: memory allocation flags
-+ * @msg: string describing syscall being rejected
-+ */
-+int aa_audit_syscallreject(struct aa_profile *profile, gfp_t gfp,
-+                         const char *msg)
-+{
-+      struct aa_audit sa;
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = "syscall";
-+      sa.name = msg;
-+      sa.gfp_mask = gfp;
-+      sa.error_code = -EPERM;
-+
-+      return aa_audit_base(profile, &sa, current->audit_context,
-+                           AUDIT_APPARMOR_DENIED);
-+}
-+
-+int aa_audit_message(struct aa_profile *profile, struct aa_audit *sa,
-+                    int type)
-+{
-+      struct audit_context *audit_cxt;
-+
-+      audit_cxt = apparmor_logsyscall ? current->audit_context : NULL;
-+      return aa_audit_base(profile, sa, audit_cxt, type);
-+}
-+
-+void aa_audit_hint(struct aa_profile *profile, struct aa_audit *sa)
-+{
-+      aa_audit_message(profile, sa, AUDIT_APPARMOR_HINT);
-+}
-+
-+void aa_audit_status(struct aa_profile *profile, struct aa_audit *sa)
-+{
-+      aa_audit_message(profile, sa, AUDIT_APPARMOR_STATUS);
-+}
-+
-+int aa_audit_reject(struct aa_profile *profile, struct aa_audit *sa)
-+{
-+      return aa_audit_message(profile, sa, AUDIT_APPARMOR_DENIED);
-+}
-+
-+/**
-+ * aa_audit - Log an audit event to the audit subsystem
-+ * @profile: profile to check against
-+ * @sa: audit event
-+ */
-+int aa_audit(struct aa_profile *profile, struct aa_audit *sa)
-+{
-+      int type = AUDIT_APPARMOR_DENIED;
-+      struct audit_context *audit_cxt;
-+
-+      if (likely(!sa->error_code))
-+              type = AUDIT_APPARMOR_AUDIT;
-+      else if (PROFILE_COMPLAIN(profile))
-+              type = AUDIT_APPARMOR_ALLOWED;
-+
-+      audit_cxt = apparmor_logsyscall ? current->audit_context : NULL;
-+      return aa_audit_base(profile, sa, audit_cxt, type);
-+}
-+
-+static int aa_audit_file(struct aa_profile *profile, struct aa_audit *sa)
-+{
-+      if (likely(!sa->error_code)) {
-+              int mask = sa->audit_mask & AUDIT_FILE_MASK;
-+
-+              if (unlikely(PROFILE_AUDIT(profile)))
-+                      mask |= AUDIT_FILE_MASK;
-+
-+              if (likely(!(sa->request_mask & mask)))
-+                      return 0;
-+
-+              /* mask off perms that are not being force audited */
-+              sa->request_mask &= mask | ALL_AA_EXEC_TYPE;
-+      } else {
-+              int mask = AUDIT_QUIET_MASK(sa->audit_mask);
-+
-+              if (!(sa->denied_mask & ~mask))
-+                      return sa->error_code;
-+
-+              /* mask off perms whose denial is being silenced */
-+              sa->denied_mask &= (~mask) | ALL_AA_EXEC_TYPE;
-+      }
-+
-+      return aa_audit(profile, sa);
-+}
-+
-+static int aa_audit_caps(struct aa_profile *profile, struct aa_audit *sa,
-+                       int cap)
-+{
-+      if (likely(!sa->error_code)) {
-+              if (likely(!PROFILE_AUDIT(profile) &&
-+                         !cap_raised(profile->audit_caps, cap)))
-+                      return 0;
-+      }
-+
-+      /* quieting of capabilities is handled the caps_logged cache */
-+      return aa_audit(profile, sa);
-+}
-+
-+/**
-+ * aa_file_denied - check for @mask access on a file
-+ * @profile: profile to check against
-+ * @name: pathname of file
-+ * @mask: permission mask requested for file
-+ * @audit_mask: return audit mask for the match
-+ *
-+ * Return %0 on success, or else the permissions in @mask that the
-+ * profile denies.
-+ */
-+static int aa_file_denied(struct aa_profile *profile, const char *name,
-+                        int mask, int *audit_mask)
-+{
-+      return (mask & ~aa_match(profile->file_rules, name, audit_mask));
-+}
-+
-+/**
-+ * aa_link_denied - check for permission to link a file
-+ * @profile: profile to check against
-+ * @link: pathname of link being created
-+ * @target: pathname of target to be linked to
-+ * @target_mode: UGO shift for target inode
-+ * @request_mask: the permissions subset valid only if link succeeds
-+ * @audit_mask: return the audit_mask for the link permission
-+ * Return %0 on success, or else the permissions that the profile denies.
-+ */
-+static int aa_link_denied(struct aa_profile *profile, const char *link,
-+                        const char *target, int target_mode,
-+                        int *request_mask, int *audit_mask)
-+{
-+      unsigned int state;
-+      int l_mode, t_mode, l_x, t_x, denied_mask = 0;
-+      int link_mask = AA_MAY_LINK << target_mode;
-+
-+      *request_mask = link_mask;
-+
-+      l_mode = aa_match_state(profile->file_rules, DFA_START, link, &state);
-+
-+      if (l_mode & link_mask) {
-+              int mode;
-+              /* test to see if target can be paired with link */
-+              state = aa_dfa_null_transition(profile->file_rules, state);
-+              mode = aa_match_state(profile->file_rules, state, target,
-+                                    &state);
-+
-+              if (!(mode & link_mask))
-+                      denied_mask |= link_mask;
-+
-+              *audit_mask = dfa_audit_mask(profile->file_rules, state);
-+
-+              /* return if link subset test is not required */
-+              if (!(mode & (AA_LINK_SUBSET_TEST << target_mode)))
-+                      return denied_mask;
-+      }
-+
-+      /* Do link perm subset test requiring permission on link are a
-+       * subset of the permissions on target.
-+       * If a subset test is required a permission subset test of the
-+       * perms for the link are done against the user::other of the
-+       * target's 'r', 'w', 'x', 'a', 'k', and 'm' permissions.
-+       *
-+       * If the link has 'x', an exact match of all the execute flags
-+       * must match.
-+       */
-+      denied_mask |= ~l_mode & link_mask;
-+
-+      t_mode = aa_match(profile->file_rules, target, NULL);
-+
-+      l_x = l_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
-+      t_x = t_mode & (ALL_AA_EXEC_TYPE | AA_EXEC_BITS);
-+
-+      /* For actual subset test ignore valid-profile-transition flags,
-+       * and link bits
-+       */
-+      l_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
-+      t_mode &= AA_FILE_PERMS & ~AA_LINK_BITS;
-+
-+      *request_mask = l_mode | link_mask;
-+
-+      if (l_mode) {
-+              int x = l_x | (t_x & ALL_AA_EXEC_UNSAFE);
-+              denied_mask |= l_mode & ~t_mode;
-+              /* mask off x modes not used by link */
-+
-+              /* handle exec subset
-+               * - link safe exec issubset of unsafe exec
-+               * - no link x perm is subset of target having x perm
-+               */
-+              if ((l_mode & AA_USER_EXEC) &&
-+                  (x & AA_USER_EXEC_TYPE) != (t_x & AA_USER_EXEC_TYPE))
-+                      denied_mask = AA_USER_EXEC | (l_x & AA_USER_EXEC_TYPE);
-+              if ((l_mode & AA_OTHER_EXEC) &&
-+                  (x & AA_OTHER_EXEC_TYPE) != (t_x & AA_OTHER_EXEC_TYPE))
-+                      denied_mask = AA_OTHER_EXEC | (l_x & AA_OTHER_EXEC_TYPE);
-+      }
-+
-+      return denied_mask;
-+}
-+
-+/**
-+ * aa_get_name - compute the pathname of a file
-+ * @dentry: dentry of the file
-+ * @mnt: vfsmount of the file
-+ * @buffer: buffer that aa_get_name() allocated
-+ * @check: AA_CHECK_DIR is set if the file is a directory
-+ *
-+ * Returns a pointer to the beginning of the pathname (which usually differs
-+ * from the beginning of the buffer), or an error code.
-+ *
-+ * We need @check 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.
-+ */
-+static char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt,
-+                       char **buffer, int check)
-+{
-+      char *name;
-+      int is_dir, size = 256;
-+
-+      is_dir = (check & AA_CHECK_DIR) ? 1 : 0;
-+
-+      for (;;) {
-+              char *buf = kmalloc(size, GFP_KERNEL);
-+              if (!buf)
-+                      return ERR_PTR(-ENOMEM);
-+
-+              name = d_namespace_path(dentry, mnt, buf, size - is_dir);
-+              if (!IS_ERR(name)) {
-+                      if (name[0] != '/') {
-+                              /*
-+                               * This dentry is not connected to the
-+                               * namespace root -- reject access.
-+                               */
-+                              kfree(buf);
-+                              return ERR_PTR(-ENOENT);
-+                      }
-+                      if (is_dir && name[1] != '\0') {
-+                              /*
-+                               * Append "/" to the pathname. The root
-+                               * directory is a special case; it already
-+                               * ends in slash.
-+                               */
-+                              buf[size - 2] = '/';
-+                              buf[size - 1] = '\0';
-+                      }
-+
-+                      *buffer = buf;
-+                      return name;
-+              }
-+              if (PTR_ERR(name) != -ENAMETOOLONG)
-+                      return name;
-+
-+              kfree(buf);
-+              size <<= 1;
-+              if (size > apparmor_path_max)
-+                      return ERR_PTR(-ENAMETOOLONG);
-+      }
-+}
-+
-+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;
-+}
-+static inline void aa_put_name_buffer(char *buffer)
-+{
-+      kfree(buffer);
-+}
-+
-+/**
-+ * aa_perm_dentry - check if @profile allows @mask for a file
-+ * @profile: profile to check against
-+ * @dentry: dentry of the file
-+ * @mnt: vfsmount o the file
-+ * @sa: audit context
-+ * @mask: requested profile permissions
-+ * @check: kind of check to perform
-+ *
-+ * Returns 0 upon success, or else an error code.
-+ *
-+ * @check indicates the file type, and whether the file was accessed through
-+ * an open file descriptor (AA_CHECK_FD) or not.
-+ */
-+static int aa_perm_dentry(struct aa_profile *profile, struct dentry *dentry,
-+                        struct vfsmount *mnt, struct aa_audit *sa, int check)
-+{
-+      int error;
-+      char *buffer = NULL;
-+
-+      sa->name = aa_get_name(dentry, mnt, &buffer, check);
-+      sa->request_mask <<= aa_inode_mode(dentry->d_inode);
-+      if (IS_ERR(sa->name)) {
-+              /*
-+               * deleted files are given a pass on permission checks when
-+               * accessed through a file descriptor.
-+               */
-+              if (PTR_ERR(sa->name) == -ENOENT && (check & AA_CHECK_FD))
-+                      sa->denied_mask = 0;
-+              else {
-+                      sa->denied_mask = sa->request_mask;
-+                      sa->error_code = PTR_ERR(sa->name);
-+                      if (sa->error_code == -ENOENT)
-+                              sa->info = "Failed name resolution - object not a valid entry";
-+                      else if (sa->error_code == -ENAMETOOLONG)
-+                              sa->info = "Failed name resolution - name too long";
-+                      else
-+                              sa->info = "Failed name resolution";
-+              }
-+              sa->name = NULL;
-+      } else
-+              sa->denied_mask = aa_file_denied(profile, sa->name,
-+                                               sa->request_mask,
-+                                               &sa->audit_mask);
-+
-+      if (!sa->denied_mask)
-+              sa->error_code = 0;
-+
-+      error = aa_audit_file(profile, sa);
-+      aa_put_name_buffer(buffer);
-+
-+      return error;
-+}
-+
-+/**
-+ * aa_attr - check if attribute change is allowed
-+ * @profile: profile to check against
-+ * @dentry: dentry of the file to check
-+ * @mnt: vfsmount of the file to check
-+ * @iattr: attribute changes requested
-+ */
-+int aa_attr(struct aa_profile *profile, struct dentry *dentry,
-+          struct vfsmount *mnt, struct iattr *iattr)
-+{
-+      struct inode *inode = dentry->d_inode;
-+      int error, check;
-+      struct aa_audit sa;
-+
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = "setattr";
-+      sa.gfp_mask = GFP_KERNEL;
-+      sa.iattr = iattr;
-+      sa.request_mask = MAY_WRITE;
-+      sa.error_code = -EACCES;
-+
-+      check = 0;
-+      if (inode && S_ISDIR(inode->i_mode))
-+              check |= AA_CHECK_DIR;
-+      if (iattr->ia_valid & ATTR_FILE)
-+              check |= AA_CHECK_FD;
-+
-+      error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
-+
-+      return error;
-+}
-+
-+/**
-+ * aa_perm_xattr - check if xattr attribute change is allowed
-+ * @profile: profile to check against
-+ * @dentry: dentry of the file to check
-+ * @mnt: vfsmount of the file to check
-+ * @operation: xattr operation being done
-+ * @mask: access mode requested
-+ * @check: kind of check to perform
-+ */
-+int aa_perm_xattr(struct aa_profile *profile, const char *operation,
-+                struct dentry *dentry, struct vfsmount *mnt, int mask,
-+                int check)
-+{
-+      struct inode *inode = dentry->d_inode;
-+      int error;
-+      struct aa_audit sa;
-+
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = operation;
-+      sa.gfp_mask = GFP_KERNEL;
-+      sa.request_mask = mask;
-+      sa.error_code = -EACCES;
-+
-+      if (inode && S_ISDIR(inode->i_mode))
-+              check |= AA_CHECK_DIR;
-+
-+      error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
-+
-+      return error;
-+}
-+
-+/**
-+ * aa_perm - basic apparmor permissions check
-+ * @profile: profile to check against
-+ * @dentry: dentry of the file to check
-+ * @mnt: vfsmount of the file to check
-+ * @mask: access mode requested
-+ * @check: kind of check to perform
-+ *
-+ * Determine if access @mask for the file is authorized by @profile.
-+ * Returns 0 on success, or else an error code.
-+ */
-+int aa_perm(struct aa_profile *profile, const char *operation,
-+          struct dentry *dentry, struct vfsmount *mnt, int mask, int check)
-+{
-+      struct aa_audit sa;
-+      int error = 0;
-+
-+      if (mask == 0)
-+              goto out;
-+
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = operation;
-+      sa.gfp_mask = GFP_KERNEL;
-+      sa.request_mask = mask;
-+      sa.error_code = -EACCES;
-+
-+      error = aa_perm_dentry(profile, dentry, mnt, &sa, check);
-+
-+out:
-+      return error;
-+}
-+
-+/**
-+ * aa_perm_dir
-+ * @profile: profile to check against
-+ * @dentry: dentry of directory to check
-+ * @mnt: vfsmount of directory to check
-+ * @operation: directory operation being performed
-+ * @mask: access mode requested
-+ *
-+ * Determine if directory operation (make/remove) for dentry is authorized
-+ * by @profile.
-+ * Returns 0 on success, or else an error code.
-+ */
-+int aa_perm_dir(struct aa_profile *profile, const char *operation,
-+              struct dentry *dentry, struct vfsmount *mnt, int mask)
-+{
-+      struct aa_audit sa;
-+
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = operation;
-+      sa.gfp_mask = GFP_KERNEL;
-+      sa.request_mask = mask;
-+      sa.error_code = -EACCES;
-+
-+      return aa_perm_dentry(profile, dentry, mnt, &sa, AA_CHECK_DIR);
-+}
-+
-+int aa_perm_path(struct aa_profile *profile, const char *operation,
-+               const char *name, int mask, uid_t uid)
-+{
-+      struct aa_audit sa;
-+
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = operation;
-+      sa.gfp_mask = GFP_KERNEL;
-+      sa.request_mask = mask;
-+      sa.name = name;
-+      if (current->fsuid == uid)
-+              sa.request_mask = mask << AA_USER_SHIFT;
-+      else
-+              sa.request_mask = mask << AA_OTHER_SHIFT;
-+
-+      sa.denied_mask = aa_file_denied(profile, name, sa.request_mask,
-+                                      &sa.audit_mask) ;
-+      sa.error_code = sa.denied_mask ? -EACCES : 0;
-+
-+      return aa_audit_file(profile, &sa);
-+}
-+
-+/**
-+ * aa_capability - test permission to use capability
-+ * @cxt: aa_task_context with profile to check against
-+ * @cap: capability to be tested
-+ *
-+ * Look up capability in profile capability set.
-+ * Returns 0 on success, or else an error code.
-+ */
-+int aa_capability(struct aa_task_context *cxt, int cap)
-+{
-+      int error = cap_raised(cxt->profile->capabilities, cap) ? 0 : -EPERM;
-+      struct aa_audit sa;
-+
-+      /* test if cap has alread been logged */
-+      if (cap_raised(cxt->caps_logged, cap)) {
-+              if (PROFILE_COMPLAIN(cxt->profile))
-+                      error = 0;
-+              return error;
-+      } else
-+              /* don't worry about rcu replacement of the cxt here.
-+               * caps_logged is a cache to reduce the occurence of
-+               * duplicate messages in the log.  The worst that can
-+               * happen is duplicate capability messages shows up in
-+               * the audit log
-+               */
-+              cap_raise(cxt->caps_logged, cap);
-+
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = "capable";
-+      sa.gfp_mask = GFP_ATOMIC;
-+      sa.name = capability_names[cap];
-+      sa.error_code = error;
-+
-+      error = aa_audit_caps(cxt->profile, &sa, cap);
-+
-+      return error;
-+}
-+
-+/* must be used inside rcu_read_lock or task_lock */
-+int aa_may_ptrace(struct aa_task_context *cxt, struct aa_profile *tracee)
-+{
-+      if (!cxt || cxt->profile == tracee)
-+              return 0;
-+      return aa_capability(cxt, CAP_SYS_PTRACE);
-+}
-+
-+/**
-+ * aa_link - hard link check
-+ * @profile: profile to check against
-+ * @link: dentry of link being created
-+ * @link_mnt: vfsmount of link being created
-+ * @target: dentry of link target
-+ * @target_mnt: vfsmunt of link target
-+ *
-+ * Returns 0 on success, or else an error code.
-+ */
-+int aa_link(struct aa_profile *profile,
-+          struct dentry *link, struct vfsmount *link_mnt,
-+          struct dentry *target, struct vfsmount *target_mnt)
-+{
-+      int error;
-+      struct aa_audit sa;
-+      char *buffer = NULL, *buffer2 = NULL;
-+
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = "inode_link";
-+      sa.gfp_mask = GFP_KERNEL;
-+      sa.name = aa_get_name(link, link_mnt, &buffer, 0);
-+      sa.name2 = aa_get_name(target, target_mnt, &buffer2, 0);
-+
-+      if (IS_ERR(sa.name)) {
-+              sa.error_code = PTR_ERR(sa.name);
-+              sa.name = NULL;
-+      }
-+      if (IS_ERR(sa.name2)) {
-+              sa.error_code = PTR_ERR(sa.name2);
-+              sa.name2 = NULL;
-+      }
-+
-+      if (sa.name && sa.name2) {
-+              sa.denied_mask = aa_link_denied(profile, sa.name, sa.name2,
-+                                              aa_inode_mode(target->d_inode),
-+                                              &sa.request_mask,
-+                                              &sa.audit_mask);
-+              sa.error_code = sa.denied_mask ? -EACCES : 0;
-+      }
-+
-+      error = aa_audit_file(profile, &sa);
-+
-+      aa_put_name_buffer(buffer);
-+      aa_put_name_buffer(buffer2);
-+
-+      return error;
-+}
-+
-+int aa_net_perm(struct aa_profile *profile, char *operation,
-+              int family, int type, int protocol)
-+{
-+      struct aa_audit sa;
-+      int error = 0;
-+      u16 family_mask, audit_mask, quiet_mask;
-+
-+      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->network_families[family];
-+      audit_mask = profile->audit_network[family];
-+      quiet_mask = profile->quiet_network[family];
-+
-+      error = (family_mask & (1 << type)) ? 0 : -EACCES;
-+
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = operation;
-+      sa.gfp_mask = GFP_KERNEL;
-+      sa.family = family;
-+      sa.type = type;
-+      sa.protocol = protocol;
-+      sa.error_code = error;
-+
-+      if (likely(!error)) {
-+              if (!PROFILE_AUDIT(profile) && !(family_mask & audit_mask))
-+                      return 0;
-+      } else if (!((1 << type) & ~quiet_mask)) {
-+              return error;
-+      }
-+
-+      error = aa_audit(profile, &sa);
-+
-+      return error;
-+}
-+
-+int aa_revalidate_sk(struct sock *sk, char *operation)
-+{
-+      struct aa_profile *profile;
-+      int error = 0;
-+
-+      /* this is some debugging code to flush out the network hooks that
-+         that are called in interrupt context */
-+      if (in_interrupt()) {
-+              printk("AppArmor Debug: Hook being called from interrupt context\n");
-+              dump_stack();
-+              return 0;
-+      }
-+
-+      profile = aa_get_profile(current);
-+      if (profile)
-+              error = aa_net_perm(profile, operation,
-+                                  sk->sk_family, sk->sk_type,
-+                                  sk->sk_protocol);
-+      aa_put_profile(profile);
-+
-+      return error;
-+}
-+/**
-+ * aa_task_setrlimit - test permission to set an rlimit
-+ * @profile - profile confining the task
-+ * @resource - the resource being set
-+ * @new_rlim - the new resource limit
-+ *
-+ * Control raising the processes hard limit.
-+ */
-+int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
-+                    struct rlimit *new_rlim)
-+{
-+      struct aa_audit sa;
-+      int error = 0;
-+
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = "setrlimit";
-+      sa.gfp_mask = GFP_KERNEL;
-+      sa.rlimit = resource + 1;
-+
-+      if (profile->rlimits.mask & (1 << resource) &&
-+          new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max) {
-+              sa.error_code = -EACCES;
-+
-+              error = aa_audit(profile, &sa);
-+      }
-+
-+      return error;
-+}
-+
-+static int aa_rlimit_nproc(struct aa_profile *profile) {
-+      if (profile && (profile->rlimits.mask & (1 << RLIMIT_NPROC)) &&
-+          profile->task_count >= profile->rlimits.limits[RLIMIT_NPROC].rlim_max)
-+              return -EAGAIN;
-+      return 0;
-+}
-+
-+void aa_set_rlimits(struct task_struct *task, struct aa_profile *profile)
-+{
-+      int i, mask;
-+
-+      if (!profile)
-+              return;
-+
-+      if (!profile->rlimits.mask)
-+              return;
-+
-+      task_lock(task->group_leader);
-+      mask = 1;
-+      for (i = 0; i < RLIM_NLIMITS; i++, mask <<= 1) {
-+              struct rlimit new_rlim, *old_rlim;
-+
-+              /* check to see if NPROC which is per profile and handled
-+               * in clone/exec or whether this is a limit to be set
-+               * can't set cpu limit either right now
-+               */
-+              if (i == RLIMIT_NPROC || i == RLIMIT_CPU)
-+                      continue;
-+
-+              old_rlim = task->signal->rlim + i;
-+              new_rlim = *old_rlim;
-+
-+              if (mask & profile->rlimits.mask &&
-+                  profile->rlimits.limits[i].rlim_max < new_rlim.rlim_max) {
-+                      new_rlim.rlim_max = profile->rlimits.limits[i].rlim_max;
-+                      /* soft limit should not exceed hard limit */
-+                      if (new_rlim.rlim_cur > new_rlim.rlim_max)
-+                              new_rlim.rlim_cur = new_rlim.rlim_max;
-+              }
-+
-+              *old_rlim = new_rlim;
-+      }
-+      task_unlock(task->group_leader);
-+}
-+
-+/*******************************
-+ * Global task related functions
-+ *******************************/
-+
-+/**
-+ * aa_clone - initialize the task context for a new task
-+ * @child: task that is being created
-+ *
-+ * Returns 0 on success, or else an error code.
-+ */
-+int aa_clone(struct task_struct *child)
-+{
-+      struct aa_audit sa;
-+      struct aa_task_context *cxt, *child_cxt;
-+      struct aa_profile *profile;
-+
-+      if (!aa_task_context(current))
-+              return 0;
-+      child_cxt = aa_alloc_task_context(GFP_KERNEL);
-+      if (!child_cxt)
-+              return -ENOMEM;
-+
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = "clone";
-+      sa.task = child->pid;
-+      sa.gfp_mask = GFP_KERNEL;
-+
-+repeat:
-+      profile = aa_get_profile(current);
-+      if (profile) {
-+              lock_profile(profile);
-+              cxt = aa_task_context(current);
-+              if (unlikely(profile->isstale || !cxt ||
-+                           cxt->profile != profile)) {
-+                      /**
-+                       * Race with profile replacement or removal, or with
-+                       * task context removal.
-+                       */
-+                      unlock_profile(profile);
-+                      aa_put_profile(profile);
-+                      goto repeat;
-+              }
-+
-+              if (aa_rlimit_nproc(profile)) {
-+                      sa.info = "rlimit nproc limit exceeded";
-+                      unlock_profile(profile);
-+                      aa_audit_reject(profile, &sa);
-+                      aa_put_profile(profile);
-+                      return -EAGAIN;
-+              }
-+
-+              /* No need to grab the child's task lock here. */
-+              aa_change_task_context(child, child_cxt, profile,
-+                                     cxt->cookie, cxt->previous_profile);
-+
-+              unlock_profile(profile);
-+
-+              if (APPARMOR_COMPLAIN(child_cxt) &&
-+                  profile == profile->ns->null_complain_profile) {
-+                      aa_audit_hint(profile, &sa);
-+              }
-+              aa_put_profile(profile);
-+      } else
-+              aa_free_task_context(child_cxt);
-+
-+      return 0;
-+}
-+
-+static struct aa_profile *
-+aa_register_find(struct aa_profile *profile, const char* ns_name,
-+               const char *name, int mandatory, int complain,
-+               struct aa_audit *sa)
-+{
-+      struct aa_namespace *ns;
-+      struct aa_profile *new_profile;
-+      int ns_ref = 0;
-+
-+      if (profile)
-+              ns = profile->ns;
-+      else
-+              ns = default_namespace;
-+
-+      if (ns_name) {
-+              /* locate the profile namespace */
-+              ns = aa_find_namespace(ns_name);
-+              if (!ns) {
-+                      if (mandatory) {
-+                              sa->info = "profile namespace not found";
-+                              sa->denied_mask = sa->request_mask;
-+                              sa->error_code = -ENOENT;
-+                              return ERR_PTR(-ENOENT);
-+                      } else {
-+                              return NULL;
-+                      }
-+              }
-+              ns_ref++;
-+      }
-+
-+      /* Locate new profile */
-+      new_profile = aa_find_profile(ns, name);
-+
-+      if (new_profile) {
-+              AA_DEBUG("%s: setting profile %s\n",
-+                       __FUNCTION__, new_profile->name);
-+      } else if (mandatory && profile) {
-+              sa->info = "mandatory profile missing";
-+              sa->denied_mask = sa->request_mask;     /* shifted MAY_EXEC */
-+              if (complain) {
-+                      aa_audit_hint(profile, sa);
-+                      new_profile =
-+                          aa_dup_profile(profile->ns->null_complain_profile);
-+              } else {
-+                      sa->error_code = -EACCES;
-+                      if (ns_ref)
-+                              aa_put_namespace(ns);
-+                      return ERR_PTR(-EACCES);
-+              }
-+      } else {
-+              /* Only way we can get into this code is if task
-+               * is unconfined, pix, nix.
-+               */
-+              AA_DEBUG("%s: No profile found for exec image '%s'\n",
-+                       __FUNCTION__,
-+                       name);
-+      }
-+      if (ns_ref)
-+              aa_put_namespace(ns);
-+      return new_profile;
-+}
-+
-+static struct aa_profile *
-+aa_x_to_profile(struct aa_profile *profile, const char *filename, int xmode,
-+              struct aa_audit *sa, char **child)
-+{
-+      struct aa_profile *new_profile = NULL;
-+      int ix = xmode & AA_EXEC_INHERIT;
-+      int complain = PROFILE_COMPLAIN(profile);
-+      int index;
-+
-+      *child = NULL;
-+      switch (xmode & AA_EXEC_MODIFIERS) {
-+      case 0:
-+              /* only valid with ix flag */
-+              ix = 1;
-+              break;
-+      case AA_EXEC_UNCONFINED:
-+              /* only valid without ix flag */
-+              ix = 0;
-+              break;
-+      case AA_EXEC_PROFILE:
-+              new_profile = aa_register_find(profile, NULL, filename, !ix,
-+                                             complain, sa);
-+              break;
-+      case AA_EXEC_CHILD:
-+              *child = new_compound_name(profile->name, filename);
-+              sa->name2 = *child;
-+              if (!*child) {
-+                      sa->info = "Failed name resolution - exec failed";
-+                      sa->error_code = -ENOMEM;
-+                      new_profile = ERR_PTR(-ENOMEM);
-+              } else {
-+                      new_profile = aa_register_find(profile, NULL, *child,
-+                                                     !ix, complain, sa);
-+              }
-+              break;
-+      default:
-+              /* all other indexes are named transitions */
-+              index = AA_EXEC_INDEX(xmode);
-+              if (index - 4 > profile->exec_table_size) {
-+                      sa->info = "invalid named transition - exec failed";
-+                      sa->error_code = -EACCES;
-+                      new_profile = ERR_PTR(-EACCES);
-+              } else {
-+                      char *ns_name = NULL;
-+                      char *name = profile->exec_table[index - 4];
-+                      if (*name == ':') {
-+                              ns_name = name + 1;
-+                              name = ns_name + strlen(ns_name) + 1;
-+                      }
-+                      sa->name2 = name;
-+                      sa->name3 = ns_name;
-+                      new_profile =
-+                              aa_register_find(profile, ns_name, name,
-+                                               !ix, complain, sa);
-+              }
-+      }
-+      if (IS_ERR(new_profile))
-+              /* all these failures must be audited - no quieting */
-+              return ERR_PTR(aa_audit_reject(profile, sa));
-+      return new_profile;
-+}
-+
-+/**
-+ * aa_register - register a new program
-+ * @bprm: binprm of program being registered
-+ *
-+ * Try to register a new program during execve().  This should give the
-+ * new program a valid aa_task_context if confined.
-+ */
-+int aa_register(struct linux_binprm *bprm)
-+{
-+      const char *filename;
-+      char  *buffer = NULL, *child = NULL;
-+      struct file *filp = bprm->file;
-+      struct aa_profile *profile, *old_profile, *new_profile = NULL;
-+      int exec_mode, complain = 0, shift;
-+      struct aa_audit sa;
-+
-+      AA_DEBUG("%s\n", __FUNCTION__);
-+
-+      profile = aa_get_profile(current);
-+
-+      shift = aa_inode_mode(filp->f_dentry->d_inode);
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = "exec";
-+      sa.gfp_mask = GFP_KERNEL;
-+      sa.request_mask = MAY_EXEC << shift;
-+
-+      filename = aa_get_name(filp->f_dentry, filp->f_vfsmnt, &buffer, 0);
-+      if (IS_ERR(filename)) {
-+              if (profile) {
-+                      sa.info = "Failed name resolution - exec failed";
-+                      sa.error_code = PTR_ERR(filename);
-+                      aa_audit_file(profile, &sa);
-+                      return sa.error_code;
-+              } else
-+                      return 0;
-+      }
-+      sa.name = filename;
-+
-+      exec_mode = AA_EXEC_UNSAFE << shift;
-+
-+repeat:
-+      if (profile) {
-+              complain = PROFILE_COMPLAIN(profile);
-+
-+              /* Confined task, determine what mode inherit, unconfined or
-+               * mandatory to load new profile
-+               */
-+              exec_mode = aa_match(profile->file_rules, filename,
-+                                   &sa.audit_mask);
-+
-+
-+              if (exec_mode & sa.request_mask) {
-+                      int xm = exec_mode >> shift;
-+                      new_profile = aa_x_to_profile(profile, filename,
-+                                                    xm, &sa, &child);
-+
-+                      if (!new_profile && (xm & AA_EXEC_INHERIT))
-+                              /* (p|c|n|)ix - don't change profile */
-+                              goto cleanup;
-+                      /* error case caught below */
-+
-+              } else if (sa.request_mask & AUDIT_QUIET_MASK(sa.audit_mask)) {
-+                      /* quiet failed exit */
-+                      new_profile = ERR_PTR(-EACCES);
-+              } else if (complain) {
-+                      /* There was no entry in calling profile
-+                       * describing mode to execute image in.
-+                       * Drop into null-profile (disabling secure exec).
-+                       */
-+                      new_profile =
-+                          aa_dup_profile(profile->ns->null_complain_profile);
-+                      exec_mode |= AA_EXEC_UNSAFE << shift;
-+              } else {
-+                      sa.denied_mask = sa.request_mask;
-+                      sa.error_code = -EACCES;
-+                      new_profile = ERR_PTR(aa_audit_file(profile, &sa));
-+              }
-+      } else {
-+              /* Unconfined task, load profile if it exists */
-+              new_profile = aa_register_find(NULL, NULL, filename, 0, 0, &sa);
-+              if (new_profile == NULL)
-+                      goto cleanup;
-+      }
-+
-+      if (IS_ERR(new_profile))
-+              goto cleanup;
-+
-+      old_profile = __aa_replace_profile(current, new_profile);
-+      if (IS_ERR(old_profile)) {
-+              aa_put_profile(new_profile);
-+              aa_put_profile(profile);
-+              if (PTR_ERR(old_profile) == -ESTALE) {
-+                      profile = aa_get_profile(current);
-+                      goto repeat;
-+              }
-+              if (PTR_ERR(old_profile) == -EPERM) {
-+                      sa.denied_mask = sa.request_mask;
-+                      sa.info = "unable to set profile due to ptrace";
-+                      sa.task = current->parent->pid;
-+                      aa_audit_reject(profile, &sa);
-+              }
-+              if (PTR_ERR(old_profile) == -EAGAIN) {
-+                      sa.info = "rlimit nproc limit exceeded";
-+                      aa_audit_reject(profile, &sa);
-+              }
-+              new_profile = old_profile;
-+              goto cleanup;
-+      }
-+      aa_put_profile(old_profile);
-+      aa_put_profile(profile);
-+
-+      /* Handle confined exec.
-+       * 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")
-+       */
-+      if (!(exec_mode & (AA_EXEC_UNSAFE << shift))) {
-+              unsigned long bprm_flags;
-+
-+              bprm_flags = AA_SECURE_EXEC_NEEDED;
-+              bprm->security = (void*)
-+                      ((unsigned long)bprm->security | bprm_flags);
-+      }
-+
-+      if (complain && new_profile &&
-+          new_profile == new_profile->ns->null_complain_profile) {
-+              sa.request_mask = 0;
-+              sa.name = NULL;
-+              sa.info = "set profile";
-+              aa_audit_hint(new_profile, &sa);
-+      }
-+
-+cleanup:
-+      aa_put_name_buffer(child);
-+      aa_put_name_buffer(buffer);
-+      if (IS_ERR(new_profile))
-+              return PTR_ERR(new_profile);
-+      aa_put_profile(new_profile);
-+      return 0;
-+}
-+
-+/**
-+ * aa_release - release a task context
-+ * @task: task being released
+diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
+new file mode 100644
+index 0000000..cb8a121
+--- /dev/null
++++ b/security/apparmor/include/net.h
+@@ -0,0 +1,44 @@
++/*
++ * AppArmor security module
++ *
++ * This file contains AppArmor network mediation definitions.
++ *
++ * Copyright (C) 1998-2008 Novell/SUSE
++ * Copyright 2009-2012 Canonical Ltd.
 + *
-+ * This is called after a task has exited and the parent has reaped it.
++ * 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.
 + */
-+void aa_release(struct task_struct *task)
-+{
-+      struct aa_task_context *cxt;
-+      struct aa_profile *profile;
-+      /*
-+       * While the task context is still on a profile's task context
-+       * list, another process could replace the profile under us,
-+       * leaving us with a locked profile that is no longer attached
-+       * to this task. So after locking the profile, we check that
-+       * the profile is still attached.  The profile lock is
-+       * sufficient to prevent the replacement race so we do not lock
-+       * the task.
-+       *
-+       * Use lock subtyping to avoid lockdep reporting a false irq
-+       * possible inversion between the task_lock and profile_lock
-+       *
-+       * We also avoid taking the task_lock here because lock_dep
-+       * would report another false {softirq-on-W} potential irq_lock
-+       * inversion.
-+       *
-+       * If the task does not have a profile attached we are safe;
-+       * nothing can race with us at this point.
-+       */
-+
-+repeat:
-+      profile = aa_get_profile(task);
-+      if (profile) {
-+              lock_profile_nested(profile, aa_lock_task_release);
-+              cxt = aa_task_context(task);
-+              if (unlikely(!cxt || cxt->profile != profile)) {
-+                      unlock_profile(profile);
-+                      aa_put_profile(profile);
-+                      goto repeat;
-+              }
-+              aa_change_task_context(task, NULL, NULL, 0, NULL);
-+              unlock_profile(profile);
-+              aa_put_profile(profile);
-+      }
-+}
-+
-+static int do_change_profile(struct aa_profile *expected,
-+                           struct aa_namespace *ns, const char *name,
-+                           u64 cookie, int restore, int hat,
-+                           struct aa_audit *sa)
-+{
-+      struct aa_profile *new_profile = NULL, *old_profile = NULL,
-+              *previous_profile = NULL;
-+      struct aa_task_context *new_cxt, *cxt;
-+      int error = 0;
-+
-+      sa->name = name;
 +
-+      new_cxt = aa_alloc_task_context(GFP_KERNEL);
-+      if (!new_cxt)
-+              return -ENOMEM;
++#ifndef __AA_NET_H
++#define __AA_NET_H
 +
-+      new_profile = aa_find_profile(ns, name);
-+      if (!new_profile && !restore) {
-+              if (!PROFILE_COMPLAIN(expected)) {
-+                      aa_free_task_context(new_cxt);
-+                      return -ENOENT;
-+              }
-+              new_profile = aa_dup_profile(ns->null_complain_profile);
-+      } else if (new_profile && hat && !PROFILE_IS_HAT(new_profile)) {
-+              aa_free_task_context(new_cxt);
-+              aa_put_profile(new_profile);
-+              return error;
-+      }
-+
-+      cxt = lock_task_and_profiles(current, new_profile);
-+      if (!cxt) {
-+              error = -EPERM;
-+              goto out;
-+      }
-+      old_profile = cxt->profile;
-+
-+      if (cxt->profile != expected || (new_profile && new_profile->isstale)) {
-+              error = -ESTALE;
-+              goto out;
-+      }
-+
-+      if (cxt->previous_profile) {
-+              if (cxt->cookie != cookie) {
-+                      error = -EACCES;
-+                      sa->info = "killing process";
-+                      aa_audit_reject(cxt->profile, sa);
-+                      /* terminate process */
-+                      (void)send_sig_info(SIGKILL, NULL, current);
-+                      goto out;
-+              }
-+
-+              if (!restore)
-+                      previous_profile = cxt->previous_profile;
-+      } else
-+              previous_profile = cxt->profile;
-+
-+      if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, new_profile)) {
-+              error = -EACCES;
-+              goto out;
-+      }
++#include <net/sock.h>
 +
-+      if ((error = aa_rlimit_nproc(new_profile))) {
-+              sa->info = "rlimit nproc limit exceeded";
-+              aa_audit_reject(cxt->profile, sa);
-+              goto out;
-+      }
++#include "apparmorfs.h"
 +
-+      if (new_profile == ns->null_complain_profile)
-+              aa_audit_hint(cxt->profile, sa);
++/* 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];
++};
 +
-+      if (APPARMOR_AUDIT(cxt))
-+              aa_audit_message(cxt->profile, sa, AUDIT_APPARMOR_AUDIT);
++extern struct aa_fs_entry aa_fs_entry_network[];
 +
-+      if (!restore && cookie)
-+              aa_change_task_context(current, new_cxt, new_profile, cookie,
-+                                     previous_profile);
-+      else
-+              /* either return to previous_profile, or a permanent change */
-+              aa_change_task_context(current, new_cxt, new_profile, 0, NULL);
++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);
 +
-+out:
-+      if (aa_task_context(current) != new_cxt)
-+              aa_free_task_context(new_cxt);
-+      task_unlock(current);
-+      unlock_both_profiles(old_profile, new_profile);
-+      aa_put_profile(new_profile);
-+      return error;
++static inline void aa_free_net_rules(struct aa_net *new)
++{
++      /* NOP */
 +}
 +
-+/**
-+ * aa_change_profile - perform a one-way profile transition
-+ * @ns_name: name of the profile namespace to change to
-+ * @name: name of profile to change to
-+ * Change to new profile @name.  Unlike with hats, there is no way
-+ * to change back.
-+ *
-+ * Returns %0 on success, error otherwise.
-+ */
-+int aa_change_profile(const char *ns_name, const char *name)
++#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_task_context *cxt;
-+      struct aa_profile *profile = NULL;
-+      struct aa_namespace *ns = NULL;
-+      struct aa_audit sa;
-+      unsigned int state;
-+      int error = -EINVAL;
-+
-+      if (!name)
-+              return -EINVAL;
-+
-+      memset(&sa, 0, sizeof(sa));
-+      sa.gfp_mask = GFP_ATOMIC;
-+      sa.operation = "change_profile";
-+
-+repeat:
-+      task_lock(current);
-+      cxt = aa_task_context(current);
-+      if (cxt)
-+              profile = aa_dup_profile(cxt->profile);
-+      task_unlock(current);
-+
-+      if (ns_name)
-+              ns = aa_find_namespace(ns_name);
-+      else if (profile)
-+              ns = aa_get_namespace(profile->ns);
-+      else
-+              ns = aa_get_namespace(default_namespace);
-+
-+      if (!ns) {
-+              aa_put_profile(profile);
-+              return -ENOENT;
-+      }
-+
-+      if (!profile || PROFILE_COMPLAIN(profile) ||
-+          (ns == profile->ns &&
-+           (aa_match(profile->file_rules, name, NULL) & AA_CHANGE_PROFILE)))
-+              error = do_change_profile(profile, ns, name, 0, 0, 0, &sa);
-+      else {
-+              /* check for a rule with a namespace prepended */
-+              aa_match_state(profile->file_rules, DFA_START, ns->name,
-+                             &state);
-+              state = aa_dfa_null_transition(profile->file_rules, state);
-+              if ((aa_match_state(profile->file_rules, state, name, NULL) &
-+                    AA_CHANGE_PROFILE))
-+                      error = do_change_profile(profile, ns, name, 0, 0, 0,
-+                                                &sa);
-+              else
-+                      /* no permission to transition to profile @name */
-+                      error = -EACCES;
-+      }
++      struct aa_profile *profile;
++      int error = 0;
 +
-+      aa_put_namespace(ns);
-+      aa_put_profile(profile);
-+      if (error == -ESTALE)
-+              goto repeat;
++      if (kern)
++              return 0;
 +
++      profile = __aa_current_profile();
++      if (!unconfined(profile))
++              error = aa_net_perm(OP_CREATE, profile, family, type, protocol,
++                                  NULL);
 +      return error;
 +}
 +
-+/**
-+ * aa_change_hat - change hat to/from subprofile
-+ * @hat_name: hat to change to
-+ * @cookie: magic value to validate the hat change
-+ *
-+ * Change to new @hat_name, and store the @hat_magic in the current task
-+ * context.  If the new @hat_name is %NULL and the @cookie matches that
-+ * stored in the current task context and is not 0, return to the top level
-+ * profile.
-+ * Returns %0 on success, error otherwise.
-+ */
-+int aa_change_hat(const char *hat_name, u64 cookie)
++static int apparmor_socket_bind(struct socket *sock,
++                              struct sockaddr *address, int addrlen)
 +{
-+      struct aa_task_context *cxt;
-+      struct aa_profile *profile, *previous_profile;
-+      struct aa_audit sa;
-+      int error = 0;
++      struct sock *sk = sock->sk;
 +
-+      memset(&sa, 0, sizeof(sa));
-+      sa.gfp_mask = GFP_ATOMIC;
-+      sa.operation = "change_hat";
++      return aa_revalidate_sk(OP_BIND, sk);
++}
 +
-+repeat:
-+      task_lock(current);
-+      cxt = aa_task_context(current);
-+      if (!cxt) {
-+              task_unlock(current);
-+              return -EPERM;
-+      }
-+      profile = aa_dup_profile(cxt->profile);
-+      previous_profile = aa_dup_profile(cxt->previous_profile);
-+      task_unlock(current);
++static int apparmor_socket_connect(struct socket *sock,
++                                 struct sockaddr *address, int addrlen)
++{
++      struct sock *sk = sock->sk;
 +
-+      if (hat_name) {
-+              char *name, *profile_name;
++      return aa_revalidate_sk(OP_CONNECT, sk);
++}
 +
-+              if (previous_profile)
-+                      profile_name = previous_profile->name;
-+              else
-+                      profile_name = profile->name;
++static int apparmor_socket_listen(struct socket *sock, int backlog)
++{
++      struct sock *sk = sock->sk;
 +
-+              name = new_compound_name(profile_name, hat_name);
-+              if (!name) {
-+                      error = -ENOMEM;
-+                      goto out;
-+              }
-+              error = do_change_profile(profile, profile->ns, name, cookie,
-+                                        0, 1, &sa);
-+              aa_put_name_buffer(name);
-+      } else if (previous_profile)
-+              error = do_change_profile(profile, profile->ns,
-+                                        previous_profile->name, cookie, 1, 0,
-+                                        &sa);
-+      /* else ignore restores when there is no saved profile */
++      return aa_revalidate_sk(OP_LISTEN, sk);
++}
 +
-+out:
-+      aa_put_profile(previous_profile);
-+      aa_put_profile(profile);
-+      if (error == -ESTALE)
-+              goto repeat;
++static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
++{
++      struct sock *sk = sock->sk;
 +
-+      return error;
++      return aa_revalidate_sk(OP_ACCEPT, sk);
 +}
 +
-+/**
-+ * __aa_replace_profile - replace a task's profile
-+ * @task: task to switch the profile of
-+ * @profile: profile to switch to
-+ *
-+ * Returns a handle to the previous profile upon success, or else an
-+ * error code.
-+ */
-+struct aa_profile *__aa_replace_profile(struct task_struct *task,
-+                                      struct aa_profile *profile)
++static int apparmor_socket_sendmsg(struct socket *sock,
++                                 struct msghdr *msg, int size)
 +{
-+      struct aa_task_context *cxt, *new_cxt = NULL;
-+      struct aa_profile *old_profile = NULL;
++      struct sock *sk = sock->sk;
 +
-+      if (profile) {
-+              new_cxt = aa_alloc_task_context(GFP_KERNEL);
-+              if (!new_cxt)
-+                      return ERR_PTR(-ENOMEM);
-+      }
++      return aa_revalidate_sk(OP_SENDMSG, sk);
++}
 +
-+      cxt = lock_task_and_profiles(task, profile);
-+      if (unlikely(profile && profile->isstale)) {
-+              old_profile = ERR_PTR(-ESTALE);
-+              goto error;
-+      }
++static int apparmor_socket_recvmsg(struct socket *sock,
++                                 struct msghdr *msg, int size, int flags)
++{
++      struct sock *sk = sock->sk;
 +
-+      if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, profile)) {
-+              old_profile = ERR_PTR(-EPERM);
-+              goto error;
-+      }
++      return aa_revalidate_sk(OP_RECVMSG, sk);
++}
 +
-+      if (aa_rlimit_nproc(profile)) {
-+              old_profile = ERR_PTR(-EAGAIN);
-+              goto error;
-+      }
++static int apparmor_socket_getsockname(struct socket *sock)
++{
++      struct sock *sk = sock->sk;
 +
-+      if (cxt)
-+              old_profile = aa_dup_profile(cxt->profile);
-+      aa_change_task_context(task, new_cxt, profile, 0, NULL);
++      return aa_revalidate_sk(OP_GETSOCKNAME, sk);
++}
 +
-+      task_unlock(task);
-+      aa_set_rlimits(task, profile);
-+      unlock_both_profiles(profile, old_profile);
-+      return old_profile;
++static int apparmor_socket_getpeername(struct socket *sock)
++{
++      struct sock *sk = sock->sk;
 +
-+error:
-+      task_unlock(task);
-+      unlock_both_profiles(profile, cxt ? cxt->profile : NULL);
-+      aa_free_task_context(new_cxt);
-+      return old_profile;
++      return aa_revalidate_sk(OP_GETPEERNAME, sk);
 +}
 +
-+/**
-+ * lock_task_and_profiles - lock the task and confining profiles and @profile
-+ * @task: task to lock
-+ * @profile: extra profile to lock in addition to the current profile
-+ *
-+ * Handle the spinning on locking to make sure the task context and
-+ * profile are consistent once all locks are aquired.
-+ *
-+ * return the aa_task_context currently confining the task.  The task lock
-+ * will be held whether or not the task is confined.
-+ */
-+struct aa_task_context *
-+lock_task_and_profiles(struct task_struct *task, struct aa_profile *profile)
++static int apparmor_socket_getsockopt(struct socket *sock, int level,
++                                    int optname)
 +{
-+      struct aa_task_context *cxt;
-+      struct aa_profile *old_profile = NULL;
-+
-+      rcu_read_lock();
-+repeat:
-+      cxt = aa_task_context(task);
-+      if (cxt)
-+              old_profile = cxt->profile;
-+
-+      lock_both_profiles(profile, old_profile);
-+      task_lock(task);
-+
-+      /* check for race with profile transition, replacement or removal */
-+      if (unlikely(cxt != aa_task_context(task))) {
-+              task_unlock(task);
-+              unlock_both_profiles(profile, old_profile);
-+              old_profile = NULL;
-+              goto repeat;
-+      }
-+      rcu_read_unlock();
-+      return cxt;
++      struct sock *sk = sock->sk;
++
++      return aa_revalidate_sk(OP_GETSOCKOPT, sk);
 +}
 +
-+static void free_aa_task_context_rcu_callback(struct rcu_head *head)
++static int apparmor_socket_setsockopt(struct socket *sock, int level,
++                                    int optname)
 +{
-+      struct aa_task_context *cxt;
++      struct sock *sk = sock->sk;
 +
-+      cxt = container_of(head, struct aa_task_context, rcu);
-+      aa_free_task_context(cxt);
++      return aa_revalidate_sk(OP_SETSOCKOPT, sk);
 +}
 +
-+/**
-+ * aa_change_task_context - switch a task to use a new context and profile
-+ * @task: task that is having its task context changed
-+ * @new_cxt: new task context to use after the switch
-+ * @profile: new profile to use after the switch
-+ * @cookie: magic value to switch to
-+ * @previous_profile: profile the task can return to
-+ */
-+void aa_change_task_context(struct task_struct *task,
-+                          struct aa_task_context *new_cxt,
-+                          struct aa_profile *profile, u64 cookie,
-+                          struct aa_profile *previous_profile)
++static int apparmor_socket_shutdown(struct socket *sock, int how)
 +{
-+      struct aa_task_context *old_cxt = aa_task_context(task);
++      struct sock *sk = sock->sk;
 +
-+      if (old_cxt) {
-+              list_del_init(&old_cxt->list);
-+              old_cxt->profile->task_count--;
-+              call_rcu(&old_cxt->rcu, free_aa_task_context_rcu_callback);
-+      }
-+      if (new_cxt) {
-+              /* set the caps_logged cache to the quiet_caps mask
-+               * this has the effect of quieting caps that are not
-+               * supposed to be logged
-+               */
-+              new_cxt->caps_logged = profile->quiet_caps;
-+              new_cxt->cookie = cookie;
-+              new_cxt->task = task;
-+              new_cxt->profile = aa_dup_profile(profile);
-+              profile->task_count++;
-+              new_cxt->previous_profile = aa_dup_profile(previous_profile);
-+              list_move(&new_cxt->list, &profile->task_contexts);
-+      }
-+      rcu_assign_pointer(task->security, new_cxt);
-+}
-diff -uprN e/security/apparmor/match.c f/security/apparmor/match.c
---- e/security/apparmor/match.c        1970-01-01 00:00:00.000000000 +0000
-+++ f/security/apparmor/match.c        2008-05-28 20:29:29.410207000 +0000
-@@ -0,0 +1,364 @@
++      return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
++}
++
+ 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..003dd18
+--- /dev/null
++++ b/security/apparmor/net.c
+@@ -0,0 +1,162 @@
 +/*
-+ *    Copyright (C) 2007 Novell/SUSE
++ * AppArmor security module
++ *
++ * This file contains AppArmor network mediation
 + *
-+ *    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.
++ * Copyright (C) 1998-2008 Novell/SUSE
++ * Copyright 2009-2012 Canonical Ltd.
 + *
-+ *    Regular expression transition table matching
++ * 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/kernel.h>
-+#include <linux/slab.h>
-+#include <linux/errno.h>
-+#include "apparmor.h"
-+#include "match.h"
-+#include "inline.h"
++#include "include/apparmor.h"
++#include "include/audit.h"
++#include "include/context.h"
++#include "include/net.h"
++#include "include/policy.h"
 +
-+static struct table_header *unpack_table(void *blob, size_t bsize)
-+{
-+      struct table_header *table = NULL;
-+      struct table_header th;
-+      size_t tsize;
-+
-+      if (bsize < sizeof(struct table_header))
-+              goto out;
-+
-+      th.td_id = be16_to_cpu(*(u16 *) (blob));
-+      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;
-+
-+      table = kmalloc(tsize, GFP_KERNEL);
-+      if (table) {
-+              *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
-+                      UNPACK_ARRAY(table->td_data, blob, th.td_lolen,
-+                                   u32, be32_to_cpu);
-+      }
++#include "net_names.h"
 +
-+out:
-+      return table;
-+}
++struct aa_fs_entry aa_fs_entry_network[] = {
++      AA_FS_FILE_STRING("af_mask", AA_FS_AF_MASK),
++      { }
++};
 +
-+int unpack_dfa(struct aa_dfa *dfa, void *blob, size_t size)
++/* audit callback for net specific fields */
++static void audit_cb(struct audit_buffer *ab, void *va)
 +{
-+      int hsize, i;
-+      int error = -ENOMEM;
-+
-+      /* get dfa table set header */
-+      if (size < sizeof(struct table_set_header))
-+              goto fail;
-+
-+      if (ntohl(*(u32 *)blob) != YYTH_MAGIC)
-+              goto fail;
-+
-+      hsize = ntohl(*(u32 *)(blob + 4));
-+      if (size < hsize)
-+              goto fail;
-+
-+      blob += hsize;
-+      size -= hsize;
-+
-+      error = -EPROTO;
-+      while (size > 0) {
-+              struct table_header *table;
-+              table = unpack_table(blob, size);
-+              if (!table)
-+                      goto fail;
-+
-+              switch(table->td_id) {
-+              case YYTD_ID_ACCEPT:
-+              case YYTD_ID_ACCEPT2:
-+              case YYTD_ID_BASE:
-+                      dfa->tables[table->td_id - 1] = table;
-+                      if (table->td_flags != YYTD_DATA32)
-+                              goto fail;
-+                      break;
-+              case YYTD_ID_DEF:
-+              case YYTD_ID_NXT:
-+              case YYTD_ID_CHK:
-+                      dfa->tables[table->td_id - 1] = table;
-+                      if (table->td_flags != YYTD_DATA16)
-+                              goto fail;
-+                      break;
-+              case YYTD_ID_EC:
-+                      dfa->tables[table->td_id - 1] = table;
-+                      if (table->td_flags != YYTD_DATA8)
-+                              goto fail;
-+                      break;
-+              default:
-+                      kfree(table);
-+                      goto fail;
-+              }
++      struct common_audit_data *sa = va;
 +
-+              blob += table_size(table->td_lolen, table->td_flags);
-+              size -= table_size(table->td_lolen, table->td_flags);
++      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 0;
-+
-+fail:
-+      for (i = 0; i < ARRAY_SIZE(dfa->tables); i++) {
-+              if (dfa->tables[i]) {
-+                      kfree(dfa->tables[i]);
-+                      dfa->tables[i] = NULL;
-+              }
++      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);
 +      }
-+      return error;
++      audit_log_format(ab, " protocol=%d", sa->aad->net.protocol);
 +}
 +
 +/**
-+ * verify_dfa - verify that all the transitions and states in the dfa tables
-+ *              are in bounds.
-+ * @dfa: dfa to test
-+ *
-+ * assumes dfa has gone through the verification done by unpacking
-+ */
-+int verify_dfa(struct aa_dfa *dfa)
-+{
-+      size_t i, state_count, trans_count;
-+      int error = -EPROTO;
-+
-+      /* check that required tables exist */
-+      if (!(dfa->tables[YYTD_ID_ACCEPT - 1] &&
-+            dfa->tables[YYTD_ID_ACCEPT2 - 1] &&
-+            dfa->tables[YYTD_ID_DEF - 1] &&
-+            dfa->tables[YYTD_ID_BASE - 1] &&
-+            dfa->tables[YYTD_ID_NXT - 1] &&
-+            dfa->tables[YYTD_ID_CHK - 1]))
-+              goto out;
-+
-+      /* accept.size == default.size == base.size */
-+      state_count = dfa->tables[YYTD_ID_BASE - 1]->td_lolen;
-+      if (!(state_count == dfa->tables[YYTD_ID_DEF - 1]->td_lolen &&
-+            state_count == dfa->tables[YYTD_ID_ACCEPT - 1]->td_lolen &&
-+            state_count == dfa->tables[YYTD_ID_ACCEPT2 - 1]->td_lolen))
-+              goto out;
-+
-+      /* next.size == chk.size */
-+      trans_count = dfa->tables[YYTD_ID_NXT - 1]->td_lolen;
-+      if (trans_count != dfa->tables[YYTD_ID_CHK - 1]->td_lolen)
-+              goto out;
-+
-+      /* if equivalence classes then its table size must be 256 */
-+      if (dfa->tables[YYTD_ID_EC - 1] &&
-+          dfa->tables[YYTD_ID_EC - 1]->td_lolen != 256)
-+              goto out;
-+
-+      for (i = 0; i < state_count; i++) {
-+              if (DEFAULT_TABLE(dfa)[i] >= state_count)
-+                      goto out;
-+              if (BASE_TABLE(dfa)[i] >= trans_count + 256)
-+                      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;
-+      }
-+
-+      /* verify accept permissions */
-+      for (i = 0; i < state_count; i++) {
-+              int mode = ACCEPT_TABLE(dfa)[i];
++ * 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;
++      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;
 +
-+              if (mode & ~AA_VALID_PERM_MASK)
-+                      goto out;
-+              if (ACCEPT_TABLE2(dfa)[i] & ~AA_VALID_PERM2_MASK)
-+                      goto out;
++              if (denied & kill_mask)
++                      audit_type = AUDIT_APPARMOR_KILL;
 +
-+              /* if any exec modifier is set MAY_EXEC must be set */
-+              if ((mode & AA_USER_EXEC_TYPE) && !(mode & AA_USER_EXEC))
-+                      goto out;
-+              if ((mode & AA_OTHER_EXEC_TYPE) && !(mode & AA_OTHER_EXEC))
-+                      goto out;
++              if ((denied & quiet_mask) &&
++                  AUDIT_MODE(profile) != AUDIT_NOQUIET &&
++                  AUDIT_MODE(profile) != AUDIT_ALL)
++                      return COMPLAIN_MODE(profile) ? 0 : sa.aad->error;
 +      }
 +
-+      error = 0;
-+out:
-+      return error;
-+}
-+
-+struct aa_dfa *aa_match_alloc(void)
-+{
-+      return kzalloc(sizeof(struct aa_dfa), GFP_KERNEL);
-+}
-+
-+void aa_match_free(struct aa_dfa *dfa)
-+{
-+      if (dfa) {
-+              int i;
-+
-+              for (i = 0; i < ARRAY_SIZE(dfa->tables); i++)
-+                      kfree(dfa->tables[i]);
-+      }
-+      kfree(dfa);
++      return aa_audit(audit_type, profile, GFP_KERNEL, &sa, audit_cb);
 +}
 +
 +/**
-+ * aa_dfa_next_state_len - traverse @dfa to find state @str stops at
-+ * @dfa: the dfa to match @str against
-+ * @start: the state of the dfa to start matching in
-+ * @str: the string of bytes to match against the dfa
-+ * @len: length of the string of bytes to match
-+ *
-+ * 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.
++ * 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
 + *
-+ * aa_dfa_next_state could be implement using this function by doing
-+ * return aa_dfa_next_state_len(dfa, start, str, strlen(str));
-+ * but that would require traversing the string twice and be slightly
-+ * slower.
++ * Returns: %0 else error if permission denied
 + */
-+unsigned int aa_dfa_next_state_len(struct aa_dfa *dfa, unsigned int start,
-+                                 const char *str, int len)
++int aa_net_perm(int op, struct aa_profile *profile, u16 family, int type,
++              int protocol, struct sock *sk)
 +{
-+      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;
++      u16 family_mask;
++      int error;
++
++      if ((family < 0) || (family >= AF_MAX))
++              return -EINVAL;
 +
-+      if (state == 0)
++      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;
 +
-+      /* current state is <state>, matching character *str */
-+      if (dfa->tables[YYTD_ID_EC - 1]) {
-+              u8 *equiv = EQUIV_TABLE(dfa);
-+              for (; len; len--) {
-+                      pos = base[state] + equiv[(u8)*str++];
-+                      if (check[pos] == state)
-+                              state = next[pos];
-+                      else
-+                              state = def[state];
-+              }
-+      } else {
-+              for (; len; len--) {
-+                      pos = base[state] + (u8)*str++;
-+                      if (check[pos] == state)
-+                              state = next[pos];
-+                      else
-+                              state = def[state];
-+              }
-+      }
-+      return state;
++      family_mask = profile->net.allow[family];
++
++      error = (family_mask & (1 << type)) ? 0 : -EACCES;
++
++      return audit_net(profile, op, family, type, protocol, sk, error);
 +}
 +
 +/**
-+ * aa_dfa_next_state - traverse @dfa to find state @str stops at
-+ * @dfa: the dfa to match @str against
-+ * @start: the state of the dfa to start matching in
-+ * @str: the null terminated string of bytes to match against the dfa
++ * aa_revalidate_sk - Revalidate access to a sock
++ * @op: operation being checked
++ * @sk: sock being revalidated  (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: %0 else error if permission denied
 + */
-+unsigned int aa_dfa_next_state(struct aa_dfa *dfa, unsigned int start,
-+                             const char *str)
++int aa_revalidate_sk(int op, struct sock *sk)
 +{
-+      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;
++      struct aa_profile *profile;
++      int error = 0;
 +
-+      if (state == 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;
 +
-+      /* current state is <state>, matching character *str */
-+      if (dfa->tables[YYTD_ID_EC - 1]) {
-+              u8 *equiv = EQUIV_TABLE(dfa);
-+              while (*str) {
-+                      pos = base[state] + equiv[(u8)*str++];
-+                      if (check[pos] == state)
-+                              state = next[pos];
-+                      else
-+                              state = def[state];
-+              }
-+      } else {
-+              while (*str) {
-+                      pos = base[state] + (u8)*str++;
-+                      if (check[pos] == state)
-+                              state = next[pos];
-+                      else
-+                              state = def[state];
-+              }
-+      }
-+      return state;
-+}
-+
-+/**
-+ * 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 seperate pairs.
-+ */
-+unsigned int aa_dfa_null_transition(struct aa_dfa *dfa, unsigned int start)
-+{
-+      return aa_dfa_next_state_len(dfa, start, "", 1);
-+}
++      profile = __aa_current_profile();
++      if (!unconfined(profile))
++              error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
++                                  sk->sk_protocol, sk);
 +
-+/**
-+ * aa_dfa_match - find accept perm for @str in @dfa
-+ * @dfa: the dfa to match @str against
-+ * @str: the string to match against the dfa
-+ * @audit_mask: the audit_mask for the final state
-+ *
-+ * aa_dfa_match will match @str and return the accept perms for the
-+ * final state.
-+ */
-+unsigned int aa_dfa_match(struct aa_dfa *dfa, const char *str, int *audit_mask)
-+{
-+      int state = aa_dfa_next_state(dfa, DFA_START, str);
-+      if (audit_mask)
-+              *audit_mask = dfa_audit_mask(dfa, state);
-+      return ACCEPT_TABLE(dfa)[state];
++      return error;
 +}
-+
-+/**
-+ * aa_match_state - find accept perm and state for @str in @dfa
-+ * @dfa: the dfa to match @str against
-+ * @start: the state to start the match from
-+ * @str: the string to match against the dfa
-+ * @final: the state that the match finished in
-+ *
-+ * aa_match_state will match @str and return the accept perms, and @final
-+ * state, the match occured in.
-+ */
-+unsigned int aa_match_state(struct aa_dfa *dfa, unsigned int start,
-+                          const char *str, unsigned int *final)
+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)
 +{
-+      unsigned int state;
-+      if (dfa) {
-+              state = aa_dfa_next_state(dfa, start, str);
-+              if (final)
-+                      *final = state;
-+              return ACCEPT_TABLE(dfa)[state];
++      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;
 +      }
-+      if (final)
-+              *final = 0;
 +      return 0;
 +}
 +
-diff -uprN e/security/apparmor/match.h f/security/apparmor/match.h
---- e/security/apparmor/match.h        1970-01-01 00:00:00.000000000 +0000
-+++ f/security/apparmor/match.h        2008-05-28 20:29:29.410207000 +0000
-@@ -0,0 +1,87 @@
-+/*
-+ *    Copyright (C) 2007 Novell/SUSE
-+ *
-+ *    This program is free software; you can redistribute it and/or
-+ *    modify it under the terms of the GNU General Public License as
-+ *    published by the Free Software Foundation, version 2 of the
-+ *    License.
-+ *
-+ *    AppArmor submodule (match) prototypes
-+ */
-+
-+#ifndef __MATCH_H
-+#define __MATCH_H
-+
-+#define DFA_START                     1
-+
-+/**
-+ * 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
+ 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) {
 +
-+struct table_set_header {
-+      u32             th_magic;       /* YYTH_MAGIC */
-+      u32             th_hsize;
-+      u32             th_ssize;
-+      u16             th_flags;
-+      char            th_version[];
-+};
++              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;
 +
-+#define       YYTD_ID_ACCEPT  1
-+#define YYTD_ID_BASE  2
-+#define YYTD_ID_CHK   3
-+#define YYTD_ID_DEF   4
-+#define YYTD_ID_EC    5
-+#define YYTD_ID_META  6
-+#define YYTD_ID_ACCEPT2 7
-+#define YYTD_ID_NXT   8
-+
-+
-+#define YYTD_DATA8    1
-+#define YYTD_DATA16   2
-+#define YYTD_DATA32   4
-+
-+struct table_header {
-+      u16             td_id;
-+      u16             td_flags;
-+      u32             td_hilen;
-+      u32             td_lolen;
-+      char            td_data[];
+       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),
+-      {}
++      { }
 +};
 +
-+#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF - 1]->td_data))
-+#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE - 1]->td_data))
-+#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT - 1]->td_data))
-+#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK - 1]->td_data))
-+#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC - 1]->td_data))
-+#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT - 1]->td_data))
-+#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2 -1]->td_data))
-+
-+struct aa_dfa {
-+      struct table_header *tables[YYTD_ID_NXT];
++static struct aa_fs_entry aa_fs_entry_mount[] = {
++      AA_FS_FILE_STRING("mask", "mount umount"),
++      { }
 +};
 +
-+#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);
-+}
-+
-+#endif /* __MATCH_H */
-diff -uprN e/security/apparmor/module_interface.c f/security/apparmor/module_interface.c
---- e/security/apparmor/module_interface.c     1970-01-01 00:00:00.000000000 +0000
-+++ f/security/apparmor/module_interface.c     2008-05-28 20:29:29.410207000 +0000
-@@ -0,0 +1,966 @@
++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",
++
+       "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);
++
+ 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..a43b1d6
+--- /dev/null
++++ b/security/apparmor/include/mount.h
+@@ -0,0 +1,54 @@
 +/*
-+ *    Copyright (C) 1998-2007 Novell/SUSE
++ * AppArmor security module
++ *
++ * This file contains AppArmor file mediation function definitions.
 + *
-+ *    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.
++ * Copyright 2012 Canonical Ltd.
 + *
-+ *    AppArmor userspace policy interface
++ * 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 <asm/unaligned.h>
++#ifndef __AA_MOUNT_H
++#define __AA_MOUNT_H
 +
-+#include "apparmor.h"
-+#include "inline.h"
++#include <linux/fs.h>
++#include <linux/path.h>
 +
-+/*
-+ * This mutex is used to synchronize profile adds, replacements, and
-+ * removals: we only allow one of these operations at a time.
-+ * We do not use the profile list lock here in order to avoid blocking
-+ * exec during those operations.  (Exec involves a profile list lookup
-+ * for named-profile transitions.)
-+ */
-+DEFINE_MUTEX(aa_interface_lock);
++#include "domain.h"
++#include "policy.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 compatability.
-+ */
++/* 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
 +
-+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,
-+};
++#define AA_MS_IGNORE_MASK (MS_KERNMOUNT | MS_NOSEC | MS_ACTIVE | MS_BORN)
 +
-+/*
-+ * 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;
-+      char *ns_name;
-+};
++int aa_remount(struct aa_profile *profile, const struct path *path,
++             unsigned long flags, void *data);
 +
-+static inline int aa_inbounds(struct aa_ext *e, size_t size)
-+{
-+      return (size <= e->end - e->pos);
-+}
++int aa_bind_mount(struct aa_profile *profile, const struct path *path,
++                const char *old_name, unsigned long flags);
 +
-+/**
-+ * aa_u16_chunck - test and do bounds checking for a u16 size based chunk
-+ * @e: serialized data read head
-+ * @chunk: start address for chunk of data
-+ *
-+ * return the size of chunk found with the read head at the end of
-+ * the chunk.
-+ */
-+static size_t aa_is_u16_chunk(struct aa_ext *e, char **chunk)
-+{
-+      void *pos = e->pos;
-+      size_t size = 0;
 +
-+      if (!aa_inbounds(e, sizeof(u16)))
-+              goto fail;
-+      size = le16_to_cpu(get_unaligned((u16 *)e->pos));
-+      e->pos += sizeof(u16);
-+      if (!aa_inbounds(e, size))
-+              goto fail;
-+      *chunk = e->pos;
-+      e->pos += size;
-+      return size;
-+
-+fail:
-+      e->pos = pos;
-+      return 0;
-+}
++int aa_mount_change_type(struct aa_profile *profile, const struct path *path,
++                       unsigned long flags);
 +
-+static inline int aa_is_X(struct aa_ext *e, enum aa_code code)
-+{
-+      if (!aa_inbounds(e, 1))
-+              return 0;
-+      if (*(u8 *) e->pos != code)
-+              return 0;
-+      e->pos++;
-+      return 1;
-+}
++int aa_move_mount(struct aa_profile *profile, const struct path *path,
++                const char *old_name);
 +
-+/**
-+ * aa_is_nameX - check is the next element is of type X with a name of @name
-+ * @e: serialized data extent information
-+ * @code: type code
-+ * @name: name to match to the serialized element.
-+ *
-+ * 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 failes, the read head does not move
-+ */
-+static int aa_is_nameX(struct aa_ext *e, enum aa_code code, const char *name)
-+{
-+      void *pos = e->pos;
-+      /*
-+       * Check for presence of a tagname, and if present name size
-+       * AA_NAME tag value is a u16.
-+       */
-+      if (aa_is_X(e, AA_NAME)) {
-+              char *tag;
-+              size_t size = aa_is_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;
-+      }
++int aa_new_mount(struct aa_profile *profile, const char *dev_name,
++               const struct path *path, const char *type, unsigned long flags,
++               void *data);
 +
-+      /* now check if type code matches */
-+      if (aa_is_X(e, code))
-+              return 1;
++int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags);
 +
-+fail:
-+      e->pos = pos;
-+      return 0;
-+}
++int aa_pivotroot(struct aa_profile *profile, const struct path *old_path,
++               const struct path *new_path);
 +
-+static int aa_is_u16(struct aa_ext *e, u16 *data, const char *name)
++#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)
 +{
-+      void *pos = e->pos;
-+      if (aa_is_nameX(e, AA_U16, name)) {
-+              if (!aa_inbounds(e, sizeof(u16)))
-+                      goto fail;
-+              if (data)
-+                      *data = le16_to_cpu(get_unaligned((u16 *)e->pos));
-+              e->pos += sizeof(u16);
-+              return 1;
-+      }
-+fail:
-+      e->pos = pos;
-+      return 0;
-+}
++      struct aa_profile *profile;
++      int error = 0;
 +
-+static int aa_is_u32(struct aa_ext *e, u32 *data, const char *name)
-+{
-+      void *pos = e->pos;
-+      if (aa_is_nameX(e, AA_U32, name)) {
-+              if (!aa_inbounds(e, sizeof(u32)))
-+                      goto fail;
-+              if (data)
-+                      *data = le32_to_cpu(get_unaligned((u32 *)e->pos));
-+              e->pos += sizeof(u32);
-+              return 1;
++      /* 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
++                      error = aa_new_mount(profile, dev_name, path, type,
++                                           flags, data);
 +      }
-+fail:
-+      e->pos = pos;
-+      return 0;
++      return error;
 +}
 +
-+static int aa_is_u64(struct aa_ext *e, u64 *data, const char *name)
++static int apparmor_sb_umount(struct vfsmount *mnt, int flags)
 +{
-+      void *pos = e->pos;
-+      if (aa_is_nameX(e, AA_U64, name)) {
-+              if (!aa_inbounds(e, sizeof(u64)))
-+                      goto fail;
-+              if (data)
-+                      *data = le64_to_cpu(get_unaligned((u64 *)e->pos));
-+              e->pos += sizeof(u64);
-+              return 1;
-+      }
-+fail:
-+      e->pos = pos;
-+      return 0;
-+}
++      struct aa_profile *profile;
++      int error = 0;
 +
-+static size_t aa_is_array(struct aa_ext *e, const char *name)
-+{
-+      void *pos = e->pos;
-+      if (aa_is_nameX(e, AA_ARRAY, name)) {
-+              int size;
-+              if (!aa_inbounds(e, sizeof(u16)))
-+                      goto fail;
-+              size = (int) le16_to_cpu(get_unaligned((u16 *)e->pos));
-+              e->pos += sizeof(u16);
-+              return size;
-+      }
-+fail:
-+      e->pos = pos;
-+      return 0;
-+}
++      profile = __aa_current_profile();
++      if (!unconfined(profile))
++              error = aa_umount(profile, mnt, flags);
 +
-+static size_t aa_is_blob(struct aa_ext *e, char **blob, const char *name)
-+{
-+      void *pos = e->pos;
-+      if (aa_is_nameX(e, AA_BLOB, name)) {
-+              u32 size;
-+              if (!aa_inbounds(e, sizeof(u32)))
-+                      goto fail;
-+              size = le32_to_cpu(get_unaligned((u32 *)e->pos));
-+              e->pos += sizeof(u32);
-+              if (aa_inbounds(e, (size_t) size)) {
-+                      * blob = e->pos;
-+                      e->pos += size;
-+                      return size;
-+              }
-+      }
-+fail:
-+      e->pos = pos;
-+      return 0;
++      return error;
 +}
 +
-+static int aa_is_dynstring(struct aa_ext *e, char **string, const char *name)
++static int apparmor_sb_pivotroot(const struct path *old_path,
++                               const struct path *new_path)
 +{
-+      char *src_str;
-+      size_t size = 0;
-+      void *pos = e->pos;
-+      *string = NULL;
-+      if (aa_is_nameX(e, AA_STRING, name) &&
-+          (size = aa_is_u16_chunk(e, &src_str))) {
-+              char *str;
-+              if (!(str = kmalloc(size, GFP_KERNEL)))
-+                      goto fail;
-+              memcpy(str, src_str, size);
-+              *string = str;
-+      }
++      struct aa_profile *profile;
++      int error = 0;
 +
-+      return size;
++      profile = __aa_current_profile();
++      if (!unconfined(profile))
++              error = aa_pivotroot(profile, old_path, new_path);
 +
-+fail:
-+      e->pos = pos;
-+      return 0;
++      return error;
 +}
 +
-+/**
-+ * aa_unpack_dfa - unpack a file rule dfa
-+ * @e: serialized data extent information
+ 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..9cf9170
+--- /dev/null
++++ b/security/apparmor/mount.c
+@@ -0,0 +1,620 @@
++/*
++ * AppArmor security module
++ *
++ * This file contains AppArmor mediation of files
 + *
-+ * returns dfa or ERR_PTR
++ * Copyright (C) 1998-2008 Novell/SUSE
++ * 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.
 + */
-+static struct aa_dfa *aa_unpack_dfa(struct aa_ext *e)
-+{
-+      char *blob = NULL;
-+      size_t size, error = 0;
-+      struct aa_dfa *dfa = NULL;
 +
-+      size = aa_is_blob(e, &blob, "aadfa");
-+      if (size) {
-+              dfa = aa_match_alloc();
-+              if (dfa) {
-+                      /*
-+                       * 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;
-+                      error = unpack_dfa(dfa, blob + pad, size - pad);
-+                      if (!error)
-+                              error = verify_dfa(dfa);
-+              } else {
-+                      error = -ENOMEM;
-+              }
++#include <linux/fs.h>
++#include <linux/mount.h>
++#include <linux/namei.h>
 +
-+              if (error) {
-+                      aa_match_free(dfa);
-+                      dfa = ERR_PTR(error);
-+              }
-+      }
++#include "include/apparmor.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"
 +
-+      return dfa;
-+}
 +
-+static int aa_unpack_exec_table(struct aa_ext *e, struct aa_profile *profile)
++static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
 +{
-+      void *pos = e->pos;
-+
-+      /* exec table is optional */
-+      if (aa_is_nameX(e, AA_STRUCT, "xtable")) {
-+              int i, size;
-+
-+              size = aa_is_array(e, NULL);
-+              /* currently 4 exec bits and entries 0-3 are reserved iupcx */
-+              if (size > 16 - 4)
-+                      goto fail;
-+              profile->exec_table = kzalloc(sizeof(char *) * size,
-+                                            GFP_KERNEL);
-+              if (!profile->exec_table)
-+                      goto fail;
-+
-+              for (i = 0; i < size; i++) {
-+                  char *tmp;
-+                      if (!aa_is_dynstring(e, &tmp, NULL))
-+                              goto fail;
-+                      /* note: strings beginning with a : have an embedded
-+                         \0 seperating the profile ns name from the profile
-+                         name */
-+                      profile->exec_table[i] = tmp;
-+              }
-+              if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
-+                      goto fail;
-+              if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
-+                      goto fail;
-+      }
-+      return 1;
-+
-+fail:
-+      e->pos = pos;
-+      return 0;
++      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");
 +}
 +
-+int aa_unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
++/**
++ * 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)
 +{
-+      void *pos = e->pos;
-+
-+      /* rlimits are optional */
-+      if (aa_is_nameX(e, AA_STRUCT, "rlimits")) {
-+              int i, size;
-+              u32 tmp = 0;
-+              if (!aa_is_u32(e, &tmp, NULL))
-+                      goto fail;
-+              profile->rlimits.mask = tmp;
++      struct common_audit_data *sa = va;
 +
-+              size = aa_is_array(e, NULL);
-+              if (size > RLIM_NLIMITS)
-+                      goto fail;
-+              for (i = 0; i < size; i++) {
-+                      u64 tmp = 0;
-+                      if (!aa_is_u64(e, &tmp, NULL))
-+                              goto fail;
-+                      profile->rlimits.limits[i].rlim_max = tmp;
-+              }
-+              if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
-+                      goto fail;
-+              if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
-+                      goto fail;
++      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);
 +      }
-+      return 1;
-+
-+fail:
-+      e->pos = pos;
-+      return 0;
 +}
 +
 +/**
-+ * aa_unpack_profile - unpack a serialized profile
-+ * @e: serialized data extent information
-+ * @sa: audit struct for the operation
-+ */
-+static struct aa_profile *aa_unpack_profile(struct aa_ext *e,
-+                                          struct aa_audit *sa)
-+{
-+      struct aa_profile *profile = NULL;
-+      size_t size = 0;
-+      int i, error = -EPROTO;
-+
-+      profile = alloc_aa_profile();
-+      if (!profile)
-+              return ERR_PTR(-ENOMEM);
-+
-+      /* check that we have the right struct being passed */
-+      if (!aa_is_nameX(e, AA_STRUCT, "profile"))
-+              goto fail;
-+      if (!aa_is_dynstring(e, &profile->name, NULL))
-+              goto fail;
-+
-+      /* per profile debug flags (complain, audit) */
-+      if (!aa_is_nameX(e, AA_STRUCT, "flags"))
-+              goto fail;
-+      if (!aa_is_u32(e, &(profile->flags.hat), NULL))
-+              goto fail;
-+      if (!aa_is_u32(e, &(profile->flags.complain), NULL))
-+              goto fail;
-+      if (!aa_is_u32(e, &(profile->flags.audit), NULL))
-+              goto fail;
-+      if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
-+              goto fail;
-+
-+      if (!aa_is_u32(e, &(profile->capabilities.cap[0]), NULL))
-+              goto fail;
-+      if (!aa_is_u32(e, &(profile->audit_caps.cap[0]), NULL))
-+              goto fail;
-+      if (!aa_is_u32(e, &(profile->quiet_caps.cap[0]), NULL))
-+              goto fail;
-+      if (!aa_is_u32(e, &(profile->set_caps.cap[0]), NULL))
-+              goto fail;
-+
-+      if (aa_is_nameX(e, AA_STRUCT, "caps64")) {
-+              /* optional upper half of 64 bit caps */
-+              if (!aa_is_u32(e, &(profile->capabilities.cap[1]), NULL))
-+                      goto fail;
-+              if (!aa_is_u32(e, &(profile->audit_caps.cap[1]), NULL))
-+                      goto fail;
-+              if (!aa_is_u32(e, &(profile->quiet_caps.cap[1]), NULL))
-+                      goto fail;
-+              if (!aa_is_u32(e, &(profile->set_caps.cap[1]), NULL))
-+                      goto fail;
-+              if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
-+                      goto fail;
-+      }
++ * 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 error on failure
++ */
++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)
++{
++      int audit_type = AUDIT_APPARMOR_AUTO;
++      struct common_audit_data sa = { };
++      struct apparmor_audit_data aad = { };
 +
-+      if (!aa_unpack_rlimits(e, profile))
-+              goto fail;
++      if (likely(!error)) {
++              u32 mask = perms->audit;
 +
-+      size = aa_is_array(e, "net_allowed_af");
-+      if (size) {
-+              if (size > AF_MAX)
-+                      goto fail;
++              if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
++                      mask = 0xffff;
 +
-+              for (i = 0; i < size; i++) {
-+                      if (!aa_is_u16(e, &profile->network_families[i], NULL))
-+                              goto fail;
-+                      if (!aa_is_u16(e, &profile->audit_network[i], NULL))
-+                              goto fail;
-+                      if (!aa_is_u16(e, &profile->quiet_network[i], NULL))
-+                              goto fail;
-+              }
-+              if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
-+                      goto fail;
-+              /* allow unix domain and netlink sockets they are handled
-+               * by IPC
-+               */
-+      }
-+      profile->network_families[AF_UNIX] = 0xffff;
-+      profile->network_families[AF_NETLINK] = 0xffff;
-+
-+      /* get file rules */
-+      profile->file_rules = aa_unpack_dfa(e);
-+      if (IS_ERR(profile->file_rules)) {
-+              error = PTR_ERR(profile->file_rules);
-+              profile->file_rules = NULL;
-+              goto fail;
-+      }
++              /* mask off perms that are not being force audited */
++              request &= mask;
 +
-+      if (!aa_unpack_exec_table(e, profile))
-+              goto fail;
++              if (likely(!request))
++                      return 0;
++              audit_type = AUDIT_APPARMOR_AUDIT;
++      } else {
++              /* only report permissions that were denied */
++              request = request & ~perms->allow;
 +
-+      if (!aa_is_nameX(e, AA_STRUCTEND, NULL))
-+              goto fail;
++              if (request & perms->kill)
++                      audit_type = AUDIT_APPARMOR_KILL;
 +
-+      return profile;
++              /* 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;
 +
-+fail:
-+      sa->name = profile && profile->name ? profile->name : "unknown";
-+      if (!sa->info)
-+              sa->info = "failed to unpack profile";
-+      aa_audit_status(NULL, sa);
++              if (!request)
++                      return COMPLAIN_MODE(profile) ?
++                              complain_error(error) : error;
++      }
 +
-+      if (profile)
-+              free_aa_profile(profile);
++      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;
 +
-+      return ERR_PTR(error);
++      return aa_audit(audit_type, profile, gfp, &sa, audit_cb);
 +}
 +
 +/**
-+ * aa_verify_head - unpack serialized stream header
-+ * @e: serialized data read head
-+ * @operation: operation header is being verified for
++ * 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 error or 0 if header is good
++ * Returns: next state after flags match
 + */
-+static int aa_verify_header(struct aa_ext *e, struct aa_audit *sa)
++static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
++                                  unsigned long flags)
 +{
-+      /* get the interface version */
-+      if (!aa_is_u32(e, &e->version, "version")) {
-+              sa->info = "invalid profile format";
-+              aa_audit_status(NULL, sa);
-+              return -EPROTONOSUPPORT;
-+      }
-+
-+      /* check that the interface version is currently supported */
-+      if (e->version != 5) {
-+              sa->info = "unsupported interface version";
-+              aa_audit_status(NULL, sa);
-+              return -EPROTONOSUPPORT;
-+      }
++      unsigned int i;
 +
-+      /* read the namespace if present */
-+      if (!aa_is_dynstring(e, &e->ns_name, "namespace")) {
-+              e->ns_name = NULL;
++      for (i = 0; i <= 31 ; ++i) {
++              if ((1 << i) & flags)
++                      state = aa_dfa_next(dfa, state, i + 1);
 +      }
 +
-+      return 0;
++      return state;
 +}
 +
 +/**
-+ * aa_add_profile - Unpack and add a new profile to the profile list
-+ * @data: serialized data stream
-+ * @size: size of the serialized data stream
++ * compute_mnt_perms - compute mount permission associated with @state
++ * @dfa: dfa to match against (NOT NULL)
++ * @state: state match finished in
++ *
++ * Returns: mount permissions
 + */
-+ssize_t aa_add_profile(void *data, size_t size)
++static struct file_perms compute_mnt_perms(struct aa_dfa *dfa,
++                                         unsigned int state)
 +{
-+      struct aa_profile *profile = NULL;
-+      struct aa_namespace *ns = NULL;
-+      struct aa_ext e = {
-+              .start = data,
-+              .end = data + size,
-+              .pos = data,
-+              .ns_name = NULL
-+      };
-+      ssize_t error;
-+      struct aa_audit sa;
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = "profile_load";
-+      sa.gfp_mask = GFP_KERNEL;
-+
-+      error = aa_verify_header(&e, &sa);
-+      if (error)
-+              return error;
-+
-+      profile = aa_unpack_profile(&e, &sa);
-+      if (IS_ERR(profile))
-+              return PTR_ERR(profile);
++      struct file_perms perms;
 +
-+      mutex_lock(&aa_interface_lock);
-+      write_lock(&profile_ns_list_lock);
-+      if (e.ns_name)
-+              ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
-+      else
-+              ns = default_namespace;
-+      if (!ns) {
-+              struct aa_namespace *new_ns;
-+              write_unlock(&profile_ns_list_lock);
-+              new_ns = alloc_aa_namespace(e.ns_name);
-+              if (!new_ns) {
-+                      mutex_unlock(&aa_interface_lock);
-+                      return -ENOMEM;
-+              }
-+              write_lock(&profile_ns_list_lock);
-+              ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
-+              if (!ns) {
-+                      list_add(&new_ns->list, &profile_ns_list);
-+                      ns = new_ns;
-+              } else
-+                      free_aa_namespace(new_ns);
-+      }
++      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);
 +
-+      write_lock(&ns->lock);
-+      if (__aa_find_profile(profile->name, &ns->profiles)) {
-+              /* A profile with this name exists already. */
-+              write_unlock(&ns->lock);
-+              write_unlock(&profile_ns_list_lock);
-+              sa.name = profile->name;
-+              sa.name2 = ns->name;
-+              sa.info = "failed: profile already loaded";
-+              aa_audit_status(NULL, &sa);
-+              mutex_unlock(&aa_interface_lock);
-+              aa_put_profile(profile);
-+              return -EEXIST;
-+      }
-+      profile->ns = aa_get_namespace(ns);
-+      ns->profile_count++;
-+      list_add(&profile->list, &ns->profiles);
-+      write_unlock(&ns->lock);
-+      write_unlock(&profile_ns_list_lock);
-+
-+      sa.name = profile->name;
-+      sa.name2 = ns->name;
-+      aa_audit_status(NULL, &sa);
-+      mutex_unlock(&aa_interface_lock);
-+      return size;
++      return perms;
 +}
 +
-+/**
-+ * task_replace - replace a task's profile
-+ * @task: task to replace profile on
-+ * @new_cxt: new aa_task_context to do replacement with
-+ * @new_profile: new profile
++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
 + */
-+static inline void task_replace(struct task_struct *task,
-+                              struct aa_task_context *new_cxt,
-+                              struct aa_profile *new_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_context *cxt = aa_task_context(task);
++      unsigned int state;
++
++      state = aa_dfa_match(dfa, start, mntpnt);
++      state = aa_dfa_null_transition(dfa, state);
++      if (!state)
++              return 1;
++
++      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_DEBUG("%s: replacing profile for task %d "
-+               "profile=%s (%p)\n",
-+               __FUNCTION__,
-+               cxt->task->pid,
-+               cxt->profile->name, cxt->profile);
++      /* 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;
++      }
 +
-+      aa_change_task_context(task, new_cxt, new_profile, cxt->cookie,
-+                             cxt->previous_profile);
++      /* failed at end of flags match */
++      return 4;
 +}
 +
 +/**
-+ * aa_replace_profile - replace a profile on the profile list
-+ * @udata: serialized data stream
-+ * @size: size of the serialized data stream
++ * 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
 + *
-+ * unpack and replace a profile on the profile list and uses of that profile
-+ * by any aa_task_context.  If the profile does not exist on the profile list
-+ * it is added.  Return %0 or error.
++ * Returns: 0 on success else error
 + */
-+ssize_t aa_replace_profile(void *udata, size_t size)
++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_profile *old_profile, *new_profile;
-+      struct aa_namespace *ns;
-+      struct aa_task_context *new_cxt;
-+      struct aa_ext e = {
-+              .start = udata,
-+              .end = udata + size,
-+              .pos = udata,
-+              .ns_name = NULL
-+      };
-+      ssize_t error;
-+      struct aa_audit sa;
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = "profile_replace";
-+      sa.gfp_mask = GFP_KERNEL;
-+
-+      error = aa_verify_header(&e, &sa);
-+      if (error)
-+              return error;
++      int pos;
 +
-+      new_profile = aa_unpack_profile(&e, &sa);
-+      if (IS_ERR(new_profile))
-+              return PTR_ERR(new_profile);
-+
-+      mutex_lock(&aa_interface_lock);
-+      write_lock(&profile_ns_list_lock);
-+      if (e.ns_name)
-+              ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
-+      else
-+              ns = default_namespace;
-+      if (!ns) {
-+              struct aa_namespace *new_ns;
-+              write_unlock(&profile_ns_list_lock);
-+              new_ns = alloc_aa_namespace(e.ns_name);
-+              if (!new_ns) {
-+                      mutex_unlock(&aa_interface_lock);
-+                      return -ENOMEM;
-+              }
-+              write_lock(&profile_ns_list_lock);
-+              ns = __aa_find_namespace(e.ns_name, &profile_ns_list);
-+              if (!ns) {
-+                      list_add(&new_ns->list, &profile_ns_list);
-+                      ns = new_ns;
-+              } else
-+                      free_aa_namespace(new_ns);
-+      }
++      if (!profile->policy.dfa)
++              return -EACCES;
 +
-+      write_lock(&ns->lock);
-+      old_profile = __aa_find_profile(new_profile->name, &ns->profiles);
-+      if (old_profile) {
-+              lock_profile(old_profile);
-+              old_profile->isstale = 1;
-+              list_del_init(&old_profile->list);
-+              unlock_profile(old_profile);
-+              ns->profile_count--;
++      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;
 +      }
-+      new_profile->ns = aa_get_namespace(ns);
-+      ns->profile_count++;
-+      /* not don't need an extra ref count to keep new_profile as
-+       * it is protect by the interface mutex */
-+      list_add(&new_profile->list, &ns->profiles);
-+      write_unlock(&ns->lock);
-+      write_unlock(&profile_ns_list_lock);
-+
-+      if (!old_profile) {
-+              sa.operation = "profile_load";
-+              goto out;
-+      }
-+      /* do not fail replacement based off of profile's NPROC rlimit */
 +
-+      /*
-+       * Replacement needs to allocate a new aa_task_context for each
-+       * task confined by old_profile.  To do this the profile locks
-+       * are only held when the actual switch is done per task.  While
-+       * looping to allocate a new aa_task_context the old_task list
-+       * may get shorter if tasks exit/change their profile but will
-+       * not get longer as new task will not use old_profile detecting
-+       * that is stale.
-+       */
-+      do {
-+              new_cxt = aa_alloc_task_context(GFP_KERNEL | __GFP_NOFAIL);
-+
-+              lock_both_profiles(old_profile, new_profile);
-+              if (!list_empty(&old_profile->task_contexts)) {
-+                      struct task_struct *task =
-+                              list_entry(old_profile->task_contexts.next,
-+                                         struct aa_task_context, list)->task;
-+                      task_lock(task);
-+                      task_replace(task, new_cxt, new_profile);
-+                      task_unlock(task);
-+                      aa_set_rlimits(task, new_profile);
-+                      new_cxt = NULL;
-+              }
-+              unlock_both_profiles(old_profile, new_profile);
-+      } while (!new_cxt);
-+      aa_free_task_context(new_cxt);
-+      aa_put_profile(old_profile);
++      return 0;
++}
 +
-+out:
-+      sa.name = new_profile->name;
-+      sa.name2 = ns->name;
-+      aa_audit_status(NULL, &sa);
-+      mutex_unlock(&aa_interface_lock);
-+      return size;
++static int path_flags(struct aa_profile *profile, const struct path *path)
++{
++      return profile->path_flags |
++              S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0;
 +}
 +
-+/**
-+ * aa_remove_profile - remove a profile from the system
-+ * @name: name of the profile to remove
-+ * @size: size of the name
-+ *
-+ * remove a profile from the profile list and all aa_task_context references
-+ * to said profile.
-+ * NOTE: removing confinement does not restore rlimits to preconfinemnet values
-+ */
-+ssize_t aa_remove_profile(char *name, size_t size)
++int aa_remount(struct aa_profile *profile, const struct path *path,
++             unsigned long flags, void *data)
 +{
-+      struct aa_namespace *ns;
-+      struct aa_profile *profile;
-+      struct aa_audit sa;
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = "profile_remove";
-+      sa.gfp_mask = GFP_KERNEL;
-+
-+      mutex_lock(&aa_interface_lock);
-+      write_lock(&profile_ns_list_lock);
-+
-+      if (name[0] == ':') {
-+              char *split = strchr(name + 1, ':');
-+              if (!split)
-+                      goto noent;
-+              *split = 0;
-+              ns = __aa_find_namespace(name + 1, &profile_ns_list);
-+              name = split + 1;
-+      } else {
-+              ns = default_namespace;
-+      }
++      struct file_perms perms = { };
++      const char *name, *info = NULL;
++      char *buffer = NULL;
++      int binary, error;
 +
-+      if (!ns)
-+              goto noent;
-+      sa.name2 = ns->name;
-+      write_lock(&ns->lock);
-+      profile = __aa_find_profile(name, &ns->profiles);
-+      if (!profile) {
-+              write_unlock(&ns->lock);
-+              goto noent;
-+      }
-+      sa.name = profile->name;
-+
-+      /* Remove the profile from each task context it is on. */
-+      lock_profile(profile);
-+      profile->isstale = 1;
-+      aa_unconfine_tasks(profile);
-+      list_del_init(&profile->list);
-+      ns->profile_count--;
-+      unlock_profile(profile);
-+      /* Release the profile itself. */
-+      write_unlock(&ns->lock);
-+      /* check to see if the namespace has become stale */
-+      if (ns != default_namespace && ns->profile_count == 0) {
-+              list_del_init(&ns->list);
-+              aa_put_namespace(ns);
-+      }
-+      write_unlock(&profile_ns_list_lock);
++      binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
++
++      error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
++                           &info);
++      if (error)
++              goto audit;
 +
-+      aa_audit_status(NULL, &sa);
-+      mutex_unlock(&aa_interface_lock);
-+      aa_put_profile(profile);
++      error = match_mnt(profile, name, NULL, NULL, flags, data, binary,
++                        &perms, &info);
 +
-+      return size;
++audit:
++      error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
++                          NULL, flags, data, AA_MAY_MOUNT, &perms, info,
++                          error);
++      kfree(buffer);
 +
-+noent:
-+      write_unlock(&profile_ns_list_lock);
-+      sa.info = "failed: profile does not exist";
-+      aa_audit_status(NULL, &sa);
-+      mutex_unlock(&aa_interface_lock);
-+      return -ENOENT;
++      return error;
 +}
 +
-+/**
-+ * free_aa_namespace_kref - free aa_namespace by kref (see aa_put_namespace)
-+ * @kr: kref callback for freeing of a namespace
-+ */
-+void free_aa_namespace_kref(struct kref *kref)
++int aa_bind_mount(struct aa_profile *profile, const struct path *path,
++                const char *dev_name, unsigned long flags)
 +{
-+      struct aa_namespace *ns=container_of(kref, struct aa_namespace, count);
++      struct file_perms perms = { };
++      char *buffer = NULL, *old_buffer = NULL;
++      const char *name, *old_name = NULL, *info = NULL;
++      struct path old_path;
++      int error;
 +
-+      free_aa_namespace(ns);
-+}
++      if (!dev_name || !*dev_name)
++              return -EINVAL;
 +
-+/**
-+ * alloc_aa_namespace - allocate, initialize and return a new namespace
-+ * @name: a preallocated name
-+ * Returns NULL on failure.
-+ */
-+struct aa_namespace *alloc_aa_namespace(char *name)
-+{
-+      struct aa_namespace *ns;
-+
-+      ns = kzalloc(sizeof(*ns), GFP_KERNEL);
-+      AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
-+      if (ns) {
-+              ns->name = name;
-+              INIT_LIST_HEAD(&ns->list);
-+              INIT_LIST_HEAD(&ns->profiles);
-+              kref_init(&ns->count);
-+              rwlock_init(&ns->lock);
-+
-+              ns->null_complain_profile = alloc_aa_profile();
-+              if (!ns->null_complain_profile) {
-+                      if (!name)
-+                              kfree(ns->name);
-+                      kfree(ns);
-+                      return NULL;
-+              }
-+              ns->null_complain_profile->name =
-+                      kstrdup("null-complain-profile", GFP_KERNEL);
-+              if (!ns->null_complain_profile->name) {
-+                      free_aa_profile(ns->null_complain_profile);
-+                      if (!name)
-+                              kfree(ns->name);
-+                      kfree(ns);
-+                      return NULL;
-+              }
-+              ns->null_complain_profile->flags.complain = 1;
-+              /* null_complain_profile doesn't contribute to ns ref count */
-+              ns->null_complain_profile->ns = ns;
-+      }
-+      return ns;
-+}
++      flags &= MS_REC | MS_BIND;
 +
-+/**
-+ * free_aa_namespace - free a profile namespace
-+ * @namespace: the namespace to free
-+ *
-+ * Free a namespace.  All references to the namespace must have been put.
-+ * If the namespace was referenced by a profile confining a task,
-+ * free_aa_namespace will be called indirectly (through free_aa_profile)
-+ * from an rcu callback routine, so we must not sleep here.
-+ */
-+void free_aa_namespace(struct aa_namespace *ns)
-+{
-+      AA_DEBUG("%s(%p)\n", __FUNCTION__, ns);
-+
-+      if (!ns)
-+              return;
-+
-+      /* namespace still contains profiles -- invalid */
-+      if (!list_empty(&ns->profiles)) {
-+              AA_ERROR("%s: internal error, "
-+                       "namespace '%s' still contains profiles\n",
-+                       __FUNCTION__,
-+                       ns->name);
-+              BUG();
-+      }
-+      if (!list_empty(&ns->list)) {
-+              AA_ERROR("%s: internal error, "
-+                       "namespace '%s' still on list\n",
-+                       __FUNCTION__,
-+                       ns->name);
-+              BUG();
-+      }
-+      /* null_complain_profile doesn't contribute to ns ref counting */
-+      ns->null_complain_profile->ns = NULL;
-+      aa_put_profile(ns->null_complain_profile);
-+      kfree(ns->name);
-+      kfree(ns);
-+}
++      error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
++                           &info);
++      if (error)
++              goto audit;
 +
-+/**
-+ * free_aa_profile_kref - free aa_profile by kref (called by aa_put_profile)
-+ * @kr: kref callback for freeing of a profile
-+ */
-+void free_aa_profile_kref(struct kref *kref)
-+{
-+      struct aa_profile *p=container_of(kref, struct aa_profile, count);
++      error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
++      if (error)
++              goto audit;
 +
-+      free_aa_profile(p);
-+}
++      error = aa_path_name(&old_path, path_flags(profile, &old_path),
++                           &old_buffer, &old_name, &info);
++      path_put(&old_path);
++      if (error)
++              goto audit;
 +
-+/**
-+ * alloc_aa_profile - allocate, initialize and return a new profile
-+ * Returns NULL on failure.
-+ */
-+struct aa_profile *alloc_aa_profile(void)
-+{
-+      struct aa_profile *profile;
++      error = match_mnt(profile, name, old_name, NULL, flags, NULL, 0,
++                        &perms, &info);
 +
-+      profile = kzalloc(sizeof(*profile), GFP_KERNEL);
-+      AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
-+      if (profile) {
-+              INIT_LIST_HEAD(&profile->list);
-+              kref_init(&profile->count);
-+              INIT_LIST_HEAD(&profile->task_contexts);
-+              spin_lock_init(&profile->lock);
-+      }
-+      return profile;
++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 error;
 +}
 +
-+/**
-+ * free_aa_profile - free a profile
-+ * @profile: the profile to free
-+ *
-+ * 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_aa_profile() will
-+ * be called from an rcu callback routine, so we must not sleep here.
-+ */
-+void free_aa_profile(struct aa_profile *profile)
++int aa_mount_change_type(struct aa_profile *profile, const struct path *path,
++                       unsigned long flags)
 +{
-+      AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
-+
-+      if (!profile)
-+              return;
-+
-+      /* profile is still on profile namespace list -- invalid */
-+      if (!list_empty(&profile->list)) {
-+              AA_ERROR("%s: internal error, "
-+                       "profile '%s' still on global list\n",
-+                       __FUNCTION__,
-+                       profile->name);
-+              BUG();
-+      }
-+      aa_put_namespace(profile->ns);
++      struct file_perms perms = { };
++      char *buffer = NULL;
++      const char *name, *info = NULL;
++      int error;
++
++      /* These are the flags allowed by do_change_type() */
++      flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
++                MS_UNBINDABLE);
++
++      error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
++                           &info);
++      if (error)
++              goto audit;
 +
-+      aa_match_free(profile->file_rules);
++      error = match_mnt(profile, name, NULL, NULL, flags, NULL, 0, &perms,
++                        &info);
 +
-+      if (profile->name) {
-+              AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
-+              kfree(profile->name);
-+      }
++audit:
++      error = audit_mount(profile, GFP_KERNEL, OP_MOUNT, name, NULL, NULL,
++                          NULL, flags, NULL, AA_MAY_MOUNT, &perms, info,
++                          error);
++      kfree(buffer);
 +
-+      kfree(profile);
++      return error;
 +}
 +
-+/**
-+ * aa_unconfine_tasks - remove tasks on a profile's task context list
-+ * @profile: profile to remove tasks from
-+ *
-+ * Assumes that @profile lock is held.
-+ */
-+void aa_unconfine_tasks(struct aa_profile *profile)
++int aa_move_mount(struct aa_profile *profile, const struct path *path,
++                const char *orig_name)
 +{
-+      while (!list_empty(&profile->task_contexts)) {
-+              struct task_struct *task =
-+                      list_entry(profile->task_contexts.next,
-+                                 struct aa_task_context, list)->task;
-+              task_lock(task);
-+              aa_change_task_context(task, NULL, NULL, 0, NULL);
-+              task_unlock(task);
-+      }
-+}
-diff -uprN e/security/apparmor/procattr.c f/security/apparmor/procattr.c
---- e/security/apparmor/procattr.c     1970-01-01 00:00:00.000000000 +0000
-+++ f/security/apparmor/procattr.c     2008-05-28 20:29:29.410207000 +0000
-@@ -0,0 +1,195 @@
-+/*
-+ *    Copyright (C) 1998-2007 Novell/SUSE
-+ *
-+ *    This program is free software; you can redistribute it and/or
-+ *    modify it under the terms of the GNU General Public License as
-+ *    published by the Free Software Foundation, version 2 of the
-+ *    License.
-+ *
-+ *    AppArmor /proc/pid/attr handling
-+ */
++      struct file_perms perms = { };
++      char *buffer = NULL, *old_buffer = NULL;
++      const char *name, *old_name = NULL, *info = NULL;
++      struct path old_path;
++      int error;
 +
-+#include "apparmor.h"
-+#include "inline.h"
++      if (!orig_name || !*orig_name)
++              return -EINVAL;
 +
-+int aa_getprocattr(struct aa_profile *profile, char **string, unsigned *len)
-+{
-+      char *str;
-+
-+      if (profile) {
-+              const char *mode_str = PROFILE_COMPLAIN(profile) ?
-+                      " (complain)" : " (enforce)";
-+              int mode_len, name_len, ns_len = 0;
-+
-+              mode_len = strlen(mode_str);
-+              name_len = strlen(profile->name);
-+              if (profile->ns != default_namespace)
-+                      ns_len = strlen(profile->ns->name) + 2;
-+              *len = mode_len + ns_len + name_len + 1;
-+              str = kmalloc(*len, GFP_ATOMIC);
-+              if (!str)
-+                      return -ENOMEM;
-+
-+              if (ns_len) {
-+                      *str++ = ':';
-+                      memcpy(str, profile->ns->name, ns_len - 2);
-+                      str += ns_len - 2;
-+                      *str++ = ':';
-+              }
-+              memcpy(str, profile->name, name_len);
-+              str += name_len;
-+              memcpy(str, mode_str, mode_len);
-+              str += mode_len;
-+              *str++ = '\n';
-+              str -= *len;
-+      } else {
-+              const char *unconfined_str = "unconfined\n";
++      error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
++                           &info);
++      if (error)
++              goto audit;
++
++      error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
++      if (error)
++              goto audit;
 +
-+              *len = strlen(unconfined_str);
-+              str = kmalloc(*len, GFP_ATOMIC);
-+              if (!str)
-+                      return -ENOMEM;
++      error = aa_path_name(&old_path, path_flags(profile, &old_path),
++                           &old_buffer, &old_name, &info);
++      path_put(&old_path);
++      if (error)
++              goto audit;
 +
-+              memcpy(str, unconfined_str, *len);
-+      }
-+      *string = str;
++      error = match_mnt(profile, name, old_name, NULL, MS_MOVE, NULL, 0,
++                        &perms, &info);
 +
-+      return 0;
++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;
 +}
 +
-+static char *split_token_from_name(const char *op, char *args, u64 *cookie)
++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)
 +{
-+      char *name;
++      struct file_perms perms = { };
++      char *buffer = NULL, *dev_buffer = NULL;
++      const char *name = NULL, *dev_name = NULL, *info = NULL;
++      int binary = 1;
++      int error;
 +
-+      *cookie = simple_strtoull(args, &name, 16);
-+      if ((name == args) || *name != '^') {
-+              AA_ERROR("%s: Invalid input '%s'", op, args);
-+              return ERR_PTR(-EINVAL);
-+      }
++      dev_name = orig_dev_name;
++      if (type) {
++              int requires_dev;
++              struct file_system_type *fstype = get_fs_type(type);
++              if (!fstype)
++                      return -ENODEV;
 +
-+      name++;  /* skip ^ */
-+      if (!*name)
-+              name = NULL;
-+      return name;
-+}
++              binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
++              requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
++              put_filesystem(fstype);
 +
-+int aa_setprocattr_changehat(char *args)
-+{
-+      char *hat;
-+      u64 cookie;
++              if (requires_dev) {
++                      struct path dev_path;
++
++                      if (!dev_name || !*dev_name) {
++                              error = -ENOENT;
++                              goto out;
++                      }
 +
-+      hat = split_token_from_name("change_hat", args, &cookie);
-+      if (IS_ERR(hat))
-+              return PTR_ERR(hat);
++                      error = kern_path(dev_name, LOOKUP_FOLLOW, &dev_path);
++                      if (error)
++                              goto audit;
 +
-+      if (!hat && !cookie) {
-+              AA_ERROR("change_hat: Invalid input, NULL hat and NULL magic");
-+              return -EINVAL;
++                      error = aa_path_name(&dev_path,
++                                           path_flags(profile, &dev_path),
++                                           &dev_buffer, &dev_name, &info);
++                      path_put(&dev_path);
++                      if (error)
++                              goto audit;
++              }
 +      }
 +
-+      AA_DEBUG("%s: Magic 0x%llx Hat '%s'\n",
-+               __FUNCTION__, cookie, hat ? hat : NULL);
++      error = aa_path_name(path, path_flags(profile, path), &buffer, &name,
++                           &info);
++      if (error)
++              goto audit;
++
++      error = match_mnt(profile, name, dev_name, type, flags, data, binary,
++                        &perms, &info);
++
++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;
 +
-+      return aa_change_hat(hat, cookie);
 +}
 +
-+int aa_setprocattr_changeprofile(char *args)
++int aa_umount(struct aa_profile *profile, struct vfsmount *mnt, int flags)
 +{
-+      char *name = args, *ns_name = NULL;
-+
-+      if (name[0] == ':') {
-+              char *split = strchr(&name[1], ':');
-+              if (split) {
-+                      *split = 0;
-+                      ns_name = &name[1];
-+                      name = split + 1;
-+              }
++      struct file_perms perms = { };
++      char *buffer = NULL;
++      const char *name, *info = NULL;
++      int error;
++
++      struct path path = { mnt, mnt->mnt_root };
++      error = aa_path_name(&path, path_flags(profile, &path), &buffer, &name,
++                           &info);
++      if (error)
++              goto audit;
++
++      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);
 +      }
 +
-+      return aa_change_profile(ns_name, name);
++      if (AA_MAY_UMOUNT & ~perms.allow)
++              error = -EACCES;
++
++audit:
++      error = audit_mount(profile, GFP_KERNEL, OP_UMOUNT, name, NULL, NULL,
++                          NULL, 0, NULL, AA_MAY_UMOUNT, &perms, info, error);
++      kfree(buffer);
++
++      return error;
 +}
 +
-+int aa_setprocattr_setprofile(struct task_struct *task, char *args)
++int aa_pivotroot(struct aa_profile *profile, const struct path *old_path,
++               const struct path *new_path)
 +{
-+      struct aa_profile *old_profile, *new_profile;
-+      struct aa_namespace *ns;
-+      struct aa_audit sa;
-+      char *name, *ns_name = NULL;
-+
-+      memset(&sa, 0, sizeof(sa));
-+      sa.operation = "profile_set";
-+      sa.gfp_mask = GFP_KERNEL;
-+      sa.task = task->pid;
-+
-+      AA_DEBUG("%s: current %d\n",
-+               __FUNCTION__, current->pid);
-+
-+      name = args;
-+      if (args[0] != '/') {
-+              char *split = strchr(args, ':');
-+              if (split) {
-+                      *split = 0;
-+                      ns_name = args;
-+                      name = split + 1;
-+              }
-+      }
-+      if (ns_name)
-+              ns = aa_find_namespace(ns_name);
-+      else
-+              ns = aa_get_namespace(default_namespace);
-+      if (!ns) {
-+              sa.name = ns_name;
-+              sa.info = "unknown namespace";
-+              aa_audit_reject(NULL, &sa);
-+              aa_put_namespace(ns);
-+              return -EINVAL;
-+      }
++      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;
 +
-+repeat:
-+      if (strcmp(name, "unconfined") == 0)
-+              new_profile = NULL;
-+      else {
-+              new_profile = aa_find_profile(ns, name);
-+              if (!new_profile) {
-+                      sa.name = ns_name;
-+                      sa.name2 = name;
-+                      sa.info = "unknown profile";
-+                      aa_audit_reject(NULL, &sa);
-+                      aa_put_namespace(ns);
-+                      return -EINVAL;
-+              }
-+      }
++      error = aa_path_name(old_path, path_flags(profile, old_path),
++                           &old_buffer, &old_name, &info);
++      if (error)
++              goto audit;
 +
-+      old_profile = __aa_replace_profile(task, new_profile);
-+      if (IS_ERR(old_profile)) {
-+              int error;
++      error = aa_path_name(new_path, path_flags(profile, new_path),
++                           &new_buffer, &new_name, &info);
++      if (error)
++              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);
++      }
++
++      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;
 +
-+              aa_put_profile(new_profile);
-+              error = PTR_ERR(old_profile);
-+              if (error == -ESTALE)
-+                      goto repeat;
-+              aa_put_namespace(ns);
-+              return error;
-+      }
++audit:
++      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);
 +
-+      if (new_profile) {
-+              sa.name = ns_name;
-+              sa.name2 = name;
-+              sa.name3 = old_profile ? old_profile->name :
-+                      "unconfined";
-+              aa_audit_status(NULL, &sa);
-+      } else {
-+              if (old_profile) {
-+                      sa.name = "unconfined";
-+                      sa.name2 = old_profile->name;
-+                      aa_audit_status(NULL, &sa);
-+              } else {
-+                      sa.info = "task is unconfined";
-+                      aa_audit_status(NULL, &sa);
-+              }
-+      }
-+      aa_put_namespace(ns);
-+      aa_put_profile(old_profile);
-+      aa_put_profile(new_profile);
-+      return 0;
++      return error;
 +}
-diff -uprN e/security/commoncap.c f/security/commoncap.c
---- e/security/commoncap.c     2008-04-17 02:49:44.000000000 +0000
-+++ f/security/commoncap.c     2008-05-28 20:29:29.410207000 +0000
-@@ -386,8 +386,8 @@ int cap_bprm_secureexec (struct linux_bi
-               current->egid != current->gid);
- }
--int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
--                     size_t size, int flags)
-+int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt, char *name,
-+                     void *value, size_t size, int flags, struct file *file)
- {
-       if (!strcmp(name, XATTR_NAME_CAPS)) {
-               if (!capable(CAP_SETFCAP))
-@@ -400,7 +400,8 @@ int cap_inode_setxattr(struct dentry *de
-       return 0;
- }
--int cap_inode_removexattr(struct dentry *dentry, char *name)
-+int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
-+                        char *name, struct file *file)
- {
-       if (!strcmp(name, XATTR_NAME_CAPS)) {
-               if (!capable(CAP_SETFCAP))
-diff -uprN e/security/dummy.c f/security/dummy.c
---- e/security/dummy.c 2008-04-17 02:49:44.000000000 +0000
-+++ f/security/dummy.c 2008-05-28 20:29:29.410207000 +0000
-@@ -287,54 +287,60 @@ static int dummy_inode_init_security (st
- }
- static int dummy_inode_create (struct inode *inode, struct dentry *dentry,
--                             int mask)
-+                             struct vfsmount *mnt, int mask)
- {
-       return 0;
- }
--static int dummy_inode_link (struct dentry *old_dentry, struct inode *inode,
--                           struct dentry *new_dentry)
-+static int dummy_inode_link (struct dentry *old_dentry,
-+                           struct vfsmount *old_mnt, struct inode *inode,
-+                           struct dentry *new_dentry,
-+                           struct vfsmount *new_mnt)
- {
-       return 0;
- }
--static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry)
-+static int dummy_inode_unlink (struct inode *inode, struct dentry *dentry,
-+                             struct vfsmount *mnt)
- {
-       return 0;
- }
- static int dummy_inode_symlink (struct inode *inode, struct dentry *dentry,
--                              const char *name)
-+                              struct vfsmount *mnt, const char *name)
- {
-       return 0;
- }
- static int dummy_inode_mkdir (struct inode *inode, struct dentry *dentry,
--                            int mask)
-+                            struct vfsmount *mnt, int mask)
- {
-       return 0;
- }
--static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry)
-+static int dummy_inode_rmdir (struct inode *inode, struct dentry *dentry,
-+                            struct vfsmount *mnt)
- {
-       return 0;
- }
- static int dummy_inode_mknod (struct inode *inode, struct dentry *dentry,
--                            int mode, dev_t dev)
-+                            struct vfsmount *mnt, int mode, dev_t dev)
- {
-       return 0;
- }
- static int dummy_inode_rename (struct inode *old_inode,
-                              struct dentry *old_dentry,
-+                             struct vfsmount *old_mnt,
-                              struct inode *new_inode,
--                             struct dentry *new_dentry)
-+                             struct dentry *new_dentry,
-+                             struct vfsmount *new_mnt)
- {
-       return 0;
- }
--static int dummy_inode_readlink (struct dentry *dentry)
-+static int dummy_inode_readlink (struct dentry *dentry, struct vfsmount *mnt)
- {
-       return 0;
- }
-@@ -350,7 +356,8 @@ static int dummy_inode_permission (struc
-       return 0;
- }
--static int dummy_inode_setattr (struct dentry *dentry, struct iattr *iattr)
-+static int dummy_inode_setattr (struct dentry *dentry, struct vfsmount *mnt,
-+                              struct iattr *iattr)
- {
-       return 0;
- }
-@@ -365,8 +372,9 @@ static void dummy_inode_delete (struct i
-       return;
- }
--static int dummy_inode_setxattr (struct dentry *dentry, char *name, void *value,
--                              size_t size, int flags)
-+static int dummy_inode_setxattr (struct dentry *dentry, struct vfsmount *mnt,
-+                               char *name, void *value, size_t size,
-+                               int flags, struct file *file)
- {
-       if (!strncmp(name, XATTR_SECURITY_PREFIX,
-                    sizeof(XATTR_SECURITY_PREFIX) - 1) &&
-@@ -375,22 +383,28 @@ static int dummy_inode_setxattr (struct 
-       return 0;
- }
--static void dummy_inode_post_setxattr (struct dentry *dentry, char *name, void *value,
-+static void dummy_inode_post_setxattr (struct dentry *dentry,
-+                                     struct vfsmount *mnt,
-+                                     char *name, void *value,
-                                      size_t size, int flags)
- {
- }
--static int dummy_inode_getxattr (struct dentry *dentry, char *name)
-+static int dummy_inode_getxattr (struct dentry *dentry,
-+                                struct vfsmount *mnt, char *name,
-+                                struct file *file)
- {
-       return 0;
- }
--static int dummy_inode_listxattr (struct dentry *dentry)
-+static int dummy_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt,
-+                                struct file *file)
- {
-       return 0;
- }
--static int dummy_inode_removexattr (struct dentry *dentry, char *name)
-+static int dummy_inode_removexattr (struct dentry *dentry, struct vfsmount *mnt,
-+                                  char *name, struct file *file)
- {
-       if (!strncmp(name, XATTR_SECURITY_PREFIX,
-                    sizeof(XATTR_SECURITY_PREFIX) - 1) &&
-diff -uprN e/security/security.c f/security/security.c
---- e/security/security.c      2008-04-17 02:49:44.000000000 +0000
-+++ f/security/security.c      2008-05-28 20:29:29.410207000 +0000
-@@ -352,72 +352,80 @@ int security_inode_init_security(struct 
- }
- EXPORT_SYMBOL(security_inode_init_security);
--int security_inode_create(struct inode *dir, struct dentry *dentry, int mode)
-+int security_inode_create(struct inode *dir, struct dentry *dentry,
-+                        struct vfsmount *mnt, int mode)
- {
-       if (unlikely(IS_PRIVATE(dir)))
-               return 0;
--      return security_ops->inode_create(dir, dentry, mode);
-+      return security_ops->inode_create(dir, dentry, mnt, mode);
- }
--int security_inode_link(struct dentry *old_dentry, struct inode *dir,
--                       struct dentry *new_dentry)
-+int security_inode_link(struct dentry *old_dentry, struct vfsmount *old_mnt,
-+                      struct inode *dir, struct dentry *new_dentry,
-+                      struct vfsmount *new_mnt)
- {
-       if (unlikely(IS_PRIVATE(old_dentry->d_inode)))
-               return 0;
--      return security_ops->inode_link(old_dentry, dir, new_dentry);
-+      return security_ops->inode_link(old_dentry, old_mnt, dir,
-+                                       new_dentry, new_mnt);
- }
--int security_inode_unlink(struct inode *dir, struct dentry *dentry)
-+int security_inode_unlink(struct inode *dir, struct dentry *dentry,
-+                        struct vfsmount *mnt)
- {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
-               return 0;
--      return security_ops->inode_unlink(dir, dentry);
-+      return security_ops->inode_unlink(dir, dentry, mnt);
- }
- int security_inode_symlink(struct inode *dir, struct dentry *dentry,
--                          const char *old_name)
-+                         struct vfsmount *mnt, const char *old_name)
- {
-       if (unlikely(IS_PRIVATE(dir)))
-               return 0;
--      return security_ops->inode_symlink(dir, dentry, old_name);
-+      return security_ops->inode_symlink(dir, dentry, mnt, old_name);
- }
--int security_inode_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-+int security_inode_mkdir(struct inode *dir, struct dentry *dentry,
-+                       struct vfsmount *mnt, int mode)
- {
-       if (unlikely(IS_PRIVATE(dir)))
-               return 0;
--      return security_ops->inode_mkdir(dir, dentry, mode);
-+      return security_ops->inode_mkdir(dir, dentry, mnt, mode);
- }
--int security_inode_rmdir(struct inode *dir, struct dentry *dentry)
-+int security_inode_rmdir(struct inode *dir, struct dentry *dentry,
-+                       struct vfsmount *mnt)
- {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
-               return 0;
--      return security_ops->inode_rmdir(dir, dentry);
-+      return security_ops->inode_rmdir(dir, dentry, mnt);
- }
--int security_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
-+int security_inode_mknod(struct inode *dir, struct dentry *dentry,
-+                       struct vfsmount *mnt, int mode, dev_t dev)
- {
-       if (unlikely(IS_PRIVATE(dir)))
-               return 0;
--      return security_ops->inode_mknod(dir, dentry, mode, dev);
-+      return security_ops->inode_mknod(dir, dentry, mnt, mode, dev);
- }
- int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
--                         struct inode *new_dir, struct dentry *new_dentry)
-+                        struct vfsmount *old_mnt, struct inode *new_dir,
-+                        struct dentry *new_dentry, struct vfsmount *new_mnt)
- {
-         if (unlikely(IS_PRIVATE(old_dentry->d_inode) ||
-             (new_dentry->d_inode && IS_PRIVATE(new_dentry->d_inode))))
-               return 0;
--      return security_ops->inode_rename(old_dir, old_dentry,
--                                         new_dir, new_dentry);
-+      return security_ops->inode_rename(old_dir, old_dentry, old_mnt,
-+                                         new_dir, new_dentry, new_mnt);
- }
--int security_inode_readlink(struct dentry *dentry)
-+int security_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
- {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
-               return 0;
--      return security_ops->inode_readlink(dentry);
-+      return security_ops->inode_readlink(dentry, mnt);
- }
- int security_inode_follow_link(struct dentry *dentry, struct nameidata *nd)
-@@ -434,11 +442,12 @@ int security_inode_permission(struct ino
-       return security_ops->inode_permission(inode, mask, nd);
- }
--int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
-+int security_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
-+                         struct iattr *attr)
- {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
-               return 0;
--      return security_ops->inode_setattr(dentry, attr);
-+      return security_ops->inode_setattr(dentry, mnt, attr);
- }
- int security_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
-@@ -455,41 +464,48 @@ void security_inode_delete(struct inode 
-       security_ops->inode_delete(inode);
- }
--int security_inode_setxattr(struct dentry *dentry, char *name,
--                           void *value, size_t size, int flags)
-+int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
-+                          char *name, void *value, size_t size, int flags,
-+                          struct file *file)
- {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
-               return 0;
--      return security_ops->inode_setxattr(dentry, name, value, size, flags);
-+      return security_ops->inode_setxattr(dentry, mnt, name, value, size,
-+                                          flags, file);
- }
--void security_inode_post_setxattr(struct dentry *dentry, char *name,
--                                 void *value, size_t size, int flags)
-+void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
-+                                char *name, void *value, size_t size,
-+                                int flags)
- {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
-               return;
--      security_ops->inode_post_setxattr(dentry, name, value, size, flags);
-+      security_ops->inode_post_setxattr(dentry, mnt, name, value, size,
-+                                       flags);
- }
--int security_inode_getxattr(struct dentry *dentry, char *name)
-+int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
-+                          char *name, struct file *file)
- {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
-               return 0;
--      return security_ops->inode_getxattr(dentry, name);
-+      return security_ops->inode_getxattr(dentry, mnt, name, file);
- }
--int security_inode_listxattr(struct dentry *dentry)
-+int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
-+                           struct file *file)
- {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
-               return 0;
--      return security_ops->inode_listxattr(dentry);
-+      return security_ops->inode_listxattr(dentry, mnt, file);
- }
--int security_inode_removexattr(struct dentry *dentry, char *name)
-+int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
-+                             char *name, struct file *file)
- {
-       if (unlikely(IS_PRIVATE(dentry->d_inode)))
-               return 0;
--      return security_ops->inode_removexattr(dentry, name);
-+      return security_ops->inode_removexattr(dentry, mnt, name, file);
- }
- int security_inode_need_killpriv(struct dentry *dentry)
-diff -uprN e/security/selinux/hooks.c f/security/selinux/hooks.c
---- e/security/selinux/hooks.c 2008-05-28 20:32:27.897940261 +0000
-+++ f/security/selinux/hooks.c 2008-05-28 20:29:29.410207000 +0000
-@@ -1712,40 +1712,15 @@ static int selinux_capable(struct task_s
- static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid)
- {
--      int buflen, rc;
--      char *buffer, *path, *end;
-+      char *buffer, *path;
-+      int rc = -ENOMEM;
--      rc = -ENOMEM;
-       buffer = (char*)__get_free_page(GFP_KERNEL);
-       if (!buffer)
-               goto out;
--
--      buflen = PAGE_SIZE;
--      end = buffer+buflen;
--      *--end = '\0';
--      buflen--;
--      path = end-1;
--      *path = '/';
--      while (table) {
--              const char *name = table->procname;
--              size_t namelen = strlen(name);
--              buflen -= namelen + 1;
--              if (buflen < 0)
--                      goto out_free;
--              end -= namelen;
--              memcpy(end, name, namelen);
--              *--end = '/';
--              path = end;
--              table = table->parent;
--      }
--      buflen -= 4;
--      if (buflen < 0)
--              goto out_free;
--      end -= 4;
--      memcpy(end, "/sys", 4);
--      path = end;
--      rc = security_genfs_sid("proc", path, tclass, sid);
--out_free:
-+      path = sysctl_pathname(table, buffer, PAGE_SIZE);
-+      if (path)
-+              rc = security_genfs_sid("proc", path, tclass, sid);
-       free_page((unsigned long)buffer);
- out:
-       return rc;
-@@ -2458,64 +2433,79 @@ static int selinux_inode_init_security(s
-       return 0;
- }
--static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask)
-+static int selinux_inode_create(struct inode *dir, struct dentry *dentry,
-+                               struct vfsmount *mnt, int mask)
- {
-       return may_create(dir, dentry, SECCLASS_FILE);
- }
--static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
-+static int selinux_inode_link(struct dentry *old_dentry,
-+                            struct vfsmount *old_mnt,
-+                            struct inode *dir,
-+                            struct dentry *new_dentry,
-+                            struct vfsmount *new_mnt)
- {
-       int rc;
--      rc = secondary_ops->inode_link(old_dentry,dir,new_dentry);
-+      rc = secondary_ops->inode_link(old_dentry, old_mnt, dir, new_dentry,
-+                                     new_mnt);
-       if (rc)
-               return rc;
-       return may_link(dir, old_dentry, MAY_LINK);
- }
--static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry)
-+static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry,
-+                              struct vfsmount *mnt)
- {
-       int rc;
--      rc = secondary_ops->inode_unlink(dir, dentry);
-+      rc = secondary_ops->inode_unlink(dir, dentry, mnt);
-       if (rc)
-               return rc;
-       return may_link(dir, dentry, MAY_UNLINK);
- }
--static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const char *name)
-+static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry,
-+                               struct vfsmount *mnt, const char *name)
- {
-       return may_create(dir, dentry, SECCLASS_LNK_FILE);
- }
--static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask)
-+static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry,
-+                             struct vfsmount *mnt, int mask)
- {
-       return may_create(dir, dentry, SECCLASS_DIR);
- }
--static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry)
-+static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry,
-+                             struct vfsmount *mnt)
- {
-       return may_link(dir, dentry, MAY_RMDIR);
- }
--static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
-+static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry,
-+                             struct vfsmount *mnt, int mode, dev_t dev)
- {
-       int rc;
--      rc = secondary_ops->inode_mknod(dir, dentry, mode, dev);
-+      rc = secondary_ops->inode_mknod(dir, dentry, mnt, mode, dev);
-       if (rc)
-               return rc;
-       return may_create(dir, dentry, inode_mode_to_security_class(mode));
- }
--static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
--                                struct inode *new_inode, struct dentry *new_dentry)
-+static int selinux_inode_rename(struct inode *old_inode,
-+                              struct dentry *old_dentry,
-+                              struct vfsmount *old_mnt,
-+                                struct inode *new_inode,
-+                              struct dentry *new_dentry,
-+                              struct vfsmount *new_mnt)
- {
-       return may_rename(old_inode, old_dentry, new_inode, new_dentry);
- }
--static int selinux_inode_readlink(struct dentry *dentry)
-+static int selinux_inode_readlink(struct dentry *dentry, struct vfsmount *mnt)
- {
-       return dentry_has_perm(current, NULL, dentry, FILE__READ);
- }
-@@ -2548,11 +2538,12 @@ static int selinux_inode_permission(stru
-                              file_mask_to_av(inode->i_mode, mask), NULL);
- }
--static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
-+static int selinux_inode_setattr(struct dentry *dentry, struct vfsmount *mnt,
-+                               struct iattr *iattr)
- {
-       int rc;
--      rc = secondary_ops->inode_setattr(dentry, iattr);
-+      rc = secondary_ops->inode_setattr(dentry, mnt, iattr);
-       if (rc)
-               return rc;
-@@ -2590,7 +2581,9 @@ static int selinux_inode_setotherxattr(s
-       return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
- }
--static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
-+static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
-+                                char *name, void *value, size_t size,
-+                                int flags, struct file *file)
- {
-       struct task_security_struct *tsec = current->security;
-       struct inode *inode = dentry->d_inode;
-@@ -2639,7 +2632,9 @@ static int selinux_inode_setxattr(struct
-                           &ad);
- }
--static void selinux_inode_post_setxattr(struct dentry *dentry, char *name,
-+static void selinux_inode_post_setxattr(struct dentry *dentry,
-+                                      struct vfsmount *mnt,
-+                                      char *name,
-                                         void *value, size_t size, int flags)
- {
-       struct inode *inode = dentry->d_inode;
-@@ -2663,17 +2658,21 @@ static void selinux_inode_post_setxattr(
-       return;
- }
--static int selinux_inode_getxattr (struct dentry *dentry, char *name)
-+static int selinux_inode_getxattr (struct dentry *dentry, struct vfsmount *mnt,
-+                                 char *name, struct file *file)
- {
-       return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
- }
--static int selinux_inode_listxattr (struct dentry *dentry)
-+static int selinux_inode_listxattr (struct dentry *dentry, struct vfsmount *mnt,
-+                                  struct file *file)
- {
-       return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
- }
--static int selinux_inode_removexattr (struct dentry *dentry, char *name)
-+static int selinux_inode_removexattr (struct dentry *dentry,
-+                                    struct vfsmount *mnt, char *name,
-+                                    struct file *file)
- {
-       if (strcmp(name, XATTR_NAME_SELINUX))
-               return selinux_inode_setotherxattr(dentry, name);
---- s/fs/namei.c~      2008-05-29 00:47:22.000000000 +0200
-+++ s/fs/namei.c       2008-05-29 00:53:55.814585231 +0200
-@@ -3022,8 +3022,8 @@
-               new_path.dentry->d_name.len,
-               old_path.dentry->d_name.len, old_path.dentry->d_name.name,
-               old_path.dentry->d_name.len);
--      ret = vfs_rename(dir_nd.path.dentry->d_inode, new_path.dentry,
--              old_nd.path.dentry->d_parent->d_inode, old_path.dentry);
-+      ret = vfs_rename(dir_nd.path.dentry->d_inode, new_path.dentry, new_path.mnt,
-+              old_nd.path.dentry->d_parent->d_inode, old_path.dentry, old_path.mnt);
-       vxdprintk(VXD_CBIT(misc, 2), "vfs_rename: %d", ret);
-       res = new_path.dentry;
---- s/fs/namei.c~      2008-05-29 00:59:12.000000000 +0200
-+++ s/fs/namei.c       2008-05-29 00:59:40.790875766 +0200
-@@ -3048,7 +3048,7 @@
-               goto out_redo;
-       /* error path cleanup */
--      vfs_unlink(dir->d_inode, new_path.dentry, &dir_nd);
-+      vfs_unlink(dir->d_inode, new_path.dentry, &dir_nd, new_path.mnt);
-       dput(new_path.dentry);
- out_redo:
---- s/include/linux/xattr.h~   2008-05-29 01:40:01.000000000 +0200
-+++ s/include/linux/xattr.h    2008-05-29 01:40:06.624153911 +0200
-@@ -16,6 +16,7 @@
- #ifdef  __KERNEL__
- #include <linux/types.h>
-+#include <linux/fs.h>
- /* Namespaces */
- #define XATTR_OS2_PREFIX "os2."
----
- security/apparmor/main.c |    2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
 
---- a/security/apparmor/main.c
-+++ b/security/apparmor/main.c
-@@ -503,10 +503,10 @@ static char *aa_get_name(struct dentry *
-                       *buffer = buf;
-                       return name;
-               }
-+              kfree(buf);
-               if (PTR_ERR(name) != -ENAMETOOLONG)
-                       return name;
--              kfree(buf);
-               size <<= 1;
-               if (size > apparmor_path_max)
-                       return ERR_PTR(-ENAMETOOLONG);
+
This page took 0.355657 seconds and 4 git commands to generate.