From: NeilBrown <ne...@suse.de>

commit 24c5efe41c29ee3e55bcf5a1c9f61ca8709622e8 upstream.

gss_mech_register() calls svcauth_gss_register_pseudoflavor() for each
flavour, but gss_mech_unregister() does not call auth_domain_put().
This is unbalanced and makes it impossible to reload the module.

Change svcauth_gss_register_pseudoflavor() to return the registered
auth_domain, and save it for later release.

Cc: sta...@vger.kernel.org (v2.6.12+)
Link: https://bugzilla.kernel.org/show_bug.cgi?id=206651
Signed-off-by: NeilBrown <ne...@suse.de>
Signed-off-by: J. Bruce Fields <bfie...@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 include/linux/sunrpc/gss_api.h        |    1 +
 include/linux/sunrpc/svcauth_gss.h    |    3 ++-
 net/sunrpc/auth_gss/gss_mech_switch.c |   12 +++++++++---
 net/sunrpc/auth_gss/svcauth_gss.c     |   12 ++++++------
 4 files changed, 18 insertions(+), 10 deletions(-)

--- a/include/linux/sunrpc/gss_api.h
+++ b/include/linux/sunrpc/gss_api.h
@@ -81,6 +81,7 @@ struct pf_desc {
        u32     service;
        char    *name;
        char    *auth_domain_name;
+       struct auth_domain *domain;
 };
 
 /* Different mechanisms (e.g., krb5 or spkm3) may implement gss-api, and
--- a/include/linux/sunrpc/svcauth_gss.h
+++ b/include/linux/sunrpc/svcauth_gss.h
@@ -20,7 +20,8 @@ int gss_svc_init(void);
 void gss_svc_shutdown(void);
 int gss_svc_init_net(struct net *net);
 void gss_svc_shutdown_net(struct net *net);
-int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name);
+struct auth_domain *svcauth_gss_register_pseudoflavor(u32 pseudoflavor,
+                                                     char *name);
 u32 svcauth_gss_flavor(struct auth_domain *dom);
 
 #endif /* __KERNEL__ */
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -61,6 +61,8 @@ gss_mech_free(struct gss_api_mech *gm)
 
        for (i = 0; i < gm->gm_pf_num; i++) {
                pf = &gm->gm_pfs[i];
+               if (pf->domain)
+                       auth_domain_put(pf->domain);
                kfree(pf->auth_domain_name);
                pf->auth_domain_name = NULL;
        }
@@ -83,6 +85,7 @@ make_auth_domain_name(char *name)
 static int
 gss_mech_svc_setup(struct gss_api_mech *gm)
 {
+       struct auth_domain *dom;
        struct pf_desc *pf;
        int i, status;
 
@@ -92,10 +95,13 @@ gss_mech_svc_setup(struct gss_api_mech *
                status = -ENOMEM;
                if (pf->auth_domain_name == NULL)
                        goto out;
-               status = svcauth_gss_register_pseudoflavor(pf->pseudoflavor,
-                                                       pf->auth_domain_name);
-               if (status)
+               dom = svcauth_gss_register_pseudoflavor(
+                       pf->pseudoflavor, pf->auth_domain_name);
+               if (IS_ERR(dom)) {
+                       status = PTR_ERR(dom);
                        goto out;
+               }
+               pf->domain = dom;
        }
        return 0;
 out:
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -772,7 +772,7 @@ u32 svcauth_gss_flavor(struct auth_domai
 
 EXPORT_SYMBOL_GPL(svcauth_gss_flavor);
 
-int
+struct auth_domain *
 svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
 {
        struct gss_domain       *new;
@@ -795,17 +795,17 @@ svcauth_gss_register_pseudoflavor(u32 ps
                        name);
                stat = -EADDRINUSE;
                auth_domain_put(test);
-               kfree(new->h.name);
-               goto out_free_dom;
+               goto out_free_name;
        }
-       return 0;
+       return test;
 
+out_free_name:
+       kfree(new->h.name);
 out_free_dom:
        kfree(new);
 out:
-       return stat;
+       return ERR_PTR(stat);
 }
-
 EXPORT_SYMBOL_GPL(svcauth_gss_register_pseudoflavor);
 
 static inline int


Reply via email to