diff options
Diffstat (limited to 'net/sunrpc/svcauth_unix.c')
-rw-r--r-- | net/sunrpc/svcauth_unix.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 4d0129203733..a1852e19ed0c 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -415,10 +415,15 @@ svcauth_unix_info_release(struct svc_xprt *xpt) | |||
415 | 415 | ||
416 | struct unix_gid { | 416 | struct unix_gid { |
417 | struct cache_head h; | 417 | struct cache_head h; |
418 | uid_t uid; | 418 | kuid_t uid; |
419 | struct group_info *gi; | 419 | struct group_info *gi; |
420 | }; | 420 | }; |
421 | 421 | ||
422 | static int unix_gid_hash(kuid_t uid) | ||
423 | { | ||
424 | return hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS); | ||
425 | } | ||
426 | |||
422 | static void unix_gid_put(struct kref *kref) | 427 | static void unix_gid_put(struct kref *kref) |
423 | { | 428 | { |
424 | struct cache_head *item = container_of(kref, struct cache_head, ref); | 429 | struct cache_head *item = container_of(kref, struct cache_head, ref); |
@@ -433,7 +438,7 @@ static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew) | |||
433 | { | 438 | { |
434 | struct unix_gid *orig = container_of(corig, struct unix_gid, h); | 439 | struct unix_gid *orig = container_of(corig, struct unix_gid, h); |
435 | struct unix_gid *new = container_of(cnew, struct unix_gid, h); | 440 | struct unix_gid *new = container_of(cnew, struct unix_gid, h); |
436 | return orig->uid == new->uid; | 441 | return uid_eq(orig->uid, new->uid); |
437 | } | 442 | } |
438 | static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem) | 443 | static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem) |
439 | { | 444 | { |
@@ -465,7 +470,7 @@ static void unix_gid_request(struct cache_detail *cd, | |||
465 | char tuid[20]; | 470 | char tuid[20]; |
466 | struct unix_gid *ug = container_of(h, struct unix_gid, h); | 471 | struct unix_gid *ug = container_of(h, struct unix_gid, h); |
467 | 472 | ||
468 | snprintf(tuid, 20, "%u", ug->uid); | 473 | snprintf(tuid, 20, "%u", from_kuid(&init_user_ns, ug->uid)); |
469 | qword_add(bpp, blen, tuid); | 474 | qword_add(bpp, blen, tuid); |
470 | (*bpp)[-1] = '\n'; | 475 | (*bpp)[-1] = '\n'; |
471 | } | 476 | } |
@@ -475,13 +480,14 @@ static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h) | |||
475 | return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); | 480 | return sunrpc_cache_pipe_upcall(cd, h, unix_gid_request); |
476 | } | 481 | } |
477 | 482 | ||
478 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid); | 483 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid); |
479 | 484 | ||
480 | static int unix_gid_parse(struct cache_detail *cd, | 485 | static int unix_gid_parse(struct cache_detail *cd, |
481 | char *mesg, int mlen) | 486 | char *mesg, int mlen) |
482 | { | 487 | { |
483 | /* uid expiry Ngid gid0 gid1 ... gidN-1 */ | 488 | /* uid expiry Ngid gid0 gid1 ... gidN-1 */ |
484 | int uid; | 489 | int id; |
490 | kuid_t uid; | ||
485 | int gids; | 491 | int gids; |
486 | int rv; | 492 | int rv; |
487 | int i; | 493 | int i; |
@@ -493,9 +499,12 @@ static int unix_gid_parse(struct cache_detail *cd, | |||
493 | return -EINVAL; | 499 | return -EINVAL; |
494 | mesg[mlen-1] = 0; | 500 | mesg[mlen-1] = 0; |
495 | 501 | ||
496 | rv = get_int(&mesg, &uid); | 502 | rv = get_int(&mesg, &id); |
497 | if (rv) | 503 | if (rv) |
498 | return -EINVAL; | 504 | return -EINVAL; |
505 | uid = make_kuid(&init_user_ns, id); | ||
506 | if (!uid_valid(uid)) | ||
507 | return -EINVAL; | ||
499 | ug.uid = uid; | 508 | ug.uid = uid; |
500 | 509 | ||
501 | expiry = get_expiry(&mesg); | 510 | expiry = get_expiry(&mesg); |
@@ -530,7 +539,7 @@ static int unix_gid_parse(struct cache_detail *cd, | |||
530 | ug.h.expiry_time = expiry; | 539 | ug.h.expiry_time = expiry; |
531 | ch = sunrpc_cache_update(cd, | 540 | ch = sunrpc_cache_update(cd, |
532 | &ug.h, &ugp->h, | 541 | &ug.h, &ugp->h, |
533 | hash_long(uid, GID_HASHBITS)); | 542 | unix_gid_hash(uid)); |
534 | if (!ch) | 543 | if (!ch) |
535 | err = -ENOMEM; | 544 | err = -ENOMEM; |
536 | else { | 545 | else { |
@@ -549,7 +558,7 @@ static int unix_gid_show(struct seq_file *m, | |||
549 | struct cache_detail *cd, | 558 | struct cache_detail *cd, |
550 | struct cache_head *h) | 559 | struct cache_head *h) |
551 | { | 560 | { |
552 | struct user_namespace *user_ns = current_user_ns(); | 561 | struct user_namespace *user_ns = &init_user_ns; |
553 | struct unix_gid *ug; | 562 | struct unix_gid *ug; |
554 | int i; | 563 | int i; |
555 | int glen; | 564 | int glen; |
@@ -565,7 +574,7 @@ static int unix_gid_show(struct seq_file *m, | |||
565 | else | 574 | else |
566 | glen = 0; | 575 | glen = 0; |
567 | 576 | ||
568 | seq_printf(m, "%u %d:", ug->uid, glen); | 577 | seq_printf(m, "%u %d:", from_kuid_munged(user_ns, ug->uid), glen); |
569 | for (i = 0; i < glen; i++) | 578 | for (i = 0; i < glen; i++) |
570 | seq_printf(m, " %d", from_kgid_munged(user_ns, GROUP_AT(ug->gi, i))); | 579 | seq_printf(m, " %d", from_kgid_munged(user_ns, GROUP_AT(ug->gi, i))); |
571 | seq_printf(m, "\n"); | 580 | seq_printf(m, "\n"); |
@@ -615,20 +624,20 @@ void unix_gid_cache_destroy(struct net *net) | |||
615 | cache_destroy_net(cd, net); | 624 | cache_destroy_net(cd, net); |
616 | } | 625 | } |
617 | 626 | ||
618 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid) | 627 | static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid) |
619 | { | 628 | { |
620 | struct unix_gid ug; | 629 | struct unix_gid ug; |
621 | struct cache_head *ch; | 630 | struct cache_head *ch; |
622 | 631 | ||
623 | ug.uid = uid; | 632 | ug.uid = uid; |
624 | ch = sunrpc_cache_lookup(cd, &ug.h, hash_long(uid, GID_HASHBITS)); | 633 | ch = sunrpc_cache_lookup(cd, &ug.h, unix_gid_hash(uid)); |
625 | if (ch) | 634 | if (ch) |
626 | return container_of(ch, struct unix_gid, h); | 635 | return container_of(ch, struct unix_gid, h); |
627 | else | 636 | else |
628 | return NULL; | 637 | return NULL; |
629 | } | 638 | } |
630 | 639 | ||
631 | static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) | 640 | static struct group_info *unix_gid_find(kuid_t uid, struct svc_rqst *rqstp) |
632 | { | 641 | { |
633 | struct unix_gid *ug; | 642 | struct unix_gid *ug; |
634 | struct group_info *gi; | 643 | struct group_info *gi; |
@@ -750,8 +759,8 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
750 | } | 759 | } |
751 | 760 | ||
752 | /* Signal that mapping to nobody uid/gid is required */ | 761 | /* Signal that mapping to nobody uid/gid is required */ |
753 | cred->cr_uid = (uid_t) -1; | 762 | cred->cr_uid = INVALID_UID; |
754 | cred->cr_gid = (gid_t) -1; | 763 | cred->cr_gid = INVALID_GID; |
755 | cred->cr_group_info = groups_alloc(0); | 764 | cred->cr_group_info = groups_alloc(0); |
756 | if (cred->cr_group_info == NULL) | 765 | if (cred->cr_group_info == NULL) |
757 | return SVC_CLOSE; /* kmalloc failure - client must retry */ | 766 | return SVC_CLOSE; /* kmalloc failure - client must retry */ |
@@ -812,8 +821,10 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
812 | argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */ | 821 | argv->iov_base = (void*)((__be32*)argv->iov_base + slen); /* skip machname */ |
813 | argv->iov_len -= slen*4; | 822 | argv->iov_len -= slen*4; |
814 | 823 | ||
815 | cred->cr_uid = svc_getnl(argv); /* uid */ | 824 | cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */ |
816 | cred->cr_gid = svc_getnl(argv); /* gid */ | 825 | cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */ |
826 | if (!uid_valid(cred->cr_uid) || !gid_valid(cred->cr_gid)) | ||
827 | goto badcred; | ||
817 | slen = svc_getnl(argv); /* gids length */ | 828 | slen = svc_getnl(argv); /* gids length */ |
818 | if (slen > 16 || (len -= (slen + 2)*4) < 0) | 829 | if (slen > 16 || (len -= (slen + 2)*4) < 0) |
819 | goto badcred; | 830 | goto badcred; |