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 (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_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_no_path; 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 out_no_path: 479 if (dom) 480 auth_domain_put(dom); 481 kfree(buf); 482 return err; 483 } 484 485 static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong); 486 487 static int svc_export_show(struct seq_file *m, 488 struct cache_detail *cd, 489 struct cache_head *h) 490 { 491 struct svc_export *exp ; 492 493 if (h ==NULL) { 494 seq_puts(m, "#path domain(flags)\n"); 495 return 0; 496 } 497 exp = container_of(h, struct svc_export, h); 498 seq_path(m, exp->ex_mnt, exp->ex_dentry, " \t\n\\"); 499 seq_putc(m, '\t'); 500 seq_escape(m, exp->ex_client->name, " \t\n\\"); 501 seq_putc(m, '('); 502 if (test_bit(CACHE_VALID, &h->flags) && 503 !test_bit(CACHE_NEGATIVE, &h->flags)) 504 exp_flags(m, exp->ex_flags, exp->ex_fsid, 505 exp->ex_anon_uid, exp->ex_anon_gid); 506 seq_puts(m, ")\n"); 507 return 0; 508 } 509 static int svc_export_match(struct cache_head *a, struct cache_head *b) 510 { 511 struct svc_export *orig = container_of(a, struct svc_export, h); 512 struct svc_export *new = container_of(b, struct svc_export, h); 513 return orig->ex_client == new->ex_client && 514 orig->ex_dentry == new->ex_dentry && 515 orig->ex_mnt == new->ex_mnt; 516 } 517 518 static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) 519 { 520 struct svc_export *new = container_of(cnew, struct svc_export, h); 521 struct svc_export *item = container_of(citem, struct svc_export, h); 522 523 kref_get(&item->ex_client->ref); 524 new->ex_client = item->ex_client; 525 new->ex_dentry = dget(item->ex_dentry); 526 new->ex_mnt = mntget(item->ex_mnt); 527 } 528 529 static void export_update(struct cache_head *cnew, struct cache_head *citem) 530 { 531 struct svc_export *new = container_of(cnew, struct svc_export, h); 532 struct svc_export *item = container_of(citem, struct svc_export, h); 533 534 new->ex_flags = item->ex_flags; 535 new->ex_anon_uid = item->ex_anon_uid; 536 new->ex_anon_gid = item->ex_anon_gid; 537 new->ex_fsid = item->ex_fsid; 538 } 539 540 static struct cache_head *svc_export_alloc(void) 541 { 542 struct svc_export *i = kmalloc(sizeof(*i), GFP_KERNEL); 543 if (i) 544 return &i->h; 545 else 546 return NULL; 547 } 548 549 struct cache_detail svc_export_cache = { 550 .owner = THIS_MODULE, 551 .hash_size = EXPORT_HASHMAX, 552 .hash_table = export_table, 553 .name = "nfsd.export", 554 .cache_put = svc_export_put, 555 .cache_request = svc_export_request, 556 .cache_parse = svc_export_parse, 557 .cache_show = svc_export_show, 558 .match = svc_export_match, 559 .init = svc_export_init, 560 .update = export_update, 561 .alloc = svc_export_alloc, 562 }; 563 564 static struct svc_export * 565 svc_export_lookup(struct svc_export *exp) 566 { 567 struct cache_head *ch; 568 int hash; 569 hash = hash_ptr(exp->ex_client, EXPORT_HASHBITS); 570 hash ^= hash_ptr(exp->ex_dentry, EXPORT_HASHBITS); 571 hash ^= hash_ptr(exp->ex_mnt, EXPORT_HASHBITS); 572 573 ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h, 574 hash); 575 if (ch) 576 return container_of(ch, struct svc_export, h); 577 else 578 return NULL; 579 } 580 581 static struct svc_export * 582 svc_export_update(struct svc_export *new, struct svc_export *old) 583 { 584 struct cache_head *ch; 585 int hash; 586 hash = hash_ptr(old->ex_client, EXPORT_HASHBITS); 587 hash ^= hash_ptr(old->ex_dentry, EXPORT_HASHBITS); 588 hash ^= hash_ptr(old->ex_mnt, EXPORT_HASHBITS); 589 590 ch = sunrpc_cache_update(&svc_export_cache, &new->h, 591 &old->h, 592 hash); 593 if (ch) 594 return container_of(ch, struct svc_export, h); 595 else 596 return NULL; 597 } 598 599 600 static struct svc_expkey * 601 exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) 602 { 603 struct svc_expkey key, *ek; 604 int err; 605 606 if (!clp) 607 return NULL; 608 609 key.ek_client = clp; 610 key.ek_fsidtype = fsid_type; 611 memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); 612 613 ek = svc_expkey_lookup(&key); 614 if (ek != NULL) 615 if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp))) 616 ek = ERR_PTR(err); 617 return ek; 618 } 619 620 static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv, 621 struct svc_export *exp) 622 { 623 struct svc_expkey key, *ek; 624 625 key.ek_client = clp; 626 key.ek_fsidtype = fsid_type; 627 memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); 628 key.ek_mnt = exp->ex_mnt; 629 key.ek_dentry = exp->ex_dentry; 630 key.h.expiry_time = NEVER; 631 key.h.flags = 0; 632 633 ek = svc_expkey_lookup(&key); 634 if (ek) 635 ek = svc_expkey_update(&key,ek); 636 if (ek) { 637 cache_put(&ek->h, &svc_expkey_cache); 638 return 0; 639 } 640 return -ENOMEM; 641 } 642 643 /* 644 * Find the client's export entry matching xdev/xino. 645 */ 646 static inline struct svc_expkey * 647 exp_get_key(svc_client *clp, dev_t dev, ino_t ino) 648 { 649 u32 fsidv[3]; 650 651 if (old_valid_dev(dev)) { 652 mk_fsid_v0(fsidv, dev, ino); 653 return exp_find_key(clp, 0, fsidv, NULL); 654 } 655 mk_fsid_v3(fsidv, dev, ino); 656 return exp_find_key(clp, 3, fsidv, NULL); 657 } 658 659 /* 660 * Find the client's export entry matching fsid 661 */ 662 static inline struct svc_expkey * 663 exp_get_fsid_key(svc_client *clp, int fsid) 664 { 665 u32 fsidv[2]; 666 667 mk_fsid_v1(fsidv, fsid); 668 669 return exp_find_key(clp, 1, fsidv, NULL); 670 } 671 672 svc_export * 673 exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry, 674 struct cache_req *reqp) 675 { 676 struct svc_export *exp, key; 677 678 if (!clp) 679 return NULL; 680 681 key.ex_client = clp; 682 key.ex_mnt = mnt; 683 key.ex_dentry = dentry; 684 685 exp = svc_export_lookup(&key); 686 if (exp != NULL) 687 switch (cache_check(&svc_export_cache, &exp->h, reqp)) { 688 case 0: break; 689 case -EAGAIN: 690 exp = ERR_PTR(-EAGAIN); 691 break; 692 default: 693 exp = NULL; 694 } 695 696 return exp; 697 } 698 699 /* 700 * Find the export entry for a given dentry. 701 */ 702 struct svc_export * 703 exp_parent(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry, 704 struct cache_req *reqp) 705 { 706 svc_export *exp; 707 708 dget(dentry); 709 exp = exp_get_by_name(clp, mnt, dentry, reqp); 710 711 while (exp == NULL && !IS_ROOT(dentry)) { 712 struct dentry *parent; 713 714 parent = dget_parent(dentry); 715 dput(dentry); 716 dentry = parent; 717 exp = exp_get_by_name(clp, mnt, dentry, reqp); 718 } 719 dput(dentry); 720 return exp; 721 } 722 723 /* 724 * Hashtable locking. Write locks are placed only by user processes 725 * wanting to modify export information. 726 * Write locking only done in this file. Read locking 727 * needed externally. 728 */ 729 730 static DECLARE_RWSEM(hash_sem); 731 732 void 733 exp_readlock(void) 734 { 735 down_read(&hash_sem); 736 } 737 738 static inline void 739 exp_writelock(void) 740 { 741 down_write(&hash_sem); 742 } 743 744 void 745 exp_readunlock(void) 746 { 747 up_read(&hash_sem); 748 } 749 750 static inline void 751 exp_writeunlock(void) 752 { 753 up_write(&hash_sem); 754 } 755 756 static void exp_fsid_unhash(struct svc_export *exp) 757 { 758 struct svc_expkey *ek; 759 760 if ((exp->ex_flags & NFSEXP_FSID) == 0) 761 return; 762 763 ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); 764 if (ek && !IS_ERR(ek)) { 765 ek->h.expiry_time = get_seconds()-1; 766 cache_put(&ek->h, &svc_expkey_cache); 767 } 768 svc_expkey_cache.nextcheck = get_seconds(); 769 } 770 771 static int exp_fsid_hash(svc_client *clp, struct svc_export *exp) 772 { 773 u32 fsid[2]; 774 775 if ((exp->ex_flags & NFSEXP_FSID) == 0) 776 return 0; 777 778 mk_fsid_v1(fsid, exp->ex_fsid); 779 return exp_set_key(clp, 1, fsid, exp); 780 } 781 782 static int exp_hash(struct auth_domain *clp, struct svc_export *exp) 783 { 784 u32 fsid[2]; 785 struct inode *inode = exp->ex_dentry->d_inode; 786 dev_t dev = inode->i_sb->s_dev; 787 788 if (old_valid_dev(dev)) { 789 mk_fsid_v0(fsid, dev, inode->i_ino); 790 return exp_set_key(clp, 0, fsid, exp); 791 } 792 mk_fsid_v3(fsid, dev, inode->i_ino); 793 return exp_set_key(clp, 3, fsid, exp); 794 } 795 796 static void exp_unhash(struct svc_export *exp) 797 { 798 struct svc_expkey *ek; 799 struct inode *inode = exp->ex_dentry->d_inode; 800 801 ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); 802 if (ek && !IS_ERR(ek)) { 803 ek->h.expiry_time = get_seconds()-1; 804 cache_put(&ek->h, &svc_expkey_cache); 805 } 806 svc_expkey_cache.nextcheck = get_seconds(); 807 } 808 809 /* 810 * Export a file system. 811 */ 812 int 813 exp_export(struct nfsctl_export *nxp) 814 { 815 svc_client *clp; 816 struct svc_export *exp = NULL; 817 struct svc_export new; 818 struct svc_expkey *fsid_key = NULL; 819 struct nameidata nd; 820 int err; 821 822 /* Consistency check */ 823 err = -EINVAL; 824 if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) || 825 !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX)) 826 goto out; 827 828 dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n", 829 nxp->ex_client, nxp->ex_path, 830 (unsigned)nxp->ex_dev, (long)nxp->ex_ino, 831 nxp->ex_flags); 832 833 /* Try to lock the export table for update */ 834 exp_writelock(); 835 836 /* Look up client info */ 837 if (!(clp = auth_domain_find(nxp->ex_client))) 838 goto out_unlock; 839 840 841 /* Look up the dentry */ 842 err = path_lookup(nxp->ex_path, 0, &nd); 843 if (err) 844 goto out_unlock; 845 err = -EINVAL; 846 847 exp = exp_get_by_name(clp, nd.mnt, nd.dentry, NULL); 848 849 /* must make sure there won't be an ex_fsid clash */ 850 if ((nxp->ex_flags & NFSEXP_FSID) && 851 (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && 852 !IS_ERR(fsid_key) && 853 fsid_key->ek_mnt && 854 (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) ) 855 goto finish; 856 857 if (exp) { 858 /* just a flags/id/fsid update */ 859 860 exp_fsid_unhash(exp); 861 exp->ex_flags = nxp->ex_flags; 862 exp->ex_anon_uid = nxp->ex_anon_uid; 863 exp->ex_anon_gid = nxp->ex_anon_gid; 864 exp->ex_fsid = nxp->ex_dev; 865 866 err = exp_fsid_hash(clp, exp); 867 goto finish; 868 } 869 870 err = check_export(nd.dentry->d_inode, nxp->ex_flags); 871 if (err) goto finish; 872 873 err = -ENOMEM; 874 875 dprintk("nfsd: creating export entry %p for client %p\n", exp, clp); 876 877 new.h.expiry_time = NEVER; 878 new.h.flags = 0; 879 new.ex_client = clp; 880 new.ex_mnt = nd.mnt; 881 new.ex_dentry = nd.dentry; 882 new.ex_flags = nxp->ex_flags; 883 new.ex_anon_uid = nxp->ex_anon_uid; 884 new.ex_anon_gid = nxp->ex_anon_gid; 885 new.ex_fsid = nxp->ex_dev; 886 887 exp = svc_export_lookup(&new); 888 if (exp) 889 exp = svc_export_update(&new, exp); 890 891 if (!exp) 892 goto finish; 893 894 if (exp_hash(clp, exp) || 895 exp_fsid_hash(clp, exp)) { 896 /* failed to create at least one index */ 897 exp_do_unexport(exp); 898 cache_flush(); 899 err = -ENOMEM; 900 } 901 902 finish: 903 if (exp) 904 exp_put(exp); 905 if (fsid_key && !IS_ERR(fsid_key)) 906 cache_put(&fsid_key->h, &svc_expkey_cache); 907 if (clp) 908 auth_domain_put(clp); 909 path_release(&nd); 910 out_unlock: 911 exp_writeunlock(); 912 out: 913 return err; 914 } 915 916 /* 917 * Unexport a file system. The export entry has already 918 * been removed from the client's list of exported fs's. 919 */ 920 static void 921 exp_do_unexport(svc_export *unexp) 922 { 923 unexp->h.expiry_time = get_seconds()-1; 924 svc_export_cache.nextcheck = get_seconds(); 925 exp_unhash(unexp); 926 exp_fsid_unhash(unexp); 927 } 928 929 930 /* 931 * unexport syscall. 932 */ 933 int 934 exp_unexport(struct nfsctl_export *nxp) 935 { 936 struct auth_domain *dom; 937 svc_export *exp; 938 struct nameidata nd; 939 int err; 940 941 /* Consistency check */ 942 if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) || 943 !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX)) 944 return -EINVAL; 945 946 exp_writelock(); 947 948 err = -EINVAL; 949 dom = auth_domain_find(nxp->ex_client); 950 if (!dom) { 951 dprintk("nfsd: unexport couldn't find %s\n", nxp->ex_client); 952 goto out_unlock; 953 } 954 955 err = path_lookup(nxp->ex_path, 0, &nd); 956 if (err) 957 goto out_domain; 958 959 err = -EINVAL; 960 exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL); 961 path_release(&nd); 962 if (!exp) 963 goto out_domain; 964 965 exp_do_unexport(exp); 966 exp_put(exp); 967 err = 0; 968 969 out_domain: 970 auth_domain_put(dom); 971 cache_flush(); 972 out_unlock: 973 exp_writeunlock(); 974 return err; 975 } 976 977 /* 978 * Obtain the root fh on behalf of a client. 979 * This could be done in user space, but I feel that it adds some safety 980 * since its harder to fool a kernel module than a user space program. 981 */ 982 int 983 exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize) 984 { 985 struct svc_export *exp; 986 struct nameidata nd; 987 struct inode *inode; 988 struct svc_fh fh; 989 int err; 990 991 err = -EPERM; 992 /* NB: we probably ought to check that it's NUL-terminated */ 993 if (path_lookup(path, 0, &nd)) { 994 printk("nfsd: exp_rootfh path not found %s", path); 995 return err; 996 } 997 inode = nd.dentry->d_inode; 998 999 dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n", 1000 path, nd.dentry, clp->name, 1001 inode->i_sb->s_id, inode->i_ino); 1002 exp = exp_parent(clp, nd.mnt, nd.dentry, NULL); 1003 if (!exp) { 1004 dprintk("nfsd: exp_rootfh export not found.\n"); 1005 goto out; 1006 } 1007 1008 /* 1009 * fh must be initialized before calling fh_compose 1010 */ 1011 fh_init(&fh, maxsize); 1012 if (fh_compose(&fh, exp, nd.dentry, NULL)) 1013 err = -EINVAL; 1014 else 1015 err = 0; 1016 memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh)); 1017 fh_put(&fh); 1018 exp_put(exp); 1019 out: 1020 path_release(&nd); 1021 return err; 1022 } 1023 1024 struct svc_export * 1025 exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, 1026 struct cache_req *reqp) 1027 { 1028 struct svc_export *exp; 1029 struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); 1030 if (!ek || IS_ERR(ek)) 1031 return ERR_PTR(PTR_ERR(ek)); 1032 1033 exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp); 1034 cache_put(&ek->h, &svc_expkey_cache); 1035 1036 if (!exp || IS_ERR(exp)) 1037 return ERR_PTR(PTR_ERR(exp)); 1038 return exp; 1039 } 1040 1041 1042 /* 1043 * Called when we need the filehandle for the root of the pseudofs, 1044 * for a given NFSv4 client. The root is defined to be the 1045 * export point with fsid==0 1046 */ 1047 int 1048 exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, 1049 struct cache_req *creq) 1050 { 1051 struct svc_expkey *fsid_key; 1052 struct svc_export *exp; 1053 int rv; 1054 u32 fsidv[2]; 1055 1056 mk_fsid_v1(fsidv, 0); 1057 1058 fsid_key = exp_find_key(clp, 1, fsidv, creq); 1059 if (IS_ERR(fsid_key) && PTR_ERR(fsid_key) == -EAGAIN) 1060 return nfserr_dropit; 1061 if (!fsid_key || IS_ERR(fsid_key)) 1062 return nfserr_perm; 1063 1064 exp = exp_get_by_name(clp, fsid_key->ek_mnt, fsid_key->ek_dentry, creq); 1065 if (exp == NULL) 1066 rv = nfserr_perm; 1067 else if (IS_ERR(exp)) 1068 rv = nfserrno(PTR_ERR(exp)); 1069 else { 1070 rv = fh_compose(fhp, exp, 1071 fsid_key->ek_dentry, NULL); 1072 exp_put(exp); 1073 } 1074 cache_put(&fsid_key->h, &svc_expkey_cache); 1075 return rv; 1076 } 1077 1078 /* Iterator */ 1079 1080 static void *e_start(struct seq_file *m, loff_t *pos) 1081 { 1082 loff_t n = *pos; 1083 unsigned hash, export; 1084 struct cache_head *ch; 1085 1086 exp_readlock(); 1087 read_lock(&svc_export_cache.hash_lock); 1088 if (!n--) 1089 return (void *)1; 1090 hash = n >> 32; 1091 export = n & ((1LL<<32) - 1); 1092 1093 1094 for (ch=export_table[hash]; ch; ch=ch->next) 1095 if (!export--) 1096 return ch; 1097 n &= ~((1LL<<32) - 1); 1098 do { 1099 hash++; 1100 n += 1LL<<32; 1101 } while(hash < EXPORT_HASHMAX && export_table[hash]==NULL); 1102 if (hash >= EXPORT_HASHMAX) 1103 return NULL; 1104 *pos = n+1; 1105 return export_table[hash]; 1106 } 1107 1108 static void *e_next(struct seq_file *m, void *p, loff_t *pos) 1109 { 1110 struct cache_head *ch = p; 1111 int hash = (*pos >> 32); 1112 1113 if (p == (void *)1) 1114 hash = 0; 1115 else if (ch->next == NULL) { 1116 hash++; 1117 *pos += 1LL<<32; 1118 } else { 1119 ++*pos; 1120 return ch->next; 1121 } 1122 *pos &= ~((1LL<<32) - 1); 1123 while (hash < EXPORT_HASHMAX && export_table[hash] == NULL) { 1124 hash++; 1125 *pos += 1LL<<32; 1126 } 1127 if (hash >= EXPORT_HASHMAX) 1128 return NULL; 1129 ++*pos; 1130 return export_table[hash]; 1131 } 1132 1133 static void e_stop(struct seq_file *m, void *p) 1134 { 1135 read_unlock(&svc_export_cache.hash_lock); 1136 exp_readunlock(); 1137 } 1138 1139 static struct flags { 1140 int flag; 1141 char *name[2]; 1142 } expflags[] = { 1143 { NFSEXP_READONLY, {"ro", "rw"}}, 1144 { NFSEXP_INSECURE_PORT, {"insecure", ""}}, 1145 { NFSEXP_ROOTSQUASH, {"root_squash", "no_root_squash"}}, 1146 { NFSEXP_ALLSQUASH, {"all_squash", ""}}, 1147 { NFSEXP_ASYNC, {"async", "sync"}}, 1148 { NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}}, 1149 { NFSEXP_NOHIDE, {"nohide", ""}}, 1150 { NFSEXP_CROSSMOUNT, {"crossmnt", ""}}, 1151 { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}}, 1152 { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}}, 1153 #ifdef MSNFS 1154 { NFSEXP_MSNFS, {"msnfs", ""}}, 1155 #endif 1156 { 0, {"", ""}} 1157 }; 1158 1159 static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong) 1160 { 1161 int first = 0; 1162 struct flags *flg; 1163 1164 for (flg = expflags; flg->flag; flg++) { 1165 int state = (flg->flag & flag)?0:1; 1166 if (*flg->name[state]) 1167 seq_printf(m, "%s%s", first++?",":"", flg->name[state]); 1168 } 1169 if (flag & NFSEXP_FSID) 1170 seq_printf(m, "%sfsid=%d", first++?",":"", fsid); 1171 if (anonu != (uid_t)-2 && anonu != (0x10000-2)) 1172 seq_printf(m, "%sanonuid=%d", first++?",":"", anonu); 1173 if (anong != (gid_t)-2 && anong != (0x10000-2)) 1174 seq_printf(m, "%sanongid=%d", first++?",":"", anong); 1175 } 1176 1177 static int e_show(struct seq_file *m, void *p) 1178 { 1179 struct cache_head *cp = p; 1180 struct svc_export *exp = container_of(cp, struct svc_export, h); 1181 svc_client *clp; 1182 1183 if (p == (void *)1) { 1184 seq_puts(m, "# Version 1.1\n"); 1185 seq_puts(m, "# Path Client(Flags) # IPs\n"); 1186 return 0; 1187 } 1188 1189 clp = exp->ex_client; 1190 cache_get(&exp->h); 1191 if (cache_check(&svc_export_cache, &exp->h, NULL)) 1192 return 0; 1193 cache_put(&exp->h, &svc_export_cache); 1194 return svc_export_show(m, &svc_export_cache, cp); 1195 } 1196 1197 struct seq_operations nfs_exports_op = { 1198 .start = e_start, 1199 .next = e_next, 1200 .stop = e_stop, 1201 .show = e_show, 1202 }; 1203 1204 /* 1205 * Add or modify a client. 1206 * Change requests may involve the list of host addresses. The list of 1207 * exports and possibly existing uid maps are left untouched. 1208 */ 1209 int 1210 exp_addclient(struct nfsctl_client *ncp) 1211 { 1212 struct auth_domain *dom; 1213 int i, err; 1214 1215 /* First, consistency check. */ 1216 err = -EINVAL; 1217 if (! exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX)) 1218 goto out; 1219 if (ncp->cl_naddr > NFSCLNT_ADDRMAX) 1220 goto out; 1221 1222 /* Lock the hashtable */ 1223 exp_writelock(); 1224 1225 dom = unix_domain_find(ncp->cl_ident); 1226 1227 err = -ENOMEM; 1228 if (!dom) 1229 goto out_unlock; 1230 1231 /* Insert client into hashtable. */ 1232 for (i = 0; i < ncp->cl_naddr; i++) 1233 auth_unix_add_addr(ncp->cl_addrlist[i], dom); 1234 1235 auth_unix_forget_old(dom); 1236 auth_domain_put(dom); 1237 1238 err = 0; 1239 1240 out_unlock: 1241 exp_writeunlock(); 1242 out: 1243 return err; 1244 } 1245 1246 /* 1247 * Delete a client given an identifier. 1248 */ 1249 int 1250 exp_delclient(struct nfsctl_client *ncp) 1251 { 1252 int err; 1253 struct auth_domain *dom; 1254 1255 err = -EINVAL; 1256 if (!exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX)) 1257 goto out; 1258 1259 /* Lock the hashtable */ 1260 exp_writelock(); 1261 1262 dom = auth_domain_find(ncp->cl_ident); 1263 /* just make sure that no addresses work 1264 * and that it will expire soon 1265 */ 1266 if (dom) { 1267 err = auth_unix_forget_old(dom); 1268 auth_domain_put(dom); 1269 } 1270 1271 exp_writeunlock(); 1272 out: 1273 return err; 1274 } 1275 1276 /* 1277 * Verify that string is non-empty and does not exceed max length. 1278 */ 1279 static int 1280 exp_verify_string(char *cp, int max) 1281 { 1282 int i; 1283 1284 for (i = 0; i < max; i++) 1285 if (!cp[i]) 1286 return i; 1287 cp[i] = 0; 1288 printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp); 1289 return 0; 1290 } 1291 1292 /* 1293 * Initialize the exports module. 1294 */ 1295 void 1296 nfsd_export_init(void) 1297 { 1298 dprintk("nfsd: initializing export module.\n"); 1299 1300 cache_register(&svc_export_cache); 1301 cache_register(&svc_expkey_cache); 1302 1303 } 1304 1305 /* 1306 * Flush exports table - called when last nfsd thread is killed 1307 */ 1308 void 1309 nfsd_export_flush(void) 1310 { 1311 exp_writelock(); 1312 cache_purge(&svc_expkey_cache); 1313 cache_purge(&svc_export_cache); 1314 exp_writeunlock(); 1315 } 1316 1317 /* 1318 * Shutdown the exports module. 1319 */ 1320 void 1321 nfsd_export_shutdown(void) 1322 { 1323 1324 dprintk("nfsd: shutting down export module.\n"); 1325 1326 exp_writelock(); 1327 1328 if (cache_unregister(&svc_expkey_cache)) 1329 printk(KERN_ERR "nfsd: failed to unregister expkey cache\n"); 1330 if (cache_unregister(&svc_export_cache)) 1331 printk(KERN_ERR "nfsd: failed to unregister export cache\n"); 1332 svcauth_unix_purge(); 1333 1334 exp_writeunlock(); 1335 dprintk("nfsd: export shutdown complete.\n"); 1336 } 1337