]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 10 Aug 2020 12:11:33 +0000 (14:11 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 10 Aug 2020 12:11:33 +0000 (14:11 +0200)
added patches:
xattr-break-delegations-in-set-remove-xattr.patch

queue-4.19/series
queue-4.19/xattr-break-delegations-in-set-remove-xattr.patch [new file with mode: 0644]

index 7d2a785751d83a1a0a84b4e5f255a300ec94f2e4..59f470b4a0dee08014455eb0d31768dcfc50c6f6 100644 (file)
@@ -28,3 +28,4 @@ igb-reinit_locked-should-be-called-with-rtnl_lock.patch
 atm-fix-atm_dev-refcnt-leaks-in-atmtcp_remove_persis.patch
 tools-lib-traceevent-fix-memory-leak-in-process_dyna.patch
 drivers-hv-vmbus-ignore-channelmsg_tl_connect_result.patch
+xattr-break-delegations-in-set-remove-xattr.patch
diff --git a/queue-4.19/xattr-break-delegations-in-set-remove-xattr.patch b/queue-4.19/xattr-break-delegations-in-set-remove-xattr.patch
new file mode 100644 (file)
index 0000000..ca68ec6
--- /dev/null
@@ -0,0 +1,181 @@
+From 08b5d5014a27e717826999ad20e394a8811aae92 Mon Sep 17 00:00:00 2001
+From: Frank van der Linden <fllinden@amazon.com>
+Date: Tue, 23 Jun 2020 22:39:18 +0000
+Subject: xattr: break delegations in {set,remove}xattr
+
+From: Frank van der Linden <fllinden@amazon.com>
+
+commit 08b5d5014a27e717826999ad20e394a8811aae92 upstream.
+
+set/removexattr on an exported filesystem should break NFS delegations.
+This is true in general, but also for the upcoming support for
+RFC 8726 (NFSv4 extended attribute support). Make sure that they do.
+
+Additionally, they need to grow a _locked variant, since callers might
+call this with i_rwsem held (like the NFS server code).
+
+Cc: stable@vger.kernel.org # v4.9+
+Cc: linux-fsdevel@vger.kernel.org
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Frank van der Linden <fllinden@amazon.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/xattr.c            |   84 +++++++++++++++++++++++++++++++++++++++++++++-----
+ include/linux/xattr.h |    2 +
+ 2 files changed, 79 insertions(+), 7 deletions(-)
+
+--- a/fs/xattr.c
++++ b/fs/xattr.c
+@@ -203,10 +203,22 @@ int __vfs_setxattr_noperm(struct dentry
+       return error;
+ }
+-
++/**
++ * __vfs_setxattr_locked: set an extended attribute while holding the inode
++ * lock
++ *
++ *  @dentry - object to perform setxattr on
++ *  @name - xattr name to set
++ *  @value - value to set @name to
++ *  @size - size of @value
++ *  @flags - flags to pass into filesystem operations
++ *  @delegated_inode - on return, will contain an inode pointer that
++ *  a delegation was broken on, NULL if none.
++ */
+ int
+-vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
+-              size_t size, int flags)
++__vfs_setxattr_locked(struct dentry *dentry, const char *name,
++              const void *value, size_t size, int flags,
++              struct inode **delegated_inode)
+ {
+       struct inode *inode = dentry->d_inode;
+       int error;
+@@ -215,15 +227,40 @@ vfs_setxattr(struct dentry *dentry, cons
+       if (error)
+               return error;
+-      inode_lock(inode);
+       error = security_inode_setxattr(dentry, name, value, size, flags);
+       if (error)
+               goto out;
++      error = try_break_deleg(inode, delegated_inode);
++      if (error)
++              goto out;
++
+       error = __vfs_setxattr_noperm(dentry, name, value, size, flags);
+ out:
++      return error;
++}
++EXPORT_SYMBOL_GPL(__vfs_setxattr_locked);
++
++int
++vfs_setxattr(struct dentry *dentry, const char *name, const void *value,
++              size_t size, int flags)
++{
++      struct inode *inode = dentry->d_inode;
++      struct inode *delegated_inode = NULL;
++      int error;
++
++retry_deleg:
++      inode_lock(inode);
++      error = __vfs_setxattr_locked(dentry, name, value, size, flags,
++          &delegated_inode);
+       inode_unlock(inode);
++
++      if (delegated_inode) {
++              error = break_deleg_wait(&delegated_inode);
++              if (!error)
++                      goto retry_deleg;
++      }
+       return error;
+ }
+ EXPORT_SYMBOL_GPL(vfs_setxattr);
+@@ -377,8 +414,18 @@ __vfs_removexattr(struct dentry *dentry,
+ }
+ EXPORT_SYMBOL(__vfs_removexattr);
++/**
++ * __vfs_removexattr_locked: set an extended attribute while holding the inode
++ * lock
++ *
++ *  @dentry - object to perform setxattr on
++ *  @name - name of xattr to remove
++ *  @delegated_inode - on return, will contain an inode pointer that
++ *  a delegation was broken on, NULL if none.
++ */
+ int
+-vfs_removexattr(struct dentry *dentry, const char *name)
++__vfs_removexattr_locked(struct dentry *dentry, const char *name,
++              struct inode **delegated_inode)
+ {
+       struct inode *inode = dentry->d_inode;
+       int error;
+@@ -387,11 +434,14 @@ vfs_removexattr(struct dentry *dentry, c
+       if (error)
+               return error;
+-      inode_lock(inode);
+       error = security_inode_removexattr(dentry, name);
+       if (error)
+               goto out;
++      error = try_break_deleg(inode, delegated_inode);
++      if (error)
++              goto out;
++
+       error = __vfs_removexattr(dentry, name);
+       if (!error) {
+@@ -400,12 +450,32 @@ vfs_removexattr(struct dentry *dentry, c
+       }
+ out:
++      return error;
++}
++EXPORT_SYMBOL_GPL(__vfs_removexattr_locked);
++
++int
++vfs_removexattr(struct dentry *dentry, const char *name)
++{
++      struct inode *inode = dentry->d_inode;
++      struct inode *delegated_inode = NULL;
++      int error;
++
++retry_deleg:
++      inode_lock(inode);
++      error = __vfs_removexattr_locked(dentry, name, &delegated_inode);
+       inode_unlock(inode);
++
++      if (delegated_inode) {
++              error = break_deleg_wait(&delegated_inode);
++              if (!error)
++                      goto retry_deleg;
++      }
++
+       return error;
+ }
+ EXPORT_SYMBOL_GPL(vfs_removexattr);
+-
+ /*
+  * Extended attribute SET operations
+  */
+--- a/include/linux/xattr.h
++++ b/include/linux/xattr.h
+@@ -51,8 +51,10 @@ ssize_t vfs_getxattr(struct dentry *, co
+ 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_noperm(struct dentry *, const char *, const void *, size_t, int);
++int __vfs_setxattr_locked(struct dentry *, const char *, const void *, size_t, int, struct inode **);
+ int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int);
+ int __vfs_removexattr(struct dentry *, const char *);
++int __vfs_removexattr_locked(struct dentry *, const char *, struct inode **);
+ int vfs_removexattr(struct dentry *, const char *);
+ ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);