Re: [patch] fs: Allow user.* xattr in tmpfs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 17 Feb 2020, Pete Zaitcev wrote:

> 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>

Thanks for looking into this - and thanks to Helge for reminding
that we discussed it before in private mail, 13 September 2018 most
recently (when I falsely implied that I might get around to doing it:
sorry, I have not).

Below looks like a bit of a misunderstanding of what I intended there.
Yes, I still think that accounting xattr memory consumption from the
space already (usually) limited by max_inodes is the best way forward
to enabling user xattrs on tmpfs, while limiting the damage they can do.

But, perhaps I'm misreading, here it looks as if you're allowing
max_inodes xattrs of size 8k on each inode?

No, I meant that we expect a memory size of, very approximately, 1k for
each inode+dentry, so max_inodes*1k is a limited pool of memory, from
which we currently count just the inodes, but could reasonably count
xattr memory too - but will need to extend to byte-counting for that. 

Hugh

> ---
>  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
> 




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux