apparmor/kernel-patches/2.6.27/add-path_permission.diff

201 lines
5.9 KiB
Diff

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
@@ -365,7 +365,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;
@@ -269,7 +269,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;
@@ -277,6 +282,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
@@ -289,7 +303,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);
}
/**
@@ -306,7 +320,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);
}
/*
@@ -447,8 +461,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)
@@ -473,7 +488,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);
}
/*
@@ -870,7 +885,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)
@@ -1245,7 +1260,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);
@@ -2872,6 +2887,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
@@ -250,7 +250,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;
@@ -474,7 +474,7 @@ asmlinkage long sys_faccessat(int dfd, c
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;
@@ -517,7 +517,7 @@ asmlinkage long sys_chdir(const char __u
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;
@@ -546,7 +546,7 @@ asmlinkage long sys_fchdir(unsigned int
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:
@@ -564,7 +564,7 @@ asmlinkage long sys_chroot(const char __
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
@@ -1183,6 +1183,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