[PATCH v8] Add flags option to get xattr method paired to __vfs_getxattr

Darrick J. Wong darrick.wong at oracle.com
Wed Aug 28 07:35:43 AEST 2019


On Tue, Aug 27, 2019 at 08:05:15AM -0700, Mark Salyzyn wrote:
> Replace arguments for get and set xattr methods, and __vfs_getxattr
> and __vfs_setaxtr functions with a reference to the following now
> common argument structure:
> 
> struct xattr_gs_args {
> 	struct dentry *dentry;
> 	struct inode *inode;
> 	const char *name;
> 	union {
> 		void *buffer;
> 		const void *value;
> 	};
> 	size_t size;
> 	int flags;
> };
> 
> Which in effect adds a flags option to the get method and
> __vfs_getxattr function.
> 
> Add a flag option to get xattr method that has bit flag of
> XATTR_NOSECURITY passed to it.  XATTR_NOSECURITY is generally then
> set in the __vfs_getxattr path when called by security
> infrastructure.
> 
> This handles the case of a union filesystem driver that is being
> requested by the security layer to report back the xattr data.
> 
> For the use case where access is to be blocked by the security layer.
> 
> The path then could be security(dentry) ->
> __vfs_getxattr({dentry...XATTR_NOSECURITY}) ->
> handler->get({dentry...XATTR_NOSECURITY}) ->
> __vfs_getxattr({lower_dentry...XATTR_NOSECURITY}) ->
> lower_handler->get({lower_dentry...XATTR_NOSECURITY})
> which would report back through the chain data and success as
> expected, the logging security layer at the top would have the
> data to determine the access permissions and report back the target
> context that was blocked.
> 
> Without the get handler flag, the path on a union filesystem would be
> the errant security(dentry) -> __vfs_getxattr(dentry) ->
> handler->get(dentry) -> vfs_getxattr(lower_dentry) -> nested ->
> security(lower_dentry, log off) -> lower_handler->get(lower_dentry)
> which would report back through the chain no data, and -EACCES.
> 
> For selinux for both cases, this would translate to a correctly
> determined blocked access. In the first case with this change a correct avc
> log would be reported, in the second legacy case an incorrect avc log
> would be reported against an uninitialized u:object_r:unlabeled:s0
> context making the logs cosmetically useless for audit2allow.
> 
> This patch series is inert and is the wide-spread addition of the
> flags option for xattr functions, and a replacement of __vfs_getxattr
> with __vfs_getxattr({...XATTR_NOSECURITY}).
> 
> Signed-off-by: Mark Salyzyn <salyzyn at android.com>
> Reviewed-by: Jan Kara <jack at suse.cz>
> Cc: Stephen Smalley <sds at tycho.nsa.gov>
> Cc: linux-kernel at vger.kernel.org
> Cc: kernel-team at android.com
> Cc: linux-security-module at vger.kernel.org
> Cc: stable at vger.kernel.org # 4.4, 4.9, 4.14 & 4.19

For the XFS part,
Acked-by: Darrick J. Wong <darrick.wong at oracle.com>

