linux/net/sunrpc/svcauth_unix.c
<<
>>
Prefs
   1#include <linux/types.h>
   2#include <linux/sched.h>
   3#include <linux/module.h>
   4#include <linux/sunrpc/types.h>
   5#include <linux/sunrpc/xdr.h>
   6#include <linux/sunrpc/svcsock.h>
   7#include <linux/sunrpc/svcauth.h>
   8#include <linux/sunrpc/gss_api.h>
   9#include <linux/sunrpc/addr.h>
  10#include <linux/err.h>
  11#include <linux/seq_file.h>
  12#include <linux/hash.h>
  13#include <linux/string.h>
  14#include <linux/slab.h>
  15#include <net/sock.h>
  16#include <net/ipv6.h>
  17#include <linux/kernel.h>
  18#include <linux/user_namespace.h>
  19#define RPCDBG_FACILITY RPCDBG_AUTH
  20
  21
  22#include "netns.h"
  23
  24/*
  25 * AUTHUNIX and AUTHNULL credentials are both handled here.
  26 * AUTHNULL is treated just like AUTHUNIX except that the uid/gid
  27 * are always nobody (-2).  i.e. we do the same IP address checks for
  28 * AUTHNULL as for AUTHUNIX, and that is done here.
  29 */
  30
  31
  32struct unix_domain {
  33        struct auth_domain      h;
  34        /* other stuff later */
  35};
  36
  37extern struct auth_ops svcauth_null;
  38extern struct auth_ops svcauth_unix;
  39
  40static void svcauth_unix_domain_release_rcu(struct rcu_head *head)
  41{
  42        struct auth_domain *dom = container_of(head, struct auth_domain, rcu_head);
  43        struct unix_domain *ud = container_of(dom, struct unix_domain, h);
  44
  45        kfree(dom->name);
  46        kfree(ud);
  47}
  48
  49static void svcauth_unix_domain_release(struct auth_domain *dom)
  50{
  51        call_rcu(&dom->rcu_head, svcauth_unix_domain_release_rcu);
  52}
  53
  54struct auth_domain *unix_domain_find(char *name)
  55{
  56        struct auth_domain *rv;
  57        struct unix_domain *new = NULL;
  58
  59        rv = auth_domain_find(name);
  60        while(1) {
  61                if (rv) {
  62                        if (new && rv != &new->h)
  63                                svcauth_unix_domain_release(&new->h);
  64
  65                        if (rv->flavour != &svcauth_unix) {
  66                                auth_domain_put(rv);
  67                                return NULL;
  68                        }
  69                        return rv;
  70                }
  71
  72                new = kmalloc(sizeof(*new), GFP_KERNEL);
  73                if (new == NULL)
  74                        return NULL;
  75                kref_init(&new->h.ref);
  76                new->h.name = kstrdup(name, GFP_KERNEL);
  77                if (new->h.name == NULL) {
  78                        kfree(new);
  79                        return NULL;
  80                }
  81                new->h.flavour = &svcauth_unix;
  82                rv = auth_domain_lookup(name, &new->h);
  83        }
  84}
  85EXPORT_SYMBOL_GPL(unix_domain_find);
  86
  87
  88/**************************************************
  89 * cache for IP address to unix_domain
  90 * as needed by AUTH_UNIX
  91 */
  92#define IP_HASHBITS     8
  93#define IP_HASHMAX      (1<<IP_HASHBITS)
  94
  95struct ip_map {
  96        struct cache_head       h;
  97        char                    m_class[8]; /* e.g. "nfsd" */
  98        struct in6_addr         m_addr;
  99        struct unix_domain      *m_client;
 100        struct rcu_head         m_rcu;
 101};
 102
 103static void ip_map_put(struct kref *kref)
 104{
 105        struct cache_head *item = container_of(kref, struct cache_head, ref);
 106        struct ip_map *im = container_of(item, struct ip_map,h);
 107
 108        if (test_bit(CACHE_VALID, &item->flags) &&
 109            !test_bit(CACHE_NEGATIVE, &item->flags))
 110                auth_domain_put(&im->m_client->h);
 111        kfree_rcu(im, m_rcu);
 112}
 113
 114static inline int hash_ip6(const struct in6_addr *ip)
 115{
 116        return hash_32(ipv6_addr_hash(ip), IP_HASHBITS);
 117}
 118static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
 119{
 120        struct ip_map *orig = container_of(corig, struct ip_map, h);
 121        struct ip_map *new = container_of(cnew, struct ip_map, h);
 122        return strcmp(orig->m_class, new->m_class) == 0 &&
 123               ipv6_addr_equal(&orig->m_addr, &new->m_addr);
 124}
 125static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
 126{
 127        struct ip_map *new = container_of(cnew, struct ip_map, h);
 128        struct ip_map *item = container_of(citem, struct ip_map, h);
 129
 130        strcpy(new->m_class, item->m_class);
 131        new->m_addr = item->m_addr;
 132}
 133static void update(struct cache_head *cnew, struct cache_head *citem)
 134{
 135        struct ip_map *new = container_of(cnew, struct ip_map, h);
 136        struct ip_map *item = container_of(citem, struct ip_map, h);
 137
 138        kref_get(&item->m_client->h.ref);
 139        new->m_client = item->m_client;
 140}
 141static struct cache_head *ip_map_alloc(void)
 142{
 143        struct ip_map *i = kmalloc(sizeof(*i), GFP_KERNEL);
 144        if (i)
 145                return &i->h;
 146        else
 147                return NULL;
 148}
 149
 150static int ip_map_upcall(struct cache_detail *cd, struct cache_head *h)
 151{
 152        return sunrpc_cache_pipe_upcall(cd, h);
 153}
 154
 155static void ip_map_request(struct cache_detail *cd,
 156                                  struct cache_head *h,
 157                                  char **bpp, int *blen)
 158{
 159        char text_addr[40];
 160        struct ip_map *im = container_of(h, struct ip_map, h);
 161
 162        if (ipv6_addr_v4mapped(&(im->m_addr))) {
 163                snprintf(text_addr, 20, "%pI4", &im->m_addr.s6_addr32[3]);
 164        } else {
 165                snprintf(text_addr, 40, "%pI6", &im->m_addr);
 166        }
 167        qword_add(bpp, blen, im->m_class);
 168        qword_add(bpp, blen, text_addr);
 169        (*bpp)[-1] = '\n';
 170}
 171
 172static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, struct in6_addr *addr);
 173static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, struct unix_domain *udom, time64_t expiry);
 174
 175static int ip_map_parse(struct cache_detail *cd,
 176                          char *mesg, int mlen)
 177{
 178        /* class ipaddress [domainname] */
 179        /* should be safe just to use the start of the input buffer
 180         * for scratch: */
 181        char *buf = mesg;
 182        int len;
 183        char class[8];
 184        union {
 185                struct sockaddr         sa;
 186                struct sockaddr_in      s4;
 187                struct sockaddr_in6     s6;
 188        } address;
 189        struct sockaddr_in6 sin6;
 190        int err;
 191
 192        struct ip_map *ipmp;
 193        struct auth_domain *dom;
 194        time64_t expiry;
 195
 196        if (mesg[mlen-1] != '\n')
 197                return -EINVAL;
 198        mesg[mlen-1] = 0;
 199
 200        /* class */
 201        len = qword_get(&mesg, class, sizeof(class));
 202        if (len <= 0) return -EINVAL;
 203
 204        /* ip address */
 205        len = qword_get(&mesg, buf, mlen);
 206        if (len <= 0) return -EINVAL;
 207
 208        if (rpc_pton(cd->net, buf, len, &address.sa, sizeof(address)) == 0)
 209                return -EINVAL;
 210        switch (address.sa.sa_family) {
 211        case AF_INET:
 212                /* Form a mapped IPv4 address in sin6 */
 213                sin6.sin6_family = AF_INET6;
 214                ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr,
 215                                &sin6.sin6_addr);
 216                break;
 217#if IS_ENABLED(CONFIG_IPV6)
 218        case AF_INET6:
 219                memcpy(&sin6, &address.s6, sizeof(sin6));
 220                break;
 221#endif
 222        default:
 223                return -EINVAL;
 224        }
 225
 226        expiry = get_expiry(&mesg);
 227        if (expiry ==0)
 228                return -EINVAL;
 229
 230        /* domainname, or empty for NEGATIVE */
 231        len = qword_get(&mesg, buf, mlen);
 232        if (len < 0) return -EINVAL;
 233
 234        if (len) {
 235                dom = unix_domain_find(buf);
 236                if (dom == NULL)
 237                        return -ENOENT;
 238        } else
 239                dom = NULL;
 240
 241        /* IPv6 scope IDs are ignored for now */
 242        ipmp = __ip_map_lookup(cd, class, &sin6.sin6_addr);
 243        if (ipmp) {
 244                err = __ip_map_update(cd, ipmp,
 245                             container_of(dom, struct unix_domain, h),
 246                             expiry);
 247        } else
 248                err = -ENOMEM;
 249
 250        if (dom)
 251                auth_domain_put(dom);
 252
 253        cache_flush();
 254        return err;
 255}
 256
 257static int ip_map_show(struct seq_file *m,
 258                       struct cache_detail *cd,
 259                       struct cache_head *h)
 260{
 261        struct ip_map *im;
 262        struct in6_addr addr;
 263        char *dom = "-no-domain-";
 264
 265        if (h == NULL) {
 266                seq_puts(m, "#class IP domain\n");
 267                return 0;
 268        }
 269        im = container_of(h, struct ip_map, h);
 270        /* class addr domain */
 271        addr = im->m_addr;
 272
 273        if (test_bit(CACHE_VALID, &h->flags) &&
 274            !test_bit(CACHE_NEGATIVE, &h->flags))
 275                dom = im->m_client->h.name;
 276
 277        if (ipv6_addr_v4mapped(&addr)) {
 278                seq_printf(m, "%s %pI4 %s\n",
 279                        im->m_class, &addr.s6_addr32[3], dom);
 280        } else {
 281                seq_printf(m, "%s %pI6 %s\n", im->m_class, &addr, dom);
 282        }
 283        return 0;
 284}
 285
 286
 287static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,
 288                struct in6_addr *addr)
 289{
 290        struct ip_map ip;
 291        struct cache_head *ch;
 292
 293        strcpy(ip.m_class, class);
 294        ip.m_addr = *addr;
 295        ch = sunrpc_cache_lookup_rcu(cd, &ip.h,
 296                                     hash_str(class, IP_HASHBITS) ^
 297                                     hash_ip6(addr));
 298
 299        if (ch)
 300                return container_of(ch, struct ip_map, h);
 301        else
 302                return NULL;
 303}
 304
 305static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
 306                struct unix_domain *udom, time64_t expiry)
 307{
 308        struct ip_map ip;
 309        struct cache_head *ch;
 310
 311        ip.m_client = udom;
 312        ip.h.flags = 0;
 313        if (!udom)
 314                set_bit(CACHE_NEGATIVE, &ip.h.flags);
 315        ip.h.expiry_time = expiry;
 316        ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
 317                                 hash_str(ipm->m_class, IP_HASHBITS) ^
 318                                 hash_ip6(&ipm->m_addr));
 319        if (!ch)
 320                return -ENOMEM;
 321        cache_put(ch, cd);
 322        return 0;
 323}
 324
 325void svcauth_unix_purge(struct net *net)
 326{
 327        struct sunrpc_net *sn;
 328
 329        sn = net_generic(net, sunrpc_net_id);
 330        cache_purge(sn->ip_map_cache);
 331}
 332EXPORT_SYMBOL_GPL(svcauth_unix_purge);
 333
 334static inline struct ip_map *
 335ip_map_cached_get(struct svc_xprt *xprt)
 336{
 337        struct ip_map *ipm = NULL;
 338        struct sunrpc_net *sn;
 339
 340        if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
 341                spin_lock(&xprt->xpt_lock);
 342                ipm = xprt->xpt_auth_cache;
 343                if (ipm != NULL) {
 344                        sn = net_generic(xprt->xpt_net, sunrpc_net_id);
 345                        if (cache_is_expired(sn->ip_map_cache, &ipm->h)) {
 346                                /*
 347                                 * The entry has been invalidated since it was
 348                                 * remembered, e.g. by a second mount from the
 349                                 * same IP address.
 350                                 */
 351                                xprt->xpt_auth_cache = NULL;
 352                                spin_unlock(&xprt->xpt_lock);
 353                                cache_put(&ipm->h, sn->ip_map_cache);
 354                                return NULL;
 355                        }
 356                        cache_get(&ipm->h);
 357                }
 358                spin_unlock(&xprt->xpt_lock);
 359        }
 360        return ipm;
 361}
 362
 363static inline void
 364ip_map_cached_put(struct svc_xprt *xprt, struct ip_map *ipm)
 365{
 366        if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
 367                spin_lock(&xprt->xpt_lock);
 368                if (xprt->xpt_auth_cache == NULL) {
 369                        /* newly cached, keep the reference */
 370                        xprt->xpt_auth_cache = ipm;
 371                        ipm = NULL;
 372                }
 373                spin_unlock(&xprt->xpt_lock);
 374        }
 375        if (ipm) {
 376                struct sunrpc_net *sn;
 377
 378                sn = net_generic(xprt->xpt_net, sunrpc_net_id);
 379                cache_put(&ipm->h, sn->ip_map_cache);
 380        }
 381}
 382
 383void
 384svcauth_unix_info_release(struct svc_xprt *xpt)
 385{
 386        struct ip_map *ipm;
 387
 388        ipm = xpt->xpt_auth_cache;
 389        if (ipm != NULL) {
 390                struct sunrpc_net *sn;
 391
 392                sn = net_generic(xpt->xpt_net, sunrpc_net_id);
 393                cache_put(&ipm->h, sn->ip_map_cache);
 394        }
 395}
 396
 397/****************************************************************************
 398 * auth.unix.gid cache
 399 * simple cache to map a UID to a list of GIDs
 400 * because AUTH_UNIX aka AUTH_SYS has a max of UNX_NGROUPS
 401 */
 402#define GID_HASHBITS    8
 403#define GID_HASHMAX     (1<<GID_HASHBITS)
 404
 405struct unix_gid {
 406        struct cache_head       h;
 407        kuid_t                  uid;
 408        struct group_info       *gi;
 409        struct rcu_head         rcu;
 410};
 411
 412static int unix_gid_hash(kuid_t uid)
 413{
 414        return hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS);
 415}
 416
 417static void unix_gid_put(struct kref *kref)
 418{
 419        struct cache_head *item = container_of(kref, struct cache_head, ref);
 420        struct unix_gid *ug = container_of(item, struct unix_gid, h);
 421        if (test_bit(CACHE_VALID, &item->flags) &&
 422            !test_bit(CACHE_NEGATIVE, &item->flags))
 423                put_group_info(ug->gi);
 424        kfree_rcu(ug, rcu);
 425}
 426
 427static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew)
 428{
 429        struct unix_gid *orig = container_of(corig, struct unix_gid, h);
 430        struct unix_gid *new = container_of(cnew, struct unix_gid, h);
 431        return uid_eq(orig->uid, new->uid);
 432}
 433static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem)
 434{
 435        struct unix_gid *new = container_of(cnew, struct unix_gid, h);
 436        struct unix_gid *item = container_of(citem, struct unix_gid, h);
 437        new->uid = item->uid;
 438}
 439static void unix_gid_update(struct cache_head *cnew, struct cache_head *citem)
 440{
 441        struct unix_gid *new = container_of(cnew, struct unix_gid, h);
 442        struct unix_gid *item = container_of(citem, struct unix_gid, h);
 443
 444        get_group_info(item->gi);
 445        new->gi = item->gi;
 446}
 447static struct cache_head *unix_gid_alloc(void)
 448{
 449        struct unix_gid *g = kmalloc(sizeof(*g), GFP_KERNEL);
 450        if (g)
 451                return &g->h;
 452        else
 453                return NULL;
 454}
 455
 456static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h)
 457{
 458        return sunrpc_cache_pipe_upcall_timeout(cd, h);
 459}
 460
 461static void unix_gid_request(struct cache_detail *cd,
 462                             struct cache_head *h,
 463                             char **bpp, int *blen)
 464{
 465        char tuid[20];
 466        struct unix_gid *ug = container_of(h, struct unix_gid, h);
 467
 468        snprintf(tuid, 20, "%u", from_kuid(&init_user_ns, ug->uid));
 469        qword_add(bpp, blen, tuid);
 470        (*bpp)[-1] = '\n';
 471}
 472
 473static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid);
 474
 475static int unix_gid_parse(struct cache_detail *cd,
 476                        char *mesg, int mlen)
 477{
 478        /* uid expiry Ngid gid0 gid1 ... gidN-1 */
 479        int id;
 480        kuid_t uid;
 481        int gids;
 482        int rv;
 483        int i;
 484        int err;
 485        time64_t expiry;
 486        struct unix_gid ug, *ugp;
 487
 488        if (mesg[mlen - 1] != '\n')
 489                return -EINVAL;
 490        mesg[mlen-1] = 0;
 491
 492        rv = get_int(&mesg, &id);
 493        if (rv)
 494                return -EINVAL;
 495        uid = make_kuid(current_user_ns(), id);
 496        ug.uid = uid;
 497
 498        expiry = get_expiry(&mesg);
 499        if (expiry == 0)
 500                return -EINVAL;
 501
 502        rv = get_int(&mesg, &gids);
 503        if (rv || gids < 0 || gids > 8192)
 504                return -EINVAL;
 505
 506        ug.gi = groups_alloc(gids);
 507        if (!ug.gi)
 508                return -ENOMEM;
 509
 510        for (i = 0 ; i < gids ; i++) {
 511                int gid;
 512                kgid_t kgid;
 513                rv = get_int(&mesg, &gid);
 514                err = -EINVAL;
 515                if (rv)
 516                        goto out;
 517                kgid = make_kgid(current_user_ns(), gid);
 518                if (!gid_valid(kgid))
 519                        goto out;
 520                ug.gi->gid[i] = kgid;
 521        }
 522
 523        groups_sort(ug.gi);
 524        ugp = unix_gid_lookup(cd, uid);
 525        if (ugp) {
 526                struct cache_head *ch;
 527                ug.h.flags = 0;
 528                ug.h.expiry_time = expiry;
 529                ch = sunrpc_cache_update(cd,
 530                                         &ug.h, &ugp->h,
 531                                         unix_gid_hash(uid));
 532                if (!ch)
 533                        err = -ENOMEM;
 534                else {
 535                        err = 0;
 536                        cache_put(ch, cd);
 537                }
 538        } else
 539                err = -ENOMEM;
 540 out:
 541        if (ug.gi)
 542                put_group_info(ug.gi);
 543        return err;
 544}
 545
 546static int unix_gid_show(struct seq_file *m,
 547                         struct cache_detail *cd,
 548                         struct cache_head *h)
 549{
 550        struct user_namespace *user_ns = m->file->f_cred->user_ns;
 551        struct unix_gid *ug;
 552        int i;
 553        int glen;
 554
 555        if (h == NULL) {
 556                seq_puts(m, "#uid cnt: gids...\n");
 557                return 0;
 558        }
 559        ug = container_of(h, struct unix_gid, h);
 560        if (test_bit(CACHE_VALID, &h->flags) &&
 561            !test_bit(CACHE_NEGATIVE, &h->flags))
 562                glen = ug->gi->ngroups;
 563        else
 564                glen = 0;
 565
 566        seq_printf(m, "%u %d:", from_kuid_munged(user_ns, ug->uid), glen);
 567        for (i = 0; i < glen; i++)
 568                seq_printf(m, " %d", from_kgid_munged(user_ns, ug->gi->gid[i]));
 569        seq_printf(m, "\n");
 570        return 0;
 571}
 572
 573static const struct cache_detail unix_gid_cache_template = {
 574        .owner          = THIS_MODULE,
 575        .hash_size      = GID_HASHMAX,
 576        .name           = "auth.unix.gid",
 577        .cache_put      = unix_gid_put,
 578        .cache_upcall   = unix_gid_upcall,
 579        .cache_request  = unix_gid_request,
 580        .cache_parse    = unix_gid_parse,
 581        .cache_show     = unix_gid_show,
 582        .match          = unix_gid_match,
 583        .init           = unix_gid_init,
 584        .update         = unix_gid_update,
 585        .alloc          = unix_gid_alloc,
 586};
 587
 588int unix_gid_cache_create(struct net *net)
 589{
 590        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 591        struct cache_detail *cd;
 592        int err;
 593
 594        cd = cache_create_net(&unix_gid_cache_template, net);
 595        if (IS_ERR(cd))
 596                return PTR_ERR(cd);
 597        err = cache_register_net(cd, net);
 598        if (err) {
 599                cache_destroy_net(cd, net);
 600                return err;
 601        }
 602        sn->unix_gid_cache = cd;
 603        return 0;
 604}
 605
 606void unix_gid_cache_destroy(struct net *net)
 607{
 608        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 609        struct cache_detail *cd = sn->unix_gid_cache;
 610
 611        sn->unix_gid_cache = NULL;
 612        cache_purge(cd);
 613        cache_unregister_net(cd, net);
 614        cache_destroy_net(cd, net);
 615}
 616
 617static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid)
 618{
 619        struct unix_gid ug;
 620        struct cache_head *ch;
 621
 622        ug.uid = uid;
 623        ch = sunrpc_cache_lookup_rcu(cd, &ug.h, unix_gid_hash(uid));
 624        if (ch)
 625                return container_of(ch, struct unix_gid, h);
 626        else
 627                return NULL;
 628}
 629
 630static struct group_info *unix_gid_find(kuid_t uid, struct svc_rqst *rqstp)
 631{
 632        struct unix_gid *ug;
 633        struct group_info *gi;
 634        int ret;
 635        struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net,
 636                                            sunrpc_net_id);
 637
 638        ug = unix_gid_lookup(sn->unix_gid_cache, uid);
 639        if (!ug)
 640                return ERR_PTR(-EAGAIN);
 641        ret = cache_check(sn->unix_gid_cache, &ug->h, &rqstp->rq_chandle);
 642        switch (ret) {
 643        case -ENOENT:
 644                return ERR_PTR(-ENOENT);
 645        case -ETIMEDOUT:
 646                return ERR_PTR(-ESHUTDOWN);
 647        case 0:
 648                gi = get_group_info(ug->gi);
 649                cache_put(&ug->h, sn->unix_gid_cache);
 650                return gi;
 651        default:
 652                return ERR_PTR(-EAGAIN);
 653        }
 654}
 655
 656int
 657svcauth_unix_set_client(struct svc_rqst *rqstp)
 658{
 659        struct sockaddr_in *sin;
 660        struct sockaddr_in6 *sin6, sin6_storage;
 661        struct ip_map *ipm;
 662        struct group_info *gi;
 663        struct svc_cred *cred = &rqstp->rq_cred;
 664        struct svc_xprt *xprt = rqstp->rq_xprt;
 665        struct net *net = xprt->xpt_net;
 666        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 667
 668        switch (rqstp->rq_addr.ss_family) {
 669        case AF_INET:
 670                sin = svc_addr_in(rqstp);
 671                sin6 = &sin6_storage;
 672                ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &sin6->sin6_addr);
 673                break;
 674        case AF_INET6:
 675                sin6 = svc_addr_in6(rqstp);
 676                break;
 677        default:
 678                BUG();
 679        }
 680
 681        rqstp->rq_client = NULL;
 682        if (rqstp->rq_proc == 0)
 683                return SVC_OK;
 684
 685        ipm = ip_map_cached_get(xprt);
 686        if (ipm == NULL)
 687                ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class,
 688                                    &sin6->sin6_addr);
 689
 690        if (ipm == NULL)
 691                return SVC_DENIED;
 692
 693        switch (cache_check(sn->ip_map_cache, &ipm->h, &rqstp->rq_chandle)) {
 694                default:
 695                        BUG();
 696                case -ETIMEDOUT:
 697                        return SVC_CLOSE;
 698                case -EAGAIN:
 699                        return SVC_DROP;
 700                case -ENOENT:
 701                        return SVC_DENIED;
 702                case 0:
 703                        rqstp->rq_client = &ipm->m_client->h;
 704                        kref_get(&rqstp->rq_client->ref);
 705                        ip_map_cached_put(xprt, ipm);
 706                        break;
 707        }
 708
 709        gi = unix_gid_find(cred->cr_uid, rqstp);
 710        switch (PTR_ERR(gi)) {
 711        case -EAGAIN:
 712                return SVC_DROP;
 713        case -ESHUTDOWN:
 714                return SVC_CLOSE;
 715        case -ENOENT:
 716                break;
 717        default:
 718                put_group_info(cred->cr_group_info);
 719                cred->cr_group_info = gi;
 720        }
 721        return SVC_OK;
 722}
 723
 724EXPORT_SYMBOL_GPL(svcauth_unix_set_client);
 725
 726static int
 727svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
 728{
 729        struct kvec     *argv = &rqstp->rq_arg.head[0];
 730        struct kvec     *resv = &rqstp->rq_res.head[0];
 731        struct svc_cred *cred = &rqstp->rq_cred;
 732
 733        if (argv->iov_len < 3*4)
 734                return SVC_GARBAGE;
 735
 736        if (svc_getu32(argv) != 0) {
 737                dprintk("svc: bad null cred\n");
 738                *authp = rpc_autherr_badcred;
 739                return SVC_DENIED;
 740        }
 741        if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
 742                dprintk("svc: bad null verf\n");
 743                *authp = rpc_autherr_badverf;
 744                return SVC_DENIED;
 745        }
 746
 747        /* Signal that mapping to nobody uid/gid is required */
 748        cred->cr_uid = INVALID_UID;
 749        cred->cr_gid = INVALID_GID;
 750        cred->cr_group_info = groups_alloc(0);
 751        if (cred->cr_group_info == NULL)
 752                return SVC_CLOSE; /* kmalloc failure - client must retry */
 753
 754        /* Put NULL verifier */
 755        svc_putnl(resv, RPC_AUTH_NULL);
 756        svc_putnl(resv, 0);
 757
 758        rqstp->rq_cred.cr_flavor = RPC_AUTH_NULL;
 759        return SVC_OK;
 760}
 761
 762static int
 763svcauth_null_release(struct svc_rqst *rqstp)
 764{
 765        if (rqstp->rq_client)
 766                auth_domain_put(rqstp->rq_client);
 767        rqstp->rq_client = NULL;
 768        if (rqstp->rq_cred.cr_group_info)
 769                put_group_info(rqstp->rq_cred.cr_group_info);
 770        rqstp->rq_cred.cr_group_info = NULL;
 771
 772        return 0; /* don't drop */
 773}
 774
 775
 776struct auth_ops svcauth_null = {
 777        .name           = "null",
 778        .owner          = THIS_MODULE,
 779        .flavour        = RPC_AUTH_NULL,
 780        .accept         = svcauth_null_accept,
 781        .release        = svcauth_null_release,
 782        .set_client     = svcauth_unix_set_client,
 783};
 784
 785
 786static int
 787svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
 788{
 789        struct kvec     *argv = &rqstp->rq_arg.head[0];
 790        struct kvec     *resv = &rqstp->rq_res.head[0];
 791        struct svc_cred *cred = &rqstp->rq_cred;
 792        struct user_namespace *userns;
 793        u32             slen, i;
 794        int             len   = argv->iov_len;
 795
 796        if ((len -= 3*4) < 0)
 797                return SVC_GARBAGE;
 798
 799        svc_getu32(argv);                       /* length */
 800        svc_getu32(argv);                       /* time stamp */
 801        slen = XDR_QUADLEN(svc_getnl(argv));    /* machname length */
 802        if (slen > 64 || (len -= (slen + 3)*4) < 0)
 803                goto badcred;
 804        argv->iov_base = (void*)((__be32*)argv->iov_base + slen);       /* skip machname */
 805        argv->iov_len -= slen*4;
 806        /*
 807         * Note: we skip uid_valid()/gid_valid() checks here for
 808         * backwards compatibility with clients that use -1 id's.
 809         * Instead, -1 uid or gid is later mapped to the
 810         * (export-specific) anonymous id by nfsd_setuser.
 811         * Supplementary gid's will be left alone.
 812         */
 813        userns = (rqstp->rq_xprt && rqstp->rq_xprt->xpt_cred) ?
 814                rqstp->rq_xprt->xpt_cred->user_ns : &init_user_ns;
 815        cred->cr_uid = make_kuid(userns, svc_getnl(argv)); /* uid */
 816        cred->cr_gid = make_kgid(userns, svc_getnl(argv)); /* gid */
 817        slen = svc_getnl(argv);                 /* gids length */
 818        if (slen > UNX_NGROUPS || (len -= (slen + 2)*4) < 0)
 819                goto badcred;
 820        cred->cr_group_info = groups_alloc(slen);
 821        if (cred->cr_group_info == NULL)
 822                return SVC_CLOSE;
 823        for (i = 0; i < slen; i++) {
 824                kgid_t kgid = make_kgid(userns, svc_getnl(argv));
 825                cred->cr_group_info->gid[i] = kgid;
 826        }
 827        groups_sort(cred->cr_group_info);
 828        if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
 829                *authp = rpc_autherr_badverf;
 830                return SVC_DENIED;
 831        }
 832
 833        /* Put NULL verifier */
 834        svc_putnl(resv, RPC_AUTH_NULL);
 835        svc_putnl(resv, 0);
 836
 837        rqstp->rq_cred.cr_flavor = RPC_AUTH_UNIX;
 838        return SVC_OK;
 839
 840badcred:
 841        *authp = rpc_autherr_badcred;
 842        return SVC_DENIED;
 843}
 844
 845static int
 846svcauth_unix_release(struct svc_rqst *rqstp)
 847{
 848        /* Verifier (such as it is) is already in place.
 849         */
 850        if (rqstp->rq_client)
 851                auth_domain_put(rqstp->rq_client);
 852        rqstp->rq_client = NULL;
 853        if (rqstp->rq_cred.cr_group_info)
 854                put_group_info(rqstp->rq_cred.cr_group_info);
 855        rqstp->rq_cred.cr_group_info = NULL;
 856
 857        return 0;
 858}
 859
 860
 861struct auth_ops svcauth_unix = {
 862        .name           = "unix",
 863        .owner          = THIS_MODULE,
 864        .flavour        = RPC_AUTH_UNIX,
 865        .accept         = svcauth_unix_accept,
 866        .release        = svcauth_unix_release,
 867        .domain_release = svcauth_unix_domain_release,
 868        .set_client     = svcauth_unix_set_client,
 869};
 870
 871static const struct cache_detail ip_map_cache_template = {
 872        .owner          = THIS_MODULE,
 873        .hash_size      = IP_HASHMAX,
 874        .name           = "auth.unix.ip",
 875        .cache_put      = ip_map_put,
 876        .cache_upcall   = ip_map_upcall,
 877        .cache_request  = ip_map_request,
 878        .cache_parse    = ip_map_parse,
 879        .cache_show     = ip_map_show,
 880        .match          = ip_map_match,
 881        .init           = ip_map_init,
 882        .update         = update,
 883        .alloc          = ip_map_alloc,
 884};
 885
 886int ip_map_cache_create(struct net *net)
 887{
 888        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 889        struct cache_detail *cd;
 890        int err;
 891
 892        cd = cache_create_net(&ip_map_cache_template, net);
 893        if (IS_ERR(cd))
 894                return PTR_ERR(cd);
 895        err = cache_register_net(cd, net);
 896        if (err) {
 897                cache_destroy_net(cd, net);
 898                return err;
 899        }
 900        sn->ip_map_cache = cd;
 901        return 0;
 902}
 903
 904void ip_map_cache_destroy(struct net *net)
 905{
 906        struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 907        struct cache_detail *cd = sn->ip_map_cache;
 908
 909        sn->ip_map_cache = NULL;
 910        cache_purge(cd);
 911        cache_unregister_net(cd, net);
 912        cache_destroy_net(cd, net);
 913}
 914