aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/svcauth_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/svcauth_unix.c')
-rw-r--r--net/sunrpc/svcauth_unix.c195
1 files changed, 93 insertions, 102 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 4d012920373..ce136323da8 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -14,7 +14,6 @@
14#include <net/sock.h> 14#include <net/sock.h>
15#include <net/ipv6.h> 15#include <net/ipv6.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/user_namespace.h>
18#define RPCDBG_FACILITY RPCDBG_AUTH 17#define RPCDBG_FACILITY RPCDBG_AUTH
19 18
20#include <linux/sunrpc/clnt.h> 19#include <linux/sunrpc/clnt.h>
@@ -104,9 +103,23 @@ static void ip_map_put(struct kref *kref)
104 kfree(im); 103 kfree(im);
105} 104}
106 105
107static inline int hash_ip6(const struct in6_addr *ip) 106#if IP_HASHBITS == 8
107/* hash_long on a 64 bit machine is currently REALLY BAD for
108 * IP addresses in reverse-endian (i.e. on a little-endian machine).
109 * So use a trivial but reliable hash instead
110 */
111static inline int hash_ip(__be32 ip)
112{
113 int hash = (__force u32)ip ^ ((__force u32)ip>>16);
114 return (hash ^ (hash>>8)) & 0xff;
115}
116#endif
117static inline int hash_ip6(struct in6_addr ip)
108{ 118{
109 return hash_32(ipv6_addr_hash(ip), IP_HASHBITS); 119 return (hash_ip(ip.s6_addr32[0]) ^
120 hash_ip(ip.s6_addr32[1]) ^
121 hash_ip(ip.s6_addr32[2]) ^
122 hash_ip(ip.s6_addr32[3]));
110} 123}
111static int ip_map_match(struct cache_head *corig, struct cache_head *cnew) 124static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
112{ 125{
@@ -121,7 +134,7 @@ static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
121 struct ip_map *item = container_of(citem, struct ip_map, h); 134 struct ip_map *item = container_of(citem, struct ip_map, h);
122 135
123 strcpy(new->m_class, item->m_class); 136 strcpy(new->m_class, item->m_class);
124 new->m_addr = item->m_addr; 137 ipv6_addr_copy(&new->m_addr, &item->m_addr);
125} 138}
126static void update(struct cache_head *cnew, struct cache_head *citem) 139static void update(struct cache_head *cnew, struct cache_head *citem)
127{ 140{
@@ -198,7 +211,7 @@ static int ip_map_parse(struct cache_detail *cd,
198 len = qword_get(&mesg, buf, mlen); 211 len = qword_get(&mesg, buf, mlen);
199 if (len <= 0) return -EINVAL; 212 if (len <= 0) return -EINVAL;
200 213
201 if (rpc_pton(cd->net, buf, len, &address.sa, sizeof(address)) == 0) 214 if (rpc_pton(buf, len, &address.sa, sizeof(address)) == 0)
202 return -EINVAL; 215 return -EINVAL;
203 switch (address.sa.sa_family) { 216 switch (address.sa.sa_family) {
204 case AF_INET: 217 case AF_INET:
@@ -207,7 +220,7 @@ static int ip_map_parse(struct cache_detail *cd,
207 ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr, 220 ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr,
208 &sin6.sin6_addr); 221 &sin6.sin6_addr);
209 break; 222 break;
210#if IS_ENABLED(CONFIG_IPV6) 223#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
211 case AF_INET6: 224 case AF_INET6:
212 memcpy(&sin6, &address.s6, sizeof(sin6)); 225 memcpy(&sin6, &address.s6, sizeof(sin6));
213 break; 226 break;
@@ -261,7 +274,7 @@ static int ip_map_show(struct seq_file *m,
261 } 274 }
262 im = container_of(h, struct ip_map, h); 275 im = container_of(h, struct ip_map, h);
263 /* class addr domain */ 276 /* class addr domain */
264 addr = im->m_addr; 277 ipv6_addr_copy(&addr, &im->m_addr);
265 278
266 if (test_bit(CACHE_VALID, &h->flags) && 279 if (test_bit(CACHE_VALID, &h->flags) &&
267 !test_bit(CACHE_NEGATIVE, &h->flags)) 280 !test_bit(CACHE_NEGATIVE, &h->flags))
@@ -284,10 +297,10 @@ static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,
284 struct cache_head *ch; 297 struct cache_head *ch;
285 298
286 strcpy(ip.m_class, class); 299 strcpy(ip.m_class, class);
287 ip.m_addr = *addr; 300 ipv6_addr_copy(&ip.m_addr, addr);
288 ch = sunrpc_cache_lookup(cd, &ip.h, 301 ch = sunrpc_cache_lookup(cd, &ip.h,
289 hash_str(class, IP_HASHBITS) ^ 302 hash_str(class, IP_HASHBITS) ^
290 hash_ip6(addr)); 303 hash_ip6(*addr));
291 304
292 if (ch) 305 if (ch)
293 return container_of(ch, struct ip_map, h); 306 return container_of(ch, struct ip_map, h);
@@ -317,7 +330,7 @@ static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
317 ip.h.expiry_time = expiry; 330 ip.h.expiry_time = expiry;
318 ch = sunrpc_cache_update(cd, &ip.h, &ipm->h, 331 ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
319 hash_str(ipm->m_class, IP_HASHBITS) ^ 332 hash_str(ipm->m_class, IP_HASHBITS) ^
320 hash_ip6(&ipm->m_addr)); 333 hash_ip6(ipm->m_addr));
321 if (!ch) 334 if (!ch)
322 return -ENOMEM; 335 return -ENOMEM;
323 cache_put(ch, cd); 336 cache_put(ch, cd);
@@ -333,12 +346,17 @@ static inline int ip_map_update(struct net *net, struct ip_map *ipm,
333 return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry); 346 return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry);
334} 347}
335 348
336void svcauth_unix_purge(struct net *net) 349
350void svcauth_unix_purge(void)
337{ 351{
338 struct sunrpc_net *sn; 352 struct net *net;
339 353
340 sn = net_generic(net, sunrpc_net_id); 354 for_each_net(net) {
341 cache_purge(sn->ip_map_cache); 355 struct sunrpc_net *sn;
356
357 sn = net_generic(net, sunrpc_net_id);
358 cache_purge(sn->ip_map_cache);
359 }
342} 360}
343EXPORT_SYMBOL_GPL(svcauth_unix_purge); 361EXPORT_SYMBOL_GPL(svcauth_unix_purge);
344 362
@@ -418,6 +436,7 @@ struct unix_gid {
418 uid_t uid; 436 uid_t uid;
419 struct group_info *gi; 437 struct group_info *gi;
420}; 438};
439static struct cache_head *gid_table[GID_HASHMAX];
421 440
422static void unix_gid_put(struct kref *kref) 441static void unix_gid_put(struct kref *kref)
423{ 442{
@@ -475,7 +494,8 @@ static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h)
475 return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); 494 return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request);
476} 495}
477 496
478static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid); 497static struct unix_gid *unix_gid_lookup(uid_t uid);
498extern struct cache_detail unix_gid_cache;
479 499
480static int unix_gid_parse(struct cache_detail *cd, 500static int unix_gid_parse(struct cache_detail *cd,
481 char *mesg, int mlen) 501 char *mesg, int mlen)
@@ -489,7 +509,7 @@ static int unix_gid_parse(struct cache_detail *cd,
489 time_t expiry; 509 time_t expiry;
490 struct unix_gid ug, *ugp; 510 struct unix_gid ug, *ugp;
491 511
492 if (mesg[mlen - 1] != '\n') 512 if (mlen <= 0 || mesg[mlen-1] != '\n')
493 return -EINVAL; 513 return -EINVAL;
494 mesg[mlen-1] = 0; 514 mesg[mlen-1] = 0;
495 515
@@ -512,30 +532,26 @@ static int unix_gid_parse(struct cache_detail *cd,
512 532
513 for (i = 0 ; i < gids ; i++) { 533 for (i = 0 ; i < gids ; i++) {
514 int gid; 534 int gid;
515 kgid_t kgid;
516 rv = get_int(&mesg, &gid); 535 rv = get_int(&mesg, &gid);
517 err = -EINVAL; 536 err = -EINVAL;
518 if (rv) 537 if (rv)
519 goto out; 538 goto out;
520 kgid = make_kgid(&init_user_ns, gid); 539 GROUP_AT(ug.gi, i) = gid;
521 if (!gid_valid(kgid))
522 goto out;
523 GROUP_AT(ug.gi, i) = kgid;
524 } 540 }
525 541
526 ugp = unix_gid_lookup(cd, uid); 542 ugp = unix_gid_lookup(uid);
527 if (ugp) { 543 if (ugp) {
528 struct cache_head *ch; 544 struct cache_head *ch;
529 ug.h.flags = 0; 545 ug.h.flags = 0;
530 ug.h.expiry_time = expiry; 546 ug.h.expiry_time = expiry;
531 ch = sunrpc_cache_update(cd, 547 ch = sunrpc_cache_update(&unix_gid_cache,
532 &ug.h, &ugp->h, 548 &ug.h, &ugp->h,
533 hash_long(uid, GID_HASHBITS)); 549 hash_long(uid, GID_HASHBITS));
534 if (!ch) 550 if (!ch)
535 err = -ENOMEM; 551 err = -ENOMEM;
536 else { 552 else {
537 err = 0; 553 err = 0;
538 cache_put(ch, cd); 554 cache_put(ch, &unix_gid_cache);
539 } 555 }
540 } else 556 } else
541 err = -ENOMEM; 557 err = -ENOMEM;
@@ -549,7 +565,6 @@ static int unix_gid_show(struct seq_file *m,
549 struct cache_detail *cd, 565 struct cache_detail *cd,
550 struct cache_head *h) 566 struct cache_head *h)
551{ 567{
552 struct user_namespace *user_ns = current_user_ns();
553 struct unix_gid *ug; 568 struct unix_gid *ug;
554 int i; 569 int i;
555 int glen; 570 int glen;
@@ -567,14 +582,15 @@ static int unix_gid_show(struct seq_file *m,
567 582
568 seq_printf(m, "%u %d:", ug->uid, glen); 583 seq_printf(m, "%u %d:", ug->uid, glen);
569 for (i = 0; i < glen; i++) 584 for (i = 0; i < glen; i++)
570 seq_printf(m, " %d", from_kgid_munged(user_ns, GROUP_AT(ug->gi, i))); 585 seq_printf(m, " %d", GROUP_AT(ug->gi, i));
571 seq_printf(m, "\n"); 586 seq_printf(m, "\n");
572 return 0; 587 return 0;
573} 588}
574 589
575static struct cache_detail unix_gid_cache_template = { 590struct cache_detail unix_gid_cache = {
576 .owner = THIS_MODULE, 591 .owner = THIS_MODULE,
577 .hash_size = GID_HASHMAX, 592 .hash_size = GID_HASHMAX,
593 .hash_table = gid_table,
578 .name = "auth.unix.gid", 594 .name = "auth.unix.gid",
579 .cache_put = unix_gid_put, 595 .cache_put = unix_gid_put,
580 .cache_upcall = unix_gid_upcall, 596 .cache_upcall = unix_gid_upcall,
@@ -586,42 +602,14 @@ static struct cache_detail unix_gid_cache_template = {
586 .alloc = unix_gid_alloc, 602 .alloc = unix_gid_alloc,
587}; 603};
588 604
589int unix_gid_cache_create(struct net *net) 605static struct unix_gid *unix_gid_lookup(uid_t uid)
590{
591 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
592 struct cache_detail *cd;
593 int err;
594
595 cd = cache_create_net(&unix_gid_cache_template, net);
596 if (IS_ERR(cd))
597 return PTR_ERR(cd);
598 err = cache_register_net(cd, net);
599 if (err) {
600 cache_destroy_net(cd, net);
601 return err;
602 }
603 sn->unix_gid_cache = cd;
604 return 0;
605}
606
607void unix_gid_cache_destroy(struct net *net)
608{
609 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
610 struct cache_detail *cd = sn->unix_gid_cache;
611
612 sn->unix_gid_cache = NULL;
613 cache_purge(cd);
614 cache_unregister_net(cd, net);
615 cache_destroy_net(cd, net);
616}
617
618static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid)
619{ 606{
620 struct unix_gid ug; 607 struct unix_gid ug;
621 struct cache_head *ch; 608 struct cache_head *ch;
622 609
623 ug.uid = uid; 610 ug.uid = uid;
624 ch = sunrpc_cache_lookup(cd, &ug.h, hash_long(uid, GID_HASHBITS)); 611 ch = sunrpc_cache_lookup(&unix_gid_cache, &ug.h,
612 hash_long(uid, GID_HASHBITS));
625 if (ch) 613 if (ch)
626 return container_of(ch, struct unix_gid, h); 614 return container_of(ch, struct unix_gid, h);
627 else 615 else
@@ -633,13 +621,11 @@ static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp)
633 struct unix_gid *ug; 621 struct unix_gid *ug;
634 struct group_info *gi; 622 struct group_info *gi;
635 int ret; 623 int ret;
636 struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net,
637 sunrpc_net_id);
638 624
639 ug = unix_gid_lookup(sn->unix_gid_cache, uid); 625 ug = unix_gid_lookup(uid);
640 if (!ug) 626 if (!ug)
641 return ERR_PTR(-EAGAIN); 627 return ERR_PTR(-EAGAIN);
642 ret = cache_check(sn->unix_gid_cache, &ug->h, &rqstp->rq_chandle); 628 ret = cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle);
643 switch (ret) { 629 switch (ret) {
644 case -ENOENT: 630 case -ENOENT:
645 return ERR_PTR(-ENOENT); 631 return ERR_PTR(-ENOENT);
@@ -647,7 +633,7 @@ static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp)
647 return ERR_PTR(-ESHUTDOWN); 633 return ERR_PTR(-ESHUTDOWN);
648 case 0: 634 case 0:
649 gi = get_group_info(ug->gi); 635 gi = get_group_info(ug->gi);
650 cache_put(&ug->h, sn->unix_gid_cache); 636 cache_put(&ug->h, &unix_gid_cache);
651 return gi; 637 return gi;
652 default: 638 default:
653 return ERR_PTR(-EAGAIN); 639 return ERR_PTR(-EAGAIN);
@@ -732,7 +718,6 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
732 struct svc_cred *cred = &rqstp->rq_cred; 718 struct svc_cred *cred = &rqstp->rq_cred;
733 719
734 cred->cr_group_info = NULL; 720 cred->cr_group_info = NULL;
735 cred->cr_principal = NULL;
736 rqstp->rq_client = NULL; 721 rqstp->rq_client = NULL;
737 722
738 if (argv->iov_len < 3*4) 723 if (argv->iov_len < 3*4)
@@ -760,7 +745,7 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
760 svc_putnl(resv, RPC_AUTH_NULL); 745 svc_putnl(resv, RPC_AUTH_NULL);
761 svc_putnl(resv, 0); 746 svc_putnl(resv, 0);
762 747
763 rqstp->rq_cred.cr_flavor = RPC_AUTH_NULL; 748 rqstp->rq_flavor = RPC_AUTH_NULL;
764 return SVC_OK; 749 return SVC_OK;
765} 750}
766 751
@@ -798,7 +783,6 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
798 int len = argv->iov_len; 783 int len = argv->iov_len;
799 784
800 cred->cr_group_info = NULL; 785 cred->cr_group_info = NULL;
801 cred->cr_principal = NULL;
802 rqstp->rq_client = NULL; 786 rqstp->rq_client = NULL;
803 787
804 if ((len -= 3*4) < 0) 788 if ((len -= 3*4) < 0)
@@ -820,12 +804,8 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
820 cred->cr_group_info = groups_alloc(slen); 804 cred->cr_group_info = groups_alloc(slen);
821 if (cred->cr_group_info == NULL) 805 if (cred->cr_group_info == NULL)
822 return SVC_CLOSE; 806 return SVC_CLOSE;
823 for (i = 0; i < slen; i++) { 807 for (i = 0; i < slen; i++)
824 kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv)); 808 GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
825 if (!gid_valid(kgid))
826 goto badcred;
827 GROUP_AT(cred->cr_group_info, i) = kgid;
828 }
829 if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { 809 if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
830 *authp = rpc_autherr_badverf; 810 *authp = rpc_autherr_badverf;
831 return SVC_DENIED; 811 return SVC_DENIED;
@@ -835,7 +815,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
835 svc_putnl(resv, RPC_AUTH_NULL); 815 svc_putnl(resv, RPC_AUTH_NULL);
836 svc_putnl(resv, 0); 816 svc_putnl(resv, 0);
837 817
838 rqstp->rq_cred.cr_flavor = RPC_AUTH_UNIX; 818 rqstp->rq_flavor = RPC_AUTH_UNIX;
839 return SVC_OK; 819 return SVC_OK;
840 820
841badcred: 821badcred:
@@ -869,45 +849,56 @@ struct auth_ops svcauth_unix = {
869 .set_client = svcauth_unix_set_client, 849 .set_client = svcauth_unix_set_client,
870}; 850};
871 851
872static struct cache_detail ip_map_cache_template = {
873 .owner = THIS_MODULE,
874 .hash_size = IP_HASHMAX,
875 .name = "auth.unix.ip",
876 .cache_put = ip_map_put,
877 .cache_upcall = ip_map_upcall,
878 .cache_parse = ip_map_parse,
879 .cache_show = ip_map_show,
880 .match = ip_map_match,
881 .init = ip_map_init,
882 .update = update,
883 .alloc = ip_map_alloc,
884};
885
886int ip_map_cache_create(struct net *net) 852int ip_map_cache_create(struct net *net)
887{ 853{
888 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 854 int err = -ENOMEM;
889 struct cache_detail *cd; 855 struct cache_detail *cd;
890 int err; 856 struct cache_head **tbl;
857 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
858
859 cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL);
860 if (cd == NULL)
861 goto err_cd;
862
863 tbl = kzalloc(IP_HASHMAX * sizeof(struct cache_head *), GFP_KERNEL);
864 if (tbl == NULL)
865 goto err_tbl;
866
867 cd->owner = THIS_MODULE,
868 cd->hash_size = IP_HASHMAX,
869 cd->hash_table = tbl,
870 cd->name = "auth.unix.ip",
871 cd->cache_put = ip_map_put,
872 cd->cache_upcall = ip_map_upcall,
873 cd->cache_parse = ip_map_parse,
874 cd->cache_show = ip_map_show,
875 cd->match = ip_map_match,
876 cd->init = ip_map_init,
877 cd->update = update,
878 cd->alloc = ip_map_alloc,
891 879
892 cd = cache_create_net(&ip_map_cache_template, net);
893 if (IS_ERR(cd))
894 return PTR_ERR(cd);
895 err = cache_register_net(cd, net); 880 err = cache_register_net(cd, net);
896 if (err) { 881 if (err)
897 cache_destroy_net(cd, net); 882 goto err_reg;
898 return err; 883
899 }
900 sn->ip_map_cache = cd; 884 sn->ip_map_cache = cd;
901 return 0; 885 return 0;
886
887err_reg:
888 kfree(tbl);
889err_tbl:
890 kfree(cd);
891err_cd:
892 return err;
902} 893}
903 894
904void ip_map_cache_destroy(struct net *net) 895void ip_map_cache_destroy(struct net *net)
905{ 896{
906 struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); 897 struct sunrpc_net *sn;
907 struct cache_detail *cd = sn->ip_map_cache;
908 898
909 sn->ip_map_cache = NULL; 899 sn = net_generic(net, sunrpc_net_id);
910 cache_purge(cd); 900 cache_purge(sn->ip_map_cache);
911 cache_unregister_net(cd, net); 901 cache_unregister_net(sn->ip_map_cache, net);
912 cache_destroy_net(cd, net); 902 kfree(sn->ip_map_cache->hash_table);
903 kfree(sn->ip_map_cache);
913} 904}