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