SUNRPC: Fix the server AUTH_UNIX userspace mappings
authorTrond Myklebust <trondmy@gmail.com>
Tue, 9 Apr 2019 16:13:40 +0000 (12:13 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Wed, 24 Apr 2019 13:46:35 +0000 (09:46 -0400)
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>
net/sunrpc/svcauth_unix.c

index fb9041b..f92ef79 100644 (file)
@@ -500,7 +500,7 @@ static int unix_gid_parse(struct cache_detail *cd,
        rv = get_int(&mesg, &id);
        if (rv)
                return -EINVAL;
-       uid = make_kuid(&init_user_ns, id);
+       uid = make_kuid(current_user_ns(), id);
        ug.uid = uid;
 
        expiry = get_expiry(&mesg);
@@ -522,7 +522,7 @@ static int unix_gid_parse(struct cache_detail *cd,
                err = -EINVAL;
                if (rv)
                        goto out;
-               kgid = make_kgid(&init_user_ns, gid);
+               kgid = make_kgid(current_user_ns(), gid);
                if (!gid_valid(kgid))
                        goto out;
                ug.gi->gid[i] = kgid;
@@ -555,7 +555,7 @@ static int unix_gid_show(struct seq_file *m,
                         struct cache_detail *cd,
                         struct cache_head *h)
 {
-       struct user_namespace *user_ns = &init_user_ns;
+       struct user_namespace *user_ns = m->file->f_cred->user_ns;
        struct unix_gid *ug;
        int i;
        int glen;
@@ -796,6 +796,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
        struct kvec     *argv = &rqstp->rq_arg.head[0];
        struct kvec     *resv = &rqstp->rq_res.head[0];
        struct svc_cred *cred = &rqstp->rq_cred;
+       struct user_namespace *userns;
        u32             slen, i;
        int             len   = argv->iov_len;
 
@@ -816,8 +817,10 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
         * (export-specific) anonymous id by nfsd_setuser.
         * Supplementary gid's will be left alone.
         */
-       cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */
-       cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */
+       userns = (rqstp->rq_xprt && rqstp->rq_xprt->xpt_cred) ?
+               rqstp->rq_xprt->xpt_cred->user_ns : &init_user_ns;
+       cred->cr_uid = make_kuid(userns, svc_getnl(argv)); /* uid */
+       cred->cr_gid = make_kgid(userns, svc_getnl(argv)); /* gid */
        slen = svc_getnl(argv);                 /* gids length */
        if (slen > UNX_NGROUPS || (len -= (slen + 2)*4) < 0)
                goto badcred;
@@ -825,7 +828,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
        if (cred->cr_group_info == NULL)
                return SVC_CLOSE;
        for (i = 0; i < slen; i++) {
-               kgid_t kgid = make_kgid(&init_user_ns, svc_getnl(argv));
+               kgid_t kgid = make_kgid(userns, svc_getnl(argv));
                cred->cr_group_info->gid[i] = kgid;
        }
        groups_sort(cred->cr_group_info);