Commit f83b53c5 authored by Andrew Morton's avatar Andrew Morton Committed by Jens Axboe

[PATCH] xattr: allow kernel code to override EA permissions

Patch from Andreas Gruenbacher <agruen@suse.de>

This adds the XATTR_KERNEL_CONTEXT extended attributes flag.  Kernel code may
use this flag to override extended attribute permission restrictions that
would otherwise be imposed on the calling process.
parent 36bc191b
......@@ -23,7 +23,8 @@ ext2_xattr_user_list(char *list, struct inode *inode,
{
const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
if (!test_opt(inode->i_sb, XATTR_USER))
if (!(flags & XATTR_KERNEL_CONTEXT) &&
!test_opt(inode->i_sb, XATTR_USER))
return 0;
if (list) {
......@@ -38,20 +39,21 @@ static int
ext2_xattr_user_get(struct inode *inode, const char *name,
void *buffer, size_t size, int flags)
{
int error;
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
if (!(flags & XATTR_KERNEL_CONTEXT)) {
int error;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
#ifdef CONFIG_EXT2_FS_POSIX_ACL
error = ext2_permission_locked(inode, MAY_READ);
error = ext2_permission_locked(inode, MAY_READ);
#else
error = permission(inode, MAY_READ);
error = permission(inode, MAY_READ);
#endif
if (error)
return error;
if (error)
return error;
}
return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
buffer, size);
}
......@@ -60,23 +62,24 @@ static int
ext2_xattr_user_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
int error;
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
if ( !S_ISREG(inode->i_mode) &&
(!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
return -EPERM;
if (!(flags & XATTR_KERNEL_CONTEXT)) {
int error;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
#ifdef CONFIG_EXT2_FS_POSIX_ACL
error = ext2_permission_locked(inode, MAY_WRITE);
error = ext2_permission_locked(inode, MAY_WRITE);
#else
error = permission(inode, MAY_WRITE);
error = permission(inode, MAY_WRITE);
#endif
if (error)
return error;
if (error)
return error;
}
return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
value, size, flags);
}
......
......@@ -25,7 +25,8 @@ ext3_xattr_user_list(char *list, struct inode *inode,
{
const int prefix_len = sizeof(XATTR_USER_PREFIX)-1;
if (!test_opt(inode->i_sb, XATTR_USER))
if (!(flags & XATTR_KERNEL_CONTEXT) &&
!test_opt(inode->i_sb, XATTR_USER))
return 0;
if (list) {
......@@ -40,20 +41,21 @@ static int
ext3_xattr_user_get(struct inode *inode, const char *name,
void *buffer, size_t size, int flags)
{
int error;
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
if (!(flags & XATTR_KERNEL_CONTEXT)) {
int error;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
#ifdef CONFIG_EXT3_FS_POSIX_ACL
error = ext3_permission_locked(inode, MAY_READ);
error = ext3_permission_locked(inode, MAY_READ);
#else
error = permission(inode, MAY_READ);
error = permission(inode, MAY_READ);
#endif
if (error)
return error;
if (error)
return error;
}
return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
buffer, size);
}
......@@ -62,26 +64,26 @@ static int
ext3_xattr_user_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags)
{
int error;
if (strcmp(name, "") == 0)
return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
if ( !S_ISREG(inode->i_mode) &&
(!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
return -EPERM;
if (!(flags & XATTR_KERNEL_CONTEXT)) {
int error;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
#ifdef CONFIG_EXT3_FS_POSIX_ACL
error = ext3_permission_locked(inode, MAY_WRITE);
error = ext3_permission_locked(inode, MAY_WRITE);
#else
error = permission(inode, MAY_WRITE);
error = permission(inode, MAY_WRITE);
#endif
if (error)
return error;
if (error)
return error;
}
return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name,
value, size, flags);
}
struct ext3_xattr_handler ext3_xattr_user_handler = {
......
......@@ -9,7 +9,8 @@
#ifndef _LINUX_XATTR_H
#define _LINUX_XATTR_H
#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
#define XATTR_CREATE 0x1 /* fail if attr already exists */
#define XATTR_REPLACE 0x2 /* fail if attr does not exist */
#define XATTR_KERNEL_CONTEXT 0x4 /* called from kernel context */
#endif /* _LINUX_XATTR_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment