Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

SUNRPC: create GSS auth cache per network namespace

This patch makes GSS auth cache details allocated and registered per network
namespace context.
Thus with this patch rsi_cache and rsc_cache contents for network namespace "X"
are controlled from proc file system mount for the same network namespace "X".

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Acked-by: J. Bruce Fields <bfields@redhat.com>

authored by

Stanislav Kinsbursky and committed by
Trond Myklebust
a1db410d 73393232

+147 -56
+2
include/linux/sunrpc/svcauth_gss.h
··· 18 18 19 19 int gss_svc_init(void); 20 20 void gss_svc_shutdown(void); 21 + int gss_svc_init_net(struct net *net); 22 + void gss_svc_shutdown_net(struct net *net); 21 23 int svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name); 22 24 u32 svcauth_gss_flavor(struct auth_domain *dom); 23 25 char *svc_gss_principal(struct svc_rqst *);
+21
net/sunrpc/auth_gss/auth_gss.c
··· 1662 1662 .release_pipe = gss_pipe_release, 1663 1663 }; 1664 1664 1665 + static __net_init int rpcsec_gss_init_net(struct net *net) 1666 + { 1667 + return gss_svc_init_net(net); 1668 + } 1669 + 1670 + static __net_exit void rpcsec_gss_exit_net(struct net *net) 1671 + { 1672 + gss_svc_shutdown_net(net); 1673 + } 1674 + 1675 + static struct pernet_operations rpcsec_gss_net_ops = { 1676 + .init = rpcsec_gss_init_net, 1677 + .exit = rpcsec_gss_exit_net, 1678 + }; 1679 + 1665 1680 /* 1666 1681 * Initialize RPCSEC_GSS module 1667 1682 */ ··· 1690 1675 err = gss_svc_init(); 1691 1676 if (err) 1692 1677 goto out_unregister; 1678 + err = register_pernet_subsys(&rpcsec_gss_net_ops); 1679 + if (err) 1680 + goto out_svc_exit; 1693 1681 rpc_init_wait_queue(&pipe_version_rpc_waitqueue, "gss pipe version"); 1694 1682 return 0; 1683 + out_svc_exit: 1684 + gss_svc_shutdown(); 1695 1685 out_unregister: 1696 1686 rpcauth_unregister(&authgss_ops); 1697 1687 out: ··· 1705 1685 1706 1686 static void __exit exit_rpcsec_gss(void) 1707 1687 { 1688 + unregister_pernet_subsys(&rpcsec_gss_net_ops); 1708 1689 gss_svc_shutdown(); 1709 1690 rpcauth_unregister(&authgss_ops); 1710 1691 rcu_barrier(); /* Wait for completion of call_rcu()'s */
+121 -56
net/sunrpc/auth_gss/svcauth_gss.c
··· 48 48 #include <linux/sunrpc/svcauth_gss.h> 49 49 #include <linux/sunrpc/cache.h> 50 50 51 + #include "../netns.h" 52 + 51 53 #ifdef RPC_DEBUG 52 54 # define RPCDBG_FACILITY RPCDBG_AUTH 53 55 #endif ··· 77 75 int major_status, minor_status; 78 76 }; 79 77 80 - static struct cache_head *rsi_table[RSI_HASHMAX]; 81 - static struct cache_detail rsi_cache; 82 - static struct rsi *rsi_update(struct rsi *new, struct rsi *old); 83 - static struct rsi *rsi_lookup(struct rsi *item); 78 + static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old); 79 + static struct rsi *rsi_lookup(struct cache_detail *cd, struct rsi *item); 84 80 85 81 static void rsi_free(struct rsi *rsii) 86 82 { ··· 216 216 if (dup_to_netobj(&rsii.in_token, buf, len)) 217 217 goto out; 218 218 219 - rsip = rsi_lookup(&rsii); 219 + rsip = rsi_lookup(cd, &rsii); 220 220 if (!rsip) 221 221 goto out; 222 222 ··· 258 258 if (dup_to_netobj(&rsii.out_token, buf, len)) 259 259 goto out; 260 260 rsii.h.expiry_time = expiry; 261 - rsip = rsi_update(&rsii, rsip); 261 + rsip = rsi_update(cd, &rsii, rsip); 262 262 status = 0; 263 263 out: 264 264 rsi_free(&rsii); 265 265 if (rsip) 266 - cache_put(&rsip->h, &rsi_cache); 266 + cache_put(&rsip->h, cd); 267 267 else 268 268 status = -ENOMEM; 269 269 return status; 270 270 } 271 271 272 - static struct cache_detail rsi_cache = { 272 + static struct cache_detail rsi_cache_template = { 273 273 .owner = THIS_MODULE, 274 274 .hash_size = RSI_HASHMAX, 275 - .hash_table = rsi_table, 276 275 .name = "auth.rpcsec.init", 277 276 .cache_put = rsi_put, 278 277 .cache_upcall = rsi_upcall, ··· 282 283 .alloc = rsi_alloc, 283 284 }; 284 285 285 - static struct rsi *rsi_lookup(struct rsi *item) 286 + static struct rsi *rsi_lookup(struct cache_detail *cd, struct rsi *item) 286 287 { 287 288 struct cache_head *ch; 288 289 int hash = rsi_hash(item); 289 290 290 - ch = sunrpc_cache_lookup(&rsi_cache, &item->h, hash); 291 + ch = sunrpc_cache_lookup(cd, &item->h, hash); 291 292 if (ch) 292 293 return container_of(ch, struct rsi, h); 293 294 else 294 295 return NULL; 295 296 } 296 297 297 - static struct rsi *rsi_update(struct rsi *new, struct rsi *old) 298 + static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old) 298 299 { 299 300 struct cache_head *ch; 300 301 int hash = rsi_hash(new); 301 302 302 - ch = sunrpc_cache_update(&rsi_cache, &new->h, 303 + ch = sunrpc_cache_update(cd, &new->h, 303 304 &old->h, hash); 304 305 if (ch) 305 306 return container_of(ch, struct rsi, h); ··· 338 339 char *client_name; 339 340 }; 340 341 341 - static struct cache_head *rsc_table[RSC_HASHMAX]; 342 - static struct cache_detail rsc_cache; 343 - static struct rsc *rsc_update(struct rsc *new, struct rsc *old); 344 - static struct rsc *rsc_lookup(struct rsc *item); 342 + static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old); 343 + static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item); 345 344 346 345 static void rsc_free(struct rsc *rsci) 347 346 { ··· 441 444 if (expiry == 0) 442 445 goto out; 443 446 444 - rscp = rsc_lookup(&rsci); 447 + rscp = rsc_lookup(cd, &rsci); 445 448 if (!rscp) 446 449 goto out; 447 450 ··· 503 506 504 507 } 505 508 rsci.h.expiry_time = expiry; 506 - rscp = rsc_update(&rsci, rscp); 509 + rscp = rsc_update(cd, &rsci, rscp); 507 510 status = 0; 508 511 out: 509 512 gss_mech_put(gm); 510 513 rsc_free(&rsci); 511 514 if (rscp) 512 - cache_put(&rscp->h, &rsc_cache); 515 + cache_put(&rscp->h, cd); 513 516 else 514 517 status = -ENOMEM; 515 518 return status; 516 519 } 517 520 518 - static struct cache_detail rsc_cache = { 521 + static struct cache_detail rsc_cache_template = { 519 522 .owner = THIS_MODULE, 520 523 .hash_size = RSC_HASHMAX, 521 - .hash_table = rsc_table, 522 524 .name = "auth.rpcsec.context", 523 525 .cache_put = rsc_put, 524 526 .cache_parse = rsc_parse, ··· 527 531 .alloc = rsc_alloc, 528 532 }; 529 533 530 - static struct rsc *rsc_lookup(struct rsc *item) 534 + static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item) 531 535 { 532 536 struct cache_head *ch; 533 537 int hash = rsc_hash(item); 534 538 535 - ch = sunrpc_cache_lookup(&rsc_cache, &item->h, hash); 539 + ch = sunrpc_cache_lookup(cd, &item->h, hash); 536 540 if (ch) 537 541 return container_of(ch, struct rsc, h); 538 542 else 539 543 return NULL; 540 544 } 541 545 542 - static struct rsc *rsc_update(struct rsc *new, struct rsc *old) 546 + static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old) 543 547 { 544 548 struct cache_head *ch; 545 549 int hash = rsc_hash(new); 546 550 547 - ch = sunrpc_cache_update(&rsc_cache, &new->h, 551 + ch = sunrpc_cache_update(cd, &new->h, 548 552 &old->h, hash); 549 553 if (ch) 550 554 return container_of(ch, struct rsc, h); ··· 554 558 555 559 556 560 static struct rsc * 557 - gss_svc_searchbyctx(struct xdr_netobj *handle) 561 + gss_svc_searchbyctx(struct cache_detail *cd, struct xdr_netobj *handle) 558 562 { 559 563 struct rsc rsci; 560 564 struct rsc *found; ··· 562 566 memset(&rsci, 0, sizeof(rsci)); 563 567 if (dup_to_netobj(&rsci.handle, handle->data, handle->len)) 564 568 return NULL; 565 - found = rsc_lookup(&rsci); 569 + found = rsc_lookup(cd, &rsci); 566 570 rsc_free(&rsci); 567 571 if (!found) 568 572 return NULL; 569 - if (cache_check(&rsc_cache, &found->h, NULL)) 573 + if (cache_check(cd, &found->h, NULL)) 570 574 return NULL; 571 575 return found; 572 576 } ··· 964 968 } 965 969 966 970 static inline int 967 - gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip) 971 + gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi *rsip) 968 972 { 969 973 struct rsc *rsci; 970 974 int rc; 971 975 972 976 if (rsip->major_status != GSS_S_COMPLETE) 973 977 return gss_write_null_verf(rqstp); 974 - rsci = gss_svc_searchbyctx(&rsip->out_handle); 978 + rsci = gss_svc_searchbyctx(cd, &rsip->out_handle); 975 979 if (rsci == NULL) { 976 980 rsip->major_status = GSS_S_NO_CONTEXT; 977 981 return gss_write_null_verf(rqstp); 978 982 } 979 983 rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN); 980 - cache_put(&rsci->h, &rsc_cache); 984 + cache_put(&rsci->h, cd); 981 985 return rc; 982 986 } 983 987 ··· 996 1000 struct xdr_netobj tmpobj; 997 1001 struct rsi *rsip, rsikey; 998 1002 int ret; 1003 + struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); 999 1004 1000 1005 /* Read the verifier; should be NULL: */ 1001 1006 *authp = rpc_autherr_badverf; ··· 1025 1028 } 1026 1029 1027 1030 /* Perform upcall, or find upcall result: */ 1028 - rsip = rsi_lookup(&rsikey); 1031 + rsip = rsi_lookup(sn->rsi_cache, &rsikey); 1029 1032 rsi_free(&rsikey); 1030 1033 if (!rsip) 1031 1034 return SVC_CLOSE; 1032 - if (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle) < 0) 1035 + if (cache_check(sn->rsi_cache, &rsip->h, &rqstp->rq_chandle) < 0) 1033 1036 /* No upcall result: */ 1034 1037 return SVC_CLOSE; 1035 1038 1036 1039 ret = SVC_CLOSE; 1037 1040 /* Got an answer to the upcall; use it: */ 1038 - if (gss_write_init_verf(rqstp, rsip)) 1041 + if (gss_write_init_verf(sn->rsc_cache, rqstp, rsip)) 1039 1042 goto out; 1040 1043 if (resv->iov_len + 4 > PAGE_SIZE) 1041 1044 goto out; ··· 1052 1055 1053 1056 ret = SVC_COMPLETE; 1054 1057 out: 1055 - cache_put(&rsip->h, &rsi_cache); 1058 + cache_put(&rsip->h, sn->rsi_cache); 1056 1059 return ret; 1057 1060 } 1058 1061 ··· 1076 1079 __be32 *rpcstart; 1077 1080 __be32 *reject_stat = resv->iov_base + resv->iov_len; 1078 1081 int ret; 1082 + struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); 1079 1083 1080 1084 dprintk("RPC: svcauth_gss: argv->iov_len = %zd\n", 1081 1085 argv->iov_len); ··· 1127 1129 case RPC_GSS_PROC_DESTROY: 1128 1130 /* Look up the context, and check the verifier: */ 1129 1131 *authp = rpcsec_gsserr_credproblem; 1130 - rsci = gss_svc_searchbyctx(&gc->gc_ctx); 1132 + rsci = gss_svc_searchbyctx(sn->rsc_cache, &gc->gc_ctx); 1131 1133 if (!rsci) 1132 1134 goto auth_err; 1133 1135 switch (gss_verify_header(rqstp, rsci, rpcstart, gc, authp)) { ··· 1207 1209 ret = SVC_DROP; 1208 1210 out: 1209 1211 if (rsci) 1210 - cache_put(&rsci->h, &rsc_cache); 1212 + cache_put(&rsci->h, sn->rsc_cache); 1211 1213 return ret; 1212 1214 } 1213 1215 ··· 1360 1362 struct rpc_gss_wire_cred *gc = &gsd->clcred; 1361 1363 struct xdr_buf *resbuf = &rqstp->rq_res; 1362 1364 int stat = -EINVAL; 1365 + struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); 1363 1366 1364 1367 if (gc->gc_proc != RPC_GSS_PROC_DATA) 1365 1368 goto out; ··· 1403 1404 put_group_info(rqstp->rq_cred.cr_group_info); 1404 1405 rqstp->rq_cred.cr_group_info = NULL; 1405 1406 if (gsd->rsci) 1406 - cache_put(&gsd->rsci->h, &rsc_cache); 1407 + cache_put(&gsd->rsci->h, sn->rsc_cache); 1407 1408 gsd->rsci = NULL; 1408 1409 1409 1410 return stat; ··· 1428 1429 .set_client = svcauth_gss_set_client, 1429 1430 }; 1430 1431 1432 + static int rsi_cache_create_net(struct net *net) 1433 + { 1434 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1435 + struct cache_detail *cd; 1436 + int err; 1437 + 1438 + cd = cache_create_net(&rsi_cache_template, net); 1439 + if (IS_ERR(cd)) 1440 + return PTR_ERR(cd); 1441 + err = cache_register_net(cd, net); 1442 + if (err) { 1443 + cache_destroy_net(cd, net); 1444 + return err; 1445 + } 1446 + sn->rsi_cache = cd; 1447 + return 0; 1448 + } 1449 + 1450 + static void rsi_cache_destroy_net(struct net *net) 1451 + { 1452 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1453 + struct cache_detail *cd = sn->rsi_cache; 1454 + 1455 + sn->rsi_cache = NULL; 1456 + cache_purge(cd); 1457 + cache_unregister_net(cd, net); 1458 + cache_destroy_net(cd, net); 1459 + } 1460 + 1461 + static int rsc_cache_create_net(struct net *net) 1462 + { 1463 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1464 + struct cache_detail *cd; 1465 + int err; 1466 + 1467 + cd = cache_create_net(&rsc_cache_template, net); 1468 + if (IS_ERR(cd)) 1469 + return PTR_ERR(cd); 1470 + err = cache_register_net(cd, net); 1471 + if (err) { 1472 + cache_destroy_net(cd, net); 1473 + return err; 1474 + } 1475 + sn->rsc_cache = cd; 1476 + return 0; 1477 + } 1478 + 1479 + static void rsc_cache_destroy_net(struct net *net) 1480 + { 1481 + struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 1482 + struct cache_detail *cd = sn->rsc_cache; 1483 + 1484 + sn->rsc_cache = NULL; 1485 + cache_purge(cd); 1486 + cache_unregister_net(cd, net); 1487 + cache_destroy_net(cd, net); 1488 + } 1489 + 1490 + int 1491 + gss_svc_init_net(struct net *net) 1492 + { 1493 + int rv; 1494 + 1495 + rv = rsc_cache_create_net(net); 1496 + if (rv) 1497 + return rv; 1498 + rv = rsi_cache_create_net(net); 1499 + if (rv) 1500 + goto out1; 1501 + return 0; 1502 + out1: 1503 + rsc_cache_destroy_net(net); 1504 + return rv; 1505 + } 1506 + 1507 + void 1508 + gss_svc_shutdown_net(struct net *net) 1509 + { 1510 + rsi_cache_destroy_net(net); 1511 + rsc_cache_destroy_net(net); 1512 + } 1513 + 1431 1514 int 1432 1515 gss_svc_init(void) 1433 1516 { 1434 - int rv = svc_auth_register(RPC_AUTH_GSS, &svcauthops_gss); 1435 - if (rv) 1436 - return rv; 1437 - rv = cache_register(&rsc_cache); 1438 - if (rv) 1439 - goto out1; 1440 - rv = cache_register(&rsi_cache); 1441 - if (rv) 1442 - goto out2; 1443 - return 0; 1444 - out2: 1445 - cache_unregister(&rsc_cache); 1446 - out1: 1447 - svc_auth_unregister(RPC_AUTH_GSS); 1448 - return rv; 1517 + return svc_auth_register(RPC_AUTH_GSS, &svcauthops_gss); 1449 1518 } 1450 1519 1451 1520 void 1452 1521 gss_svc_shutdown(void) 1453 1522 { 1454 - cache_unregister(&rsc_cache); 1455 - cache_unregister(&rsi_cache); 1456 1523 svc_auth_unregister(RPC_AUTH_GSS); 1457 1524 }
+2
net/sunrpc/netns.h
··· 10 10 struct proc_dir_entry *proc_net_rpc; 11 11 struct cache_detail *ip_map_cache; 12 12 struct cache_detail *unix_gid_cache; 13 + struct cache_detail *rsc_cache; 14 + struct cache_detail *rsi_cache; 13 15 14 16 struct super_block *pipefs_sb; 15 17 struct mutex pipefs_sb_lock;
+1
net/sunrpc/sunrpc_syms.c
··· 25 25 #include "netns.h" 26 26 27 27 int sunrpc_net_id; 28 + EXPORT_SYMBOL_GPL(sunrpc_net_id); 28 29 29 30 extern int unix_gid_cache_create(struct net *net); 30 31 extern int unix_gid_cache_destroy(struct net *net);