

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.



 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 */

_
