diff options
author | Gabor Juhos <juhosg@openwrt.org> | 2012-05-18 20:10:51 +0000 |
---|---|---|
committer | Gabor Juhos <juhosg@openwrt.org> | 2012-05-18 20:10:51 +0000 |
commit | 1fd4bf270b2100ef13eb41677ff36a377d0d6dba (patch) | |
tree | 19e86293e372b4b3eea7c8a0028c50944058be5a /target/linux/generic/patches-2.6.39/040-backport_tmpfs_xattr.patch | |
parent | 05c0d8b28e5a7cd3209181e5e9250b417e122041 (diff) | |
download | upstream-1fd4bf270b2100ef13eb41677ff36a377d0d6dba.tar.gz upstream-1fd4bf270b2100ef13eb41677ff36a377d0d6dba.tar.bz2 upstream-1fd4bf270b2100ef13eb41677ff36a377d0d6dba.zip |
linux/2.6.39: R.I.P.
SVN-Revision: 31808
Diffstat (limited to 'target/linux/generic/patches-2.6.39/040-backport_tmpfs_xattr.patch')
-rw-r--r-- | target/linux/generic/patches-2.6.39/040-backport_tmpfs_xattr.patch | 477 |
1 files changed, 0 insertions, 477 deletions
diff --git a/target/linux/generic/patches-2.6.39/040-backport_tmpfs_xattr.patch b/target/linux/generic/patches-2.6.39/040-backport_tmpfs_xattr.patch deleted file mode 100644 index c7ae1964e4..0000000000 --- a/target/linux/generic/patches-2.6.39/040-backport_tmpfs_xattr.patch +++ /dev/null @@ -1,477 +0,0 @@ ---- a/fs/Kconfig -+++ b/fs/Kconfig -@@ -121,9 +121,25 @@ config TMPFS - - See <file:Documentation/filesystems/tmpfs.txt> for details. - -+config TMPFS_XATTR -+ bool "Tmpfs extended attributes" -+ depends on TMPFS -+ default n -+ help -+ Extended attributes are name:value pairs associated with inodes by -+ the kernel or by users (see the attr(5) manual page, or visit -+ <http://acl.bestbits.at/> for details). -+ -+ Currently this enables support for the trusted.* and -+ security.* namespaces. -+ -+ If unsure, say N. -+ -+ You need this for POSIX ACL support on tmpfs. -+ - config TMPFS_POSIX_ACL - bool "Tmpfs POSIX Access Control Lists" -- depends on TMPFS -+ depends on TMPFS_XATTR - select GENERIC_ACL - help - POSIX Access Control Lists (ACLs) support permissions for users and ---- a/include/linux/shmem_fs.h -+++ b/include/linux/shmem_fs.h -@@ -9,6 +9,8 @@ - - #define SHMEM_NR_DIRECT 16 - -+#define SHMEM_SYMLINK_INLINE_LEN (SHMEM_NR_DIRECT * sizeof(swp_entry_t)) -+ - struct shmem_inode_info { - spinlock_t lock; - unsigned long flags; -@@ -17,8 +19,12 @@ struct shmem_inode_info { - unsigned long next_index; /* highest alloced index + 1 */ - struct shared_policy policy; /* NUMA memory alloc policy */ - struct page *i_indirect; /* top indirect blocks page */ -- swp_entry_t i_direct[SHMEM_NR_DIRECT]; /* first blocks */ -+ union { -+ swp_entry_t i_direct[SHMEM_NR_DIRECT]; /* first blocks */ -+ char inline_symlink[SHMEM_SYMLINK_INLINE_LEN]; -+ }; - struct list_head swaplist; /* chain of maybes on swap */ -+ struct list_head xattr_list; /* list of shmem_xattr */ - struct inode vfs_inode; - }; - ---- a/mm/shmem.c -+++ b/mm/shmem.c -@@ -99,6 +99,13 @@ static struct vfsmount *shm_mnt; - /* Pretend that each entry is of this size in directory's i_size */ - #define BOGO_DIRENT_SIZE 20 - -+struct shmem_xattr { -+ struct list_head list; /* anchored by shmem_inode_info->xattr_list */ -+ char *name; /* xattr name */ -+ size_t size; -+ char value[0]; -+}; -+ - /* Flag allocation requirements to shmem_getpage and shmem_swp_alloc */ - enum sgp_type { - SGP_READ, /* don't exceed i_size, don't allocate page */ -@@ -822,6 +829,7 @@ static int shmem_notify_change(struct de - static void shmem_evict_inode(struct inode *inode) - { - struct shmem_inode_info *info = SHMEM_I(inode); -+ struct shmem_xattr *xattr, *nxattr; - - if (inode->i_mapping->a_ops == &shmem_aops) { - truncate_inode_pages(inode->i_mapping, 0); -@@ -834,6 +842,11 @@ static void shmem_evict_inode(struct ino - mutex_unlock(&shmem_swaplist_mutex); - } - } -+ -+ list_for_each_entry_safe(xattr, nxattr, &info->xattr_list, list) { -+ kfree(xattr->name); -+ kfree(xattr); -+ } - BUG_ON(inode->i_blocks); - shmem_free_inode(inode->i_sb); - end_writeback(inode); -@@ -1615,6 +1628,7 @@ static struct inode *shmem_get_inode(str - spin_lock_init(&info->lock); - info->flags = flags & VM_NORESERVE; - INIT_LIST_HEAD(&info->swaplist); -+ INIT_LIST_HEAD(&info->xattr_list); - cache_no_acl(inode); - - switch (mode & S_IFMT) { -@@ -2014,9 +2028,9 @@ static int shmem_symlink(struct inode *d - - info = SHMEM_I(inode); - inode->i_size = len-1; -- if (len <= (char *)inode - (char *)info) { -+ if (len <= SHMEM_SYMLINK_INLINE_LEN) { - /* do it inline */ -- memcpy(info, symname, len); -+ memcpy(info->inline_symlink, symname, len); - inode->i_op = &shmem_symlink_inline_operations; - } else { - error = shmem_getpage(inode, 0, &page, SGP_WRITE, NULL); -@@ -2042,7 +2056,7 @@ static int shmem_symlink(struct inode *d - - static void *shmem_follow_link_inline(struct dentry *dentry, struct nameidata *nd) - { -- nd_set_link(nd, (char *)SHMEM_I(dentry->d_inode)); -+ nd_set_link(nd, SHMEM_I(dentry->d_inode)->inline_symlink); - return NULL; - } - -@@ -2066,63 +2080,253 @@ static void shmem_put_link(struct dentry - } - } - --static const struct inode_operations shmem_symlink_inline_operations = { -- .readlink = generic_readlink, -- .follow_link = shmem_follow_link_inline, --}; -- --static const struct inode_operations shmem_symlink_inode_operations = { -- .readlink = generic_readlink, -- .follow_link = shmem_follow_link, -- .put_link = shmem_put_link, --}; -- --#ifdef CONFIG_TMPFS_POSIX_ACL -+#ifdef CONFIG_TMPFS_XATTR - /* -- * Superblocks without xattr inode operations will get security.* xattr -- * support from the VFS "for free". As soon as we have any other xattrs -+ * Superblocks without xattr inode operations may get some security.* xattr -+ * support from the LSM "for free". As soon as we have any other xattrs - * like ACLs, we also need to implement the security.* handlers at - * filesystem level, though. - */ - --static size_t shmem_xattr_security_list(struct dentry *dentry, char *list, -- size_t list_len, const char *name, -- size_t name_len, int handler_flags) -+static int shmem_xattr_get(struct dentry *dentry, const char *name, -+ void *buffer, size_t size) - { -- return security_inode_listsecurity(dentry->d_inode, list, list_len); --} -+ struct shmem_inode_info *info; -+ struct shmem_xattr *xattr; -+ int ret = -ENODATA; - --static int shmem_xattr_security_get(struct dentry *dentry, const char *name, -- void *buffer, size_t size, int handler_flags) --{ -- if (strcmp(name, "") == 0) -- return -EINVAL; -- return xattr_getsecurity(dentry->d_inode, name, buffer, size); -+ info = SHMEM_I(dentry->d_inode); -+ -+ spin_lock(&info->lock); -+ list_for_each_entry(xattr, &info->xattr_list, list) { -+ if (strcmp(name, xattr->name)) -+ continue; -+ -+ ret = xattr->size; -+ if (buffer) { -+ if (size < xattr->size) -+ ret = -ERANGE; -+ else -+ memcpy(buffer, xattr->value, xattr->size); -+ } -+ break; -+ } -+ spin_unlock(&info->lock); -+ return ret; - } - --static int shmem_xattr_security_set(struct dentry *dentry, const char *name, -- const void *value, size_t size, int flags, int handler_flags) -+static int shmem_xattr_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->d_inode, name, value, -- size, flags); -+ struct inode *inode = dentry->d_inode; -+ struct shmem_inode_info *info = SHMEM_I(inode); -+ struct shmem_xattr *xattr; -+ struct shmem_xattr *new_xattr = NULL; -+ size_t len; -+ int err = 0; -+ -+ /* value == NULL means remove */ -+ if (value) { -+ /* wrap around? */ -+ len = sizeof(*new_xattr) + size; -+ if (len <= sizeof(*new_xattr)) -+ return -ENOMEM; -+ -+ new_xattr = kmalloc(len, GFP_KERNEL); -+ if (!new_xattr) -+ return -ENOMEM; -+ -+ new_xattr->name = kstrdup(name, GFP_KERNEL); -+ if (!new_xattr->name) { -+ kfree(new_xattr); -+ return -ENOMEM; -+ } -+ -+ new_xattr->size = size; -+ memcpy(new_xattr->value, value, size); -+ } -+ -+ spin_lock(&info->lock); -+ list_for_each_entry(xattr, &info->xattr_list, list) { -+ if (!strcmp(name, xattr->name)) { -+ if (flags & XATTR_CREATE) { -+ xattr = new_xattr; -+ err = -EEXIST; -+ } else if (new_xattr) { -+ list_replace(&xattr->list, &new_xattr->list); -+ } else { -+ list_del(&xattr->list); -+ } -+ goto out; -+ } -+ } -+ if (flags & XATTR_REPLACE) { -+ xattr = new_xattr; -+ err = -ENODATA; -+ } else { -+ list_add(&new_xattr->list, &info->xattr_list); -+ xattr = NULL; -+ } -+out: -+ spin_unlock(&info->lock); -+ if (xattr) -+ kfree(xattr->name); -+ kfree(xattr); -+ return err; - } - --static const struct xattr_handler shmem_xattr_security_handler = { -- .prefix = XATTR_SECURITY_PREFIX, -- .list = shmem_xattr_security_list, -- .get = shmem_xattr_security_get, -- .set = shmem_xattr_security_set, --}; - - static const struct xattr_handler *shmem_xattr_handlers[] = { -+#ifdef CONFIG_TMPFS_POSIX_ACL - &generic_acl_access_handler, - &generic_acl_default_handler, -- &shmem_xattr_security_handler, -+#endif - NULL - }; -+ -+static int shmem_xattr_validate(const char *name) -+{ -+ struct { const char *prefix; size_t len; } arr[] = { -+ { XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN }, -+ { XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN } -+ }; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(arr); i++) { -+ size_t preflen = arr[i].len; -+ if (strncmp(name, arr[i].prefix, preflen) == 0) { -+ if (!name[preflen]) -+ return -EINVAL; -+ return 0; -+ } -+ } -+ return -EOPNOTSUPP; -+} -+ -+static ssize_t shmem_getxattr(struct dentry *dentry, const char *name, -+ void *buffer, size_t size) -+{ -+ int err; -+ -+ /* -+ * If this is a request for a synthetic attribute in the system.* -+ * namespace use the generic infrastructure to resolve a handler -+ * for it via sb->s_xattr. -+ */ -+ if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) -+ return generic_getxattr(dentry, name, buffer, size); -+ -+ err = shmem_xattr_validate(name); -+ if (err) -+ return err; -+ -+ return shmem_xattr_get(dentry, name, buffer, size); -+} -+ -+static int shmem_setxattr(struct dentry *dentry, const char *name, -+ const void *value, size_t size, int flags) -+{ -+ int err; -+ -+ /* -+ * If this is a request for a synthetic attribute in the system.* -+ * namespace use the generic infrastructure to resolve a handler -+ * for it via sb->s_xattr. -+ */ -+ if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) -+ return generic_setxattr(dentry, name, value, size, flags); -+ -+ err = shmem_xattr_validate(name); -+ if (err) -+ return err; -+ -+ if (size == 0) -+ value = ""; /* empty EA, do not remove */ -+ -+ return shmem_xattr_set(dentry, name, value, size, flags); -+ -+} -+ -+static int shmem_removexattr(struct dentry *dentry, const char *name) -+{ -+ int err; -+ -+ /* -+ * If this is a request for a synthetic attribute in the system.* -+ * namespace use the generic infrastructure to resolve a handler -+ * for it via sb->s_xattr. -+ */ -+ if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) -+ return generic_removexattr(dentry, name); -+ -+ err = shmem_xattr_validate(name); -+ if (err) -+ return err; -+ -+ return shmem_xattr_set(dentry, name, NULL, 0, XATTR_REPLACE); -+} -+ -+static bool xattr_is_trusted(const char *name) -+{ -+ return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN); -+} -+ -+static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size) -+{ -+ bool trusted = capable(CAP_SYS_ADMIN); -+ struct shmem_xattr *xattr; -+ struct shmem_inode_info *info; -+ size_t used = 0; -+ -+ info = SHMEM_I(dentry->d_inode); -+ -+ spin_lock(&info->lock); -+ list_for_each_entry(xattr, &info->xattr_list, list) { -+ size_t len; -+ -+ /* skip "trusted." attributes for unprivileged callers */ -+ if (!trusted && xattr_is_trusted(xattr->name)) -+ continue; -+ -+ len = strlen(xattr->name) + 1; -+ used += len; -+ if (buffer) { -+ if (size < used) { -+ used = -ERANGE; -+ break; -+ } -+ memcpy(buffer, xattr->name, len); -+ buffer += len; -+ } -+ } -+ spin_unlock(&info->lock); -+ -+ return used; -+} -+#endif /* CONFIG_TMPFS_XATTR */ -+ -+static const struct inode_operations shmem_symlink_inline_operations = { -+ .readlink = generic_readlink, -+ .follow_link = shmem_follow_link_inline, -+#ifdef CONFIG_TMPFS_XATTR -+ .setxattr = shmem_setxattr, -+ .getxattr = shmem_getxattr, -+ .listxattr = shmem_listxattr, -+ .removexattr = shmem_removexattr, -+#endif -+}; -+ -+static const struct inode_operations shmem_symlink_inode_operations = { -+ .readlink = generic_readlink, -+ .follow_link = shmem_follow_link, -+ .put_link = shmem_put_link, -+#ifdef CONFIG_TMPFS_XATTR -+ .setxattr = shmem_setxattr, -+ .getxattr = shmem_getxattr, -+ .listxattr = shmem_listxattr, -+ .removexattr = shmem_removexattr, - #endif -+}; - - static struct dentry *shmem_get_parent(struct dentry *child) - { -@@ -2402,8 +2606,10 @@ int shmem_fill_super(struct super_block - sb->s_magic = TMPFS_MAGIC; - sb->s_op = &shmem_ops; - sb->s_time_gran = 1; --#ifdef CONFIG_TMPFS_POSIX_ACL -+#ifdef CONFIG_TMPFS_XATTR - sb->s_xattr = shmem_xattr_handlers; -+#endif -+#ifdef CONFIG_TMPFS_POSIX_ACL - sb->s_flags |= MS_POSIXACL; - #endif - -@@ -2501,11 +2707,13 @@ static const struct file_operations shme - static const struct inode_operations shmem_inode_operations = { - .setattr = shmem_notify_change, - .truncate_range = shmem_truncate_range, -+#ifdef CONFIG_TMPFS_XATTR -+ .setxattr = shmem_setxattr, -+ .getxattr = shmem_getxattr, -+ .listxattr = shmem_listxattr, -+ .removexattr = shmem_removexattr, -+#endif - #ifdef CONFIG_TMPFS_POSIX_ACL -- .setxattr = generic_setxattr, -- .getxattr = generic_getxattr, -- .listxattr = generic_listxattr, -- .removexattr = generic_removexattr, - .check_acl = generic_check_acl, - #endif - -@@ -2523,23 +2731,27 @@ static const struct inode_operations shm - .mknod = shmem_mknod, - .rename = shmem_rename, - #endif -+#ifdef CONFIG_TMPFS_XATTR -+ .setxattr = shmem_setxattr, -+ .getxattr = shmem_getxattr, -+ .listxattr = shmem_listxattr, -+ .removexattr = shmem_removexattr, -+#endif - #ifdef CONFIG_TMPFS_POSIX_ACL - .setattr = shmem_notify_change, -- .setxattr = generic_setxattr, -- .getxattr = generic_getxattr, -- .listxattr = generic_listxattr, -- .removexattr = generic_removexattr, - .check_acl = generic_check_acl, - #endif - }; - - static const struct inode_operations shmem_special_inode_operations = { -+#ifdef CONFIG_TMPFS_XATTR -+ .setxattr = shmem_setxattr, -+ .getxattr = shmem_getxattr, -+ .listxattr = shmem_listxattr, -+ .removexattr = shmem_removexattr, -+#endif - #ifdef CONFIG_TMPFS_POSIX_ACL - .setattr = shmem_notify_change, -- .setxattr = generic_setxattr, -- .getxattr = generic_getxattr, -- .listxattr = generic_listxattr, -- .removexattr = generic_removexattr, - .check_acl = generic_check_acl, - #endif - }; |