diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/svcauth_unix.c | 53 |
1 files changed, 30 insertions, 23 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 117f68a8aa40..97cc3de7432e 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -655,23 +655,25 @@ static struct unix_gid *unix_gid_lookup(uid_t uid) | |||
655 | return NULL; | 655 | return NULL; |
656 | } | 656 | } |
657 | 657 | ||
658 | static int unix_gid_find(uid_t uid, struct group_info **gip, | 658 | static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp) |
659 | struct svc_rqst *rqstp) | ||
660 | { | 659 | { |
661 | struct unix_gid *ug = unix_gid_lookup(uid); | 660 | struct unix_gid *ug; |
661 | struct group_info *gi; | ||
662 | int ret; | ||
663 | |||
664 | ug = unix_gid_lookup(uid); | ||
662 | if (!ug) | 665 | if (!ug) |
663 | return -EAGAIN; | 666 | return ERR_PTR(-EAGAIN); |
664 | switch (cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle)) { | 667 | ret = cache_check(&unix_gid_cache, &ug->h, &rqstp->rq_chandle); |
668 | switch (ret) { | ||
665 | case -ENOENT: | 669 | case -ENOENT: |
666 | *gip = NULL; | 670 | return ERR_PTR(-ENOENT); |
667 | return 0; | ||
668 | case 0: | 671 | case 0: |
669 | *gip = ug->gi; | 672 | gi = get_group_info(ug->gi); |
670 | get_group_info(*gip); | ||
671 | cache_put(&ug->h, &unix_gid_cache); | 673 | cache_put(&ug->h, &unix_gid_cache); |
672 | return 0; | 674 | return gi; |
673 | default: | 675 | default: |
674 | return -EAGAIN; | 676 | return ERR_PTR(-EAGAIN); |
675 | } | 677 | } |
676 | } | 678 | } |
677 | 679 | ||
@@ -681,6 +683,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) | |||
681 | struct sockaddr_in *sin; | 683 | struct sockaddr_in *sin; |
682 | struct sockaddr_in6 *sin6, sin6_storage; | 684 | struct sockaddr_in6 *sin6, sin6_storage; |
683 | struct ip_map *ipm; | 685 | struct ip_map *ipm; |
686 | struct group_info *gi; | ||
687 | struct svc_cred *cred = &rqstp->rq_cred; | ||
684 | 688 | ||
685 | switch (rqstp->rq_addr.ss_family) { | 689 | switch (rqstp->rq_addr.ss_family) { |
686 | case AF_INET: | 690 | case AF_INET: |
@@ -722,6 +726,17 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) | |||
722 | ip_map_cached_put(rqstp, ipm); | 726 | ip_map_cached_put(rqstp, ipm); |
723 | break; | 727 | break; |
724 | } | 728 | } |
729 | |||
730 | gi = unix_gid_find(cred->cr_uid, rqstp); | ||
731 | switch (PTR_ERR(gi)) { | ||
732 | case -EAGAIN: | ||
733 | return SVC_DROP; | ||
734 | case -ENOENT: | ||
735 | break; | ||
736 | default: | ||
737 | put_group_info(cred->cr_group_info); | ||
738 | cred->cr_group_info = gi; | ||
739 | } | ||
725 | return SVC_OK; | 740 | return SVC_OK; |
726 | } | 741 | } |
727 | 742 | ||
@@ -818,19 +833,11 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
818 | slen = svc_getnl(argv); /* gids length */ | 833 | slen = svc_getnl(argv); /* gids length */ |
819 | if (slen > 16 || (len -= (slen + 2)*4) < 0) | 834 | if (slen > 16 || (len -= (slen + 2)*4) < 0) |
820 | goto badcred; | 835 | goto badcred; |
821 | if (unix_gid_find(cred->cr_uid, &cred->cr_group_info, rqstp) | 836 | cred->cr_group_info = groups_alloc(slen); |
822 | == -EAGAIN) | 837 | if (cred->cr_group_info == NULL) |
823 | return SVC_DROP; | 838 | return SVC_DROP; |
824 | if (cred->cr_group_info == NULL) { | 839 | for (i = 0; i < slen; i++) |
825 | cred->cr_group_info = groups_alloc(slen); | 840 | GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv); |
826 | if (cred->cr_group_info == NULL) | ||
827 | return SVC_DROP; | ||
828 | for (i = 0; i < slen; i++) | ||
829 | GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv); | ||
830 | } else { | ||
831 | for (i = 0; i < slen ; i++) | ||
832 | svc_getnl(argv); | ||
833 | } | ||
834 | if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { | 841 | if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) { |
835 | *authp = rpc_autherr_badverf; | 842 | *authp = rpc_autherr_badverf; |
836 | return SVC_DENIED; | 843 | return SVC_DENIED; |