summaryrefslogtreecommitdiff
path: root/kernels/linux-libre-grsec/0001-SUNRPC-Ensure-that-gss_auth-isn-t-freed-before-its-u.patch
diff options
context:
space:
mode:
Diffstat (limited to 'kernels/linux-libre-grsec/0001-SUNRPC-Ensure-that-gss_auth-isn-t-freed-before-its-u.patch')
-rw-r--r--kernels/linux-libre-grsec/0001-SUNRPC-Ensure-that-gss_auth-isn-t-freed-before-its-u.patch82
1 files changed, 82 insertions, 0 deletions
diff --git a/kernels/linux-libre-grsec/0001-SUNRPC-Ensure-that-gss_auth-isn-t-freed-before-its-u.patch b/kernels/linux-libre-grsec/0001-SUNRPC-Ensure-that-gss_auth-isn-t-freed-before-its-u.patch
new file mode 100644
index 000000000..93803d2e6
--- /dev/null
+++ b/kernels/linux-libre-grsec/0001-SUNRPC-Ensure-that-gss_auth-isn-t-freed-before-its-u.patch
@@ -0,0 +1,82 @@
+From 2bd7c7b5f011b3d57e4f5625b561a6f3f2f34a81 Mon Sep 17 00:00:00 2001
+From: Trond Myklebust <trond.myklebust@primarydata.com>
+Date: Sun, 16 Feb 2014 12:14:13 -0500
+Subject: [PATCH] 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>
+---
+ net/sunrpc/auth_gss/auth_gss.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 42fdfc6..a642fd616 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);
+ }
+
+@@ -500,6 +502,7 @@ gss_alloc_msg(struct gss_auth *gss_auth,
+ if (err)
+ goto err_free_msg;
+ };
++ kref_get(&gss_auth->kref);
+ return gss_msg;
+ err_free_msg:
+ kfree(gss_msg);
+@@ -1071,6 +1074,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,
+@@ -1091,7 +1100,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);
+ }
+
+ /*
+@@ -1262,7 +1271,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
+--
+1.9.0
+