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

[PATCH] xattr: trusted extended attributes

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.
parent f83b53c5
...@@ -8,7 +8,7 @@ ext2-objs := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ ...@@ -8,7 +8,7 @@ ext2-objs := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
ioctl.o namei.o super.o symlink.o ioctl.o namei.o super.o symlink.o
ifeq ($(CONFIG_EXT2_FS_XATTR),y) ifeq ($(CONFIG_EXT2_FS_XATTR),y)
ext2-objs += xattr.o xattr_user.o ext2-objs += xattr.o xattr_user.o xattr_trusted.o
endif endif
ifeq ($(CONFIG_EXT2_FS_POSIX_ACL),y) ifeq ($(CONFIG_EXT2_FS_POSIX_ACL),y)
......
...@@ -1093,27 +1093,35 @@ init_ext2_xattr(void) ...@@ -1093,27 +1093,35 @@ init_ext2_xattr(void)
{ {
int err; 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) if (err)
return 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 #ifdef CONFIG_EXT2_FS_POSIX_ACL
err = init_ext2_acl(); err = init_ext2_acl();
if (err) if (err)
goto out; goto out1;
#endif #endif
ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL, ext2_xattr_cache = mb_cache_create("ext2_xattr", NULL,
sizeof(struct mb_cache_entry) + sizeof(struct mb_cache_entry) +
sizeof(struct mb_cache_entry_index), 1, 6); sizeof(struct mb_cache_entry_index), 1, 6);
if (!ext2_xattr_cache) { if (!ext2_xattr_cache) {
err = -ENOMEM; err = -ENOMEM;
goto out1; goto out2;
} }
return 0; return 0;
out1: out2:
#ifdef CONFIG_EXT2_FS_POSIX_ACL #ifdef CONFIG_EXT2_FS_POSIX_ACL
exit_ext2_acl(); exit_ext2_acl();
out: out1:
#endif #endif
ext2_xattr_unregister(EXT2_XATTR_INDEX_TRUSTED,
&ext2_xattr_trusted_handler);
out:
ext2_xattr_unregister(EXT2_XATTR_INDEX_USER, ext2_xattr_unregister(EXT2_XATTR_INDEX_USER,
&ext2_xattr_user_handler); &ext2_xattr_user_handler);
return err; return err;
...@@ -1126,5 +1134,8 @@ exit_ext2_xattr(void) ...@@ -1126,5 +1134,8 @@ exit_ext2_xattr(void)
#ifdef CONFIG_EXT2_FS_POSIX_ACL #ifdef CONFIG_EXT2_FS_POSIX_ACL
exit_ext2_acl(); exit_ext2_acl();
#endif #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);
} }
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#define EXT2_XATTR_INDEX_USER 1 #define EXT2_XATTR_INDEX_USER 1
#define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2 #define EXT2_XATTR_INDEX_POSIX_ACL_ACCESS 2
#define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3 #define EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT 3
#define EXT2_XATTR_INDEX_TRUSTED 4
struct ext2_xattr_header { struct ext2_xattr_header {
__u32 h_magic; /* magic number for identification */ __u32 h_magic; /* magic number for identification */
...@@ -132,4 +133,5 @@ exit_ext2_xattr(void) ...@@ -132,4 +133,5 @@ exit_ext2_xattr(void)
# endif /* CONFIG_EXT2_FS_XATTR */ # endif /* CONFIG_EXT2_FS_XATTR */
extern struct ext2_xattr_handler ext2_xattr_user_handler; extern struct ext2_xattr_handler ext2_xattr_user_handler;
extern struct ext2_xattr_handler ext2_xattr_trusted_handler;
/*
* 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,
};
...@@ -8,7 +8,7 @@ ext3-objs := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \ ...@@ -8,7 +8,7 @@ ext3-objs := balloc.o bitmap.o dir.o file.o fsync.o ialloc.o inode.o \
ioctl.o namei.o super.o symlink.o hash.o ioctl.o namei.o super.o symlink.o hash.o
ifeq ($(CONFIG_EXT3_FS_XATTR),y) ifeq ($(CONFIG_EXT3_FS_XATTR),y)
ext3-objs += xattr.o xattr_user.o ext3-objs += xattr.o xattr_user.o xattr_trusted.o
endif endif
ifeq ($(CONFIG_EXT3_FS_POSIX_ACL),y) ifeq ($(CONFIG_EXT3_FS_POSIX_ACL),y)
......
...@@ -1133,27 +1133,35 @@ init_ext3_xattr(void) ...@@ -1133,27 +1133,35 @@ init_ext3_xattr(void)
{ {
int err; 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) if (err)
return 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 #ifdef CONFIG_EXT3_FS_POSIX_ACL
err = init_ext3_acl(); err = init_ext3_acl();
if (err) if (err)
goto out; goto out1;
#endif #endif
ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL, ext3_xattr_cache = mb_cache_create("ext3_xattr", NULL,
sizeof(struct mb_cache_entry) + sizeof(struct mb_cache_entry) +
sizeof(struct mb_cache_entry_index), 1, 6); sizeof(struct mb_cache_entry_index), 1, 6);
if (!ext3_xattr_cache) { if (!ext3_xattr_cache) {
err = -ENOMEM; err = -ENOMEM;
goto out1; goto out2;
} }
return 0; return 0;
out1: out2:
#ifdef CONFIG_EXT3_FS_POSIX_ACL #ifdef CONFIG_EXT3_FS_POSIX_ACL
exit_ext3_acl(); exit_ext3_acl();
out: out1:
#endif #endif
ext3_xattr_unregister(EXT3_XATTR_INDEX_TRUSTED,
&ext3_xattr_trusted_handler);
out:
ext3_xattr_unregister(EXT3_XATTR_INDEX_USER, ext3_xattr_unregister(EXT3_XATTR_INDEX_USER,
&ext3_xattr_user_handler); &ext3_xattr_user_handler);
return err; return err;
...@@ -1168,5 +1176,8 @@ exit_ext3_xattr(void) ...@@ -1168,5 +1176,8 @@ exit_ext3_xattr(void)
#ifdef CONFIG_EXT3_FS_POSIX_ACL #ifdef CONFIG_EXT3_FS_POSIX_ACL
exit_ext3_acl(); exit_ext3_acl();
#endif #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);
} }
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#define EXT3_XATTR_INDEX_USER 1 #define EXT3_XATTR_INDEX_USER 1
#define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2 #define EXT3_XATTR_INDEX_POSIX_ACL_ACCESS 2
#define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3 #define EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT 3
#define EXT3_XATTR_INDEX_TRUSTED 4
struct ext3_xattr_header { struct ext3_xattr_header {
__u32 h_magic; /* magic number for identification */ __u32 h_magic; /* magic number for identification */
...@@ -139,3 +140,4 @@ exit_ext3_xattr(void) ...@@ -139,3 +140,4 @@ exit_ext3_xattr(void)
# endif /* CONFIG_EXT3_FS_XATTR */ # endif /* CONFIG_EXT3_FS_XATTR */
extern struct ext3_xattr_handler ext3_xattr_user_handler; extern struct ext3_xattr_handler ext3_xattr_user_handler;
extern struct ext3_xattr_handler ext3_xattr_trusted_handler;
/*
* 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,
};
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