Patch from Andreas Gruenbacher 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. fs/ext2/xattr_user.c | 41 ++++++++++++++++++++++------------------- fs/ext3/xattr_user.c | 42 ++++++++++++++++++++++-------------------- include/linux/xattr.h | 5 +++-- 3 files changed, 47 insertions(+), 41 deletions(-) diff -puN fs/ext2/xattr_user.c~xattr-flags-policy fs/ext2/xattr_user.c --- 25/fs/ext2/xattr_user.c~xattr-flags-policy Tue Feb 11 12:17:47 2003 +++ 25-akpm/fs/ext2/xattr_user.c Tue Feb 11 12:17:47 2003 @@ -23,7 +23,8 @@ ext2_xattr_user_list(char *list, struct { 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); } diff -puN fs/ext3/xattr_user.c~xattr-flags-policy fs/ext3/xattr_user.c --- 25/fs/ext3/xattr_user.c~xattr-flags-policy Tue Feb 11 12:17:47 2003 +++ 25-akpm/fs/ext3/xattr_user.c Tue Feb 11 12:17:47 2003 @@ -25,7 +25,8 @@ ext3_xattr_user_list(char *list, struct { 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 = { diff -puN include/linux/xattr.h~xattr-flags-policy include/linux/xattr.h --- 25/include/linux/xattr.h~xattr-flags-policy Tue Feb 11 12:17:47 2003 +++ 25-akpm/include/linux/xattr.h Tue Feb 11 12:17:47 2003 @@ -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 */ _