diff options
Diffstat (limited to 'net/sunrpc/svcauth_unix.c')
-rw-r--r-- | net/sunrpc/svcauth_unix.c | 59 |
1 files changed, 30 insertions, 29 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 4d0129203733..c3f9e1ef7f53 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/sunrpc/svcsock.h> | 6 | #include <linux/sunrpc/svcsock.h> |
7 | #include <linux/sunrpc/svcauth.h> | 7 | #include <linux/sunrpc/svcauth.h> |
8 | #include <linux/sunrpc/gss_api.h> | 8 | #include <linux/sunrpc/gss_api.h> |
9 | #include <linux/sunrpc/addr.h> | ||
9 | #include <linux/err.h> | 10 | #include <linux/err.h> |
10 | #include <linux/seq_file.h> | 11 | #include <linux/seq_file.h> |
11 | #include <linux/hash.h> | 12 | #include <linux/hash.h> |
@@ -17,7 +18,6 @@ | |||
17 | #include <linux/user_namespace.h> | 18 | #include <linux/user_namespace.h> |
18 | #define RPCDBG_FACILITY RPCDBG_AUTH | 19 | #define RPCDBG_FACILITY RPCDBG_AUTH |
19 | 20 | ||
20 | #include <linux/sunrpc/clnt.h> | ||
21 | 21 | ||
22 | #include "netns.h" | 22 | #include "netns.h" |
23 | 23 | ||
@@ -157,11 +157,6 @@ static void ip_map_request(struct cache_detail *cd, | |||
157 | (*bpp)[-1] = '\n'; | 157 | (*bpp)[-1] = '\n'; |
158 | } | 158 | } |
159 | 159 | ||
160 | static int ip_map_upcall(struct cache_detail *cd, struct cache_head *h) | ||
161 | { | ||
162 | return sunrpc_cache_pipe_upcall(cd, h, ip_map_request); | ||
163 | } | ||
164 | |||
165 | static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, struct in6_addr *addr); | 160 | static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, struct in6_addr *addr); |
166 | static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, struct unix_domain *udom, time_t expiry); | 161 | static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, struct unix_domain *udom, time_t expiry); |
167 | 162 | ||
@@ -415,10 +410,15 @@ svcauth_unix_info_release(struct svc_xprt *xpt) | |||
415 | 410 | ||
416 | struct unix_gid { | 411 | struct unix_gid { |
417 | struct cache_head h; | 412 | struct cache_head h; |
418 | uid_t uid; | 413 | kuid_t uid; |
419 | struct group_info *gi; | 414 | struct group_info *gi; |
420 | }; | 415 | }; |
421 | 416 | ||
417 | static int unix_gid_hash(kuid_t uid) | ||
418 | { | ||
419 | return hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS); | ||
420 | } | ||
421 | |||
422 | static void unix_gid_put(struct kref *kref) | 422 | static void unix_gid_put(struct kref *kref) |
423 | { | 423 | { |
424 | struct cache_head *item = container_of(kref, struct cache_head, ref); | 424 | struct cache_head *item = container_of(kref, struct cache_head, ref); |
@@ -433,7 +433,7 @@ static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew) | |||
433 | { | 433 | { |
434 | struct unix_gid *orig = container_of(corig, struct unix_gid, h); | 434 | struct unix_gid *orig = container_of(corig, struct unix_gid, h); |
435 | struct unix_gid *new = container_of(cnew, struct unix_gid, h); | 435 | struct unix_gid *new = container_of(cnew, struct unix_gid, h); |
436 | return orig->uid == new->uid; | 436 | return uid_eq(orig->uid, new->uid); |
437 | } | 437 | } |
438 | static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem) | 438 | static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem) |
439 | { | 439 | { |
@@ -465,23 +465,19 @@ static void unix_gid_request(struct cache_detail *cd, | |||
465 | char tuid[20]; | 465 | char tuid[20]; |
466 | struct unix_gid *ug = container_of(h, struct unix_gid, h); | 466 | struct unix_gid *ug = container_of(h, struct unix_gid, h); |
467 | 467 | ||
468 | snprintf(tuid, 20, "%u", ug->uid); | 468 | snprintf(tuid, 20, "%u", from_kuid(&init_user_ns, ug->uid)); |
469 | qword_add(bpp, blen, tuid); | 469 | qword_add(bpp, blen, tuid); |
470 | (*bpp)[-1] = '\n'; | 470 | (*bpp)[-1] = '\n'; |
471 | } | 471 | } |
472 | 472 | ||
473 | static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h) | 473 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid); |
474 | { | ||
475 | return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); | ||
476 | } | ||
477 | |||
478 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid); | ||
479 | 474 | ||
480 | static int unix_gid_parse(struct cache_detail *cd, | 475 | static int unix_gid_parse(struct cache_detail *cd, |
481 | char *mesg, int mlen) | 476 | char *mesg, int mlen) |
482 | { | 477 | { |
483 | /* uid expiry Ngid gid0 gid1 ... gidN-1 */ | 478 | /* uid expiry Ngid gid0 gid1 ... gidN-1 */ |
484 | int uid; | 479 | int id; |
480 | kuid_t uid; | ||
485 | int gids; | 481 | int gids; |
486 | int rv; | 482 | int rv; |
487 | int i; | 483 | int i; |
@@ -493,9 +489,12 @@ static int unix_gid_parse(struct cache_detail *cd, | |||
493 | return -EINVAL; | 489 | return -EINVAL; |
494 | mesg[mlen-1] = 0; | 490 | mesg[mlen-1] = 0; |
495 | 491 | ||
496 | rv = get_int(&mesg, &uid); | 492 | rv = get_int(&mesg, &id); |
497 | if (rv) | 493 | if (rv) |
498 | return -EINVAL; | 494 | return -EINVAL; |
495 | uid = make_kuid(&init_user_ns, id); | ||
496 | if (!uid_valid(uid)) | ||
497 | return -EINVAL; | ||
499 | ug.uid = uid; | 498 | ug.uid = uid; |
500 | 499 | ||
501 | expiry = get_expiry(&mesg); | 500 | expiry = get_expiry(&mesg); |
@@ -530,7 +529,7 @@ static int unix_gid_parse(struct cache_detail *cd, | |||
530 | ug.h.expiry_time = expiry; | 529 | ug.h.expiry_time = expiry; |
531 | ch = sunrpc_cache_update(cd, | 530 | ch = sunrpc_cache_update(cd, |
532 | &ug.h, &ugp->h, | 531 | &ug.h, &ugp->h, |
533 | hash_long(uid, GID_HASHBITS)); | 532 | unix_gid_hash(uid)); |
534 | if (!ch) | 533 | if (!ch) |
535 | err = -ENOMEM; | 534 | err = -ENOMEM; |
536 | else { | 535 | else { |
@@ -549,7 +548,7 @@ static int unix_gid_show(struct seq_file *m, | |||
549 | struct cache_detail *cd, | 548 | struct cache_detail *cd, |
550 | struct cache_head *h) | 549 | struct cache_head *h) |
551 | { | 550 | { |
552 | struct user_namespace *user_ns = current_user_ns(); | 551 | struct user_namespace *user_ns = &init_user_ns; |
553 | struct unix_gid *ug; | 552 | struct unix_gid *ug; |
554 | int i; | 553 | int i; |
555 | int glen; | 554 | int glen; |
@@ -565,7 +564,7 @@ static int unix_gid_show(struct seq_file *m, | |||
565 | else | 564 | else |
566 | glen = 0; | 565 | glen = 0; |
567 | 566 | ||
568 | seq_printf(m, "%u %d:", ug->uid, glen); | 567 | seq_printf(m, "%u %d:", from_kuid_munged(user_ns, ug->uid), glen); |
569 | for (i = 0; i < glen; i++) | 568 | for (i = 0; i < glen; i++) |
570 | seq_printf(m, " %d", from_kgid_munged(user_ns, GROUP_AT(ug->gi, i))); | 569 | seq_printf(m, " %d", from_kgid_munged(user_ns, GROUP_AT(ug->gi, i))); |
571 | seq_printf(m, "\n"); | 570 | seq_printf(m, "\n"); |
@@ -577,7 +576,7 @@ static struct cache_detail unix_gid_cache_template = { | |||
577 | .hash_size = GID_HASHMAX, | 576 | .hash_size = GID_HASHMAX, |
578 | .name = "auth.unix.gid", | 577 | .name = "auth.unix.gid", |
579 | .cache_put = unix_gid_put, | 578 | .cache_put = unix_gid_put, |
580 | .cache_upcall = unix_gid_upcall, | 579 | .cache_request = unix_gid_request, |
581 | .cache_parse = unix_gid_parse, | 580 | .cache_parse = unix_gid_parse, |
582 | .cache_show = unix_gid_show, | 581 | .cache_show = unix_gid_show, |
583 | .match = unix_gid_match, | 582 | .match = unix_gid_match, |
@@ -615,20 +614,20 @@ void unix_gid_cache_destroy(struct net *net) | |||
615 | cache_destroy_net(cd, net); | 614 | cache_destroy_net(cd, net); |
616 | } | 615 | } |
617 | 616 | ||
618 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid) | 617 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid) |
619 | { | 618 | { |
620 | struct unix_gid ug; | 619 | struct unix_gid ug; |
621 | struct cache_head *ch; | 620 | struct cache_head *ch; |
622 | 621 | ||
623 | ug.uid = uid; | 622 | ug.uid = uid; |
624 | ch = sunrpc_cache_lookup(cd, &ug.h, hash_long(uid, GID_HASHBITS)); | 623 | ch = sunrpc_cache_lookup(cd, &ug.h, unix_gid_hash(uid)); |
625 | if (ch) | 624 | if (ch) |
626 | return container_of(ch, struct unix_gid, h); | 625 | return container_of(ch, struct unix_gid, h); |
627 | else | 626 | else |
628 | return NULL; | 627 | return NULL; |
629 | } | 628 | } |
630 | 629 | ||
631 | static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) | 630 | static struct group_info *unix_gid_find(kuid_t uid, struct svc_rqst *rqstp) |
632 | { | 631 | { |
633 | struct unix_gid *ug; | 632 | struct unix_gid *ug; |
634 | struct group_info *gi; | 633 | struct group_info *gi; |
@@ -750,8 +749,8 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
750 | } | 749 | } |
751 | 750 | ||
752 | /* Signal that mapping to nobody uid/gid is required */ | 751 | /* Signal that mapping to nobody uid/gid is required */ |
753 | cred->cr_uid = (uid_t) -1; | 752 | cred->cr_uid = INVALID_UID; |
754 | cred->cr_gid = (gid_t) -1; | 753 | cred->cr_gid = INVALID_GID; |
755 | cred->cr_group_info = groups_alloc(0); | 754 | cred->cr_group_info = groups_alloc(0); |
756 | if (cred->cr_group_info == NULL) | 755 | if (cred->cr_group_info == NULL) |
757 | return SVC_CLOSE; /* kmalloc failure - client must retry */ | 756 | return SVC_CLOSE; /* kmalloc failure - client must retry */ |
@@ -812,8 +811,10 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
812 | argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */ | 811 | argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */ |
813 | argv->iov_len -= slen*4; | 812 | argv->iov_len -= slen*4; |
814 | 813 | ||
815 | cred->cr_uid = svc_getnl(argv); /* uid */ | 814 | cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */ |
816 | cred->cr_gid = svc_getnl(argv); /* gid */ | 815 | cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */ |
816 | if (!uid_valid(cred->cr_uid) || !gid_valid(cred->cr_gid)) | ||
817 | goto badcred; | ||
817 | slen = svc_getnl(argv); /* gids length */ | 818 | slen = svc_getnl(argv); /* gids length */ |
818 | if (slen > 16 || (len -= (slen + 2)*4) < 0) | 819 | if (slen > 16 || (len -= (slen + 2)*4) < 0) |
819 | goto badcred; | 820 | goto badcred; |
@@ -874,7 +875,7 @@ static struct cache_detail ip_map_cache_template = { | |||
874 | .hash_size = IP_HASHMAX, | 875 | .hash_size = IP_HASHMAX, |
875 | .name = "auth.unix.ip", | 876 | .name = "auth.unix.ip", |
876 | .cache_put = ip_map_put, | 877 | .cache_put = ip_map_put, |
877 | .cache_upcall = ip_map_upcall, | 878 | .cache_request = ip_map_request, |
878 | .cache_parse = ip_map_parse, | 879 | .cache_parse = ip_map_parse, |
879 | .cache_show = ip_map_show, | 880 | .cache_show = ip_map_show, |
880 | .match = ip_map_match, | 881 | .match = ip_map_match, |