This is a note to let you know that I've just added the patch titled SUNRPC: Avoid deep recursion in rpc_release_client to the 3.12-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: sunrpc-avoid-deep-recursion-in-rpc_release_client.patch and it can be found in the queue-3.12 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From d07ba8422f1e58be94cc98a1f475946dc1b89f1b Mon Sep 17 00:00:00 2001 From: Trond Myklebust <Trond.Myklebust@xxxxxxxxxx> Date: Tue, 12 Nov 2013 17:24:36 -0500 Subject: SUNRPC: Avoid deep recursion in rpc_release_client From: Trond Myklebust <Trond.Myklebust@xxxxxxxxxx> commit d07ba8422f1e58be94cc98a1f475946dc1b89f1b upstream. In cases where an rpc client has a parent hierarchy, then rpc_free_client may end up calling rpc_release_client() on the parent, thus recursing back into rpc_free_client. If the hierarchy is deep enough, then we can get into situations where the stack simply overflows. The fix is to have rpc_release_client() loop so that it can take care of the parent rpc client hierarchy without needing to recurse. Reported-by: Jeff Layton <jlayton@xxxxxxxxxx> Reported-by: Weston Andros Adamson <dros@xxxxxxxxxx> Reported-by: Bruce Fields <bfields@xxxxxxxxxxxx> Link: http://lkml.kernel.org/r/2C73011F-0939-434C-9E4D-13A1EB1403D7@xxxxxxxxxx Signed-off-by: Trond Myklebust <Trond.Myklebust@xxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- net/sunrpc/clnt.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -656,14 +656,16 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); /* * Free an RPC client */ -static void +static struct rpc_clnt * rpc_free_client(struct rpc_clnt *clnt) { + struct rpc_clnt *parent = NULL; + dprintk_rcu("RPC: destroying %s client for %s\n", clnt->cl_program->name, rcu_dereference(clnt->cl_xprt)->servername); if (clnt->cl_parent != clnt) - rpc_release_client(clnt->cl_parent); + parent = clnt->cl_parent; rpc_clnt_remove_pipedir(clnt); rpc_unregister_client(clnt); rpc_free_iostats(clnt->cl_metrics); @@ -672,18 +674,17 @@ rpc_free_client(struct rpc_clnt *clnt) rpciod_down(); rpc_free_clid(clnt); kfree(clnt); + return parent; } /* * Free an RPC client */ -static void +static struct rpc_clnt * rpc_free_auth(struct rpc_clnt *clnt) { - if (clnt->cl_auth == NULL) { - rpc_free_client(clnt); - return; - } + if (clnt->cl_auth == NULL) + return rpc_free_client(clnt); /* * Note: RPCSEC_GSS may need to send NULL RPC calls in order to @@ -694,7 +695,8 @@ rpc_free_auth(struct rpc_clnt *clnt) rpcauth_release(clnt->cl_auth); clnt->cl_auth = NULL; if (atomic_dec_and_test(&clnt->cl_count)) - rpc_free_client(clnt); + return rpc_free_client(clnt); + return NULL; } /* @@ -705,10 +707,13 @@ rpc_release_client(struct rpc_clnt *clnt { dprintk("RPC: rpc_release_client(%p)\n", clnt); - if (list_empty(&clnt->cl_tasks)) - wake_up(&destroy_wait); - if (atomic_dec_and_test(&clnt->cl_count)) - rpc_free_auth(clnt); + do { + if (list_empty(&clnt->cl_tasks)) + wake_up(&destroy_wait); + if (!atomic_dec_and_test(&clnt->cl_count)) + break; + clnt = rpc_free_auth(clnt); + } while (clnt != NULL); } EXPORT_SYMBOL_GPL(rpc_release_client); Patches currently in stable-queue which might be from Trond.Myklebust@xxxxxxxxxx are queue-3.12/nfsv4.2-fix-a-mismatch-between-linux-labeled-nfs-and-the-nfsv4.2-spec.patch queue-3.12/nfs-fix-oops-when-trying-to-set-selinux-label.patch queue-3.12/nfs-fix-a-missing-initialisation-when-reading-the-selinux-label.patch queue-3.12/sunrpc-avoid-deep-recursion-in-rpc_release_client.patch queue-3.12/nfsv4-fix-a-use-after-free-situation-in-_nfs4_proc_getlk.patch queue-3.12/nfs-fix-inverted-test-for-delegation-in-nfs4_reclaim_open_state.patch queue-3.12/nfsv4-fix-null-dereference-in-open-recover.patch queue-3.12/nfs-don-t-retry-detect_trunking-with-rpc_auth_unix-more-than-once.patch queue-3.12/nfsv4-don-t-reprocess-cached-open-claim_previous.patch queue-3.12/nfsv4-fix-state-reference-counting-in-_nfs4_opendata_reclaim_to_nfs4_state.patch queue-3.12/nfsv4-don-t-fail-on-missing-fattr-in-open-recover.patch queue-3.12/sunrpc-gss_alloc_msg-choose-_either_-a-v0-message-or-a-v1-message.patch queue-3.12/sunrpc-fix-a-data-corruption-issue-when-retransmitting-rpc-calls.patch -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html