Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+30 -19
+27 -19
net/sunrpc/auth_gss/auth_gss.c
··· 87 87 }; 88 88 89 89 /* pipe_version >= 0 if and only if someone has a pipe open. */ 90 - static int pipe_version = -1; 91 - static atomic_t pipe_users = ATOMIC_INIT(0); 92 90 static DEFINE_SPINLOCK(pipe_version_lock); 93 91 static struct rpc_wait_queue pipe_version_rpc_waitqueue; 94 92 static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); ··· 266 268 char databuf[UPCALL_BUF_LEN]; 267 269 }; 268 270 269 - static int get_pipe_version(void) 271 + static int get_pipe_version(struct net *net) 270 272 { 273 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 271 274 int ret; 272 275 273 276 spin_lock(&pipe_version_lock); 274 - if (pipe_version >= 0) { 275 - atomic_inc(&pipe_users); 276 - ret = pipe_version; 277 + if (sn->pipe_version >= 0) { 278 + atomic_inc(&sn->pipe_users); 279 + ret = sn->pipe_version; 277 280 } else 278 281 ret = -EAGAIN; 279 282 spin_unlock(&pipe_version_lock); 280 283 return ret; 281 284 } 282 285 283 - static void put_pipe_version(void) 286 + static void put_pipe_version(struct net *net) 284 287 { 285 - if (atomic_dec_and_lock(&pipe_users, &pipe_version_lock)) { 286 - pipe_version = -1; 288 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 289 + 290 + if (atomic_dec_and_lock(&sn->pipe_users, &pipe_version_lock)) { 291 + sn->pipe_version = -1; 287 292 spin_unlock(&pipe_version_lock); 288 293 } 289 294 } ··· 294 293 static void 295 294 gss_release_msg(struct gss_upcall_msg *gss_msg) 296 295 { 296 + struct net *net = rpc_net_ns(gss_msg->auth->client); 297 297 if (!atomic_dec_and_test(&gss_msg->count)) 298 298 return; 299 - put_pipe_version(); 299 + put_pipe_version(net); 300 300 BUG_ON(!list_empty(&gss_msg->list)); 301 301 if (gss_msg->ctx != NULL) 302 302 gss_put_ctx(gss_msg->ctx); ··· 443 441 struct rpc_clnt *clnt, 444 442 const char *service_name) 445 443 { 446 - if (pipe_version == 0) 444 + struct net *net = rpc_net_ns(clnt); 445 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 446 + 447 + if (sn->pipe_version == 0) 447 448 gss_encode_v0_msg(gss_msg); 448 449 else /* pipe_version == 1 */ 449 450 gss_encode_v1_msg(gss_msg, clnt, service_name); ··· 462 457 gss_msg = kzalloc(sizeof(*gss_msg), GFP_NOFS); 463 458 if (gss_msg == NULL) 464 459 return ERR_PTR(-ENOMEM); 465 - vers = get_pipe_version(); 460 + vers = get_pipe_version(rpc_net_ns(clnt)); 466 461 if (vers < 0) { 467 462 kfree(gss_msg); 468 463 return ERR_PTR(vers); ··· 586 581 gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred); 587 582 if (PTR_ERR(gss_msg) == -EAGAIN) { 588 583 err = wait_event_interruptible_timeout(pipe_version_waitqueue, 589 - pipe_version >= 0, timeout); 590 - if (pipe_version < 0) { 584 + sn->pipe_version >= 0, timeout); 585 + if (sn->pipe_version < 0) { 591 586 if (err == 0) 592 587 sn->gssd_running = 0; 593 588 warn_gssd(); ··· 724 719 725 720 static int gss_pipe_open(struct inode *inode, int new_version) 726 721 { 722 + struct net *net = inode->i_sb->s_fs_info; 723 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 727 724 int ret = 0; 728 725 729 726 spin_lock(&pipe_version_lock); 730 - if (pipe_version < 0) { 727 + if (sn->pipe_version < 0) { 731 728 /* First open of any gss pipe determines the version: */ 732 - pipe_version = new_version; 729 + sn->pipe_version = new_version; 733 730 rpc_wake_up(&pipe_version_rpc_waitqueue); 734 731 wake_up(&pipe_version_waitqueue); 735 - } else if (pipe_version != new_version) { 732 + } else if (sn->pipe_version != new_version) { 736 733 /* Trying to open a pipe of a different version */ 737 734 ret = -EBUSY; 738 735 goto out; 739 736 } 740 - atomic_inc(&pipe_users); 737 + atomic_inc(&sn->pipe_users); 741 738 out: 742 739 spin_unlock(&pipe_version_lock); 743 740 return ret; ··· 759 752 static void 760 753 gss_pipe_release(struct inode *inode) 761 754 { 755 + struct net *net = inode->i_sb->s_fs_info; 762 756 struct rpc_pipe *pipe = RPC_I(inode)->pipe; 763 757 struct gss_upcall_msg *gss_msg; 764 758 ··· 778 770 } 779 771 spin_unlock(&pipe->lock); 780 772 781 - put_pipe_version(); 773 + put_pipe_version(net); 782 774 } 783 775 784 776 static void
+2
net/sunrpc/netns.h
··· 28 28 wait_queue_head_t gssp_wq; 29 29 struct rpc_clnt *gssp_clnt; 30 30 int use_gss_proxy; 31 + int pipe_version; 32 + atomic_t pipe_users; 31 33 struct proc_dir_entry *use_gssp_proc; 32 34 33 35 unsigned int gssd_running;
+1
net/sunrpc/rpc_pipe.c
··· 1073 1073 1074 1074 mutex_init(&sn->pipefs_sb_lock); 1075 1075 sn->gssd_running = 1; 1076 + sn->pipe_version = -1; 1076 1077 } 1077 1078 1078 1079 /*