aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/auth_gss/auth_gss.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/auth_gss/auth_gss.c')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c61
1 files changed, 42 insertions, 19 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 30f970cdc7f6..5d3f252659f1 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1239,36 +1239,59 @@ gss_create(const struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
1239 return &gss_auth->rpc_auth; 1239 return &gss_auth->rpc_auth;
1240} 1240}
1241 1241
1242static struct gss_cred *
1243gss_dup_cred(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
1244{
1245 struct gss_cred *new;
1246
1247 /* Make a copy of the cred so that we can reference count it */
1248 new = kzalloc(sizeof(*gss_cred), GFP_NOIO);
1249 if (new) {
1250 struct auth_cred acred = {
1251 .uid = gss_cred->gc_base.cr_uid,
1252 };
1253 struct gss_cl_ctx *ctx =
1254 rcu_dereference_protected(gss_cred->gc_ctx, 1);
1255
1256 rpcauth_init_cred(&new->gc_base, &acred,
1257 &gss_auth->rpc_auth,
1258 &gss_nullops);
1259 new->gc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
1260 new->gc_service = gss_cred->gc_service;
1261 new->gc_principal = gss_cred->gc_principal;
1262 kref_get(&gss_auth->kref);
1263 rcu_assign_pointer(new->gc_ctx, ctx);
1264 gss_get_ctx(ctx);
1265 }
1266 return new;
1267}
1268
1242/* 1269/*
1243 * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call 1270 * gss_send_destroy_context will cause the RPCSEC_GSS to send a NULL RPC call
1244 * to the server with the GSS control procedure field set to 1271 * to the server with the GSS control procedure field set to
1245 * RPC_GSS_PROC_DESTROY. This should normally cause the server to release 1272 * RPC_GSS_PROC_DESTROY. This should normally cause the server to release
1246 * all RPCSEC_GSS state associated with that context. 1273 * all RPCSEC_GSS state associated with that context.
1247 */ 1274 */
1248static int 1275static void
1249gss_destroying_context(struct rpc_cred *cred) 1276gss_send_destroy_context(struct rpc_cred *cred)
1250{ 1277{
1251 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); 1278 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
1252 struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); 1279 struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth);
1253 struct gss_cl_ctx *ctx = rcu_dereference_protected(gss_cred->gc_ctx, 1); 1280 struct gss_cl_ctx *ctx = rcu_dereference_protected(gss_cred->gc_ctx, 1);
1281 struct gss_cred *new;
1254 struct rpc_task *task; 1282 struct rpc_task *task;
1255 1283
1256 if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) 1284 new = gss_dup_cred(gss_auth, gss_cred);
1257 return 0; 1285 if (new) {
1258 1286 ctx->gc_proc = RPC_GSS_PROC_DESTROY;
1259 ctx->gc_proc = RPC_GSS_PROC_DESTROY;
1260 cred->cr_ops = &gss_nullops;
1261
1262 /* Take a reference to ensure the cred will be destroyed either
1263 * by the RPC call or by the put_rpccred() below */
1264 get_rpccred(cred);
1265 1287
1266 task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC|RPC_TASK_SOFT); 1288 task = rpc_call_null(gss_auth->client, &new->gc_base,
1267 if (!IS_ERR(task)) 1289 RPC_TASK_ASYNC|RPC_TASK_SOFT);
1268 rpc_put_task(task); 1290 if (!IS_ERR(task))
1291 rpc_put_task(task);
1269 1292
1270 put_rpccred(cred); 1293 put_rpccred(&new->gc_base);
1271 return 1; 1294 }
1272} 1295}
1273 1296
1274/* gss_destroy_cred (and gss_free_ctx) are used to clean up after failure 1297/* gss_destroy_cred (and gss_free_ctx) are used to clean up after failure
@@ -1330,8 +1353,8 @@ static void
1330gss_destroy_cred(struct rpc_cred *cred) 1353gss_destroy_cred(struct rpc_cred *cred)
1331{ 1354{
1332 1355
1333 if (gss_destroying_context(cred)) 1356 if (test_and_clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0)
1334 return; 1357 gss_send_destroy_context(cred);
1335 gss_destroy_nullcred(cred); 1358 gss_destroy_nullcred(cred);
1336} 1359}
1337 1360