• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * NFS exporting and validation.
3  *
4  * We maintain a list of clients, each of which has a list of
5  * exports. To export an fs to a given client, you first have
6  * to create the client entry with NFSCTL_ADDCLIENT, which
7  * creates a client control block and adds it to the hash
8  * table. Then, you call NFSCTL_EXPORT for each fs.
9  *
10  *
11  * Copyright (C) 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
12  */
13 
14 #include <linux/slab.h>
15 #include <linux/namei.h>
16 #include <linux/module.h>
17 #include <linux/exportfs.h>
18 #include <linux/sunrpc/svc_xprt.h>
19 
20 #include "nfsd.h"
21 #include "nfsfh.h"
22 #include "netns.h"
23 
24 #define NFSDDBG_FACILITY	NFSDDBG_EXPORT
25 
26 /*
27  * We have two caches.
28  * One maps client+vfsmnt+dentry to export options - the export map
29  * The other maps client+filehandle-fragment to export options. - the expkey map
30  *
31  * The export options are actually stored in the first map, and the
32  * second map contains a reference to the entry in the first map.
33  */
34 
35 #define	EXPKEY_HASHBITS		8
36 #define	EXPKEY_HASHMAX		(1 << EXPKEY_HASHBITS)
37 #define	EXPKEY_HASHMASK		(EXPKEY_HASHMAX -1)
38 
expkey_put(struct kref * ref)39 static void expkey_put(struct kref *ref)
40 {
41 	struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
42 
43 	if (test_bit(CACHE_VALID, &key->h.flags) &&
44 	    !test_bit(CACHE_NEGATIVE, &key->h.flags))
45 		path_put(&key->ek_path);
46 	auth_domain_put(key->ek_client);
47 	kfree(key);
48 }
49 
expkey_request(struct cache_detail * cd,struct cache_head * h,char ** bpp,int * blen)50 static void expkey_request(struct cache_detail *cd,
51 			   struct cache_head *h,
52 			   char **bpp, int *blen)
53 {
54 	/* client fsidtype \xfsid */
55 	struct svc_expkey *ek = container_of(h, struct svc_expkey, h);
56 	char type[5];
57 
58 	qword_add(bpp, blen, ek->ek_client->name);
59 	snprintf(type, 5, "%d", ek->ek_fsidtype);
60 	qword_add(bpp, blen, type);
61 	qword_addhex(bpp, blen, (char*)ek->ek_fsid, key_len(ek->ek_fsidtype));
62 	(*bpp)[-1] = '\n';
63 }
64 
65 static struct svc_expkey *svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new,
66 					    struct svc_expkey *old);
67 static struct svc_expkey *svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *);
68 
expkey_parse(struct cache_detail * cd,char * mesg,int mlen)69 static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
70 {
71 	/* client fsidtype fsid expiry [path] */
72 	char *buf;
73 	int len;
74 	struct auth_domain *dom = NULL;
75 	int err;
76 	int fsidtype;
77 	char *ep;
78 	struct svc_expkey key;
79 	struct svc_expkey *ek = NULL;
80 
81 	if (mesg[mlen - 1] != '\n')
82 		return -EINVAL;
83 	mesg[mlen-1] = 0;
84 
85 	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
86 	err = -ENOMEM;
87 	if (!buf)
88 		goto out;
89 
90 	err = -EINVAL;
91 	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
92 		goto out;
93 
94 	err = -ENOENT;
95 	dom = auth_domain_find(buf);
96 	if (!dom)
97 		goto out;
98 	dprintk("found domain %s\n", buf);
99 
100 	err = -EINVAL;
101 	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
102 		goto out;
103 	fsidtype = simple_strtoul(buf, &ep, 10);
104 	if (*ep)
105 		goto out;
106 	dprintk("found fsidtype %d\n", fsidtype);
107 	if (key_len(fsidtype)==0) /* invalid type */
108 		goto out;
109 	if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
110 		goto out;
111 	dprintk("found fsid length %d\n", len);
112 	if (len != key_len(fsidtype))
113 		goto out;
114 
115 	/* OK, we seem to have a valid key */
116 	key.h.flags = 0;
117 	key.h.expiry_time = get_expiry(&mesg);
118 	if (key.h.expiry_time == 0)
119 		goto out;
120 
121 	key.ek_client = dom;
122 	key.ek_fsidtype = fsidtype;
123 	memcpy(key.ek_fsid, buf, len);
124 
125 	ek = svc_expkey_lookup(cd, &key);
126 	err = -ENOMEM;
127 	if (!ek)
128 		goto out;
129 
130 	/* now we want a pathname, or empty meaning NEGATIVE  */
131 	err = -EINVAL;
132 	len = qword_get(&mesg, buf, PAGE_SIZE);
133 	if (len < 0)
134 		goto out;
135 	dprintk("Path seems to be <%s>\n", buf);
136 	err = 0;
137 	if (len == 0) {
138 		set_bit(CACHE_NEGATIVE, &key.h.flags);
139 		ek = svc_expkey_update(cd, &key, ek);
140 		if (!ek)
141 			err = -ENOMEM;
142 	} else {
143 		err = kern_path(buf, 0, &key.ek_path);
144 		if (err)
145 			goto out;
146 
147 		dprintk("Found the path %s\n", buf);
148 
149 		ek = svc_expkey_update(cd, &key, ek);
150 		if (!ek)
151 			err = -ENOMEM;
152 		path_put(&key.ek_path);
153 	}
154 	cache_flush();
155  out:
156 	if (ek)
157 		cache_put(&ek->h, cd);
158 	if (dom)
159 		auth_domain_put(dom);
160 	kfree(buf);
161 	return err;
162 }
163 
expkey_show(struct seq_file * m,struct cache_detail * cd,struct cache_head * h)164 static int expkey_show(struct seq_file *m,
165 		       struct cache_detail *cd,
166 		       struct cache_head *h)
167 {
168 	struct svc_expkey *ek ;
169 	int i;
170 
171 	if (h ==NULL) {
172 		seq_puts(m, "#domain fsidtype fsid [path]\n");
173 		return 0;
174 	}
175 	ek = container_of(h, struct svc_expkey, h);
176 	seq_printf(m, "%s %d 0x", ek->ek_client->name,
177 		   ek->ek_fsidtype);
178 	for (i=0; i < key_len(ek->ek_fsidtype)/4; i++)
179 		seq_printf(m, "%08x", ek->ek_fsid[i]);
180 	if (test_bit(CACHE_VALID, &h->flags) &&
181 	    !test_bit(CACHE_NEGATIVE, &h->flags)) {
182 		seq_printf(m, " ");
183 		seq_path(m, &ek->ek_path, "\\ \t\n");
184 	}
185 	seq_printf(m, "\n");
186 	return 0;
187 }
188 
expkey_match(struct cache_head * a,struct cache_head * b)189 static inline int expkey_match (struct cache_head *a, struct cache_head *b)
190 {
191 	struct svc_expkey *orig = container_of(a, struct svc_expkey, h);
192 	struct svc_expkey *new = container_of(b, struct svc_expkey, h);
193 
194 	if (orig->ek_fsidtype != new->ek_fsidtype ||
195 	    orig->ek_client != new->ek_client ||
196 	    memcmp(orig->ek_fsid, new->ek_fsid, key_len(orig->ek_fsidtype)) != 0)
197 		return 0;
198 	return 1;
199 }
200 
expkey_init(struct cache_head * cnew,struct cache_head * citem)201 static inline void expkey_init(struct cache_head *cnew,
202 				   struct cache_head *citem)
203 {
204 	struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
205 	struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
206 
207 	kref_get(&item->ek_client->ref);
208 	new->ek_client = item->ek_client;
209 	new->ek_fsidtype = item->ek_fsidtype;
210 
211 	memcpy(new->ek_fsid, item->ek_fsid, sizeof(new->ek_fsid));
212 }
213 
expkey_update(struct cache_head * cnew,struct cache_head * citem)214 static inline void expkey_update(struct cache_head *cnew,
215 				   struct cache_head *citem)
216 {
217 	struct svc_expkey *new = container_of(cnew, struct svc_expkey, h);
218 	struct svc_expkey *item = container_of(citem, struct svc_expkey, h);
219 
220 	new->ek_path = item->ek_path;
221 	path_get(&item->ek_path);
222 }
223 
expkey_alloc(void)224 static struct cache_head *expkey_alloc(void)
225 {
226 	struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL);
227 	if (i)
228 		return &i->h;
229 	else
230 		return NULL;
231 }
232 
233 static struct cache_detail svc_expkey_cache_template = {
234 	.owner		= THIS_MODULE,
235 	.hash_size	= EXPKEY_HASHMAX,
236 	.name		= "nfsd.fh",
237 	.cache_put	= expkey_put,
238 	.cache_request	= expkey_request,
239 	.cache_parse	= expkey_parse,
240 	.cache_show	= expkey_show,
241 	.match		= expkey_match,
242 	.init		= expkey_init,
243 	.update       	= expkey_update,
244 	.alloc		= expkey_alloc,
245 };
246 
247 static int
svc_expkey_hash(struct svc_expkey * item)248 svc_expkey_hash(struct svc_expkey *item)
249 {
250 	int hash = item->ek_fsidtype;
251 	char * cp = (char*)item->ek_fsid;
252 	int len = key_len(item->ek_fsidtype);
253 
254 	hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
255 	hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
256 	hash &= EXPKEY_HASHMASK;
257 	return hash;
258 }
259 
260 static struct svc_expkey *
svc_expkey_lookup(struct cache_detail * cd,struct svc_expkey * item)261 svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *item)
262 {
263 	struct cache_head *ch;
264 	int hash = svc_expkey_hash(item);
265 
266 	ch = sunrpc_cache_lookup(cd, &item->h, hash);
267 	if (ch)
268 		return container_of(ch, struct svc_expkey, h);
269 	else
270 		return NULL;
271 }
272 
273 static struct svc_expkey *
svc_expkey_update(struct cache_detail * cd,struct svc_expkey * new,struct svc_expkey * old)274 svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new,
275 		  struct svc_expkey *old)
276 {
277 	struct cache_head *ch;
278 	int hash = svc_expkey_hash(new);
279 
280 	ch = sunrpc_cache_update(cd, &new->h, &old->h, hash);
281 	if (ch)
282 		return container_of(ch, struct svc_expkey, h);
283 	else
284 		return NULL;
285 }
286 
287 
288 #define	EXPORT_HASHBITS		8
289 #define	EXPORT_HASHMAX		(1<< EXPORT_HASHBITS)
290 
nfsd4_fslocs_free(struct nfsd4_fs_locations * fsloc)291 static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc)
292 {
293 	struct nfsd4_fs_location *locations = fsloc->locations;
294 	int i;
295 
296 	if (!locations)
297 		return;
298 
299 	for (i = 0; i < fsloc->locations_count; i++) {
300 		kfree(locations[i].path);
301 		kfree(locations[i].hosts);
302 	}
303 
304 	kfree(locations);
305 	fsloc->locations = NULL;
306 }
307 
svc_export_put(struct kref * ref)308 static void svc_export_put(struct kref *ref)
309 {
310 	struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
311 	path_put(&exp->ex_path);
312 	auth_domain_put(exp->ex_client);
313 	nfsd4_fslocs_free(&exp->ex_fslocs);
314 	kfree(exp->ex_uuid);
315 	kfree(exp);
316 }
317 
svc_export_request(struct cache_detail * cd,struct cache_head * h,char ** bpp,int * blen)318 static void svc_export_request(struct cache_detail *cd,
319 			       struct cache_head *h,
320 			       char **bpp, int *blen)
321 {
322 	/*  client path */
323 	struct svc_export *exp = container_of(h, struct svc_export, h);
324 	char *pth;
325 
326 	qword_add(bpp, blen, exp->ex_client->name);
327 	pth = d_path(&exp->ex_path, *bpp, *blen);
328 	if (IS_ERR(pth)) {
329 		/* is this correct? */
330 		(*bpp)[0] = '\n';
331 		return;
332 	}
333 	qword_add(bpp, blen, pth);
334 	(*bpp)[-1] = '\n';
335 }
336 
337 static struct svc_export *svc_export_update(struct svc_export *new,
338 					    struct svc_export *old);
339 static struct svc_export *svc_export_lookup(struct svc_export *);
340 
check_export(struct inode * inode,int * flags,unsigned char * uuid)341 static int check_export(struct inode *inode, int *flags, unsigned char *uuid)
342 {
343 
344 	/*
345 	 * We currently export only dirs, regular files, and (for v4
346 	 * pseudoroot) symlinks.
347 	 */
348 	if (!S_ISDIR(inode->i_mode) &&
349 	    !S_ISLNK(inode->i_mode) &&
350 	    !S_ISREG(inode->i_mode))
351 		return -ENOTDIR;
352 
353 	/*
354 	 * Mountd should never pass down a writeable V4ROOT export, but,
355 	 * just to make sure:
356 	 */
357 	if (*flags & NFSEXP_V4ROOT)
358 		*flags |= NFSEXP_READONLY;
359 
360 	/* There are two requirements on a filesystem to be exportable.
361 	 * 1:  We must be able to identify the filesystem from a number.
362 	 *       either a device number (so FS_REQUIRES_DEV needed)
363 	 *       or an FSID number (so NFSEXP_FSID or ->uuid is needed).
364 	 * 2:  We must be able to find an inode from a filehandle.
365 	 *       This means that s_export_op must be set.
366 	 */
367 	if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
368 	    !(*flags & NFSEXP_FSID) &&
369 	    uuid == NULL) {
370 		dprintk("exp_export: export of non-dev fs without fsid\n");
371 		return -EINVAL;
372 	}
373 
374 	if (!inode->i_sb->s_export_op ||
375 	    !inode->i_sb->s_export_op->fh_to_dentry) {
376 		dprintk("exp_export: export of invalid fs type.\n");
377 		return -EINVAL;
378 	}
379 
380 	return 0;
381 
382 }
383 
384 #ifdef CONFIG_NFSD_V4
385 
386 static int
fsloc_parse(char ** mesg,char * buf,struct nfsd4_fs_locations * fsloc)387 fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc)
388 {
389 	int len;
390 	int migrated, i, err;
391 
392 	/* more than one fsloc */
393 	if (fsloc->locations)
394 		return -EINVAL;
395 
396 	/* listsize */
397 	err = get_uint(mesg, &fsloc->locations_count);
398 	if (err)
399 		return err;
400 	if (fsloc->locations_count > MAX_FS_LOCATIONS)
401 		return -EINVAL;
402 	if (fsloc->locations_count == 0)
403 		return 0;
404 
405 	fsloc->locations = kzalloc(fsloc->locations_count
406 			* sizeof(struct nfsd4_fs_location), GFP_KERNEL);
407 	if (!fsloc->locations)
408 		return -ENOMEM;
409 	for (i=0; i < fsloc->locations_count; i++) {
410 		/* colon separated host list */
411 		err = -EINVAL;
412 		len = qword_get(mesg, buf, PAGE_SIZE);
413 		if (len <= 0)
414 			goto out_free_all;
415 		err = -ENOMEM;
416 		fsloc->locations[i].hosts = kstrdup(buf, GFP_KERNEL);
417 		if (!fsloc->locations[i].hosts)
418 			goto out_free_all;
419 		err = -EINVAL;
420 		/* slash separated path component list */
421 		len = qword_get(mesg, buf, PAGE_SIZE);
422 		if (len <= 0)
423 			goto out_free_all;
424 		err = -ENOMEM;
425 		fsloc->locations[i].path = kstrdup(buf, GFP_KERNEL);
426 		if (!fsloc->locations[i].path)
427 			goto out_free_all;
428 	}
429 	/* migrated */
430 	err = get_int(mesg, &migrated);
431 	if (err)
432 		goto out_free_all;
433 	err = -EINVAL;
434 	if (migrated < 0 || migrated > 1)
435 		goto out_free_all;
436 	fsloc->migrated = migrated;
437 	return 0;
438 out_free_all:
439 	nfsd4_fslocs_free(fsloc);
440 	return err;
441 }
442 
secinfo_parse(char ** mesg,char * buf,struct svc_export * exp)443 static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
444 {
445 	struct exp_flavor_info *f;
446 	u32 listsize;
447 	int err;
448 
449 	/* more than one secinfo */
450 	if (exp->ex_nflavors)
451 		return -EINVAL;
452 
453 	err = get_uint(mesg, &listsize);
454 	if (err)
455 		return err;
456 	if (listsize > MAX_SECINFO_LIST)
457 		return -EINVAL;
458 
459 	for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) {
460 		err = get_uint(mesg, &f->pseudoflavor);
461 		if (err)
462 			return err;
463 		/*
464 		 * XXX: It would be nice to also check whether this
465 		 * pseudoflavor is supported, so we can discover the
466 		 * problem at export time instead of when a client fails
467 		 * to authenticate.
468 		 */
469 		err = get_uint(mesg, &f->flags);
470 		if (err)
471 			return err;
472 		/* Only some flags are allowed to differ between flavors: */
473 		if (~NFSEXP_SECINFO_FLAGS & (f->flags ^ exp->ex_flags))
474 			return -EINVAL;
475 	}
476 	exp->ex_nflavors = listsize;
477 	return 0;
478 }
479 
480 #else /* CONFIG_NFSD_V4 */
481 static inline int
fsloc_parse(char ** mesg,char * buf,struct nfsd4_fs_locations * fsloc)482 fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc){return 0;}
483 static inline int
secinfo_parse(char ** mesg,char * buf,struct svc_export * exp)484 secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; }
485 #endif
486 
487 static inline int
uuid_parse(char ** mesg,char * buf,unsigned char ** puuid)488 uuid_parse(char **mesg, char *buf, unsigned char **puuid)
489 {
490 	int len;
491 
492 	/* more than one uuid */
493 	if (*puuid)
494 		return -EINVAL;
495 
496 	/* expect a 16 byte uuid encoded as \xXXXX... */
497 	len = qword_get(mesg, buf, PAGE_SIZE);
498 	if (len != EX_UUID_LEN)
499 		return -EINVAL;
500 
501 	*puuid = kmemdup(buf, EX_UUID_LEN, GFP_KERNEL);
502 	if (*puuid == NULL)
503 		return -ENOMEM;
504 
505 	return 0;
506 }
507 
svc_export_parse(struct cache_detail * cd,char * mesg,int mlen)508 static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
509 {
510 	/* client path expiry [flags anonuid anongid fsid] */
511 	char *buf;
512 	int len;
513 	int err;
514 	struct auth_domain *dom = NULL;
515 	struct svc_export exp = {}, *expp;
516 	int an_int;
517 
518 	if (mesg[mlen-1] != '\n')
519 		return -EINVAL;
520 	mesg[mlen-1] = 0;
521 
522 	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
523 	if (!buf)
524 		return -ENOMEM;
525 
526 	/* client */
527 	err = -EINVAL;
528 	len = qword_get(&mesg, buf, PAGE_SIZE);
529 	if (len <= 0)
530 		goto out;
531 
532 	err = -ENOENT;
533 	dom = auth_domain_find(buf);
534 	if (!dom)
535 		goto out;
536 
537 	/* path */
538 	err = -EINVAL;
539 	if ((len = qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
540 		goto out1;
541 
542 	err = kern_path(buf, 0, &exp.ex_path);
543 	if (err)
544 		goto out1;
545 
546 	exp.ex_client = dom;
547 	exp.cd = cd;
548 
549 	/* expiry */
550 	err = -EINVAL;
551 	exp.h.expiry_time = get_expiry(&mesg);
552 	if (exp.h.expiry_time == 0)
553 		goto out3;
554 
555 	/* flags */
556 	err = get_int(&mesg, &an_int);
557 	if (err == -ENOENT) {
558 		err = 0;
559 		set_bit(CACHE_NEGATIVE, &exp.h.flags);
560 	} else {
561 		if (err || an_int < 0)
562 			goto out3;
563 		exp.ex_flags= an_int;
564 
565 		/* anon uid */
566 		err = get_int(&mesg, &an_int);
567 		if (err)
568 			goto out3;
569 		exp.ex_anon_uid= make_kuid(&init_user_ns, an_int);
570 
571 		/* anon gid */
572 		err = get_int(&mesg, &an_int);
573 		if (err)
574 			goto out3;
575 		exp.ex_anon_gid= make_kgid(&init_user_ns, an_int);
576 
577 		/* fsid */
578 		err = get_int(&mesg, &an_int);
579 		if (err)
580 			goto out3;
581 		exp.ex_fsid = an_int;
582 
583 		while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) {
584 			if (strcmp(buf, "fsloc") == 0)
585 				err = fsloc_parse(&mesg, buf, &exp.ex_fslocs);
586 			else if (strcmp(buf, "uuid") == 0)
587 				err = uuid_parse(&mesg, buf, &exp.ex_uuid);
588 			else if (strcmp(buf, "secinfo") == 0)
589 				err = secinfo_parse(&mesg, buf, &exp);
590 			else
591 				/* quietly ignore unknown words and anything
592 				 * following. Newer user-space can try to set
593 				 * new values, then see what the result was.
594 				 */
595 				break;
596 			if (err)
597 				goto out4;
598 		}
599 
600 		err = check_export(exp.ex_path.dentry->d_inode, &exp.ex_flags,
601 				   exp.ex_uuid);
602 		if (err)
603 			goto out4;
604 		/*
605 		 * No point caching this if it would immediately expire.
606 		 * Also, this protects exportfs's dummy export from the
607 		 * anon_uid/anon_gid checks:
608 		 */
609 		if (exp.h.expiry_time < seconds_since_boot())
610 			goto out4;
611 		/*
612 		 * For some reason exportfs has been passing down an
613 		 * invalid (-1) uid & gid on the "dummy" export which it
614 		 * uses to test export support.  To make sure exportfs
615 		 * sees errors from check_export we therefore need to
616 		 * delay these checks till after check_export:
617 		 */
618 		err = -EINVAL;
619 		if (!uid_valid(exp.ex_anon_uid))
620 			goto out4;
621 		if (!gid_valid(exp.ex_anon_gid))
622 			goto out4;
623 		err = 0;
624 	}
625 
626 	expp = svc_export_lookup(&exp);
627 	if (expp)
628 		expp = svc_export_update(&exp, expp);
629 	else
630 		err = -ENOMEM;
631 	cache_flush();
632 	if (expp == NULL)
633 		err = -ENOMEM;
634 	else
635 		exp_put(expp);
636 out4:
637 	nfsd4_fslocs_free(&exp.ex_fslocs);
638 	kfree(exp.ex_uuid);
639 out3:
640 	path_put(&exp.ex_path);
641 out1:
642 	auth_domain_put(dom);
643 out:
644 	kfree(buf);
645 	return err;
646 }
647 
648 static void exp_flags(struct seq_file *m, int flag, int fsid,
649 		kuid_t anonu, kgid_t anong, struct nfsd4_fs_locations *fslocs);
650 static void show_secinfo(struct seq_file *m, struct svc_export *exp);
651 
svc_export_show(struct seq_file * m,struct cache_detail * cd,struct cache_head * h)652 static int svc_export_show(struct seq_file *m,
653 			   struct cache_detail *cd,
654 			   struct cache_head *h)
655 {
656 	struct svc_export *exp ;
657 
658 	if (h ==NULL) {
659 		seq_puts(m, "#path domain(flags)\n");
660 		return 0;
661 	}
662 	exp = container_of(h, struct svc_export, h);
663 	seq_path(m, &exp->ex_path, " \t\n\\");
664 	seq_putc(m, '\t');
665 	seq_escape(m, exp->ex_client->name, " \t\n\\");
666 	seq_putc(m, '(');
667 	if (test_bit(CACHE_VALID, &h->flags) &&
668 	    !test_bit(CACHE_NEGATIVE, &h->flags)) {
669 		exp_flags(m, exp->ex_flags, exp->ex_fsid,
670 			  exp->ex_anon_uid, exp->ex_anon_gid, &exp->ex_fslocs);
671 		if (exp->ex_uuid) {
672 			int i;
673 			seq_puts(m, ",uuid=");
674 			for (i = 0; i < EX_UUID_LEN; i++) {
675 				if ((i&3) == 0 && i)
676 					seq_putc(m, ':');
677 				seq_printf(m, "%02x", exp->ex_uuid[i]);
678 			}
679 		}
680 		show_secinfo(m, exp);
681 	}
682 	seq_puts(m, ")\n");
683 	return 0;
684 }
svc_export_match(struct cache_head * a,struct cache_head * b)685 static int svc_export_match(struct cache_head *a, struct cache_head *b)
686 {
687 	struct svc_export *orig = container_of(a, struct svc_export, h);
688 	struct svc_export *new = container_of(b, struct svc_export, h);
689 	return orig->ex_client == new->ex_client &&
690 		orig->ex_path.dentry == new->ex_path.dentry &&
691 		orig->ex_path.mnt == new->ex_path.mnt;
692 }
693 
svc_export_init(struct cache_head * cnew,struct cache_head * citem)694 static void svc_export_init(struct cache_head *cnew, struct cache_head *citem)
695 {
696 	struct svc_export *new = container_of(cnew, struct svc_export, h);
697 	struct svc_export *item = container_of(citem, struct svc_export, h);
698 
699 	kref_get(&item->ex_client->ref);
700 	new->ex_client = item->ex_client;
701 	new->ex_path = item->ex_path;
702 	path_get(&item->ex_path);
703 	new->ex_fslocs.locations = NULL;
704 	new->ex_fslocs.locations_count = 0;
705 	new->ex_fslocs.migrated = 0;
706 	new->ex_uuid = NULL;
707 	new->cd = item->cd;
708 }
709 
export_update(struct cache_head * cnew,struct cache_head * citem)710 static void export_update(struct cache_head *cnew, struct cache_head *citem)
711 {
712 	struct svc_export *new = container_of(cnew, struct svc_export, h);
713 	struct svc_export *item = container_of(citem, struct svc_export, h);
714 	int i;
715 
716 	new->ex_flags = item->ex_flags;
717 	new->ex_anon_uid = item->ex_anon_uid;
718 	new->ex_anon_gid = item->ex_anon_gid;
719 	new->ex_fsid = item->ex_fsid;
720 	new->ex_uuid = item->ex_uuid;
721 	item->ex_uuid = NULL;
722 	new->ex_fslocs.locations = item->ex_fslocs.locations;
723 	item->ex_fslocs.locations = NULL;
724 	new->ex_fslocs.locations_count = item->ex_fslocs.locations_count;
725 	item->ex_fslocs.locations_count = 0;
726 	new->ex_fslocs.migrated = item->ex_fslocs.migrated;
727 	item->ex_fslocs.migrated = 0;
728 	new->ex_nflavors = item->ex_nflavors;
729 	for (i = 0; i < MAX_SECINFO_LIST; i++) {
730 		new->ex_flavors[i] = item->ex_flavors[i];
731 	}
732 }
733 
svc_export_alloc(void)734 static struct cache_head *svc_export_alloc(void)
735 {
736 	struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL);
737 	if (i)
738 		return &i->h;
739 	else
740 		return NULL;
741 }
742 
743 static struct cache_detail svc_export_cache_template = {
744 	.owner		= THIS_MODULE,
745 	.hash_size	= EXPORT_HASHMAX,
746 	.name		= "nfsd.export",
747 	.cache_put	= svc_export_put,
748 	.cache_request	= svc_export_request,
749 	.cache_parse	= svc_export_parse,
750 	.cache_show	= svc_export_show,
751 	.match		= svc_export_match,
752 	.init		= svc_export_init,
753 	.update		= export_update,
754 	.alloc		= svc_export_alloc,
755 };
756 
757 static int
svc_export_hash(struct svc_export * exp)758 svc_export_hash(struct svc_export *exp)
759 {
760 	int hash;
761 
762 	hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS);
763 	hash ^= hash_ptr(exp->ex_path.dentry, EXPORT_HASHBITS);
764 	hash ^= hash_ptr(exp->ex_path.mnt, EXPORT_HASHBITS);
765 	return hash;
766 }
767 
768 static struct svc_export *
svc_export_lookup(struct svc_export * exp)769 svc_export_lookup(struct svc_export *exp)
770 {
771 	struct cache_head *ch;
772 	int hash = svc_export_hash(exp);
773 
774 	ch = sunrpc_cache_lookup(exp->cd, &exp->h, hash);
775 	if (ch)
776 		return container_of(ch, struct svc_export, h);
777 	else
778 		return NULL;
779 }
780 
781 static struct svc_export *
svc_export_update(struct svc_export * new,struct svc_export * old)782 svc_export_update(struct svc_export *new, struct svc_export *old)
783 {
784 	struct cache_head *ch;
785 	int hash = svc_export_hash(old);
786 
787 	ch = sunrpc_cache_update(old->cd, &new->h, &old->h, hash);
788 	if (ch)
789 		return container_of(ch, struct svc_export, h);
790 	else
791 		return NULL;
792 }
793 
794 
795 static struct svc_expkey *
exp_find_key(struct cache_detail * cd,struct auth_domain * clp,int fsid_type,u32 * fsidv,struct cache_req * reqp)796 exp_find_key(struct cache_detail *cd, struct auth_domain *clp, int fsid_type,
797 	     u32 *fsidv, struct cache_req *reqp)
798 {
799 	struct svc_expkey key, *ek;
800 	int err;
801 
802 	if (!clp)
803 		return ERR_PTR(-ENOENT);
804 
805 	key.ek_client = clp;
806 	key.ek_fsidtype = fsid_type;
807 	memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
808 
809 	ek = svc_expkey_lookup(cd, &key);
810 	if (ek == NULL)
811 		return ERR_PTR(-ENOMEM);
812 	err = cache_check(cd, &ek->h, reqp);
813 	if (err)
814 		return ERR_PTR(err);
815 	return ek;
816 }
817 
818 static struct svc_export *
exp_get_by_name(struct cache_detail * cd,struct auth_domain * clp,const struct path * path,struct cache_req * reqp)819 exp_get_by_name(struct cache_detail *cd, struct auth_domain *clp,
820 		const struct path *path, struct cache_req *reqp)
821 {
822 	struct svc_export *exp, key;
823 	int err;
824 
825 	if (!clp)
826 		return ERR_PTR(-ENOENT);
827 
828 	key.ex_client = clp;
829 	key.ex_path = *path;
830 	key.cd = cd;
831 
832 	exp = svc_export_lookup(&key);
833 	if (exp == NULL)
834 		return ERR_PTR(-ENOMEM);
835 	err = cache_check(cd, &exp->h, reqp);
836 	if (err)
837 		return ERR_PTR(err);
838 	return exp;
839 }
840 
841 /*
842  * Find the export entry for a given dentry.
843  */
844 static struct svc_export *
exp_parent(struct cache_detail * cd,struct auth_domain * clp,struct path * path)845 exp_parent(struct cache_detail *cd, struct auth_domain *clp, struct path *path)
846 {
847 	struct dentry *saved = dget(path->dentry);
848 	struct svc_export *exp = exp_get_by_name(cd, clp, path, NULL);
849 
850 	while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) {
851 		struct dentry *parent = dget_parent(path->dentry);
852 		dput(path->dentry);
853 		path->dentry = parent;
854 		exp = exp_get_by_name(cd, clp, path, NULL);
855 	}
856 	dput(path->dentry);
857 	path->dentry = saved;
858 	return exp;
859 }
860 
861 
862 
863 /*
864  * Obtain the root fh on behalf of a client.
865  * This could be done in user space, but I feel that it adds some safety
866  * since its harder to fool a kernel module than a user space program.
867  */
868 int
exp_rootfh(struct net * net,struct auth_domain * clp,char * name,struct knfsd_fh * f,int maxsize)869 exp_rootfh(struct net *net, struct auth_domain *clp, char *name,
870 	   struct knfsd_fh *f, int maxsize)
871 {
872 	struct svc_export	*exp;
873 	struct path		path;
874 	struct inode		*inode;
875 	struct svc_fh		fh;
876 	int			err;
877 	struct nfsd_net		*nn = net_generic(net, nfsd_net_id);
878 	struct cache_detail	*cd = nn->svc_export_cache;
879 
880 	err = -EPERM;
881 	/* NB: we probably ought to check that it's NUL-terminated */
882 	if (kern_path(name, 0, &path)) {
883 		printk("nfsd: exp_rootfh path not found %s", name);
884 		return err;
885 	}
886 	inode = path.dentry->d_inode;
887 
888 	dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
889 		 name, path.dentry, clp->name,
890 		 inode->i_sb->s_id, inode->i_ino);
891 	exp = exp_parent(cd, clp, &path);
892 	if (IS_ERR(exp)) {
893 		err = PTR_ERR(exp);
894 		goto out;
895 	}
896 
897 	/*
898 	 * fh must be initialized before calling fh_compose
899 	 */
900 	fh_init(&fh, maxsize);
901 	if (fh_compose(&fh, exp, path.dentry, NULL))
902 		err = -EINVAL;
903 	else
904 		err = 0;
905 	memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh));
906 	fh_put(&fh);
907 	exp_put(exp);
908 out:
909 	path_put(&path);
910 	return err;
911 }
912 
exp_find(struct cache_detail * cd,struct auth_domain * clp,int fsid_type,u32 * fsidv,struct cache_req * reqp)913 static struct svc_export *exp_find(struct cache_detail *cd,
914 				   struct auth_domain *clp, int fsid_type,
915 				   u32 *fsidv, struct cache_req *reqp)
916 {
917 	struct svc_export *exp;
918 	struct nfsd_net *nn = net_generic(cd->net, nfsd_net_id);
919 	struct svc_expkey *ek = exp_find_key(nn->svc_expkey_cache, clp, fsid_type, fsidv, reqp);
920 	if (IS_ERR(ek))
921 		return ERR_CAST(ek);
922 
923 	exp = exp_get_by_name(cd, clp, &ek->ek_path, reqp);
924 	cache_put(&ek->h, nn->svc_expkey_cache);
925 
926 	if (IS_ERR(exp))
927 		return ERR_CAST(exp);
928 	return exp;
929 }
930 
check_nfsd_access(struct svc_export * exp,struct svc_rqst * rqstp)931 __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
932 {
933 	struct exp_flavor_info *f;
934 	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
935 
936 	/* legacy gss-only clients are always OK: */
937 	if (exp->ex_client == rqstp->rq_gssclient)
938 		return 0;
939 	/* ip-address based client; check sec= export option: */
940 	for (f = exp->ex_flavors; f < end; f++) {
941 		if (f->pseudoflavor == rqstp->rq_cred.cr_flavor)
942 			return 0;
943 	}
944 	/* defaults in absence of sec= options: */
945 	if (exp->ex_nflavors == 0) {
946 		if (rqstp->rq_cred.cr_flavor == RPC_AUTH_NULL ||
947 		    rqstp->rq_cred.cr_flavor == RPC_AUTH_UNIX)
948 			return 0;
949 	}
950 	return nfserr_wrongsec;
951 }
952 
953 /*
954  * Uses rq_client and rq_gssclient to find an export; uses rq_client (an
955  * auth_unix client) if it's available and has secinfo information;
956  * otherwise, will try to use rq_gssclient.
957  *
958  * Called from functions that handle requests; functions that do work on
959  * behalf of mountd are passed a single client name to use, and should
960  * use exp_get_by_name() or exp_find().
961  */
962 struct svc_export *
rqst_exp_get_by_name(struct svc_rqst * rqstp,struct path * path)963 rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path)
964 {
965 	struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
966 	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
967 	struct cache_detail *cd = nn->svc_export_cache;
968 
969 	if (rqstp->rq_client == NULL)
970 		goto gss;
971 
972 	/* First try the auth_unix client: */
973 	exp = exp_get_by_name(cd, rqstp->rq_client, path, &rqstp->rq_chandle);
974 	if (PTR_ERR(exp) == -ENOENT)
975 		goto gss;
976 	if (IS_ERR(exp))
977 		return exp;
978 	/* If it has secinfo, assume there are no gss/... clients */
979 	if (exp->ex_nflavors > 0)
980 		return exp;
981 gss:
982 	/* Otherwise, try falling back on gss client */
983 	if (rqstp->rq_gssclient == NULL)
984 		return exp;
985 	gssexp = exp_get_by_name(cd, rqstp->rq_gssclient, path, &rqstp->rq_chandle);
986 	if (PTR_ERR(gssexp) == -ENOENT)
987 		return exp;
988 	if (!IS_ERR(exp))
989 		exp_put(exp);
990 	return gssexp;
991 }
992 
993 struct svc_export *
rqst_exp_find(struct svc_rqst * rqstp,int fsid_type,u32 * fsidv)994 rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
995 {
996 	struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
997 	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
998 	struct cache_detail *cd = nn->svc_export_cache;
999 
1000 	if (rqstp->rq_client == NULL)
1001 		goto gss;
1002 
1003 	/* First try the auth_unix client: */
1004 	exp = exp_find(cd, rqstp->rq_client, fsid_type,
1005 		       fsidv, &rqstp->rq_chandle);
1006 	if (PTR_ERR(exp) == -ENOENT)
1007 		goto gss;
1008 	if (IS_ERR(exp))
1009 		return exp;
1010 	/* If it has secinfo, assume there are no gss/... clients */
1011 	if (exp->ex_nflavors > 0)
1012 		return exp;
1013 gss:
1014 	/* Otherwise, try falling back on gss client */
1015 	if (rqstp->rq_gssclient == NULL)
1016 		return exp;
1017 	gssexp = exp_find(cd, rqstp->rq_gssclient, fsid_type, fsidv,
1018 						&rqstp->rq_chandle);
1019 	if (PTR_ERR(gssexp) == -ENOENT)
1020 		return exp;
1021 	if (!IS_ERR(exp))
1022 		exp_put(exp);
1023 	return gssexp;
1024 }
1025 
1026 struct svc_export *
rqst_exp_parent(struct svc_rqst * rqstp,struct path * path)1027 rqst_exp_parent(struct svc_rqst *rqstp, struct path *path)
1028 {
1029 	struct dentry *saved = dget(path->dentry);
1030 	struct svc_export *exp = rqst_exp_get_by_name(rqstp, path);
1031 
1032 	while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) {
1033 		struct dentry *parent = dget_parent(path->dentry);
1034 		dput(path->dentry);
1035 		path->dentry = parent;
1036 		exp = rqst_exp_get_by_name(rqstp, path);
1037 	}
1038 	dput(path->dentry);
1039 	path->dentry = saved;
1040 	return exp;
1041 }
1042 
rqst_find_fsidzero_export(struct svc_rqst * rqstp)1043 struct svc_export *rqst_find_fsidzero_export(struct svc_rqst *rqstp)
1044 {
1045 	u32 fsidv[2];
1046 
1047 	mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL);
1048 
1049 	return rqst_exp_find(rqstp, FSID_NUM, fsidv);
1050 }
1051 
1052 /*
1053  * Called when we need the filehandle for the root of the pseudofs,
1054  * for a given NFSv4 client.   The root is defined to be the
1055  * export point with fsid==0
1056  */
1057 __be32
exp_pseudoroot(struct svc_rqst * rqstp,struct svc_fh * fhp)1058 exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
1059 {
1060 	struct svc_export *exp;
1061 	__be32 rv;
1062 
1063 	exp = rqst_find_fsidzero_export(rqstp);
1064 	if (IS_ERR(exp))
1065 		return nfserrno(PTR_ERR(exp));
1066 	rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL);
1067 	exp_put(exp);
1068 	return rv;
1069 }
1070 
1071 /* Iterator */
1072 
e_start(struct seq_file * m,loff_t * pos)1073 static void *e_start(struct seq_file *m, loff_t *pos)
1074 	__acquires(((struct cache_detail *)m->private)->hash_lock)
1075 {
1076 	loff_t n = *pos;
1077 	unsigned hash, export;
1078 	struct cache_head *ch;
1079 	struct cache_detail *cd = m->private;
1080 	struct cache_head **export_table = cd->hash_table;
1081 
1082 	read_lock(&cd->hash_lock);
1083 	if (!n--)
1084 		return SEQ_START_TOKEN;
1085 	hash = n >> 32;
1086 	export = n & ((1LL<<32) - 1);
1087 
1088 
1089 	for (ch=export_table[hash]; ch; ch=ch->next)
1090 		if (!export--)
1091 			return ch;
1092 	n &= ~((1LL<<32) - 1);
1093 	do {
1094 		hash++;
1095 		n += 1LL<<32;
1096 	} while(hash < EXPORT_HASHMAX && export_table[hash]==NULL);
1097 	if (hash >= EXPORT_HASHMAX)
1098 		return NULL;
1099 	*pos = n+1;
1100 	return export_table[hash];
1101 }
1102 
e_next(struct seq_file * m,void * p,loff_t * pos)1103 static void *e_next(struct seq_file *m, void *p, loff_t *pos)
1104 {
1105 	struct cache_head *ch = p;
1106 	int hash = (*pos >> 32);
1107 	struct cache_detail *cd = m->private;
1108 	struct cache_head **export_table = cd->hash_table;
1109 
1110 	if (p == SEQ_START_TOKEN)
1111 		hash = 0;
1112 	else if (ch->next == NULL) {
1113 		hash++;
1114 		*pos += 1LL<<32;
1115 	} else {
1116 		++*pos;
1117 		return ch->next;
1118 	}
1119 	*pos &= ~((1LL<<32) - 1);
1120 	while (hash < EXPORT_HASHMAX && export_table[hash] == NULL) {
1121 		hash++;
1122 		*pos += 1LL<<32;
1123 	}
1124 	if (hash >= EXPORT_HASHMAX)
1125 		return NULL;
1126 	++*pos;
1127 	return export_table[hash];
1128 }
1129 
e_stop(struct seq_file * m,void * p)1130 static void e_stop(struct seq_file *m, void *p)
1131 	__releases(((struct cache_detail *)m->private)->hash_lock)
1132 {
1133 	struct cache_detail *cd = m->private;
1134 
1135 	read_unlock(&cd->hash_lock);
1136 }
1137 
1138 static struct flags {
1139 	int flag;
1140 	char *name[2];
1141 } expflags[] = {
1142 	{ NFSEXP_READONLY, {"ro", "rw"}},
1143 	{ NFSEXP_INSECURE_PORT, {"insecure", ""}},
1144 	{ NFSEXP_ROOTSQUASH, {"root_squash", "no_root_squash"}},
1145 	{ NFSEXP_ALLSQUASH, {"all_squash", ""}},
1146 	{ NFSEXP_ASYNC, {"async", "sync"}},
1147 	{ NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}},
1148 	{ NFSEXP_NOREADDIRPLUS, {"nordirplus", ""}},
1149 	{ NFSEXP_NOHIDE, {"nohide", ""}},
1150 	{ NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
1151 	{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
1152 	{ NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
1153 	{ NFSEXP_V4ROOT, {"v4root", ""}},
1154 	{ 0, {"", ""}}
1155 };
1156 
show_expflags(struct seq_file * m,int flags,int mask)1157 static void show_expflags(struct seq_file *m, int flags, int mask)
1158 {
1159 	struct flags *flg;
1160 	int state, first = 0;
1161 
1162 	for (flg = expflags; flg->flag; flg++) {
1163 		if (flg->flag & ~mask)
1164 			continue;
1165 		state = (flg->flag & flags) ? 0 : 1;
1166 		if (*flg->name[state])
1167 			seq_printf(m, "%s%s", first++?",":"", flg->name[state]);
1168 	}
1169 }
1170 
show_secinfo_flags(struct seq_file * m,int flags)1171 static void show_secinfo_flags(struct seq_file *m, int flags)
1172 {
1173 	seq_printf(m, ",");
1174 	show_expflags(m, flags, NFSEXP_SECINFO_FLAGS);
1175 }
1176 
secinfo_flags_equal(int f,int g)1177 static bool secinfo_flags_equal(int f, int g)
1178 {
1179 	f &= NFSEXP_SECINFO_FLAGS;
1180 	g &= NFSEXP_SECINFO_FLAGS;
1181 	return f == g;
1182 }
1183 
show_secinfo_run(struct seq_file * m,struct exp_flavor_info ** fp,struct exp_flavor_info * end)1184 static int show_secinfo_run(struct seq_file *m, struct exp_flavor_info **fp, struct exp_flavor_info *end)
1185 {
1186 	int flags;
1187 
1188 	flags = (*fp)->flags;
1189 	seq_printf(m, ",sec=%d", (*fp)->pseudoflavor);
1190 	(*fp)++;
1191 	while (*fp != end && secinfo_flags_equal(flags, (*fp)->flags)) {
1192 		seq_printf(m, ":%d", (*fp)->pseudoflavor);
1193 		(*fp)++;
1194 	}
1195 	return flags;
1196 }
1197 
show_secinfo(struct seq_file * m,struct svc_export * exp)1198 static void show_secinfo(struct seq_file *m, struct svc_export *exp)
1199 {
1200 	struct exp_flavor_info *f;
1201 	struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
1202 	int flags;
1203 
1204 	if (exp->ex_nflavors == 0)
1205 		return;
1206 	f = exp->ex_flavors;
1207 	flags = show_secinfo_run(m, &f, end);
1208 	if (!secinfo_flags_equal(flags, exp->ex_flags))
1209 		show_secinfo_flags(m, flags);
1210 	while (f != end) {
1211 		flags = show_secinfo_run(m, &f, end);
1212 		show_secinfo_flags(m, flags);
1213 	}
1214 }
1215 
exp_flags(struct seq_file * m,int flag,int fsid,kuid_t anonu,kgid_t anong,struct nfsd4_fs_locations * fsloc)1216 static void exp_flags(struct seq_file *m, int flag, int fsid,
1217 		kuid_t anonu, kgid_t anong, struct nfsd4_fs_locations *fsloc)
1218 {
1219 	show_expflags(m, flag, NFSEXP_ALLFLAGS);
1220 	if (flag & NFSEXP_FSID)
1221 		seq_printf(m, ",fsid=%d", fsid);
1222 	if (!uid_eq(anonu, make_kuid(&init_user_ns, (uid_t)-2)) &&
1223 	    !uid_eq(anonu, make_kuid(&init_user_ns, 0x10000-2)))
1224 		seq_printf(m, ",anonuid=%u", from_kuid(&init_user_ns, anonu));
1225 	if (!gid_eq(anong, make_kgid(&init_user_ns, (gid_t)-2)) &&
1226 	    !gid_eq(anong, make_kgid(&init_user_ns, 0x10000-2)))
1227 		seq_printf(m, ",anongid=%u", from_kgid(&init_user_ns, anong));
1228 	if (fsloc && fsloc->locations_count > 0) {
1229 		char *loctype = (fsloc->migrated) ? "refer" : "replicas";
1230 		int i;
1231 
1232 		seq_printf(m, ",%s=", loctype);
1233 		seq_escape(m, fsloc->locations[0].path, ",;@ \t\n\\");
1234 		seq_putc(m, '@');
1235 		seq_escape(m, fsloc->locations[0].hosts, ",;@ \t\n\\");
1236 		for (i = 1; i < fsloc->locations_count; i++) {
1237 			seq_putc(m, ';');
1238 			seq_escape(m, fsloc->locations[i].path, ",;@ \t\n\\");
1239 			seq_putc(m, '@');
1240 			seq_escape(m, fsloc->locations[i].hosts, ",;@ \t\n\\");
1241 		}
1242 	}
1243 }
1244 
e_show(struct seq_file * m,void * p)1245 static int e_show(struct seq_file *m, void *p)
1246 {
1247 	struct cache_head *cp = p;
1248 	struct svc_export *exp = container_of(cp, struct svc_export, h);
1249 	struct cache_detail *cd = m->private;
1250 
1251 	if (p == SEQ_START_TOKEN) {
1252 		seq_puts(m, "# Version 1.1\n");
1253 		seq_puts(m, "# Path Client(Flags) # IPs\n");
1254 		return 0;
1255 	}
1256 
1257 	exp_get(exp);
1258 	if (cache_check(cd, &exp->h, NULL))
1259 		return 0;
1260 	exp_put(exp);
1261 	return svc_export_show(m, cd, cp);
1262 }
1263 
1264 const struct seq_operations nfs_exports_op = {
1265 	.start	= e_start,
1266 	.next	= e_next,
1267 	.stop	= e_stop,
1268 	.show	= e_show,
1269 };
1270 
1271 /*
1272  * Initialize the exports module.
1273  */
1274 int
nfsd_export_init(struct net * net)1275 nfsd_export_init(struct net *net)
1276 {
1277 	int rv;
1278 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1279 
1280 	dprintk("nfsd: initializing export module (net: %p).\n", net);
1281 
1282 	nn->svc_export_cache = cache_create_net(&svc_export_cache_template, net);
1283 	if (IS_ERR(nn->svc_export_cache))
1284 		return PTR_ERR(nn->svc_export_cache);
1285 	rv = cache_register_net(nn->svc_export_cache, net);
1286 	if (rv)
1287 		goto destroy_export_cache;
1288 
1289 	nn->svc_expkey_cache = cache_create_net(&svc_expkey_cache_template, net);
1290 	if (IS_ERR(nn->svc_expkey_cache)) {
1291 		rv = PTR_ERR(nn->svc_expkey_cache);
1292 		goto unregister_export_cache;
1293 	}
1294 	rv = cache_register_net(nn->svc_expkey_cache, net);
1295 	if (rv)
1296 		goto destroy_expkey_cache;
1297 	return 0;
1298 
1299 destroy_expkey_cache:
1300 	cache_destroy_net(nn->svc_expkey_cache, net);
1301 unregister_export_cache:
1302 	cache_unregister_net(nn->svc_export_cache, net);
1303 destroy_export_cache:
1304 	cache_destroy_net(nn->svc_export_cache, net);
1305 	return rv;
1306 }
1307 
1308 /*
1309  * Flush exports table - called when last nfsd thread is killed
1310  */
1311 void
nfsd_export_flush(struct net * net)1312 nfsd_export_flush(struct net *net)
1313 {
1314 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1315 
1316 	cache_purge(nn->svc_expkey_cache);
1317 	cache_purge(nn->svc_export_cache);
1318 }
1319 
1320 /*
1321  * Shutdown the exports module.
1322  */
1323 void
nfsd_export_shutdown(struct net * net)1324 nfsd_export_shutdown(struct net *net)
1325 {
1326 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1327 
1328 	dprintk("nfsd: shutting down export module (net: %p).\n", net);
1329 
1330 	cache_unregister_net(nn->svc_expkey_cache, net);
1331 	cache_unregister_net(nn->svc_export_cache, net);
1332 	cache_destroy_net(nn->svc_expkey_cache, net);
1333 	cache_destroy_net(nn->svc_export_cache, net);
1334 	svcauth_unix_purge(net);
1335 
1336 	dprintk("nfsd: export shutdown complete (net: %p).\n", net);
1337 }
1338