diff -purN -X dontdiff linux-2.6.8.1.o/fs/Kconfig linux-2.6.8.1.w/fs/Kconfig --- linux-2.6.8.1.o/fs/Kconfig 2004-08-14 10:25:37.000000000 -0400 +++ linux-2.6.8.1.w/fs/Kconfig 2004-08-24 16:47:44.000000000 -0400 @@ -916,6 +916,27 @@ config TMPFS See for details. +config TMPFS_FS_XATTR + bool "tmpfs Extended Attributes" + help + Extended attributes are name:value pairs associated with inodes by + the kernel or by users (see the attr(5) manual page, or visit + for details). + + If unsure, say N. + +config TMPFS_FS_SECURITY + bool "tmpfs Security Labels" + depends on TMPFS_FS_XATTR + help + Security labels support alternative access control models + implemented by security modules like SELinux. This option + enables an extended attribute handler for file security + labels in the tmpfs filesystem. + + If you are not using a security module that requires using + extended attributes for file security labels, say N. + config HUGETLBFS bool "HugeTLB file system support" depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || X86_64 || BROKEN diff -purN -X dontdiff linux-2.6.8.1.o/mm/Makefile linux-2.6.8.1.w/mm/Makefile --- linux-2.6.8.1.o/mm/Makefile 2004-06-16 01:19:37.000000000 -0400 +++ linux-2.6.8.1.w/mm/Makefile 2004-08-24 16:48:16.000000000 -0400 @@ -15,3 +15,5 @@ obj-y := bootmem.o filemap.o mempool.o obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o obj-$(CONFIG_HUGETLBFS) += hugetlb.o obj-$(CONFIG_NUMA) += mempolicy.o +obj-$(CONFIG_TMPFS_FS_XATTR) += xattr.o +obj-$(CONFIG_TMPFS_FS_SECURITY) += xattr_security.o diff -purN -X dontdiff linux-2.6.8.1.o/mm/shmem.c linux-2.6.8.1.w/mm/shmem.c --- linux-2.6.8.1.o/mm/shmem.c 2004-08-14 10:25:45.000000000 -0400 +++ linux-2.6.8.1.w/mm/shmem.c 2004-08-25 00:34:58.237257096 -0400 @@ -10,6 +10,10 @@ * Copyright (C) 2002-2003 VERITAS Software Corporation. * Copyright (C) 2004 Andi Kleen, SuSE Labs * + * xattr support: + * Copyright (C) 2004 Luke Kenneth Casson Leighton + * Copyright (C) 2004 Red Hat, Inc., James Morris + * * This file is released under the GPL. */ @@ -44,6 +48,7 @@ #include #include #include +#include "xattr.h" /* This magic number is used in glibc for posix shared memory */ #define TMPFS_MAGIC 0x01021994 @@ -171,6 +176,7 @@ static struct address_space_operations s static struct file_operations shmem_file_operations; static struct inode_operations shmem_inode_operations; static struct inode_operations shmem_dir_inode_operations; +static struct inode_operations shmfs_special_inode_operations; static struct vm_operations_struct shmem_vm_ops; static struct backing_dev_info shmem_backing_dev_info = { @@ -1202,6 +1208,7 @@ shmem_get_inode(struct super_block *sb, mpol_shared_policy_init(&info->policy); switch (mode & S_IFMT) { default: + inode->i_op = &shmfs_special_inode_operations; init_special_inode(inode, mode, dev); break; case S_IFREG: @@ -1698,6 +1705,10 @@ static void shmem_put_link(struct dentry static struct inode_operations shmem_symlink_inline_operations = { .readlink = generic_readlink, .follow_link = shmem_follow_link_inline, + .setxattr = shmfs_setxattr, + .getxattr = shmfs_getxattr, + .listxattr = shmfs_listxattr, + .removexattr = shmfs_removexattr, }; static struct inode_operations shmem_symlink_inode_operations = { @@ -1705,6 +1716,10 @@ static struct inode_operations shmem_sym .readlink = generic_readlink, .follow_link = shmem_follow_link, .put_link = shmem_put_link, + .setxattr = shmfs_setxattr, + .getxattr = shmfs_getxattr, + .listxattr = shmfs_listxattr, + .removexattr = shmfs_removexattr, }; static int shmem_parse_options(char *options, int *mode, uid_t *uid, gid_t *gid, unsigned long *blocks, unsigned long *inodes) @@ -1923,6 +1938,12 @@ static struct file_operations shmem_file static struct inode_operations shmem_inode_operations = { .truncate = shmem_truncate, .setattr = shmem_notify_change, +#ifdef CONFIG_TMPFS + .setxattr = shmfs_setxattr, + .getxattr = shmfs_getxattr, + .listxattr = shmfs_listxattr, + .removexattr = shmfs_removexattr, +#endif }; static struct inode_operations shmem_dir_inode_operations = { @@ -1936,6 +1957,19 @@ static struct inode_operations shmem_dir .rmdir = shmem_rmdir, .mknod = shmem_mknod, .rename = shmem_rename, + .setxattr = shmfs_setxattr, + .getxattr = shmfs_getxattr, + .listxattr = shmfs_listxattr, + .removexattr = shmfs_removexattr, +#endif +}; + +static struct inode_operations shmfs_special_inode_operations = { +#ifdef CONFIG_TMPFS + .setxattr = shmfs_setxattr, + .getxattr = shmfs_getxattr, + .listxattr = shmfs_listxattr, + .removexattr = shmfs_removexattr, #endif }; @@ -1977,6 +2011,10 @@ static struct vfsmount *shm_mnt; static int __init init_tmpfs(void) { int error; + + error = init_shmfs_xattr(); + if (error) + goto out4; error = init_inodecache(); if (error) @@ -2006,7 +2044,9 @@ out1: out2: destroy_inodecache(); out3: + exit_shmfs_xattr(); shm_mnt = ERR_PTR(error); +out4: return error; } module_init(init_tmpfs) diff -purN -X dontdiff linux-2.6.8.1.o/mm/xattr.c linux-2.6.8.1.w/mm/xattr.c --- linux-2.6.8.1.o/mm/xattr.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.8.1.w/mm/xattr.c 2004-08-24 16:47:44.000000000 -0400 @@ -0,0 +1,214 @@ +/* + File: fs/shmfs/xattr.c + + Derived from fs/ext3/xattr.c, changed in the following ways: + drop everything related to persistent storage of EAs + pass dentry rather than inode to internal methods + only presently define a handler for security modules +*/ + +#include +#include +#include +#include +#include +#include "xattr.h" + +static struct shmfs_xattr_handler *shmfs_xattr_handlers[TMPFS_XATTR_INDEX_MAX]; +static rwlock_t shmfs_handler_lock = RW_LOCK_UNLOCKED; + +int +shmfs_xattr_register(int name_index, struct shmfs_xattr_handler *handler) +{ + int error = -EINVAL; + + if (name_index > 0 && name_index <= TMPFS_XATTR_INDEX_MAX) { + write_lock(&shmfs_handler_lock); + if (!shmfs_xattr_handlers[name_index-1]) { + shmfs_xattr_handlers[name_index-1] = handler; + error = 0; + } + write_unlock(&shmfs_handler_lock); + } + return error; +} + +void +shmfs_xattr_unregister(int name_index, struct shmfs_xattr_handler *handler) +{ + if (name_index > 0 || name_index <= TMPFS_XATTR_INDEX_MAX) { + write_lock(&shmfs_handler_lock); + shmfs_xattr_handlers[name_index-1] = NULL; + write_unlock(&shmfs_handler_lock); + } +} + +static inline const char * +strcmp_prefix(const char *a, const char *a_prefix) +{ + while (*a_prefix && *a == *a_prefix) { + a++; + a_prefix++; + } + return *a_prefix ? NULL : a; +} + +/* + * Decode the extended attribute name, and translate it into + * the name_index and name suffix. + */ +static inline struct shmfs_xattr_handler * +shmfs_xattr_resolve_name(const char **name) +{ + struct shmfs_xattr_handler *handler = NULL; + int i; + + if (!*name) + return NULL; + read_lock(&shmfs_handler_lock); + for (i=0; iprefix); + if (n) { + handler = shmfs_xattr_handlers[i]; + *name = n; + break; + } + } + } + read_unlock(&shmfs_handler_lock); + return handler; +} + +static inline struct shmfs_xattr_handler * +shmfs_xattr_handler(int name_index) +{ + struct shmfs_xattr_handler *handler = NULL; + if (name_index > 0 && name_index <= TMPFS_XATTR_INDEX_MAX) { + read_lock(&shmfs_handler_lock); + handler = shmfs_xattr_handlers[name_index-1]; + read_unlock(&shmfs_handler_lock); + } + return handler; +} + +/* + * Inode operation getxattr() + * + * dentry->d_inode->i_sem down + */ +ssize_t +shmfs_getxattr(struct dentry *dentry, const char *name, + void *buffer, size_t size) +{ + struct shmfs_xattr_handler *handler; + + handler = shmfs_xattr_resolve_name(&name); + if (!handler) + return -EOPNOTSUPP; + return handler->get(dentry, name, buffer, size); +} + +/* + * Inode operation listxattr() + * + * dentry->d_inode->i_sem down + */ +ssize_t +shmfs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) +{ + struct shmfs_xattr_handler *handler = NULL; + int i, error = 0; + unsigned int size = 0; + char *buf; + + read_lock(&shmfs_handler_lock); + + for (i=0; ilist(dentry, NULL); + } + + if (!buffer) { + error = size; + goto out; + } else { + error = -ERANGE; + if (size > buffer_size) + goto out; + } + + buf = buffer; + for (i=0; ilist(dentry, buf); + } + error = size; + +out: + read_unlock(&shmfs_handler_lock); + return size; +} + +/* + * Inode operation setxattr() + * + * dentry->d_inode->i_sem down + */ +int +shmfs_setxattr(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags) +{ + struct shmfs_xattr_handler *handler; + + if (size == 0) + value = ""; /* empty EA, do not remove */ + handler = shmfs_xattr_resolve_name(&name); + if (!handler) + return -EOPNOTSUPP; + return handler->set(dentry, name, value, size, flags); +} + +/* + * Inode operation removexattr() + * + * dentry->d_inode->i_sem down + */ +int +shmfs_removexattr(struct dentry *dentry, const char *name) +{ + struct shmfs_xattr_handler *handler; + + handler = shmfs_xattr_resolve_name(&name); + if (!handler) + return -EOPNOTSUPP; + return handler->set(dentry, name, NULL, 0, XATTR_REPLACE); +} + +int __init +init_shmfs_xattr(void) +{ +#ifdef CONFIG_TMPFS_FS_SECURITY + int err; + + err = shmfs_xattr_register(TMPFS_XATTR_INDEX_SECURITY, + &shmfs_xattr_security_handler); + if (err) + return err; +#endif + + return 0; +} + +void +exit_shmfs_xattr(void) +{ +#ifdef CONFIG_TMPFS_FS_SECURITY + shmfs_xattr_unregister(TMPFS_XATTR_INDEX_SECURITY, + &shmfs_xattr_security_handler); +#endif + +} diff -purN -X dontdiff linux-2.6.8.1.o/mm/xattr.h linux-2.6.8.1.w/mm/xattr.h --- linux-2.6.8.1.o/mm/xattr.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.8.1.w/mm/xattr.h 2004-08-24 16:47:44.000000000 -0400 @@ -0,0 +1,59 @@ +/* + File: fs/shmfs/xattr.h + + Derived from fs/ext3/xattr.h, changed in the following ways: + drop everything related to persistent storage of EAs + pass dentry rather than inode to internal methods + only presently define a handler for security modules +*/ + +#include +#include + +/* Name indexes */ +#define TMPFS_XATTR_INDEX_MAX 10 +#define TMPFS_XATTR_INDEX_SECURITY 1 + +# ifdef CONFIG_TMPFS_FS_XATTR + +struct shmfs_xattr_handler { + char *prefix; + size_t (*list)(struct dentry *dentry, char *buffer); + int (*get)(struct dentry *dentry, const char *name, void *buffer, + size_t size); + int (*set)(struct dentry *dentry, const char *name, const void *buffer, + size_t size, int flags); +}; + +extern int shmfs_xattr_register(int, struct shmfs_xattr_handler *); +extern void shmfs_xattr_unregister(int, struct shmfs_xattr_handler *); + +extern int shmfs_setxattr(struct dentry *, const char *, const void *, size_t, int); +extern ssize_t shmfs_getxattr(struct dentry *, const char *, void *, size_t); +extern ssize_t shmfs_listxattr(struct dentry *, char *, size_t); +extern int shmfs_removexattr(struct dentry *, const char *); + +extern int init_shmfs_xattr(void); +extern void exit_shmfs_xattr(void); + +# else /* CONFIG_TMPFS_FS_XATTR */ +# define shmfs_setxattr NULL +# define shmfs_getxattr NULL +# define shmfs_listxattr NULL +# define shmfs_removexattr NULL + +static inline int +init_shmfs_xattr(void) +{ + return 0; +} + +static inline void +exit_shmfs_xattr(void) +{ +} + +# endif /* CONFIG_TMPFS_FS_XATTR */ + +extern struct shmfs_xattr_handler shmfs_xattr_security_handler; + diff -purN -X dontdiff linux-2.6.8.1.o/mm/xattr_security.c linux-2.6.8.1.w/mm/xattr_security.c --- linux-2.6.8.1.o/mm/xattr_security.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.8.1.w/mm/xattr_security.c 2004-08-24 16:47:44.000000000 -0400 @@ -0,0 +1,40 @@ +/* + * File: fs/shmfs/xattr_security.c + */ + +#include +#include +#include +#include +#include "xattr.h" + +static size_t +shmfs_xattr_security_list(struct dentry *dentry, char *buffer) +{ + return security_inode_listsecurity(dentry, buffer); +} + +static int +shmfs_xattr_security_get(struct dentry *dentry, const char *name, + void *buffer, size_t size) +{ + if (strcmp(name, "") == 0) + return -EINVAL; + return security_inode_getsecurity(dentry, name, buffer, size); +} + +static int +shmfs_xattr_security_set(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags) +{ + if (strcmp(name, "") == 0) + return -EINVAL; + return security_inode_setsecurity(dentry, name, value, size, flags); +} + +struct shmfs_xattr_handler shmfs_xattr_security_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .list = shmfs_xattr_security_list, + .get = shmfs_xattr_security_get, + .set = shmfs_xattr_security_set, +}; diff -purN -X dontdiff linux-2.6.8.1.o/security/selinux/hooks.c linux-2.6.8.1.w/security/selinux/hooks.c --- linux-2.6.8.1.o/security/selinux/hooks.c 2004-08-14 10:25:45.000000000 -0400 +++ linux-2.6.8.1.w/security/selinux/hooks.c 2004-08-24 23:30:37.000000000 -0400 @@ -386,13 +386,6 @@ static int try_context_mount(struct supe break; case Opt_fscontext: - if (sbsec->behavior != SECURITY_FS_USE_XATTR) { - rc = -EINVAL; - printk(KERN_WARNING "SELinux: " - "fscontext option is invalid for" - " this filesystem type\n"); - goto out_free; - } if (seen & (Opt_context|Opt_fscontext)) { rc = -EINVAL; printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);