mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
[PATCH] move xattr permission checks into the VFS
) From: Christoph Hellwig <[email protected]> The xattr code has rather complex permission checks because the rules are very different for different attribute namespaces. This patch moves as much as we can into the generic code. Currently all the major disk based filesystems duplicate these checks, while many minor filesystems or network filesystems lack some or all of them. To do this we need defines for the extended attribute names in common code, I moved them up from JFS which had the nicest defintions. Signed-off-by: Christoph Hellwig <[email protected]> Acked-by: Dave Kleikamp <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
5be196e5f9
commit
e0ad7b073e
3 changed files with 72 additions and 19 deletions
61
fs/xattr.c
61
fs/xattr.c
|
|
@ -20,6 +20,47 @@
|
|||
#include <asm/uaccess.h>
|
||||
|
||||
|
||||
/*
|
||||
* Check permissions for extended attribute access. This is a bit complicated
|
||||
* because different namespaces have very different rules.
|
||||
*/
|
||||
static int
|
||||
xattr_permission(struct inode *inode, const char *name, int mask)
|
||||
{
|
||||
/*
|
||||
* We can never set or remove an extended attribute on a read-only
|
||||
* filesystem or on an immutable / append-only inode.
|
||||
*/
|
||||
if (mask & MAY_WRITE) {
|
||||
if (IS_RDONLY(inode))
|
||||
return -EROFS;
|
||||
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
/*
|
||||
* No restriction for security.* and system.* from the VFS. Decision
|
||||
* on these is left to the underlying filesystem / security module.
|
||||
*/
|
||||
if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
|
||||
!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The trusted.* namespace can only accessed by a privilegued user.
|
||||
*/
|
||||
if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
|
||||
return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM);
|
||||
|
||||
if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
|
||||
if (!S_ISREG(inode->i_mode) &&
|
||||
(!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
return permission(inode, mask, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
vfs_setxattr(struct dentry *dentry, char *name, void *value,
|
||||
size_t size, int flags)
|
||||
|
|
@ -27,6 +68,10 @@ vfs_setxattr(struct dentry *dentry, char *name, void *value,
|
|||
struct inode *inode = dentry->d_inode;
|
||||
int error;
|
||||
|
||||
error = xattr_permission(inode, name, MAY_WRITE);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
mutex_lock(&inode->i_mutex);
|
||||
error = security_inode_setxattr(dentry, name, value, size, flags);
|
||||
if (error)
|
||||
|
|
@ -40,8 +85,8 @@ vfs_setxattr(struct dentry *dentry, char *name, void *value,
|
|||
size, flags);
|
||||
}
|
||||
} else if (!strncmp(name, XATTR_SECURITY_PREFIX,
|
||||
sizeof XATTR_SECURITY_PREFIX - 1)) {
|
||||
const char *suffix = name + sizeof XATTR_SECURITY_PREFIX - 1;
|
||||
XATTR_SECURITY_PREFIX_LEN)) {
|
||||
const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
|
||||
error = security_inode_setsecurity(inode, suffix, value,
|
||||
size, flags);
|
||||
if (!error)
|
||||
|
|
@ -59,6 +104,10 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
|
|||
struct inode *inode = dentry->d_inode;
|
||||
int error;
|
||||
|
||||
error = xattr_permission(inode, name, MAY_READ);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = security_inode_getxattr(dentry, name);
|
||||
if (error)
|
||||
return error;
|
||||
|
|
@ -69,8 +118,8 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
|
|||
error = -EOPNOTSUPP;
|
||||
|
||||
if (!strncmp(name, XATTR_SECURITY_PREFIX,
|
||||
sizeof XATTR_SECURITY_PREFIX - 1)) {
|
||||
const char *suffix = name + sizeof XATTR_SECURITY_PREFIX - 1;
|
||||
XATTR_SECURITY_PREFIX_LEN)) {
|
||||
const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
|
||||
int ret = security_inode_getsecurity(inode, suffix, value,
|
||||
size, error);
|
||||
/*
|
||||
|
|
@ -94,6 +143,10 @@ vfs_removexattr(struct dentry *dentry, char *name)
|
|||
if (!inode->i_op->removexattr)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
error = xattr_permission(inode, name, MAY_WRITE);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = security_inode_removexattr(dentry, name);
|
||||
if (error)
|
||||
return error;
|
||||
|
|
|
|||
Loading…
Reference in a new issue