knfsd: nfs4 name->id mapping not correctly parsing negative downcall
[safe/jmp/linux-2.6] / fs / nfsd / nfs4idmap.c
index bea6b94..4c0c683 100644 (file)
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
-#include <linux/smp_lock.h>
 #include <linux/sunrpc/cache.h>
 #include <linux/nfsd_idmap.h>
 #include <linux/list.h>
-#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/seq_file.h>
 #include <linux/sunrpc/svcauth.h>
@@ -140,7 +138,7 @@ idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
        char idstr[11];
 
        qword_add(bpp, blen, ent->authname);
-       snprintf(idstr, sizeof(idstr), "%d", ent->id);
+       snprintf(idstr, sizeof(idstr), "%u", ent->id);
        qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user");
        qword_add(bpp, blen, idstr);
 
@@ -167,7 +165,7 @@ idtoname_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
                return 0;
        }
        ent = container_of(h, struct ent, h);
-       seq_printf(m, "%s %s %d", ent->authname,
+       seq_printf(m, "%s %s %u", ent->authname,
                        ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
                        ent->id);
        if (test_bit(CACHE_VALID, &h->flags))
@@ -209,6 +207,7 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
 {
        struct ent ent, *res;
        char *buf1, *bp;
+       int len;
        int error = -EINVAL;
 
        if (buf[buflen - 1] != '\n')
@@ -250,10 +249,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
                goto out;
 
        /* Name */
-       error = qword_get(&buf, buf1, PAGE_SIZE);
-       if (error == -EINVAL)
+       error = -EINVAL;
+       len = qword_get(&buf, buf1, PAGE_SIZE);
+       if (len < 0)
                goto out;
-       if (error == -ENOENT)
+       if (len == 0)
                set_bit(CACHE_NEGATIVE, &ent.h.flags);
        else {
                if (error >= IDMAP_NAMESZ) {
@@ -351,7 +351,7 @@ nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
                        ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
                        ent->name);
        if (test_bit(CACHE_VALID, &h->flags))
-               seq_printf(m, " %d", ent->id);
+               seq_printf(m, " %u", ent->id);
        seq_printf(m, "\n");
        return 0;
 }
@@ -573,10 +573,9 @@ idmap_lookup(struct svc_rqst *rqstp,
        struct idmap_defer_req *mdr;
        int ret;
 
-       mdr = kmalloc(sizeof(*mdr), GFP_KERNEL);
+       mdr = kzalloc(sizeof(*mdr), GFP_KERNEL);
        if (!mdr)
                return -ENOMEM;
-       memset(mdr, 0, sizeof(*mdr));
        atomic_set(&mdr->count, 1);
        init_waitqueue_head(&mdr->waitq);
        mdr->req.defer = idmap_defer;
@@ -590,6 +589,15 @@ idmap_lookup(struct svc_rqst *rqstp,
        return ret;
 }
 
+static char *
+rqst_authname(struct svc_rqst *rqstp)
+{
+       struct auth_domain *clp;
+
+       clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
+       return clp->name;
+}
+
 static int
 idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen,
                uid_t *id)
@@ -603,7 +611,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
                return -EINVAL;
        memcpy(key.name, name, namelen);
        key.name[namelen] = '\0';
-       strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
+       strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
        ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item);
        if (ret == -ENOENT)
                ret = -ESRCH; /* nfserr_badname */
@@ -623,7 +631,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
        };
        int ret;
 
-       strlcpy(key.authname, rqstp->rq_client->name, sizeof(key.authname));
+       strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
        ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item);
        if (ret == -ENOENT)
                return sprintf(name, "%u", id);