

Patch from Andreas Gruenbacher <agruen@suse.de>

This patch adds trusted extended attributes.  Trusted extended attributes are
visible and accessible only to processes that have the CAP_SYS_ADMIN
capability.  Attributes in this class are used to implement mechanisms in
user space (i.e., outside the kernel) which keep information in extended
attributes to which ordinary processes have no access.  HSM is an example.




 fs/ext2/Makefile        |    2 -
 fs/ext2/xattr.c         |   23 ++++++++++++-----
 fs/ext2/xattr.h         |    2 +
 fs/ext2/xattr_trusted.c |   63 +++++++++++++++++++++++++++++++++++++++++++++++
 fs/ext3/Makefile        |    2 -
 fs/ext3/xattr.c         |   23 ++++++++++++-----
 fs/ext3/xattr.h         |    2 +
 fs/ext3/xattr_trusted.c |   64 ++++++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 167 insertions(+), 14 deletions(-)

diff -puN fs/ext2/Makefile~xattr-trusted fs/ext2/Makefile
--- 25/fs/ext2/Makefile~xattr-trusted	Tue Feb 11 12:17:49 2003
+++ 25-akpm/fs/ext2/Makefile	Tue Feb 11 12:17:49 2003
@@ -8,7 +8,7 @@ ext2-objs := balloc.o bitmap.o dir.o fil
 	     ioctl.o namei.o super.o symlink.o
 
 ifeq ($(CONFIG_EXT2_FS_XATTR),y)
-ext2-objs += xattr.o xattr_user.o
+ext2-objs += xattr.o xattr_user.o xattr_trusted.o
 endif
 
 ifeq ($(CONFIG_EXT2_FS_POSIX_ACL),y)
diff -puN fs/ext2/xattr.c~xattr-trusted fs/ext2/xattr.c
--- 25/fs/ext2/xattr.c~xattr-trusted	Tue Feb 11 12:17:49 2003
+++ 25-akpm/fs/ext2/xattr.c	Tue Feb 11 12:17:49 2003
@@ -1093,27 +1093,35 @@ init_ext2_xattr(void)
 {
 	int	err;
 	
-	err = ext2_xattr_register(EXT2_XATTR_INDEX_USER, &ext2_xattr_user_handler);
+	err = ext2_xattr_register(EXT2_XATTR_INDEX_USER,
+				  &ext2_xattr_user_handler);
 	if (err)
 		return err;
+	err = ext2_xattr_register(EXT2_XATTR_INDEX_TRUSTED,
+				  &ext2_xattr_trusted_handler);
+	if (err)
+		goto out;
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
 	err = init_ext2_acl();
 	if (err)
-		goto out;
+		goto out1;
 #endif
 	ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
 		sizeof(struct mb_cache_entry) +
 		sizeof(struct mb_cache_entry_index), 1, 6);
 	if (!ext2_xattr_cache) {
 		err = -ENOMEM;
-		goto out1;
+		goto out2;
 	}
 	return 0;
-out1:
+out2:
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
 	exit_ext2_acl();
-out:
+out1:
 #endif
+	ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED,
+			      &ext2_xattr_trusted_handler);
+out:
 	ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
 			      &ext2_xattr_user_handler);
 	return err;
@@ -1126,5 +1134,8 @@ exit_ext2_xattr(void)
 #ifdef CONFIG_EXT2_FS_POSIX_ACL
 	exit_ext2_acl();
 #endif
-	ext2_xattr_unregister(EXT2_XATTR_INDEX_USER, &ext2_xattr_user_handler);
+	ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED,
+			      &ext2_xattr_trusted_handler);
+	ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
+			      &ext2_xattr_user_handler);
 }
diff -puN fs/ext2/xattr.h~xattr-trusted fs/ext2/xattr.h
--- 25/fs/ext2/xattr.h~xattr-trusted	Tue Feb 11 12:17:49 2003
+++ 25-akpm/fs/ext2/xattr.h	Tue Feb 11 12:17:49 2003
@@ -21,6 +21,7 @@
 #define EXT2_XATTR_INDEX_USER			1
 #define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS	2
 #define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT	3
