diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-02-16 12:14:13 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-02-16 13:06:06 -0500 |
commit | 9eb2ddb48ce3a7bd745c14a933112994647fa3cd (patch) | |
tree | 3ddc95def93147d05ea19eb623d97e3d984e6773 /net/sunrpc | |
parent | 628356791b04ea988fee070f66a748a823d001bb (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.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 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 { | |||
108 | static DEFINE_SPINLOCK(pipe_version_lock); | 108 | static DEFINE_SPINLOCK(pipe_version_lock); |
109 | static struct rpc_wait_queue pipe_version_rpc_waitqueue; | 109 | static struct rpc_wait_queue pipe_version_rpc_waitqueue; |
110 | static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); | 110 | static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); |
111 | static void gss_put_auth(struct gss_auth *gss_auth); | ||
111 | 112 | ||
112 | static void gss_free_ctx(struct gss_cl_ctx *); | 113 | static void gss_free_ctx(struct gss_cl_ctx *); |
113 | static const struct rpc_pipe_ops gss_upcall_ops_v0; | 114 | static 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; |
504 | err_free_msg: | 507 | err_free_msg: |
505 | kfree(gss_msg); | 508 | kfree(gss_msg); |
@@ -1064,6 +1067,12 @@ gss_free_callback(struct kref *kref) | |||
1064 | } | 1067 | } |
1065 | 1068 | ||
1066 | static void | 1069 | static void |
1070 | gss_put_auth(struct gss_auth *gss_auth) | ||
1071 | { | ||
1072 | kref_put(&gss_auth->kref, gss_free_callback); | ||
1073 | } | ||
1074 | |||
1075 | static void | ||
1067 | gss_destroy(struct rpc_auth *auth) | 1076 | gss_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 | ||
1261 | static void | 1270 | static void |