]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 Jul 2019 09:49:59 +0000 (11:49 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 31 Jul 2019 09:49:59 +0000 (11:49 +0200)
added patches:
arm64-compat-provide-definition-for-compat_sigminstksz.patch
binder-fix-possible-uaf-when-freeing-buffer.patch
nfs-fix-dentry-revalidation-on-nfsv4-lookup.patch
nfs-refactor-nfs_lookup_revalidate.patch
nfsv4-fix-lookup-revalidate-of-regular-files.patch
usb-dwc2-disable-all-ep-s-on-disconnect.patch
usb-dwc2-fix-disable-all-ep-s-on-disconnect.patch

queue-4.19/arm64-compat-provide-definition-for-compat_sigminstksz.patch [new file with mode: 0644]
queue-4.19/binder-fix-possible-uaf-when-freeing-buffer.patch [new file with mode: 0644]
queue-4.19/nfs-fix-dentry-revalidation-on-nfsv4-lookup.patch [new file with mode: 0644]
queue-4.19/nfs-refactor-nfs_lookup_revalidate.patch [new file with mode: 0644]
queue-4.19/nfsv4-fix-lookup-revalidate-of-regular-files.patch [new file with mode: 0644]
queue-4.19/series
queue-4.19/usb-dwc2-disable-all-ep-s-on-disconnect.patch [new file with mode: 0644]
queue-4.19/usb-dwc2-fix-disable-all-ep-s-on-disconnect.patch [new file with mode: 0644]

diff --git a/queue-4.19/arm64-compat-provide-definition-for-compat_sigminstksz.patch b/queue-4.19/arm64-compat-provide-definition-for-compat_sigminstksz.patch
new file mode 100644 (file)
index 0000000..1c94088
--- /dev/null
@@ -0,0 +1,39 @@
+From 24951465cbd279f60b1fdc2421b3694405bcff42 Mon Sep 17 00:00:00 2001
+From: Will Deacon <will.deacon@arm.com>
+Date: Wed, 5 Sep 2018 15:34:43 +0100
+Subject: arm64: compat: Provide definition for COMPAT_SIGMINSTKSZ
+
+From: Will Deacon <will.deacon@arm.com>
+
+commit 24951465cbd279f60b1fdc2421b3694405bcff42 upstream.
+
+arch/arm/ defines a SIGMINSTKSZ of 2k, so we should use the same value
+for compat tasks.
+
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Dominik Brodowski <linux@dominikbrodowski.net>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Cc: Oleg Nesterov <oleg@redhat.com>
+Reviewed-by: Dave Martin <Dave.Martin@arm.com>
+Reported-by: Steve McIntyre <steve.mcintyre@arm.com>
+Tested-by: Steve McIntyre <93sam@debian.org>
+Signed-off-by: Will Deacon <will.deacon@arm.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/include/asm/compat.h |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm64/include/asm/compat.h
++++ b/arch/arm64/include/asm/compat.h
+@@ -159,6 +159,7 @@ static inline compat_uptr_t ptr_to_compa
+ }
+ #define compat_user_stack_pointer() (user_stack_pointer(task_pt_regs(current)))
++#define COMPAT_MINSIGSTKSZ    2048
+ static inline void __user *arch_compat_alloc_user_space(long len)
+ {
diff --git a/queue-4.19/binder-fix-possible-uaf-when-freeing-buffer.patch b/queue-4.19/binder-fix-possible-uaf-when-freeing-buffer.patch
new file mode 100644 (file)
index 0000000..4260ca1
--- /dev/null
@@ -0,0 +1,62 @@
+From a370003cc301d4361bae20c9ef615f89bf8d1e8a Mon Sep 17 00:00:00 2001
+From: Todd Kjos <tkjos@android.com>
+Date: Wed, 12 Jun 2019 13:29:27 -0700
+Subject: binder: fix possible UAF when freeing buffer
+
+From: Todd Kjos <tkjos@android.com>
+
+commit a370003cc301d4361bae20c9ef615f89bf8d1e8a upstream.
+
+There is a race between the binder driver cleaning
+up a completed transaction via binder_free_transaction()
+and a user calling binder_ioctl(BC_FREE_BUFFER) to
+release a buffer. It doesn't matter which is first but
+they need to be protected against running concurrently
+which can result in a UAF.
+
+Signed-off-by: Todd Kjos <tkjos@google.com>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+
+---
+ drivers/android/binder.c |   16 ++++++++++++++--
+ 1 file changed, 14 insertions(+), 2 deletions(-)
+
+--- a/drivers/android/binder.c
++++ b/drivers/android/binder.c
+@@ -1960,8 +1960,18 @@ static struct binder_thread *binder_get_
+ static void binder_free_transaction(struct binder_transaction *t)
+ {
+-      if (t->buffer)
+-              t->buffer->transaction = NULL;
++      struct binder_proc *target_proc = t->to_proc;
++
++      if (target_proc) {
++              binder_inner_proc_lock(target_proc);
++              if (t->buffer)
++                      t->buffer->transaction = NULL;
++              binder_inner_proc_unlock(target_proc);
++      }
++      /*
++       * If the transaction has no target_proc, then
++       * t->buffer->transaction has already been cleared.
++       */
+       kfree(t);
+       binder_stats_deleted(BINDER_STAT_TRANSACTION);
+ }
+@@ -3484,10 +3494,12 @@ static int binder_thread_write(struct bi
+                                    buffer->debug_id,
+                                    buffer->transaction ? "active" : "finished");
++                      binder_inner_proc_lock(proc);
+                       if (buffer->transaction) {
+                               buffer->transaction->buffer = NULL;
+                               buffer->transaction = NULL;
+                       }
++                      binder_inner_proc_unlock(proc);
+                       if (buffer->async_transaction && buffer->target_node) {
+                               struct binder_node *buf_node;
+                               struct binder_work *w;
diff --git a/queue-4.19/nfs-fix-dentry-revalidation-on-nfsv4-lookup.patch b/queue-4.19/nfs-fix-dentry-revalidation-on-nfsv4-lookup.patch
new file mode 100644 (file)
index 0000000..2770ff6
--- /dev/null
@@ -0,0 +1,68 @@
+From be189f7e7f03de35887e5a85ddcf39b91b5d7fc1 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+Date: Thu, 27 Sep 2018 17:12:33 -0400
+Subject: NFS: Fix dentry revalidation on NFSv4 lookup
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+commit be189f7e7f03de35887e5a85ddcf39b91b5d7fc1 upstream.
+
+We need to ensure that inode and dentry revalidation occurs correctly
+on reopen of a file that is already open. Currently, we can end up
+not revalidating either in the case of NFSv4.0, due to the 'cached open'
+path.
+Let's fix that by ensuring that we only do cached open for the special
+cases of open recovery and delegation return.
+
+Reported-by: Stan Hu <stanhu@gmail.com>
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Qian Lu <luqia@amazon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/nfs4proc.c |   15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -1355,12 +1355,20 @@ static bool nfs4_mode_match_open_stateid
+       return false;
+ }
+-static int can_open_cached(struct nfs4_state *state, fmode_t mode, int open_mode)
++static int can_open_cached(struct nfs4_state *state, fmode_t mode,
++              int open_mode, enum open_claim_type4 claim)
+ {
+       int ret = 0;
+       if (open_mode & (O_EXCL|O_TRUNC))
+               goto out;
++      switch (claim) {
++      case NFS4_OPEN_CLAIM_NULL:
++      case NFS4_OPEN_CLAIM_FH:
++              goto out;
++      default:
++              break;
++      }
+       switch (mode & (FMODE_READ|FMODE_WRITE)) {
+               case FMODE_READ:
+                       ret |= test_bit(NFS_O_RDONLY_STATE, &state->flags) != 0
+@@ -1753,7 +1761,7 @@ static struct nfs4_state *nfs4_try_open_
+       for (;;) {
+               spin_lock(&state->owner->so_lock);
+-              if (can_open_cached(state, fmode, open_mode)) {
++              if (can_open_cached(state, fmode, open_mode, claim)) {
+                       update_open_stateflags(state, fmode);
+                       spin_unlock(&state->owner->so_lock);
+                       goto out_return_state;
+@@ -2282,7 +2290,8 @@ static void nfs4_open_prepare(struct rpc
+       if (data->state != NULL) {
+               struct nfs_delegation *delegation;
+-              if (can_open_cached(data->state, data->o_arg.fmode, data->o_arg.open_flags))
++              if (can_open_cached(data->state, data->o_arg.fmode,
++                                      data->o_arg.open_flags, claim))
+                       goto out_no_action;
+               rcu_read_lock();
+               delegation = rcu_dereference(NFS_I(data->state->inode)->delegation);
diff --git a/queue-4.19/nfs-refactor-nfs_lookup_revalidate.patch b/queue-4.19/nfs-refactor-nfs_lookup_revalidate.patch
new file mode 100644 (file)
index 0000000..349714b
--- /dev/null
@@ -0,0 +1,296 @@
+From 5ceb9d7fdaaf6d8ced6cd7861cf1deb9cd93fa47 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+Date: Fri, 28 Sep 2018 09:04:05 -0400
+Subject: NFS: Refactor nfs_lookup_revalidate()
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+commit 5ceb9d7fdaaf6d8ced6cd7861cf1deb9cd93fa47 upstream.
+
+Refactor the code in nfs_lookup_revalidate() as a stepping stone towards
+optimising and fixing nfs4_lookup_revalidate().
+
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Qian Lu <luqia@amazon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/dir.c |  222 +++++++++++++++++++++++++++++++++--------------------------
+ 1 file changed, 126 insertions(+), 96 deletions(-)
+
+--- a/fs/nfs/dir.c
++++ b/fs/nfs/dir.c
+@@ -1072,6 +1072,100 @@ int nfs_neg_need_reval(struct inode *dir
+       return !nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU);
+ }
++static int
++nfs_lookup_revalidate_done(struct inode *dir, struct dentry *dentry,
++                         struct inode *inode, int error)
++{
++      switch (error) {
++      case 1:
++              dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) is valid\n",
++                      __func__, dentry);
++              return 1;
++      case 0:
++              nfs_mark_for_revalidate(dir);
++              if (inode && S_ISDIR(inode->i_mode)) {
++                      /* Purge readdir caches. */
++                      nfs_zap_caches(inode);
++                      /*
++                       * We can't d_drop the root of a disconnected tree:
++                       * its d_hash is on the s_anon list and d_drop() would hide
++                       * it from shrink_dcache_for_unmount(), leading to busy
++                       * inodes on unmount and further oopses.
++                       */
++                      if (IS_ROOT(dentry))
++                              return 1;
++              }
++              dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) is invalid\n",
++                              __func__, dentry);
++              return 0;
++      }
++      dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) lookup returned error %d\n",
++                              __func__, dentry, error);
++      return error;
++}
++
++static int
++nfs_lookup_revalidate_negative(struct inode *dir, struct dentry *dentry,
++                             unsigned int flags)
++{
++      int ret = 1;
++      if (nfs_neg_need_reval(dir, dentry, flags)) {
++              if (flags & LOOKUP_RCU)
++                      return -ECHILD;
++              ret = 0;
++      }
++      return nfs_lookup_revalidate_done(dir, dentry, NULL, ret);
++}
++
++static int
++nfs_lookup_revalidate_delegated(struct inode *dir, struct dentry *dentry,
++                              struct inode *inode)
++{
++      nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
++      return nfs_lookup_revalidate_done(dir, dentry, inode, 1);
++}
++
++static int
++nfs_lookup_revalidate_dentry(struct inode *dir, struct dentry *dentry,
++                           struct inode *inode)
++{
++      struct nfs_fh *fhandle;
++      struct nfs_fattr *fattr;
++      struct nfs4_label *label;
++      int ret;
++
++      ret = -ENOMEM;
++      fhandle = nfs_alloc_fhandle();
++      fattr = nfs_alloc_fattr();
++      label = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL);
++      if (fhandle == NULL || fattr == NULL || IS_ERR(label))
++              goto out;
++
++      ret = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
++      if (ret < 0) {
++              if (ret == -ESTALE || ret == -ENOENT)
++                      ret = 0;
++              goto out;
++      }
++      ret = 0;
++      if (nfs_compare_fh(NFS_FH(inode), fhandle))
++              goto out;
++      if (nfs_refresh_inode(inode, fattr) < 0)
++              goto out;
++
++      nfs_setsecurity(inode, fattr, label);
++      nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
++
++      /* set a readdirplus hint that we had a cache miss */
++      nfs_force_use_readdirplus(dir);
++      ret = 1;
++out:
++      nfs_free_fattr(fattr);
++      nfs_free_fhandle(fhandle);
++      nfs4_label_free(label);
++      return nfs_lookup_revalidate_done(dir, dentry, inode, ret);
++}
++
+ /*
+  * This is called every time the dcache has a lookup hit,
+  * and we should check whether we can really trust that
+@@ -1083,58 +1177,36 @@ int nfs_neg_need_reval(struct inode *dir
+  * If the parent directory is seen to have changed, we throw out the
+  * cached dentry and do a new lookup.
+  */
+-static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
++static int
++nfs_do_lookup_revalidate(struct inode *dir, struct dentry *dentry,
++                       unsigned int flags)
+ {
+-      struct inode *dir;
+       struct inode *inode;
+-      struct dentry *parent;
+-      struct nfs_fh *fhandle = NULL;
+-      struct nfs_fattr *fattr = NULL;
+-      struct nfs4_label *label = NULL;
+       int error;
+-      if (flags & LOOKUP_RCU) {
+-              parent = READ_ONCE(dentry->d_parent);
+-              dir = d_inode_rcu(parent);
+-              if (!dir)
+-                      return -ECHILD;
+-      } else {
+-              parent = dget_parent(dentry);
+-              dir = d_inode(parent);
+-      }
+       nfs_inc_stats(dir, NFSIOS_DENTRYREVALIDATE);
+       inode = d_inode(dentry);
+-      if (!inode) {
+-              if (nfs_neg_need_reval(dir, dentry, flags)) {
+-                      if (flags & LOOKUP_RCU)
+-                              return -ECHILD;
+-                      goto out_bad;
+-              }
+-              goto out_valid;
+-      }
++      if (!inode)
++              return nfs_lookup_revalidate_negative(dir, dentry, flags);
+       if (is_bad_inode(inode)) {
+-              if (flags & LOOKUP_RCU)
+-                      return -ECHILD;
+               dfprintk(LOOKUPCACHE, "%s: %pd2 has dud inode\n",
+                               __func__, dentry);
+               goto out_bad;
+       }
+       if (NFS_PROTO(dir)->have_delegation(inode, FMODE_READ))
+-              goto out_set_verifier;
++              return nfs_lookup_revalidate_delegated(dir, dentry, inode);
+       /* Force a full look up iff the parent directory has changed */
+       if (!(flags & (LOOKUP_EXCL | LOOKUP_REVAL)) &&
+           nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU)) {
+               error = nfs_lookup_verify_inode(inode, flags);
+               if (error) {
+-                      if (flags & LOOKUP_RCU)
+-                              return -ECHILD;
+                       if (error == -ESTALE)
+-                              goto out_zap_parent;
+-                      goto out_error;
++                              nfs_zap_caches(dir);
++                      goto out_bad;
+               }
+               nfs_advise_use_readdirplus(dir);
+               goto out_valid;
+@@ -1146,81 +1218,39 @@ static int nfs_lookup_revalidate(struct
+       if (NFS_STALE(inode))
+               goto out_bad;
+-      error = -ENOMEM;
+-      fhandle = nfs_alloc_fhandle();
+-      fattr = nfs_alloc_fattr();
+-      if (fhandle == NULL || fattr == NULL)
+-              goto out_error;
+-
+-      label = nfs4_label_alloc(NFS_SERVER(inode), GFP_NOWAIT);
+-      if (IS_ERR(label))
+-              goto out_error;
+-
+       trace_nfs_lookup_revalidate_enter(dir, dentry, flags);
+-      error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
++      error = nfs_lookup_revalidate_dentry(dir, dentry, inode);
+       trace_nfs_lookup_revalidate_exit(dir, dentry, flags, error);
+-      if (error == -ESTALE || error == -ENOENT)
+-              goto out_bad;
+-      if (error)
+-              goto out_error;
+-      if (nfs_compare_fh(NFS_FH(inode), fhandle))
+-              goto out_bad;
+-      if ((error = nfs_refresh_inode(inode, fattr)) != 0)
+-              goto out_bad;
+-
+-      nfs_setsecurity(inode, fattr, label);
+-
+-      nfs_free_fattr(fattr);
+-      nfs_free_fhandle(fhandle);
+-      nfs4_label_free(label);
++      return error;
++out_valid:
++      return nfs_lookup_revalidate_done(dir, dentry, inode, 1);
++out_bad:
++      if (flags & LOOKUP_RCU)
++              return -ECHILD;
++      return nfs_lookup_revalidate_done(dir, dentry, inode, 0);
++}
+-      /* set a readdirplus hint that we had a cache miss */
+-      nfs_force_use_readdirplus(dir);
++static int
++nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
++{
++      struct dentry *parent;
++      struct inode *dir;
++      int ret;
+-out_set_verifier:
+-      nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+- out_valid:
+       if (flags & LOOKUP_RCU) {
++              parent = READ_ONCE(dentry->d_parent);
++              dir = d_inode_rcu(parent);
++              if (!dir)
++                      return -ECHILD;
++              ret = nfs_do_lookup_revalidate(dir, dentry, flags);
+               if (parent != READ_ONCE(dentry->d_parent))
+                       return -ECHILD;
+-      } else
++      } else {
++              parent = dget_parent(dentry);
++              ret = nfs_do_lookup_revalidate(d_inode(parent), dentry, flags);
+               dput(parent);
+-      dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) is valid\n",
+-                      __func__, dentry);
+-      return 1;
+-out_zap_parent:
+-      nfs_zap_caches(dir);
+- out_bad:
+-      WARN_ON(flags & LOOKUP_RCU);
+-      nfs_free_fattr(fattr);
+-      nfs_free_fhandle(fhandle);
+-      nfs4_label_free(label);
+-      nfs_mark_for_revalidate(dir);
+-      if (inode && S_ISDIR(inode->i_mode)) {
+-              /* Purge readdir caches. */
+-              nfs_zap_caches(inode);
+-              /*
+-               * We can't d_drop the root of a disconnected tree:
+-               * its d_hash is on the s_anon list and d_drop() would hide
+-               * it from shrink_dcache_for_unmount(), leading to busy
+-               * inodes on unmount and further oopses.
+-               */
+-              if (IS_ROOT(dentry))
+-                      goto out_valid;
+       }
+-      dput(parent);
+-      dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) is invalid\n",
+-                      __func__, dentry);
+-      return 0;
+-out_error:
+-      WARN_ON(flags & LOOKUP_RCU);
+-      nfs_free_fattr(fattr);
+-      nfs_free_fhandle(fhandle);
+-      nfs4_label_free(label);
+-      dput(parent);
+-      dfprintk(LOOKUPCACHE, "NFS: %s(%pd2) lookup returned error %d\n",
+-                      __func__, dentry, error);
+-      return error;
++      return ret;
+ }
+ /*
diff --git a/queue-4.19/nfsv4-fix-lookup-revalidate-of-regular-files.patch b/queue-4.19/nfsv4-fix-lookup-revalidate-of-regular-files.patch
new file mode 100644 (file)
index 0000000..1e092a0
--- /dev/null
@@ -0,0 +1,151 @@
+From c7944ebb9ce9461079659e9e6ec5baaf73724b3b Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+Date: Fri, 28 Sep 2018 12:42:51 -0400
+Subject: NFSv4: Fix lookup revalidate of regular files
+
+From: Trond Myklebust <trond.myklebust@hammerspace.com>
+
+commit c7944ebb9ce9461079659e9e6ec5baaf73724b3b upstream.
+
+If we're revalidating an existing dentry in order to open a file, we need
+to ensure that we check the directory has not changed before we optimise
+away the lookup.
+
+Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
+Signed-off-by: Qian Lu <luqia@amazon.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/nfs/dir.c |   79 +++++++++++++++++++++++++++++------------------------------
+ 1 file changed, 39 insertions(+), 40 deletions(-)
+
+--- a/fs/nfs/dir.c
++++ b/fs/nfs/dir.c
+@@ -1231,7 +1231,8 @@ out_bad:
+ }
+ static int
+-nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
++__nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags,
++                      int (*reval)(struct inode *, struct dentry *, unsigned int))
+ {
+       struct dentry *parent;
+       struct inode *dir;
+@@ -1242,17 +1243,22 @@ nfs_lookup_revalidate(struct dentry *den
+               dir = d_inode_rcu(parent);
+               if (!dir)
+                       return -ECHILD;
+-              ret = nfs_do_lookup_revalidate(dir, dentry, flags);
++              ret = reval(dir, dentry, flags);
+               if (parent != READ_ONCE(dentry->d_parent))
+                       return -ECHILD;
+       } else {
+               parent = dget_parent(dentry);
+-              ret = nfs_do_lookup_revalidate(d_inode(parent), dentry, flags);
++              ret = reval(d_inode(parent), dentry, flags);
+               dput(parent);
+       }
+       return ret;
+ }
++static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
++{
++      return __nfs_lookup_revalidate(dentry, flags, nfs_do_lookup_revalidate);
++}
++
+ /*
+  * A weaker form of d_revalidate for revalidating just the d_inode(dentry)
+  * when we don't really care about the dentry name. This is called when a
+@@ -1609,62 +1615,55 @@ no_open:
+ }
+ EXPORT_SYMBOL_GPL(nfs_atomic_open);
+-static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags)
++static int
++nfs4_do_lookup_revalidate(struct inode *dir, struct dentry *dentry,
++                        unsigned int flags)
+ {
+       struct inode *inode;
+-      int ret = 0;
+       if (!(flags & LOOKUP_OPEN) || (flags & LOOKUP_DIRECTORY))
+-              goto no_open;
++              goto full_reval;
+       if (d_mountpoint(dentry))
+-              goto no_open;
+-      if (NFS_SB(dentry->d_sb)->caps & NFS_CAP_ATOMIC_OPEN_V1)
+-              goto no_open;
++              goto full_reval;
+       inode = d_inode(dentry);
+       /* We can't create new files in nfs_open_revalidate(), so we
+        * optimize away revalidation of negative dentries.
+        */
+-      if (inode == NULL) {
+-              struct dentry *parent;
+-              struct inode *dir;
+-
+-              if (flags & LOOKUP_RCU) {
+-                      parent = READ_ONCE(dentry->d_parent);
+-                      dir = d_inode_rcu(parent);
+-                      if (!dir)
+-                              return -ECHILD;
+-              } else {
+-                      parent = dget_parent(dentry);
+-                      dir = d_inode(parent);
+-              }
+-              if (!nfs_neg_need_reval(dir, dentry, flags))
+-                      ret = 1;
+-              else if (flags & LOOKUP_RCU)
+-                      ret = -ECHILD;
+-              if (!(flags & LOOKUP_RCU))
+-                      dput(parent);
+-              else if (parent != READ_ONCE(dentry->d_parent))
+-                      return -ECHILD;
+-              goto out;
+-      }
++      if (inode == NULL)
++              goto full_reval;
++
++      if (NFS_PROTO(dir)->have_delegation(inode, FMODE_READ))
++              return nfs_lookup_revalidate_delegated(dir, dentry, inode);
+       /* NFS only supports OPEN on regular files */
+       if (!S_ISREG(inode->i_mode))
+-              goto no_open;
++              goto full_reval;
++
+       /* We cannot do exclusive creation on a positive dentry */
+-      if (flags & LOOKUP_EXCL)
+-              goto no_open;
++      if (flags & (LOOKUP_EXCL | LOOKUP_REVAL))
++              goto reval_dentry;
++
++      /* Check if the directory changed */
++      if (!nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU))
++              goto reval_dentry;
+       /* Let f_op->open() actually open (and revalidate) the file */
+-      ret = 1;
++      return 1;
++reval_dentry:
++      if (flags & LOOKUP_RCU)
++              return -ECHILD;
++      return nfs_lookup_revalidate_dentry(dir, dentry, inode);;
+-out:
+-      return ret;
++full_reval:
++      return nfs_do_lookup_revalidate(dir, dentry, flags);
++}
+-no_open:
+-      return nfs_lookup_revalidate(dentry, flags);
++static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags)
++{
++      return __nfs_lookup_revalidate(dentry, flags,
++                      nfs4_do_lookup_revalidate);
+ }
+ #endif /* CONFIG_NFSV4 */
index c845a8f42370296480281dee17d6c96ad543a0d5..11dcb81881678220bf9a5aaca6a541653057fde4 100644 (file)
@@ -1,2 +1,9 @@
 hv_sock-add-support-for-delayed-close.patch
 vsock-correct-removal-of-socket-from-the-list.patch
