mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-07 01:41:00 +01:00
201 lines
5.9 KiB
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
|