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