Not having xattr in /tmp can be worked around usually by configuring the affected software with TMPDIR=/var/tmp and the like, but I prefer having this automated, if possible. Signed-off-by: Pete Zaitcev <zaitcev@xxxxxxxxx> --- fs/xattr.c | 3 +++ include/linux/xattr.h | 13 +++++++++++++ mm/shmem.c | 25 +++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/fs/xattr.c b/fs/xattr.c index 90dd78f0eb27..502567a4a478 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -896,6 +896,7 @@ int simple_xattr_set(struct simple_xattrs *xattrs, const char *name, } else if (new_xattr) { list_replace(&xattr->list, &new_xattr->list); } else { + --xattrs->count; list_del(&xattr->list); } goto out; @@ -906,6 +907,7 @@ int simple_xattr_set(struct simple_xattrs *xattrs, const char *name, err = -ENODATA; } else { list_add(&new_xattr->list, &xattrs->head); + xattrs->count++; xattr = NULL; } out: @@ -988,5 +990,6 @@ void simple_xattr_list_add(struct simple_xattrs *xattrs, { spin_lock(&xattrs->lock); list_add(&new_xattr->list, &xattrs->head); + xattrs->count++; spin_unlock(&xattrs->lock); } diff --git a/include/linux/xattr.h b/include/linux/xattr.h index 6dad031be3c2..e1ed5910ef5c 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -67,6 +67,7 @@ static inline const char *xattr_prefix(const struct xattr_handler *handler) struct simple_xattrs { struct list_head head; spinlock_t lock; + int count; }; struct simple_xattr { @@ -83,6 +84,7 @@ static inline void simple_xattrs_init(struct simple_xattrs *xattrs) { INIT_LIST_HEAD(&xattrs->head); spin_lock_init(&xattrs->lock); + xattrs->count = 0; } /* @@ -96,6 +98,17 @@ static inline void simple_xattrs_free(struct simple_xattrs *xattrs) kfree(xattr->name); kfree(xattr); } + xattrs->count = 0; +} + +static inline int simple_xattrs_count(struct simple_xattrs *xattrs) +{ + int ret; + + spin_lock(&xattrs->lock); + ret = xattrs->count; + spin_unlock(&xattrs->lock); + return ret; } struct simple_xattr *simple_xattr_alloc(const void *value, size_t size); diff --git a/mm/shmem.c b/mm/shmem.c index c8f7540ef048..0ce17afad30e 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -3246,6 +3246,30 @@ static int shmem_xattr_handler_set(const struct xattr_handler *handler, return simple_xattr_set(&info->xattrs, name, value, size, flags); } +static int shmem_xattr_handler_set_user(const struct xattr_handler *handler, + struct dentry *unused, struct inode *inode, + const char *name, const void *value, + size_t size, int flags) +{ + struct shmem_inode_info *info = SHMEM_I(inode); + struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb); + + if (value) { + if (size > 8192) + return -EINVAL; + if (simple_xattrs_count(&info->xattrs) >= sbinfo->max_inodes) + return -ENOSPC; + } + name = xattr_full_name(handler, name); + return simple_xattr_set(&info->xattrs, name, value, size, flags); +} + +static const struct xattr_handler shmem_user_xattr_handler = { + .prefix = XATTR_USER_PREFIX, + .get = shmem_xattr_handler_get, + .set = shmem_xattr_handler_set_user, +}; + static const struct xattr_handler shmem_security_xattr_handler = { .prefix = XATTR_SECURITY_PREFIX, .get = shmem_xattr_handler_get, @@ -3263,6 +3287,7 @@ static const struct xattr_handler *shmem_xattr_handlers[] = { &posix_acl_access_xattr_handler, &posix_acl_default_xattr_handler, #endif + &shmem_user_xattr_handler, &shmem_security_xattr_handler, &shmem_trusted_xattr_handler, NULL