Skip to content

Commit eb6dc19

Browse files
Trond MyklebustTrond Myklebust
authored andcommitted
RPCSEC_GSS: Share all credential caches on a per-transport basis
Ensure that all struct rpc_clnt for any given socket/rdma channel share the same RPCSEC_GSS/krb5,krb5i,krb5p caches. Signed-off-by: Trond Myklebust <[email protected]>
1 parent 414a629 commit eb6dc19

File tree

1 file changed

+89
-3
lines changed

1 file changed

+89
-3
lines changed

net/sunrpc/auth_gss/auth_gss.c

Lines changed: 89 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include <linux/sunrpc/rpc_pipe_fs.h>
5252
#include <linux/sunrpc/gss_api.h>
5353
#include <asm/uaccess.h>
54+
#include <linux/hashtable.h>
5455

5556
#include "../netns.h"
5657

@@ -71,6 +72,9 @@ static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED;
7172
* using integrity (two 4-byte integers): */
7273
#define GSS_VERF_SLACK 100
7374

75+
static DEFINE_HASHTABLE(gss_auth_hash_table, 16);
76+
static DEFINE_SPINLOCK(gss_auth_hash_lock);
77+
7478
struct gss_pipe {
7579
struct rpc_pipe_dir_object pdo;
7680
struct rpc_pipe *pipe;
@@ -81,6 +85,7 @@ struct gss_pipe {
8185

8286
struct gss_auth {
8387
struct kref kref;
88+
struct hlist_node hash;
8489
struct rpc_auth rpc_auth;
8590
struct gss_api_mech *mech;
8691
enum rpc_gss_svc service;
@@ -940,8 +945,8 @@ static void gss_pipe_free(struct gss_pipe *p)
940945
* NOTE: we have the opportunity to use different
941946
* parameters based on the input flavor (which must be a pseudoflavor)
942947
*/
943-
static struct rpc_auth *
944-
gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
948+
static struct gss_auth *
949+
gss_create_new(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
945950
{
946951
rpc_authflavor_t flavor = args->pseudoflavor;
947952
struct gss_auth *gss_auth;
@@ -955,6 +960,7 @@ gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
955960
return ERR_PTR(err);
956961
if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL)))
957962
goto out_dec;
963+
INIT_HLIST_NODE(&gss_auth->hash);
958964
gss_auth->target_name = NULL;
959965
if (args->target_name) {
960966
gss_auth->target_name = kstrdup(args->target_name, GFP_KERNEL);
@@ -1004,7 +1010,7 @@ gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
10041010
}
10051011
gss_auth->gss_pipe[0] = gss_pipe;
10061012

1007-
return auth;
1013+
return gss_auth;
10081014
err_destroy_pipe_1:
10091015
gss_pipe_free(gss_auth->gss_pipe[1]);
10101016
err_destroy_credcache:
@@ -1051,6 +1057,12 @@ gss_destroy(struct rpc_auth *auth)
10511057
dprintk("RPC: destroying GSS authenticator %p flavor %d\n",
10521058
auth, auth->au_flavor);
10531059

1060+
if (hash_hashed(&gss_auth->hash)) {
1061+
spin_lock(&gss_auth_hash_lock);
1062+
hash_del(&gss_auth->hash);
1063+
spin_unlock(&gss_auth_hash_lock);
1064+
}
1065+
10541066
gss_pipe_free(gss_auth->gss_pipe[0]);
10551067
gss_auth->gss_pipe[0] = NULL;
10561068
gss_pipe_free(gss_auth->gss_pipe[1]);
@@ -1060,6 +1072,80 @@ gss_destroy(struct rpc_auth *auth)
10601072
kref_put(&gss_auth->kref, gss_free_callback);
10611073
}
10621074

1075+
static struct gss_auth *
1076+
gss_auth_find_or_add_hashed(struct rpc_auth_create_args *args,
1077+
struct rpc_clnt *clnt,
1078+
struct gss_auth *new)
1079+
{
1080+
struct gss_auth *gss_auth;
1081+
unsigned long hashval = (unsigned long)clnt;
1082+
1083+
spin_lock(&gss_auth_hash_lock);
1084+
hash_for_each_possible(gss_auth_hash_table,
1085+
gss_auth,
1086+
hash,
1087+
hashval) {
1088+
if (gss_auth->rpc_auth.au_flavor != args->pseudoflavor)
1089+
continue;
1090+
if (gss_auth->target_name != args->target_name) {
1091+
if (gss_auth->target_name == NULL)
1092+
continue;
1093+
if (args->target_name == NULL)
1094+
continue;
1095+
if (strcmp(gss_auth->target_name, args->target_name))
1096+
continue;
1097+
}
1098+
if (!atomic_inc_not_zero(&gss_auth->rpc_auth.au_count))
1099+
continue;
1100+
goto out;
1101+
}
1102+
if (new)
1103+
hash_add(gss_auth_hash_table, &new->hash, hashval);
1104+
gss_auth = new;
1105+
out:
1106+
spin_unlock(&gss_auth_hash_lock);
1107+
return gss_auth;
1108+
}
1109+
1110+
static struct gss_auth *
1111+
gss_create_hashed(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
1112+
{
1113+
struct gss_auth *gss_auth;
1114+
struct gss_auth *new;
1115+
1116+
gss_auth = gss_auth_find_or_add_hashed(args, clnt, NULL);
1117+
if (gss_auth != NULL)
1118+
goto out;
1119+
new = gss_create_new(args, clnt);
1120+
if (IS_ERR(new))
1121+
return new;
1122+
gss_auth = gss_auth_find_or_add_hashed(args, clnt, new);
1123+
if (gss_auth != new)
1124+
gss_destroy(&new->rpc_auth);
1125+
out:
1126+
return gss_auth;
1127+
}
1128+
1129+
static struct rpc_auth *
1130+
gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
1131+
{
1132+
struct gss_auth *gss_auth;
1133+
struct rpc_xprt *xprt = rcu_access_pointer(clnt->cl_xprt);
1134+
1135+
while (clnt != clnt->cl_parent) {
1136+
struct rpc_clnt *parent = clnt->cl_parent;
1137+
/* Find the original parent for this transport */
1138+
if (rcu_access_pointer(parent->cl_xprt) != xprt)
1139+
break;
1140+
clnt = parent;
1141+
}
1142+
1143+
gss_auth = gss_create_hashed(args, clnt);
1144+
if (IS_ERR(gss_auth))
1145+
return ERR_CAST(gss_auth);
1146+
return &gss_auth->rpc_auth;
1147+
}
1148+
10631149
/*
10641150
* gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call
10651151
* to the server with the GSS control procedure field set to

0 commit comments

Comments
 (0)