提交 9eb2ddb4 编写于 作者: T Trond Myklebust

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.comReported-by: NJohn <da_audiophile@yahoo.com>
Reported-by: NBorislav Petkov <bp@alien8.de>
Cc: stable@vger.kernel.org # 3.12+
Signed-off-by: NTrond Myklebust <trond.myklebust@primarydata.com>
上级 62835679
...@@ -108,6 +108,7 @@ struct gss_auth { ...@@ -108,6 +108,7 @@ struct gss_auth {
static DEFINE_SPINLOCK(pipe_version_lock); static DEFINE_SPINLOCK(pipe_version_lock);
static struct rpc_wait_queue pipe_version_rpc_waitqueue; static struct rpc_wait_queue pipe_version_rpc_waitqueue;
static DECLARE_WAIT_QUEUE_HEAD(pipe_version_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 void gss_free_ctx(struct gss_cl_ctx *);
static const struct rpc_pipe_ops gss_upcall_ops_v0; static const struct rpc_pipe_ops gss_upcall_ops_v0;
...@@ -320,6 +321,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg) ...@@ -320,6 +321,7 @@ gss_release_msg(struct gss_upcall_msg *gss_msg)
if (gss_msg->ctx != NULL) if (gss_msg->ctx != NULL)
gss_put_ctx(gss_msg->ctx); gss_put_ctx(gss_msg->ctx);
rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue); rpc_destroy_wait_queue(&gss_msg->rpc_waitqueue);
gss_put_auth(gss_msg->auth);
kfree(gss_msg); kfree(gss_msg);
} }
...@@ -500,6 +502,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, ...@@ -500,6 +502,7 @@ gss_alloc_msg(struct gss_auth *gss_auth,
if (err) if (err)
goto err_free_msg; goto err_free_msg;
}; };
kref_get(&gss_auth->kref);
return gss_msg; return gss_msg;
err_free_msg: err_free_msg:
kfree(gss_msg); kfree(gss_msg);
...@@ -1063,6 +1066,12 @@ gss_free_callback(struct kref *kref) ...@@ -1063,6 +1066,12 @@ gss_free_callback(struct kref *kref)
gss_free(gss_auth); gss_free(gss_auth);
} }
static void
gss_put_auth(struct gss_auth *gss_auth)
{
kref_put(&gss_auth->kref, gss_free_callback);
}
static void static void
gss_destroy(struct rpc_auth *auth) gss_destroy(struct rpc_auth *auth)
{ {
...@@ -1084,7 +1093,7 @@ gss_destroy(struct rpc_auth *auth) ...@@ -1084,7 +1093,7 @@ gss_destroy(struct rpc_auth *auth)
gss_auth->gss_pipe[1] = NULL; gss_auth->gss_pipe[1] = NULL;
rpcauth_destroy_credcache(auth); rpcauth_destroy_credcache(auth);
kref_put(&gss_auth->kref, gss_free_callback); gss_put_auth(gss_auth);
} }
/* /*
...@@ -1255,7 +1264,7 @@ gss_destroy_nullcred(struct rpc_cred *cred) ...@@ -1255,7 +1264,7 @@ gss_destroy_nullcred(struct rpc_cred *cred)
call_rcu(&cred->cr_rcu, gss_free_cred_callback); call_rcu(&cred->cr_rcu, gss_free_cred_callback);
if (ctx) if (ctx)
gss_put_ctx(ctx); gss_put_ctx(ctx);
kref_put(&gss_auth->kref, gss_free_callback); gss_put_auth(gss_auth);
} }
static void static void
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册