diff options
Diffstat (limited to 'net/sunrpc/auth_gss/auth_gss.c')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index afb292cd797d..53ed8d3f8897 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -1353,6 +1353,7 @@ gss_stringify_acceptor(struct rpc_cred *cred) | |||
1353 | char *string = NULL; | 1353 | char *string = NULL; |
1354 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | 1354 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
1355 | struct gss_cl_ctx *ctx; | 1355 | struct gss_cl_ctx *ctx; |
1356 | unsigned int len; | ||
1356 | struct xdr_netobj *acceptor; | 1357 | struct xdr_netobj *acceptor; |
1357 | 1358 | ||
1358 | rcu_read_lock(); | 1359 | rcu_read_lock(); |
@@ -1360,15 +1361,39 @@ gss_stringify_acceptor(struct rpc_cred *cred) | |||
1360 | if (!ctx) | 1361 | if (!ctx) |
1361 | goto out; | 1362 | goto out; |
1362 | 1363 | ||
1363 | acceptor = &ctx->gc_acceptor; | 1364 | len = ctx->gc_acceptor.len; |
1365 | rcu_read_unlock(); | ||
1364 | 1366 | ||
1365 | /* no point if there's no string */ | 1367 | /* no point if there's no string */ |
1366 | if (!acceptor->len) | 1368 | if (!len) |
1367 | goto out; | 1369 | return NULL; |
1368 | 1370 | realloc: | |
1369 | string = kmalloc(acceptor->len + 1, GFP_KERNEL); | 1371 | string = kmalloc(len + 1, GFP_KERNEL); |
1370 | if (!string) | 1372 | if (!string) |
1373 | return NULL; | ||
1374 | |||
1375 | rcu_read_lock(); | ||
1376 | ctx = rcu_dereference(gss_cred->gc_ctx); | ||
1377 | |||
1378 | /* did the ctx disappear or was it replaced by one with no acceptor? */ | ||
1379 | if (!ctx || !ctx->gc_acceptor.len) { | ||
1380 | kfree(string); | ||
1381 | string = NULL; | ||
1371 | goto out; | 1382 | goto out; |
1383 | } | ||
1384 | |||
1385 | acceptor = &ctx->gc_acceptor; | ||
1386 | |||
1387 | /* | ||
1388 | * Did we find a new acceptor that's longer than the original? Allocate | ||
1389 | * a longer buffer and try again. | ||
1390 | */ | ||
1391 | if (len < acceptor->len) { | ||
1392 | len = acceptor->len; | ||
1393 | rcu_read_unlock(); | ||
1394 | kfree(string); | ||
1395 | goto realloc; | ||
1396 | } | ||
1372 | 1397 | ||
1373 | memcpy(string, acceptor->data, acceptor->len); | 1398 | memcpy(string, acceptor->data, acceptor->len); |
1374 | string[acceptor->len] = '\0'; | 1399 | string[acceptor->len] = '\0'; |