aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c116
1 files changed, 96 insertions, 20 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index fe06acd6029b..153b3e11e61a 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -72,7 +72,13 @@ struct gss_auth {
72 struct gss_api_mech *mech; 72 struct gss_api_mech *mech;
73 enum rpc_gss_svc service; 73 enum rpc_gss_svc service;
74 struct rpc_clnt *client; 74 struct rpc_clnt *client;
75 struct dentry *dentry; 75 /*
76 * There are two upcall pipes; dentry[1], named "gssd", is used
77 * for the new text-based upcall; dentry[0] is named after the
78 * mechanism (for example, "krb5") and exists for
79 * backwards-compatibility with older gssd's.
80 */
81 struct dentry *dentry[2];
76}; 82};
77 83
78/* pipe_version >= 0 if and only if someone has a pipe open. */ 84/* pipe_version >= 0 if and only if someone has a pipe open. */
@@ -83,7 +89,8 @@ static struct rpc_wait_queue pipe_version_rpc_waitqueue;
83static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue); 89static DECLARE_WAIT_QUEUE_HEAD(pipe_version_waitqueue);
84 90
85static void gss_free_ctx(struct gss_cl_ctx *); 91static void gss_free_ctx(struct gss_cl_ctx *);
86static struct rpc_pipe_ops gss_upcall_ops; 92static struct rpc_pipe_ops gss_upcall_ops_v0;
93static struct rpc_pipe_ops gss_upcall_ops_v1;
87 94
88static inline struct gss_cl_ctx * 95static inline struct gss_cl_ctx *
89gss_get_ctx(struct gss_cl_ctx *ctx) 96gss_get_ctx(struct gss_cl_ctx *ctx)
@@ -227,6 +234,7 @@ err:
227 return p; 234 return p;
228} 235}
229 236
237#define UPCALL_BUF_LEN 128
230 238
231struct gss_upcall_msg { 239struct gss_upcall_msg {
232 atomic_t count; 240 atomic_t count;
@@ -238,6 +246,7 @@ struct gss_upcall_msg {
238 struct rpc_wait_queue rpc_waitqueue; 246 struct rpc_wait_queue rpc_waitqueue;
239 wait_queue_head_t waitqueue; 247 wait_queue_head_t waitqueue;
240 struct gss_cl_ctx *ctx; 248 struct gss_cl_ctx *ctx;
249 char databuf[UPCALL_BUF_LEN];
241}; 250};
242 251
243static int get_pipe_version(void) 252static int get_pipe_version(void)
@@ -247,7 +256,7 @@ static int get_pipe_version(void)
247 spin_lock(&pipe_version_lock); 256 spin_lock(&pipe_version_lock);
248 if (pipe_version >= 0) { 257 if (pipe_version >= 0) {
249 atomic_inc(&pipe_users); 258 atomic_inc(&pipe_users);
250 ret = 0; 259 ret = pipe_version;
251 } else 260 } else
252 ret = -EAGAIN; 261 ret = -EAGAIN;
253 spin_unlock(&pipe_version_lock); 262 spin_unlock(&pipe_version_lock);
@@ -353,6 +362,29 @@ gss_upcall_callback(struct rpc_task *task)
353 gss_release_msg(gss_msg); 362 gss_release_msg(gss_msg);
354} 363}
355 364
365static void gss_encode_v0_msg(struct gss_upcall_msg *gss_msg)
366{
367 gss_msg->msg.data = &gss_msg->uid;
368 gss_msg->msg.len = sizeof(gss_msg->uid);
369}
370
371static void gss_encode_v1_msg(struct gss_upcall_msg *gss_msg)
372{
373 gss_msg->msg.len = sprintf(gss_msg->databuf, "mech=%s uid=%d\n",
374 gss_msg->auth->mech->gm_name,
375 gss_msg->uid);
376 gss_msg->msg.data = gss_msg->databuf;
377 BUG_ON(gss_msg->msg.len > UPCALL_BUF_LEN);
378}
379
380static void gss_encode_msg(struct gss_upcall_msg *gss_msg)
381{
382 if (pipe_version == 0)
383 gss_encode_v0_msg(gss_msg);
384 else /* pipe_version == 1 */
385 gss_encode_v1_msg(gss_msg);
386}
387
356static inline struct gss_upcall_msg * 388static inline struct gss_upcall_msg *
357gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid) 389gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
358{ 390{
@@ -367,15 +399,14 @@ gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
367 kfree(gss_msg); 399 kfree(gss_msg);
368 return ERR_PTR(vers); 400 return ERR_PTR(vers);
369 } 401 }
370 gss_msg->inode = RPC_I(gss_auth->dentry->d_inode); 402 gss_msg->inode = RPC_I(gss_auth->dentry[vers]->d_inode);
371 INIT_LIST_HEAD(&gss_msg->list); 403 INIT_LIST_HEAD(&gss_msg->list);
372 rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq"); 404 rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
373 init_waitqueue_head(&gss_msg->waitqueue); 405 init_waitqueue_head(&gss_msg->waitqueue);
374 atomic_set(&gss_msg->count, 1); 406 atomic_set(&gss_msg->count, 1);
375 gss_msg->msg.data = &gss_msg->uid;
376 gss_msg->msg.len = sizeof(gss_msg->uid);
377 gss_msg->uid = uid; 407 gss_msg->uid = uid;
378 gss_msg->auth = gss_auth; 408 gss_msg->auth = gss_auth;
409 gss_encode_msg(gss_msg);
379 return gss_msg; 410 return gss_msg;
380} 411}
381 412
@@ -613,18 +644,36 @@ out:
613 return err; 644 return err;
614} 645}
615 646
616static int 647static int gss_pipe_open(struct inode *inode, int new_version)
617gss_pipe_open(struct inode *inode)
618{ 648{
649 int ret = 0;
650
619 spin_lock(&pipe_version_lock); 651 spin_lock(&pipe_version_lock);
620 if (pipe_version < 0) { 652 if (pipe_version < 0) {
621 pipe_version = 0; 653 /* First open of any gss pipe determines the version: */
654 pipe_version = new_version;
622 rpc_wake_up(&pipe_version_rpc_waitqueue); 655 rpc_wake_up(&pipe_version_rpc_waitqueue);
623 wake_up(&pipe_version_waitqueue); 656 wake_up(&pipe_version_waitqueue);
657 } else if (pipe_version != new_version) {
658 /* Trying to open a pipe of a different version */
659 ret = -EBUSY;
660 goto out;
624 } 661 }
625 atomic_inc(&pipe_users); 662 atomic_inc(&pipe_users);
663out:
626 spin_unlock(&pipe_version_lock); 664 spin_unlock(&pipe_version_lock);
627 return 0; 665 return ret;
666
667}
668
669static int gss_pipe_open_v0(struct inode *inode)
670{
671 return gss_pipe_open(inode, 0);
672}
673
674static int gss_pipe_open_v1(struct inode *inode)
675{
676 return gss_pipe_open(inode, 1);
628} 677}
629 678
630static void 679static void
@@ -702,20 +751,38 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
702 atomic_set(&auth->au_count, 1); 751 atomic_set(&auth->au_count, 1);
703 kref_init(&gss_auth->kref); 752 kref_init(&gss_auth->kref);
704 753
705 gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name, 754 /*
706 clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); 755 * Note: if we created the old pipe first, then someone who
707 if (IS_ERR(gss_auth->dentry)) { 756 * examined the directory at the right moment might conclude
708 err = PTR_ERR(gss_auth->dentry); 757 * that we supported only the old pipe. So we instead create
758 * the new pipe first.
759 */
760 gss_auth->dentry[1] = rpc_mkpipe(clnt->cl_dentry,
761 "gssd",
762 clnt, &gss_upcall_ops_v1,
763 RPC_PIPE_WAIT_FOR_OPEN);
764 if (IS_ERR(gss_auth->dentry[1])) {
765 err = PTR_ERR(gss_auth->dentry[1]);
709 goto err_put_mech; 766 goto err_put_mech;
710 } 767 }
711 768
769 gss_auth->dentry[0] = rpc_mkpipe(clnt->cl_dentry,
770 gss_auth->mech->gm_name,
771 clnt, &gss_upcall_ops_v0,
772 RPC_PIPE_WAIT_FOR_OPEN);
773 if (IS_ERR(gss_auth->dentry[0])) {
774 err = PTR_ERR(gss_auth->dentry[0]);
775 goto err_unlink_pipe_1;
776 }
712 err = rpcauth_init_credcache(auth); 777 err = rpcauth_init_credcache(auth);
713 if (err) 778 if (err)
714 goto err_unlink_pipe; 779 goto err_unlink_pipe_0;
715 780
716 return auth; 781 return auth;
717err_unlink_pipe: 782err_unlink_pipe_0:
718 rpc_unlink(gss_auth->dentry); 783 rpc_unlink(gss_auth->dentry[0]);
784err_unlink_pipe_1:
785 rpc_unlink(gss_auth->dentry[1]);
719err_put_mech: 786err_put_mech:
720 gss_mech_put(gss_auth->mech); 787 gss_mech_put(gss_auth->mech);
721err_free: 788err_free:
@@ -728,7 +795,8 @@ out_dec:
728static void 795static void
729gss_free(struct gss_auth *gss_auth) 796gss_free(struct gss_auth *gss_auth)
730{ 797{
731 rpc_unlink(gss_auth->dentry); 798 rpc_unlink(gss_auth->dentry[1]);
799 rpc_unlink(gss_auth->dentry[0]);
732 gss_mech_put(gss_auth->mech); 800 gss_mech_put(gss_auth->mech);
733 801
734 kfree(gss_auth); 802 kfree(gss_auth);
@@ -1419,11 +1487,19 @@ static const struct rpc_credops gss_nullops = {
1419 .crunwrap_resp = gss_unwrap_resp, 1487 .crunwrap_resp = gss_unwrap_resp,
1420}; 1488};
1421 1489
1422static struct rpc_pipe_ops gss_upcall_ops = { 1490static struct rpc_pipe_ops gss_upcall_ops_v0 = {
1491 .upcall = gss_pipe_upcall,
1492 .downcall = gss_pipe_downcall,
1493 .destroy_msg = gss_pipe_destroy_msg,
1494 .open_pipe = gss_pipe_open_v0,
1495 .release_pipe = gss_pipe_release,
1496};
1497
1498static struct rpc_pipe_ops gss_upcall_ops_v1 = {
1423 .upcall = gss_pipe_upcall, 1499 .upcall = gss_pipe_upcall,
1424 .downcall = gss_pipe_downcall, 1500 .downcall = gss_pipe_downcall,
1425 .destroy_msg = gss_pipe_destroy_msg, 1501 .destroy_msg = gss_pipe_destroy_msg,
1426 .open_pipe = gss_pipe_open, 1502 .open_pipe = gss_pipe_open_v1,
1427 .release_pipe = gss_pipe_release, 1503 .release_pipe = gss_pipe_release,
1428}; 1504};
1429 1505