--- /dev/null
+From: Jeff Mahoney <jeffm@suse.com>
+Subject: [PATCH] vfs: introduce path_permission()
+
+ 2.6.27 eliminated the nameidata parameter from permission and replaced
+ several call sites with inode_permission. This keeps the information
+ required by AppArmor from reaching it.
+
+ The following patch factors out the permission assessment part of
+ inode_permission into __inode_permission and adds a path_permission
+ function that takes a struct path instead of a struct inode and passes
+ it to security_path_permission instead of security_inode_permission.
+
+ All of the call sites that had access to a struct path whether by
+ itself or via a file or nameidata (and used it) in 2.6.26 are changed
+ to use the path_permission call.
+
+Signed-off-by: Jeff Mahoney <jeffm@suse.com>
+---
+ fs/inotify_user.c | 2 +-
+ fs/namei.c | 32 ++++++++++++++++++++++++--------
+ fs/open.c | 10 +++++-----
+ include/linux/fs.h | 5 +++++
+ 4 files changed, 35 insertions(+), 14 deletions(-)
+
+--- a/fs/inotify_user.c
++++ b/fs/inotify_user.c
+@@ -372,7 +372,7 @@ static int find_inode(const char __user
+ if (error)
+ return error;
+ /* you can only watch an inode if you have read permissions on it */
+- error = inode_permission(path->dentry->d_inode, MAY_READ);
++ error = path_permission(path, MAY_READ);
+ if (error)
+ path_put(path);
+ return error;
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -227,7 +227,7 @@ int generic_permission(struct inode *ino
+ return -EACCES;
+ }
+
+-int inode_permission(struct inode *inode, int mask)
++static int __inode_permission(struct inode *inode, int mask)
+ {
+ int retval;
+ int submask = mask;
+@@ -273,7 +273,12 @@ int inode_permission(struct inode *inode
+ if (retval)
+ return retval;
+
+- retval = devcgroup_inode_permission(inode, mask);
++ return devcgroup_inode_permission(inode, mask);
++}
++
++int inode_permission(struct inode *inode, int mask)
++{
++ int retval = __inode_permission(inode, mask);
+ if (retval)
+ return retval;
+
+@@ -281,6 +286,15 @@ int inode_permission(struct inode *inode
+ mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
+ }
+
++int path_permission(struct path *path, int mask)
++{
++ int retval = __inode_permission(path->dentry->d_inode, mask);
++ if (retval)
++ return retval;
++ return security_path_permission(path,
++ mask & (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND));
++}
++
+ /**
+ * vfs_permission - check for access rights to a given path
+ * @nd: lookup result that describes the path
+@@ -293,7 +307,7 @@ int inode_permission(struct inode *inode
+ */
+ int vfs_permission(struct nameidata *nd, int mask)
+ {
+- return inode_permission(nd->path.dentry->d_inode, mask);
++ return path_permission(&nd->path, mask);
+ }
+
+ /**
+@@ -310,7 +324,7 @@ int vfs_permission(struct nameidata *nd,
+ */
+ int file_permission(struct file *file, int mask)
+ {
+- return inode_permission(file->f_path.dentry->d_inode, mask);
++ return path_permission(&file->f_path, mask);
+ }
+
+ /*
+@@ -452,8 +466,9 @@ static struct dentry * cached_lookup(str
+ * short-cut DAC fails, then call permission() to do more
+ * complete permission check.
+ */
+-static int exec_permission_lite(struct inode *inode)
++static int exec_permission_lite(struct path *path)
+ {
++ struct inode *inode = path->dentry->d_inode;
+ umode_t mode = inode->i_mode;
+
+ if (inode->i_op && inode->i_op->permission)
+@@ -478,7 +493,7 @@ static int exec_permission_lite(struct i
+
+ return -EACCES;
+ ok:
+- return security_inode_permission(inode, MAY_EXEC);
++ return security_path_permission(path, MAY_EXEC);
+ }
+
+ /*
+@@ -875,7 +890,7 @@ static int __link_path_walk(const char *
+ unsigned int c;
+
+ nd->flags |= LOOKUP_CONTINUE;
+- err = exec_permission_lite(inode);
++ err = exec_permission_lite(&nd->path);
+ if (err == -EAGAIN)
+ err = vfs_permission(nd, MAY_EXEC);
+ if (err)
+@@ -1250,7 +1265,7 @@ static struct dentry *lookup_hash(struct
+ {
+ int err;
+
+- err = inode_permission(nd->path.dentry->d_inode, MAY_EXEC);
++ err = path_permission(&nd->path, MAY_EXEC);
+ if (err)
+ return ERR_PTR(err);
+ return __lookup_hash(&nd->last, nd->path.dentry, nd);
+@@ -2907,6 +2922,7 @@ EXPORT_SYMBOL(page_symlink_inode_operati
+ EXPORT_SYMBOL(path_lookup);
+ EXPORT_SYMBOL(vfs_path_lookup);
+ EXPORT_SYMBOL(inode_permission);
++EXPORT_SYMBOL(path_permission);
+ EXPORT_SYMBOL(vfs_permission);
+ EXPORT_SYMBOL(file_permission);
+ EXPORT_SYMBOL(unlock_rename);
+--- a/fs/open.c
++++ b/fs/open.c
+@@ -248,7 +248,7 @@ static long do_sys_truncate(const char _
+ if (error)
+ goto dput_and_out;
+
+- error = inode_permission(inode, MAY_WRITE);
++ error = path_permission(&path, MAY_WRITE);
+ if (error)
+ goto mnt_drop_write_and_out;
+
+@@ -493,7 +493,7 @@ SYSCALL_DEFINE3(faccessat, int, dfd, con
+ goto out_path_release;
+ }
+
+- res = inode_permission(inode, mode | MAY_ACCESS);
++ res = path_permission(&path, mode | MAY_ACCESS);
+ /* SuS v2 requires we report a read only fs too */
+ if (res || !(mode & S_IWOTH) || special_file(inode->i_mode))
+ goto out_path_release;
+@@ -536,7 +536,7 @@ SYSCALL_DEFINE1(chdir, const char __user
+ if (error)
+ goto out;
+
+- error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
++ error = path_permission(&path, MAY_EXEC | MAY_ACCESS);
+ if (error)
+ goto dput_and_out;
+
+@@ -565,7 +565,7 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd
+ if (!S_ISDIR(inode->i_mode))
+ goto out_putf;
+
+- error = inode_permission(inode, MAY_EXEC | MAY_ACCESS);
++ error = path_permission(&file->f_path, MAY_EXEC | MAY_ACCESS);
+ if (!error)
+ set_fs_pwd(current->fs, &file->f_path);
+ out_putf:
+@@ -583,7 +583,7 @@ SYSCALL_DEFINE1(chroot, const char __use
+ if (error)
+ goto out;
+
+- error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS);
++ error = path_permission(&path, MAY_EXEC | MAY_ACCESS);
+ if (error)
+ goto dput_and_out;
+
+--- a/include/linux/fs.h
++++ b/include/linux/fs.h
+@@ -1201,6 +1201,11 @@ extern void dentry_unhash(struct dentry
+ extern int file_permission(struct file *, int);
+
+ /*
++ * VFS path helper functions.
++ */
++extern int path_permission(struct path *, int);
++
++/*
+ * File types
+ *
+ * NOTE! These match bits 12..15 of stat.st_mode