Skip to content

Commit 414a629

Browse files
Trond MyklebustTrond Myklebust
authored andcommitted
RPCSEC_GSS: Share rpc_pipes when an rpc_clnt owns multiple rpcsec auth caches
Ensure that if an rpc_clnt owns more than one RPCSEC_GSS-based authentication mechanism, then those caches will share the same 'gssd' upcall pipe. Signed-off-by: Trond Myklebust <[email protected]>
1 parent 298fc35 commit 414a629

File tree

1 file changed

+68
-9
lines changed

1 file changed

+68
-9
lines changed

net/sunrpc/auth_gss/auth_gss.c

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ struct gss_pipe {
7676
struct rpc_pipe *pipe;
7777
struct rpc_clnt *clnt;
7878
const char *name;
79+
struct kref kref;
7980
};
8081

8182
struct gss_auth {
@@ -832,7 +833,6 @@ static struct gss_pipe *gss_pipe_alloc(struct rpc_clnt *clnt,
832833
const char *name,
833834
const struct rpc_pipe_ops *upcall_ops)
834835
{
835-
struct net *net = rpc_net_ns(clnt);
836836
struct gss_pipe *p;
837837
int err = -ENOMEM;
838838

@@ -846,19 +846,71 @@ static struct gss_pipe *gss_pipe_alloc(struct rpc_clnt *clnt,
846846
}
847847
p->name = name;
848848
p->clnt = clnt;
849+
kref_init(&p->kref);
849850
rpc_init_pipe_dir_object(&p->pdo,
850851
&gss_pipe_dir_object_ops,
851852
p);
852-
err = rpc_add_pipe_dir_object(net, &clnt->cl_pipedir_objects, &p->pdo);
853-
if (!err)
854-
return p;
855-
rpc_destroy_pipe_data(p->pipe);
853+
return p;
856854
err_free_gss_pipe:
857855
kfree(p);
858856
err:
859857
return ERR_PTR(err);
860858
}
861859

860+
struct gss_alloc_pdo {
861+
struct rpc_clnt *clnt;
862+
const char *name;
863+
const struct rpc_pipe_ops *upcall_ops;
864+
};
865+
866+
static int gss_pipe_match_pdo(struct rpc_pipe_dir_object *pdo, void *data)
867+
{
868+
struct gss_pipe *gss_pipe;
869+
struct gss_alloc_pdo *args = data;
870+
871+
if (pdo->pdo_ops != &gss_pipe_dir_object_ops)
872+
return 0;
873+
gss_pipe = container_of(pdo, struct gss_pipe, pdo);
874+
if (strcmp(gss_pipe->name, args->name) != 0)
875+
return 0;
876+
if (!kref_get_unless_zero(&gss_pipe->kref))
877+
return 0;
878+
return 1;
879+
}
880+
881+
static struct rpc_pipe_dir_object *gss_pipe_alloc_pdo(void *data)
882+
{
883+
struct gss_pipe *gss_pipe;
884+
struct gss_alloc_pdo *args = data;
885+
886+
gss_pipe = gss_pipe_alloc(args->clnt, args->name, args->upcall_ops);
887+
if (!IS_ERR(gss_pipe))
888+
return &gss_pipe->pdo;
889+
return NULL;
890+
}
891+
892+
static struct gss_pipe *gss_pipe_get(struct rpc_clnt *clnt,
893+
const char *name,
894+
const struct rpc_pipe_ops *upcall_ops)
895+
{
896+
struct net *net = rpc_net_ns(clnt);
897+
struct rpc_pipe_dir_object *pdo;
898+
struct gss_alloc_pdo args = {
899+
.clnt = clnt,
900+
.name = name,
901+
.upcall_ops = upcall_ops,
902+
};
903+
904+
pdo = rpc_find_or_alloc_pipe_dir_object(net,
905+
&clnt->cl_pipedir_objects,
906+
gss_pipe_match_pdo,
907+
gss_pipe_alloc_pdo,
908+
&args);
909+
if (pdo != NULL)
910+
return container_of(pdo, struct gss_pipe, pdo);
911+
return ERR_PTR(-ENOMEM);
912+
}
913+
862914
static void __gss_pipe_free(struct gss_pipe *p)
863915
{
864916
struct rpc_clnt *clnt = p->clnt;
@@ -871,10 +923,17 @@ static void __gss_pipe_free(struct gss_pipe *p)
871923
kfree(p);
872924
}
873925

926+
static void __gss_pipe_release(struct kref *kref)
927+
{
928+
struct gss_pipe *p = container_of(kref, struct gss_pipe, kref);
929+
930+
__gss_pipe_free(p);
931+
}
932+
874933
static void gss_pipe_free(struct gss_pipe *p)
875934
{
876935
if (p != NULL)
877-
__gss_pipe_free(p);
936+
kref_put(&p->kref, __gss_pipe_release);
878937
}
879938

880939
/*
@@ -930,14 +989,14 @@ gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
930989
* that we supported only the old pipe. So we instead create
931990
* the new pipe first.
932991
*/
933-
gss_pipe = gss_pipe_alloc(clnt, "gssd", &gss_upcall_ops_v1);
992+
gss_pipe = gss_pipe_get(clnt, "gssd", &gss_upcall_ops_v1);
934993
if (IS_ERR(gss_pipe)) {
935994
err = PTR_ERR(gss_pipe);
936995
goto err_destroy_credcache;
937996
}
938997
gss_auth->gss_pipe[1] = gss_pipe;
939998

940-
gss_pipe = gss_pipe_alloc(clnt, gss_auth->mech->gm_name,
999+
gss_pipe = gss_pipe_get(clnt, gss_auth->mech->gm_name,
9411000
&gss_upcall_ops_v0);
9421001
if (IS_ERR(gss_pipe)) {
9431002
err = PTR_ERR(gss_pipe);
@@ -947,7 +1006,7 @@ gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
9471006

9481007
return auth;
9491008
err_destroy_pipe_1:
950-
__gss_pipe_free(gss_auth->gss_pipe[1]);
1009+
gss_pipe_free(gss_auth->gss_pipe[1]);
9511010
err_destroy_credcache:
9521011
rpcauth_destroy_credcache(auth);
9531012
err_put_mech:

0 commit comments

Comments
 (0)