diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-02-16 12:14:13 -0500 |
---|---|---|
committer | Jiri Slaby <jslaby@suse.cz> | 2014-03-05 17:13:45 +0100 |
commit | 9f93a183e6266283dce26ad92855ba7b7472c9cd (patch) | |
tree | ce2ab634d2f0e2845a9931b47e8a97eab815277e /net/sunrpc | |
parent | d1c07003693c1944ef9ee8ad484c61be61829ce7 (diff) | |
download | linux-stable-9f93a183e6266283dce26ad92855ba7b7472c9cd.tar.gz linux-stable-9f93a183e6266283dce26ad92855ba7b7472c9cd.tar.bz2 linux-stable-9f93a183e6266283dce26ad92855ba7b7472c9cd.zip |
SUNRPC: Ensure that gss_auth isn't freed before its upcall messages
commit 9eb2ddb48ce3a7bd745c14a933112994647fa3cd upstream.
Fix a race in which the RPC client is shutting down while the
gss daemon is processing a downcall. If the RPC client manages to
shut down before the gss daemon is done, then the struct gss_auth
used in gss_release_msg() may have already been freed.
Link: http://lkml.kernel.org/r/1392494917.71728.YahooMailNeo@web140002.mail.bf1.yahoo.com
Reported-by: John <da_audiophile@yahoo.com>
Reported-by: Borislav Petkov <bp@alien8.de>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index cc24323d3045..a7f9821d1760 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -108,6 +108,7 @@ struct gss_auth { static DEFINE_SPINLOCK(pipe_version_lock); static struct rpc_wait_queue pipe_version_rpc_waitqueue; static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); +static void gss_put_auth(struct gss_auth *gss_auth); static void gss_free_ctx(struct gss_cl_ctx *); static const struct rpc_pipe_ops gss_upcall_ops_v0; @@ -320,6 +321,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg) if (gss_msg->ctx != NULL) gss_put_ctx(gss_msg->ctx); rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue); + gss_put_auth(gss_msg->auth); kfree(gss_msg); } @@ -486,6 +488,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, default: gss_encode_v1_msg(gss_msg, service_name, gss_auth->target_name); }; + kref_get(&gss_auth->kref); return gss_msg; } @@ -1053,6 +1056,12 @@ gss_free_callback(struct kref *kref) } static void +gss_put_auth(struct gss_auth *gss_auth) +{ + kref_put(&gss_auth->kref, gss_free_callback); +} + +static void gss_destroy(struct rpc_auth *auth) { struct gss_auth *gss_auth = container_of(auth, @@ -1073,7 +1082,7 @@ gss_destroy(struct rpc_auth *auth) gss_auth->gss_pipe[1] = NULL; rpcauth_destroy_credcache(auth); - kref_put(&gss_auth->kref, gss_free_callback); + gss_put_auth(gss_auth); } /* @@ -1244,7 +1253,7 @@ gss_destroy_nullcred(struct rpc_cred *cred) call_rcu(&cred->cr_rcu, gss_free_cred_callback); if (ctx) gss_put_ctx(ctx); - kref_put(&gss_auth->kref, gss_free_callback); + gss_put_auth(gss_auth); } static void |