+nfs-fix-dentry-revalidation-on-nfsv4-lookup.patch
+nfs-refactor-nfs_lookup_revalidate.patch
+nfsv4-fix-lookup-revalidate-of-regular-files.patch
+usb-dwc2-disable-all-ep-s-on-disconnect.patch
+usb-dwc2-fix-disable-all-ep-s-on-disconnect.patch
+arm64-compat-provide-definition-for-compat_sigminstksz.patch
+binder-fix-possible-uaf-when-freeing-buffer.patch
diff --git a/queue-4.19/usb-dwc2-disable-all-ep-s-on-disconnect.patch b/queue-4.19/usb-dwc2-disable-all-ep-s-on-disconnect.patch
new file mode 100644 (file)
index 0000000..97a31a7
--- /dev/null
@@ -0,0 +1,112 @@
+From dccf1bad4be7eaa096c1f3697bd37883f9a08ecb Mon Sep 17 00:00:00 2001
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+Date: Wed, 19 Sep 2018 18:13:52 +0400
+Subject: usb: dwc2: Disable all EP's on disconnect
+
+From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
+
+commit dccf1bad4be7eaa096c1f3697bd37883f9a08ecb upstream.
+
+Disabling all EP's allow to reset EP's to initial state.
+On disconnect disable all EP's instead of just killing
+all requests. Because of some platform didn't catch
+disconnect event, same stuff added to
+dwc2_hsotg_core_init_disconnected() function when USB
+reset detected on the bus.
+
+Changed from version 1:
+Changed lock acquire flow in dwc2_hsotg_ep_disable()
+function.
+
+Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc2/gadget.c |   30 +++++++++++++++++++++++-------
+ 1 file changed, 23 insertions(+), 7 deletions(-)
+
+--- a/drivers/usb/dwc2/gadget.c
++++ b/drivers/usb/dwc2/gadget.c
+@@ -3107,6 +3107,8 @@ static void kill_all_requests(struct dwc
+               dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
+ }
++static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
++
+ /**
+  * dwc2_hsotg_disconnect - disconnect service
+  * @hsotg: The device state.
+@@ -3125,13 +3127,12 @@ void dwc2_hsotg_disconnect(struct dwc2_h
+       hsotg->connected = 0;
+       hsotg->test_mode = 0;
++      /* all endpoints should be shutdown */
+       for (ep = 0; ep < hsotg->num_of_eps; ep++) {
+               if (hsotg->eps_in[ep])
+-                      kill_all_requests(hsotg, hsotg->eps_in[ep],
+-                                        -ESHUTDOWN);
++                      dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
+               if (hsotg->eps_out[ep])
+-                      kill_all_requests(hsotg, hsotg->eps_out[ep],
+-                                        -ESHUTDOWN);
++                      dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
+       }
+       call_gadget(hsotg, disconnect);
+@@ -3189,13 +3190,23 @@ void dwc2_hsotg_core_init_disconnected(s
+       u32 val;
+       u32 usbcfg;
+       u32 dcfg = 0;
++      int ep;
+       /* Kill any ep0 requests as controller will be reinitialized */
+       kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
+-      if (!is_usb_reset)
++      if (!is_usb_reset) {
+               if (dwc2_core_reset(hsotg, true))
+                       return;
++      } else {
++              /* all endpoints should be shutdown */
++              for (ep = 1; ep < hsotg->num_of_eps; ep++) {
++                      if (hsotg->eps_in[ep])
++                              dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
++                      if (hsotg->eps_out[ep])
++                              dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
++              }
++      }
+       /*
+        * we must now enable ep0 ready for host detection and then
+@@ -3996,6 +4007,7 @@ static int dwc2_hsotg_ep_disable(struct
+       unsigned long flags;
+       u32 epctrl_reg;
+       u32 ctrl;
++      int locked;
+       dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);
+@@ -4011,7 +4023,9 @@ static int dwc2_hsotg_ep_disable(struct
+       epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
+-      spin_lock_irqsave(&hsotg->lock, flags);
++      locked = spin_is_locked(&hsotg->lock);
++      if (!locked)
++              spin_lock_irqsave(&hsotg->lock, flags);
+       ctrl = dwc2_readl(hsotg, epctrl_reg);
+@@ -4035,7 +4049,9 @@ static int dwc2_hsotg_ep_disable(struct
+       hs_ep->fifo_index = 0;
+       hs_ep->fifo_size = 0;
+-      spin_unlock_irqrestore(&hsotg->lock, flags);
++      if (!locked)
++              spin_unlock_irqrestore(&hsotg->lock, flags);
++
+       return 0;
+ }
diff --git a/queue-4.19/usb-dwc2-fix-disable-all-ep-s-on-disconnect.patch b/queue-4.19/usb-dwc2-fix-disable-all-ep-s-on-disconnect.patch
new file mode 100644 (file)
index 0000000..7068a1c
--- /dev/null
@@ -0,0 +1,157 @@
+From 4fe4f9fecc36956fd53c8edf96dd0c691ef98ff9 Mon Sep 17 00:00:00 2001
+From: Minas Harutyunyan <minas.harutyunyan@synopsys.com>
+Date: Mon, 10 Dec 2018 18:09:32 +0400
+Subject: usb: dwc2: Fix disable all EP's on disconnect
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Minas Harutyunyan <minas.harutyunyan@synopsys.com>
+
+commit 4fe4f9fecc36956fd53c8edf96dd0c691ef98ff9 upstream.
+
+Disabling all EP's allow to reset EP's to initial state.
+Introduced new function dwc2_hsotg_ep_disable_lock() which
+before calling dwc2_hsotg_ep_disable() function acquire
+hsotg->lock and release on exiting.
+From dwc2_hsotg_ep_disable() function removed acquiring
+hsotg->lock.
+In dwc2_hsotg_core_init_disconnected() function when USB
+reset interrupt asserted disabling all ep’s by
+dwc2_hsotg_ep_disable() function.
+This updates eliminating sparse imbalance warnings.
+
+Reverted changes in dwc2_hostg_disconnect() function.
+Introduced new function dwc2_hsotg_ep_disable_lock().
+Changed dwc2_hsotg_ep_ops. Now disable point to
+dwc2_hsotg_ep_disable_lock() function.
+In functions dwc2_hsotg_udc_stop() and dwc2_hsotg_suspend()
+dwc2_hsotg_ep_disable() function replaced by
+dwc2_hsotg_ep_disable_lock() function.
+In dwc2_hsotg_ep_disable() function removed acquiring
+of hsotg->lock.
+
+Fixes: dccf1bad4be7 ("usb: dwc2: Disable all EP's on disconnect")
+Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc2/gadget.c |   41 +++++++++++++++++++++++------------------
+ 1 file changed, 23 insertions(+), 18 deletions(-)
+
+--- a/drivers/usb/dwc2/gadget.c
++++ b/drivers/usb/dwc2/gadget.c
+@@ -3107,8 +3107,6 @@ static void kill_all_requests(struct dwc
+               dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
+ }
+-static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
+-
+ /**
+  * dwc2_hsotg_disconnect - disconnect service
+  * @hsotg: The device state.
+@@ -3130,9 +3128,11 @@ void dwc2_hsotg_disconnect(struct dwc2_h
+       /* all endpoints should be shutdown */
+       for (ep = 0; ep < hsotg->num_of_eps; ep++) {
+               if (hsotg->eps_in[ep])
+-                      dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
++                      kill_all_requests(hsotg, hsotg->eps_in[ep],
++                                        -ESHUTDOWN);
+               if (hsotg->eps_out[ep])
+-                      dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
++                      kill_all_requests(hsotg, hsotg->eps_out[ep],
++                                        -ESHUTDOWN);
+       }
+       call_gadget(hsotg, disconnect);
+@@ -3176,6 +3176,7 @@ static void dwc2_hsotg_irq_fifoempty(str
+                       GINTSTS_PTXFEMP |  \
+                       GINTSTS_RXFLVL)
++static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
+ /**
+  * dwc2_hsotg_core_init - issue softreset to the core
+  * @hsotg: The device state
+@@ -4004,10 +4005,8 @@ static int dwc2_hsotg_ep_disable(struct
+       struct dwc2_hsotg *hsotg = hs_ep->parent;
+       int dir_in = hs_ep->dir_in;
+       int index = hs_ep->index;
+-      unsigned long flags;
+       u32 epctrl_reg;
+       u32 ctrl;
+-      int locked;
+       dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);
+@@ -4023,10 +4022,6 @@ static int dwc2_hsotg_ep_disable(struct
+       epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
+-      locked = spin_is_locked(&hsotg->lock);
+-      if (!locked)
+-              spin_lock_irqsave(&hsotg->lock, flags);
+-
+       ctrl = dwc2_readl(hsotg, epctrl_reg);
+       if (ctrl & DXEPCTL_EPENA)
+@@ -4049,12 +4044,22 @@ static int dwc2_hsotg_ep_disable(struct
+       hs_ep->fifo_index = 0;
+       hs_ep->fifo_size = 0;
+-      if (!locked)
+-              spin_unlock_irqrestore(&hsotg->lock, flags);
+-
+       return 0;
+ }
++static int dwc2_hsotg_ep_disable_lock(struct usb_ep *ep)
++{
++      struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
++      struct dwc2_hsotg *hsotg = hs_ep->parent;
++      unsigned long flags;
++      int ret;
++
++      spin_lock_irqsave(&hsotg->lock, flags);
++      ret = dwc2_hsotg_ep_disable(ep);
++      spin_unlock_irqrestore(&hsotg->lock, flags);
++      return ret;
++}
++
+ /**
+  * on_list - check request is on the given endpoint
+  * @ep: The endpoint to check.
+@@ -4202,7 +4207,7 @@ static int dwc2_hsotg_ep_sethalt_lock(st
+ static const struct usb_ep_ops dwc2_hsotg_ep_ops = {
+       .enable         = dwc2_hsotg_ep_enable,
+-      .disable        = dwc2_hsotg_ep_disable,
++      .disable        = dwc2_hsotg_ep_disable_lock,
+       .alloc_request  = dwc2_hsotg_ep_alloc_request,
+       .free_request   = dwc2_hsotg_ep_free_request,
+       .queue          = dwc2_hsotg_ep_queue_lock,
+@@ -4342,9 +4347,9 @@ static int dwc2_hsotg_udc_stop(struct us
+       /* all endpoints should be shutdown */
+       for (ep = 1; ep < hsotg->num_of_eps; ep++) {
+               if (hsotg->eps_in[ep])
+-                      dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
++                      dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep);
+               if (hsotg->eps_out[ep])
+-                      dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
++                      dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep);
+       }
+       spin_lock_irqsave(&hsotg->lock, flags);
+@@ -4792,9 +4797,9 @@ int dwc2_hsotg_suspend(struct dwc2_hsotg
+               for (ep = 0; ep < hsotg->num_of_eps; ep++) {
+                       if (hsotg->eps_in[ep])
+-                              dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
++                              dwc2_hsotg_ep_disable_lock(&hsotg->eps_in[ep]->ep);
+                       if (hsotg->eps_out[ep])
+-                              dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
++                              dwc2_hsotg_ep_disable_lock(&hsotg->eps_out[ep]->ep);
+               }
+       }