1 #define MSNFS /* HACK HACK */ 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 20 #include <linux/nfsd/syscall.h> 21 #include <net/ipv6.h> 22 23 #include "nfsd.h" 24 #include "nfsfh.h" 25 26 #define NFSDDBG_FACILITY NFSDDBG_EXPORT 27 28 typedef struct auth_domain svc_client; 29 typedef struct svc_export svc_export; 30 31 static void exp_do_unexport(svc_export *unexp); 32 static int exp_verify_string(char *cp, int max); 33 34 /* 35 * We have two caches. 36 * One maps client+vfsmnt+dentry to export options - the export map 37 * The other maps client+filehandle-fragment to export options. - the expkey map 38 * 39 * The export options are actually stored in the first map, and the 40 * second map contains a reference to the entry in the first map. 41 */ 42 43 #define EXPKEY_HASHBITS 8 44 #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) 45 #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) 46 static struct cache_head *expkey_table[EXPKEY_HASHMAX]; 47 48 static void expkey_put(struct kref *ref) 49 { 50 struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); 51 52 if (test_bit(CACHE_VALID, &key->h.flags) && 53 !test_bit(CACHE_NEGATIVE, &key->h.flags)) 54 path_put(&key->ek_path); 55 auth_domain_put(key->ek_client); 56 kfree(key); 57 } 58 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 int expkey_upcall(struct cache_detail *cd, struct cache_head *h) 75 { 76 return sunrpc_cache_pipe_upcall(cd, h, expkey_request); 77 } 78 79 static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old); 80 static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *); 81 static struct cache_detail svc_expkey_cache; 82 83 static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) 84 { 85 /* client fsidtype fsid [path] */ 86 char *buf; 87 int len; 88 struct auth_domain *dom = NULL; 89 int err; 90 int fsidtype; 91 char *ep; 92 struct svc_expkey key; 93 struct svc_expkey *ek = NULL; 94 95 if (mesg[mlen-1] != '\n') 96 return -EINVAL; 97 mesg[mlen-1] = 0; 98 99 buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 100 err = -ENOMEM; 101 if (!buf) 102 goto out; 103 104 err = -EINVAL; 105 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0) 106 goto out; 107 108 err = -ENOENT; 109 dom = auth_domain_find(buf); 110 if (!dom) 111 goto out; 112 dprintk("found domain %s\n", buf); 113 114 err = -EINVAL; 115 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0) 116 goto out; 117 fsidtype = simple_strtoul(buf, &ep, 10); 118 if (*ep) 119 goto out; 120 dprintk("found fsidtype %d\n", fsidtype); 121 if (key_len(fsidtype)==0) /* invalid type */ 122 goto out; 123 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0) 124 goto out; 125 dprintk("found fsid length %d\n", len); 126 if (len != key_len(fsidtype)) 127 goto out; 128 129 /* OK, we seem to have a valid key */ 130 key.h.flags = 0; 131 key.h.expiry_time = get_expiry(&mesg); 132 if (key.h.expiry_time == 0) 133 goto out; 134 135 key.ek_client = dom; 136 key.ek_fsidtype = fsidtype; 137 memcpy(key.ek_fsid, buf, len); 138 139 ek = svc_expkey_lookup(&key); 140 err = -ENOMEM; 141 if (!ek) 142 goto out; 143 144 /* now we want a pathname, or empty meaning NEGATIVE */ 145 err = -EINVAL; 146 len = qword_get(&mesg, buf, PAGE_SIZE); 147 if (len < 0) 148 goto out; 149 dprintk("Path seems to be <%s>\n", buf); 150 err = 0; 151 if (len == 0) { 152 set_bit(CACHE_NEGATIVE, &key.h.flags); 153 ek = svc_expkey_update(&key, ek); 154 if (!ek) 155 err = -ENOMEM; 156 } else { 157 err = kern_path(buf, 0, &key.ek_path); 158 if (err) 159 goto out; 160 161 dprintk("Found the path %s\n", buf); 162 163 ek = svc_expkey_update(&key, ek); 164 if (!ek) 165 err = -ENOMEM; 166 path_put(&key.ek_path); 167 } 168 cache_flush(); 169 out: 170 if (ek) 171 cache_put(&ek->h, &svc_expkey_cache); 172 if (dom) 173 auth_domain_put(dom); 174 kfree(buf); 175 return err; 176 } 177 178 static int expkey_show(struct seq_file *m, 179 struct cache_detail *cd, 180 struct cache_head *h) 181 { 182 struct svc_expkey *ek ; 183 int i; 184 185 if (h ==NULL) { 186 seq_puts(m, "#domain fsidtype fsid [path]\n"); 187 return 0; 188 } 189 ek = container_of(h, struct svc_expkey, h); 190 seq_printf(m, "%s %d 0x", ek->ek_client->name, 191 ek->ek_fsidtype); 192 for (i=0; i < key_len(ek->ek_fsidtype)/4; i++) 193 seq_printf(m, "%08x", ek->ek_fsid[i]); 194 if (test_bit(CACHE_VALID, &h->flags) && 195 !test_bit(CACHE_NEGATIVE, &h->flags)) { 196 seq_printf(m, " "); 197 seq_path(m, &ek->ek_path, "\\ \t\n"); 198 } 199 seq_printf(m, "\n"); 200 return 0; 201 } 202 203 static inline int expkey_match (struct cache_head *a, struct cache_head *b) 204 { 205 struct svc_expkey *orig = container_of(a, struct svc_expkey, h); 206 struct svc_expkey *new = container_of(b, struct svc_expkey, h); 207 208 if (orig->ek_fsidtype != new->ek_fsidtype || 209 orig->ek_client != new->ek_client || 210 memcmp(orig->ek_fsid, new->ek_fsid, key_len(orig->ek_fsidtype)) != 0) 211 return 0; 212 return 1; 213 } 214 215 static inline void expkey_init(struct cache_head *cnew, 216 struct cache_head *citem) 217 { 218 struct svc_expkey *new = container_of(cnew, struct svc_expkey, h); 219 struct svc_expkey *item = container_of(citem, struct svc_expkey, h); 220 221 kref_get(&item->ek_client->ref); 222 new->ek_client = item->ek_client; 223 new->ek_fsidtype = item->ek_fsidtype; 224 225 memcpy(new->ek_fsid, item->ek_fsid, sizeof(new->ek_fsid)); 226 } 227 228 static inline void expkey_update(struct cache_head *cnew, 229 struct cache_head *citem) 230 { 231 struct svc_expkey *new = container_of(cnew, struct svc_expkey, h); 232 struct svc_expkey *item = container_of(citem, struct svc_expkey, h); 233 234 new->ek_path = item->ek_path; 235 path_get(&item->ek_path); 236 } 237 238 static struct cache_head *expkey_alloc(void) 239 { 240 struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL); 241 if (i) 242 return &i->h; 243 else 244 return NULL; 245 } 246 247 static struct cache_detail svc_expkey_cache = { 248 .owner = THIS_MODULE, 249 .hash_size = EXPKEY_HASHMAX, 250 .hash_table = expkey_table, 251 .name = "nfsd.fh", 252 .cache_put = expkey_put, 253 .cache_upcall = expkey_upcall, 254 .cache_parse = expkey_parse, 255 .cache_show = expkey_show, 256 .match = expkey_match, 257 .init = expkey_init, 258 .update = expkey_update, 259 .alloc = expkey_alloc, 260 }; 261 262 static int 263 svc_expkey_hash(struct svc_expkey *item) 264 { 265 int hash = item->ek_fsidtype; 266 char * cp = (char*)item->ek_fsid; 267 int len = key_len(item->ek_fsidtype); 268 269 hash ^= hash_mem(cp, len, EXPKEY_HASHBITS); 270 hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS); 271 hash &= EXPKEY_HASHMASK; 272 return hash; 273 } 274 275 static struct svc_expkey * 276 svc_expkey_lookup(struct svc_expkey *item) 277 { 278 struct cache_head *ch; 279 int hash = svc_expkey_hash(item); 280 281 ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h, 282 hash); 283 if (ch) 284 return container_of(ch, struct svc_expkey, h); 285 else 286 return NULL; 287 } 288 289 static struct svc_expkey * 290 svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old) 291 { 292 struct cache_head *ch; 293 int hash = svc_expkey_hash(new); 294 295 ch = sunrpc_cache_update(&svc_expkey_cache, &new->h, 296 &old->h, hash); 297 if (ch) 298 return container_of(ch, struct svc_expkey, h); 299 else 300 return NULL; 301 } 302 303 304 #define EXPORT_HASHBITS 8 305 #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) 306 #define EXPORT_HASHMASK (EXPORT_HASHMAX -1) 307 308 static struct cache_head *export_table[EXPORT_HASHMAX]; 309 310 static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc) 311 { 312 int i; 313 314 for (i = 0; i < fsloc->locations_count; i++) { 315 kfree(fsloc->locations[i].path); 316 kfree(fsloc->locations[i].hosts); 317 } 318 kfree(fsloc->locations); 319 } 320 321 static void svc_export_put(struct kref *ref) 322 { 323 struct svc_export *exp = container_of(ref, struct svc_export, h.ref); 324 path_put(&exp->ex_path); 325 auth_domain_put(exp->ex_client); 326 kfree(exp->ex_pathname); 327 nfsd4_fslocs_free(&exp->ex_fslocs); 328 kfree(exp); 329 } 330 331 static void svc_export_request(struct cache_detail *cd, 332 struct cache_head *h, 333 char **bpp, int *blen) 334 { 335 /* client path */ 336 struct svc_export *exp = container_of(h, struct svc_export, h); 337 char *pth; 338 339 qword_add(bpp, blen, exp->ex_client->name); 340 pth = d_path(&exp->ex_path, *bpp, *blen); 341 if (IS_ERR(pth)) { 342 /* is this correct? */ 343 (*bpp)[0] = '\n'; 344 return; 345 } 346 qword_add(bpp, blen, pth); 347 (*bpp)[-1] = '\n'; 348 } 349 350 static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h) 351 { 352 return sunrpc_cache_pipe_upcall(cd, h, svc_export_request); 353 } 354 355 static struct svc_export *svc_export_update(struct svc_export *new, 356 struct svc_export *old); 357 static struct svc_export *svc_export_lookup(struct svc_export *); 358 359 static int check_export(struct inode *inode, int *flags, unsigned char *uuid) 360 { 361 362 /* 363 * We currently export only dirs, regular files, and (for v4 364 * pseudoroot) symlinks. 365 */ 366 if (!S_ISDIR(inode->i_mode) && 367 !S_ISLNK(inode->i_mode) && 368 !S_ISREG(inode->i_mode)) 369 return -ENOTDIR; 370 371 /* 372 * Mountd should never pass down a writeable V4ROOT export, but, 373 * just to make sure: 374 */ 375 if (*flags & NFSEXP_V4ROOT) 376 *flags |= NFSEXP_READONLY; 377 378 /* There are two requirements on a filesystem to be exportable. 379 * 1: We must be able to identify the filesystem from a number. 380 * either a device number (so FS_REQUIRES_DEV needed) 381 * or an FSID number (so NFSEXP_FSID or ->uuid is needed). 382 * 2: We must be able to find an inode from a filehandle. 383 * This means that s_export_op must be set. 384 */ 385 if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) && 386 !(*flags & NFSEXP_FSID) && 387 uuid == NULL) { 388 dprintk("exp_export: export of non-dev fs without fsid\n"); 389 return -EINVAL; 390 } 391 392 if (!inode->i_sb->s_export_op || 393 !inode->i_sb->s_export_op->fh_to_dentry) { 394 dprintk("exp_export: export of invalid fs type.\n"); 395 return -EINVAL; 396 } 397 398 return 0; 399 400 } 401 402 #ifdef CONFIG_NFSD_V4 403 404 static int 405 fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) 406 { 407 int len; 408 int migrated, i, err; 409 410 /* listsize */ 411 err = get_int(mesg, &fsloc->locations_count); 412 if (err) 413 return err; 414 if (fsloc->locations_count > MAX_FS_LOCATIONS) 415 return -EINVAL; 416 if (fsloc->locations_count == 0) 417 return 0; 418 419 fsloc->locations = kzalloc(fsloc->locations_count 420 * sizeof(struct nfsd4_fs_location), GFP_KERNEL); 421 if (!fsloc->locations) 422 return -ENOMEM; 423 for (i=0; i < fsloc->locations_count; i++) { 424 /* colon separated host list */ 425 err = -EINVAL; 426 len = qword_get(mesg, buf, PAGE_SIZE); 427 if (len <= 0) 428 goto out_free_all; 429 err = -ENOMEM; 430 fsloc->locations[i].hosts = kstrdup(buf, GFP_KERNEL); 431 if (!fsloc->locations[i].hosts) 432 goto out_free_all; 433 err = -EINVAL; 434 /* slash separated path component list */ 435 len = qword_get(mesg, buf, PAGE_SIZE); 436 if (len <= 0) 437 goto out_free_all; 438 err = -ENOMEM; 439 fsloc->locations[i].path = kstrdup(buf, GFP_KERNEL); 440 if (!fsloc->locations[i].path) 441 goto out_free_all; 442 } 443 /* migrated */ 444 err = get_int(mesg, &migrated); 445 if (err) 446 goto out_free_all; 447 err = -EINVAL; 448 if (migrated < 0 || migrated > 1) 449 goto out_free_all; 450 fsloc->migrated = migrated; 451 return 0; 452 out_free_all: 453 nfsd4_fslocs_free(fsloc); 454 return err; 455 } 456 457 static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp) 458 { 459 int listsize, err; 460 struct exp_flavor_info *f; 461 462 err = get_int(mesg, &listsize); 463 if (err) 464 return err; 465 if (listsize < 0 || listsize > MAX_SECINFO_LIST) 466 return -EINVAL; 467 468 for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) { 469 err = get_int(mesg, &f->pseudoflavor); 470 if (err) 471 return err; 472 /* 473 * XXX: It would be nice to also check whether this 474 * pseudoflavor is supported, so we can discover the 475 * problem at export time instead of when a client fails 476 * to authenticate. 477 */ 478 err = get_int(mesg, &f->flags); 479 if (err) 480 return err; 481 /* Only some flags are allowed to differ between flavors: */ 482 if (~NFSEXP_SECINFO_FLAGS & (f->flags ^ exp->ex_flags)) 483 return -EINVAL; 484 } 485 exp->ex_nflavors = listsize; 486 return 0; 487 } 488 489 #else /* CONFIG_NFSD_V4 */ 490 static inline int 491 fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc){return 0;} 492 static inline int 493 secinfo_parse(char **mesg, char *buf, struct svc_export *exp) { return 0; } 494 #endif 495 496 static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) 497 { 498 /* client path expiry [flags anonuid anongid fsid] */ 499 char *buf; 500 int len; 501 int err; 502 struct auth_domain *dom = NULL; 503 struct svc_export exp = {}, *expp; 504 int an_int; 505 506 if (mesg[mlen-1] != '\n') 507 return -EINVAL; 508 mesg[mlen-1] = 0; 509 510 buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 511 if (!buf) 512 return -ENOMEM; 513 514 /* client */ 515 err = -EINVAL; 516 len = qword_get(&mesg, buf, PAGE_SIZE); 517 if (len <= 0) 518 goto out; 519 520 err = -ENOENT; 521 dom = auth_domain_find(buf); 522 if (!dom) 523 goto out; 524 525 /* path */ 526 err = -EINVAL; 527 if ((len = qword_get(&mesg, buf, PAGE_SIZE)) <= 0) 528 goto out1; 529 530 err = kern_path(buf, 0, &exp.ex_path); 531 if (err) 532 goto out1; 533 534 exp.ex_client = dom; 535 536 err = -ENOMEM; 537 exp.ex_pathname = kstrdup(buf, GFP_KERNEL); 538 if (!exp.ex_pathname) 539 goto out2; 540 541 /* expiry */ 542 err = -EINVAL; 543 exp.h.expiry_time = get_expiry(&mesg); 544 if (exp.h.expiry_time == 0) 545 goto out3; 546 547 /* flags */ 548 err = get_int(&mesg, &an_int); 549 if (err == -ENOENT) { 550 err = 0; 551 set_bit(CACHE_NEGATIVE, &exp.h.flags); 552 } else { 553 if (err || an_int < 0) 554 goto out3; 555 exp.ex_flags= an_int; 556 557 /* anon uid */ 558 err = get_int(&mesg, &an_int); 559 if (err) 560 goto out3; 561 exp.ex_anon_uid= an_int; 562 563 /* anon gid */ 564 err = get_int(&mesg, &an_int); 565 if (err) 566 goto out3; 567 exp.ex_anon_gid= an_int; 568 569 /* fsid */ 570 err = get_int(&mesg, &an_int); 571 if (err) 572 goto out3; 573 exp.ex_fsid = an_int; 574 575 while ((len = qword_get(&mesg, buf, PAGE_SIZE)) > 0) { 576 if (strcmp(buf, "fsloc") == 0) 577 err = fsloc_parse(&mesg, buf, &exp.ex_fslocs); 578 else if (strcmp(buf, "uuid") == 0) { 579 /* expect a 16 byte uuid encoded as \xXXXX... */ 580 len = qword_get(&mesg, buf, PAGE_SIZE); 581 if (len != 16) 582 err = -EINVAL; 583 else { 584 exp.ex_uuid = 585 kmemdup(buf, 16, GFP_KERNEL); 586 if (exp.ex_uuid == NULL) 587 err = -ENOMEM; 588 } 589 } else if (strcmp(buf, "secinfo") == 0) 590 err = secinfo_parse(&mesg, buf, &exp); 591 else 592 /* quietly ignore unknown words and anything 593 * following. Newer user-space can try to set 594 * new values, then see what the result was. 595 */ 596 break; 597 if (err) 598 goto out4; 599 } 600 601 err = check_export(exp.ex_path.dentry->d_inode, &exp.ex_flags, 602 exp.ex_uuid); 603 if (err) 604 goto out4; 605 } 606 607 expp = svc_export_lookup(&exp); 608 if (expp) 609 expp = svc_export_update(&exp, expp); 610 else 611 err = -ENOMEM; 612 cache_flush(); 613 if (expp == NULL) 614 err = -ENOMEM; 615 else 616 exp_put(expp); 617 out4: 618 nfsd4_fslocs_free(&exp.ex_fslocs); 619 kfree(exp.ex_uuid); 620 out3: 621 kfree(exp.ex_pathname); 622 out2: 623 path_put(&exp.ex_path); 624 out1: 625 auth_domain_put(dom); 626 out: 627 kfree(buf); 628 return err; 629 } 630 631 static void exp_flags(struct seq_file *m, int flag, int fsid, 632 uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fslocs); 633 static void show_secinfo(struct seq_file *m, struct svc_export *exp); 634 635 static int svc_export_show(struct seq_file *m, 636 struct cache_detail *cd, 637 struct cache_head *h) 638 { 639 struct svc_export *exp ; 640 641 if (h ==NULL) { 642 seq_puts(m, "#path domain(flags)\n"); 643 return 0; 644 } 645 exp = container_of(h, struct svc_export, h); 646 seq_path(m, &exp->ex_path, " \t\n\\"); 647 seq_putc(m, '\t'); 648 seq_escape(m, exp->ex_client->name, " \t\n\\"); 649 seq_putc(m, '('); 650 if (test_bit(CACHE_VALID, &h->flags) && 651 !test_bit(CACHE_NEGATIVE, &h->flags)) { 652 exp_flags(m, exp->ex_flags, exp->ex_fsid, 653 exp->ex_anon_uid, exp->ex_anon_gid, &exp->ex_fslocs); 654 if (exp->ex_uuid) { 655 int i; 656 seq_puts(m, ",uuid="); 657 for (i=0; i<16; i++) { 658 if ((i&3) == 0 && i) 659 seq_putc(m, ':'); 660 seq_printf(m, "%02x", exp->ex_uuid[i]); 661 } 662 } 663 show_secinfo(m, exp); 664 } 665 seq_puts(m, ")\n"); 666 return 0; 667 } 668 static int svc_export_match(struct cache_head *a, struct cache_head *b) 669 { 670 struct svc_export *orig = container_of(a, struct svc_export, h); 671 struct svc_export *new = container_of(b, struct svc_export, h); 672 return orig->ex_client == new->ex_client && 673 orig->ex_path.dentry == new->ex_path.dentry && 674 orig->ex_path.mnt == new->ex_path.mnt; 675 } 676 677 static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) 678 { 679 struct svc_export *new = container_of(cnew, struct svc_export, h); 680 struct svc_export *item = container_of(citem, struct svc_export, h); 681 682 kref_get(&item->ex_client->ref); 683 new->ex_client = item->ex_client; 684 new->ex_path.dentry = dget(item->ex_path.dentry); 685 new->ex_path.mnt = mntget(item->ex_path.mnt); 686 new->ex_pathname = NULL; 687 new->ex_fslocs.locations = NULL; 688 new->ex_fslocs.locations_count = 0; 689 new->ex_fslocs.migrated = 0; 690 } 691 692 static void export_update(struct cache_head *cnew, struct cache_head *citem) 693 { 694 struct svc_export *new = container_of(cnew, struct svc_export, h); 695 struct svc_export *item = container_of(citem, struct svc_export, h); 696 int i; 697 698 new->ex_flags = item->ex_flags; 699 new->ex_anon_uid = item->ex_anon_uid; 700 new->ex_anon_gid = item->ex_anon_gid; 701 new->ex_fsid = item->ex_fsid; 702 new->ex_uuid = item->ex_uuid; 703 item->ex_uuid = NULL; 704 new->ex_pathname = item->ex_pathname; 705 item->ex_pathname = NULL; 706 new->ex_fslocs.locations = item->ex_fslocs.locations; 707 item->ex_fslocs.locations = NULL; 708 new->ex_fslocs.locations_count = item->ex_fslocs.locations_count; 709 item->ex_fslocs.locations_count = 0; 710 new->ex_fslocs.migrated = item->ex_fslocs.migrated; 711 item->ex_fslocs.migrated = 0; 712 new->ex_nflavors = item->ex_nflavors; 713 for (i = 0; i < MAX_SECINFO_LIST; i++) { 714 new->ex_flavors[i] = item->ex_flavors[i]; 715 } 716 } 717 718 static struct cache_head *svc_export_alloc(void) 719 { 720 struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL); 721 if (i) 722 return &i->h; 723 else 724 return NULL; 725 } 726 727 struct cache_detail svc_export_cache = { 728 .owner = THIS_MODULE, 729 .hash_size = EXPORT_HASHMAX, 730 .hash_table = export_table, 731 .name = "nfsd.export", 732 .cache_put = svc_export_put, 733 .cache_upcall = svc_export_upcall, 734 .cache_parse = svc_export_parse, 735 .cache_show = svc_export_show, 736 .match = svc_export_match, 737 .init = svc_export_init, 738 .update = export_update, 739 .alloc = svc_export_alloc, 740 }; 741 742 static int 743 svc_export_hash(struct svc_export *exp) 744 { 745 int hash; 746 747 hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS); 748 hash ^= hash_ptr(exp->ex_path.dentry, EXPORT_HASHBITS); 749 hash ^= hash_ptr(exp->ex_path.mnt, EXPORT_HASHBITS); 750 return hash; 751 } 752 753 static struct svc_export * 754 svc_export_lookup(struct svc_export *exp) 755 { 756 struct cache_head *ch; 757 int hash = svc_export_hash(exp); 758 759 ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h, 760 hash); 761 if (ch) 762 return container_of(ch, struct svc_export, h); 763 else 764 return NULL; 765 } 766 767 static struct svc_export * 768 svc_export_update(struct svc_export *new, struct svc_export *old) 769 { 770 struct cache_head *ch; 771 int hash = svc_export_hash(old); 772 773 ch = sunrpc_cache_update(&svc_export_cache, &new->h, 774 &old->h, 775 hash); 776 if (ch) 777 return container_of(ch, struct svc_export, h); 778 else 779 return NULL; 780 } 781 782 783 static struct svc_expkey * 784 exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) 785 { 786 struct svc_expkey key, *ek; 787 int err; 788 789 if (!clp) 790 return ERR_PTR(-ENOENT); 791 792 key.ek_client = clp; 793 key.ek_fsidtype = fsid_type; 794 memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); 795 796 ek = svc_expkey_lookup(&key); 797 if (ek == NULL) 798 return ERR_PTR(-ENOMEM); 799 err = cache_check(&svc_expkey_cache, &ek->h, reqp); 800 if (err) 801 return ERR_PTR(err); 802 return ek; 803 } 804 805 static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv, 806 struct svc_export *exp) 807 { 808 struct svc_expkey key, *ek; 809 810 key.ek_client = clp; 811 key.ek_fsidtype = fsid_type; 812 memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); 813 key.ek_path = exp->ex_path; 814 key.h.expiry_time = NEVER; 815 key.h.flags = 0; 816 817 ek = svc_expkey_lookup(&key); 818 if (ek) 819 ek = svc_expkey_update(&key,ek); 820 if (ek) { 821 cache_put(&ek->h, &svc_expkey_cache); 822 return 0; 823 } 824 return -ENOMEM; 825 } 826 827 /* 828 * Find the client's export entry matching xdev/xino. 829 */ 830 static inline struct svc_expkey * 831 exp_get_key(svc_client *clp, dev_t dev, ino_t ino) 832 { 833 u32 fsidv[3]; 834 835 if (old_valid_dev(dev)) { 836 mk_fsid(FSID_DEV, fsidv, dev, ino, 0, NULL); 837 return exp_find_key(clp, FSID_DEV, fsidv, NULL); 838 } 839 mk_fsid(FSID_ENCODE_DEV, fsidv, dev, ino, 0, NULL); 840 return exp_find_key(clp, FSID_ENCODE_DEV, fsidv, NULL); 841 } 842 843 /* 844 * Find the client's export entry matching fsid 845 */ 846 static inline struct svc_expkey * 847 exp_get_fsid_key(svc_client *clp, int fsid) 848 { 849 u32 fsidv[2]; 850 851 mk_fsid(FSID_NUM, fsidv, 0, 0, fsid, NULL); 852 853 return exp_find_key(clp, FSID_NUM, fsidv, NULL); 854 } 855 856 static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, 857 struct cache_req *reqp) 858 { 859 struct svc_export *exp, key; 860 int err; 861 862 if (!clp) 863 return ERR_PTR(-ENOENT); 864 865 key.ex_client = clp; 866 key.ex_path = *path; 867 868 exp = svc_export_lookup(&key); 869 if (exp == NULL) 870 return ERR_PTR(-ENOMEM); 871 err = cache_check(&svc_export_cache, &exp->h, reqp); 872 if (err) 873 return ERR_PTR(err); 874 return exp; 875 } 876 877 /* 878 * Find the export entry for a given dentry. 879 */ 880 static struct svc_export *exp_parent(svc_client *clp, struct path *path) 881 { 882 struct dentry *saved = dget(path->dentry); 883 svc_export *exp = exp_get_by_name(clp, path, NULL); 884 885 while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) { 886 struct dentry *parent = dget_parent(path->dentry); 887 dput(path->dentry); 888 path->dentry = parent; 889 exp = exp_get_by_name(clp, path, NULL); 890 } 891 dput(path->dentry); 892 path->dentry = saved; 893 return exp; 894 } 895 896 /* 897 * Hashtable locking. Write locks are placed only by user processes 898 * wanting to modify export information. 899 * Write locking only done in this file. Read locking 900 * needed externally. 901 */ 902 903 static DECLARE_RWSEM(hash_sem); 904 905 void 906 exp_readlock(void) 907 { 908 down_read(&hash_sem); 909 } 910 911 static inline void 912 exp_writelock(void) 913 { 914 down_write(&hash_sem); 915 } 916 917 void 918 exp_readunlock(void) 919 { 920 up_read(&hash_sem); 921 } 922 923 static inline void 924 exp_writeunlock(void) 925 { 926 up_write(&hash_sem); 927 } 928 929 static void exp_fsid_unhash(struct svc_export *exp) 930 { 931 struct svc_expkey *ek; 932 933 if ((exp->ex_flags & NFSEXP_FSID) == 0) 934 return; 935 936 ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); 937 if (!IS_ERR(ek)) { 938 ek->h.expiry_time = get_seconds()-1; 939 cache_put(&ek->h, &svc_expkey_cache); 940 } 941 svc_expkey_cache.nextcheck = get_seconds(); 942 } 943 944 static int exp_fsid_hash(svc_client *clp, struct svc_export *exp) 945 { 946 u32 fsid[2]; 947 948 if ((exp->ex_flags & NFSEXP_FSID) == 0) 949 return 0; 950 951 mk_fsid(FSID_NUM, fsid, 0, 0, exp->ex_fsid, NULL); 952 return exp_set_key(clp, FSID_NUM, fsid, exp); 953 } 954 955 static int exp_hash(struct auth_domain *clp, struct svc_export *exp) 956 { 957 u32 fsid[2]; 958 struct inode *inode = exp->ex_path.dentry->d_inode; 959 dev_t dev = inode->i_sb->s_dev; 960 961 if (old_valid_dev(dev)) { 962 mk_fsid(FSID_DEV, fsid, dev, inode->i_ino, 0, NULL); 963 return exp_set_key(clp, FSID_DEV, fsid, exp); 964 } 965 mk_fsid(FSID_ENCODE_DEV, fsid, dev, inode->i_ino, 0, NULL); 966 return exp_set_key(clp, FSID_ENCODE_DEV, fsid, exp); 967 } 968 969 static void exp_unhash(struct svc_export *exp) 970 { 971 struct svc_expkey *ek; 972 struct inode *inode = exp->ex_path.dentry->d_inode; 973 974 ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); 975 if (!IS_ERR(ek)) { 976 ek->h.expiry_time = get_seconds()-1; 977 cache_put(&ek->h, &svc_expkey_cache); 978 } 979 svc_expkey_cache.nextcheck = get_seconds(); 980 } 981 982 /* 983 * Export a file system. 984 */ 985 int 986 exp_export(struct nfsctl_export *nxp) 987 { 988 svc_client *clp; 989 struct svc_export *exp = NULL; 990 struct svc_export new; 991 struct svc_expkey *fsid_key = NULL; 992 struct path path; 993 int err; 994 995 /* Consistency check */ 996 err = -EINVAL; 997 if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) || 998 !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX)) 999 goto out; 1000 1001 dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n", 1002 nxp->ex_client, nxp->ex_path, 1003 (unsigned)nxp->ex_dev, (long)nxp->ex_ino, 1004 nxp->ex_flags); 1005 1006 /* Try to lock the export table for update */ 1007 exp_writelock(); 1008 1009 /* Look up client info */ 1010 if (!(clp = auth_domain_find(nxp->ex_client))) 1011 goto out_unlock; 1012 1013 1014 /* Look up the dentry */ 1015 err = kern_path(nxp->ex_path, 0, &path); 1016 if (err) 1017 goto out_put_clp; 1018 err = -EINVAL; 1019 1020 exp = exp_get_by_name(clp, &path, NULL); 1021 1022 memset(&new, 0, sizeof(new)); 1023 1024 /* must make sure there won't be an ex_fsid clash */ 1025 if ((nxp->ex_flags & NFSEXP_FSID) && 1026 (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) && 1027 fsid_key->ek_path.mnt && 1028 (fsid_key->ek_path.mnt != path.mnt || 1029 fsid_key->ek_path.dentry != path.dentry)) 1030 goto finish; 1031 1032 if (!IS_ERR(exp)) { 1033 /* just a flags/id/fsid update */ 1034 1035 exp_fsid_unhash(exp); 1036 exp->ex_flags = nxp->ex_flags; 1037 exp->ex_anon_uid = nxp->ex_anon_uid; 1038 exp->ex_anon_gid = nxp->ex_anon_gid; 1039 exp->ex_fsid = nxp->ex_dev; 1040 1041 err = exp_fsid_hash(clp, exp); 1042 goto finish; 1043 } 1044 1045 err = check_export(path.dentry->d_inode, &nxp->ex_flags, NULL); 1046 if (err) goto finish; 1047 1048 err = -ENOMEM; 1049 1050 dprintk("nfsd: creating export entry %p for client %p\n", exp, clp); 1051 1052 new.h.expiry_time = NEVER; 1053 new.h.flags = 0; 1054 new.ex_pathname = kstrdup(nxp->ex_path, GFP_KERNEL); 1055 if (!new.ex_pathname) 1056 goto finish; 1057 new.ex_client = clp; 1058 new.ex_path = path; 1059 new.ex_flags = nxp->ex_flags; 1060 new.ex_anon_uid = nxp->ex_anon_uid; 1061 new.ex_anon_gid = nxp->ex_anon_gid; 1062 new.ex_fsid = nxp->ex_dev; 1063 1064 exp = svc_export_lookup(&new); 1065 if (exp) 1066 exp = svc_export_update(&new, exp); 1067 1068 if (!exp) 1069 goto finish; 1070 1071 if (exp_hash(clp, exp) || 1072 exp_fsid_hash(clp, exp)) { 1073 /* failed to create at least one index */ 1074 exp_do_unexport(exp); 1075 cache_flush(); 1076 } else 1077 err = 0; 1078 finish: 1079 kfree(new.ex_pathname); 1080 if (!IS_ERR_OR_NULL(exp)) 1081 exp_put(exp); 1082 if (!IS_ERR_OR_NULL(fsid_key)) 1083 cache_put(&fsid_key->h, &svc_expkey_cache); 1084 path_put(&path); 1085 out_put_clp: 1086 auth_domain_put(clp); 1087 out_unlock: 1088 exp_writeunlock(); 1089 out: 1090 return err; 1091 } 1092 1093 /* 1094 * Unexport a file system. The export entry has already 1095 * been removed from the client's list of exported fs's. 1096 */ 1097 static void 1098 exp_do_unexport(svc_export *unexp) 1099 { 1100 unexp->h.expiry_time = get_seconds()-1; 1101 svc_export_cache.nextcheck = get_seconds(); 1102 exp_unhash(unexp); 1103 exp_fsid_unhash(unexp); 1104 } 1105 1106 1107 /* 1108 * unexport syscall. 1109 */ 1110 int 1111 exp_unexport(struct nfsctl_export *nxp) 1112 { 1113 struct auth_domain *dom; 1114 svc_export *exp; 1115 struct path path; 1116 int err; 1117 1118 /* Consistency check */ 1119 if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) || 1120 !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX)) 1121 return -EINVAL; 1122 1123 exp_writelock(); 1124 1125 err = -EINVAL; 1126 dom = auth_domain_find(nxp->ex_client); 1127 if (!dom) { 1128 dprintk("nfsd: unexport couldn't find %s\n", nxp->ex_client); 1129 goto out_unlock; 1130 } 1131 1132 err = kern_path(nxp->ex_path, 0, &path); 1133 if (err) 1134 goto out_domain; 1135 1136 err = -EINVAL; 1137 exp = exp_get_by_name(dom, &path, NULL); 1138 path_put(&path); 1139 if (IS_ERR(exp)) 1140 goto out_domain; 1141 1142 exp_do_unexport(exp); 1143 exp_put(exp); 1144 err = 0; 1145 1146 out_domain: 1147 auth_domain_put(dom); 1148 cache_flush(); 1149 out_unlock: 1150 exp_writeunlock(); 1151 return err; 1152 } 1153 1154 /* 1155 * Obtain the root fh on behalf of a client. 1156 * This could be done in user space, but I feel that it adds some safety 1157 * since its harder to fool a kernel module than a user space program. 1158 */ 1159 int 1160 exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize) 1161 { 1162 struct svc_export *exp; 1163 struct path path; 1164 struct inode *inode; 1165 struct svc_fh fh; 1166 int err; 1167 1168 err = -EPERM; 1169 /* NB: we probably ought to check that it's NUL-terminated */ 1170 if (kern_path(name, 0, &path)) { 1171 printk("nfsd: exp_rootfh path not found %s", name); 1172 return err; 1173 } 1174 inode = path.dentry->d_inode; 1175 1176 dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n", 1177 name, path.dentry, clp->name, 1178 inode->i_sb->s_id, inode->i_ino); 1179 exp = exp_parent(clp, &path); 1180 if (IS_ERR(exp)) { 1181 err = PTR_ERR(exp); 1182 goto out; 1183 } 1184 1185 /* 1186 * fh must be initialized before calling fh_compose 1187 */ 1188 fh_init(&fh, maxsize); 1189 if (fh_compose(&fh, exp, path.dentry, NULL)) 1190 err = -EINVAL; 1191 else 1192 err = 0; 1193 memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh)); 1194 fh_put(&fh); 1195 exp_put(exp); 1196 out: 1197 path_put(&path); 1198 return err; 1199 } 1200 1201 static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type, 1202 u32 *fsidv, struct cache_req *reqp) 1203 { 1204 struct svc_export *exp; 1205 struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); 1206 if (IS_ERR(ek)) 1207 return ERR_CAST(ek); 1208 1209 exp = exp_get_by_name(clp, &ek->ek_path, reqp); 1210 cache_put(&ek->h, &svc_expkey_cache); 1211 1212 if (IS_ERR(exp)) 1213 return ERR_CAST(exp); 1214 return exp; 1215 } 1216 1217 __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp) 1218 { 1219 struct exp_flavor_info *f; 1220 struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors; 1221 1222 /* legacy gss-only clients are always OK: */ 1223 if (exp->ex_client == rqstp->rq_gssclient) 1224 return 0; 1225 /* ip-address based client; check sec= export option: */ 1226 for (f = exp->ex_flavors; f < end; f++) { 1227 if (f->pseudoflavor == rqstp->rq_flavor) 1228 return 0; 1229 } 1230 /* defaults in absence of sec= options: */ 1231 if (exp->ex_nflavors == 0) { 1232 if (rqstp->rq_flavor == RPC_AUTH_NULL || 1233 rqstp->rq_flavor == RPC_AUTH_UNIX) 1234 return 0; 1235 } 1236 return nfserr_wrongsec; 1237 } 1238 1239 /* 1240 * Uses rq_client and rq_gssclient to find an export; uses rq_client (an 1241 * auth_unix client) if it's available and has secinfo information; 1242 * otherwise, will try to use rq_gssclient. 1243 * 1244 * Called from functions that handle requests; functions that do work on 1245 * behalf of mountd are passed a single client name to use, and should 1246 * use exp_get_by_name() or exp_find(). 1247 */ 1248 struct svc_export * 1249 rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path) 1250 { 1251 struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); 1252 1253 if (rqstp->rq_client == NULL) 1254 goto gss; 1255 1256 /* First try the auth_unix client: */ 1257 exp = exp_get_by_name(rqstp->rq_client, path, &rqstp->rq_chandle); 1258 if (PTR_ERR(exp) == -ENOENT) 1259 goto gss; 1260 if (IS_ERR(exp)) 1261 return exp; 1262 /* If it has secinfo, assume there are no gss/... clients */ 1263 if (exp->ex_nflavors > 0) 1264 return exp; 1265 gss: 1266 /* Otherwise, try falling back on gss client */ 1267 if (rqstp->rq_gssclient == NULL) 1268 return exp; 1269 gssexp = exp_get_by_name(rqstp->rq_gssclient, path, &rqstp->rq_chandle); 1270 if (PTR_ERR(gssexp) == -ENOENT) 1271 return exp; 1272 if (!IS_ERR(exp)) 1273 exp_put(exp); 1274 return gssexp; 1275 } 1276 1277 struct svc_export * 1278 rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) 1279 { 1280 struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); 1281 1282 if (rqstp->rq_client == NULL) 1283 goto gss; 1284 1285 /* First try the auth_unix client: */ 1286 exp = exp_find(rqstp->rq_client, fsid_type, fsidv, &rqstp->rq_chandle); 1287 if (PTR_ERR(exp) == -ENOENT) 1288 goto gss; 1289 if (IS_ERR(exp)) 1290 return exp; 1291 /* If it has secinfo, assume there are no gss/... clients */ 1292 if (exp->ex_nflavors > 0) 1293 return exp; 1294 gss: 1295 /* Otherwise, try falling back on gss client */ 1296 if (rqstp->rq_gssclient == NULL) 1297 return exp; 1298 gssexp = exp_find(rqstp->rq_gssclient, fsid_type, fsidv, 1299 &rqstp->rq_chandle); 1300 if (PTR_ERR(gssexp) == -ENOENT) 1301 return exp; 1302 if (!IS_ERR(exp)) 1303 exp_put(exp); 1304 return gssexp; 1305 } 1306 1307 struct svc_export * 1308 rqst_exp_parent(struct svc_rqst *rqstp, struct path *path) 1309 { 1310 struct dentry *saved = dget(path->dentry); 1311 struct svc_export *exp = rqst_exp_get_by_name(rqstp, path); 1312 1313 while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) { 1314 struct dentry *parent = dget_parent(path->dentry); 1315 dput(path->dentry); 1316 path->dentry = parent; 1317 exp = rqst_exp_get_by_name(rqstp, path); 1318 } 1319 dput(path->dentry); 1320 path->dentry = saved; 1321 return exp; 1322 } 1323 1324 static struct svc_export *find_fsidzero_export(struct svc_rqst *rqstp) 1325 { 1326 u32 fsidv[2]; 1327 1328 mk_fsid(FSID_NUM, fsidv, 0, 0, 0, NULL); 1329 1330 return rqst_exp_find(rqstp, FSID_NUM, fsidv); 1331 } 1332 1333 /* 1334 * Called when we need the filehandle for the root of the pseudofs, 1335 * for a given NFSv4 client. The root is defined to be the 1336 * export point with fsid==0 1337 */ 1338 __be32 1339 exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp) 1340 { 1341 struct svc_export *exp; 1342 __be32 rv; 1343 1344 exp = find_fsidzero_export(rqstp); 1345 if (IS_ERR(exp)) 1346 return nfserrno(PTR_ERR(exp)); 1347 rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL); 1348 if (rv) 1349 goto out; 1350 rv = check_nfsd_access(exp, rqstp); 1351 if (rv) 1352 fh_put(fhp); 1353 out: 1354 exp_put(exp); 1355 return rv; 1356 } 1357 1358 /* Iterator */ 1359 1360 static void *e_start(struct seq_file *m, loff_t *pos) 1361 __acquires(svc_export_cache.hash_lock) 1362 { 1363 loff_t n = *pos; 1364 unsigned hash, export; 1365 struct cache_head *ch; 1366 1367 exp_readlock(); 1368 read_lock(&svc_export_cache.hash_lock); 1369 if (!n--) 1370 return SEQ_START_TOKEN; 1371 hash = n >> 32; 1372 export = n & ((1LL<<32) - 1); 1373 1374 1375 for (ch=export_table[hash]; ch; ch=ch->next) 1376 if (!export--) 1377 return ch; 1378 n &= ~((1LL<<32) - 1); 1379 do { 1380 hash++; 1381 n += 1LL<<32; 1382 } while(hash < EXPORT_HASHMAX && export_table[hash]==NULL); 1383 if (hash >= EXPORT_HASHMAX) 1384 return NULL; 1385 *pos = n+1; 1386 return export_table[hash]; 1387 } 1388 1389 static void *e_next(struct seq_file *m, void *p, loff_t *pos) 1390 { 1391 struct cache_head *ch = p; 1392 int hash = (*pos >> 32); 1393 1394 if (p == SEQ_START_TOKEN) 1395 hash = 0; 1396 else if (ch->next == NULL) { 1397 hash++; 1398 *pos += 1LL<<32; 1399 } else { 1400 ++*pos; 1401 return ch->next; 1402 } 1403 *pos &= ~((1LL<<32) - 1); 1404 while (hash < EXPORT_HASHMAX && export_table[hash] == NULL) { 1405 hash++; 1406 *pos += 1LL<<32; 1407 } 1408 if (hash >= EXPORT_HASHMAX) 1409 return NULL; 1410 ++*pos; 1411 return export_table[hash]; 1412 } 1413 1414 static void e_stop(struct seq_file *m, void *p) 1415 __releases(svc_export_cache.hash_lock) 1416 { 1417 read_unlock(&svc_export_cache.hash_lock); 1418 exp_readunlock(); 1419 } 1420 1421 static struct flags { 1422 int flag; 1423 char *name[2]; 1424 } expflags[] = { 1425 { NFSEXP_READONLY, {"ro", "rw"}}, 1426 { NFSEXP_INSECURE_PORT, {"insecure", ""}}, 1427 { NFSEXP_ROOTSQUASH, {"root_squash", "no_root_squash"}}, 1428 { NFSEXP_ALLSQUASH, {"all_squash", ""}}, 1429 { NFSEXP_ASYNC, {"async", "sync"}}, 1430 { NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}}, 1431 { NFSEXP_NOHIDE, {"nohide", ""}}, 1432 { NFSEXP_CROSSMOUNT, {"crossmnt", ""}}, 1433 { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}}, 1434 { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}}, 1435 { NFSEXP_V4ROOT, {"v4root", ""}}, 1436 #ifdef MSNFS 1437 { NFSEXP_MSNFS, {"msnfs", ""}}, 1438 #endif 1439 { 0, {"", ""}} 1440 }; 1441 1442 static void show_expflags(struct seq_file *m, int flags, int mask) 1443 { 1444 struct flags *flg; 1445 int state, first = 0; 1446 1447 for (flg = expflags; flg->flag; flg++) { 1448 if (flg->flag & ~mask) 1449 continue; 1450 state = (flg->flag & flags) ? 0 : 1; 1451 if (*flg->name[state]) 1452 seq_printf(m, "%s%s", first++?",":"", flg->name[state]); 1453 } 1454 } 1455 1456 static void show_secinfo_flags(struct seq_file *m, int flags) 1457 { 1458 seq_printf(m, ","); 1459 show_expflags(m, flags, NFSEXP_SECINFO_FLAGS); 1460 } 1461 1462 static void show_secinfo(struct seq_file *m, struct svc_export *exp) 1463 { 1464 struct exp_flavor_info *f; 1465 struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors; 1466 int lastflags = 0, first = 0; 1467 1468 if (exp->ex_nflavors == 0) 1469 return; 1470 for (f = exp->ex_flavors; f < end; f++) { 1471 if (first || f->flags != lastflags) { 1472 if (!first) 1473 show_secinfo_flags(m, lastflags); 1474 seq_printf(m, ",sec=%d", f->pseudoflavor); 1475 lastflags = f->flags; 1476 } else { 1477 seq_printf(m, ":%d", f->pseudoflavor); 1478 } 1479 } 1480 show_secinfo_flags(m, lastflags); 1481 } 1482 1483 static void exp_flags(struct seq_file *m, int flag, int fsid, 1484 uid_t anonu, uid_t anong, struct nfsd4_fs_locations *fsloc) 1485 { 1486 show_expflags(m, flag, NFSEXP_ALLFLAGS); 1487 if (flag & NFSEXP_FSID) 1488 seq_printf(m, ",fsid=%d", fsid); 1489 if (anonu != (uid_t)-2 && anonu != (0x10000-2)) 1490 seq_printf(m, ",anonuid=%u", anonu); 1491 if (anong != (gid_t)-2 && anong != (0x10000-2)) 1492 seq_printf(m, ",anongid=%u", anong); 1493 if (fsloc && fsloc->locations_count > 0) { 1494 char *loctype = (fsloc->migrated) ? "refer" : "replicas"; 1495 int i; 1496 1497 seq_printf(m, ",%s=", loctype); 1498 seq_escape(m, fsloc->locations[0].path, ",;@ \t\n\\"); 1499 seq_putc(m, '@'); 1500 seq_escape(m, fsloc->locations[0].hosts, ",;@ \t\n\\"); 1501 for (i = 1; i < fsloc->locations_count; i++) { 1502 seq_putc(m, ';'); 1503 seq_escape(m, fsloc->locations[i].path, ",;@ \t\n\\"); 1504 seq_putc(m, '@'); 1505 seq_escape(m, fsloc->locations[i].hosts, ",;@ \t\n\\"); 1506 } 1507 } 1508 } 1509 1510 static int e_show(struct seq_file *m, void *p) 1511 { 1512 struct cache_head *cp = p; 1513 struct svc_export *exp = container_of(cp, struct svc_export, h); 1514 1515 if (p == SEQ_START_TOKEN) { 1516 seq_puts(m, "# Version 1.1\n"); 1517 seq_puts(m, "# Path Client(Flags) # IPs\n"); 1518 return 0; 1519 } 1520 1521 cache_get(&exp->h); 1522 if (cache_check(&svc_export_cache, &exp->h, NULL)) 1523 return 0; 1524 cache_put(&exp->h, &svc_export_cache); 1525 return svc_export_show(m, &svc_export_cache, cp); 1526 } 1527 1528 const struct seq_operations nfs_exports_op = { 1529 .start = e_start, 1530 .next = e_next, 1531 .stop = e_stop, 1532 .show = e_show, 1533 }; 1534 1535 /* 1536 * Add or modify a client. 1537 * Change requests may involve the list of host addresses. The list of 1538 * exports and possibly existing uid maps are left untouched. 1539 */ 1540 int 1541 exp_addclient(struct nfsctl_client *ncp) 1542 { 1543 struct auth_domain *dom; 1544 int i, err; 1545 struct in6_addr addr6; 1546 1547 /* First, consistency check. */ 1548 err = -EINVAL; 1549 if (! exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX)) 1550 goto out; 1551 if (ncp->cl_naddr > NFSCLNT_ADDRMAX) 1552 goto out; 1553 1554 /* Lock the hashtable */ 1555 exp_writelock(); 1556 1557 dom = unix_domain_find(ncp->cl_ident); 1558 1559 err = -ENOMEM; 1560 if (!dom) 1561 goto out_unlock; 1562 1563 /* Insert client into hashtable. */ 1564 for (i = 0; i < ncp->cl_naddr; i++) { 1565 ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &addr6); 1566 auth_unix_add_addr(&addr6, dom); 1567 } 1568 auth_unix_forget_old(dom); 1569 auth_domain_put(dom); 1570 1571 err = 0; 1572 1573 out_unlock: 1574 exp_writeunlock(); 1575 out: 1576 return err; 1577 } 1578 1579 /* 1580 * Delete a client given an identifier. 1581 */ 1582 int 1583 exp_delclient(struct nfsctl_client *ncp) 1584 { 1585 int err; 1586 struct auth_domain *dom; 1587 1588 err = -EINVAL; 1589 if (!exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX)) 1590 goto out; 1591 1592 /* Lock the hashtable */ 1593 exp_writelock(); 1594 1595 dom = auth_domain_find(ncp->cl_ident); 1596 /* just make sure that no addresses work 1597 * and that it will expire soon 1598 */ 1599 if (dom) { 1600 err = auth_unix_forget_old(dom); 1601 auth_domain_put(dom); 1602 } 1603 1604 exp_writeunlock(); 1605 out: 1606 return err; 1607 } 1608 1609 /* 1610 * Verify that string is non-empty and does not exceed max length. 1611 */ 1612 static int 1613 exp_verify_string(char *cp, int max) 1614 { 1615 int i; 1616 1617 for (i = 0; i < max; i++) 1618 if (!cp[i]) 1619 return i; 1620 cp[i] = 0; 1621 printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp); 1622 return 0; 1623 } 1624 1625 /* 1626 * Initialize the exports module. 1627 */ 1628 int 1629 nfsd_export_init(void) 1630 { 1631 int rv; 1632 dprintk("nfsd: initializing export module.\n"); 1633 1634 rv = cache_register(&svc_export_cache); 1635 if (rv) 1636 return rv; 1637 rv = cache_register(&svc_expkey_cache); 1638 if (rv) 1639 cache_unregister(&svc_export_cache); 1640 return rv; 1641 1642 } 1643 1644 /* 1645 * Flush exports table - called when last nfsd thread is killed 1646 */ 1647 void 1648 nfsd_export_flush(void) 1649 { 1650 exp_writelock(); 1651 cache_purge(&svc_expkey_cache); 1652 cache_purge(&svc_export_cache); 1653 exp_writeunlock(); 1654 } 1655 1656 /* 1657 * Shutdown the exports module. 1658 */ 1659 void 1660 nfsd_export_shutdown(void) 1661 { 1662 1663 dprintk("nfsd: shutting down export module.\n"); 1664 1665 exp_writelock(); 1666 1667 cache_unregister(&svc_expkey_cache); 1668 cache_unregister(&svc_export_cache); 1669 svcauth_unix_purge(); 1670 1671 exp_writeunlock(); 1672 dprintk("nfsd: export shutdown complete.\n"); 1673 } 1674