aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2014-02-16 12:14:13 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-02-16 13:06:06 -0500
commit9eb2ddb48ce3a7bd745c14a933112994647fa3cd (patch)
tree3ddc95def93147d05ea19eb623d97e3d984e6773 /net/sunrpc
parent628356791b04ea988fee070f66a748a823d001bb (diff)
SUNRPC: Ensure that gss_auth isn't freed before its upcall messages
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> Cc: stable@vger.kernel.org # 3.12+ Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c13
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 44a61e8fda6f..1ba1fd114912 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -108,6 +108,7 @@ struct gss_auth {
108static DEFINE_SPINLOCK(pipe_version_lock); 108static DEFINE_SPINLOCK(pipe_version_lock);
109static struct rpc_wait_queue pipe_version_rpc_waitqueue; 109static struct rpc_wait_queue pipe_version_rpc_waitqueue;
110static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); 110static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue);
111static void gss_put_auth(struct gss_auth *gss_auth);
111 112
112static void gss_free_ctx(struct gss_cl_ctx *); 113static void gss_free_ctx(struct gss_cl_ctx *);
113static const struct rpc_pipe_ops gss_upcall_ops_v0; 114static const struct rpc_pipe_ops gss_upcall_ops_v0;
@@ -320,6 +321,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
320 if (gss_msg->ctx != NULL) 321 if (gss_msg->ctx != NULL)
321 gss_put_ctx(gss_msg->ctx); 322 gss_put_ctx(gss_msg->ctx);
322 rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue); 323 rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue);
324 gss_put_auth(gss_msg->auth);
323 kfree(gss_msg); 325 kfree(gss_msg);
324} 326}
325 327
@@ -500,6 +502,7 @@ gss_alloc_msg(struct gss_auth *gss_auth,
500 if (err) 502 if (err)
501 goto err_free_msg; 503 goto err_free_msg;
502 }; 504 };
505 kref_get(&gss_auth->kref);
503 return gss_msg; 506 return gss_msg;
504err_free_msg: 507err_free_msg:
505 kfree(gss_msg); 508 kfree(gss_msg);
@@ -1064,6 +1067,12 @@ gss_free_callback(struct kref *kref)
1064} 1067}
1065 1068
1066static void 1069static void
1070gss_put_auth(struct gss_auth *gss_auth)
1071{
1072 kref_put(&gss_auth->kref, gss_free_callback);
1073}
1074
1075static void
1067gss_destroy(struct rpc_auth *auth) 1076gss_destroy(struct rpc_auth *auth)
1068{ 1077{
1069 struct gss_auth *gss_auth = container_of(auth, 1078 struct gss_auth *gss_auth = container_of(auth,
@@ -1084,7 +1093,7 @@ gss_destroy(struct rpc_auth *auth)
1084 gss_auth->gss_pipe[1] = NULL; 1093 gss_auth->gss_pipe[1] = NULL;
1085 rpcauth_destroy_credcache(auth); 1094 rpcauth_destroy_credcache(auth);
1086 1095
1087 kref_put(&gss_auth->kref, gss_free_callback); 1096 gss_put_auth(gss_auth);
1088} 1097}
1089 1098
1090/* 1099/*
@@ -1255,7 +1264,7 @@ gss_destroy_nullcred(struct rpc_cred *cred)
1255 call_rcu(&cred->cr_rcu, gss_free_cred_callback); 1264 call_rcu(&cred->cr_rcu, gss_free_cred_callback);
1256 if (ctx) 1265 if (ctx)
1257 gss_put_ctx(ctx); 1266 gss_put_ctx(ctx);
1258 kref_put(&gss_auth->kref, gss_free_callback); 1267 gss_put_auth(gss_auth);
1259} 1268}
1260 1269
1261static void 1270static void