From: Greg Kroah-Hartman Date: Wed, 31 Jul 2019 09:49:59 +0000 (+0200) Subject: 4.19-stable patches X-Git-Tag: v5.2.6~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=32d48516c43c0fd72aa788cb622510ac73ae78cd;p=thirdparty%2Fkernel%2Fstable-queue.git 4.19-stable patches 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 --- 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 index 00000000000..1c94088bf41 --- /dev/null +++ b/queue-4.19/arm64-compat-provide-definition-for-compat_sigminstksz.patch @@ -0,0 +1,39 @@ +From 24951465cbd279f60b1fdc2421b3694405bcff42 Mon Sep 17 00:00:00 2001 +From: Will Deacon +Date: Wed, 5 Sep 2018 15:34:43 +0100 +Subject: arm64: compat: Provide definition for COMPAT_SIGMINSTKSZ + +From: Will Deacon + +commit 24951465cbd279f60b1fdc2421b3694405bcff42 upstream. + +arch/arm/ defines a SIGMINSTKSZ of 2k, so we should use the same value +for compat tasks. + +Cc: Arnd Bergmann +Cc: Dominik Brodowski +Cc: "Eric W. Biederman" +Cc: Andrew Morton +Cc: Al Viro +Cc: Oleg Nesterov +Reviewed-by: Dave Martin +Reported-by: Steve McIntyre +Tested-by: Steve McIntyre <93sam@debian.org> +Signed-off-by: Will Deacon +Signed-off-by: Catalin Marinas +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..4260ca13914 --- /dev/null +++ b/queue-4.19/binder-fix-possible-uaf-when-freeing-buffer.patch @@ -0,0 +1,62 @@ +From a370003cc301d4361bae20c9ef615f89bf8d1e8a Mon Sep 17 00:00:00 2001 +From: Todd Kjos +Date: Wed, 12 Jun 2019 13:29:27 -0700 +Subject: binder: fix possible UAF when freeing buffer + +From: Todd Kjos + +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 +Cc: stable +Signed-off-by: Greg Kroah-Hartman + + + +--- + 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 index 00000000000..2770ff6046c --- /dev/null +++ b/queue-4.19/nfs-fix-dentry-revalidation-on-nfsv4-lookup.patch @@ -0,0 +1,68 @@ +From be189f7e7f03de35887e5a85ddcf39b91b5d7fc1 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Thu, 27 Sep 2018 17:12:33 -0400 +Subject: NFS: Fix dentry revalidation on NFSv4 lookup + +From: Trond Myklebust + +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 +Signed-off-by: Trond Myklebust +Signed-off-by: Qian Lu +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..349714b463b --- /dev/null +++ b/queue-4.19/nfs-refactor-nfs_lookup_revalidate.patch @@ -0,0 +1,296 @@ +From 5ceb9d7fdaaf6d8ced6cd7861cf1deb9cd93fa47 Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Fri, 28 Sep 2018 09:04:05 -0400 +Subject: NFS: Refactor nfs_lookup_revalidate() + +From: Trond Myklebust + +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 +Signed-off-by: Qian Lu +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..1e092a0d328 --- /dev/null +++ b/queue-4.19/nfsv4-fix-lookup-revalidate-of-regular-files.patch @@ -0,0 +1,151 @@ +From c7944ebb9ce9461079659e9e6ec5baaf73724b3b Mon Sep 17 00:00:00 2001 +From: Trond Myklebust +Date: Fri, 28 Sep 2018 12:42:51 -0400 +Subject: NFSv4: Fix lookup revalidate of regular files + +From: Trond Myklebust + +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 +Signed-off-by: Qian Lu +Signed-off-by: Greg Kroah-Hartman + +--- + 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 */ diff --git a/queue-4.19/series b/queue-4.19/series index c845a8f4237..11dcb818816 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -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 index 00000000000..97a31a7fc19 --- /dev/null +++ b/queue-4.19/usb-dwc2-disable-all-ep-s-on-disconnect.patch @@ -0,0 +1,112 @@ +From dccf1bad4be7eaa096c1f3697bd37883f9a08ecb Mon Sep 17 00:00:00 2001 +From: Minas Harutyunyan +Date: Wed, 19 Sep 2018 18:13:52 +0400 +Subject: usb: dwc2: Disable all EP's on disconnect + +From: Minas Harutyunyan + +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 +Signed-off-by: Felipe Balbi +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + 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 index 00000000000..7068a1c3504 --- /dev/null +++ b/queue-4.19/usb-dwc2-fix-disable-all-ep-s-on-disconnect.patch @@ -0,0 +1,157 @@ +From 4fe4f9fecc36956fd53c8edf96dd0c691ef98ff9 Mon Sep 17 00:00:00 2001 +From: Minas Harutyunyan +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 + +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 +Signed-off-by: Felipe Balbi +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + } + } +