aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-05-15 13:27:32 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-05-16 09:17:54 -0400
commit2aed8b476f3478be140df92bbfb182978e835504 (patch)
tree1ec837ead098b2eae7e4d8a8ad5f325c7591285e
parentabfdbd53a4e28844ad953b313f017f55edbb85b7 (diff)
SUNRPC: Convert auth_gss pipe detection to work in namespaces
This seems to have been overlooked when we did the namespace conversion. If a container is running a legacy version of rpc.gssd then it will be disrupted if the global 'pipe_version' is set by a container running the new version of rpc.gssd. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c46
-rw-r--r--net/sunrpc/netns.h2
-rw-r--r--net/sunrpc/rpc_pipe.c1
3 files changed, 30 insertions, 19 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 3aff72f78bf2..fc2f78d6a9b4 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -87,8 +87,6 @@ struct gss_auth {
87}; 87};
88 88
89/* pipe_version >= 0 if and only if someone has a pipe open. */ 89/* pipe_version >= 0 if and only if someone has a pipe open. */
90static int pipe_version = -1;
91static atomic_t pipe_users = ATOMIC_INIT(0);
92static DEFINE_SPINLOCK(pipe_version_lock); 90static DEFINE_SPINLOCK(pipe_version_lock);
93static struct rpc_wait_queue pipe_version_rpc_waitqueue; 91static struct rpc_wait_queue pipe_version_rpc_waitqueue;
94static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); 92static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue);
@@ -268,24 +266,27 @@ struct gss_upcall_msg {
268 char databuf[UPCALL_BUF_LEN]; 266 char databuf[UPCALL_BUF_LEN];
269}; 267};
270 268
271static int get_pipe_version(void) 269static int get_pipe_version(struct net *net)
272{ 270{
271 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
273 int ret; 272 int ret;
274 273
275 spin_lock(&pipe_version_lock); 274 spin_lock(&pipe_version_lock);
276 if (pipe_version >= 0) { 275 if (sn->pipe_version >= 0) {
277 atomic_inc(&pipe_users); 276 atomic_inc(&sn->pipe_users);
278 ret = pipe_version; 277 ret = sn->pipe_version;
279 } else 278 } else
280 ret = -EAGAIN; 279 ret = -EAGAIN;
281 spin_unlock(&pipe_version_lock); 280 spin_unlock(&pipe_version_lock);
282 return ret; 281 return ret;
283} 282}
284 283
285static void put_pipe_version(void) 284static void put_pipe_version(struct net *net)
286{ 285{
287 if (atomic_dec_and_lock(&pipe_users, &pipe_version_lock)) { 286 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
288 pipe_version = -1; 287
288 if (atomic_dec_and_lock(&sn->pipe_users, &pipe_version_lock)) {
289 sn->pipe_version = -1;
289 spin_unlock(&pipe_version_lock); 290 spin_unlock(&pipe_version_lock);
290 } 291 }
291} 292}
@@ -293,9 +294,10 @@ static void put_pipe_version(void)
293static void 294static void
294gss_release_msg(struct gss_upcall_msg *gss_msg) 295gss_release_msg(struct gss_upcall_msg *gss_msg)
295{ 296{
297 struct net *net = rpc_net_ns(gss_msg->auth->client);
296 if (!atomic_dec_and_test(&gss_msg->count)) 298 if (!atomic_dec_and_test(&gss_msg->count))
297 return; 299 return;
298 put_pipe_version(); 300 put_pipe_version(net);
299 BUG_ON(!list_empty(&gss_msg->list)); 301 BUG_ON(!list_empty(&gss_msg->list));
300 if (gss_msg->ctx != NULL) 302 if (gss_msg->ctx != NULL)
301 gss_put_ctx(gss_msg->ctx); 303 gss_put_ctx(gss_msg->ctx);
@@ -441,7 +443,10 @@ static void gss_encode_msg(struct gss_upcall_msg *gss_msg,
441 struct rpc_clnt *clnt, 443 struct rpc_clnt *clnt,
442 const char *service_name) 444 const char *service_name)
443{ 445{
444 if (pipe_version == 0) 446 struct net *net = rpc_net_ns(clnt);
447 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
448
449 if (sn->pipe_version == 0)
445 gss_encode_v0_msg(gss_msg); 450 gss_encode_v0_msg(gss_msg);
446 else /* pipe_version == 1 */ 451 else /* pipe_version == 1 */
447 gss_encode_v1_msg(gss_msg, clnt, service_name); 452 gss_encode_v1_msg(gss_msg, clnt, service_name);
@@ -457,7 +462,7 @@ gss_alloc_msg(struct gss_auth *gss_auth, struct rpc_clnt *clnt,
457 gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); 462 gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS);
458 if (gss_msg == NULL) 463 if (gss_msg == NULL)
459 return ERR_PTR(-ENOMEM); 464 return ERR_PTR(-ENOMEM);
460 vers = get_pipe_version(); 465 vers = get_pipe_version(rpc_net_ns(clnt));
461 if (vers < 0) { 466 if (vers < 0) {
462 kfree(gss_msg); 467 kfree(gss_msg);
463 return ERR_PTR(vers); 468 return ERR_PTR(vers);
@@ -581,8 +586,8 @@ retry:
581 gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); 586 gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred);
582 if (PTR_ERR(gss_msg) == -EAGAIN) { 587 if (PTR_ERR(gss_msg) == -EAGAIN) {
583 err = wait_event_interruptible_timeout(pipe_version_waitqueue, 588 err = wait_event_interruptible_timeout(pipe_version_waitqueue,
584 pipe_version >= 0, timeout); 589 sn->pipe_version >= 0, timeout);
585 if (pipe_version < 0) { 590 if (sn->pipe_version < 0) {
586 if (err == 0) 591 if (err == 0)
587 sn->gssd_running = 0; 592 sn->gssd_running = 0;
588 warn_gssd(); 593 warn_gssd();
@@ -719,20 +724,22 @@ out:
719 724
720static int gss_pipe_open(struct inode *inode, int new_version) 725static int gss_pipe_open(struct inode *inode, int new_version)
721{ 726{
727 struct net *net = inode->i_sb->s_fs_info;
728 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
722 int ret = 0; 729 int ret = 0;
723 730
724 spin_lock(&pipe_version_lock); 731 spin_lock(&pipe_version_lock);
725 if (pipe_version < 0) { 732 if (sn->pipe_version < 0) {
726 /* First open of any gss pipe determines the version: */ 733 /* First open of any gss pipe determines the version: */
727 pipe_version = new_version; 734 sn->pipe_version = new_version;
728 rpc_wake_up(&pipe_version_rpc_waitqueue); 735 rpc_wake_up(&pipe_version_rpc_waitqueue);
729 wake_up(&pipe_version_waitqueue); 736 wake_up(&pipe_version_waitqueue);
730 } else if (pipe_version != new_version) { 737 } else if (sn->pipe_version != new_version) {
731 /* Trying to open a pipe of a different version */ 738 /* Trying to open a pipe of a different version */
732 ret = -EBUSY; 739 ret = -EBUSY;
733 goto out; 740 goto out;
734 } 741 }
735 atomic_inc(&pipe_users); 742 atomic_inc(&sn->pipe_users);
736out: 743out:
737 spin_unlock(&pipe_version_lock); 744 spin_unlock(&pipe_version_lock);
738 return ret; 745 return ret;
@@ -752,6 +759,7 @@ static int gss_pipe_open_v1(struct inode *inode)
752static void 759static void
753gss_pipe_release(struct inode *inode) 760gss_pipe_release(struct inode *inode)
754{ 761{
762 struct net *net = inode->i_sb->s_fs_info;
755 struct rpc_pipe *pipe = RPC_I(inode)->pipe; 763 struct rpc_pipe *pipe = RPC_I(inode)->pipe;
756 struct gss_upcall_msg *gss_msg; 764 struct gss_upcall_msg *gss_msg;
757 765
@@ -770,7 +778,7 @@ restart:
770 } 778 }
771 spin_unlock(&pipe->lock); 779 spin_unlock(&pipe->lock);
772 780
773 put_pipe_version(); 781 put_pipe_version(net);
774} 782}
775 783
776static void 784static void
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
index 0827f641e8d7..74d948f5d5a1 100644
--- a/net/sunrpc/netns.h
+++ b/net/sunrpc/netns.h
@@ -28,6 +28,8 @@ struct sunrpc_net {
28 wait_queue_head_t gssp_wq; 28 wait_queue_head_t gssp_wq;
29 struct rpc_clnt *gssp_clnt; 29 struct rpc_clnt *gssp_clnt;
30 int use_gss_proxy; 30 int use_gss_proxy;
31 int pipe_version;
32 atomic_t pipe_users;
31 struct proc_dir_entry *use_gssp_proc; 33 struct proc_dir_entry *use_gssp_proc;
32 34
33 unsigned int gssd_running; 35 unsigned int gssd_running;
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index a370762e459d..e7ce4b3eb0bd 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -1073,6 +1073,7 @@ void rpc_pipefs_init_net(struct net *net)
1073 1073
1074 mutex_init(&sn->pipefs_sb_lock); 1074 mutex_init(&sn->pipefs_sb_lock);
1075 sn->gssd_running = 1; 1075 sn->gssd_running = 1;
1076 sn->pipe_version = -1;
1076} 1077}
1077 1078
1078/* 1079/*