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/sched.h> 20 #include <linux/stat.h> 21 #include <linux/in.h> 22 #include <linux/seq_file.h> 23 #include <linux/syscalls.h> 24 #include <linux/rwsem.h> 25 #include <linux/dcache.h> 26 #include <linux/namei.h> 27 #include <linux/mount.h> 28 #include <linux/hash.h> 29 #include <linux/module.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 37 #define NFSDDBG_FACILITY NFSDDBG_EXPORT 38 #define NFSD_PARANOIA 1 39 40 typedef struct auth_domain svc_client; 41 typedef struct svc_export svc_export; 42 43 static void exp_do_unexport(svc_export *unexp); 44 static int exp_verify_string(char *cp, int max); 45 46 /* 47 * We have two caches. 48 * One maps client+vfsmnt+dentry to export options - the export map 49 * The other maps client+filehandle-fragment to export options. - the expkey map 50 * 51 * The export options are actually stored in the first map, and the 52 * second map contains a reference to the entry in the first map. 53 */ 54 55 #define EXPKEY_HASHBITS 8 56 #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) 57 #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) 58 static struct cache_head *expkey_table[EXPKEY_HASHMAX]; 59 60 static void expkey_put(struct kref *ref) 61 { 62 struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref); 63 64 if (test_bit(CACHE_VALID, &key->h.flags) && 65 !test_bit(CACHE_NEGATIVE, &key->h.flags)) { 66 dput(key->ek_dentry); 67 mntput(key->ek_mnt); 68 } 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 (fsidtype > 2) 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_mnt = nd.mnt; 172 key.ek_dentry = nd.dentry; 173 174 ek = svc_expkey_update(&key, ek); 175 if (ek) 176 cache_put(&ek->h, &svc_expkey_cache); 177 else 178 err = -ENOMEM; 179 path_release(&nd); 180 } 181 cache_flush(); 182 out: 183 if (dom) 184 auth_domain_put(dom); 185 kfree(buf); 186 return err; 187 } 188 189 static int expkey_show(struct seq_file *m, 190 struct cache_detail *cd, 191 struct cache_head *h) 192 { 193 struct svc_expkey *ek ; 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%08x", ek->ek_client->name, 201 ek->ek_fsidtype, ek->ek_fsid[0]); 202 if (ek->ek_fsidtype != 1) 203 seq_printf(m, "%08x", ek->ek_fsid[1]); 204 if (ek->ek_fsidtype == 2) 205 seq_printf(m, "%08x", ek->ek_fsid[2]); 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 new->ek_fsid[0] = item->ek_fsid[0]; 237 new->ek_fsid[1] = item->ek_fsid[1]; 238 new->ek_fsid[2] = item->ek_fsid[2]; 239 } 240 241 static inline void expkey_update(struct cache_head *cnew, 242 struct cache_head *citem) 243 { 244 struct svc_expkey *new = container_of(cnew, struct svc_expkey, h); 245 struct svc_expkey *item = container_of(citem, struct svc_expkey, h); 246 247 new->ek_mnt = mntget(item->ek_mnt); 248 new->ek_dentry = dget(item->ek_dentry); 249 } 250 251 static struct cache_head *expkey_alloc(void) 252 { 253 struct svc_expkey *i = kmalloc(sizeof(*i), GFP_KERNEL); 254 if (i) 255 return &i->h; 256 else 257 return NULL; 258 } 259 260 static struct cache_detail svc_expkey_cache = { 261 .owner = THIS_MODULE, 262 .hash_size = EXPKEY_HASHMAX, 263 .hash_table = expkey_table, 264 .name = "nfsd.fh", 265 .cache_put = expkey_put, 266 .cache_request = expkey_request, 267 .cache_parse = expkey_parse, 268 .cache_show = expkey_show, 269 .match = expkey_match, 270 .init = expkey_init, 271 .update = expkey_update, 272 .alloc = expkey_alloc, 273 }; 274 275 static struct svc_expkey * 276 svc_expkey_lookup(struct svc_expkey *item) 277 { 278 struct cache_head *ch; 279 int hash = item->ek_fsidtype; 280 char * cp = (char*)item->ek_fsid; 281 int len = key_len(item->ek_fsidtype); 282 283 hash ^= hash_mem(cp, len, EXPKEY_HASHBITS); 284 hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS); 285 hash &= EXPKEY_HASHMASK; 286 287 ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h, 288 hash); 289 if (ch) 290 return container_of(ch, struct svc_expkey, h); 291 else 292 return NULL; 293 } 294 295 static struct svc_expkey * 296 svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old) 297 { 298 struct cache_head *ch; 299 int hash = new->ek_fsidtype; 300 char * cp = (char*)new->ek_fsid; 301 int len = key_len(new->ek_fsidtype); 302 303 hash ^= hash_mem(cp, len, EXPKEY_HASHBITS); 304 hash ^= hash_ptr(new->ek_client, EXPKEY_HASHBITS); 305 hash &= EXPKEY_HASHMASK; 306 307 ch = sunrpc_cache_update(&svc_expkey_cache, &new->h, 308 &old->h, hash); 309 if (ch) 310 return container_of(ch, struct svc_expkey, h); 311 else 312 return NULL; 313 } 314 315 316 #define EXPORT_HASHBITS 8 317 #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) 318 #define EXPORT_HASHMASK (EXPORT_HASHMAX -1) 319 320 static struct cache_head *export_table[EXPORT_HASHMAX]; 321 322 static void svc_export_put(struct kref *ref) 323 { 324 struct svc_export *exp = container_of(ref, struct svc_export, h.ref); 325 dput(exp->ex_dentry); 326 mntput(exp->ex_mnt); 327 auth_domain_put(exp->ex_client); 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_dentry, exp->ex_mnt, *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 struct svc_export *svc_export_update(struct svc_export *new, 351 struct svc_export *old); 352 static struct svc_export *svc_export_lookup(struct svc_export *); 353 354 static int check_export(struct inode *inode, int flags) 355 { 356 357 /* We currently export only dirs and regular files. 358 * This is what umountd does. 359 */ 360 if (!S_ISDIR(inode->i_mode) && 361 !S_ISREG(inode->i_mode)) 362 return -ENOTDIR; 363 364 /* There are two requirements on a filesystem to be exportable. 365 * 1: We must be able to identify the filesystem from a number. 366 * either a device number (so FS_REQUIRES_DEV needed) 367 * or an FSID number (so NFSEXP_FSID needed). 368 * 2: We must be able to find an inode from a filehandle. 369 * This means that s_export_op must be set. 370 */ 371 if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) && 372 !(flags & NFSEXP_FSID)) { 373 dprintk("exp_export: export of non-dev fs without fsid"); 374 return -EINVAL; 375 } 376 if (!inode->i_sb->s_export_op) { 377 dprintk("exp_export: export of invalid fs type.\n"); 378 return -EINVAL; 379 } 380 381 /* Ok, we can export it */; 382 if (!inode->i_sb->s_export_op->find_exported_dentry) 383 inode->i_sb->s_export_op->find_exported_dentry = 384 find_exported_dentry; 385 return 0; 386 387 } 388 389 static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen) 390 { 391 /* client path expiry [flags anonuid anongid fsid] */ 392 char *buf; 393 int len; 394 int err; 395 struct auth_domain *dom = NULL; 396 struct nameidata nd; 397 struct svc_export exp, *expp; 398 int an_int; 399 400 nd.dentry = NULL; 401 402 if (mesg[mlen-1] != '\n') 403 return -EINVAL; 404 mesg[mlen-1] = 0; 405 406 buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 407 err = -ENOMEM; 408 if (!buf) goto out; 409 410 /* client */ 411 len = qword_get(&mesg, buf, PAGE_SIZE); 412 err = -EINVAL; 413 if (len <= 0) goto out; 414 415 err = -ENOENT; 416 dom = auth_domain_find(buf); 417 if (!dom) 418 goto out; 419 420 /* path */ 421 err = -EINVAL; 422 if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0) 423 goto out; 424 err = path_lookup(buf, 0, &nd); 425 if (err) goto out; 426 427 exp.h.flags = 0; 428 exp.ex_client = dom; 429 exp.ex_mnt = nd.mnt; 430 exp.ex_dentry = nd.dentry; 431 432 /* expiry */ 433 err = -EINVAL; 434 exp.h.expiry_time = get_expiry(&mesg); 435 if (exp.h.expiry_time == 0) 436 goto out; 437 438 /* flags */ 439 err = get_int(&mesg, &an_int); 440 if (err == -ENOENT) 441 set_bit(CACHE_NEGATIVE, &exp.h.flags); 442 else { 443 if (err || an_int < 0) goto out; 444 exp.ex_flags= an_int; 445 446 /* anon uid */ 447 err = get_int(&mesg, &an_int); 448 if (err) goto out; 449 exp.ex_anon_uid= an_int; 450 451 /* anon gid */ 452 err = get_int(&mesg, &an_int); 453 if (err) goto out; 454 exp.ex_anon_gid= an_int; 455 456 /* fsid */ 457 err = get_int(&mesg, &an_int); 458 if (err) goto out; 459 exp.ex_fsid = an_int; 460 461 err = check_export(nd.dentry->d_inode, exp.ex_flags); 462 if (err) goto out; 463 } 464 465 expp = svc_export_lookup(&exp); 466 if (expp) 467 expp = svc_export_update(&exp, expp); 468 else 469 err = -ENOMEM; 470 cache_flush(); 471 if (expp == NULL) 472 err = -ENOMEM; 473 else 474 exp_put(expp); 475 out: 476 if (nd.dentry) 477 path_release(&nd); 478 if (dom) 479 auth_domain_put(dom); 480 kfree(buf); 481 return err; 482 } 483 484 static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong); 485 486 static int svc_export_show(struct seq_file *m, 487 struct cache_detail *cd, 488 struct cache_head *h) 489 { 490 struct svc_export *exp ; 491 492 if (h ==NULL) { 493 seq_puts(m, "#path domain(flags)\n"); 494 return 0; 495 } 496 exp = container_of(h, struct svc_export, h); 497 seq_path(m, exp->ex_mnt, exp->ex_dentry, " \t\n\\"); 498 seq_putc(m, '\t'); 499 seq_escape(m, exp->ex_client->name, " \t\n\\"); 500 seq_putc(m, '('); 501 if (test_bit(CACHE_VALID, &h->flags) && 502 !test_bit(CACHE_NEGATIVE, &h->flags)) 503 exp_flags(m, exp->ex_flags, exp->ex_fsid, 504 exp->ex_anon_uid, exp->ex_anon_gid); 505 seq_puts(m, ")\n"); 506 return 0; 507 } 508 static int svc_export_match(struct cache_head *a, struct cache_head *b) 509 { 510 struct svc_export *orig = container_of(a, struct svc_export, h); 511 struct svc_export *new = container_of(b, struct svc_export, h); 512 return orig->ex_client == new->ex_client && 513 orig->ex_dentry == new->ex_dentry && 514 orig->ex_mnt == new->ex_mnt; 515 } 516 517 static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) 518 { 519 struct svc_export *new = container_of(cnew, struct svc_export, h); 520 struct svc_export *item = container_of(citem, struct svc_export, h); 521 522 kref_get(&item->ex_client->ref); 523 new->ex_client = item->ex_client; 524 new->ex_dentry = dget(item->ex_dentry); 525 new->ex_mnt = mntget(item->ex_mnt); 526 } 527 528 static void export_update(struct cache_head *cnew, struct cache_head *citem) 529 { 530 struct svc_export *new = container_of(cnew, struct svc_export, h); 531 struct svc_export *item = container_of(citem, struct svc_export, h); 532 533 new->ex_flags = item->ex_flags; 534 new->ex_anon_uid = item->ex_anon_uid; 535 new->ex_anon_gid = item->ex_anon_gid; 536 new->ex_fsid = item->ex_fsid; 537 } 538 539 static struct cache_head *svc_export_alloc(void) 540 { 541 struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL); 542 if (i) 543 return &i->h; 544 else 545 return NULL; 546 } 547 548 struct cache_detail svc_export_cache = { 549 .owner = THIS_MODULE, 550 .hash_size = EXPORT_HASHMAX, 551 .hash_table = export_table, 552 .name = "nfsd.export", 553 .cache_put = svc_export_put, 554 .cache_request = svc_export_request, 555 .cache_parse = svc_export_parse, 556 .cache_show = svc_export_show, 557 .match = svc_export_match, 558 .init = svc_export_init, 559 .update = export_update, 560 .alloc = svc_export_alloc, 561 }; 562 563 static struct svc_export * 564 svc_export_lookup(struct svc_export *exp) 565 { 566 struct cache_head *ch; 567 int hash; 568 hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS); 569 hash ^= hash_ptr(exp->ex_dentry, EXPORT_HASHBITS); 570 hash ^= hash_ptr(exp->ex_mnt, EXPORT_HASHBITS); 571 572 ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h, 573 hash); 574 if (ch) 575 return container_of(ch, struct svc_export, h); 576 else 577 return NULL; 578 } 579 580 static struct svc_export * 581 svc_export_update(struct svc_export *new, struct svc_export *old) 582 { 583 struct cache_head *ch; 584 int hash; 585 hash = hash_ptr(old->ex_client, EXPORT_HASHBITS); 586 hash ^= hash_ptr(old->ex_dentry, EXPORT_HASHBITS); 587 hash ^= hash_ptr(old->ex_mnt, EXPORT_HASHBITS); 588 589 ch = sunrpc_cache_update(&svc_export_cache, &new->h, 590 &old->h, 591 hash); 592 if (ch) 593 return container_of(ch, struct svc_export, h); 594 else 595 return NULL; 596 } 597 598 599 static struct svc_expkey * 600 exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) 601 { 602 struct svc_expkey key, *ek; 603 int err; 604 605 if (!clp) 606 return NULL; 607 608 key.ek_client = clp; 609 key.ek_fsidtype = fsid_type; 610 memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); 611 612 ek = svc_expkey_lookup(&key); 613 if (ek != NULL) 614 if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp))) 615 ek = ERR_PTR(err); 616 return ek; 617 } 618 619 static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv, 620 struct svc_export *exp) 621 { 622 struct svc_expkey key, *ek; 623 624 key.ek_client = clp; 625 key.ek_fsidtype = fsid_type; 626 memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); 627 key.ek_mnt = exp->ex_mnt; 628 key.ek_dentry = exp->ex_dentry; 629 key.h.expiry_time = NEVER; 630 key.h.flags = 0; 631 632 ek = svc_expkey_lookup(&key); 633 if (ek) 634 ek = svc_expkey_update(&key,ek); 635 if (ek) { 636 cache_put(&ek->h, &svc_expkey_cache); 637 return 0; 638 } 639 return -ENOMEM; 640 } 641 642 /* 643 * Find the client's export entry matching xdev/xino. 644 */ 645 static inline struct svc_expkey * 646 exp_get_key(svc_client *clp, dev_t dev, ino_t ino) 647 { 648 u32 fsidv[3]; 649 650 if (old_valid_dev(dev)) { 651 mk_fsid_v0(fsidv, dev, ino); 652 return exp_find_key(clp, 0, fsidv, NULL); 653 } 654 mk_fsid_v3(fsidv, dev, ino); 655 return exp_find_key(clp, 3, fsidv, NULL); 656 } 657 658 /* 659 * Find the client's export entry matching fsid 660 */ 661 static inline struct svc_expkey * 662 exp_get_fsid_key(svc_client *clp, int fsid) 663 { 664 u32 fsidv[2]; 665 666 mk_fsid_v1(fsidv, fsid); 667 668 return exp_find_key(clp, 1, fsidv, NULL); 669 } 670 671 svc_export * 672 exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry, 673 struct cache_req *reqp) 674 { 675 struct svc_export *exp, key; 676 677 if (!clp) 678 return NULL; 679 680 key.ex_client = clp; 681 key.ex_mnt = mnt; 682 key.ex_dentry = dentry; 683 684 exp = svc_export_lookup(&key); 685 if (exp != NULL) 686 switch (cache_check(&svc_export_cache, &exp->h, reqp)) { 687 case 0: break; 688 case -EAGAIN: 689 exp = ERR_PTR(-EAGAIN); 690 break; 691 default: 692 exp = NULL; 693 } 694 695 return exp; 696 } 697 698 /* 699 * Find the export entry for a given dentry. 700 */ 701 struct svc_export * 702 exp_parent(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry, 703 struct cache_req *reqp) 704 { 705 svc_export *exp; 706 707 dget(dentry); 708 exp = exp_get_by_name(clp, mnt, dentry, reqp); 709 710 while (exp == NULL && !IS_ROOT(dentry)) { 711 struct dentry *parent; 712 713 parent = dget_parent(dentry); 714 dput(dentry); 715 dentry = parent; 716 exp = exp_get_by_name(clp, mnt, dentry, reqp); 717 } 718 dput(dentry); 719 return exp; 720 } 721 722 /* 723 * Hashtable locking. Write locks are placed only by user processes 724 * wanting to modify export information. 725 * Write locking only done in this file. Read locking 726 * needed externally. 727 */ 728 729 static DECLARE_RWSEM(hash_sem); 730 731 void 732 exp_readlock(void) 733 { 734 down_read(&hash_sem); 735 } 736 737 static inline void 738 exp_writelock(void) 739 { 740 down_write(&hash_sem); 741 } 742 743 void 744 exp_readunlock(void) 745 { 746 up_read(&hash_sem); 747 } 748 749 static inline void 750 exp_writeunlock(void) 751 { 752 up_write(&hash_sem); 753 } 754 755 static void exp_fsid_unhash(struct svc_export *exp) 756 { 757 struct svc_expkey *ek; 758 759 if ((exp->ex_flags & NFSEXP_FSID) == 0) 760 return; 761 762 ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); 763 if (ek && !IS_ERR(ek)) { 764 ek->h.expiry_time = get_seconds()-1; 765 cache_put(&ek->h, &svc_expkey_cache); 766 } 767 svc_expkey_cache.nextcheck = get_seconds(); 768 } 769 770 static int exp_fsid_hash(svc_client *clp, struct svc_export *exp) 771 { 772 u32 fsid[2]; 773 774 if ((exp->ex_flags & NFSEXP_FSID) == 0) 775 return 0; 776 777 mk_fsid_v1(fsid, exp->ex_fsid); 778 return exp_set_key(clp, 1, fsid, exp); 779 } 780 781 static int exp_hash(struct auth_domain *clp, struct svc_export *exp) 782 { 783 u32 fsid[2]; 784 struct inode *inode = exp->ex_dentry->d_inode; 785 dev_t dev = inode->i_sb->s_dev; 786 787 if (old_valid_dev(dev)) { 788 mk_fsid_v0(fsid, dev, inode->i_ino); 789 return exp_set_key(clp, 0, fsid, exp); 790 } 791 mk_fsid_v3(fsid, dev, inode->i_ino); 792 return exp_set_key(clp, 3, fsid, exp); 793 } 794 795 static void exp_unhash(struct svc_export *exp) 796 { 797 struct svc_expkey *ek; 798 struct inode *inode = exp->ex_dentry->d_inode; 799 800 ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); 801 if (ek && !IS_ERR(ek)) { 802 ek->h.expiry_time = get_seconds()-1; 803 cache_put(&ek->h, &svc_expkey_cache); 804 } 805 svc_expkey_cache.nextcheck = get_seconds(); 806 } 807 808 /* 809 * Export a file system. 810 */ 811 int 812 exp_export(struct nfsctl_export *nxp) 813 { 814 svc_client *clp; 815 struct svc_export *exp = NULL; 816 struct svc_export new; 817 struct svc_expkey *fsid_key = NULL; 818 struct nameidata nd; 819 int err; 820 821 /* Consistency check */ 822 err = -EINVAL; 823 if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) || 824 !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX)) 825 goto out; 826 827 dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n", 828 nxp->ex_client, nxp->ex_path, 829 (unsigned)nxp->ex_dev, (long)nxp->ex_ino, 830 nxp->ex_flags); 831 832 /* Try to lock the export table for update */ 833 exp_writelock(); 834 835 /* Look up client info */ 836 if (!(clp = auth_domain_find(nxp->ex_client))) 837 goto out_unlock; 838 839 840 /* Look up the dentry */ 841 err = path_lookup(nxp->ex_path, 0, &nd); 842 if (err) 843 goto out_unlock; 844 err = -EINVAL; 845 846 exp = exp_get_by_name(clp, nd.mnt, nd.dentry, NULL); 847 848 /* must make sure there won't be an ex_fsid clash */ 849 if ((nxp->ex_flags & NFSEXP_FSID) && 850 (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && 851 !IS_ERR(fsid_key) && 852 fsid_key->ek_mnt && 853 (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) ) 854 goto finish; 855 856 if (exp) { 857 /* just a flags/id/fsid update */ 858 859 exp_fsid_unhash(exp); 860 exp->ex_flags = nxp->ex_flags; 861 exp->ex_anon_uid = nxp->ex_anon_uid; 862 exp->ex_anon_gid = nxp->ex_anon_gid; 863 exp->ex_fsid = nxp->ex_dev; 864 865 err = exp_fsid_hash(clp, exp); 866 goto finish; 867 } 868 869 err = check_export(nd.dentry->d_inode, nxp->ex_flags); 870 if (err) goto finish; 871 872 err = -ENOMEM; 873 874 dprintk("nfsd: creating export entry %p for client %p\n", exp, clp); 875 876 new.h.expiry_time = NEVER; 877 new.h.flags = 0; 878 new.ex_client = clp; 879 new.ex_mnt = nd.mnt; 880 new.ex_dentry = nd.dentry; 881 new.ex_flags = nxp->ex_flags; 882 new.ex_anon_uid = nxp->ex_anon_uid; 883 new.ex_anon_gid = nxp->ex_anon_gid; 884 new.ex_fsid = nxp->ex_dev; 885 886 exp = svc_export_lookup(&new); 887 if (exp) 888 exp = svc_export_update(&new, exp); 889 890 if (!exp) 891 goto finish; 892 893 if (exp_hash(clp, exp) || 894 exp_fsid_hash(clp, exp)) { 895 /* failed to create at least one index */ 896 exp_do_unexport(exp); 897 cache_flush(); 898 err = -ENOMEM; 899 } 900 901 finish: 902 if (exp) 903 exp_put(exp); 904 if (fsid_key && !IS_ERR(fsid_key)) 905 cache_put(&fsid_key->h, &svc_expkey_cache); 906 if (clp) 907 auth_domain_put(clp); 908 path_release(&nd); 909 out_unlock: 910 exp_writeunlock(); 911 out: 912 return err; 913 } 914 915 /* 916 * Unexport a file system. The export entry has already 917 * been removed from the client's list of exported fs's. 918 */ 919 static void 920 exp_do_unexport(svc_export *unexp) 921 { 922 unexp->h.expiry_time = get_seconds()-1; 923 svc_export_cache.nextcheck = get_seconds(); 924 exp_unhash(unexp); 925 exp_fsid_unhash(unexp); 926 } 927 928 929 /* 930 * unexport syscall. 931 */ 932 int 933 exp_unexport(struct nfsctl_export *nxp) 934 { 935 struct auth_domain *dom; 936 svc_export *exp; 937 struct nameidata nd; 938 int err; 939 940 /* Consistency check */ 941 if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) || 942 !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX)) 943 return -EINVAL; 944 945 exp_writelock(); 946 947 err = -EINVAL; 948 dom = auth_domain_find(nxp->ex_client); 949 if (!dom) { 950 dprintk("nfsd: unexport couldn't find %s\n", nxp->ex_client); 951 goto out_unlock; 952 } 953 954 err = path_lookup(nxp->ex_path, 0, &nd); 955 if (err) 956 goto out_domain; 957 958 err = -EINVAL; 959 exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL); 960 path_release(&nd); 961 if (!exp) 962 goto out_domain; 963 964 exp_do_unexport(exp); 965 exp_put(exp); 966 err = 0; 967 968 out_domain: 969 auth_domain_put(dom); 970 cache_flush(); 971 out_unlock: 972 exp_writeunlock(); 973 return err; 974 } 975 976 /* 977 * Obtain the root fh on behalf of a client. 978 * This could be done in user space, but I feel that it adds some safety 979 * since its harder to fool a kernel module than a user space program. 980 */ 981 int 982 exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize) 983 { 984 struct svc_export *exp; 985 struct nameidata nd; 986 struct inode *inode; 987 struct svc_fh fh; 988 int err; 989 990 err = -EPERM; 991 /* NB: we probably ought to check that it's NUL-terminated */ 992 if (path_lookup(path, 0, &nd)) { 993 printk("nfsd: exp_rootfh path not found %s", path); 994 return err; 995 } 996 inode = nd.dentry->d_inode; 997 998 dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n", 999 path, nd.dentry, clp->name, 1000 inode->i_sb->s_id, inode->i_ino); 1001 exp = exp_parent(clp, nd.mnt, nd.dentry, NULL); 1002 if (!exp) { 1003 dprintk("nfsd: exp_rootfh export not found.\n"); 1004 goto out; 1005 } 1006 1007 /* 1008 * fh must be initialized before calling fh_compose 1009 */ 1010 fh_init(&fh, maxsize); 1011 if (fh_compose(&fh, exp, nd.dentry, NULL)) 1012 err = -EINVAL; 1013 else 1014 err = 0; 1015 memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh)); 1016 fh_put(&fh); 1017 exp_put(exp); 1018 out: 1019 path_release(&nd); 1020 return err; 1021 } 1022 1023 struct svc_export * 1024 exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, 1025 struct cache_req *reqp) 1026 { 1027 struct svc_export *exp; 1028 struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); 1029 if (!ek || IS_ERR(ek)) 1030 return ERR_PTR(PTR_ERR(ek)); 1031 1032 exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp); 1033 cache_put(&ek->h, &svc_expkey_cache); 1034 1035 if (!exp || IS_ERR(exp)) 1036 return ERR_PTR(PTR_ERR(exp)); 1037 return exp; 1038 } 1039 1040 1041 /* 1042 * Called when we need the filehandle for the root of the pseudofs, 1043 * for a given NFSv4 client. The root is defined to be the 1044 * export point with fsid==0 1045 */ 1046 int 1047 exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, 1048 struct cache_req *creq) 1049 { 1050 struct svc_expkey *fsid_key; 1051 struct svc_export *exp; 1052 int rv; 1053 u32 fsidv[2]; 1054 1055 mk_fsid_v1(fsidv, 0); 1056 1057 fsid_key = exp_find_key(clp, 1, fsidv, creq); 1058 if (IS_ERR(fsid_key) && PTR_ERR(fsid_key) == -EAGAIN) 1059 return nfserr_dropit; 1060 if (!fsid_key || IS_ERR(fsid_key)) 1061 return nfserr_perm; 1062 1063 exp = exp_get_by_name(clp, fsid_key->ek_mnt, fsid_key->ek_dentry, creq); 1064 if (exp == NULL) 1065 rv = nfserr_perm; 1066 else if (IS_ERR(exp)) 1067 rv = nfserrno(PTR_ERR(exp)); 1068 else 1069 rv = fh_compose(fhp, exp, 1070 fsid_key->ek_dentry, NULL); 1071 cache_put(&fsid_key->h, &svc_expkey_cache); 1072 return rv; 1073 } 1074 1075 /* Iterator */ 1076 1077 static void *e_start(struct seq_file *m, loff_t *pos) 1078 { 1079 loff_t n = *pos; 1080 unsigned hash, export; 1081 struct cache_head *ch; 1082 1083 exp_readlock(); 1084 read_lock(&svc_export_cache.hash_lock); 1085 if (!n--) 1086 return (void *)1; 1087 hash = n >> 32; 1088 export = n & ((1LL<<32) - 1); 1089 1090 1091 for (ch=export_table[hash]; ch; ch=ch->next) 1092 if (!export--) 1093 return ch; 1094 n &= ~((1LL<<32) - 1); 1095 do { 1096 hash++; 1097 n += 1LL<<32; 1098 } while(hash < EXPORT_HASHMAX && export_table[hash]==NULL); 1099 if (hash >= EXPORT_HASHMAX) 1100 return NULL; 1101 *pos = n+1; 1102 return export_table[hash]; 1103 } 1104 1105 static void *e_next(struct seq_file *m, void *p, loff_t *pos) 1106 { 1107 struct cache_head *ch = p; 1108 int hash = (*pos >> 32); 1109 1110 if (p == (void *)1) 1111 hash = 0; 1112 else if (ch->next == NULL) { 1113 hash++; 1114 *pos += 1LL<<32; 1115 } else { 1116 ++*pos; 1117 return ch->next; 1118 } 1119 *pos &= ~((1LL<<32) - 1); 1120 while (hash < EXPORT_HASHMAX && export_table[hash] == NULL) { 1121 hash++; 1122 *pos += 1LL<<32; 1123 } 1124 if (hash >= EXPORT_HASHMAX) 1125 return NULL; 1126 ++*pos; 1127 return export_table[hash]; 1128 } 1129 1130 static void e_stop(struct seq_file *m, void *p) 1131 { 1132 read_unlock(&svc_export_cache.hash_lock); 1133 exp_readunlock(); 1134 } 1135 1136 static struct flags { 1137 int flag; 1138 char *name[2]; 1139 } expflags[] = { 1140 { NFSEXP_READONLY, {"ro", "rw"}}, 1141 { NFSEXP_INSECURE_PORT, {"insecure", ""}}, 1142 { NFSEXP_ROOTSQUASH, {"root_squash", "no_root_squash"}}, 1143 { NFSEXP_ALLSQUASH, {"all_squash", ""}}, 1144 { NFSEXP_ASYNC, {"async", "sync"}}, 1145 { NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}}, 1146 { NFSEXP_NOHIDE, {"nohide", ""}}, 1147 { NFSEXP_CROSSMOUNT, {"crossmnt", ""}}, 1148 { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}}, 1149 { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}}, 1150 #ifdef MSNFS 1151 { NFSEXP_MSNFS, {"msnfs", ""}}, 1152 #endif 1153 { 0, {"", ""}} 1154 }; 1155 1156 static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong) 1157 { 1158 int first = 0; 1159 struct flags *flg; 1160 1161 for (flg = expflags; flg->flag; flg++) { 1162 int state = (flg->flag & flag)?0:1; 1163 if (*flg->name[state]) 1164 seq_printf(m, "%s%s", first++?",":"", flg->name[state]); 1165 } 1166 if (flag & NFSEXP_FSID) 1167 seq_printf(m, "%sfsid=%d", first++?",":"", fsid); 1168 if (anonu != (uid_t)-2 && anonu != (0x10000-2)) 1169 seq_printf(m, "%sanonuid=%d", first++?",":"", anonu); 1170 if (anong != (gid_t)-2 && anong != (0x10000-2)) 1171 seq_printf(m, "%sanongid=%d", first++?",":"", anong); 1172 } 1173 1174 static int e_show(struct seq_file *m, void *p) 1175 { 1176 struct cache_head *cp = p; 1177 struct svc_export *exp = container_of(cp, struct svc_export, h); 1178 svc_client *clp; 1179 1180 if (p == (void *)1) { 1181 seq_puts(m, "# Version 1.1\n"); 1182 seq_puts(m, "# Path Client(Flags) # IPs\n"); 1183 return 0; 1184 } 1185 1186 clp = exp->ex_client; 1187 cache_get(&exp->h); 1188 if (cache_check(&svc_export_cache, &exp->h, NULL)) 1189 return 0; 1190 cache_put(&exp->h, &svc_export_cache); 1191 return svc_export_show(m, &svc_export_cache, cp); 1192 } 1193 1194 struct seq_operations nfs_exports_op = { 1195 .start = e_start, 1196 .next = e_next, 1197 .stop = e_stop, 1198 .show = e_show, 1199 }; 1200 1201 /* 1202 * Add or modify a client. 1203 * Change requests may involve the list of host addresses. The list of 1204 * exports and possibly existing uid maps are left untouched. 1205 */ 1206 int 1207 exp_addclient(struct nfsctl_client *ncp) 1208 { 1209 struct auth_domain *dom; 1210 int i, err; 1211 1212 /* First, consistency check. */ 1213 err = -EINVAL; 1214 if (! exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX)) 1215 goto out; 1216 if (ncp->cl_naddr > NFSCLNT_ADDRMAX) 1217 goto out; 1218 1219 /* Lock the hashtable */ 1220 exp_writelock(); 1221 1222 dom = unix_domain_find(ncp->cl_ident); 1223 1224 err = -ENOMEM; 1225 if (!dom) 1226 goto out_unlock; 1227 1228 /* Insert client into hashtable. */ 1229 for (i = 0; i < ncp->cl_naddr; i++) 1230 auth_unix_add_addr(ncp->cl_addrlist[i], dom); 1231 1232 auth_unix_forget_old(dom); 1233 auth_domain_put(dom); 1234 1235 err = 0; 1236 1237 out_unlock: 1238 exp_writeunlock(); 1239 out: 1240 return err; 1241 } 1242 1243 /* 1244 * Delete a client given an identifier. 1245 */ 1246 int 1247 exp_delclient(struct nfsctl_client *ncp) 1248 { 1249 int err; 1250 struct auth_domain *dom; 1251 1252 err = -EINVAL; 1253 if (!exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX)) 1254 goto out; 1255 1256 /* Lock the hashtable */ 1257 exp_writelock(); 1258 1259 dom = auth_domain_find(ncp->cl_ident); 1260 /* just make sure that no addresses work 1261 * and that it will expire soon 1262 */ 1263 if (dom) { 1264 err = auth_unix_forget_old(dom); 1265 auth_domain_put(dom); 1266 } 1267 1268 exp_writeunlock(); 1269 out: 1270 return err; 1271 } 1272 1273 /* 1274 * Verify that string is non-empty and does not exceed max length. 1275 */ 1276 static int 1277 exp_verify_string(char *cp, int max) 1278 { 1279 int i; 1280 1281 for (i = 0; i < max; i++) 1282 if (!cp[i]) 1283 return i; 1284 cp[i] = 0; 1285 printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp); 1286 return 0; 1287 } 1288 1289 /* 1290 * Initialize the exports module. 1291 */ 1292 void 1293 nfsd_export_init(void) 1294 { 1295 dprintk("nfsd: initializing export module.\n"); 1296 1297 cache_register(&svc_export_cache); 1298 cache_register(&svc_expkey_cache); 1299 1300 } 1301 1302 /* 1303 * Flush exports table - called when last nfsd thread is killed 1304 */ 1305 void 1306 nfsd_export_flush(void) 1307 { 1308 exp_writelock(); 1309 cache_purge(&svc_expkey_cache); 1310 cache_purge(&svc_export_cache); 1311 exp_writeunlock(); 1312 } 1313 1314 /* 1315 * Shutdown the exports module. 1316 */ 1317 void 1318 nfsd_export_shutdown(void) 1319 { 1320 1321 dprintk("nfsd: shutting down export module.\n"); 1322 1323 exp_writelock(); 1324 1325 if (cache_unregister(&svc_expkey_cache)) 1326 printk(KERN_ERR "nfsd: failed to unregister expkey cache\n"); 1327 if (cache_unregister(&svc_export_cache)) 1328 printk(KERN_ERR "nfsd: failed to unregister export cache\n"); 1329 svcauth_unix_purge(); 1330 1331 exp_writeunlock(); 1332 dprintk("nfsd: export shutdown complete.\n"); 1333 } 1334