Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 #include <linux/types.h>
0003 #include <linux/sched.h>
0004 #include <linux/module.h>
0005 #include <linux/sunrpc/types.h>
0006 #include <linux/sunrpc/xdr.h>
0007 #include <linux/sunrpc/svcsock.h>
0008 #include <linux/sunrpc/svcauth.h>
0009 #include <linux/sunrpc/gss_api.h>
0010 #include <linux/sunrpc/addr.h>
0011 #include <linux/err.h>
0012 #include <linux/seq_file.h>
0013 #include <linux/hash.h>
0014 #include <linux/string.h>
0015 #include <linux/slab.h>
0016 #include <net/sock.h>
0017 #include <net/ipv6.h>
0018 #include <linux/kernel.h>
0019 #include <linux/user_namespace.h>
0020 #define RPCDBG_FACILITY RPCDBG_AUTH
0021 
0022 
0023 #include "netns.h"
0024 
0025 /*
0026  * AUTHUNIX and AUTHNULL credentials are both handled here.
0027  * AUTHNULL is treated just like AUTHUNIX except that the uid/gid
0028  * are always nobody (-2).  i.e. we do the same IP address checks for
0029  * AUTHNULL as for AUTHUNIX, and that is done here.
0030  */
0031 
0032 
0033 struct unix_domain {
0034     struct auth_domain  h;
0035     /* other stuff later */
0036 };
0037 
0038 extern struct auth_ops svcauth_null;
0039 extern struct auth_ops svcauth_unix;
0040 extern struct auth_ops svcauth_tls;
0041 
0042 static void svcauth_unix_domain_release_rcu(struct rcu_head *head)
0043 {
0044     struct auth_domain *dom = container_of(head, struct auth_domain, rcu_head);
0045     struct unix_domain *ud = container_of(dom, struct unix_domain, h);
0046 
0047     kfree(dom->name);
0048     kfree(ud);
0049 }
0050 
0051 static void svcauth_unix_domain_release(struct auth_domain *dom)
0052 {
0053     call_rcu(&dom->rcu_head, svcauth_unix_domain_release_rcu);
0054 }
0055 
0056 struct auth_domain *unix_domain_find(char *name)
0057 {
0058     struct auth_domain *rv;
0059     struct unix_domain *new = NULL;
0060 
0061     rv = auth_domain_find(name);
0062     while(1) {
0063         if (rv) {
0064             if (new && rv != &new->h)
0065                 svcauth_unix_domain_release(&new->h);
0066 
0067             if (rv->flavour != &svcauth_unix) {
0068                 auth_domain_put(rv);
0069                 return NULL;
0070             }
0071             return rv;
0072         }
0073 
0074         new = kmalloc(sizeof(*new), GFP_KERNEL);
0075         if (new == NULL)
0076             return NULL;
0077         kref_init(&new->h.ref);
0078         new->h.name = kstrdup(name, GFP_KERNEL);
0079         if (new->h.name == NULL) {
0080             kfree(new);
0081             return NULL;
0082         }
0083         new->h.flavour = &svcauth_unix;
0084         rv = auth_domain_lookup(name, &new->h);
0085     }
0086 }
0087 EXPORT_SYMBOL_GPL(unix_domain_find);
0088 
0089 
0090 /**************************************************
0091  * cache for IP address to unix_domain
0092  * as needed by AUTH_UNIX
0093  */
0094 #define IP_HASHBITS 8
0095 #define IP_HASHMAX  (1<<IP_HASHBITS)
0096 
0097 struct ip_map {
0098     struct cache_head   h;
0099     char            m_class[8]; /* e.g. "nfsd" */
0100     struct in6_addr     m_addr;
0101     struct unix_domain  *m_client;
0102     struct rcu_head     m_rcu;
0103 };
0104 
0105 static void ip_map_put(struct kref *kref)
0106 {
0107     struct cache_head *item = container_of(kref, struct cache_head, ref);
0108     struct ip_map *im = container_of(item, struct ip_map,h);
0109 
0110     if (test_bit(CACHE_VALID, &item->flags) &&
0111         !test_bit(CACHE_NEGATIVE, &item->flags))
0112         auth_domain_put(&im->m_client->h);
0113     kfree_rcu(im, m_rcu);
0114 }
0115 
0116 static inline int hash_ip6(const struct in6_addr *ip)
0117 {
0118     return hash_32(ipv6_addr_hash(ip), IP_HASHBITS);
0119 }
0120 static int ip_map_match(struct cache_head *corig, struct cache_head *cnew)
0121 {
0122     struct ip_map *orig = container_of(corig, struct ip_map, h);
0123     struct ip_map *new = container_of(cnew, struct ip_map, h);
0124     return strcmp(orig->m_class, new->m_class) == 0 &&
0125            ipv6_addr_equal(&orig->m_addr, &new->m_addr);
0126 }
0127 static void ip_map_init(struct cache_head *cnew, struct cache_head *citem)
0128 {
0129     struct ip_map *new = container_of(cnew, struct ip_map, h);
0130     struct ip_map *item = container_of(citem, struct ip_map, h);
0131 
0132     strcpy(new->m_class, item->m_class);
0133     new->m_addr = item->m_addr;
0134 }
0135 static void update(struct cache_head *cnew, struct cache_head *citem)
0136 {
0137     struct ip_map *new = container_of(cnew, struct ip_map, h);
0138     struct ip_map *item = container_of(citem, struct ip_map, h);
0139 
0140     kref_get(&item->m_client->h.ref);
0141     new->m_client = item->m_client;
0142 }
0143 static struct cache_head *ip_map_alloc(void)
0144 {
0145     struct ip_map *i = kmalloc(sizeof(*i), GFP_KERNEL);
0146     if (i)
0147         return &i->h;
0148     else
0149         return NULL;
0150 }
0151 
0152 static int ip_map_upcall(struct cache_detail *cd, struct cache_head *h)
0153 {
0154     return sunrpc_cache_pipe_upcall(cd, h);
0155 }
0156 
0157 static void ip_map_request(struct cache_detail *cd,
0158                   struct cache_head *h,
0159                   char **bpp, int *blen)
0160 {
0161     char text_addr[40];
0162     struct ip_map *im = container_of(h, struct ip_map, h);
0163 
0164     if (ipv6_addr_v4mapped(&(im->m_addr))) {
0165         snprintf(text_addr, 20, "%pI4", &im->m_addr.s6_addr32[3]);
0166     } else {
0167         snprintf(text_addr, 40, "%pI6", &im->m_addr);
0168     }
0169     qword_add(bpp, blen, im->m_class);
0170     qword_add(bpp, blen, text_addr);
0171     (*bpp)[-1] = '\n';
0172 }
0173 
0174 static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, struct in6_addr *addr);
0175 static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, struct unix_domain *udom, time64_t expiry);
0176 
0177 static int ip_map_parse(struct cache_detail *cd,
0178               char *mesg, int mlen)
0179 {
0180     /* class ipaddress [domainname] */
0181     /* should be safe just to use the start of the input buffer
0182      * for scratch: */
0183     char *buf = mesg;
0184     int len;
0185     char class[8];
0186     union {
0187         struct sockaddr     sa;
0188         struct sockaddr_in  s4;
0189         struct sockaddr_in6 s6;
0190     } address;
0191     struct sockaddr_in6 sin6;
0192     int err;
0193 
0194     struct ip_map *ipmp;
0195     struct auth_domain *dom;
0196     time64_t expiry;
0197 
0198     if (mesg[mlen-1] != '\n')
0199         return -EINVAL;
0200     mesg[mlen-1] = 0;
0201 
0202     /* class */
0203     len = qword_get(&mesg, class, sizeof(class));
0204     if (len <= 0) return -EINVAL;
0205 
0206     /* ip address */
0207     len = qword_get(&mesg, buf, mlen);
0208     if (len <= 0) return -EINVAL;
0209 
0210     if (rpc_pton(cd->net, buf, len, &address.sa, sizeof(address)) == 0)
0211         return -EINVAL;
0212     switch (address.sa.sa_family) {
0213     case AF_INET:
0214         /* Form a mapped IPv4 address in sin6 */
0215         sin6.sin6_family = AF_INET6;
0216         ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr,
0217                 &sin6.sin6_addr);
0218         break;
0219 #if IS_ENABLED(CONFIG_IPV6)
0220     case AF_INET6:
0221         memcpy(&sin6, &address.s6, sizeof(sin6));
0222         break;
0223 #endif
0224     default:
0225         return -EINVAL;
0226     }
0227 
0228     expiry = get_expiry(&mesg);
0229     if (expiry ==0)
0230         return -EINVAL;
0231 
0232     /* domainname, or empty for NEGATIVE */
0233     len = qword_get(&mesg, buf, mlen);
0234     if (len < 0) return -EINVAL;
0235 
0236     if (len) {
0237         dom = unix_domain_find(buf);
0238         if (dom == NULL)
0239             return -ENOENT;
0240     } else
0241         dom = NULL;
0242 
0243     /* IPv6 scope IDs are ignored for now */
0244     ipmp = __ip_map_lookup(cd, class, &sin6.sin6_addr);
0245     if (ipmp) {
0246         err = __ip_map_update(cd, ipmp,
0247                  container_of(dom, struct unix_domain, h),
0248                  expiry);
0249     } else
0250         err = -ENOMEM;
0251 
0252     if (dom)
0253         auth_domain_put(dom);
0254 
0255     cache_flush();
0256     return err;
0257 }
0258 
0259 static int ip_map_show(struct seq_file *m,
0260                struct cache_detail *cd,
0261                struct cache_head *h)
0262 {
0263     struct ip_map *im;
0264     struct in6_addr addr;
0265     char *dom = "-no-domain-";
0266 
0267     if (h == NULL) {
0268         seq_puts(m, "#class IP domain\n");
0269         return 0;
0270     }
0271     im = container_of(h, struct ip_map, h);
0272     /* class addr domain */
0273     addr = im->m_addr;
0274 
0275     if (test_bit(CACHE_VALID, &h->flags) &&
0276         !test_bit(CACHE_NEGATIVE, &h->flags))
0277         dom = im->m_client->h.name;
0278 
0279     if (ipv6_addr_v4mapped(&addr)) {
0280         seq_printf(m, "%s %pI4 %s\n",
0281             im->m_class, &addr.s6_addr32[3], dom);
0282     } else {
0283         seq_printf(m, "%s %pI6 %s\n", im->m_class, &addr, dom);
0284     }
0285     return 0;
0286 }
0287 
0288 
0289 static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,
0290         struct in6_addr *addr)
0291 {
0292     struct ip_map ip;
0293     struct cache_head *ch;
0294 
0295     strcpy(ip.m_class, class);
0296     ip.m_addr = *addr;
0297     ch = sunrpc_cache_lookup_rcu(cd, &ip.h,
0298                      hash_str(class, IP_HASHBITS) ^
0299                      hash_ip6(addr));
0300 
0301     if (ch)
0302         return container_of(ch, struct ip_map, h);
0303     else
0304         return NULL;
0305 }
0306 
0307 static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
0308         struct unix_domain *udom, time64_t expiry)
0309 {
0310     struct ip_map ip;
0311     struct cache_head *ch;
0312 
0313     ip.m_client = udom;
0314     ip.h.flags = 0;
0315     if (!udom)
0316         set_bit(CACHE_NEGATIVE, &ip.h.flags);
0317     ip.h.expiry_time = expiry;
0318     ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
0319                  hash_str(ipm->m_class, IP_HASHBITS) ^
0320                  hash_ip6(&ipm->m_addr));
0321     if (!ch)
0322         return -ENOMEM;
0323     cache_put(ch, cd);
0324     return 0;
0325 }
0326 
0327 void svcauth_unix_purge(struct net *net)
0328 {
0329     struct sunrpc_net *sn;
0330 
0331     sn = net_generic(net, sunrpc_net_id);
0332     cache_purge(sn->ip_map_cache);
0333 }
0334 EXPORT_SYMBOL_GPL(svcauth_unix_purge);
0335 
0336 static inline struct ip_map *
0337 ip_map_cached_get(struct svc_xprt *xprt)
0338 {
0339     struct ip_map *ipm = NULL;
0340     struct sunrpc_net *sn;
0341 
0342     if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
0343         spin_lock(&xprt->xpt_lock);
0344         ipm = xprt->xpt_auth_cache;
0345         if (ipm != NULL) {
0346             sn = net_generic(xprt->xpt_net, sunrpc_net_id);
0347             if (cache_is_expired(sn->ip_map_cache, &ipm->h)) {
0348                 /*
0349                  * The entry has been invalidated since it was
0350                  * remembered, e.g. by a second mount from the
0351                  * same IP address.
0352                  */
0353                 xprt->xpt_auth_cache = NULL;
0354                 spin_unlock(&xprt->xpt_lock);
0355                 cache_put(&ipm->h, sn->ip_map_cache);
0356                 return NULL;
0357             }
0358             cache_get(&ipm->h);
0359         }
0360         spin_unlock(&xprt->xpt_lock);
0361     }
0362     return ipm;
0363 }
0364 
0365 static inline void
0366 ip_map_cached_put(struct svc_xprt *xprt, struct ip_map *ipm)
0367 {
0368     if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
0369         spin_lock(&xprt->xpt_lock);
0370         if (xprt->xpt_auth_cache == NULL) {
0371             /* newly cached, keep the reference */
0372             xprt->xpt_auth_cache = ipm;
0373             ipm = NULL;
0374         }
0375         spin_unlock(&xprt->xpt_lock);
0376     }
0377     if (ipm) {
0378         struct sunrpc_net *sn;
0379 
0380         sn = net_generic(xprt->xpt_net, sunrpc_net_id);
0381         cache_put(&ipm->h, sn->ip_map_cache);
0382     }
0383 }
0384 
0385 void
0386 svcauth_unix_info_release(struct svc_xprt *xpt)
0387 {
0388     struct ip_map *ipm;
0389 
0390     ipm = xpt->xpt_auth_cache;
0391     if (ipm != NULL) {
0392         struct sunrpc_net *sn;
0393 
0394         sn = net_generic(xpt->xpt_net, sunrpc_net_id);
0395         cache_put(&ipm->h, sn->ip_map_cache);
0396     }
0397 }
0398 
0399 /****************************************************************************
0400  * auth.unix.gid cache
0401  * simple cache to map a UID to a list of GIDs
0402  * because AUTH_UNIX aka AUTH_SYS has a max of UNX_NGROUPS
0403  */
0404 #define GID_HASHBITS    8
0405 #define GID_HASHMAX (1<<GID_HASHBITS)
0406 
0407 struct unix_gid {
0408     struct cache_head   h;
0409     kuid_t          uid;
0410     struct group_info   *gi;
0411     struct rcu_head     rcu;
0412 };
0413 
0414 static int unix_gid_hash(kuid_t uid)
0415 {
0416     return hash_long(from_kuid(&init_user_ns, uid), GID_HASHBITS);
0417 }
0418 
0419 static void unix_gid_put(struct kref *kref)
0420 {
0421     struct cache_head *item = container_of(kref, struct cache_head, ref);
0422     struct unix_gid *ug = container_of(item, struct unix_gid, h);
0423     if (test_bit(CACHE_VALID, &item->flags) &&
0424         !test_bit(CACHE_NEGATIVE, &item->flags))
0425         put_group_info(ug->gi);
0426     kfree_rcu(ug, rcu);
0427 }
0428 
0429 static int unix_gid_match(struct cache_head *corig, struct cache_head *cnew)
0430 {
0431     struct unix_gid *orig = container_of(corig, struct unix_gid, h);
0432     struct unix_gid *new = container_of(cnew, struct unix_gid, h);
0433     return uid_eq(orig->uid, new->uid);
0434 }
0435 static void unix_gid_init(struct cache_head *cnew, struct cache_head *citem)
0436 {
0437     struct unix_gid *new = container_of(cnew, struct unix_gid, h);
0438     struct unix_gid *item = container_of(citem, struct unix_gid, h);
0439     new->uid = item->uid;
0440 }
0441 static void unix_gid_update(struct cache_head *cnew, struct cache_head *citem)
0442 {
0443     struct unix_gid *new = container_of(cnew, struct unix_gid, h);
0444     struct unix_gid *item = container_of(citem, struct unix_gid, h);
0445 
0446     get_group_info(item->gi);
0447     new->gi = item->gi;
0448 }
0449 static struct cache_head *unix_gid_alloc(void)
0450 {
0451     struct unix_gid *g = kmalloc(sizeof(*g), GFP_KERNEL);
0452     if (g)
0453         return &g->h;
0454     else
0455         return NULL;
0456 }
0457 
0458 static int unix_gid_upcall(struct cache_detail *cd, struct cache_head *h)
0459 {
0460     return sunrpc_cache_pipe_upcall_timeout(cd, h);
0461 }
0462 
0463 static void unix_gid_request(struct cache_detail *cd,
0464                  struct cache_head *h,
0465                  char **bpp, int *blen)
0466 {
0467     char tuid[20];
0468     struct unix_gid *ug = container_of(h, struct unix_gid, h);
0469 
0470     snprintf(tuid, 20, "%u", from_kuid(&init_user_ns, ug->uid));
0471     qword_add(bpp, blen, tuid);
0472     (*bpp)[-1] = '\n';
0473 }
0474 
0475 static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid);
0476 
0477 static int unix_gid_parse(struct cache_detail *cd,
0478             char *mesg, int mlen)
0479 {
0480     /* uid expiry Ngid gid0 gid1 ... gidN-1 */
0481     int id;
0482     kuid_t uid;
0483     int gids;
0484     int rv;
0485     int i;
0486     int err;
0487     time64_t expiry;
0488     struct unix_gid ug, *ugp;
0489 
0490     if (mesg[mlen - 1] != '\n')
0491         return -EINVAL;
0492     mesg[mlen-1] = 0;
0493 
0494     rv = get_int(&mesg, &id);
0495     if (rv)
0496         return -EINVAL;
0497     uid = make_kuid(current_user_ns(), id);
0498     ug.uid = uid;
0499 
0500     expiry = get_expiry(&mesg);
0501     if (expiry == 0)
0502         return -EINVAL;
0503 
0504     rv = get_int(&mesg, &gids);
0505     if (rv || gids < 0 || gids > 8192)
0506         return -EINVAL;
0507 
0508     ug.gi = groups_alloc(gids);
0509     if (!ug.gi)
0510         return -ENOMEM;
0511 
0512     for (i = 0 ; i < gids ; i++) {
0513         int gid;
0514         kgid_t kgid;
0515         rv = get_int(&mesg, &gid);
0516         err = -EINVAL;
0517         if (rv)
0518             goto out;
0519         kgid = make_kgid(current_user_ns(), gid);
0520         if (!gid_valid(kgid))
0521             goto out;
0522         ug.gi->gid[i] = kgid;
0523     }
0524 
0525     groups_sort(ug.gi);
0526     ugp = unix_gid_lookup(cd, uid);
0527     if (ugp) {
0528         struct cache_head *ch;
0529         ug.h.flags = 0;
0530         ug.h.expiry_time = expiry;
0531         ch = sunrpc_cache_update(cd,
0532                      &ug.h, &ugp->h,
0533                      unix_gid_hash(uid));
0534         if (!ch)
0535             err = -ENOMEM;
0536         else {
0537             err = 0;
0538             cache_put(ch, cd);
0539         }
0540     } else
0541         err = -ENOMEM;
0542  out:
0543     if (ug.gi)
0544         put_group_info(ug.gi);
0545     return err;
0546 }
0547 
0548 static int unix_gid_show(struct seq_file *m,
0549              struct cache_detail *cd,
0550              struct cache_head *h)
0551 {
0552     struct user_namespace *user_ns = m->file->f_cred->user_ns;
0553     struct unix_gid *ug;
0554     int i;
0555     int glen;
0556 
0557     if (h == NULL) {
0558         seq_puts(m, "#uid cnt: gids...\n");
0559         return 0;
0560     }
0561     ug = container_of(h, struct unix_gid, h);
0562     if (test_bit(CACHE_VALID, &h->flags) &&
0563         !test_bit(CACHE_NEGATIVE, &h->flags))
0564         glen = ug->gi->ngroups;
0565     else
0566         glen = 0;
0567 
0568     seq_printf(m, "%u %d:", from_kuid_munged(user_ns, ug->uid), glen);
0569     for (i = 0; i < glen; i++)
0570         seq_printf(m, " %d", from_kgid_munged(user_ns, ug->gi->gid[i]));
0571     seq_printf(m, "\n");
0572     return 0;
0573 }
0574 
0575 static const struct cache_detail unix_gid_cache_template = {
0576     .owner      = THIS_MODULE,
0577     .hash_size  = GID_HASHMAX,
0578     .name       = "auth.unix.gid",
0579     .cache_put  = unix_gid_put,
0580     .cache_upcall   = unix_gid_upcall,
0581     .cache_request  = unix_gid_request,
0582     .cache_parse    = unix_gid_parse,
0583     .cache_show = unix_gid_show,
0584     .match      = unix_gid_match,
0585     .init       = unix_gid_init,
0586     .update     = unix_gid_update,
0587     .alloc      = unix_gid_alloc,
0588 };
0589 
0590 int unix_gid_cache_create(struct net *net)
0591 {
0592     struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
0593     struct cache_detail *cd;
0594     int err;
0595 
0596     cd = cache_create_net(&unix_gid_cache_template, net);
0597     if (IS_ERR(cd))
0598         return PTR_ERR(cd);
0599     err = cache_register_net(cd, net);
0600     if (err) {
0601         cache_destroy_net(cd, net);
0602         return err;
0603     }
0604     sn->unix_gid_cache = cd;
0605     return 0;
0606 }
0607 
0608 void unix_gid_cache_destroy(struct net *net)
0609 {
0610     struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
0611     struct cache_detail *cd = sn->unix_gid_cache;
0612 
0613     sn->unix_gid_cache = NULL;
0614     cache_purge(cd);
0615     cache_unregister_net(cd, net);
0616     cache_destroy_net(cd, net);
0617 }
0618 
0619 static struct unix_gid *unix_gid_lookup(struct cache_detail *cd, kuid_t uid)
0620 {
0621     struct unix_gid ug;
0622     struct cache_head *ch;
0623 
0624     ug.uid = uid;
0625     ch = sunrpc_cache_lookup_rcu(cd, &ug.h, unix_gid_hash(uid));
0626     if (ch)
0627         return container_of(ch, struct unix_gid, h);
0628     else
0629         return NULL;
0630 }
0631 
0632 static struct group_info *unix_gid_find(kuid_t uid, struct svc_rqst *rqstp)
0633 {
0634     struct unix_gid *ug;
0635     struct group_info *gi;
0636     int ret;
0637     struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net,
0638                         sunrpc_net_id);
0639 
0640     ug = unix_gid_lookup(sn->unix_gid_cache, uid);
0641     if (!ug)
0642         return ERR_PTR(-EAGAIN);
0643     ret = cache_check(sn->unix_gid_cache, &ug->h, &rqstp->rq_chandle);
0644     switch (ret) {
0645     case -ENOENT:
0646         return ERR_PTR(-ENOENT);
0647     case -ETIMEDOUT:
0648         return ERR_PTR(-ESHUTDOWN);
0649     case 0:
0650         gi = get_group_info(ug->gi);
0651         cache_put(&ug->h, sn->unix_gid_cache);
0652         return gi;
0653     default:
0654         return ERR_PTR(-EAGAIN);
0655     }
0656 }
0657 
0658 int
0659 svcauth_unix_set_client(struct svc_rqst *rqstp)
0660 {
0661     struct sockaddr_in *sin;
0662     struct sockaddr_in6 *sin6, sin6_storage;
0663     struct ip_map *ipm;
0664     struct group_info *gi;
0665     struct svc_cred *cred = &rqstp->rq_cred;
0666     struct svc_xprt *xprt = rqstp->rq_xprt;
0667     struct net *net = xprt->xpt_net;
0668     struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
0669 
0670     switch (rqstp->rq_addr.ss_family) {
0671     case AF_INET:
0672         sin = svc_addr_in(rqstp);
0673         sin6 = &sin6_storage;
0674         ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &sin6->sin6_addr);
0675         break;
0676     case AF_INET6:
0677         sin6 = svc_addr_in6(rqstp);
0678         break;
0679     default:
0680         BUG();
0681     }
0682 
0683     rqstp->rq_client = NULL;
0684     if (rqstp->rq_proc == 0)
0685         goto out;
0686 
0687     rqstp->rq_auth_stat = rpc_autherr_badcred;
0688     ipm = ip_map_cached_get(xprt);
0689     if (ipm == NULL)
0690         ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class,
0691                     &sin6->sin6_addr);
0692 
0693     if (ipm == NULL)
0694         return SVC_DENIED;
0695 
0696     switch (cache_check(sn->ip_map_cache, &ipm->h, &rqstp->rq_chandle)) {
0697         default:
0698             BUG();
0699         case -ETIMEDOUT:
0700             return SVC_CLOSE;
0701         case -EAGAIN:
0702             return SVC_DROP;
0703         case -ENOENT:
0704             return SVC_DENIED;
0705         case 0:
0706             rqstp->rq_client = &ipm->m_client->h;
0707             kref_get(&rqstp->rq_client->ref);
0708             ip_map_cached_put(xprt, ipm);
0709             break;
0710     }
0711 
0712     gi = unix_gid_find(cred->cr_uid, rqstp);
0713     switch (PTR_ERR(gi)) {
0714     case -EAGAIN:
0715         return SVC_DROP;
0716     case -ESHUTDOWN:
0717         return SVC_CLOSE;
0718     case -ENOENT:
0719         break;
0720     default:
0721         put_group_info(cred->cr_group_info);
0722         cred->cr_group_info = gi;
0723     }
0724 
0725 out:
0726     rqstp->rq_auth_stat = rpc_auth_ok;
0727     return SVC_OK;
0728 }
0729 
0730 EXPORT_SYMBOL_GPL(svcauth_unix_set_client);
0731 
0732 static int
0733 svcauth_null_accept(struct svc_rqst *rqstp)
0734 {
0735     struct kvec *argv = &rqstp->rq_arg.head[0];
0736     struct kvec *resv = &rqstp->rq_res.head[0];
0737     struct svc_cred *cred = &rqstp->rq_cred;
0738 
0739     if (argv->iov_len < 3*4)
0740         return SVC_GARBAGE;
0741 
0742     if (svc_getu32(argv) != 0) {
0743         dprintk("svc: bad null cred\n");
0744         rqstp->rq_auth_stat = rpc_autherr_badcred;
0745         return SVC_DENIED;
0746     }
0747     if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
0748         dprintk("svc: bad null verf\n");
0749         rqstp->rq_auth_stat = rpc_autherr_badverf;
0750         return SVC_DENIED;
0751     }
0752 
0753     /* Signal that mapping to nobody uid/gid is required */
0754     cred->cr_uid = INVALID_UID;
0755     cred->cr_gid = INVALID_GID;
0756     cred->cr_group_info = groups_alloc(0);
0757     if (cred->cr_group_info == NULL)
0758         return SVC_CLOSE; /* kmalloc failure - client must retry */
0759 
0760     /* Put NULL verifier */
0761     svc_putnl(resv, RPC_AUTH_NULL);
0762     svc_putnl(resv, 0);
0763 
0764     rqstp->rq_cred.cr_flavor = RPC_AUTH_NULL;
0765     return SVC_OK;
0766 }
0767 
0768 static int
0769 svcauth_null_release(struct svc_rqst *rqstp)
0770 {
0771     if (rqstp->rq_client)
0772         auth_domain_put(rqstp->rq_client);
0773     rqstp->rq_client = NULL;
0774     if (rqstp->rq_cred.cr_group_info)
0775         put_group_info(rqstp->rq_cred.cr_group_info);
0776     rqstp->rq_cred.cr_group_info = NULL;
0777 
0778     return 0; /* don't drop */
0779 }
0780 
0781 
0782 struct auth_ops svcauth_null = {
0783     .name       = "null",
0784     .owner      = THIS_MODULE,
0785     .flavour    = RPC_AUTH_NULL,
0786     .accept     = svcauth_null_accept,
0787     .release    = svcauth_null_release,
0788     .set_client = svcauth_unix_set_client,
0789 };
0790 
0791 
0792 static int
0793 svcauth_tls_accept(struct svc_rqst *rqstp)
0794 {
0795     struct svc_cred *cred = &rqstp->rq_cred;
0796     struct kvec *argv = rqstp->rq_arg.head;
0797     struct kvec *resv = rqstp->rq_res.head;
0798 
0799     if (argv->iov_len < XDR_UNIT * 3)
0800         return SVC_GARBAGE;
0801 
0802     /* Call's cred length */
0803     if (svc_getu32(argv) != xdr_zero) {
0804         rqstp->rq_auth_stat = rpc_autherr_badcred;
0805         return SVC_DENIED;
0806     }
0807 
0808     /* Call's verifier flavor and its length */
0809     if (svc_getu32(argv) != rpc_auth_null ||
0810         svc_getu32(argv) != xdr_zero) {
0811         rqstp->rq_auth_stat = rpc_autherr_badverf;
0812         return SVC_DENIED;
0813     }
0814 
0815     /* AUTH_TLS is not valid on non-NULL procedures */
0816     if (rqstp->rq_proc != 0) {
0817         rqstp->rq_auth_stat = rpc_autherr_badcred;
0818         return SVC_DENIED;
0819     }
0820 
0821     /* Mapping to nobody uid/gid is required */
0822     cred->cr_uid = INVALID_UID;
0823     cred->cr_gid = INVALID_GID;
0824     cred->cr_group_info = groups_alloc(0);
0825     if (cred->cr_group_info == NULL)
0826         return SVC_CLOSE; /* kmalloc failure - client must retry */
0827 
0828     /* Reply's verifier */
0829     svc_putnl(resv, RPC_AUTH_NULL);
0830     if (rqstp->rq_xprt->xpt_ops->xpo_start_tls) {
0831         svc_putnl(resv, 8);
0832         memcpy(resv->iov_base + resv->iov_len, "STARTTLS", 8);
0833         resv->iov_len += 8;
0834     } else
0835         svc_putnl(resv, 0);
0836 
0837     rqstp->rq_cred.cr_flavor = RPC_AUTH_TLS;
0838     return SVC_OK;
0839 }
0840 
0841 struct auth_ops svcauth_tls = {
0842     .name       = "tls",
0843     .owner      = THIS_MODULE,
0844     .flavour    = RPC_AUTH_TLS,
0845     .accept     = svcauth_tls_accept,
0846     .release    = svcauth_null_release,
0847     .set_client = svcauth_unix_set_client,
0848 };
0849 
0850 
0851 static int
0852 svcauth_unix_accept(struct svc_rqst *rqstp)
0853 {
0854     struct kvec *argv = &rqstp->rq_arg.head[0];
0855     struct kvec *resv = &rqstp->rq_res.head[0];
0856     struct svc_cred *cred = &rqstp->rq_cred;
0857     struct user_namespace *userns;
0858     u32     slen, i;
0859     int     len   = argv->iov_len;
0860 
0861     if ((len -= 3*4) < 0)
0862         return SVC_GARBAGE;
0863 
0864     svc_getu32(argv);           /* length */
0865     svc_getu32(argv);           /* time stamp */
0866     slen = XDR_QUADLEN(svc_getnl(argv));    /* machname length */
0867     if (slen > 64 || (len -= (slen + 3)*4) < 0)
0868         goto badcred;
0869     argv->iov_base = (void*)((__be32*)argv->iov_base + slen);   /* skip machname */
0870     argv->iov_len -= slen*4;
0871     /*
0872      * Note: we skip uid_valid()/gid_valid() checks here for
0873      * backwards compatibility with clients that use -1 id's.
0874      * Instead, -1 uid or gid is later mapped to the
0875      * (export-specific) anonymous id by nfsd_setuser.
0876      * Supplementary gid's will be left alone.
0877      */
0878     userns = (rqstp->rq_xprt && rqstp->rq_xprt->xpt_cred) ?
0879         rqstp->rq_xprt->xpt_cred->user_ns : &init_user_ns;
0880     cred->cr_uid = make_kuid(userns, svc_getnl(argv)); /* uid */
0881     cred->cr_gid = make_kgid(userns, svc_getnl(argv)); /* gid */
0882     slen = svc_getnl(argv);         /* gids length */
0883     if (slen > UNX_NGROUPS || (len -= (slen + 2)*4) < 0)
0884         goto badcred;
0885     cred->cr_group_info = groups_alloc(slen);
0886     if (cred->cr_group_info == NULL)
0887         return SVC_CLOSE;
0888     for (i = 0; i < slen; i++) {
0889         kgid_t kgid = make_kgid(userns, svc_getnl(argv));
0890         cred->cr_group_info->gid[i] = kgid;
0891     }
0892     groups_sort(cred->cr_group_info);
0893     if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
0894         rqstp->rq_auth_stat = rpc_autherr_badverf;
0895         return SVC_DENIED;
0896     }
0897 
0898     /* Put NULL verifier */
0899     svc_putnl(resv, RPC_AUTH_NULL);
0900     svc_putnl(resv, 0);
0901 
0902     rqstp->rq_cred.cr_flavor = RPC_AUTH_UNIX;
0903     return SVC_OK;
0904 
0905 badcred:
0906     rqstp->rq_auth_stat = rpc_autherr_badcred;
0907     return SVC_DENIED;
0908 }
0909 
0910 static int
0911 svcauth_unix_release(struct svc_rqst *rqstp)
0912 {
0913     /* Verifier (such as it is) is already in place.
0914      */
0915     if (rqstp->rq_client)
0916         auth_domain_put(rqstp->rq_client);
0917     rqstp->rq_client = NULL;
0918     if (rqstp->rq_cred.cr_group_info)
0919         put_group_info(rqstp->rq_cred.cr_group_info);
0920     rqstp->rq_cred.cr_group_info = NULL;
0921 
0922     return 0;
0923 }
0924 
0925 
0926 struct auth_ops svcauth_unix = {
0927     .name       = "unix",
0928     .owner      = THIS_MODULE,
0929     .flavour    = RPC_AUTH_UNIX,
0930     .accept     = svcauth_unix_accept,
0931     .release    = svcauth_unix_release,
0932     .domain_release = svcauth_unix_domain_release,
0933     .set_client = svcauth_unix_set_client,
0934 };
0935 
0936 static const struct cache_detail ip_map_cache_template = {
0937     .owner      = THIS_MODULE,
0938     .hash_size  = IP_HASHMAX,
0939     .name       = "auth.unix.ip",
0940     .cache_put  = ip_map_put,
0941     .cache_upcall   = ip_map_upcall,
0942     .cache_request  = ip_map_request,
0943     .cache_parse    = ip_map_parse,
0944     .cache_show = ip_map_show,
0945     .match      = ip_map_match,
0946     .init       = ip_map_init,
0947     .update     = update,
0948     .alloc      = ip_map_alloc,
0949 };
0950 
0951 int ip_map_cache_create(struct net *net)
0952 {
0953     struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
0954     struct cache_detail *cd;
0955     int err;
0956 
0957     cd = cache_create_net(&ip_map_cache_template, net);
0958     if (IS_ERR(cd))
0959         return PTR_ERR(cd);
0960     err = cache_register_net(cd, net);
0961     if (err) {
0962         cache_destroy_net(cd, net);
0963         return err;
0964     }
0965     sn->ip_map_cache = cd;
0966     return 0;
0967 }
0968 
0969 void ip_map_cache_destroy(struct net *net)
0970 {
0971     struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
0972     struct cache_detail *cd = sn->ip_map_cache;
0973 
0974     sn->ip_map_cache = NULL;
0975     cache_purge(cd);
0976     cache_unregister_net(cd, net);
0977     cache_destroy_net(cd, net);
0978 }