Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

SUNRPC: Fix the server AUTH_UNIX userspace mappings

gid_parse() is part of a downcall, so uids and gids should be assumed
encoded using the current user namespace.
svcauth_unix_accept() is, on the other hand, decoding uids and gids from
the wire, so we assume those are encoded to match the user namespace of
the server process.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

authored by

Trond Myklebust and committed by
J. Bruce Fields
ccfe51a5 40373b12

+9 -6
+9 -6
net/sunrpc/svcauth_unix.c
··· 500 500 rv = get_int(&mesg, &id); 501 501 if (rv) 502 502 return -EINVAL; 503 - uid = make_kuid(&init_user_ns, id); 503 + uid = make_kuid(current_user_ns(), id); 504 504 ug.uid = uid; 505 505 506 506 expiry = get_expiry(&mesg); ··· 522 522 err = -EINVAL; 523 523 if (rv) 524 524 goto out; 525 - kgid = make_kgid(&init_user_ns, gid); 525 + kgid = make_kgid(current_user_ns(), gid); 526 526 if (!gid_valid(kgid)) 527 527 goto out; 528 528 ug.gi->gid[i] = kgid; ··· 555 555 struct cache_detail *cd, 556 556 struct cache_head *h) 557 557 { 558 - struct user_namespace *user_ns = &init_user_ns; 558 + struct user_namespace *user_ns = m->file->f_cred->user_ns; 559 559 struct unix_gid *ug; 560 560 int i; 561 561 int glen; ··· 796 796 struct kvec *argv = &rqstp->rq_arg.head[0]; 797 797 struct kvec *resv = &rqstp->rq_res.head[0]; 798 798 struct svc_cred *cred = &rqstp->rq_cred; 799 + struct user_namespace *userns; 799 800 u32 slen, i; 800 801 int len = argv->iov_len; 801 802 ··· 817 816 * (export-specific) anonymous id by nfsd_setuser. 818 817 * Supplementary gid's will be left alone. 819 818 */ 820 - cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */ 821 - cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */ 819 + userns = (rqstp->rq_xprt && rqstp->rq_xprt->xpt_cred) ? 820 + rqstp->rq_xprt->xpt_cred->user_ns : &init_user_ns; 821 + cred->cr_uid = make_kuid(userns, svc_getnl(argv)); /* uid */ 822 + cred->cr_gid = make_kgid(userns, svc_getnl(argv)); /* gid */ 822 823 slen = svc_getnl(argv); /* gids length */ 823 824 if (slen > UNX_NGROUPS || (len -= (slen + 2)*4) < 0) 824 825 goto badcred; ··· 828 825 if (cred->cr_group_info == NULL) 829 826 return SVC_CLOSE; 830 827 for (i = 0; i < slen; i++) { 831 - kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv)); 828 + kgid_t kgid = make_kgid(userns, svc_getnl(argv)); 832 829 cred->cr_group_info->gid[i] = kgid; 833 830 } 834 831 groups_sort(cred->cr_group_info);