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