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