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