From: Greg Kroah-Hartman Date: Mon, 20 Jul 2026 13:50:23 +0000 (+0200) Subject: 6.6-stable patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3aa701f6691f74db565e6bcaab85603786c71c59;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: jbd2-fix-integer-underflow-in-jbd2_journal_initialize_fast_commit.patch lockd-plug-nlm_file-leak-when-nlm_do_fopen-fails.patch lockd-plug-nlm_file-refcount-leak-on-cached-nlm_do_fopen-failure.patch nvdimm-btt-free-arena-sub-allocations-on-discover_arenas-error-path.patch nvdimm-btt-free-arenas-on-btt_init-error-paths.patch sunrpc-bound-check-xdr_buf_to_bvec-stores-before-writing.patch sunrpc-pin-svc_xprt-across-the-asynchronous-tls-handshake-callback.patch sunrpc-wait-for-in-flight-tls-handshake-callback-when-cancel-loses-race.patch --- diff --git a/queue-6.6/jbd2-fix-integer-underflow-in-jbd2_journal_initialize_fast_commit.patch b/queue-6.6/jbd2-fix-integer-underflow-in-jbd2_journal_initialize_fast_commit.patch new file mode 100644 index 0000000000..614e6c7415 --- /dev/null +++ b/queue-6.6/jbd2-fix-integer-underflow-in-jbd2_journal_initialize_fast_commit.patch @@ -0,0 +1,48 @@ +From 289a2ca0c9b7eae74f93fc213b0b971669b8683d Mon Sep 17 00:00:00 2001 +From: Junrui Luo +Date: Wed, 13 May 2026 17:28:40 +0800 +Subject: jbd2: fix integer underflow in jbd2_journal_initialize_fast_commit() + +From: Junrui Luo + +commit 289a2ca0c9b7eae74f93fc213b0b971669b8683d upstream. + +jbd2_journal_initialize_fast_commit() validates journal capacity by +checking (journal->j_last - num_fc_blks < JBD2_MIN_JOURNAL_BLOCKS). +Both j_last and num_fc_blks are unsigned, so when num_fc_blks exceeds +j_last the subtraction wraps to a large value, bypassing the bounds +check. + +The resulting underflow corrupts j_last, j_fc_first, and j_free, +leading to journal abort. + +Fix by checking num_fc_blks against j_last before the subtraction, +returning -EFSCORRUPTED. + +Fixes: 6866d7b3f2bb ("ext4 / jbd2: add fast commit initialization") +Reported-by: Yuhao Jiang +Cc: stable@vger.kernel.org +Signed-off-by: Junrui Luo +Fixes: e029c5f27987 ("ext4: make num of fast commit blocks configurable") +Reviewed-by: Baokun Li +Fixes: e029c5f279872 ("ext4: make num of fast commit blocks configurable") +Reviewed-by: Zhang Yi +Reviewed-by: Jan Kara +Link: https://patch.msgid.link/SYBPR01MB7881663C927DE9D7BBF4D1DFAF062@SYBPR01MB7881.ausprd01.prod.outlook.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman +--- + fs/jbd2/journal.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/jbd2/journal.c ++++ b/fs/jbd2/journal.c +@@ -2303,6 +2303,8 @@ jbd2_journal_initialize_fast_commit(jour + unsigned long long num_fc_blks; + + num_fc_blks = jbd2_journal_get_num_fc_blks(sb); ++ if (num_fc_blks > journal->j_last) ++ return -EFSCORRUPTED; + if (journal->j_last - num_fc_blks < JBD2_MIN_JOURNAL_BLOCKS) + return -ENOSPC; + diff --git a/queue-6.6/lockd-plug-nlm_file-leak-when-nlm_do_fopen-fails.patch b/queue-6.6/lockd-plug-nlm_file-leak-when-nlm_do_fopen-fails.patch new file mode 100644 index 0000000000..504c63fdc7 --- /dev/null +++ b/queue-6.6/lockd-plug-nlm_file-leak-when-nlm_do_fopen-fails.patch @@ -0,0 +1,38 @@ +From f16a1513452edb532fec81e591c64c320866719c Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Thu, 14 May 2026 16:56:04 -0400 +Subject: lockd: Plug nlm_file leak when nlm_do_fopen() fails + +From: Chuck Lever + +commit f16a1513452edb532fec81e591c64c320866719c upstream. + +A client can repeatedly drive nlm_do_fopen() failures by presenting +file handles that the underlying export rejects. After kzalloc_obj() +succeeds in nlm_lookup_file(), the freshly allocated nlm_file is not +yet inserted into nlm_files[]. The nlm_do_fopen() failure path jumps +to out_unlock, which releases nlm_file_mutex and returns without +freeing the allocation, so each failure leaks one nlm_file. + +Route the failure through out_free so kfree() runs before the +function returns. + +Fixes: 7f024fcd5c97 ("Keep read and write fds with each nlm_file") +Cc: stable@vger.kernel.org +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/lockd/svcsubs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/lockd/svcsubs.c ++++ b/fs/lockd/svcsubs.c +@@ -139,7 +139,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, + + nfserr = nlm_do_fopen(rqstp, file, mode); + if (nfserr) +- goto out_unlock; ++ goto out_free; + + hlist_add_head(&file->f_list, &nlm_files[hash]); + diff --git a/queue-6.6/lockd-plug-nlm_file-refcount-leak-on-cached-nlm_do_fopen-failure.patch b/queue-6.6/lockd-plug-nlm_file-refcount-leak-on-cached-nlm_do_fopen-failure.patch new file mode 100644 index 0000000000..dee8ec1122 --- /dev/null +++ b/queue-6.6/lockd-plug-nlm_file-refcount-leak-on-cached-nlm_do_fopen-failure.patch @@ -0,0 +1,42 @@ +From 70a38f87bed7f0694fd07988b47b2db1e10d8df3 Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Thu, 14 May 2026 16:56:06 -0400 +Subject: lockd: Plug nlm_file refcount leak on cached nlm_do_fopen() failure + +From: Chuck Lever + +commit 70a38f87bed7f0694fd07988b47b2db1e10d8df3 upstream. + +The cached-file path in nlm_lookup_file() reaches the found: label +unconditionally, even when nlm_do_fopen() fails. At that label +*result and file->f_count are updated before the error is returned. +The wrappers nlm3svc_lookup_file() and nlm4svc_lookup_file() then +bail out of their switch without copying *result back to their +caller, so the proc handler's local nlm_file pointer remains NULL +and the cleanup path skips nlm_release_file(). The f_count +increment is never released, and nlm_traverse_files() can no +longer reap the file because its refcount never returns to zero +between requests. + +Short-circuit the cached path so neither *result nor f_count is +touched when nlm_do_fopen() fails on a hashed nlm_file. + +Fixes: 7f024fcd5c97 ("Keep read and write fds with each nlm_file") +Cc: stable@vger.kernel.org +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/lockd/svcsubs.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/lockd/svcsubs.c ++++ b/fs/lockd/svcsubs.c +@@ -123,6 +123,8 @@ nlm_lookup_file(struct svc_rqst *rqstp, + mutex_lock(&file->f_mutex); + nfserr = nlm_do_fopen(rqstp, file, mode); + mutex_unlock(&file->f_mutex); ++ if (nfserr) ++ goto out_unlock; + goto found; + } + nlm_debug_print_fh("creating file for", &lock->fh); diff --git a/queue-6.6/nvdimm-btt-free-arena-sub-allocations-on-discover_arenas-error-path.patch b/queue-6.6/nvdimm-btt-free-arena-sub-allocations-on-discover_arenas-error-path.patch new file mode 100644 index 0000000000..382314274e --- /dev/null +++ b/queue-6.6/nvdimm-btt-free-arena-sub-allocations-on-discover_arenas-error-path.patch @@ -0,0 +1,41 @@ +From 13fe4cd9ddd0aacb7777812328be525a11ea3fea Mon Sep 17 00:00:00 2001 +From: Abdun Nihaal +Date: Tue, 19 May 2026 11:20:12 +0530 +Subject: nvdimm/btt: Free arena sub-allocations on discover_arenas() error path + +From: Abdun Nihaal + +commit 13fe4cd9ddd0aacb7777812328be525a11ea3fea upstream. + +Memory allocated by btt_freelist_init(), btt_rtt_init(), and +btt_maplocks_init() is not freed on some discover_arenas() error +paths. This leaks memory when arena discovery fails. + +Add the missing kfree() calls to release the allocations before +returning an error. + +[ as: commit message and log edits ] + +Fixes: 5212e11fde4d ("nd_btt: atomic sector updates") +Cc: stable@vger.kernel.org +Signed-off-by: Abdun Nihaal +Reviewed-by: Alison Schofield +Link: https://patch.msgid.link/20260519-nvdimmleaks-v1-1-592300fb7a43@cse.iitm.ac.in +Signed-off-by: Alison Schofield +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvdimm/btt.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/nvdimm/btt.c ++++ b/drivers/nvdimm/btt.c +@@ -923,6 +923,9 @@ static int discover_arenas(struct btt *b + return ret; + + out: ++ kfree(arena->freelist); ++ kfree(arena->rtt); ++ kfree(arena->map_locks); + kfree(arena); + free_arenas(btt); + out_super: diff --git a/queue-6.6/nvdimm-btt-free-arenas-on-btt_init-error-paths.patch b/queue-6.6/nvdimm-btt-free-arenas-on-btt_init-error-paths.patch new file mode 100644 index 0000000000..f1e849fe98 --- /dev/null +++ b/queue-6.6/nvdimm-btt-free-arenas-on-btt_init-error-paths.patch @@ -0,0 +1,72 @@ +From 1a6b6442a982d0ca5fb6a1a39b6f6dfd760eda57 Mon Sep 17 00:00:00 2001 +From: Abdun Nihaal +Date: Tue, 19 May 2026 11:20:13 +0530 +Subject: nvdimm/btt: Free arenas on btt_init() error paths + +From: Abdun Nihaal + +commit 1a6b6442a982d0ca5fb6a1a39b6f6dfd760eda57 upstream. + +The arenas allocated by discover_arenas() or create_arenas() are not +freed on some error paths in btt_init(). This leaks memory when BTT +initialization fails. + +Call free_arenas() from the affected error paths to release the +allocations. + +[ as: commit message and log edits ] + +Fixes: 5212e11fde4d ("nd_btt: atomic sector updates") +Cc: stable@vger.kernel.org +Signed-off-by: Abdun Nihaal +Reviewed-by: Alison Schofield +Link: https://patch.msgid.link/20260519-nvdimmleaks-v1-2-592300fb7a43@cse.iitm.ac.in +Signed-off-by: Alison Schofield +Signed-off-by: Greg Kroah-Hartman +--- + drivers/nvdimm/btt.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/drivers/nvdimm/btt.c ++++ b/drivers/nvdimm/btt.c +@@ -1593,7 +1593,7 @@ static struct btt *btt_init(struct nd_bt + if (btt->init_state != INIT_READY && nd_region->ro) { + dev_warn(dev, "%s is read-only, unable to init btt metadata\n", + dev_name(&nd_region->dev)); +- return NULL; ++ goto err; + } else if (btt->init_state != INIT_READY) { + btt->num_arenas = (rawsize / ARENA_MAX_SIZE) + + ((rawsize % ARENA_MAX_SIZE) ? 1 : 0); +@@ -1603,25 +1603,28 @@ static struct btt *btt_init(struct nd_bt + ret = create_arenas(btt); + if (ret) { + dev_info(dev, "init: create_arenas: %d\n", ret); +- return NULL; ++ goto err; + } + + ret = btt_meta_init(btt); + if (ret) { + dev_err(dev, "init: error in meta_init: %d\n", ret); +- return NULL; ++ goto err; + } + } + + ret = btt_blk_init(btt); + if (ret) { + dev_err(dev, "init: error in blk_init: %d\n", ret); +- return NULL; ++ goto err; + } + + btt_debugfs_init(btt); + + return btt; ++err: ++ free_arenas(btt); ++ return NULL; + } + + /** diff --git a/queue-6.6/series b/queue-6.6/series index 4baac5d379..9d0e506646 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -960,3 +960,11 @@ mfd-tps6586x-fix-of-node-refcount.patch hid-playstation-validate-num_touch_reports-in-dualshock-4-reports.patch bluetooth-sco-fix-sleeping-under-spinlock-in-sco_conn_ready.patch bluetooth-sco-hold-sk-properly-in-sco_conn_ready.patch +jbd2-fix-integer-underflow-in-jbd2_journal_initialize_fast_commit.patch +nvdimm-btt-free-arenas-on-btt_init-error-paths.patch +nvdimm-btt-free-arena-sub-allocations-on-discover_arenas-error-path.patch +sunrpc-pin-svc_xprt-across-the-asynchronous-tls-handshake-callback.patch +sunrpc-wait-for-in-flight-tls-handshake-callback-when-cancel-loses-race.patch +lockd-plug-nlm_file-leak-when-nlm_do_fopen-fails.patch +lockd-plug-nlm_file-refcount-leak-on-cached-nlm_do_fopen-failure.patch +sunrpc-bound-check-xdr_buf_to_bvec-stores-before-writing.patch diff --git a/queue-6.6/sunrpc-bound-check-xdr_buf_to_bvec-stores-before-writing.patch b/queue-6.6/sunrpc-bound-check-xdr_buf_to_bvec-stores-before-writing.patch new file mode 100644 index 0000000000..62d0964de1 --- /dev/null +++ b/queue-6.6/sunrpc-bound-check-xdr_buf_to_bvec-stores-before-writing.patch @@ -0,0 +1,80 @@ +From 42f5b80dda6b86e424054baf1475df686c403d5c Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Tue, 19 May 2026 09:34:21 -0400 +Subject: SUNRPC: Bound-check xdr_buf_to_bvec() stores before writing + +From: Chuck Lever + +commit 42f5b80dda6b86e424054baf1475df686c403d5c upstream. + +xdr_buf_to_bvec() writes a bio_vec into the caller's array before +testing whether that slot is in range, and the head branch performs +the store with no check at all. When the caller's budget is exactly +used up, the next store lands one element past the end of the array. +The overflow label returns count - 1, which masks the surplus store +but cannot undo it. + +rq_bvec, the array passed by nfsd_vfs_write(), is allocated to +exactly rq_maxpages entries with no slack. The OOB store can land in +adjacent slab memory; the bv_len and bv_offset fields written there +are derived from client-supplied RPC payload sizes. + +Move the in-range check ahead of the store in the head, page-loop, +and tail branches. With the check at the top of each sequence, count +is incremented only after a successful store, so the overflow label +can return count directly. + +Reported-by: Chris Mason +Fixes: 2eb2b9358181 ("SUNRPC: Convert svc_tcp_sendmsg to use bio_vecs directly") +Cc: stable@vger.kernel.org +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + net/sunrpc/xdr.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +--- a/net/sunrpc/xdr.c ++++ b/net/sunrpc/xdr.c +@@ -180,6 +180,8 @@ unsigned int xdr_buf_to_bvec(struct bio_ + unsigned int count = 0; + + if (head->iov_len) { ++ if (unlikely(count >= bvec_size)) ++ goto bvec_overflow; + bvec_set_virt(bvec++, head->iov_base, head->iov_len); + ++count; + } +@@ -193,25 +195,27 @@ unsigned int xdr_buf_to_bvec(struct bio_ + while (remaining > 0) { + len = min_t(unsigned int, remaining, + PAGE_SIZE - offset); ++ if (unlikely(count >= bvec_size)) ++ goto bvec_overflow; + bvec_set_page(bvec++, *pages++, len, offset); + remaining -= len; + offset = 0; +- if (unlikely(++count > bvec_size)) +- goto bvec_overflow; ++ ++count; + } + } + + if (tail->iov_len) { +- bvec_set_virt(bvec, tail->iov_base, tail->iov_len); +- if (unlikely(++count > bvec_size)) ++ if (unlikely(count >= bvec_size)) + goto bvec_overflow; ++ bvec_set_virt(bvec, tail->iov_base, tail->iov_len); ++ ++count; + } + + return count; + + bvec_overflow: + pr_warn_once("%s: bio_vec array overflow\n", __func__); +- return count - 1; ++ return count; + } + + /** diff --git a/queue-6.6/sunrpc-pin-svc_xprt-across-the-asynchronous-tls-handshake-callback.patch b/queue-6.6/sunrpc-pin-svc_xprt-across-the-asynchronous-tls-handshake-callback.patch new file mode 100644 index 0000000000..f307711c1a --- /dev/null +++ b/queue-6.6/sunrpc-pin-svc_xprt-across-the-asynchronous-tls-handshake-callback.patch @@ -0,0 +1,88 @@ +From 4f988f3a2808fb659f3880c282041ff067acad78 Mon Sep 17 00:00:00 2001 +From: Chris Mason +Date: Fri, 22 May 2026 09:39:06 -0400 +Subject: sunrpc: pin svc_xprt across the asynchronous TLS handshake callback + +From: Chris Mason + +commit 4f988f3a2808fb659f3880c282041ff067acad78 upstream. + +svc_tcp_handshake() stores the raw svc_xprt pointer in +tls_handshake_args.ta_data and submits the request through +tls_server_hello_x509(). The handshake core takes only +sock_hold(req->hr_sk); nothing references the embedding struct +svc_sock that svc_tcp_handshake_done() reaches via container_of(). + +Two close races leave the in-flight callback writing through a freed +svc_sock. svc_sock_free() calls tls_handshake_cancel() and discards +its return value: a false return means handshake_complete() has +already set HANDSHAKE_F_REQ_COMPLETED but hp_done() may not have +finished, yet svc_sock_free() proceeds to kfree(svsk). The +cancel-loser fall-through inside svc_tcp_handshake() itself produces +the same window: when wait_for_completion_interruptible_timeout() +returns <= 0 (timeout or signal) and tls_handshake_cancel() returns +false, the function does not drain, returns, and svc_handle_xprt() +calls svc_xprt_received(), which clears XPT_BUSY and can drop the +last reference. A concurrent close then runs svc_sock_free() while +svc_tcp_handshake_done() is still updating xpt_flags and walking +svsk->sk_handshake_done. + +The corruption surfaces as set_bit/clear_bit RMW into the freed +xpt_flags slab slot and as complete_all() walking and writing the +freed wait_queue_head_t list embedded in sk_handshake_done -- a +slab-corruption primitive, not a benign read. The path is reachable +on any TLS-enabled NFS server whenever a connection close overlaps +the tlshd downcall delivery window; the interruptible wait means +signal delivery suffices, not just SVC_HANDSHAKE_TO expiry. + +Take svc_xprt_get(xprt) immediately before tls_server_hello_x509() +so the in-flight callback owns its own reference. Release it on the +two edges where the callback is guaranteed not to fire -- submission +failure from tls_server_hello_x509() and a successful +tls_handshake_cancel() -- and at the tail of +svc_tcp_handshake_done() after complete_all(). + +Fixes: b3cbf98e2fdf ("SUNRPC: Support TLS handshake in the server-side TCP socket code") +Cc: stable@vger.kernel.org +Signed-off-by: Chris Mason +Assisted-by: kres (claude-opus-4-7) +[cel: rewrote commit message to describe the actual change] +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + net/sunrpc/svcsock.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/net/sunrpc/svcsock.c ++++ b/net/sunrpc/svcsock.c +@@ -462,6 +462,7 @@ static void svc_tcp_handshake_done(void + } + clear_bit(XPT_HANDSHAKE, &xprt->xpt_flags); + complete_all(&svsk->sk_handshake_done); ++ svc_xprt_put(xprt); + } + + /** +@@ -485,9 +486,13 @@ static void svc_tcp_handshake(struct svc + clear_bit(XPT_TLS_SESSION, &xprt->xpt_flags); + init_completion(&svsk->sk_handshake_done); + ++ /* Pin the transport across the asynchronous handshake callback. */ ++ svc_xprt_get(xprt); ++ + ret = tls_server_hello_x509(&args, GFP_KERNEL); + if (ret) { + trace_svc_tls_not_started(xprt); ++ svc_xprt_put(xprt); + goto out_failed; + } + +@@ -496,6 +501,7 @@ static void svc_tcp_handshake(struct svc + if (ret <= 0) { + if (tls_handshake_cancel(sk)) { + trace_svc_tls_timed_out(xprt); ++ svc_xprt_put(xprt); + goto out_close; + } + } diff --git a/queue-6.6/sunrpc-wait-for-in-flight-tls-handshake-callback-when-cancel-loses-race.patch b/queue-6.6/sunrpc-wait-for-in-flight-tls-handshake-callback-when-cancel-loses-race.patch new file mode 100644 index 0000000000..dff17863ef --- /dev/null +++ b/queue-6.6/sunrpc-wait-for-in-flight-tls-handshake-callback-when-cancel-loses-race.patch @@ -0,0 +1,62 @@ +From d00e32f84ca1a77cb67a3fbf59f58dada95f5a21 Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Fri, 22 May 2026 09:39:07 -0400 +Subject: sunrpc: wait for in-flight TLS handshake callback when cancel loses race + +From: Chuck Lever + +commit d00e32f84ca1a77cb67a3fbf59f58dada95f5a21 upstream. + +When wait_for_completion_interruptible_timeout() in +svc_tcp_handshake() returns 0 (timeout) or -ERESTARTSYS (signal) and +tls_handshake_cancel() then returns false, handshake_complete() has +won the cancellation race: it has set HANDSHAKE_F_REQ_COMPLETED and +is about to invoke svc_tcp_handshake_done(), but the callback's +side effects on xpt_flags and on svsk->sk_handshake_done have not +yet committed. + +The current code reads xpt_flags immediately to decide whether the +session succeeded. Two races result. + +If the callback has executed set_bit(XPT_TLS_SESSION) but not yet +clear_bit(XPT_HANDSHAKE), svc_tcp_handshake() sees a session, +enqueues the transport, and returns. svc_xprt_received() then +clears XPT_BUSY, a worker thread picks the transport up, the +dispatcher in svc_handle_xprt() observes XPT_HANDSHAKE still set, +and xpo_handshake is invoked a second time. That svc_tcp_handshake() +calls init_completion(&svsk->sk_handshake_done) while the original +callback concurrently calls complete_all() on it, corrupting the +embedded swait_queue. + +If the callback has set HANDSHAKE_F_REQ_COMPLETED but not yet +entered svc_tcp_handshake_done(), svc_tcp_handshake() reads +XPT_TLS_SESSION as clear and tears the connection down even though +the handshake is about to succeed. + +Wait for the callback to commit before inspecting xpt_flags. The +completion is guaranteed to fire because handshake_complete() +invokes svc_tcp_handshake_done() unconditionally once it has set +HANDSHAKE_F_REQ_COMPLETED. + +Fixes: b3cbf98e2fdf ("SUNRPC: Support TLS handshake in the server-side TCP socket code") +Cc: stable@vger.kernel.org +Reviewed-by: Jeff Layton +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + net/sunrpc/svcsock.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/sunrpc/svcsock.c ++++ b/net/sunrpc/svcsock.c +@@ -504,6 +504,10 @@ static void svc_tcp_handshake(struct svc + svc_xprt_put(xprt); + goto out_close; + } ++ /* Cancellation lost to handshake_complete(): the ++ * callback is in flight and should finish quickly. ++ */ ++ wait_for_completion(&svsk->sk_handshake_done); + } + + if (!test_bit(XPT_TLS_SESSION, &xprt->xpt_flags)) {