diff options
Diffstat (limited to 'net/sunrpc/auth_gss/auth_gss.c')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 61 |
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 | ||
1242 | static struct gss_cred * | ||
1243 | gss_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 | */ |
1248 | static int | 1275 | static void |
1249 | gss_destroying_context(struct rpc_cred *cred) | 1276 | gss_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 | |||
1330 | gss_destroy_cred(struct rpc_cred *cred) | 1353 | gss_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 | ||