diff options
| -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'; |