+#define EXT2_XATTR_INDEX_TRUSTED		4
 
 struct ext2_xattr_header {
 	__u32	h_magic;	/* magic number for identification */
@@ -132,4 +133,5 @@ exit_ext2_xattr(void)
 # endif  /* CONFIG_EXT2_FS_XATTR */
 
 extern struct ext2_xattr_handler ext2_xattr_user_handler;
+extern struct ext2_xattr_handler ext2_xattr_trusted_handler;
 
diff -puN /dev/null fs/ext2/xattr_trusted.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/fs/ext2/xattr_trusted.c	Tue Feb 11 12:17:49 2003
@@ -0,0 +1,63 @@
+/*
+ * linux/fs/ext2/xattr_trusted.c
+ * Handler for trusted extended attributes.
+ *
+ * Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/ext2_fs.h>
+#include "xattr.h"
+
+#define XATTR_TRUSTED_PREFIX "trusted."
+
+static size_t
+ext2_xattr_trusted_list(char *list, struct inode *inode,
+			const char *name, int name_len, int flags)
+{
+	const int prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
+
+	if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN)))
+		return 0;
+
+	if (list) {
+		memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
+		memcpy(list+prefix_len, name, name_len);
+		list[prefix_len + name_len] = '\0';
+	}
+	return prefix_len + name_len + 1;
+}
+
+static int
+ext2_xattr_trusted_get(struct inode *inode, const char *name,
+		       void *buffer, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN)))
+		return -EPERM;
+	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name,
+			      buffer, size);
+}
+
+static int
+ext2_xattr_trusted_set(struct inode *inode, const char *name,
+		       const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN)))
+		return -EPERM;
+	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name,
+			      value, size, flags);
+}
+
+struct ext2_xattr_handler ext2_xattr_trusted_handler = {
+	.prefix	= XATTR_TRUSTED_PREFIX,
+	.list	= ext2_xattr_trusted_list,
+	.get	= ext2_xattr_trusted_get,
+	.set	= ext2_xattr_trusted_set,
+};
diff -puN fs/ext3/Makefile~xattr-trusted fs/ext3/Makefile
--- 25/fs/ext3/Makefile~xattr-trusted	Tue Feb 11 12:17:49 2003
+++ 25-akpm/fs/ext3/Makefile	Tue Feb 11 12:17:49 2003
@@ -8,7 +8,7 @@ ext3-objs    := balloc.o bitmap.o dir.o 
 		ioctl.o namei.o super.o symlink.o hash.o
 
 ifeq ($(CONFIG_EXT3_FS_XATTR),y)
-ext3-objs += xattr.o xattr_user.o
+ext3-objs += xattr.o xattr_user.o xattr_trusted.o
 endif
 
 ifeq ($(CONFIG_EXT3_FS_POSIX_ACL),y)
diff -puN fs/ext3/xattr.c~xattr-trusted fs/ext3/xattr.c
--- 25/fs/ext3/xattr.c~xattr-trusted	Tue Feb 11 12:17:49 2003
+++ 25-akpm/fs/ext3/xattr.c	Tue Feb 11 12:17:49 2003
@@ -1133,27 +1133,35 @@ init_ext3_xattr(void)
 {
 	int	err;
 	
-	err = ext3_xattr_register(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler);
+	err = ext3_xattr_register(EXT3_XATTR_INDEX_USER,
+				  &ext3_xattr_user_handler);
 	if (err)
 		return err;
+	err = ext3_xattr_register(EXT3_XATTR_INDEX_TRUSTED,
+				  &ext3_xattr_trusted_handler);
+	if (err)
+		goto out;
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
 	err = init_ext3_acl();
 	if (err)
-		goto out;
+		goto out1;
 #endif
 	ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
 		sizeof(struct mb_cache_entry) +
 		sizeof(struct mb_cache_entry_index), 1, 6);
 	if (!ext3_xattr_cache) {
 		err = -ENOMEM;
-		goto out1;
+		goto out2;
 	}
 	return 0;
-out1:
+out2:
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
 	exit_ext3_acl();
-out:
+out1:
 #endif
+	ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED,
+			      &ext3_xattr_trusted_handler);
+out:
 	ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
 			      &ext3_xattr_user_handler);
 	return err;
@@ -1168,5 +1176,8 @@ exit_ext3_xattr(void)
 #ifdef CONFIG_EXT3_FS_POSIX_ACL
 	exit_ext3_acl();
 #endif
-	ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, &ext3_xattr_user_handler);
+	ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED,
+			      &ext3_xattr_trusted_handler);
+	ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
+			      &ext3_xattr_user_handler);
 }
diff -puN fs/ext3/xattr.h~xattr-trusted fs/ext3/xattr.h
--- 25/fs/ext3/xattr.h~xattr-trusted	Tue Feb 11 12:17:49 2003
+++ 25-akpm/fs/ext3/xattr.h	Tue Feb 11 12:17:49 2003
@@ -20,6 +20,7 @@
 #define EXT3_XATTR_INDEX_USER			1
 #define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS	2
 #define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT	3
+#define EXT3_XATTR_INDEX_TRUSTED		4
 
 struct ext3_xattr_header {
 	__u32	h_magic;	/* magic number for identification */
@@ -139,3 +140,4 @@ exit_ext3_xattr(void)
 # endif  /* CONFIG_EXT3_FS_XATTR */
 
 extern struct ext3_xattr_handler ext3_xattr_user_handler;
+extern struct ext3_xattr_handler ext3_xattr_trusted_handler;
diff -puN /dev/null fs/ext3/xattr_trusted.c
--- /dev/null	Thu Apr 11 07:25:15 2002
+++ 25-akpm/fs/ext3/xattr_trusted.c	Tue Feb 11 12:17:49 2003
@@ -0,0 +1,64 @@
+/*
+ * linux/fs/ext3/xattr_trusted.c
+ * Handler for trusted extended attributes.
+ *
+ * Copyright (C) 2003 by Andreas Gruenbacher, <a.gruenbacher@computer.org>
+ */
+
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/smp_lock.h>
+#include <linux/ext3_jbd.h>
+#include <linux/ext3_fs.h>
+#include "xattr.h"
+
+#define XATTR_TRUSTED_PREFIX "trusted."
+
+static size_t
+ext3_xattr_trusted_list(char *list, struct inode *inode,
+			const char *name, int name_len, int flags)
+{
+	const int prefix_len = sizeof(XATTR_TRUSTED_PREFIX)-1;
+
+	if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN)))
+		return 0;
+
+	if (list) {
+		memcpy(list, XATTR_TRUSTED_PREFIX, prefix_len);
+		memcpy(list+prefix_len, name, name_len);
+		list[prefix_len + name_len] = '\0';
+	}
+	return prefix_len + name_len + 1;
+}
+
+static int
+ext3_xattr_trusted_get(struct inode *inode, const char *name,
+		       void *buffer, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN)))
+		return -EPERM;
+	return ext3_xattr_get(inode, EXT3_XATTR_INDEX_TRUSTED, name,
+			      buffer, size);
+}
+
+static int
+ext3_xattr_trusted_set(struct inode *inode, const char *name,
+		       const void *value, size_t size, int flags)
+{
+	if (strcmp(name, "") == 0)
+		return -EINVAL;
+	if (!((flags & XATTR_KERNEL_CONTEXT) || capable(CAP_SYS_ADMIN)))
+		return -EPERM;
+	return ext3_xattr_set(inode, EXT3_XATTR_INDEX_TRUSTED, name,
+			      value, size, flags);
+}
+
+struct ext3_xattr_handler ext3_xattr_trusted_handler = {
+	.prefix	= XATTR_TRUSTED_PREFIX,
+	.list	= ext3_xattr_trusted_list,
+	.get	= ext3_xattr_trusted_get,
+	.set	= ext3_xattr_trusted_set,
+};

_
