diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-06-27 14:29:12 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-07-10 23:40:37 -0400 |
commit | 0285ed1f12298e5304f0f2642e2cf31a5f302e61 (patch) | |
tree | afc4f0829fcbe910c60a89d03c2ea99f71eb78b6 /net/sunrpc/auth_gss | |
parent | 1be27f36601973815171db684c711d30557cf50c (diff) |
SUNRPC: Ensure that the struct gss_auth lifetime exceeds the credential's
Add a refcount in order to ensure that the gss_auth doesn't disappear from
underneath us while we're freeing up GSS contexts.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/auth_gss')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index debcda86467c..982aba697e4d 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -79,6 +79,7 @@ static const struct rpc_credops gss_credops; | |||
79 | #define isprint(c) ((c > 0x1f) && (c < 0x7f)) | 79 | #define isprint(c) ((c > 0x1f) && (c < 0x7f)) |
80 | 80 | ||
81 | struct gss_auth { | 81 | struct gss_auth { |
82 | struct kref kref; | ||
82 | struct rpc_auth rpc_auth; | 83 | struct rpc_auth rpc_auth; |
83 | struct gss_api_mech *mech; | 84 | struct gss_api_mech *mech; |
84 | enum rpc_gss_svc service; | 85 | enum rpc_gss_svc service; |
@@ -636,6 +637,7 @@ gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) | |||
636 | auth->au_ops = &authgss_ops; | 637 | auth->au_ops = &authgss_ops; |
637 | auth->au_flavor = flavor; | 638 | auth->au_flavor = flavor; |
638 | atomic_set(&auth->au_count, 1); | 639 | atomic_set(&auth->au_count, 1); |
640 | kref_init(&gss_auth->kref); | ||
639 | 641 | ||
640 | gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name, | 642 | gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name, |
641 | clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); | 643 | clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); |
@@ -661,6 +663,25 @@ out_dec: | |||
661 | } | 663 | } |
662 | 664 | ||
663 | static void | 665 | static void |
666 | gss_free(struct gss_auth *gss_auth) | ||
667 | { | ||
668 | rpc_unlink(gss_auth->dentry); | ||
669 | gss_auth->dentry = NULL; | ||
670 | gss_mech_put(gss_auth->mech); | ||
671 | |||
672 | kfree(gss_auth); | ||
673 | module_put(THIS_MODULE); | ||
674 | } | ||
675 | |||
676 | static void | ||
677 | gss_free_callback(struct kref *kref) | ||
678 | { | ||
679 | struct gss_auth *gss_auth = container_of(kref, struct gss_auth, kref); | ||
680 | |||
681 | gss_free(gss_auth); | ||
682 | } | ||
683 | |||
684 | static void | ||
664 | gss_destroy(struct rpc_auth *auth) | 685 | gss_destroy(struct rpc_auth *auth) |
665 | { | 686 | { |
666 | struct gss_auth *gss_auth; | 687 | struct gss_auth *gss_auth; |
@@ -671,12 +692,7 @@ gss_destroy(struct rpc_auth *auth) | |||
671 | rpcauth_destroy_credcache(auth); | 692 | rpcauth_destroy_credcache(auth); |
672 | 693 | ||
673 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | 694 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); |
674 | rpc_unlink(gss_auth->dentry); | 695 | kref_put(&gss_auth->kref, gss_free_callback); |
675 | gss_auth->dentry = NULL; | ||
676 | gss_mech_put(gss_auth->mech); | ||
677 | |||
678 | kfree(gss_auth); | ||
679 | module_put(THIS_MODULE); | ||
680 | } | 696 | } |
681 | 697 | ||
682 | /* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure | 698 | /* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure |
@@ -725,12 +741,14 @@ static void | |||
725 | gss_destroy_cred(struct rpc_cred *cred) | 741 | gss_destroy_cred(struct rpc_cred *cred) |
726 | { | 742 | { |
727 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | 743 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
744 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); | ||
728 | struct gss_cl_ctx *ctx = gss_cred->gc_ctx; | 745 | struct gss_cl_ctx *ctx = gss_cred->gc_ctx; |
729 | 746 | ||
730 | rcu_assign_pointer(gss_cred->gc_ctx, NULL); | 747 | rcu_assign_pointer(gss_cred->gc_ctx, NULL); |
731 | call_rcu(&cred->cr_rcu, gss_free_cred_callback); | 748 | call_rcu(&cred->cr_rcu, gss_free_cred_callback); |
732 | if (ctx) | 749 | if (ctx) |
733 | gss_put_ctx(ctx); | 750 | gss_put_ctx(ctx); |
751 | kref_put(&gss_auth->kref, gss_free_callback); | ||
734 | } | 752 | } |
735 | 753 | ||
736 | /* | 754 | /* |
@@ -762,6 +780,7 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
762 | */ | 780 | */ |
763 | cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW; | 781 | cred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_NEW; |
764 | cred->gc_service = gss_auth->service; | 782 | cred->gc_service = gss_auth->service; |
783 | kref_get(&gss_auth->kref); | ||
765 | return &cred->gc_base; | 784 | return &cred->gc_base; |
766 | 785 | ||
767 | out_err: | 786 | out_err: |