linux/fs/nfsd/nfs4idmap.c
<<
>>
Prefs
   1/*
   2 *  fs/nfsd/nfs4idmap.c
   3 *
   4 *  Mapping of UID/GIDs to name and vice versa.
   5 *
   6 *  Copyright (c) 2002, 2003 The Regents of the University of
   7 *  Michigan.  All rights reserved.
   8 *
   9 *  Marius Aamodt Eriksen <marius@umich.edu>
  10 *
  11 *  Redistribution and use in source and binary forms, with or without
  12 *  modification, are permitted provided that the following conditions
  13 *  are met:
  14 *
  15 *  1. Redistributions of source code must retain the above copyright
  16 *     notice, this list of conditions and the following disclaimer.
  17 *  2. Redistributions in binary form must reproduce the above copyright
  18 *     notice, this list of conditions and the following disclaimer in the
  19 *     documentation and/or other materials provided with the distribution.
  20 *  3. Neither the name of the University nor the names of its
  21 *     contributors may be used to endorse or promote products derived
  22 *     from this software without specific prior written permission.
  23 *
  24 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  25 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  26 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  27 *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  30 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  31 *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  32 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  33 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  34 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35 */
  36
  37#include <linux/module.h>
  38#include <linux/init.h>
  39
  40#include <linux/mm.h>
  41#include <linux/utsname.h>
  42#include <linux/errno.h>
  43#include <linux/string.h>
  44#include <linux/sunrpc/clnt.h>
  45#include <linux/nfs.h>
  46#include <linux/nfs4.h>
  47#include <linux/nfs_fs.h>
  48#include <linux/nfs_page.h>
  49#include <linux/sunrpc/cache.h>
  50#include <linux/nfsd_idmap.h>
  51#include <linux/list.h>
  52#include <linux/time.h>
  53#include <linux/seq_file.h>
  54#include <linux/sunrpc/svcauth.h>
  55
  56/*
  57 * Cache entry
  58 */
  59
  60/*
  61 * XXX we know that IDMAP_NAMESZ < PAGE_SIZE, but it's ugly to rely on
  62 * that.
  63 */
  64
  65#define IDMAP_TYPE_USER  0
  66#define IDMAP_TYPE_GROUP 1
  67
  68struct ent {
  69        struct cache_head h;
  70        int               type;                /* User / Group */
  71        uid_t             id;
  72        char              name[IDMAP_NAMESZ];
  73        char              authname[IDMAP_NAMESZ];
  74};
  75
  76/* Common entry handling */
  77
  78#define ENT_HASHBITS          8
  79#define ENT_HASHMAX           (1 << ENT_HASHBITS)
  80#define ENT_HASHMASK          (ENT_HASHMAX - 1)
  81
  82static void
  83ent_init(struct cache_head *cnew, struct cache_head *citm)
  84{
  85        struct ent *new = container_of(cnew, struct ent, h);
  86        struct ent *itm = container_of(citm, struct ent, h);
  87
  88        new->id = itm->id;
  89        new->type = itm->type;
  90
  91        strlcpy(new->name, itm->name, sizeof(new->name));
  92        strlcpy(new->authname, itm->authname, sizeof(new->name));
  93}
  94
  95static void
  96ent_put(struct kref *ref)
  97{
  98        struct ent *map = container_of(ref, struct ent, h.ref);
  99        kfree(map);
 100}
 101
 102static struct cache_head *
 103ent_alloc(void)
 104{
 105        struct ent *e = kmalloc(sizeof(*e), GFP_KERNEL);
 106        if (e)
 107                return &e->h;
 108        else
 109                return NULL;
 110}
 111
 112/*
 113 * ID -> Name cache
 114 */
 115
 116static struct cache_head *idtoname_table[ENT_HASHMAX];
 117
 118static uint32_t
 119idtoname_hash(struct ent *ent)
 120{
 121        uint32_t hash;
 122
 123        hash = hash_str(ent->authname, ENT_HASHBITS);
 124        hash = hash_long(hash ^ ent->id, ENT_HASHBITS);
 125
 126        /* Flip LSB for user/group */
 127        if (ent->type == IDMAP_TYPE_GROUP)
 128                hash ^= 1;
 129
 130        return hash;
 131}
 132
 133static void
 134idtoname_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
 135    int *blen)
 136{
 137        struct ent *ent = container_of(ch, struct ent, h);
 138        char idstr[11];
 139
 140        qword_add(bpp, blen, ent->authname);
 141        snprintf(idstr, sizeof(idstr), "%u", ent->id);
 142        qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user");
 143        qword_add(bpp, blen, idstr);
 144
 145        (*bpp)[-1] = '\n';
 146}
 147
 148static int
 149idtoname_match(struct cache_head *ca, struct cache_head *cb)
 150{
 151        struct ent *a = container_of(ca, struct ent, h);
 152        struct ent *b = container_of(cb, struct ent, h);
 153
 154        return (a->id == b->id && a->type == b->type &&
 155            strcmp(a->authname, b->authname) == 0);
 156}
 157
 158static int
 159idtoname_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
 160{
 161        struct ent *ent;
 162
 163        if (h == NULL) {
 164                seq_puts(m, "#domain type id [name]\n");
 165                return 0;
 166        }
 167        ent = container_of(h, struct ent, h);
 168        seq_printf(m, "%s %s %u", ent->authname,
 169                        ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
 170                        ent->id);
 171        if (test_bit(CACHE_VALID, &h->flags))
 172                seq_printf(m, " %s", ent->name);
 173        seq_printf(m, "\n");
 174        return 0;
 175}
 176
 177static void
 178warn_no_idmapd(struct cache_detail *detail)
 179{
 180        printk("nfsd: nfsv4 idmapping failing: has idmapd %s?\n",
 181                        detail->last_close? "died" : "not been started");
 182}
 183
 184
 185static int         idtoname_parse(struct cache_detail *, char *, int);
 186static struct ent *idtoname_lookup(struct ent *);
 187static struct ent *idtoname_update(struct ent *, struct ent *);
 188
 189static struct cache_detail idtoname_cache = {
 190        .owner          = THIS_MODULE,
 191        .hash_size      = ENT_HASHMAX,
 192        .hash_table     = idtoname_table,
 193        .name           = "nfs4.idtoname",
 194        .cache_put      = ent_put,
 195        .cache_request  = idtoname_request,
 196        .cache_parse    = idtoname_parse,
 197        .cache_show     = idtoname_show,
 198        .warn_no_listener = warn_no_idmapd,
 199        .match          = idtoname_match,
 200        .init           = ent_init,
 201        .update         = ent_init,
 202        .alloc          = ent_alloc,
 203};
 204
 205int
 206idtoname_parse(struct cache_detail *cd, char *buf, int buflen)
 207{
 208        struct ent ent, *res;
 209        char *buf1, *bp;
 210        int len;
 211        int error = -EINVAL;
 212
 213        if (buf[buflen - 1] != '\n')
 214                return (-EINVAL);
 215        buf[buflen - 1]= '\0';
 216
 217        buf1 = kmalloc(PAGE_SIZE, GFP_KERNEL);
 218        if (buf1 == NULL)
 219                return (-ENOMEM);
 220
 221        memset(&ent, 0, sizeof(ent));
 222
 223        /* Authentication name */
 224        if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
 225                goto out;
 226        memcpy(ent.authname, buf1, sizeof(ent.authname));
 227
 228        /* Type */
 229        if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
 230                goto out;
 231        ent.type = strcmp(buf1, "user") == 0 ?
 232                IDMAP_TYPE_USER : IDMAP_TYPE_GROUP;
 233
 234        /* ID */
 235        if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
 236                goto out;
 237        ent.id = simple_strtoul(buf1, &bp, 10);
 238        if (bp == buf1)
 239                goto out;
 240
 241        /* expiry */
 242        ent.h.expiry_time = get_expiry(&buf);
 243        if (ent.h.expiry_time == 0)
 244                goto out;
 245
 246        error = -ENOMEM;
 247        res = idtoname_lookup(&ent);
 248        if (!res)
 249                goto out;
 250
 251        /* Name */
 252        error = -EINVAL;
 253        len = qword_get(&buf, buf1, PAGE_SIZE);
 254        if (len < 0)
 255                goto out;
 256        if (len == 0)
 257                set_bit(CACHE_NEGATIVE, &ent.h.flags);
 258        else {
 259                if (error >= IDMAP_NAMESZ) {
 260                        error = -EINVAL;
 261                        goto out;
 262                }
 263                memcpy(ent.name, buf1, sizeof(ent.name));
 264        }
 265        error = -ENOMEM;
 266        res = idtoname_update(&ent, res);
 267        if (res == NULL)
 268                goto out;
 269
 270        cache_put(&res->h, &idtoname_cache);
 271
 272        error = 0;
 273out:
 274        kfree(buf1);
 275
 276        return error;
 277}
 278
 279
 280static struct ent *
 281idtoname_lookup(struct ent *item)
 282{
 283        struct cache_head *ch = sunrpc_cache_lookup(&idtoname_cache,
 284                                                    &item->h,
 285                                                    idtoname_hash(item));
 286        if (ch)
 287                return container_of(ch, struct ent, h);
 288        else
 289                return NULL;
 290}
 291
 292static struct ent *
 293idtoname_update(struct ent *new, struct ent *old)
 294{
 295        struct cache_head *ch = sunrpc_cache_update(&idtoname_cache,
 296                                                    &new->h, &old->h,
 297                                                    idtoname_hash(new));
 298        if (ch)
 299                return container_of(ch, struct ent, h);
 300        else
 301                return NULL;
 302}
 303
 304
 305/*
 306 * Name -> ID cache
 307 */
 308
 309static struct cache_head *nametoid_table[ENT_HASHMAX];
 310
 311static inline int
 312nametoid_hash(struct ent *ent)
 313{
 314        return hash_str(ent->name, ENT_HASHBITS);
 315}
 316
 317static void
 318nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
 319    int *blen)
 320{
 321        struct ent *ent = container_of(ch, struct ent, h);
 322
 323        qword_add(bpp, blen, ent->authname);
 324        qword_add(bpp, blen, ent->type == IDMAP_TYPE_GROUP ? "group" : "user");
 325        qword_add(bpp, blen, ent->name);
 326
 327        (*bpp)[-1] = '\n';
 328}
 329
 330static int
 331nametoid_match(struct cache_head *ca, struct cache_head *cb)
 332{
 333        struct ent *a = container_of(ca, struct ent, h);
 334        struct ent *b = container_of(cb, struct ent, h);
 335
 336        return (a->type == b->type && strcmp(a->name, b->name) == 0 &&
 337            strcmp(a->authname, b->authname) == 0);
 338}
 339
 340static int
 341nametoid_show(struct seq_file *m, struct cache_detail *cd, struct cache_head *h)
 342{
 343        struct ent *ent;
 344
 345        if (h == NULL) {
 346                seq_puts(m, "#domain type name [id]\n");
 347                return 0;
 348        }
 349        ent = container_of(h, struct ent, h);
 350        seq_printf(m, "%s %s %s", ent->authname,
 351                        ent->type == IDMAP_TYPE_GROUP ? "group" : "user",
 352                        ent->name);
 353        if (test_bit(CACHE_VALID, &h->flags))
 354                seq_printf(m, " %u", ent->id);
 355        seq_printf(m, "\n");
 356        return 0;
 357}
 358
 359static struct ent *nametoid_lookup(struct ent *);
 360static struct ent *nametoid_update(struct ent *, struct ent *);
 361static int         nametoid_parse(struct cache_detail *, char *, int);
 362
 363static struct cache_detail nametoid_cache = {
 364        .owner          = THIS_MODULE,
 365        .hash_size      = ENT_HASHMAX,
 366        .hash_table     = nametoid_table,
 367        .name           = "nfs4.nametoid",
 368        .cache_put      = ent_put,
 369        .cache_request  = nametoid_request,
 370        .cache_parse    = nametoid_parse,
 371        .cache_show     = nametoid_show,
 372        .warn_no_listener = warn_no_idmapd,
 373        .match          = nametoid_match,
 374        .init           = ent_init,
 375        .update         = ent_init,
 376        .alloc          = ent_alloc,
 377};
 378
 379static int
 380nametoid_parse(struct cache_detail *cd, char *buf, int buflen)
 381{
 382        struct ent ent, *res;
 383        char *buf1;
 384        int error = -EINVAL;
 385
 386        if (buf[buflen - 1] != '\n')
 387                return (-EINVAL);
 388        buf[buflen - 1]= '\0';
 389
 390        buf1 = kmalloc(PAGE_SIZE, GFP_KERNEL);
 391        if (buf1 == NULL)
 392                return (-ENOMEM);
 393
 394        memset(&ent, 0, sizeof(ent));
 395
 396        /* Authentication name */
 397        if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
 398                goto out;
 399        memcpy(ent.authname, buf1, sizeof(ent.authname));
 400
 401        /* Type */
 402        if (qword_get(&buf, buf1, PAGE_SIZE) <= 0)
 403                goto out;
 404        ent.type = strcmp(buf1, "user") == 0 ?
 405                IDMAP_TYPE_USER : IDMAP_TYPE_GROUP;
 406
 407        /* Name */
 408        error = qword_get(&buf, buf1, PAGE_SIZE);
 409        if (error <= 0 || error >= IDMAP_NAMESZ)
 410                goto out;
 411        memcpy(ent.name, buf1, sizeof(ent.name));
 412
 413        /* expiry */
 414        ent.h.expiry_time = get_expiry(&buf);
 415        if (ent.h.expiry_time == 0)
 416                goto out;
 417
 418        /* ID */
 419        error = get_int(&buf, &ent.id);
 420        if (error == -EINVAL)
 421                goto out;
 422        if (error == -ENOENT)
 423                set_bit(CACHE_NEGATIVE, &ent.h.flags);
 424
 425        error = -ENOMEM;
 426        res = nametoid_lookup(&ent);
 427        if (res == NULL)
 428                goto out;
 429        res = nametoid_update(&ent, res);
 430        if (res == NULL)
 431                goto out;
 432
 433        cache_put(&res->h, &nametoid_cache);
 434        error = 0;
 435out:
 436        kfree(buf1);
 437
 438        return (error);
 439}
 440
 441
 442static struct ent *
 443nametoid_lookup(struct ent *item)
 444{
 445        struct cache_head *ch = sunrpc_cache_lookup(&nametoid_cache,
 446                                                    &item->h,
 447                                                    nametoid_hash(item));
 448        if (ch)
 449                return container_of(ch, struct ent, h);
 450        else
 451                return NULL;
 452}
 453
 454static struct ent *
 455nametoid_update(struct ent *new, struct ent *old)
 456{
 457        struct cache_head *ch = sunrpc_cache_update(&nametoid_cache,
 458                                                    &new->h, &old->h,
 459                                                    nametoid_hash(new));
 460        if (ch)
 461                return container_of(ch, struct ent, h);
 462        else
 463                return NULL;
 464}
 465
 466/*
 467 * Exported API
 468 */
 469
 470void
 471nfsd_idmap_init(void)
 472{
 473        cache_register(&idtoname_cache);
 474        cache_register(&nametoid_cache);
 475}
 476
 477void
 478nfsd_idmap_shutdown(void)
 479{
 480        if (cache_unregister(&idtoname_cache))
 481                printk(KERN_ERR "nfsd: failed to unregister idtoname cache\n");
 482        if (cache_unregister(&nametoid_cache))
 483                printk(KERN_ERR "nfsd: failed to unregister nametoid cache\n");
 484}
 485
 486/*
 487 * Deferred request handling
 488 */
 489
 490struct idmap_defer_req {
 491       struct cache_req         req;
 492       struct cache_deferred_req deferred_req;
 493       wait_queue_head_t        waitq;
 494       atomic_t                 count;
 495};
 496
 497static inline void
 498put_mdr(struct idmap_defer_req *mdr)
 499{
 500        if (atomic_dec_and_test(&mdr->count))
 501                kfree(mdr);
 502}
 503
 504static inline void
 505get_mdr(struct idmap_defer_req *mdr)
 506{
 507        atomic_inc(&mdr->count);
 508}
 509
 510static void
 511idmap_revisit(struct cache_deferred_req *dreq, int toomany)
 512{
 513        struct idmap_defer_req *mdr =
 514                container_of(dreq, struct idmap_defer_req, deferred_req);
 515
 516        wake_up(&mdr->waitq);
 517        put_mdr(mdr);
 518}
 519
 520static struct cache_deferred_req *
 521idmap_defer(struct cache_req *req)
 522{
 523        struct idmap_defer_req *mdr =
 524                container_of(req, struct idmap_defer_req, req);
 525
 526        mdr->deferred_req.revisit = idmap_revisit;
 527        get_mdr(mdr);
 528        return (&mdr->deferred_req);
 529}
 530
 531static inline int
 532do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *), struct ent *key,
 533                struct cache_detail *detail, struct ent **item,
 534                struct idmap_defer_req *mdr)
 535{
 536        *item = lookup_fn(key);
 537        if (!*item)
 538                return -ENOMEM;
 539        return cache_check(detail, &(*item)->h, &mdr->req);
 540}
 541
 542static inline int
 543do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *),
 544                        struct ent *key, struct cache_detail *detail,
 545                        struct ent **item)
 546{
 547        int ret = -ENOMEM;
 548
 549        *item = lookup_fn(key);
 550        if (!*item)
 551                goto out_err;
 552        ret = -ETIMEDOUT;
 553        if (!test_bit(CACHE_VALID, &(*item)->h.flags)
 554                        || (*item)->h.expiry_time < get_seconds()
 555                        || detail->flush_time > (*item)->h.last_refresh)
 556                goto out_put;
 557        ret = -ENOENT;
 558        if (test_bit(CACHE_NEGATIVE, &(*item)->h.flags))
 559                goto out_put;
 560        return 0;
 561out_put:
 562        cache_put(&(*item)->h, detail);
 563out_err:
 564        *item = NULL;
 565        return ret;
 566}
 567
 568static int
 569idmap_lookup(struct svc_rqst *rqstp,
 570                struct ent *(*lookup_fn)(struct ent *), struct ent *key,
 571                struct cache_detail *detail, struct ent **item)
 572{
 573        struct idmap_defer_req *mdr;
 574        int ret;
 575
 576        mdr = kzalloc(sizeof(*mdr), GFP_KERNEL);
 577        if (!mdr)
 578                return -ENOMEM;
 579        atomic_set(&mdr->count, 1);
 580        init_waitqueue_head(&mdr->waitq);
 581        mdr->req.defer = idmap_defer;
 582        ret = do_idmap_lookup(lookup_fn, key, detail, item, mdr);
 583        if (ret == -EAGAIN) {
 584                wait_event_interruptible_timeout(mdr->waitq,
 585                        test_bit(CACHE_VALID, &(*item)->h.flags), 1 * HZ);
 586                ret = do_idmap_lookup_nowait(lookup_fn, key, detail, item);
 587        }
 588        put_mdr(mdr);
 589        return ret;
 590}
 591
 592static char *
 593rqst_authname(struct svc_rqst *rqstp)
 594{
 595        struct auth_domain *clp;
 596
 597        clp = rqstp->rq_gssclient ? rqstp->rq_gssclient : rqstp->rq_client;
 598        return clp->name;
 599}
 600
 601static int
 602idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen,
 603                uid_t *id)
 604{
 605        struct ent *item, key = {
 606                .type = type,
 607        };
 608        int ret;
 609
 610        if (namelen + 1 > sizeof(key.name))
 611                return -EINVAL;
 612        memcpy(key.name, name, namelen);
 613        key.name[namelen] = '\0';
 614        strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
 615        ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item);
 616        if (ret == -ENOENT)
 617                ret = -ESRCH; /* nfserr_badname */
 618        if (ret)
 619                return ret;
 620        *id = item->id;
 621        cache_put(&item->h, &nametoid_cache);
 622        return 0;
 623}
 624
 625static int
 626idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
 627{
 628        struct ent *item, key = {
 629                .id = id,
 630                .type = type,
 631        };
 632        int ret;
 633
 634        strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
 635        ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item);
 636        if (ret == -ENOENT)
 637                return sprintf(name, "%u", id);
 638        if (ret)
 639                return ret;
 640        ret = strlen(item->name);
 641        BUG_ON(ret > IDMAP_NAMESZ);
 642        memcpy(name, item->name, ret);
 643        cache_put(&item->h, &idtoname_cache);
 644        return ret;
 645}
 646
 647int
 648nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
 649                __u32 *id)
 650{
 651        return idmap_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id);
 652}
 653
 654int
 655nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
 656                __u32 *id)
 657{
 658        return idmap_name_to_id(rqstp, IDMAP_TYPE_GROUP, name, namelen, id);
 659}
 660
 661int
 662nfsd_map_uid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
 663{
 664        return idmap_id_to_name(rqstp, IDMAP_TYPE_USER, id, name);
 665}
 666
 667int
 668nfsd_map_gid_to_name(struct svc_rqst *rqstp, __u32 id, char *name)
 669{
 670        return idmap_id_to_name(rqstp, IDMAP_TYPE_GROUP, id, name);
 671}
 672