> ---
> v8:
> - Documentation reported 'struct xattr_gs_flags' rather than
>   'struct xattr_gs_flags *args' as argument to get and set methods.
> 
> v7:
> - missed spots in fs/9p/acl.c, fs/afs/xattr.c, fs/ecryptfs/crypto.c,
>   fs/ubifs/xattr.c, fs/xfs/libxfs/xfs_attr.c,
>   security/integrity/evm/evm_main.c and security/smack/smack_lsm.c.
> 
> v6:
> - kernfs missed a spot
> 
> v5:
> - introduce struct xattr_gs_args for get and set methods,
>   __vfs_getxattr and __vfs_setxattr functions.
> - cover a missing spot in ext2.
> - switch from snprintf to scnprintf for correctness.
> 
> v4:
> - ifdef __KERNEL__ around XATTR_NOSECURITY to
>   keep it colocated in uapi headers.
> 
> v3:
> - poor aim on ubifs not ubifs_xattr_get, but static xattr_get
> 
> v2:
> - Missed a spot: ubifs, erofs and afs.
> 
> v1:
> - Removed from an overlayfs patch set, and made independent.
>   Expect this to be the basis of some security improvements.
> ---
>  Documentation/filesystems/Locking |  10 ++-
>  drivers/staging/erofs/xattr.c     |   8 +--
>  fs/9p/acl.c                       |  51 +++++++-------
>  fs/9p/xattr.c                     |  19 +++--
>  fs/afs/xattr.c                    | 112 +++++++++++++-----------------
>  fs/btrfs/xattr.c                  |  36 +++++-----
>  fs/ceph/xattr.c                   |  40 +++++------
>  fs/cifs/xattr.c                   |  72 +++++++++----------
>  fs/ecryptfs/crypto.c              |  20 +++---
>  fs/ecryptfs/inode.c               |  36 ++++++----
>  fs/ecryptfs/mmap.c                |  39 ++++++-----
>  fs/ext2/xattr_security.c          |  16 ++---
>  fs/ext2/xattr_trusted.c           |  15 ++--
>  fs/ext2/xattr_user.c              |  19 +++--
>  fs/ext4/xattr_security.c          |  15 ++--
>  fs/ext4/xattr_trusted.c           |  15 ++--
>  fs/ext4/xattr_user.c              |  19 +++--
>  fs/f2fs/xattr.c                   |  42 +++++------
>  fs/fuse/xattr.c                   |  23 +++---
>  fs/gfs2/xattr.c                   |  18 ++---
>  fs/hfs/attr.c                     |  15 ++--
>  fs/hfsplus/xattr.c                |  17 +++--
>  fs/hfsplus/xattr_security.c       |  13 ++--
>  fs/hfsplus/xattr_trusted.c        |  13 ++--
>  fs/hfsplus/xattr_user.c           |  13 ++--
>  fs/jffs2/security.c               |  16 ++---
>  fs/jffs2/xattr_trusted.c          |  16 ++---
>  fs/jffs2/xattr_user.c             |  16 ++---
>  fs/jfs/xattr.c                    |  33 ++++-----
>  fs/kernfs/inode.c                 |  23 +++---
>  fs/nfs/nfs4proc.c                 |  28 ++++----
>  fs/ocfs2/xattr.c                  |  52 ++++++--------
>  fs/orangefs/xattr.c               |  19 ++---
>  fs/overlayfs/inode.c              |  43 ++++++------
>  fs/overlayfs/overlayfs.h          |   6 +-
>  fs/overlayfs/super.c              |  53 ++++++--------
>  fs/posix_acl.c                    |  23 +++---
>  fs/reiserfs/xattr.c               |   2 +-
>  fs/reiserfs/xattr_security.c      |  22 +++---
>  fs/reiserfs/xattr_trusted.c       |  22 +++---
>  fs/reiserfs/xattr_user.c          |  22 +++---
>  fs/squashfs/xattr.c               |  10 +--
>  fs/ubifs/xattr.c                  |  33 +++++----
>  fs/xattr.c                        | 112 ++++++++++++++++++------------
>  fs/xfs/libxfs/xfs_attr.c          |   4 +-
>  fs/xfs/libxfs/xfs_attr.h          |   2 +-
>  fs/xfs/xfs_xattr.c                |  35 +++++-----
>  include/linux/xattr.h             |  26 ++++---
>  include/uapi/linux/xattr.h        |   7 +-
>  mm/shmem.c                        |  21 +++---
>  net/socket.c                      |  16 ++---
>  security/commoncap.c              |  29 +++++---
>  security/integrity/evm/evm_main.c |  13 +++-
>  security/selinux/hooks.c          |  28 ++++++--
>  security/smack/smack_lsm.c        |  38 ++++++----
>  55 files changed, 732 insertions(+), 734 deletions(-)
> 
> diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
> index 204dd3ea36bb..c16752a41959 100644
> --- a/Documentation/filesystems/Locking
> +++ b/Documentation/filesystems/Locking
> @@ -101,12 +101,10 @@ of the locking scheme for directory operations.
>  ----------------------- xattr_handler operations -----------------------
>  prototypes:
>  	bool (*list)(struct dentry *dentry);
> -	int (*get)(const struct xattr_handler *handler, struct dentry *dentry,
> -		   struct inode *inode, const char *name, void *buffer,
> -		   size_t size);
> -	int (*set)(const struct xattr_handler *handler, struct dentry *dentry,
> -		   struct inode *inode, const char *name, const void *buffer,
> -		   size_t size, int flags);
> +	int (*get)(const struct xattr_handler *handler,
> +		   struct xattr_gs_flags *args);
> +	int (*set)(const struct xattr_handler *handler,
> +		   struct xattr_gs_flags *args);
>  
>  locking rules:
>  	all may block
> diff --git a/drivers/staging/erofs/xattr.c b/drivers/staging/erofs/xattr.c
> index df40654b9fbb..41dcfc82f0b2 100644
> --- a/drivers/staging/erofs/xattr.c
> +++ b/drivers/staging/erofs/xattr.c
> @@ -462,10 +462,9 @@ int erofs_getxattr(struct inode *inode, int index,
>  }
>  
>  static int erofs_xattr_generic_get(const struct xattr_handler *handler,
> -				   struct dentry *unused, struct inode *inode,
> -				   const char *name, void *buffer, size_t size)
> +				   struct xattr_gs_args *args)
>  {
> -	struct erofs_sb_info *const sbi = EROFS_I_SB(inode);
> +	struct erofs_sb_info *const sbi = EROFS_I_SB(args->inode);
>  
>  	switch (handler->flags) {
>  	case EROFS_XATTR_INDEX_USER:
> @@ -482,7 +481,8 @@ static int erofs_xattr_generic_get(const struct xattr_handler *handler,
>  		return -EINVAL;
>  	}
>  
> -	return erofs_getxattr(inode, handler->flags, name, buffer, size);
> +	return erofs_getxattr(args->inode, handler->flags, args->name,
> +			      args->buffer, args->size);
>  }
>  
>  const struct xattr_handler erofs_xattr_user_handler = {
> diff --git a/fs/9p/acl.c b/fs/9p/acl.c
> index 6261719f6f2a..2f5184de75c4 100644
> --- a/fs/9p/acl.c
> +++ b/fs/9p/acl.c
> @@ -213,60 +213,61 @@ int v9fs_acl_mode(struct inode *dir, umode_t *modep,
>  }
>  
>  static int v9fs_xattr_get_acl(const struct xattr_handler *handler,
> -			      struct dentry *dentry, struct inode *inode,
> -			      const char *name, void *buffer, size_t size)
> +			      struct xattr_gs_args *args)
>  {
>  	struct v9fs_session_info *v9ses;
>  	struct posix_acl *acl;
>  	int error;
>  
> -	v9ses = v9fs_dentry2v9ses(dentry);
> +	v9ses = v9fs_dentry2v9ses(args->dentry);
>  	/*
>  	 * We allow set/get/list of acl when access=client is not specified
>  	 */
>  	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
> -		return v9fs_xattr_get(dentry, handler->name, buffer, size);
> +		return v9fs_xattr_get(args->dentry, handler->name,
> +				      args->buffer, args->size);
>  
> -	acl = v9fs_get_cached_acl(inode, handler->flags);
> +	acl = v9fs_get_cached_acl(args->inode, handler->flags);
>  	if (IS_ERR(acl))
>  		return PTR_ERR(acl);
>  	if (acl == NULL)
>  		return -ENODATA;
> -	error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
> +	error = posix_acl_to_xattr(&init_user_ns, acl,
> +				   args->buffer, args->size);
>  	posix_acl_release(acl);
>  
>  	return error;
>  }
>  
>  static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
> -			      struct dentry *dentry, struct inode *inode,
> -			      const char *name, const void *value,
> -			      size_t size, int flags)
> +			      struct xattr_gs_args *args)
>  {
>  	int retval;
>  	struct posix_acl *acl;
>  	struct v9fs_session_info *v9ses;
>  
> -	v9ses = v9fs_dentry2v9ses(dentry);
> +	v9ses = v9fs_dentry2v9ses(args->dentry);
>  	/*
>  	 * set the attribute on the remote. Without even looking at the
>  	 * xattr value. We leave it to the server to validate
>  	 */
>  	if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT)
> -		return v9fs_xattr_set(dentry, handler->name, value, size,
> -				      flags);
> +		return v9fs_xattr_set(args->dentry, handler->name,
> +				      args->value, args->size, args->flags);
>  
> -	if (S_ISLNK(inode->i_mode))
> +	if (S_ISLNK(args->inode->i_mode))
>  		return -EOPNOTSUPP;
> -	if (!inode_owner_or_capable(inode))
> +	if (!inode_owner_or_capable(args->inode))
>  		return -EPERM;
> -	if (value) {
> +	if (args->value) {
>  		/* update the cached acl value */
> -		acl = posix_acl_from_xattr(&init_user_ns, value, size);
> +		acl = posix_acl_from_xattr(&init_user_ns,
> +					   args->value, args->size);
>  		if (IS_ERR(acl))
>  			return PTR_ERR(acl);
>  		else if (acl) {
> -			retval = posix_acl_valid(inode->i_sb->s_user_ns, acl);
> +			retval = posix_acl_valid(args->inode->i_sb->s_user_ns,
> +						 acl);
>  			if (retval)
>  				goto err_out;
>  		}
> @@ -279,7 +280,8 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
>  			struct iattr iattr = { 0 };
>  			struct posix_acl *old_acl = acl;
>  
> -			retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl);
> +			retval = posix_acl_update_mode(args->inode,
> +						       &iattr.ia_mode, &acl);
>  			if (retval)
>  				goto err_out;
>  			if (!acl) {
> @@ -289,19 +291,19 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
>  				 * update ACL.
>  				 */
>  				posix_acl_release(old_acl);
> -				value = NULL;
> -				size = 0;
> +				args->value = NULL;
> +				args->size = 0;
>  			}
>  			iattr.ia_valid = ATTR_MODE;
>  			/* FIXME should we update ctime ?
>  			 * What is the following setxattr update the
>  			 * mode ?
>  			 */
> -			v9fs_vfs_setattr_dotl(dentry, &iattr);
> +			v9fs_vfs_setattr_dotl(args->dentry, &iattr);
>  		}
>  		break;
>  	case ACL_TYPE_DEFAULT:
> -		if (!S_ISDIR(inode->i_mode)) {
> +		if (!S_ISDIR(args->inode->i_mode)) {
>  			retval = acl ? -EINVAL : 0;
>  			goto err_out;
>  		}
> @@ -309,9 +311,10 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler,
>  	default:
>  		BUG();
>  	}
> -	retval = v9fs_xattr_set(dentry, handler->name, value, size, flags);
> +	retval = v9fs_xattr_set(args->dentry, handler->name,
> +				args->value, args->size, args->flags);
>  	if (!retval)
> -		set_cached_acl(inode, handler->flags, acl);
> +		set_cached_acl(args->inode, handler->flags, acl);
>  err_out:
>  	posix_acl_release(acl);
>  	return retval;
> diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c
> index ac8ff8ca4c11..36d4c309be08 100644
> --- a/fs/9p/xattr.c
> +++ b/fs/9p/xattr.c
> @@ -138,22 +138,19 @@ ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
>  }
>  
>  static int v9fs_xattr_handler_get(const struct xattr_handler *handler,
> -				  struct dentry *dentry, struct inode *inode,
> -				  const char *name, void *buffer, size_t size)
> +				  struct xattr_gs_args *args)
>  {
> -	const char *full_name = xattr_full_name(handler, name);
> -
> -	return v9fs_xattr_get(dentry, full_name, buffer, size);
> +	return v9fs_xattr_get(args->dentry,
> +			      xattr_full_name(handler, args->name),
> +			      args->buffer, args->size);
>  }
>  
>  static int v9fs_xattr_handler_set(const struct xattr_handler *handler,
> -				  struct dentry *dentry, struct inode *inode,
> -				  const char *name, const void *value,
> -				  size_t size, int flags)
> +				  struct xattr_gs_args *args)
>  {
> -	const char *full_name = xattr_full_name(handler, name);
> -
> -	return v9fs_xattr_set(dentry, full_name, value, size, flags);
> +	return v9fs_xattr_set(args->dentry,
> +			      xattr_full_name(handler, args->name),
> +			      args->value, args->size, args->flags);
>  }
>  
>  static struct xattr_handler v9fs_xattr_user_handler = {
> diff --git a/fs/afs/xattr.c b/fs/afs/xattr.c
> index 5552d034090a..787ae107642d 100644
> --- a/fs/afs/xattr.c
> +++ b/fs/afs/xattr.c
> @@ -38,13 +38,11 @@ ssize_t afs_listxattr(struct dentry *dentry, char *buffer, size_t size)
>   * Get a file's ACL.
>   */
>  static int afs_xattr_get_acl(const struct xattr_handler *handler,
> -			     struct dentry *dentry,
> -			     struct inode *inode, const char *name,
> -			     void *buffer, size_t size)
> +			     struct xattr_gs_args *args)
>  {
>  	struct afs_fs_cursor fc;
>  	struct afs_status_cb *scb;
> -	struct afs_vnode *vnode = AFS_FS_I(inode);
> +	struct afs_vnode *vnode = AFS_FS_I(args->inode);
>  	struct afs_acl *acl = NULL;
>  	struct key *key;
>  	int ret = -ENOMEM;
> @@ -76,9 +74,9 @@ static int afs_xattr_get_acl(const struct xattr_handler *handler,
>  
>  	if (ret == 0) {
>  		ret = acl->size;
> -		if (size > 0) {
> -			if (acl->size <= size)
> -				memcpy(buffer, acl->data, acl->size);
> +		if (args->size > 0) {
> +			if (acl->size <= args->size)
> +				memcpy(args->buffer, acl->data, acl->size);
>  			else
>  				ret = -ERANGE;
>  		}
> @@ -96,25 +94,23 @@ static int afs_xattr_get_acl(const struct xattr_handler *handler,
>   * Set a file's AFS3 ACL.
>   */
>  static int afs_xattr_set_acl(const struct xattr_handler *handler,
> -                             struct dentry *dentry,
> -                             struct inode *inode, const char *name,
> -                             const void *buffer, size_t size, int flags)
> +			     struct xattr_gs_args *args)
>  {
>  	struct afs_fs_cursor fc;
>  	struct afs_status_cb *scb;
> -	struct afs_vnode *vnode = AFS_FS_I(inode);
> +	struct afs_vnode *vnode = AFS_FS_I(args->inode);
>  	struct afs_acl *acl = NULL;
>  	struct key *key;
>  	int ret = -ENOMEM;
>  
> -	if (flags == XATTR_CREATE)
> +	if (args->flags == XATTR_CREATE)
>  		return -EINVAL;
>  
>  	scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
>  	if (!scb)
>  		goto error;
>  
> -	acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
> +	acl = kmalloc(sizeof(*acl) + args->size, GFP_KERNEL);
>  	if (!acl)
>  		goto error_scb;
>  
> @@ -124,8 +120,8 @@ static int afs_xattr_set_acl(const struct xattr_handler *handler,
>  		goto error_acl;
>  	}
>  
> -	acl->size = size;
> -	memcpy(acl->data, buffer, size);
> +	acl->size = args->size;
> +	memcpy(acl->data, args->value, args->size);
>  
>  	ret = -ERESTARTSYS;
>  	if (afs_begin_vnode_operation(&fc, vnode, key, true)) {
> @@ -161,25 +157,23 @@ static const struct xattr_handler afs_xattr_afs_acl_handler = {
>   * Get a file's YFS ACL.
>   */
>  static int afs_xattr_get_yfs(const struct xattr_handler *handler,
> -			     struct dentry *dentry,
> -			     struct inode *inode, const char *name,
> -			     void *buffer, size_t size)
> +			     struct xattr_gs_args *args)
>  {
>  	struct afs_fs_cursor fc;
>  	struct afs_status_cb *scb;
> -	struct afs_vnode *vnode = AFS_FS_I(inode);
> +	struct afs_vnode *vnode = AFS_FS_I(args->inode);
>  	struct yfs_acl *yacl = NULL;
>  	struct key *key;
>  	char buf[16], *data;
>  	int which = 0, dsize, ret = -ENOMEM;
>  
> -	if (strcmp(name, "acl") == 0)
> +	if (strcmp(args->name, "acl") == 0)
>  		which = 0;
> -	else if (strcmp(name, "acl_inherited") == 0)
> +	else if (strcmp(args->name, "acl_inherited") == 0)
>  		which = 1;
> -	else if (strcmp(name, "acl_num_cleaned") == 0)
> +	else if (strcmp(args->name, "acl_num_cleaned") == 0)
>  		which = 2;
> -	else if (strcmp(name, "vol_acl") == 0)
> +	else if (strcmp(args->name, "vol_acl") == 0)
>  		which = 3;
>  	else
>  		return -EOPNOTSUPP;
> @@ -228,11 +222,11 @@ static int afs_xattr_get_yfs(const struct xattr_handler *handler,
>  		break;
>  	case 1:
>  		data = buf;
> -		dsize = snprintf(buf, sizeof(buf), "%u", yacl->inherit_flag);
> +		dsize = scnprintf(buf, sizeof(buf), "%u", yacl->inherit_flag);
>  		break;
>  	case 2:
>  		data = buf;
> -		dsize = snprintf(buf, sizeof(buf), "%u", yacl->num_cleaned);
> +		dsize = scnprintf(buf, sizeof(buf), "%u", yacl->num_cleaned);
>  		break;
>  	case 3:
>  		data = yacl->vol_acl->data;
> @@ -244,12 +238,12 @@ static int afs_xattr_get_yfs(const struct xattr_handler *handler,
>  	}
>  
>  	ret = dsize;
> -	if (size > 0) {
> -		if (dsize > size) {
> +	if (args->size > 0) {
> +		if (dsize > args->size) {
>  			ret = -ERANGE;
>  			goto error_key;
>  		}
> -		memcpy(buffer, data, dsize);
> +		memcpy(args->buffer, data, dsize);
>  	}
>  
>  error_key:
> @@ -266,31 +260,29 @@ static int afs_xattr_get_yfs(const struct xattr_handler *handler,
>   * Set a file's YFS ACL.
>   */
>  static int afs_xattr_set_yfs(const struct xattr_handler *handler,
> -                             struct dentry *dentry,
> -                             struct inode *inode, const char *name,
> -                             const void *buffer, size_t size, int flags)
> +			     struct xattr_gs_args *args)
>  {
>  	struct afs_fs_cursor fc;
>  	struct afs_status_cb *scb;
> -	struct afs_vnode *vnode = AFS_FS_I(inode);
> +	struct afs_vnode *vnode = AFS_FS_I(args->inode);
>  	struct afs_acl *acl = NULL;
>  	struct key *key;
>  	int ret = -ENOMEM;
>  
> -	if (flags == XATTR_CREATE ||
> -	    strcmp(name, "acl") != 0)
> +	if (args->flags == XATTR_CREATE ||
> +	    strcmp(args->name, "acl") != 0)
>  		return -EINVAL;
>  
>  	scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS);
>  	if (!scb)
>  		goto error;
>  
> -	acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL);
> +	acl = kmalloc(sizeof(*acl) + args->size, GFP_KERNEL);
>  	if (!acl)
>  		goto error_scb;
>  
> -	acl->size = size;
> -	memcpy(acl->data, buffer, size);
> +	acl->size = args->size;
> +	memcpy(acl->data, args->value, args->size);
>  
>  	key = afs_request_key(vnode->volume->cell);
>  	if (IS_ERR(key)) {
> @@ -332,20 +324,18 @@ static const struct xattr_handler afs_xattr_yfs_handler = {
>   * Get the name of the cell on which a file resides.
>   */
>  static int afs_xattr_get_cell(const struct xattr_handler *handler,
> -			      struct dentry *dentry,
> -			      struct inode *inode, const char *name,
> -			      void *buffer, size_t size)
> +			      struct xattr_gs_args *args)
>  {
> -	struct afs_vnode *vnode = AFS_FS_I(inode);
> +	struct afs_vnode *vnode = AFS_FS_I(args->inode);
>  	struct afs_cell *cell = vnode->volume->cell;
>  	size_t namelen;
>  
>  	namelen = cell->name_len;
> -	if (size == 0)
> +	if (args->size == 0)
>  		return namelen;
> -	if (namelen > size)
> +	if (namelen > args->size)
>  		return -ERANGE;
> -	memcpy(buffer, cell->name, namelen);
> +	memcpy(args->buffer, cell->name, namelen);
>  	return namelen;
>  }
>  
> @@ -359,30 +349,30 @@ static const struct xattr_handler afs_xattr_afs_cell_handler = {
>   * hex numbers separated by colons.
>   */
>  static int afs_xattr_get_fid(const struct xattr_handler *handler,
> -			     struct dentry *dentry,
> -			     struct inode *inode, const char *name,
> -			     void *buffer, size_t size)
> +			     struct xattr_gs_args *args)
>  {
> -	struct afs_vnode *vnode = AFS_FS_I(inode);
> +	struct afs_vnode *vnode = AFS_FS_I(args->inode);
>  	char text[16 + 1 + 24 + 1 + 8 + 1];
>  	size_t len;
>  
>  	/* The volume ID is 64-bit, the vnode ID is 96-bit and the
>  	 * uniquifier is 32-bit.
>  	 */
> -	len = sprintf(text, "%llx:", vnode->fid.vid);
> +	len = scnprintf(text, sizeof(text), "%llx:", vnode->fid.vid);
>  	if (vnode->fid.vnode_hi)
> -		len += sprintf(text + len, "%x%016llx",
> +		len += scnprintf(text + len, sizeof(text) - len, "%x%016llx",
>  			       vnode->fid.vnode_hi, vnode->fid.vnode);
>  	else
> -		len += sprintf(text + len, "%llx", vnode->fid.vnode);
> -	len += sprintf(text + len, ":%x", vnode->fid.unique);
> +		len += scnprintf(text + len, sizeof(text) - len, "%llx",
> +				 vnode->fid.vnode);
> +	len += scnprintf(text + len, sizeof(text) - len, ":%x",
> +			 vnode->fid.unique);
>  
> -	if (size == 0)
> +	if (args->size == 0)
>  		return len;
> -	if (len > size)
> +	if (len > args->size)
>  		return -ERANGE;
> -	memcpy(buffer, text, len);
> +	memcpy(args->buffer, text, len);
>  	return len;
>  }
>  
> @@ -395,20 +385,18 @@ static const struct xattr_handler afs_xattr_afs_fid_handler = {
>   * Get the name of the volume on which a file resides.
>   */
>  static int afs_xattr_get_volume(const struct xattr_handler *handler,
> -			      struct dentry *dentry,
> -			      struct inode *inode, const char *name,
> -			      void *buffer, size_t size)
> +			      struct xattr_gs_args *args)
>  {
> -	struct afs_vnode *vnode = AFS_FS_I(inode);
> +	struct afs_vnode *vnode = AFS_FS_I(args->inode);
>  	const char *volname = vnode->volume->name;
>  	size_t namelen;
>  
>  	namelen = strlen(volname);
> -	if (size == 0)
> +	if (args->size == 0)
>  		return namelen;
> -	if (namelen > size)
> +	if (namelen > args->size)
>  		return -ERANGE;
> -	memcpy(buffer, volname, namelen);
> +	memcpy(args->buffer, volname, namelen);
>  	return namelen;
>  }
>  
> diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
> index 95d9aebff2c4..e47a0e461bd2 100644
> --- a/fs/btrfs/xattr.c
> +++ b/fs/btrfs/xattr.c
> @@ -352,33 +352,30 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
>  }
>  
>  static int btrfs_xattr_handler_get(const struct xattr_handler *handler,
> -				   struct dentry *unused, struct inode *inode,
> -				   const char *name, void *buffer, size_t size)
> +				   struct xattr_gs_args *args)
>  {
> -	name = xattr_full_name(handler, name);
> -	return btrfs_getxattr(inode, name, buffer, size);
> +	return btrfs_getxattr(args->inode,
> +			      xattr_full_name(handler, args->name),
> +			      args->buffer, args->size);
>  }
>  
>  static int btrfs_xattr_handler_set(const struct xattr_handler *handler,
> -				   struct dentry *unused, struct inode *inode,
> -				   const char *name, const void *buffer,
> -				   size_t size, int flags)
> +				   struct xattr_gs_args *args)
>  {
> -	name = xattr_full_name(handler, name);
> -	return btrfs_setxattr_trans(inode, name, buffer, size, flags);
> +	return btrfs_setxattr_trans(args->inode,
> +				    xattr_full_name(handler, args->name),
> +				    args->value, args->size, args->flags);
>  }
>  
>  static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
> -					struct dentry *unused, struct inode *inode,
> -					const char *name, const void *value,
> -					size_t size, int flags)
> +					struct xattr_gs_args *args)
>  {
>  	int ret;
>  	struct btrfs_trans_handle *trans;
> -	struct btrfs_root *root = BTRFS_I(inode)->root;
> +	struct btrfs_root *root = BTRFS_I(args->inode)->root;
>  
> -	name = xattr_full_name(handler, name);
> -	ret = btrfs_validate_prop(name, value, size);
> +	ret = btrfs_validate_prop(xattr_full_name(handler, args->name),
> +				  args->value, args->size);
>  	if (ret)
>  		return ret;
>  
> @@ -386,11 +383,12 @@ static int btrfs_xattr_handler_set_prop(const struct xattr_handler *handler,
>  	if (IS_ERR(trans))
>  		return PTR_ERR(trans);
>  
> -	ret = btrfs_set_prop(trans, inode, name, value, size, flags);
> +	ret = btrfs_set_prop(trans, args->inode, args->name,
> +			     args->value, args->size, args->flags);
>  	if (!ret) {
> -		inode_inc_iversion(inode);
> -		inode->i_ctime = current_time(inode);
> -		ret = btrfs_update_inode(trans, root, inode);
> +		inode_inc_iversion(args->inode);
> +		args->inode->i_ctime = current_time(args->inode);
> +		ret = btrfs_update_inode(trans, root, args->inode);
>  		BUG_ON(ret);
>  	}
>  
> diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
> index 939eab7aa219..c4fee624291b 100644
> --- a/fs/ceph/xattr.c
> +++ b/fs/ceph/xattr.c
> @@ -1179,22 +1179,21 @@ int __ceph_setxattr(struct inode *inode, const char *name,
>  }
>  
>  static int ceph_get_xattr_handler(const struct xattr_handler *handler,
> -				  struct dentry *dentry, struct inode *inode,
> -				  const char *name, void *value, size_t size)
> +				  struct xattr_gs_args *args)
>  {
> -	if (!ceph_is_valid_xattr(name))
> +	if (!ceph_is_valid_xattr(args->name))
>  		return -EOPNOTSUPP;
> -	return __ceph_getxattr(inode, name, value, size);
> +	return __ceph_getxattr(args->inode, args->name,
> +			       args->buffer, args->size);
>  }
>  
>  static int ceph_set_xattr_handler(const struct xattr_handler *handler,
> -				  struct dentry *unused, struct inode *inode,
> -				  const char *name, const void *value,
> -				  size_t size, int flags)
> +				  struct xattr_gs_args *args)
>  {
> -	if (!ceph_is_valid_xattr(name))
> +	if (!ceph_is_valid_xattr(args->name))
>  		return -EOPNOTSUPP;
> -	return __ceph_setxattr(inode, name, value, size, flags);
> +	return __ceph_setxattr(args->inode, args->name,
> +			       args->value, args->size, args->flags);
>  }
>  
>  static const struct xattr_handler ceph_other_xattr_handler = {
> @@ -1300,25 +1299,22 @@ void ceph_security_invalidate_secctx(struct inode *inode)
>  }
>  
>  static int ceph_xattr_set_security_label(const struct xattr_handler *handler,
> -				    struct dentry *unused, struct inode *inode,
> -				    const char *key, const void *buf,
> -				    size_t buflen, int flags)
> +					 struct xattr_gs_args *args)
>  {
> -	if (security_ismaclabel(key)) {
> -		const char *name = xattr_full_name(handler, key);
> -		return __ceph_setxattr(inode, name, buf, buflen, flags);
> -	}
> +	if (security_ismaclabel(args->name))
> +		return __ceph_setxattr(args->inode,
> +				       xattr_full_name(handler, args->name),
> +				       args->value, args->size, args->flags);
>  	return  -EOPNOTSUPP;
>  }
>  
>  static int ceph_xattr_get_security_label(const struct xattr_handler *handler,
> -				    struct dentry *unused, struct inode *inode,
> -				    const char *key, void *buf, size_t buflen)
> +					 struct xattr_gs_args *args)
>  {
> -	if (security_ismaclabel(key)) {
> -		const char *name = xattr_full_name(handler, key);
> -		return __ceph_getxattr(inode, name, buf, buflen);
> -	}
> +	if (security_ismaclabel(args->name))
> +		return __ceph_getxattr(args->inode,
> +				       xattr_full_name(handler, args->name),
> +				       args->buffer, args->size);
>  	return  -EOPNOTSUPP;
>  }
>  
> diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
> index 9076150758d8..2506d12c7e5d 100644
> --- a/fs/cifs/xattr.c
> +++ b/fs/cifs/xattr.c
> @@ -48,13 +48,11 @@
>  enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT };
>  
>  static int cifs_xattr_set(const struct xattr_handler *handler,
> -			  struct dentry *dentry, struct inode *inode,
> -			  const char *name, const void *value,
> -			  size_t size, int flags)
> +			  struct xattr_gs_args *args)
>  {
>  	int rc = -EOPNOTSUPP;
>  	unsigned int xid;
> -	struct super_block *sb = dentry->d_sb;
> +	struct super_block *sb = args->dentry->d_sb;
>  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
>  	struct tcon_link *tlink;
>  	struct cifs_tcon *pTcon;
> @@ -67,7 +65,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
>  
>  	xid = get_xid();
>  
> -	full_path = build_path_from_dentry(dentry);
> +	full_path = build_path_from_dentry(args->dentry);
>  	if (full_path == NULL) {
>  		rc = -ENOMEM;
>  		goto out;
> @@ -78,7 +76,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
>  	/* if proc/fs/cifs/streamstoxattr is set then
>  		search server for EAs or streams to
>  		returns as xattrs */
> -	if (size > MAX_EA_VALUE_SIZE) {
> +	if (args->size > MAX_EA_VALUE_SIZE) {
>  		cifs_dbg(FYI, "size of EA value too large\n");
>  		rc = -EOPNOTSUPP;
>  		goto out;
> @@ -91,29 +89,30 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
>  
>  		if (pTcon->ses->server->ops->set_EA)
>  			rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
> -				full_path, name, value, (__u16)size,
> +				full_path, args->name,
> +				args->value, (__u16)args->size,
>  				cifs_sb->local_nls, cifs_sb);
>  		break;
>  
>  	case XATTR_CIFS_ACL: {
>  		struct cifs_ntsd *pacl;
>  
> -		if (!value)
> +		if (!args->value)
>  			goto out;
> -		pacl = kmalloc(size, GFP_KERNEL);
> +		pacl = kmalloc(args->size, GFP_KERNEL);
>  		if (!pacl) {
>  			rc = -ENOMEM;
>  		} else {
> -			memcpy(pacl, value, size);
> -			if (value &&
> +			memcpy(pacl, args->value, args->size);
> +			if (args->value &&
>  			    pTcon->ses->server->ops->set_acl)
>  				rc = pTcon->ses->server->ops->set_acl(pacl,
> -						size, inode,
> +						args->size, args->inode,
>  						full_path, CIFS_ACL_DACL);
>  			else
>  				rc = -EOPNOTSUPP;
>  			if (rc == 0) /* force revalidate of the inode */
> -				CIFS_I(inode)->time = 0;
> +				CIFS_I(args->inode)->time = 0;
>  			kfree(pacl);
>  		}
>  		break;
> @@ -121,11 +120,11 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
>  
>  	case XATTR_ACL_ACCESS:
>  #ifdef CONFIG_CIFS_POSIX
> -		if (!value)
> +		if (!args->value)
>  			goto out;
>  		if (sb->s_flags & SB_POSIXACL)
>  			rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
> -				value, (const int)size,
> +				args->value, (const int)args->size,
>  				ACL_TYPE_ACCESS, cifs_sb->local_nls,
>  				cifs_remap(cifs_sb));
>  #endif  /* CONFIG_CIFS_POSIX */
> @@ -133,11 +132,11 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
>  
>  	case XATTR_ACL_DEFAULT:
>  #ifdef CONFIG_CIFS_POSIX
> -		if (!value)
> +		if (!args->value)
>  			goto out;
>  		if (sb->s_flags & SB_POSIXACL)
>  			rc = CIFSSMBSetPosixACL(xid, pTcon, full_path,
> -				value, (const int)size,
> +				args->value, (const int)args->size,
>  				ACL_TYPE_DEFAULT, cifs_sb->local_nls,
>  				cifs_remap(cifs_sb));
>  #endif  /* CONFIG_CIFS_POSIX */
> @@ -198,12 +197,11 @@ static int cifs_creation_time_get(struct dentry *dentry, struct inode *inode,
>  
>  
>  static int cifs_xattr_get(const struct xattr_handler *handler,
> -			  struct dentry *dentry, struct inode *inode,
> -			  const char *name, void *value, size_t size)
> +			  struct xattr_gs_args *args)
>  {
>  	ssize_t rc = -EOPNOTSUPP;
>  	unsigned int xid;
> -	struct super_block *sb = dentry->d_sb;
> +	struct super_block *sb = args->dentry->d_sb;
>  	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
>  	struct tcon_link *tlink;
>  	struct cifs_tcon *pTcon;
> @@ -216,7 +214,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
>  
>  	xid = get_xid();
>  
> -	full_path = build_path_from_dentry(dentry);
> +	full_path = build_path_from_dentry(args->dentry);
>  	if (full_path == NULL) {
>  		rc = -ENOMEM;
>  		goto out;
> @@ -225,14 +223,17 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
>  	/* return alt name if available as pseudo attr */
>  	switch (handler->flags) {
>  	case XATTR_USER:
> -		cifs_dbg(FYI, "%s:querying user xattr %s\n", __func__, name);
> -		if ((strcmp(name, CIFS_XATTR_ATTRIB) == 0) ||
> -		    (strcmp(name, SMB3_XATTR_ATTRIB) == 0)) {
> -			rc = cifs_attrib_get(dentry, inode, value, size);
> +		cifs_dbg(FYI, "%s:querying user xattr %s\n", __func__,
> +			 args->name);
> +		if ((strcmp(args->name, CIFS_XATTR_ATTRIB) == 0) ||
> +		    (strcmp(args->name, SMB3_XATTR_ATTRIB) == 0)) {
> +			rc = cifs_attrib_get(args->dentry, args->inode,
> +					     args->buffer, args->size);
>  			break;
> -		} else if ((strcmp(name, CIFS_XATTR_CREATETIME) == 0) ||
> -		    (strcmp(name, SMB3_XATTR_CREATETIME) == 0)) {
> -			rc = cifs_creation_time_get(dentry, inode, value, size);
> +		} else if ((strcmp(args->name, CIFS_XATTR_CREATETIME) == 0) ||
> +		    (strcmp(args->name, SMB3_XATTR_CREATETIME) == 0)) {
> +			rc = cifs_creation_time_get(args->dentry, args->inode,
> +						    args->buffer, args->size);
>  			break;
>  		}
>  
> @@ -241,7 +242,8 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
>  
>  		if (pTcon->ses->server->ops->query_all_EAs)
>  			rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
> -				full_path, name, value, size, cifs_sb);
> +				full_path, args->name,
> +				args->buffer, args->size, cifs_sb);
>  		break;
>  
>  	case XATTR_CIFS_ACL: {
> @@ -252,17 +254,17 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
>  			goto out; /* rc already EOPNOTSUPP */
>  
>  		pacl = pTcon->ses->server->ops->get_acl(cifs_sb,
> -				inode, full_path, &acllen);
> +				args->inode, full_path, &acllen);
>  		if (IS_ERR(pacl)) {
>  			rc = PTR_ERR(pacl);
>  			cifs_dbg(VFS, "%s: error %zd getting sec desc\n",
>  				 __func__, rc);
>  		} else {
> -			if (value) {
> -				if (acllen > size)
> +			if (args->buffer) {
> +				if (acllen > args->size)
>  					acllen = -ERANGE;
>  				else
> -					memcpy(value, pacl, acllen);
> +					memcpy(args->buffer, pacl, acllen);
>  			}
>  			rc = acllen;
>  			kfree(pacl);
> @@ -274,7 +276,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
>  #ifdef CONFIG_CIFS_POSIX
>  		if (sb->s_flags & SB_POSIXACL)
>  			rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
> -				value, size, ACL_TYPE_ACCESS,
> +				args->buffer, args->size, ACL_TYPE_ACCESS,
>  				cifs_sb->local_nls,
>  				cifs_remap(cifs_sb));
>  #endif  /* CONFIG_CIFS_POSIX */
> @@ -284,7 +286,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
>  #ifdef CONFIG_CIFS_POSIX
>  		if (sb->s_flags & SB_POSIXACL)
>  			rc = CIFSSMBGetPosixACL(xid, pTcon, full_path,
> -				value, size, ACL_TYPE_DEFAULT,
> +				args->buffer, args->size, ACL_TYPE_DEFAULT,
>  				cifs_sb->local_nls,
>  				cifs_remap(cifs_sb));
>  #endif  /* CONFIG_CIFS_POSIX */
> diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
> index f91db24bbf3b..5fbda6491920 100644
> --- a/fs/ecryptfs/crypto.c
> +++ b/fs/ecryptfs/crypto.c
> @@ -1114,20 +1114,24 @@ ecryptfs_write_metadata_to_xattr(struct dentry *ecryptfs_dentry,
>  				 char *page_virt, size_t size)
>  {
>  	int rc;
> -	struct dentry *lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
> -	struct inode *lower_inode = d_inode(lower_dentry);
> +	struct xattr_gs_args lower = {};
>  
> -	if (!(lower_inode->i_opflags & IOP_XATTR)) {
> +	lower.dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
> +	lower.inode = d_inode(lower.dentry);
> +
> +	if (!(lower.inode->i_opflags & IOP_XATTR)) {
>  		rc = -EOPNOTSUPP;
>  		goto out;
>  	}
>  
> -	inode_lock(lower_inode);
> -	rc = __vfs_setxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
> -			    page_virt, size, 0);
> +	lower.name = ECRYPTFS_XATTR_NAME;
> +	lower.value = page_virt;
> +	lower.size = size;
> +	inode_lock(lower.inode);
> +	rc = __vfs_setxattr(&lower);
>  	if (!rc && ecryptfs_inode)
> -		fsstack_copy_attr_all(ecryptfs_inode, lower_inode);
> -	inode_unlock(lower_inode);
> +		fsstack_copy_attr_all(ecryptfs_inode, lower.inode);
> +	inode_unlock(lower.inode);
>  out:
>  	return rc;
>  }
> diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
> index 18426f4855f1..fc4435847a45 100644
> --- a/fs/ecryptfs/inode.c
> +++ b/fs/ecryptfs/inode.c
> @@ -1009,16 +1009,24 @@ ecryptfs_setxattr(struct dentry *dentry, struct inode *inode,
>  
>  ssize_t
>  ecryptfs_getxattr_lower(struct dentry *lower_dentry, struct inode *lower_inode,
> -			const char *name, void *value, size_t size)
> +			const char *name, void *buffer, size_t size)
>  {
>  	int rc;
> +	struct xattr_gs_args args;
>  
>  	if (!(lower_inode->i_opflags & IOP_XATTR)) {
>  		rc = -EOPNOTSUPP;
>  		goto out;
>  	}
> +	memset(&args, 0, sizeof(args));
> +	args.dentry = lower_dentry;
> +	args.inode = lower_inode;
> +	args.name = name;
> +	args.buffer = buffer;
> +	args.size = size;
> +	args.flags = XATTR_NOSECURITY;
>  	inode_lock(lower_inode);
> -	rc = __vfs_getxattr(lower_dentry, lower_inode, name, value, size);
> +	rc = __vfs_getxattr(&args);
>  	inode_unlock(lower_inode);
>  out:
>  	return rc;
> @@ -1102,23 +1110,23 @@ const struct inode_operations ecryptfs_main_iops = {
>  };
>  
>  static int ecryptfs_xattr_get(const struct xattr_handler *handler,
> -			      struct dentry *dentry, struct inode *inode,
> -			      const char *name, void *buffer, size_t size)
> +			      struct xattr_gs_args *args)
>  {
> -	return ecryptfs_getxattr(dentry, inode, name, buffer, size);
> +	return ecryptfs_getxattr(args->dentry, args->inode, args->name,
> +				 args->buffer, args->size);
>  }
>  
>  static int ecryptfs_xattr_set(const struct xattr_handler *handler,
> -			      struct dentry *dentry, struct inode *inode,
> -			      const char *name, const void *value, size_t size,
> -			      int flags)
> +			      struct xattr_gs_args *args)
>  {
> -	if (value)
> -		return ecryptfs_setxattr(dentry, inode, name, value, size, flags);
> -	else {
> -		BUG_ON(flags != XATTR_REPLACE);
> -		return ecryptfs_removexattr(dentry, inode, name);
> -	}
> +	if (args->value)
> +		return ecryptfs_setxattr(args->dentry, args->inode, args->name,
> +					 args->value, args->size, args->flags);
> +	else if (args->flags != XATTR_REPLACE)
> +		return -EINVAL;
> +	else
> +		return ecryptfs_removexattr(args->dentry, args->inode,
> +					    args->name);
>  }
>  
>  static const struct xattr_handler ecryptfs_xattr_handler = {
> diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
> index cffa0c1ec829..90dc0354ec5e 100644
> --- a/fs/ecryptfs/mmap.c
> +++ b/fs/ecryptfs/mmap.c
> @@ -402,37 +402,40 @@ struct kmem_cache *ecryptfs_xattr_cache;
>  
>  static int ecryptfs_write_inode_size_to_xattr(struct inode *ecryptfs_inode)
>  {
> -	ssize_t size;
> -	void *xattr_virt;
> -	struct dentry *lower_dentry =
> -		ecryptfs_inode_to_private(ecryptfs_inode)->lower_file->f_path.dentry;
> -	struct inode *lower_inode = d_inode(lower_dentry);
> +	struct xattr_gs_args args;
>  	int rc;
>  
> -	if (!(lower_inode->i_opflags & IOP_XATTR)) {
> +	memset(&args, 0, sizeof(args));
> +	args.dentry = ecryptfs_inode_to_private(ecryptfs_inode)->
> +		lower_file->f_path.dentry;
> +	args.inode = d_inode(args.dentry);
> +	if (!(args.inode->i_opflags & IOP_XATTR)) {
>  		printk(KERN_WARNING
>  		       "No support for setting xattr in lower filesystem\n");
>  		rc = -ENOSYS;
>  		goto out;
>  	}
> -	xattr_virt = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL);
> -	if (!xattr_virt) {
> +	args.buffer = kmem_cache_alloc(ecryptfs_xattr_cache, GFP_KERNEL);
> +	if (!args.buffer) {
>  		rc = -ENOMEM;
>  		goto out;
>  	}
> -	inode_lock(lower_inode);
> -	size = __vfs_getxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
> -			      xattr_virt, PAGE_SIZE);
> -	if (size < 0)
> -		size = 8;
> -	put_unaligned_be64(i_size_read(ecryptfs_inode), xattr_virt);
> -	rc = __vfs_setxattr(lower_dentry, lower_inode, ECRYPTFS_XATTR_NAME,
> -			    xattr_virt, size, 0);
> -	inode_unlock(lower_inode);
> +	args.name = ECRYPTFS_XATTR_NAME;
> +	args.size = PAGE_SIZE;
> +	args.flags = XATTR_NOSECURITY;
> +	inode_lock(args.inode);
> +	args.size = __vfs_getxattr(&args);
> +	if (args.size < 0)
> +		args.size = 8;
> +	put_unaligned_be64(i_size_read(ecryptfs_inode), args.buffer);
> +	args.flags = 0;
> +	args.value = args.buffer;
> +	rc = __vfs_setxattr(&args);
> +	inode_unlock(args.inode);
>  	if (rc)
>  		printk(KERN_ERR "Error whilst attempting to write inode size "
>  		       "to lower file xattr; rc = [%d]\n", rc);
> -	kmem_cache_free(ecryptfs_xattr_cache, xattr_virt);
> +	kmem_cache_free(ecryptfs_xattr_cache, args.buffer);
>  out:
>  	return rc;
>  }
> diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c
> index 9a682e440acb..d651d4a7c9ca 100644
> --- a/fs/ext2/xattr_security.c
> +++ b/fs/ext2/xattr_security.c
> @@ -10,21 +10,19 @@
>  
>  static int
>  ext2_xattr_security_get(const struct xattr_handler *handler,
> -			struct dentry *unused, struct inode *inode,
> -			const char *name, void *buffer, size_t size)
> +			struct xattr_gs_args *args)
>  {
> -	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_SECURITY, name,
> -			      buffer, size);
> +	return ext2_xattr_get(args->inode, EXT2_XATTR_INDEX_SECURITY,
> +			      args->name, args->buffer, args->size);
>  }
>  
>  static int
>  ext2_xattr_security_set(const struct xattr_handler *handler,
> -			struct dentry *unused, struct inode *inode,
> -			const char *name, const void *value,
> -			size_t size, int flags)
> +			struct xattr_gs_args *args)
>  {
> -	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY, name,
> -			      value, size, flags);
> +	return ext2_xattr_set(args->inode, EXT2_XATTR_INDEX_SECURITY,
> +			      args->name, args->value, args->size,
> +			      args->flags);
>  }
>  
>  static int ext2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
> diff --git a/fs/ext2/xattr_trusted.c b/fs/ext2/xattr_trusted.c
> index 49add1107850..41390dd0386a 100644
> --- a/fs/ext2/xattr_trusted.c
> +++ b/fs/ext2/xattr_trusted.c
> @@ -17,21 +17,18 @@ ext2_xattr_trusted_list(struct dentry *dentry)
>  
>  static int
>  ext2_xattr_trusted_get(const struct xattr_handler *handler,
> -		       struct dentry *unused, struct inode *inode,
> -		       const char *name, void *buffer, size_t size)
> +		       struct xattr_gs_args *args)
>  {
> -	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_TRUSTED, name,
> -			      buffer, size);
> +	return ext2_xattr_get(args->inode, EXT2_XATTR_INDEX_TRUSTED, args->name,
> +			      args->buffer, args->size);
>  }
>  
>  static int
>  ext2_xattr_trusted_set(const struct xattr_handler *handler,
> -		       struct dentry *unused, struct inode *inode,
> -		       const char *name, const void *value,
> -		       size_t size, int flags)
> +		       struct xattr_gs_args *args)
>  {
> -	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_TRUSTED, name,
> -			      value, size, flags);
> +	return ext2_xattr_set(args->inode, EXT2_XATTR_INDEX_TRUSTED, args->name,
> +			      args->value, args->size, args->flags);
>  }
>  
>  const struct xattr_handler ext2_xattr_trusted_handler = {
> diff --git a/fs/ext2/xattr_user.c b/fs/ext2/xattr_user.c
> index c243a3b4d69d..1ef881890dde 100644
> --- a/fs/ext2/xattr_user.c
> +++ b/fs/ext2/xattr_user.c
> @@ -19,26 +19,23 @@ ext2_xattr_user_list(struct dentry *dentry)
>  
>  static int
>  ext2_xattr_user_get(const struct xattr_handler *handler,
> -		    struct dentry *unused, struct inode *inode,
> -		    const char *name, void *buffer, size_t size)
> +		    struct xattr_gs_args *args)
>  {
> -	if (!test_opt(inode->i_sb, XATTR_USER))
> +	if (!test_opt(args->inode->i_sb, XATTR_USER))
>  		return -EOPNOTSUPP;
> -	return ext2_xattr_get(inode, EXT2_XATTR_INDEX_USER,
> -			      name, buffer, size);
> +	return ext2_xattr_get(args->inode, EXT2_XATTR_INDEX_USER, args->name,
> +			      args->buffer, args->size);
>  }
>  
>  static int
>  ext2_xattr_user_set(const struct xattr_handler *handler,
> -		    struct dentry *unused, struct inode *inode,
> -		    const char *name, const void *value,
> -		    size_t size, int flags)
> +		    struct xattr_gs_args *args)
>  {
> -	if (!test_opt(inode->i_sb, XATTR_USER))
> +	if (!test_opt(args->inode->i_sb, XATTR_USER))
>  		return -EOPNOTSUPP;
>  
> -	return ext2_xattr_set(inode, EXT2_XATTR_INDEX_USER,
> -			      name, value, size, flags);
> +	return ext2_xattr_set(args->inode, EXT2_XATTR_INDEX_USER, args->name,
> +			      args->value, args->size, args->flags);
>  }
>  
>  const struct xattr_handler ext2_xattr_user_handler = {
> diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c
> index 197a9d8a15ef..71ed703e01fe 100644
> --- a/fs/ext4/xattr_security.c
> +++ b/fs/ext4/xattr_security.c
> @@ -14,21 +14,18 @@
>  
>  static int
>  ext4_xattr_security_get(const struct xattr_handler *handler,
> -			struct dentry *unused, struct inode *inode,
> -			const char *name, void *buffer, size_t size)
> +			struct xattr_gs_args *args)
>  {
> -	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_SECURITY,
> -			      name, buffer, size);
> +	return ext4_xattr_get(args->inode, EXT4_XATTR_INDEX_SECURITY,
> +			      args->name, args->buffer, args->size);
>  }
>  
>  static int
>  ext4_xattr_security_set(const struct xattr_handler *handler,
> -			struct dentry *unused, struct inode *inode,
> -			const char *name, const void *value,
> -			size_t size, int flags)
> +			struct xattr_gs_args *args)
>  {
> -	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_SECURITY,
> -			      name, value, size, flags);
> +	return ext4_xattr_set(args->inode, EXT4_XATTR_INDEX_SECURITY,
> +			      args->name, args->value, args->size, args->flags);
>  }
>  
>  static int
> diff --git a/fs/ext4/xattr_trusted.c b/fs/ext4/xattr_trusted.c
> index e9389e5d75c3..ed347a978102 100644
> --- a/fs/ext4/xattr_trusted.c
> +++ b/fs/ext4/xattr_trusted.c
> @@ -21,21 +21,18 @@ ext4_xattr_trusted_list(struct dentry *dentry)
>  
>  static int
>  ext4_xattr_trusted_get(const struct xattr_handler *handler,
> -		       struct dentry *unused, struct inode *inode,
> -		       const char *name, void *buffer, size_t size)
> +		       struct xattr_gs_args *args)
>  {
> -	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_TRUSTED,
> -			      name, buffer, size);
> +	return ext4_xattr_get(args->inode, EXT4_XATTR_INDEX_TRUSTED,
> +			      args->name, args->buffer, args->size);
>  }
>  
>  static int
>  ext4_xattr_trusted_set(const struct xattr_handler *handler,
> -		       struct dentry *unused, struct inode *inode,
> -		       const char *name, const void *value,
> -		       size_t size, int flags)
> +		       struct xattr_gs_args *args)
>  {
> -	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_TRUSTED,
> -			      name, value, size, flags);
> +	return ext4_xattr_set(args->inode, EXT4_XATTR_INDEX_TRUSTED,
> +			      args->name, args->value, args->size, args->flags);
>  }
>  
>  const struct xattr_handler ext4_xattr_trusted_handler = {
> diff --git a/fs/ext4/xattr_user.c b/fs/ext4/xattr_user.c
> index d4546184b34b..86e9f5a9284d 100644
> --- a/fs/ext4/xattr_user.c
> +++ b/fs/ext4/xattr_user.c
> @@ -20,25 +20,22 @@ ext4_xattr_user_list(struct dentry *dentry)
>  
>  static int
>  ext4_xattr_user_get(const struct xattr_handler *handler,
> -		    struct dentry *unused, struct inode *inode,
> -		    const char *name, void *buffer, size_t size)
> +		    struct xattr_gs_args *args)
>  {
> -	if (!test_opt(inode->i_sb, XATTR_USER))
> +	if (!test_opt(args->inode->i_sb, XATTR_USER))
>  		return -EOPNOTSUPP;
> -	return ext4_xattr_get(inode, EXT4_XATTR_INDEX_USER,
> -			      name, buffer, size);
> +	return ext4_xattr_get(args->inode, EXT4_XATTR_INDEX_USER,
> +			      args->name, args->buffer, args->size);
>  }
>  
>  static int
>  ext4_xattr_user_set(const struct xattr_handler *handler,
> -		    struct dentry *unused, struct inode *inode,
> -		    const char *name, const void *value,
> -		    size_t size, int flags)
> +		    struct xattr_gs_args *args)
>  {
> -	if (!test_opt(inode->i_sb, XATTR_USER))
> +	if (!test_opt(args->inode->i_sb, XATTR_USER))
>  		return -EOPNOTSUPP;
> -	return ext4_xattr_set(inode, EXT4_XATTR_INDEX_USER,
> -			      name, value, size, flags);
> +	return ext4_xattr_set(args->inode, EXT4_XATTR_INDEX_USER,
> +			      args->name, args->value, args->size, args->flags);
>  }
>  
>  const struct xattr_handler ext4_xattr_user_handler = {
> diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
> index b32c45621679..4fd47b84616f 100644
> --- a/fs/f2fs/xattr.c
> +++ b/fs/f2fs/xattr.c
> @@ -23,10 +23,9 @@
>  #include "xattr.h"
>  
>  static int f2fs_xattr_generic_get(const struct xattr_handler *handler,
> -		struct dentry *unused, struct inode *inode,
> -		const char *name, void *buffer, size_t size)
> +				  struct xattr_gs_args *args)
>  {
> -	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
> +	struct f2fs_sb_info *sbi = F2FS_SB(args->inode->i_sb);
>  
>  	switch (handler->flags) {
>  	case F2FS_XATTR_INDEX_USER:
> @@ -39,16 +38,14 @@ static int f2fs_xattr_generic_get(const struct xattr_handler *handler,
>  	default:
>  		return -EINVAL;
>  	}
> -	return f2fs_getxattr(inode, handler->flags, name,
> -			     buffer, size, NULL);
> +	return f2fs_getxattr(args->inode, handler->flags, args->name,
> +			     args->buffer, args->size, NULL);
>  }
>  
>  static int f2fs_xattr_generic_set(const struct xattr_handler *handler,
> -		struct dentry *unused, struct inode *inode,
> -		const char *name, const void *value,
> -		size_t size, int flags)
> +				  struct xattr_gs_args *args)
>  {
> -	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
> +	struct f2fs_sb_info *sbi = F2FS_SB(args->inode->i_sb);
>  
>  	switch (handler->flags) {
>  	case F2FS_XATTR_INDEX_USER:
> @@ -61,8 +58,8 @@ static int f2fs_xattr_generic_set(const struct xattr_handler *handler,
>  	default:
>  		return -EINVAL;
>  	}
> -	return f2fs_setxattr(inode, handler->flags, name,
> -					value, size, NULL, flags);
> +	return f2fs_setxattr(args->inode, handler->flags, args->name,
> +			     args->value, args->size, NULL, args->flags);
>  }
>  
>  static bool f2fs_xattr_user_list(struct dentry *dentry)
> @@ -78,36 +75,33 @@ static bool f2fs_xattr_trusted_list(struct dentry *dentry)
>  }
>  
>  static int f2fs_xattr_advise_get(const struct xattr_handler *handler,
> -		struct dentry *unused, struct inode *inode,
> -		const char *name, void *buffer, size_t size)
> +				 struct xattr_gs_args *args)
>  {
> -	if (buffer)
> -		*((char *)buffer) = F2FS_I(inode)->i_advise;
> +	if (args->buffer)
> +		*((char *)args->buffer) = F2FS_I(args->inode)->i_advise;
>  	return sizeof(char);
>  }
>  
>  static int f2fs_xattr_advise_set(const struct xattr_handler *handler,
> -		struct dentry *unused, struct inode *inode,
> -		const char *name, const void *value,
> -		size_t size, int flags)
> +				 struct xattr_gs_args *args)
>  {
> -	unsigned char old_advise = F2FS_I(inode)->i_advise;
> +	unsigned char old_advise = F2FS_I(args->inode)->i_advise;
>  	unsigned char new_advise;
>  
> -	if (!inode_owner_or_capable(inode))
> +	if (!inode_owner_or_capable(args->inode))
>  		return -EPERM;
> -	if (value == NULL)
> +	if (args->value == NULL)
>  		return -EINVAL;
>  
> -	new_advise = *(char *)value;
> +	new_advise = *(char *)args->value;
>  	if (new_advise & ~FADVISE_MODIFIABLE_BITS)
>  		return -EINVAL;
>  
>  	new_advise = new_advise & FADVISE_MODIFIABLE_BITS;
>  	new_advise |= old_advise & ~FADVISE_MODIFIABLE_BITS;
>  
> -	F2FS_I(inode)->i_advise = new_advise;
> -	f2fs_mark_inode_dirty_sync(inode, true);
> +	F2FS_I(args->inode)->i_advise = new_advise;
> +	f2fs_mark_inode_dirty_sync(args->inode, true);
>  	return 0;
>  }
>  
> diff --git a/fs/fuse/xattr.c b/fs/fuse/xattr.c
> index 433717640f78..8b8fb719d498 100644
> --- a/fs/fuse/xattr.c
> +++ b/fs/fuse/xattr.c
> @@ -175,21 +175,19 @@ int fuse_removexattr(struct inode *inode, const char *name)
>  }
>  
>  static int fuse_xattr_get(const struct xattr_handler *handler,
> -			 struct dentry *dentry, struct inode *inode,
> -			 const char *name, void *value, size_t size)
> +			  struct xattr_gs_args *args)
>  {
> -	return fuse_getxattr(inode, name, value, size);
> +	return fuse_getxattr(args->inode, args->name, args->buffer, args->size);
>  }
>  
>  static int fuse_xattr_set(const struct xattr_handler *handler,
> -			  struct dentry *dentry, struct inode *inode,
> -			  const char *name, const void *value, size_t size,
> -			  int flags)
> +			  struct xattr_gs_args *args)
>  {
> -	if (!value)
> -		return fuse_removexattr(inode, name);
> +	if (!args->value)
> +		return fuse_removexattr(args->inode, args->name);
>  
> -	return fuse_setxattr(inode, name, value, size, flags);
> +	return fuse_setxattr(args->inode, args->name,
> +			     args->value, args->size, args->flags);
>  }
>  
>  static bool no_xattr_list(struct dentry *dentry)
> @@ -198,16 +196,13 @@ static bool no_xattr_list(struct dentry *dentry)
>  }
>  
>  static int no_xattr_get(const struct xattr_handler *handler,
> -			struct dentry *dentry, struct inode *inode,
> -			const char *name, void *value, size_t size)
> +			struct xattr_gs_args *args)
>  {
>  	return -EOPNOTSUPP;
>  }
>  
>  static int no_xattr_set(const struct xattr_handler *handler,
> -			struct dentry *dentry, struct inode *nodee,
> -			const char *name, const void *value,
> -			size_t size, int flags)
> +			struct xattr_gs_args *args)
>  {
>  	return -EOPNOTSUPP;
>  }
> diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c
> index bbe593d16bea..bf8e1bd17a29 100644
> --- a/fs/gfs2/xattr.c
> +++ b/fs/gfs2/xattr.c
> @@ -587,10 +587,9 @@ static int __gfs2_xattr_get(struct inode *inode, const char *name,
>  }
>  
>  static int gfs2_xattr_get(const struct xattr_handler *handler,
> -			  struct dentry *unused, struct inode *inode,
> -			  const char *name, void *buffer, size_t size)
> +			  struct xattr_gs_args *args)
>  {
> -	struct gfs2_inode *ip = GFS2_I(inode);
> +	struct gfs2_inode *ip = GFS2_I(args->inode);
>  	struct gfs2_holder gh;
>  	int ret;
>  
> @@ -603,7 +602,8 @@ static int gfs2_xattr_get(const struct xattr_handler *handler,
>  	} else {
>  		gfs2_holder_mark_uninitialized(&gh);
>  	}
> -	ret = __gfs2_xattr_get(inode, name, buffer, size, handler->flags);
> +	ret = __gfs2_xattr_get(args->inode, args->name,
> +			       args->buffer, args->size, handler->flags);
>  	if (gfs2_holder_initialized(&gh))
>  		gfs2_glock_dq_uninit(&gh);
>  	return ret;
> @@ -1214,11 +1214,9 @@ int __gfs2_xattr_set(struct inode *inode, const char *name,
>  }
>  
>  static int gfs2_xattr_set(const struct xattr_handler *handler,
> -			  struct dentry *unused, struct inode *inode,
> -			  const char *name, const void *value,
> -			  size_t size, int flags)
> +			  struct xattr_gs_args *args)
>  {
> -	struct gfs2_inode *ip = GFS2_I(inode);
> +	struct gfs2_inode *ip = GFS2_I(args->inode);
>  	struct gfs2_holder gh;
>  	int ret;
>  
> @@ -1237,7 +1235,9 @@ static int gfs2_xattr_set(const struct xattr_handler *handler,
>  			return -EIO;
>  		gfs2_holder_mark_uninitialized(&gh);
>  	}
> -	ret = __gfs2_xattr_set(inode, name, value, size, flags, handler->flags);
> +	ret = __gfs2_xattr_set(args->inode, args->name,
> +			       args->value, args->size,
> +			       args->flags, handler->flags);
>  	if (gfs2_holder_initialized(&gh))
>  		gfs2_glock_dq_uninit(&gh);
>  	return ret;
> diff --git a/fs/hfs/attr.c b/fs/hfs/attr.c
> index 74fa62643136..b3355368dc58 100644
> --- a/fs/hfs/attr.c
> +++ b/fs/hfs/attr.c
> @@ -114,21 +114,20 @@ static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type,
>  }
>  
>  static int hfs_xattr_get(const struct xattr_handler *handler,
> -			 struct dentry *unused, struct inode *inode,
> -			 const char *name, void *value, size_t size)
> +			 struct xattr_gs_args *args)
>  {
> -	return __hfs_getxattr(inode, handler->flags, value, size);
> +	return __hfs_getxattr(args->inode, handler->flags,
> +			      args->buffer, args->size);
>  }
>  
>  static int hfs_xattr_set(const struct xattr_handler *handler,
> -			 struct dentry *unused, struct inode *inode,
> -			 const char *name, const void *value, size_t size,
> -			 int flags)
> +			 struct xattr_gs_args *args)
>  {
> -	if (!value)
> +	if (!args->value)
>  		return -EOPNOTSUPP;
>  
> -	return __hfs_setxattr(inode, handler->flags, value, size, flags);
> +	return __hfs_setxattr(args->inode, handler->flags,
> +			      args->value, args->size, args->flags);
>  }
>  
>  static const struct xattr_handler hfs_creator_handler = {
> diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
> index bb0b27d88e50..b6cc7f18bce8 100644
> --- a/fs/hfsplus/xattr.c
> +++ b/fs/hfsplus/xattr.c
> @@ -838,14 +838,13 @@ static int hfsplus_removexattr(struct inode *inode, const char *name)
>  }
>  
>  static int hfsplus_osx_getxattr(const struct xattr_handler *handler,
> -				struct dentry *unused, struct inode *inode,
> -				const char *name, void *buffer, size_t size)
> +				struct xattr_gs_args *args)
>  {
>  	/*
>  	 * Don't allow retrieving properly prefixed attributes
>  	 * by prepending them with "osx."
>  	 */
> -	if (is_known_namespace(name))
> +	if (is_known_namespace(args->name))
>  		return -EOPNOTSUPP;
>  
>  	/*
> @@ -854,19 +853,18 @@ static int hfsplus_osx_getxattr(const struct xattr_handler *handler,
>  	 * creates), so we pass the name through unmodified (after
>  	 * ensuring it doesn't conflict with another namespace).
>  	 */
> -	return __hfsplus_getxattr(inode, name, buffer, size);
> +	return __hfsplus_getxattr(args->inode, args->name,
> +				  args->buffer, args->size);
>  }
>  
>  static int hfsplus_osx_setxattr(const struct xattr_handler *handler,
> -				struct dentry *unused, struct inode *inode,
> -				const char *name, const void *buffer,
> -				size_t size, int flags)
> +				struct xattr_gs_args *args)
>  {
>  	/*
>  	 * Don't allow setting properly prefixed attributes
>  	 * by prepending them with "osx."
>  	 */
> -	if (is_known_namespace(name))
> +	if (is_known_namespace(args->name))
>  		return -EOPNOTSUPP;
>  
>  	/*
> @@ -875,7 +873,8 @@ static int hfsplus_osx_setxattr(const struct xattr_handler *handler,
>  	 * creates), so we pass the name through unmodified (after
>  	 * ensuring it doesn't conflict with another namespace).
>  	 */
> -	return __hfsplus_setxattr(inode, name, buffer, size, flags);
> +	return __hfsplus_setxattr(args->inode, args->name,
> +				  args->value, args->size, args->flags);
>  }
>  
>  const struct xattr_handler hfsplus_xattr_osx_handler = {
> diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c
> index cfbe6a3bfb1e..8a8185eca12e 100644
> --- a/fs/hfsplus/xattr_security.c
> +++ b/fs/hfsplus/xattr_security.c
> @@ -14,20 +14,19 @@
>  #include "xattr.h"
>  
>  static int hfsplus_security_getxattr(const struct xattr_handler *handler,
> -				     struct dentry *unused, struct inode *inode,
> -				     const char *name, void *buffer, size_t size)
> +				     struct xattr_gs_args *args)
>  {
> -	return hfsplus_getxattr(inode, name, buffer, size,
> +	return hfsplus_getxattr(args->inode, args->name,
> +				args->buffer, args->size,
>  				XATTR_SECURITY_PREFIX,
>  				XATTR_SECURITY_PREFIX_LEN);
>  }
>  
>  static int hfsplus_security_setxattr(const struct xattr_handler *handler,
> -				     struct dentry *unused, struct inode *inode,
> -				     const char *name, const void *buffer,
> -				     size_t size, int flags)
> +				     struct xattr_gs_args *args)
>  {
> -	return hfsplus_setxattr(inode, name, buffer, size, flags,
> +	return hfsplus_setxattr(args->inode, args->name,
> +				args->value, args->size, args->flags,
>  				XATTR_SECURITY_PREFIX,
>  				XATTR_SECURITY_PREFIX_LEN);
>  }
> diff --git a/fs/hfsplus/xattr_trusted.c b/fs/hfsplus/xattr_trusted.c
> index fbad91e1dada..a682a2e363e7 100644
> --- a/fs/hfsplus/xattr_trusted.c
> +++ b/fs/hfsplus/xattr_trusted.c
> @@ -13,20 +13,19 @@
>  #include "xattr.h"
>  
>  static int hfsplus_trusted_getxattr(const struct xattr_handler *handler,
> -				    struct dentry *unused, struct inode *inode,
> -				    const char *name, void *buffer, size_t size)
> +				    struct xattr_gs_args *args)
>  {
> -	return hfsplus_getxattr(inode, name, buffer, size,
> +	return hfsplus_getxattr(args->inode, args->name,
> +				args->buffer, args->size,
>  				XATTR_TRUSTED_PREFIX,
>  				XATTR_TRUSTED_PREFIX_LEN);
>  }
>  
>  static int hfsplus_trusted_setxattr(const struct xattr_handler *handler,
> -				    struct dentry *unused, struct inode *inode,
> -				    const char *name, const void *buffer,
> -				    size_t size, int flags)
> +				    struct xattr_gs_args *args)
>  {
> -	return hfsplus_setxattr(inode, name, buffer, size, flags,
> +	return hfsplus_setxattr(args->inode, args->name,
> +				args->buffer, args->size, args->flags,
>  				XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
>  }
>  
> diff --git a/fs/hfsplus/xattr_user.c b/fs/hfsplus/xattr_user.c
> index 74d19faf255e..9b58d7ec263d 100644
> --- a/fs/hfsplus/xattr_user.c
> +++ b/fs/hfsplus/xattr_user.c
> @@ -13,20 +13,19 @@
>  #include "xattr.h"
>  
>  static int hfsplus_user_getxattr(const struct xattr_handler *handler,
> -				 struct dentry *unused, struct inode *inode,
> -				 const char *name, void *buffer, size_t size)
> +				 struct xattr_gs_args *args)
>  {
>  
> -	return hfsplus_getxattr(inode, name, buffer, size,
> +	return hfsplus_getxattr(args->inode, args->name,
> +				args->buffer, args->size,
>  				XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
>  }
>  
>  static int hfsplus_user_setxattr(const struct xattr_handler *handler,
> -				 struct dentry *unused, struct inode *inode,
> -				 const char *name, const void *buffer,
> -				 size_t size, int flags)
> +				 struct xattr_gs_args *args)
>  {
> -	return hfsplus_setxattr(inode, name, buffer, size, flags,
> +	return hfsplus_setxattr(args->inode, args->name,
> +				args->value, args->size, args->flags,
>  				XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
>  }
>  
> diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
> index c2332e30f218..6aa552db3807 100644
> --- a/fs/jffs2/security.c
> +++ b/fs/jffs2/security.c
> @@ -49,20 +49,18 @@ int jffs2_init_security(struct inode *inode, struct inode *dir,
>  
>  /* ---- XATTR Handler for "security.*" ----------------- */
>  static int jffs2_security_getxattr(const struct xattr_handler *handler,
> -				   struct dentry *unused, struct inode *inode,
> -				   const char *name, void *buffer, size_t size)
> +				   struct xattr_gs_args *args)
>  {
> -	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY,
> -				 name, buffer, size);
> +	return do_jffs2_getxattr(args->inode, JFFS2_XPREFIX_SECURITY,
> +				 args->name, args->buffer, args->size);
>  }
>  
>  static int jffs2_security_setxattr(const struct xattr_handler *handler,
> -				   struct dentry *unused, struct inode *inode,
> -				   const char *name, const void *buffer,
> -				   size_t size, int flags)
> +				   struct xattr_gs_args *args)
>  {
> -	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY,
> -				 name, buffer, size, flags);
> +	return do_jffs2_setxattr(args->inode, JFFS2_XPREFIX_SECURITY,
> +				 args->name, args->value, args->size,
> +				 args->flags);
>  }
>  
>  const struct xattr_handler jffs2_security_xattr_handler = {
> diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c
> index 5d6030826c52..5d235175d6fd 100644
> --- a/fs/jffs2/xattr_trusted.c
> +++ b/fs/jffs2/xattr_trusted.c
> @@ -17,20 +17,18 @@
>  #include "nodelist.h"
>  
>  static int jffs2_trusted_getxattr(const struct xattr_handler *handler,
> -				  struct dentry *unused, struct inode *inode,
> -				  const char *name, void *buffer, size_t size)
> +				  struct xattr_gs_args *args)
>  {
> -	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED,
> -				 name, buffer, size);
> +	return do_jffs2_getxattr(args->inode, JFFS2_XPREFIX_TRUSTED,
> +				 args->name, args->buffer, args->size);
>  }
>  
>  static int jffs2_trusted_setxattr(const struct xattr_handler *handler,
> -				  struct dentry *unused, struct inode *inode,
> -				  const char *name, const void *buffer,
> -				  size_t size, int flags)
> +				  struct xattr_gs_args *args)
>  {
> -	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED,
> -				 name, buffer, size, flags);
> +	return do_jffs2_setxattr(args->inode, JFFS2_XPREFIX_TRUSTED,
> +				 args->name, args->value, args->size,
> +				 args->flags);
>  }
>  
>  static bool jffs2_trusted_listxattr(struct dentry *dentry)
> diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c
> index 9d027b4abcf9..a35a0785e72b 100644
> --- a/fs/jffs2/xattr_user.c
> +++ b/fs/jffs2/xattr_user.c
> @@ -17,20 +17,18 @@
>  #include "nodelist.h"
>  
>  static int jffs2_user_getxattr(const struct xattr_handler *handler,
> -			       struct dentry *unused, struct inode *inode,
> -			       const char *name, void *buffer, size_t size)
> +			       struct xattr_gs_args *args)
>  {
> -	return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER,
> -				 name, buffer, size);
> +	return do_jffs2_getxattr(args->inode, JFFS2_XPREFIX_USER,
> +				 args->name, args->buffer, args->size);
>  }
>  
>  static int jffs2_user_setxattr(const struct xattr_handler *handler,
> -			       struct dentry *unused, struct inode *inode,
> -			       const char *name, const void *buffer,
> -			       size_t size, int flags)
> +			       struct xattr_gs_args *args)
>  {
> -	return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER,
> -				 name, buffer, size, flags);
> +	return do_jffs2_setxattr(args->inode, JFFS2_XPREFIX_USER,
> +				 args->name, args->value, args->size,
> +				 args->flags);
>  }
>  
>  const struct xattr_handler jffs2_user_xattr_handler = {
> diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
> index db41e7803163..225fc440ff62 100644
> --- a/fs/jfs/xattr.c
> +++ b/fs/jfs/xattr.c
> @@ -924,39 +924,36 @@ static int __jfs_xattr_set(struct inode *inode, const char *name,
>  }
>  
>  static int jfs_xattr_get(const struct xattr_handler *handler,
> -			 struct dentry *unused, struct inode *inode,
> -			 const char *name, void *value, size_t size)
> +			 struct xattr_gs_args *args)
>  {
> -	name = xattr_full_name(handler, name);
> -	return __jfs_getxattr(inode, name, value, size);
> +	return __jfs_getxattr(args->inode, xattr_full_name(handler, args->name),
> +			      args->buffer, args->size);
>  }
>  
>  static int jfs_xattr_set(const struct xattr_handler *handler,
> -			 struct dentry *unused, struct inode *inode,
> -			 const char *name, const void *value,
> -			 size_t size, int flags)
> +			 struct xattr_gs_args *args)
>  {
> -	name = xattr_full_name(handler, name);
> -	return __jfs_xattr_set(inode, name, value, size, flags);
> +	return __jfs_xattr_set(args->inode,
> +			       xattr_full_name(handler, args->name),
> +			       args->value, args->size, args->flags);
>  }
>  
>  static int jfs_xattr_get_os2(const struct xattr_handler *handler,
> -			     struct dentry *unused, struct inode *inode,
> -			     const char *name, void *value, size_t size)
> +			     struct xattr_gs_args *args)
>  {
> -	if (is_known_namespace(name))
> +	if (is_known_namespace(args->name))
>  		return -EOPNOTSUPP;
> -	return __jfs_getxattr(inode, name, value, size);
> +	return __jfs_getxattr(args->inode, args->name,
> +			      args->buffer, args->size);
>  }
>  
>  static int jfs_xattr_set_os2(const struct xattr_handler *handler,
> -			     struct dentry *unused, struct inode *inode,
> -			     const char *name, const void *value,
> -			     size_t size, int flags)
> +			     struct xattr_gs_args *args)
>  {
> -	if (is_known_namespace(name))
> +	if (is_known_namespace(args->name))
>  		return -EOPNOTSUPP;
> -	return __jfs_xattr_set(inode, name, value, size, flags);
> +	return __jfs_xattr_set(args->inode, args->name,
> +			       args->value, args->size, args->flags);
>  }
>  
>  static const struct xattr_handler jfs_user_xattr_handler = {
> diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
> index f3f3984cce80..1ae646a0b20b 100644
> --- a/fs/kernfs/inode.c
> +++ b/fs/kernfs/inode.c
> @@ -288,13 +288,13 @@ int kernfs_iop_permission(struct inode *inode, int mask)
>  }
>  
>  int kernfs_xattr_get(struct kernfs_node *kn, const char *name,
> -		     void *value, size_t size)
> +		     void *buffer, size_t size)
>  {
>  	struct kernfs_iattrs *attrs = kernfs_iattrs_noalloc(kn);
>  	if (!attrs)
>  		return -ENODATA;
>  
> -	return simple_xattr_get(&attrs->xattrs, name, value, size);
> +	return simple_xattr_get(&attrs->xattrs, name, buffer, size);
>  }
>  
>  int kernfs_xattr_set(struct kernfs_node *kn, const char *name,
> @@ -308,24 +308,21 @@ int kernfs_xattr_set(struct kernfs_node *kn, const char *name,
>  }
>  
>  static int kernfs_vfs_xattr_get(const struct xattr_handler *handler,
> -				struct dentry *unused, struct inode *inode,
> -				const char *suffix, void *value, size_t size)
> +				struct xattr_gs_args *args)
>  {
> -	const char *name = xattr_full_name(handler, suffix);
> -	struct kernfs_node *kn = inode->i_private;
> +	struct kernfs_node *kn = args->inode->i_private;
>  
> -	return kernfs_xattr_get(kn, name, value, size);
> +	return kernfs_xattr_get(kn, xattr_full_name(handler, args->name),
> +				args->buffer, args->size);
>  }
>  
>  static int kernfs_vfs_xattr_set(const struct xattr_handler *handler,
> -				struct dentry *unused, struct inode *inode,
> -				const char *suffix, const void *value,
> -				size_t size, int flags)
> +				struct xattr_gs_args *args)
>  {
> -	const char *name = xattr_full_name(handler, suffix);
> -	struct kernfs_node *kn = inode->i_private;
> +	struct kernfs_node *kn = args->inode->i_private;
>  
> -	return kernfs_xattr_set(kn, name, value, size, flags);
> +	return kernfs_xattr_set(kn, xattr_full_name(handler, args->name),
> +				args->value, args->size, args->flags);
>  }
>  
>  static const struct xattr_handler kernfs_trusted_xattr_handler = {
> diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
> index 1406858bae6c..1f0388440ec9 100644
> --- a/fs/nfs/nfs4proc.c
> +++ b/fs/nfs/nfs4proc.c
> @@ -7209,18 +7209,15 @@ nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
>  #define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
>  
>  static int nfs4_xattr_set_nfs4_acl(const struct xattr_handler *handler,
> -				   struct dentry *unused, struct inode *inode,
> -				   const char *key, const void *buf,
> -				   size_t buflen, int flags)
> +				   struct xattr_gs_args *args)
>  {
> -	return nfs4_proc_set_acl(inode, buf, buflen);
> +	return nfs4_proc_set_acl(args->inode, args->value, args->size);
>  }
>  
>  static int nfs4_xattr_get_nfs4_acl(const struct xattr_handler *handler,
> -				   struct dentry *unused, struct inode *inode,
> -				   const char *key, void *buf, size_t buflen)
> +				   struct xattr_gs_args *args)
>  {
> -	return nfs4_proc_get_acl(inode, buf, buflen);
> +	return nfs4_proc_get_acl(args->inode, args->buffer, args->size);
>  }
>  
>  static bool nfs4_xattr_list_nfs4_acl(struct dentry *dentry)
> @@ -7231,22 +7228,21 @@ static bool nfs4_xattr_list_nfs4_acl(struct dentry *dentry)
>  #ifdef CONFIG_NFS_V4_SECURITY_LABEL
>  
>  static int nfs4_xattr_set_nfs4_label(const struct xattr_handler *handler,
> -				     struct dentry *unused, struct inode *inode,
> -				     const char *key, const void *buf,
> -				     size_t buflen, int flags)
> +				     struct xattr_gs_args *args)
>  {
> -	if (security_ismaclabel(key))
> -		return nfs4_set_security_label(inode, buf, buflen);
> +	if (security_ismaclabel(args->name))
> +		return nfs4_set_security_label(args->inode,
> +					       args->value, args->size);
>  
>  	return -EOPNOTSUPP;
>  }
>  
>  static int nfs4_xattr_get_nfs4_label(const struct xattr_handler *handler,
> -				     struct dentry *unused, struct inode *inode,
> -				     const char *key, void *buf, size_t buflen)
> +				     struct xattr_gs_args *args)
>  {
> -	if (security_ismaclabel(key))
> -		return nfs4_get_security_label(inode, buf, buflen);
> +	if (security_ismaclabel(args->name))
> +		return nfs4_get_security_label(args->inode,
> +					       args->buffer, args->size);
>  	return -EOPNOTSUPP;
>  }
>  
> diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
> index 90c830e3758e..25ac1557e303 100644
> --- a/fs/ocfs2/xattr.c
> +++ b/fs/ocfs2/xattr.c
> @@ -7241,20 +7241,18 @@ int ocfs2_init_security_and_acl(struct inode *dir,
>   * 'security' attributes support
>   */
>  static int ocfs2_xattr_security_get(const struct xattr_handler *handler,
> -				    struct dentry *unused, struct inode *inode,
> -				    const char *name, void *buffer, size_t size)
> +				    struct xattr_gs_args *args)
>  {
> -	return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_SECURITY,
> -			       name, buffer, size);
> +	return ocfs2_xattr_get(args->inode, OCFS2_XATTR_INDEX_SECURITY,
> +			       args->name, args->buffer, args->size);
>  }
>  
>  static int ocfs2_xattr_security_set(const struct xattr_handler *handler,
> -				    struct dentry *unused, struct inode *inode,
> -				    const char *name, const void *value,
> -				    size_t size, int flags)
> +				    struct xattr_gs_args *args)
>  {
> -	return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
> -			       name, value, size, flags);
> +	return ocfs2_xattr_set(args->inode, OCFS2_XATTR_INDEX_SECURITY,
> +			       args->name, args->value, args->size,
> +			       args->flags);
>  }
>  
>  static int ocfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
> @@ -7313,20 +7311,18 @@ const struct xattr_handler ocfs2_xattr_security_handler = {
>   * 'trusted' attributes support
>   */
>  static int ocfs2_xattr_trusted_get(const struct xattr_handler *handler,
> -				   struct dentry *unused, struct inode *inode,
> -				   const char *name, void *buffer, size_t size)
> +				   struct xattr_gs_args *args)
>  {
> -	return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_TRUSTED,
> -			       name, buffer, size);
> +	return ocfs2_xattr_get(args->inode, OCFS2_XATTR_INDEX_TRUSTED,
> +			       args->name, args->buffer, args->size);
>  }
>  
>  static int ocfs2_xattr_trusted_set(const struct xattr_handler *handler,
> -				   struct dentry *unused, struct inode *inode,
> -				   const char *name, const void *value,
> -				   size_t size, int flags)
> +				   struct xattr_gs_args *args)
>  {
> -	return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_TRUSTED,
> -			       name, value, size, flags);
> +	return ocfs2_xattr_set(args->inode, OCFS2_XATTR_INDEX_TRUSTED,
> +			       args->name, args->value, args->size,
> +			       args->flags);
>  }
>  
>  const struct xattr_handler ocfs2_xattr_trusted_handler = {
> @@ -7339,29 +7335,27 @@ const struct xattr_handler ocfs2_xattr_trusted_handler = {
>   * 'user' attributes support
>   */
>  static int ocfs2_xattr_user_get(const struct xattr_handler *handler,
> -				struct dentry *unused, struct inode *inode,
> -				const char *name, void *buffer, size_t size)
> +				struct xattr_gs_args *args)
>  {
> -	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
> +	struct ocfs2_super *osb = OCFS2_SB(args->inode->i_sb);
>  
>  	if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
>  		return -EOPNOTSUPP;
> -	return ocfs2_xattr_get(inode, OCFS2_XATTR_INDEX_USER, name,
> -			       buffer, size);
> +	return ocfs2_xattr_get(args->inode, OCFS2_XATTR_INDEX_USER, args->name,
> +			       args->buffer, args->size);
>  }
>  
>  static int ocfs2_xattr_user_set(const struct xattr_handler *handler,
> -				struct dentry *unused, struct inode *inode,
> -				const char *name, const void *value,
> -				size_t size, int flags)
> +				struct xattr_gs_args *args)
>  {
> -	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
> +	struct ocfs2_super *osb = OCFS2_SB(args->inode->i_sb);
>  
>  	if (osb->s_mount_opt & OCFS2_MOUNT_NOUSERXATTR)
>  		return -EOPNOTSUPP;
>  
> -	return ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_USER,
> -			       name, value, size, flags);
> +	return ocfs2_xattr_set(args->inode, OCFS2_XATTR_INDEX_USER,
> +			       args->name, args->value, args->size,
> +			       args->flags);
>  }
>  
>  const struct xattr_handler ocfs2_xattr_user_handler = {
> diff --git a/fs/orangefs/xattr.c b/fs/orangefs/xattr.c
> index bdc285aea360..d222922af141 100644
> --- a/fs/orangefs/xattr.c
> +++ b/fs/orangefs/xattr.c
> @@ -526,24 +526,17 @@ ssize_t orangefs_listxattr(struct dentry *dentry, char *buffer, size_t size)
>  }
>  
>  static int orangefs_xattr_set_default(const struct xattr_handler *handler,
> -				      struct dentry *unused,
> -				      struct inode *inode,
> -				      const char *name,
> -				      const void *buffer,
> -				      size_t size,
> -				      int flags)
> +				      struct xattr_gs_args *args)
>  {
> -	return orangefs_inode_setxattr(inode, name, buffer, size, flags);
> +	return orangefs_inode_setxattr(args->inode, args->name,
> +				       args->value, args->size, args->flags);
>  }
>  
>  static int orangefs_xattr_get_default(const struct xattr_handler *handler,
> -				      struct dentry *unused,
> -				      struct inode *inode,
> -				      const char *name,
> -				      void *buffer,
> -				      size_t size)
> +				      struct xattr_gs_args *args)
>  {
> -	return orangefs_inode_getxattr(inode, name, buffer, size);
> +	return orangefs_inode_getxattr(args->inode, args->name,
> +				       args->buffer, args->size);
>  
>  }
>  
> diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
> index 7663aeb85fa3..a14d450b8564 100644
> --- a/fs/overlayfs/inode.c
> +++ b/fs/overlayfs/inode.c
> @@ -318,60 +318,61 @@ bool ovl_is_private_xattr(const char *name)
>  		       sizeof(OVL_XATTR_PREFIX) - 1) == 0;
>  }
>  
> -int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
> -		  const void *value, size_t size, int flags)
> +int ovl_xattr_set(struct xattr_gs_args *args)
>  {
>  	int err;
> -	struct dentry *upperdentry = ovl_i_dentry_upper(inode);
> -	struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry);
> +	struct dentry *upperdentry = ovl_i_dentry_upper(args->inode);
> +	struct dentry *realdentry =
> +		upperdentry ?: ovl_dentry_lower(args->dentry);
>  	const struct cred *old_cred;
>  
> -	err = ovl_want_write(dentry);
> +	err = ovl_want_write(args->dentry);
>  	if (err)
>  		goto out;
>  
> -	if (!value && !upperdentry) {
> -		err = vfs_getxattr(realdentry, name, NULL, 0);
> +	if (!args->value && !upperdentry) {
> +		err = vfs_getxattr(realdentry, args->name, NULL, 0);
>  		if (err < 0)
>  			goto out_drop_write;
>  	}
>  
>  	if (!upperdentry) {
> -		err = ovl_copy_up(dentry);
> +		err = ovl_copy_up(args->dentry);
>  		if (err)
>  			goto out_drop_write;
>  
> -		realdentry = ovl_dentry_upper(dentry);
> +		realdentry = ovl_dentry_upper(args->dentry);
>  	}
>  
> -	old_cred = ovl_override_creds(dentry->d_sb);
> -	if (value)
> -		err = vfs_setxattr(realdentry, name, value, size, flags);
> +	old_cred = ovl_override_creds(args->dentry->d_sb);
> +	if (args->value)
> +		err = vfs_setxattr(realdentry, args->name,
> +				   args->value, args->size, args->flags);
>  	else {
> -		WARN_ON(flags != XATTR_REPLACE);
> -		err = vfs_removexattr(realdentry, name);
> +		WARN_ON(args->flags != XATTR_REPLACE);
> +		err = vfs_removexattr(realdentry, args->name);
>  	}
>  	revert_creds(old_cred);
>  
>  	/* copy c/mtime */
> -	ovl_copyattr(d_inode(realdentry), inode);
> +	ovl_copyattr(d_inode(realdentry), args->inode);
>  
>  out_drop_write:
> -	ovl_drop_write(dentry);
> +	ovl_drop_write(args->dentry);
>  out:
>  	return err;
>  }
>  
> -int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
> -		  void *value, size_t size)
> +int ovl_xattr_get(struct xattr_gs_args *args)
>  {
>  	ssize_t res;
>  	const struct cred *old_cred;
>  	struct dentry *realdentry =
> -		ovl_i_dentry_upper(inode) ?: ovl_dentry_lower(dentry);
> +		ovl_i_dentry_upper(args->inode) ?:
> +		ovl_dentry_lower(args->dentry);
>  
> -	old_cred = ovl_override_creds(dentry->d_sb);
> -	res = vfs_getxattr(realdentry, name, value, size);
> +	old_cred = ovl_override_creds(args->dentry->d_sb);
> +	res = vfs_getxattr(realdentry, args->name, args->buffer, args->size);
>  	revert_creds(old_cred);
>  	return res;
>  }
> diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
> index 6934bcf030f0..c6a8ec049099 100644
> --- a/fs/overlayfs/overlayfs.h
> +++ b/fs/overlayfs/overlayfs.h
> @@ -353,10 +353,8 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr);
>  int ovl_getattr(const struct path *path, struct kstat *stat,
>  		u32 request_mask, unsigned int flags);
>  int ovl_permission(struct inode *inode, int mask);
> -int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
> -		  const void *value, size_t size, int flags);
> -int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
> -		  void *value, size_t size);
> +int ovl_xattr_set(struct xattr_gs_args *args);
> +int ovl_xattr_get(struct xattr_gs_args *args);
>  ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
>  struct posix_acl *ovl_get_acl(struct inode *inode, int type);
>  int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags);
> diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
> index b368e2e102fa..e41359ba9159 100644
> --- a/fs/overlayfs/super.c
> +++ b/fs/overlayfs/super.c
> @@ -853,26 +853,24 @@ static unsigned int ovl_split_lowerdirs(char *str)
>  
>  static int __maybe_unused
>  ovl_posix_acl_xattr_get(const struct xattr_handler *handler,
> -			struct dentry *dentry, struct inode *inode,
> -			const char *name, void *buffer, size_t size)
> +			struct xattr_gs_args *args)
>  {
> -	return ovl_xattr_get(dentry, inode, handler->name, buffer, size);
> +	return ovl_xattr_get(args);
>  }
>  
>  static int __maybe_unused
>  ovl_posix_acl_xattr_set(const struct xattr_handler *handler,
> -			struct dentry *dentry, struct inode *inode,
> -			const char *name, const void *value,
> -			size_t size, int flags)
> +			struct xattr_gs_args *args)
>  {
> -	struct dentry *workdir = ovl_workdir(dentry);
> -	struct inode *realinode = ovl_inode_real(inode);
> +	struct dentry *workdir = ovl_workdir(args->dentry);
> +	struct inode *realinode = ovl_inode_real(args->inode);
>  	struct posix_acl *acl = NULL;
>  	int err;
>  
>  	/* Check that everything is OK before copy-up */
> -	if (value) {
> -		acl = posix_acl_from_xattr(&init_user_ns, value, size);
> +	if (args->value) {
> +		acl = posix_acl_from_xattr(&init_user_ns,
> +					   args->value, args->size);
>  		if (IS_ERR(acl))
>  			return PTR_ERR(acl);
>  	}
> @@ -881,12 +879,13 @@ ovl_posix_acl_xattr_set(const struct xattr_handler *handler,
>  		goto out_acl_release;
>  	if (!realinode->i_op->set_acl)
>  		goto out_acl_release;
> -	if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) {
> +	if (handler->flags == ACL_TYPE_DEFAULT &&
> +	    !S_ISDIR(args->inode->i_mode)) {
>  		err = acl ? -EACCES : 0;
>  		goto out_acl_release;
>  	}
>  	err = -EPERM;
> -	if (!inode_owner_or_capable(inode))
> +	if (!inode_owner_or_capable(args->inode))
>  		goto out_acl_release;
>  
>  	posix_acl_release(acl);
> @@ -895,20 +894,20 @@ ovl_posix_acl_xattr_set(const struct xattr_handler *handler,
>  	 * Check if sgid bit needs to be cleared (actual setacl operation will
>  	 * be done with mounter's capabilities and so that won't do it for us).
>  	 */
> -	if (unlikely(inode->i_mode & S_ISGID) &&
> +	if (unlikely(args->inode->i_mode & S_ISGID) &&
>  	    handler->flags == ACL_TYPE_ACCESS &&
> -	    !in_group_p(inode->i_gid) &&
> -	    !capable_wrt_inode_uidgid(inode, CAP_FSETID)) {
> +	    !in_group_p(args->inode->i_gid) &&
> +	    !capable_wrt_inode_uidgid(args->inode, CAP_FSETID)) {
>  		struct iattr iattr = { .ia_valid = ATTR_KILL_SGID };
>  
> -		err = ovl_setattr(dentry, &iattr);
> +		err = ovl_setattr(args->dentry, &iattr);
>  		if (err)
>  			return err;
>  	}
>  
> -	err = ovl_xattr_set(dentry, inode, handler->name, value, size, flags);
> +	err = ovl_xattr_set(args);
>  	if (!err)
> -		ovl_copyattr(ovl_inode_real(inode), inode);
> +		ovl_copyattr(ovl_inode_real(args->inode), args->inode);
>  
>  	return err;
>  
> @@ -918,33 +917,27 @@ ovl_posix_acl_xattr_set(const struct xattr_handler *handler,
>  }
>  
>  static int ovl_own_xattr_get(const struct xattr_handler *handler,
> -			     struct dentry *dentry, struct inode *inode,
> -			     const char *name, void *buffer, size_t size)
> +			     struct xattr_gs_args *args)
>  {
>  	return -EOPNOTSUPP;
>  }
>  
>  static int ovl_own_xattr_set(const struct xattr_handler *handler,
> -			     struct dentry *dentry, struct inode *inode,
> -			     const char *name, const void *value,
> -			     size_t size, int flags)
> +			     struct xattr_gs_args *args)
>  {
>  	return -EOPNOTSUPP;
>  }
>  
>  static int ovl_other_xattr_get(const struct xattr_handler *handler,
> -			       struct dentry *dentry, struct inode *inode,
> -			       const char *name, void *buffer, size_t size)
> +			       struct xattr_gs_args *args)
>  {
> -	return ovl_xattr_get(dentry, inode, name, buffer, size);
> +	return ovl_xattr_get(args);
>  }
>  
>  static int ovl_other_xattr_set(const struct xattr_handler *handler,
> -			       struct dentry *dentry, struct inode *inode,
> -			       const char *name, const void *value,
> -			       size_t size, int flags)
> +			       struct xattr_gs_args *args)
>  {
> -	return ovl_xattr_set(dentry, inode, name, value, size, flags);
> +	return ovl_xattr_set(args);
>  }
>  
>  static const struct xattr_handler __maybe_unused
> diff --git a/fs/posix_acl.c b/fs/posix_acl.c
> index 84ad1c90d535..8cc7310386fe 100644
> --- a/fs/posix_acl.c
> +++ b/fs/posix_acl.c
> @@ -831,24 +831,24 @@ EXPORT_SYMBOL (posix_acl_to_xattr);
>  
>  static int
>  posix_acl_xattr_get(const struct xattr_handler *handler,
> -		    struct dentry *unused, struct inode *inode,
> -		    const char *name, void *value, size_t size)
> +		    struct xattr_gs_args *args)
>  {
>  	struct posix_acl *acl;
>  	int error;
>  
> -	if (!IS_POSIXACL(inode))
> +	if (!IS_POSIXACL(args->inode))
>  		return -EOPNOTSUPP;
> -	if (S_ISLNK(inode->i_mode))
> +	if (S_ISLNK(args->inode->i_mode))
>  		return -EOPNOTSUPP;
>  
> -	acl = get_acl(inode, handler->flags);
> +	acl = get_acl(args->inode, handler->flags);
>  	if (IS_ERR(acl))
>  		return PTR_ERR(acl);
>  	if (acl == NULL)
>  		return -ENODATA;
>  
> -	error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
> +	error = posix_acl_to_xattr(&init_user_ns, acl,
> +				   args->buffer, args->size);
>  	posix_acl_release(acl);
>  
>  	return error;
> @@ -878,19 +878,18 @@ EXPORT_SYMBOL(set_posix_acl);
>  
>  static int
>  posix_acl_xattr_set(const struct xattr_handler *handler,
> -		    struct dentry *unused, struct inode *inode,
> -		    const char *name, const void *value,
> -		    size_t size, int flags)
> +		    struct xattr_gs_args *args)
>  {
>  	struct posix_acl *acl = NULL;
>  	int ret;
>  
> -	if (value) {
> -		acl = posix_acl_from_xattr(&init_user_ns, value, size);
> +	if (args->value) {
> +		acl = posix_acl_from_xattr(&init_user_ns,
> +					   args->value, args->size);
>  		if (IS_ERR(acl))
>  			return PTR_ERR(acl);
>  	}
> -	ret = set_posix_acl(inode, handler->flags, acl);
> +	ret = set_posix_acl(args->inode, handler->flags, acl);
>  	posix_acl_release(acl);
>  	return ret;
>  }
> diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
> index b5b26d8a192c..b949a55b95bd 100644
> --- a/fs/reiserfs/xattr.c
> +++ b/fs/reiserfs/xattr.c
> @@ -765,7 +765,7 @@ reiserfs_xattr_get(struct inode *inode, const char *name, void *buffer,
>  /* This is the implementation for the xattr plugin infrastructure */
>  static inline const struct xattr_handler *
>  find_xattr_handler_prefix(const struct xattr_handler **handlers,
> -			   const char *name)
> +			  const char *name)
>  {
>  	const struct xattr_handler *xah;
>  
> diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
> index 20be9a0e5870..6d436ef207d1 100644
> --- a/fs/reiserfs/xattr_security.c
> +++ b/fs/reiserfs/xattr_security.c
> @@ -10,27 +10,25 @@
>  #include <linux/uaccess.h>
>  
>  static int
> -security_get(const struct xattr_handler *handler, struct dentry *unused,
> -	     struct inode *inode, const char *name, void *buffer, size_t size)
> +security_get(const struct xattr_handler *handler, struct xattr_gs_args *args)
>  {
> -	if (IS_PRIVATE(inode))
> +	if (IS_PRIVATE(args->inode))
>  		return -EPERM;
>  
> -	return reiserfs_xattr_get(inode, xattr_full_name(handler, name),
> -				  buffer, size);
> +	return reiserfs_xattr_get(args->inode,
> +				  xattr_full_name(handler, args->name),
> +				  args->buffer, args->size);
>  }
>  
>  static int
> -security_set(const struct xattr_handler *handler, struct dentry *unused,
> -	     struct inode *inode, const char *name, const void *buffer,
> -	     size_t size, int flags)
> +security_set(const struct xattr_handler *handler, struct xattr_gs_args *args)
>  {
> -	if (IS_PRIVATE(inode))
> +	if (IS_PRIVATE(args->inode))
>  		return -EPERM;
>  
> -	return reiserfs_xattr_set(inode,
> -				  xattr_full_name(handler, name),
> -				  buffer, size, flags);
> +	return reiserfs_xattr_set(args->inode,
> +				  xattr_full_name(handler, args->name),
> +				  args->value, args->size, args->flags);
>  }
>  
>  static bool security_list(struct dentry *dentry)
> diff --git a/fs/reiserfs/xattr_trusted.c b/fs/reiserfs/xattr_trusted.c
> index 5ed48da3d02b..46dfc6e2e150 100644
> --- a/fs/reiserfs/xattr_trusted.c
> +++ b/fs/reiserfs/xattr_trusted.c
> @@ -9,27 +9,25 @@
>  #include <linux/uaccess.h>
>  
>  static int
> -trusted_get(const struct xattr_handler *handler, struct dentry *unused,
> -	    struct inode *inode, const char *name, void *buffer, size_t size)
> +trusted_get(const struct xattr_handler *handler, struct xattr_gs_args *args)
>  {
> -	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
> +	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(args->inode))
>  		return -EPERM;
>  
> -	return reiserfs_xattr_get(inode, xattr_full_name(handler, name),
> -				  buffer, size);
> +	return reiserfs_xattr_get(args->inode,
> +				  xattr_full_name(handler, args->name),
> +				  args->buffer, args->size);
>  }
>  
>  static int
> -trusted_set(const struct xattr_handler *handler, struct dentry *unused,
> -	    struct inode *inode, const char *name, const void *buffer,
> -	    size_t size, int flags)
> +trusted_set(const struct xattr_handler *handler, struct xattr_gs_args *args)
>  {
> -	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
> +	if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(args->inode))
>  		return -EPERM;
>  
> -	return reiserfs_xattr_set(inode,
> -				  xattr_full_name(handler, name),
> -				  buffer, size, flags);
> +	return reiserfs_xattr_set(args->inode,
> +				  xattr_full_name(handler, args->name),
> +				  args->value, args->size, args->flags);
>  }
>  
>  static bool trusted_list(struct dentry *dentry)
> diff --git a/fs/reiserfs/xattr_user.c b/fs/reiserfs/xattr_user.c
> index a573ca45bacc..4a0bafe62d05 100644
> --- a/fs/reiserfs/xattr_user.c
> +++ b/fs/reiserfs/xattr_user.c
> @@ -8,25 +8,23 @@
>  #include <linux/uaccess.h>
>  
>  static int
> -user_get(const struct xattr_handler *handler, struct dentry *unused,
> -	 struct inode *inode, const char *name, void *buffer, size_t size)
> +user_get(const struct xattr_handler *handler, struct xattr_gs_args *args)
>  {
> -	if (!reiserfs_xattrs_user(inode->i_sb))
> +	if (!reiserfs_xattrs_user(args->inode->i_sb))
>  		return -EOPNOTSUPP;
> -	return reiserfs_xattr_get(inode, xattr_full_name(handler, name),
> -				  buffer, size);
> +	return reiserfs_xattr_get(args->inode,
> +				  xattr_full_name(handler, args->name),
> +				  args->buffer, args->size);
>  }
>  
>  static int
> -user_set(const struct xattr_handler *handler, struct dentry *unused,
> -	 struct inode *inode, const char *name, const void *buffer,
> -	 size_t size, int flags)
> +user_set(const struct xattr_handler *handler, struct xattr_gs_args *args)
>  {
> -	if (!reiserfs_xattrs_user(inode->i_sb))
> +	if (!reiserfs_xattrs_user(args->inode->i_sb))
>  		return -EOPNOTSUPP;
> -	return reiserfs_xattr_set(inode,
> -				  xattr_full_name(handler, name),
> -				  buffer, size, flags);
> +	return reiserfs_xattr_set(args->inode,
> +				  xattr_full_name(handler, args->name),
> +				  args->value, args->size, args->flags);
>  }
>  
>  static bool user_list(struct dentry *dentry)
> diff --git a/fs/squashfs/xattr.c b/fs/squashfs/xattr.c
> index e1e3f3dd5a06..c6403f187ced 100644
> --- a/fs/squashfs/xattr.c
> +++ b/fs/squashfs/xattr.c
> @@ -199,15 +199,11 @@ static int squashfs_xattr_get(struct inode *inode, int name_index,
>  	return err;
>  }
>  
> -
>  static int squashfs_xattr_handler_get(const struct xattr_handler *handler,
> -				      struct dentry *unused,
> -				      struct inode *inode,
> -				      const char *name,
> -				      void *buffer, size_t size)
> +				      struct xattr_gs_args *args)
>  {
> -	return squashfs_xattr_get(inode, handler->flags, name,
> -		buffer, size);
> +	return squashfs_xattr_get(args->inode, handler->flags, args->name,
> +				  args->buffer, args->size);
>  }
>  
>  /*
> diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
> index 9aefbb60074f..aec02d94f2d6 100644
> --- a/fs/ubifs/xattr.c
> +++ b/fs/ubifs/xattr.c
> @@ -668,30 +668,29 @@ int ubifs_init_security(struct inode *dentry, struct inode *inode,
>  #endif
>  
>  static int xattr_get(const struct xattr_handler *handler,
> -			   struct dentry *dentry, struct inode *inode,
> -			   const char *name, void *buffer, size_t size)
> +		     struct xattr_gs_args *args)
>  {
> -	dbg_gen("xattr '%s', ino %lu ('%pd'), buf size %zd", name,
> -		inode->i_ino, dentry, size);
> +	dbg_gen("xattr '%s', ino %lu ('%pd'), buf size %zd", args->name,
> +		args->inode->i_ino, args->dentry, args->size);
>  
> -	name = xattr_full_name(handler, name);
> -	return ubifs_xattr_get(inode, name, buffer, size);
> +	return ubifs_xattr_get(args->inode,
> +			       xattr_full_name(handler, args->name),
> +			       args->buffer, args->size);
>  }
>  
>  static int xattr_set(const struct xattr_handler *handler,
> -			   struct dentry *dentry, struct inode *inode,
> -			   const char *name, const void *value,
> -			   size_t size, int flags)
> +		     struct xattr_gs_args *args)
>  {
>  	dbg_gen("xattr '%s', host ino %lu ('%pd'), size %zd",
> -		name, inode->i_ino, dentry, size);
> -
> -	name = xattr_full_name(handler, name);
> -
> -	if (value)
> -		return ubifs_xattr_set(inode, name, value, size, flags, true);
> -	else
> -		return ubifs_xattr_remove(inode, name);
> +		args->name, args->inode->i_ino, args->dentry, args->size);
> +
> +	if (args->value)
> +		return ubifs_xattr_set(args->inode,
> +				       xattr_full_name(handler, args->name),
> +				       args->value, args->size,
> +				       args->flags, true);
> +	return ubifs_xattr_remove(args->inode,
> +				  xattr_full_name(handler, args->name));
>  }
>  
>  static const struct xattr_handler ubifs_user_xattr_handler = {
> diff --git a/fs/xattr.c b/fs/xattr.c
> index 90dd78f0eb27..dceb5afe79be 100644
> --- a/fs/xattr.c
> +++ b/fs/xattr.c
> @@ -135,19 +135,18 @@ xattr_permission(struct inode *inode, const char *name, int mask)
>  }
>  
>  int
> -__vfs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
> -	       const void *value, size_t size, int flags)
> +__vfs_setxattr(struct xattr_gs_args *args)
>  {
>  	const struct xattr_handler *handler;
>  
> -	handler = xattr_resolve_name(inode, &name);
> +	handler = xattr_resolve_name(args->inode, &args->name);
>  	if (IS_ERR(handler))
>  		return PTR_ERR(handler);
>  	if (!handler->set)
>  		return -EOPNOTSUPP;
> -	if (size == 0)
> -		value = "";  /* empty EA, do not remove */
> -	return handler->set(handler, dentry, inode, name, value, size, flags);
> +	if (args->size == 0)
> +		args->value = "";  /* empty EA, do not remove */
> +	return handler->set(handler, args);
>  }
>  EXPORT_SYMBOL(__vfs_setxattr);
>  
> @@ -178,7 +177,16 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name,
>  	if (issec)
>  		inode->i_flags &= ~S_NOSEC;
>  	if (inode->i_opflags & IOP_XATTR) {
> -		error = __vfs_setxattr(dentry, inode, name, value, size, flags);
> +		struct xattr_gs_args args = {
> +			.dentry = dentry,
> +			.inode = inode,
> +			.name = name,
> +			.value = value,
> +			.size = size,
> +			.flags = flags,
> +		};
> +
> +		error = __vfs_setxattr(&args);
>  		if (!error) {
>  			fsnotify_xattr(dentry);
>  			security_inode_post_setxattr(dentry, name, value,
> @@ -268,68 +276,61 @@ vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
>  		   size_t xattr_size, gfp_t flags)
>  {
>  	const struct xattr_handler *handler;
> -	struct inode *inode = dentry->d_inode;
> -	char *value = *xattr_value;
> +	struct xattr_gs_args args;
>  	int error;
>  
> -	error = xattr_permission(inode, name, MAY_READ);
> +	error = xattr_permission(dentry->d_inode, name, MAY_READ);
>  	if (error)
>  		return error;
>  
> -	handler = xattr_resolve_name(inode, &name);
> +	handler = xattr_resolve_name(dentry->d_inode, &name);
>  	if (IS_ERR(handler))
>  		return PTR_ERR(handler);
>  	if (!handler->get)
>  		return -EOPNOTSUPP;
> -	error = handler->get(handler, dentry, inode, name, NULL, 0);
> +	memset(&args, 0, sizeof(args));
> +	args.inode = dentry->d_inode;
> +	args.dentry = dentry;
> +	args.name = name;
> +	error = handler->get(handler, &args);
>  	if (error < 0)
>  		return error;
>  
> -	if (!value || (error > xattr_size)) {
> -		value = krealloc(*xattr_value, error + 1, flags);
> -		if (!value)
> +	args.buffer = *xattr_value;
> +	if (!*xattr_value || (error > xattr_size)) {
> +		args.buffer = krealloc(*xattr_value, error + 1, flags);
> +		if (!args.buffer)
>  			return -ENOMEM;
> -		memset(value, 0, error + 1);
> +		memset(args.buffer, 0, error + 1);
>  	}
>  
> -	error = handler->get(handler, dentry, inode, name, value, error);
> -	*xattr_value = value;
> +	args.size = error;
> +	error = handler->get(handler, &args);
> +	*xattr_value = args.buffer;
>  	return error;
>  }
>  
>  ssize_t
> -__vfs_getxattr(struct dentry *dentry, struct inode *inode, const char *name,
> -	       void *value, size_t size)
> +__vfs_getxattr(struct xattr_gs_args *args)
>  {
>  	const struct xattr_handler *handler;
> -
> -	handler = xattr_resolve_name(inode, &name);
> -	if (IS_ERR(handler))
> -		return PTR_ERR(handler);
> -	if (!handler->get)
> -		return -EOPNOTSUPP;
> -	return handler->get(handler, dentry, inode, name, value, size);
> -}
> -EXPORT_SYMBOL(__vfs_getxattr);
> -
> -ssize_t
> -vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
> -{
> -	struct inode *inode = dentry->d_inode;
>  	int error;
>  
> -	error = xattr_permission(inode, name, MAY_READ);
> +	if (args->flags & XATTR_NOSECURITY)
> +		goto nolsm;
> +	error = xattr_permission(args->inode, args->name, MAY_READ);
>  	if (error)
>  		return error;
>  
> -	error = security_inode_getxattr(dentry, name);
> +	error = security_inode_getxattr(args->dentry, args->name);
>  	if (error)
>  		return error;
>  
> -	if (!strncmp(name, XATTR_SECURITY_PREFIX,
> +	if (!strncmp(args->name, XATTR_SECURITY_PREFIX,
>  				XATTR_SECURITY_PREFIX_LEN)) {
> -		const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
> -		int ret = xattr_getsecurity(inode, suffix, value, size);
> +		const char *suffix = args->name + XATTR_SECURITY_PREFIX_LEN;
> +		int ret = xattr_getsecurity(args->inode, suffix,
> +					    args->buffer, args->size);
>  		/*
>  		 * Only overwrite the return value if a security module
>  		 * is actually active.
> @@ -339,7 +340,27 @@ vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
>  		return ret;
>  	}
>  nolsm:
> -	return __vfs_getxattr(dentry, inode, name, value, size);
> +	handler = xattr_resolve_name(args->inode, &args->name);
> +	if (IS_ERR(handler))
> +		return PTR_ERR(handler);
> +	if (!handler->get)
> +		return -EOPNOTSUPP;
> +	return handler->get(handler, args);
> +}
> +EXPORT_SYMBOL(__vfs_getxattr);
> +
> +ssize_t
> +vfs_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
> +{
> +	struct xattr_gs_args args = {
> +		.dentry = dentry,
> +		.inode = dentry->d_inode,
> +		.name = name,
> +		.buffer = buffer,
> +		.size = size,
> +	};
> +
> +	return __vfs_getxattr(&args);
>  }
>  EXPORT_SYMBOL_GPL(vfs_getxattr);
>  
> @@ -366,15 +387,20 @@ EXPORT_SYMBOL_GPL(vfs_listxattr);
>  int
>  __vfs_removexattr(struct dentry *dentry, const char *name)
>  {
> -	struct inode *inode = d_inode(dentry);
>  	const struct xattr_handler *handler;
> +	struct xattr_gs_args args;
>  
> -	handler = xattr_resolve_name(inode, &name);
> +	handler = xattr_resolve_name(d_inode(dentry), &name);
>  	if (IS_ERR(handler))
>  		return PTR_ERR(handler);
>  	if (!handler->set)
>  		return -EOPNOTSUPP;
> -	return handler->set(handler, dentry, inode, name, NULL, 0, XATTR_REPLACE);
> +	memset(&args, 0, sizeof(args));
> +	args.dentry = dentry;
> +	args.inode = d_inode(dentry);
> +	args.name = name;
> +	args.flags = XATTR_REPLACE;
> +	return handler->set(handler, &args);
>  }
>  EXPORT_SYMBOL(__vfs_removexattr);
>  
> diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
> index d48fcf11cc35..60fec712f60b 100644
> --- a/fs/xfs/libxfs/xfs_attr.c
> +++ b/fs/xfs/libxfs/xfs_attr.c
> @@ -305,7 +305,7 @@ int
>  xfs_attr_set(
>  	struct xfs_inode	*dp,
>  	const unsigned char	*name,
> -	unsigned char		*value,
> +	const unsigned char	*value,
>  	int			valuelen,
>  	int			flags)
>  {
> @@ -324,7 +324,7 @@ xfs_attr_set(
>  	if (error)
>  		return error;
>  
> -	args.value = value;
> +	args.value = (unsigned char *)value;
>  	args.valuelen = valuelen;
>  	args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT;
>  	args.total = xfs_attr_calc_size(&args, &local);
> diff --git a/fs/xfs/libxfs/xfs_attr.h b/fs/xfs/libxfs/xfs_attr.h
> index ff28ebf3b635..afe184e5fb01 100644
> --- a/fs/xfs/libxfs/xfs_attr.h
> +++ b/fs/xfs/libxfs/xfs_attr.h
> @@ -145,7 +145,7 @@ int xfs_attr_get_ilocked(struct xfs_inode *ip, struct xfs_da_args *args);
>  int xfs_attr_get(struct xfs_inode *ip, const unsigned char *name,
>  		 unsigned char *value, int *valuelenp, int flags);
>  int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
> -		 unsigned char *value, int valuelen, int flags);
> +		 const unsigned char *value, int valuelen, int flags);
>  int xfs_attr_set_args(struct xfs_da_args *args);
>  int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
>  int xfs_attr_remove_args(struct xfs_da_args *args);
> diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
> index 3123b5aaad2a..313a828a3d1f 100644
> --- a/fs/xfs/xfs_xattr.c
> +++ b/fs/xfs/xfs_xattr.c
> @@ -17,20 +17,20 @@
>  
>  
>  static int
> -xfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused,
> -		struct inode *inode, const char *name, void *value, size_t size)
> +xfs_xattr_get(const struct xattr_handler *handler, struct xattr_gs_args *args)
>  {
>  	int xflags = handler->flags;
> -	struct xfs_inode *ip = XFS_I(inode);
> -	int error, asize = size;
> +	struct xfs_inode *ip = XFS_I(args->inode);
> +	int error, asize = args->size;
>  
>  	/* Convert Linux syscall to XFS internal ATTR flags */
> -	if (!size) {
> +	if (!args->size) {
>  		xflags |= ATTR_KERNOVAL;
> -		value = NULL;
> +		args->buffer = NULL;
>  	}
>  
> -	error = xfs_attr_get(ip, (unsigned char *)name, value, &asize, xflags);
> +	error = xfs_attr_get(ip, (const unsigned char *)args->name,
> +			     args->buffer, &asize, xflags);
>  	if (error)
>  		return error;
>  	return asize;
> @@ -59,26 +59,25 @@ xfs_forget_acl(
>  }
>  
>  static int
> -xfs_xattr_set(const struct xattr_handler *handler, struct dentry *unused,
> -		struct inode *inode, const char *name, const void *value,
> -		size_t size, int flags)
> +xfs_xattr_set(const struct xattr_handler *handler, struct xattr_gs_args *args)
>  {
>  	int			xflags = handler->flags;
> -	struct xfs_inode	*ip = XFS_I(inode);
> +	struct xfs_inode	*ip = XFS_I(args->inode);
>  	int			error;
>  
>  	/* Convert Linux syscall to XFS internal ATTR flags */
> -	if (flags & XATTR_CREATE)
> +	if (args->flags & XATTR_CREATE)
>  		xflags |= ATTR_CREATE;
> -	if (flags & XATTR_REPLACE)
> +	if (args->flags & XATTR_REPLACE)
>  		xflags |= ATTR_REPLACE;
>  
> -	if (!value)
> -		return xfs_attr_remove(ip, (unsigned char *)name, xflags);
> -	error = xfs_attr_set(ip, (unsigned char *)name,
> -				(void *)value, size, xflags);
> +	if (!args->value)
> +		return xfs_attr_remove(ip, (const unsigned char *)args->name,
> +				       xflags);
> +	error = xfs_attr_set(ip, (const unsigned char *)args->name,
> +			     args->value, args->size, xflags);
>  	if (!error)
> -		xfs_forget_acl(inode, name, xflags);
> +		xfs_forget_acl(args->inode, args->name, xflags);
>  
>  	return error;
>  }
> diff --git a/include/linux/xattr.h b/include/linux/xattr.h
> index 6dad031be3c2..b2afbdcf000f 100644
> --- a/include/linux/xattr.h
> +++ b/include/linux/xattr.h
> @@ -25,17 +25,27 @@ struct dentry;
>   * name.  When @prefix is set instead, match attributes with that prefix and
>   * with a non-empty suffix.
>   */
> +struct xattr_gs_args {
> +	struct dentry *dentry;
> +	struct inode *inode;
> +	const char *name;
> +	union {
> +		void *buffer;
> +		const void *value;
> +	};
> +	size_t size;
> +	int flags;
> +};
> +
>  struct xattr_handler {
>  	const char *name;
>  	const char *prefix;
>  	int flags;      /* fs private flags */
>  	bool (*list)(struct dentry *dentry);
> -	int (*get)(const struct xattr_handler *, struct dentry *dentry,
> -		   struct inode *inode, const char *name, void *buffer,
> -		   size_t size);
> -	int (*set)(const struct xattr_handler *, struct dentry *dentry,
> -		   struct inode *inode, const char *name, const void *buffer,
> -		   size_t size, int flags);
> +	int (*get)(const struct xattr_handler *handler,
> +		   struct xattr_gs_args *args);
> +	int (*set)(const struct xattr_handler *handler,
> +		   struct xattr_gs_args *args);
>  };
>  
>  const char *xattr_full_name(const struct xattr_handler *, const char *);
> @@ -46,10 +56,10 @@ struct xattr {
>  	size_t value_len;
>  };
>  
> -ssize_t __vfs_getxattr(struct dentry *, struct inode *, const char *, void *, size_t);
> +ssize_t __vfs_getxattr(struct xattr_gs_args *args);
>  ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
>  ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
> -int __vfs_setxattr(struct dentry *, struct inode *, const char *, const void *, size_t, int);
> +int __vfs_setxattr(struct xattr_gs_args *args);
>  int __vfs_setxattr_noperm(struct dentry *, const char *, const void *, size_t, int);
>  int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
>  int __vfs_removexattr(struct dentry *, const char *);
> diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h
> index c1395b5bd432..1eba02616274 100644
> --- a/include/uapi/linux/xattr.h
> +++ b/include/uapi/linux/xattr.h
> @@ -17,8 +17,11 @@
>  #if __UAPI_DEF_XATTR
>  #define __USE_KERNEL_XATTR_DEFS
>  
> -#define XATTR_CREATE	0x1	/* set value, fail if attr already exists */
> -#define XATTR_REPLACE	0x2	/* set value, fail if attr does not exist */
> +#define XATTR_CREATE	 0x1	/* set value, fail if attr already exists */
> +#define XATTR_REPLACE	 0x2	/* set value, fail if attr does not exist */
> +#ifdef __KERNEL__ /* following is kernel internal, colocated for maintenance */
> +#define XATTR_NOSECURITY 0x4	/* get value, do not involve security check */
> +#endif
>  #endif
>  
>  /* Namespaces */
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 2bed4761f279..c84687f57e43 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -3205,24 +3205,23 @@ static int shmem_initxattrs(struct inode *inode,
>  }
>  
>  static int shmem_xattr_handler_get(const struct xattr_handler *handler,
> -				   struct dentry *unused, struct inode *inode,
> -				   const char *name, void *buffer, size_t size)
> +				   struct xattr_gs_args *args)
>  {
> -	struct shmem_inode_info *info = SHMEM_I(inode);
> +	struct shmem_inode_info *info = SHMEM_I(args->inode);
>  
> -	name = xattr_full_name(handler, name);
> -	return simple_xattr_get(&info->xattrs, name, buffer, size);
> +	return simple_xattr_get(&info->xattrs,
> +				xattr_full_name(handler, args->name),
> +				args->buffer, args->size);
>  }
>  
>  static int shmem_xattr_handler_set(const struct xattr_handler *handler,
> -				   struct dentry *unused, struct inode *inode,
> -				   const char *name, const void *value,
> -				   size_t size, int flags)
> +				   struct xattr_gs_args *args)
>  {
> -	struct shmem_inode_info *info = SHMEM_I(inode);
> +	struct shmem_inode_info *info = SHMEM_I(args->inode);
>  
> -	name = xattr_full_name(handler, name);
> -	return simple_xattr_set(&info->xattrs, name, value, size, flags);
> +	return simple_xattr_set(&info->xattrs,
> +				xattr_full_name(handler, args->name),
> +				args->value, args->size, args->flags);
>  }
>  
>  static const struct xattr_handler shmem_security_xattr_handler = {
> diff --git a/net/socket.c b/net/socket.c
> index 6a9ab7a8b1d2..7920caece7cc 100644
> --- a/net/socket.c
> +++ b/net/socket.c
> @@ -299,15 +299,15 @@ static const struct dentry_operations sockfs_dentry_operations = {
>  };
>  
>  static int sockfs_xattr_get(const struct xattr_handler *handler,
> -			    struct dentry *dentry, struct inode *inode,
> -			    const char *suffix, void *value, size_t size)
> +			    struct xattr_gs_args *args)
>  {
> -	if (value) {
> -		if (dentry->d_name.len + 1 > size)
> +	if (args->buffer) {
> +		if (args->dentry->d_name.len + 1 > args->size)
>  			return -ERANGE;
> -		memcpy(value, dentry->d_name.name, dentry->d_name.len + 1);
> +		memcpy(args->buffer, args->dentry->d_name.name,
> +		       args->dentry->d_name.len + 1);
>  	}
> -	return dentry->d_name.len + 1;
> +	return args->dentry->d_name.len + 1;
>  }
>  
>  #define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
> @@ -320,9 +320,7 @@ static const struct xattr_handler sockfs_xattr_handler = {
>  };
>  
>  static int sockfs_security_xattr_set(const struct xattr_handler *handler,
> -				     struct dentry *dentry, struct inode *inode,
> -				     const char *suffix, const void *value,
> -				     size_t size, int flags)
> +				     struct xattr_gs_args *args)
>  {
>  	/* Handled by LSM. */
>  	return -EAGAIN;
> diff --git a/security/commoncap.c b/security/commoncap.c
> index f4ee0ae106b2..c58b684d5d9a 100644
> --- a/security/commoncap.c
> +++ b/security/commoncap.c
> @@ -294,11 +294,15 @@ int cap_capset(struct cred *new,
>   */
>  int cap_inode_need_killpriv(struct dentry *dentry)
>  {
> -	struct inode *inode = d_backing_inode(dentry);
> -	int error;
> +	struct xattr_gs_args args;
> +
> +	memset(&args, 0, sizeof(args));
> +	args.dentry = dentry;
> +	args.inode = d_backing_inode(dentry);
> +	args.name = XATTR_NAME_CAPS;
> +	args.flags = XATTR_NOSECURITY;
>  
> -	error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);
> -	return error > 0;
> +	return __vfs_getxattr(&args) > 0;
>  }
>  
>  /**
> @@ -570,7 +574,7 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
>   */
>  int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps)
>  {
> -	struct inode *inode = d_backing_inode(dentry);
> +	struct xattr_gs_args args;
>  	__u32 magic_etc;
>  	unsigned tocopy, i;
>  	int size;
> @@ -580,13 +584,20 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data
>  	struct user_namespace *fs_ns;
>  
>  	memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data));
> +	memset(&args, 0, sizeof(args));
>  
> -	if (!inode)
> +	args.dentry = (struct dentry *)dentry;
> +	args.inode = d_backing_inode(args.dentry);
> +	if (!args.inode)
>  		return -ENODATA;
>  
> -	fs_ns = inode->i_sb->s_user_ns;
> -	size = __vfs_getxattr((struct dentry *)dentry, inode,
> -			      XATTR_NAME_CAPS, &data, XATTR_CAPS_SZ);
> +	fs_ns = args.inode->i_sb->s_user_ns;
> +
> +	args.name = XATTR_NAME_CAPS;
> +	args.buffer = &data;
> +	args.size = XATTR_CAPS_SZ;
> +	args.flags = XATTR_NOSECURITY;
> +	size = __vfs_getxattr(&args);
>  	if (size == -ENODATA || size == -EOPNOTSUPP)
>  		/* no data, that's ok */
>  		return -ENODATA;
> diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
> index f9a81b187fae..a53ef9281186 100644
> --- a/security/integrity/evm/evm_main.c
> +++ b/security/integrity/evm/evm_main.c
> @@ -91,16 +91,23 @@ static bool evm_key_loaded(void)
>  
>  static int evm_find_protected_xattrs(struct dentry *dentry)
>  {
> -	struct inode *inode = d_backing_inode(dentry);
> +	struct xattr_gs_args args;
>  	struct xattr_list *xattr;
>  	int error;
>  	int count = 0;
>  
> -	if (!(inode->i_opflags & IOP_XATTR))
> +	memset(&args, 0, sizeof(args));
> +	args.dentry = dentry;
> +	args.inode = d_backing_inode(dentry);
> +
> +	if (!(args.inode->i_opflags & IOP_XATTR))
>  		return -EOPNOTSUPP;
>  
> +	args.flags = XATTR_NOSECURITY;
> +
>  	list_for_each_entry_rcu(xattr, &evm_config_xattrnames, list) {
> -		error = __vfs_getxattr(dentry, inode, xattr->name, NULL, 0);
> +		args.name = xattr->name;
> +		error = __vfs_getxattr(&args);
>  		if (error < 0) {
>  			if (error == -ENODATA)
>  				continue;
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 74dd46de01b6..23c3a2c468f7 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -540,6 +540,8 @@ static int sb_finish_set_opts(struct super_block *sb)
>  	int rc = 0;
>  
>  	if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
> +		struct xattr_gs_args args;
> +
>  		/* Make sure that the xattr handler exists and that no
>  		   error other than -ENODATA is returned by getxattr on
>  		   the root directory.  -ENODATA is ok, as this may be
> @@ -552,7 +554,12 @@ static int sb_finish_set_opts(struct super_block *sb)
>  			goto out;
>  		}
>  
> -		rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0);
> +		memset(&args, 0, sizeof(args));
> +		args.dentry = root;
> +		args.inode = root_inode;
> +		args.name = XATTR_NAME_SELINUX;
> +		args.flags = XATTR_NOSECURITY;
> +		rc = __vfs_getxattr(&args);
>  		if (rc < 0 && rc != -ENODATA) {
>  			if (rc == -EOPNOTSUPP)
>  				pr_warn("SELinux: (dev %s, type "
> @@ -1371,6 +1378,7 @@ static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
>  	char *context;
>  	unsigned int len;
>  	int rc;
> +	struct xattr_gs_args args;
>  
>  	len = INITCONTEXTLEN;
>  	context = kmalloc(len + 1, GFP_NOFS);
> @@ -1378,12 +1386,21 @@ static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
>  		return -ENOMEM;
>  
>  	context[len] = '\0';
> -	rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, context, len);
> +	memset(&args, 0, sizeof(args));
> +	args.dentry = dentry;
> +	args.inode = inode;
> +	args.name = XATTR_NAME_SELINUX;
> +	args.buffer = context;
> +	args.size = len;
> +	args.flags = XATTR_NOSECURITY;
> +	rc = __vfs_getxattr(&args);
>  	if (rc == -ERANGE) {
>  		kfree(context);
>  
>  		/* Need a larger buffer.  Query for the right size. */
> -		rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX, NULL, 0);
> +		args.buffer = NULL;
> +		args.size = 0;
> +		rc = __vfs_getxattr(&args);
>  		if (rc < 0)
>  			return rc;
>  
> @@ -1393,8 +1410,9 @@ static int inode_doinit_use_xattr(struct inode *inode, struct dentry *dentry,
>  			return -ENOMEM;
>  
>  		context[len] = '\0';
> -		rc = __vfs_getxattr(dentry, inode, XATTR_NAME_SELINUX,
> -				    context, len);
> +		args.buffer = context;
> +		args.size = len;
> +		rc = __vfs_getxattr(&args);
>  	}
>  	if (rc < 0) {
>  		kfree(context);
> diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
> index 4c5e5a438f8b..91e585bd1823 100644
> --- a/security/smack/smack_lsm.c
> +++ b/security/smack/smack_lsm.c
> @@ -282,25 +282,32 @@ static struct smack_known *smk_fetch(const char *name, struct inode *ip,
>  					struct dentry *dp)
>  {
>  	int rc;
> -	char *buffer;
>  	struct smack_known *skp = NULL;
> +	struct xattr_gs_args args;
>  
>  	if (!(ip->i_opflags & IOP_XATTR))
>  		return ERR_PTR(-EOPNOTSUPP);
>  
> -	buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
> -	if (buffer == NULL)
> +	memset(&args, 0, sizeof(args));
> +	args.dentry = dp;
> +	args.inode = ip;
> +	args.name = name;
> +	args.buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL);
> +	args.size = SMK_LONGLABEL;
> +	args.flags = XATTR_NOSECURITY;
> +
> +	if (args.buffer == NULL)
>  		return ERR_PTR(-ENOMEM);
>  
> -	rc = __vfs_getxattr(dp, ip, name, buffer, SMK_LONGLABEL);
> +	rc = __vfs_getxattr(&args);
>  	if (rc < 0)
>  		skp = ERR_PTR(rc);
>  	else if (rc == 0)
>  		skp = NULL;
>  	else
> -		skp = smk_import_entry(buffer, rc);
> +		skp = smk_import_entry(args.buffer, rc);
>  
> -	kfree(buffer);
> +	kfree(args.buffer);
>  
>  	return skp;
>  }
> @@ -3424,6 +3431,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
>  		 * Transmuting directory
>  		 */
>  		if (S_ISDIR(inode->i_mode)) {
> +			struct xattr_gs_args args;
> +
>  			/*
>  			 * If this is a new directory and the label was
>  			 * transmuted when the inode was initialized
> @@ -3433,16 +3442,19 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
>  			 * If there is a transmute attribute on the
>  			 * directory mark the inode.
>  			 */
> +			memset(&args, 0, sizeof(args));
> +			args.dentry = dp;
> +			args.inode = inode;
> +			args.name = XATTR_NAME_SMACKTRANSMUTE;
> +			args.size = TRANS_TRUE_SIZE;
>  			if (isp->smk_flags & SMK_INODE_CHANGED) {
>  				isp->smk_flags &= ~SMK_INODE_CHANGED;
> -				rc = __vfs_setxattr(dp, inode,
> -					XATTR_NAME_SMACKTRANSMUTE,
> -					TRANS_TRUE, TRANS_TRUE_SIZE,
> -					0);
> +				args.value = TRANS_TRUE;
> +				rc = __vfs_setxattr(&args);
>  			} else {
> -				rc = __vfs_getxattr(dp, inode,
> -					XATTR_NAME_SMACKTRANSMUTE, trattr,
> -					TRANS_TRUE_SIZE);
> +				args.buffer = trattr;
> +				args.flags = XATTR_NOSECURITY;
> +				rc = __vfs_getxattr(&args);
>  				if (rc >= 0 && strncmp(trattr, TRANS_TRUE,
>  						       TRANS_TRUE_SIZE) != 0)
>  					rc = -EINVAL;
> -- 
> 2.23.0.187.g17f5b7556c-goog
> 


More information about the Linux-erofs mailing list