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, |
