Merge branch 'for-3.9' of git://linux-nfs.org/~bfields/linux
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / sunrpc / svcauth_unix.c
index 5085804ec8a7360952d25c19e231eef4fca78df3..c3f9e1ef7f531857f432993896d13d0ae8442876 100644 (file)
@@ -410,10 +410,15 @@ svcauth_unix_info_release(struct svc_xprt *xpt)
 
 struct unix_gid {
        struct cache_head       h;
-       uid_t                   uid;
+       kuid_t                  uid;
        struct group_info       *gi;
 };
 
+static int unix_gid_hash(kuid_t uid)
+{
+       return hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS);
+}
+
 static void unix_gid_put(struct kref *kref)
 {
        struct cache_head *item = container_of(kref, struct cache_head, ref);
@@ -428,7 +433,7 @@ static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew)
 {
        struct unix_gid *orig = container_of(corig, struct unix_gid, h);
        struct unix_gid *new = container_of(cnew, struct unix_gid, h);
-       return orig->uid == new->uid;
+       return uid_eq(orig->uid, new->uid);
 }
 static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem)
 {
@@ -460,18 +465,19 @@ static void unix_gid_request(struct cache_detail *cd,
        char tuid[20];
        struct unix_gid *ug = container_of(h, struct unix_gid, h);
 
-       snprintf(tuid, 20, "%u", ug->uid);
+       snprintf(tuid, 20, "%u", from_kuid(&init_user_ns, ug->uid));
        qword_add(bpp, blen, tuid);
        (*bpp)[-1] = '\n';
 }
 
-static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid);
+static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid);
 
 static int unix_gid_parse(struct cache_detail *cd,
                        char *mesg, int mlen)
 {
        /* uid expiry Ngid gid0 gid1 ... gidN-1 */
-       int uid;
+       int id;
+       kuid_t uid;
        int gids;
        int rv;
        int i;
@@ -483,9 +489,12 @@ static int unix_gid_parse(struct cache_detail *cd,
                return -EINVAL;
        mesg[mlen-1] = 0;
 
-       rv = get_int(&mesg, &uid);
+       rv = get_int(&mesg, &id);
        if (rv)
                return -EINVAL;
+       uid = make_kuid(&init_user_ns, id);
+       if (!uid_valid(uid))
+               return -EINVAL;
        ug.uid = uid;
 
        expiry = get_expiry(&mesg);
@@ -520,7 +529,7 @@ static int unix_gid_parse(struct cache_detail *cd,
                ug.h.expiry_time = expiry;
                ch = sunrpc_cache_update(cd,
                                         &ug.h, &ugp->h,
-                                        hash_long(uid, GID_HASHBITS));
+                                        unix_gid_hash(uid));
                if (!ch)
                        err = -ENOMEM;
                else {
@@ -539,7 +548,7 @@ static int unix_gid_show(struct seq_file *m,
                         struct cache_detail *cd,
                         struct cache_head *h)
 {
-       struct user_namespace *user_ns = current_user_ns();
+       struct user_namespace *user_ns = &init_user_ns;
        struct unix_gid *ug;
        int i;
        int glen;
@@ -555,7 +564,7 @@ static int unix_gid_show(struct seq_file *m,
        else
                glen = 0;
 
-       seq_printf(m, "%u %d:", ug->uid, glen);
+       seq_printf(m, "%u %d:", from_kuid_munged(user_ns, ug->uid), glen);
        for (i = 0; i < glen; i++)
                seq_printf(m, " %d", from_kgid_munged(user_ns, GROUP_AT(ug->gi, i)));
        seq_printf(m, "\n");
@@ -605,20 +614,20 @@ void unix_gid_cache_destroy(struct net *net)
        cache_destroy_net(cd, net);
 }
 
-static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, uid_t uid)
+static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid)
 {
        struct unix_gid ug;
        struct cache_head *ch;
 
        ug.uid = uid;
-       ch = sunrpc_cache_lookup(cd, &ug.h, hash_long(uid, GID_HASHBITS));
+       ch = sunrpc_cache_lookup(cd, &ug.h, unix_gid_hash(uid));
        if (ch)
                return container_of(ch, struct unix_gid, h);
        else
                return NULL;
 }
 
-static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp)
+static struct group_info *unix_gid_find(kuid_t uid, struct svc_rqst *rqstp)
 {
        struct unix_gid *ug;
        struct group_info *gi;
@@ -740,8 +749,8 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
        }
 
        /* Signal that mapping to nobody uid/gid is required */
-       cred->cr_uid = (uid_t) -1;
-       cred->cr_gid = (gid_t) -1;
+       cred->cr_uid = INVALID_UID;
+       cred->cr_gid = INVALID_GID;
        cred->cr_group_info = groups_alloc(0);
        if (cred->cr_group_info == NULL)
                return SVC_CLOSE; /* kmalloc failure - client must retry */
@@ -802,8 +811,10 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
        argv->iov_base = (void*)((__be32*)argv->iov_base + slen);       /* skip machname */
        argv->iov_len -= slen*4;
 
-       cred->cr_uid = svc_getnl(argv);         /* uid */
-       cred->cr_gid = svc_getnl(argv);         /* gid */
+       cred->cr_uid = make_kuid(&init_user_ns, svc_getnl(argv)); /* uid */
+       cred->cr_gid = make_kgid(&init_user_ns, svc_getnl(argv)); /* gid */
+       if (!uid_valid(cred->cr_uid) || !gid_valid(cred->cr_gid))
+               goto badcred;
        slen = svc_getnl(argv);                 /* gids length */
        if (slen > 16 || (len -= (slen + 2)*4) < 0)
                goto badcred;