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, ...@@ -23,7 +23,8 @@ ext2_xattr_user_list(char *list, struct inode *inode,
{ {
const int prefix_len = sizeof(XATTR_USER_PREFIX)-1; 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; return 0;
if (list) { if (list) {
...@@ -38,10 +39,11 @@ static int ...@@ -38,10 +39,11 @@ static int
ext2_xattr_user_get(struct inode *inode, const char *name, ext2_xattr_user_get(struct inode *inode, const char *name,
void *buffer, size_t size, int flags) void *buffer, size_t size, int flags)
{ {
int error;
if (strcmp(name, "") == 0) if (strcmp(name, "") == 0)
return -EINVAL; return -EINVAL;
if (!(flags & XATTR_KERNEL_CONTEXT)) {
int error;
if (!test_opt(inode->i_sb, XATTR_USER)) if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP; return -EOPNOTSUPP;
#ifdef CONFIG_EXT2_FS_POSIX_ACL #ifdef CONFIG_EXT2_FS_POSIX_ACL
...@@ -51,7 +53,7 @@ ext2_xattr_user_get(struct inode *inode, const char *name, ...@@ -51,7 +53,7 @@ ext2_xattr_user_get(struct inode *inode, const char *name,
#endif #endif
if (error) if (error)
return error; return error;
}
return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name, return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER, name,
buffer, size); buffer, size);
} }
...@@ -60,15 +62,16 @@ static int ...@@ -60,15 +62,16 @@ static int
ext2_xattr_user_set(struct inode *inode, const char *name, ext2_xattr_user_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags) const void *value, size_t size, int flags)
{ {
int error;
if (strcmp(name, "") == 0) if (strcmp(name, "") == 0)
return -EINVAL; return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
if ( !S_ISREG(inode->i_mode) && if ( !S_ISREG(inode->i_mode) &&
(!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
return -EPERM; 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 #ifdef CONFIG_EXT2_FS_POSIX_ACL
error = ext2_permission_locked(inode, MAY_WRITE); error = ext2_permission_locked(inode, MAY_WRITE);
#else #else
...@@ -76,7 +79,7 @@ ext2_xattr_user_set(struct inode *inode, const char *name, ...@@ -76,7 +79,7 @@ ext2_xattr_user_set(struct inode *inode, const char *name,
#endif #endif
if (error) if (error)
return error; return error;
}
return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name, return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER, name,
value, size, flags); value, size, flags);
} }
......
...@@ -25,7 +25,8 @@ ext3_xattr_user_list(char *list, struct inode *inode, ...@@ -25,7 +25,8 @@ ext3_xattr_user_list(char *list, struct inode *inode,
{ {
const int prefix_len = sizeof(XATTR_USER_PREFIX)-1; 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; return 0;
if (list) { if (list) {
...@@ -40,10 +41,11 @@ static int ...@@ -40,10 +41,11 @@ static int
ext3_xattr_user_get(struct inode *inode, const char *name, ext3_xattr_user_get(struct inode *inode, const char *name,
void *buffer, size_t size, int flags) void *buffer, size_t size, int flags)
{ {
int error;
if (strcmp(name, "") == 0) if (strcmp(name, "") == 0)
return -EINVAL; return -EINVAL;
if (!(flags & XATTR_KERNEL_CONTEXT)) {
int error;
if (!test_opt(inode->i_sb, XATTR_USER)) if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP; return -EOPNOTSUPP;
#ifdef CONFIG_EXT3_FS_POSIX_ACL #ifdef CONFIG_EXT3_FS_POSIX_ACL
...@@ -53,7 +55,7 @@ ext3_xattr_user_get(struct inode *inode, const char *name, ...@@ -53,7 +55,7 @@ ext3_xattr_user_get(struct inode *inode, const char *name,
#endif #endif
if (error) if (error)
return error; return error;
}
return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name, return ext3_xattr_get(inode, EXT3_XATTR_INDEX_USER, name,
buffer, size); buffer, size);
} }
...@@ -62,15 +64,16 @@ static int ...@@ -62,15 +64,16 @@ static int
ext3_xattr_user_set(struct inode *inode, const char *name, ext3_xattr_user_set(struct inode *inode, const char *name,
const void *value, size_t size, int flags) const void *value, size_t size, int flags)
{ {
int error;
if (strcmp(name, "") == 0) if (strcmp(name, "") == 0)
return -EINVAL; return -EINVAL;
if (!test_opt(inode->i_sb, XATTR_USER))
return -EOPNOTSUPP;
if ( !S_ISREG(inode->i_mode) && if ( !S_ISREG(inode->i_mode) &&
(!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
return -EPERM; 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 #ifdef CONFIG_EXT3_FS_POSIX_ACL
error = ext3_permission_locked(inode, MAY_WRITE); error = ext3_permission_locked(inode, MAY_WRITE);
#else #else
...@@ -78,10 +81,9 @@ ext3_xattr_user_set(struct inode *inode, const char *name, ...@@ -78,10 +81,9 @@ ext3_xattr_user_set(struct inode *inode, const char *name,
#endif #endif
if (error) if (error)
return error; return error;
}
return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name, return ext3_xattr_set(inode, EXT3_XATTR_INDEX_USER, name,
value, size, flags); value, size, flags);
} }
struct ext3_xattr_handler ext3_xattr_user_handler = { struct ext3_xattr_handler ext3_xattr_user_handler = {
......
...@@ -9,7 +9,8 @@ ...@@ -9,7 +9,8 @@
#ifndef _LINUX_XATTR_H #ifndef _LINUX_XATTR_H
#define _LINUX_XATTR_H #define _LINUX_XATTR_H
#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ #define XATTR_CREATE 0x1 /* fail if attr already exists */
#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ #define XATTR_REPLACE 0x2 /* fail if attr does not exist */
#define XATTR_KERNEL_CONTEXT 0x4 /* called from kernel context */
#endif /* _LINUX_XATTR_H */ #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