export.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200
  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. #include <linux/unistd.h>
  17. #include <linux/slab.h>
  18. #include <linux/sched.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/sunrpc/svc.h>
  29. #include <linux/nfsd/nfsd.h>
  30. #include <linux/nfsd/nfsfh.h>
  31. #include <linux/nfsd/syscall.h>
  32. #include <linux/lockd/bind.h>
  33. #define NFSDDBG_FACILITY NFSDDBG_EXPORT
  34. #define NFSD_PARANOIA 1
  35. typedef struct auth_domain svc_client;
  36. typedef struct svc_export svc_export;
  37. static void exp_do_unexport(svc_export *unexp);
  38. static int exp_verify_string(char *cp, int max);
  39. /*
  40. * We have two caches.
  41. * One maps client+vfsmnt+dentry to export options - the export map
  42. * The other maps client+filehandle-fragment to export options. - the expkey map
  43. *
  44. * The export options are actually stored in the first map, and the
  45. * second map contains a reference to the entry in the first map.
  46. */
  47. #define EXPKEY_HASHBITS 8
  48. #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS)
  49. #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
  50. static struct cache_head *expkey_table[EXPKEY_HASHMAX];
  51. static inline int svc_expkey_hash(struct svc_expkey *item)
  52. {
  53. int hash = item->ek_fsidtype;
  54. char * cp = (char*)item->ek_fsid;
  55. int len = key_len(item->ek_fsidtype);
  56. hash ^= hash_mem(cp, len, EXPKEY_HASHBITS);
  57. hash ^= hash_ptr(item->ek_client, EXPKEY_HASHBITS);
  58. return hash & EXPKEY_HASHMASK;
  59. }
  60. void expkey_put(struct cache_head *item, struct cache_detail *cd)
  61. {
  62. if (cache_put(item, cd)) {
  63. struct svc_expkey *key = container_of(item, struct svc_expkey, h);
  64. if (test_bit(CACHE_VALID, &item->flags) &&
  65. !test_bit(CACHE_NEGATIVE, &item->flags))
  66. exp_put(key->ek_export);
  67. auth_domain_put(key->ek_client);
  68. kfree(key);
  69. }
  70. }
  71. static void expkey_request(struct cache_detail *cd,
  72. struct cache_head *h,
  73. char **bpp, int *blen)
  74. {
  75. /* client fsidtype \xfsid */
  76. struct svc_expkey *ek = container_of(h, struct svc_expkey, h);
  77. char type[5];
  78. qword_add(bpp, blen, ek->ek_client->name);
  79. snprintf(type, 5, "%d", ek->ek_fsidtype);
  80. qword_add(bpp, blen, type);
  81. qword_addhex(bpp, blen, (char*)ek->ek_fsid, key_len(ek->ek_fsidtype));
  82. (*bpp)[-1] = '\n';
  83. }
  84. static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *, int);
  85. static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
  86. {
  87. /* client fsidtype fsid [path] */
  88. char *buf;
  89. int len;
  90. struct auth_domain *dom = NULL;
  91. int err;
  92. int fsidtype;
  93. char *ep;
  94. struct svc_expkey key;
  95. if (mesg[mlen-1] != '\n')
  96. return -EINVAL;
  97. mesg[mlen-1] = 0;
  98. buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
  99. err = -ENOMEM;
  100. if (!buf) goto out;
  101. err = -EINVAL;
  102. if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
  103. goto out;
  104. err = -ENOENT;
  105. dom = auth_domain_find(buf);
  106. if (!dom)
  107. goto out;
  108. dprintk("found domain %s\n", buf);
  109. err = -EINVAL;
  110. if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
  111. goto out;
  112. fsidtype = simple_strtoul(buf, &ep, 10);
  113. if (*ep)
  114. goto out;
  115. dprintk("found fsidtype %d\n", fsidtype);
  116. if (fsidtype > 2)
  117. goto out;
  118. if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
  119. goto out;
  120. dprintk("found fsid length %d\n", len);
  121. if (len != key_len(fsidtype))
  122. goto out;
  123. /* OK, we seem to have a valid key */
  124. key.h.flags = 0;
  125. key.h.expiry_time = get_expiry(&mesg);
  126. if (key.h.expiry_time == 0)
  127. goto out;
  128. key.ek_client = dom;
  129. key.ek_fsidtype = fsidtype;
  130. memcpy(key.ek_fsid, buf, len);
  131. /* now we want a pathname, or empty meaning NEGATIVE */
  132. if ((len=qword_get(&mesg, buf, PAGE_SIZE)) < 0)
  133. goto out;
  134. dprintk("Path seems to be <%s>\n", buf);
  135. err = 0;
  136. if (len == 0) {
  137. struct svc_expkey *ek;
  138. set_bit(CACHE_NEGATIVE, &key.h.flags);
  139. ek = svc_expkey_lookup(&key, 1);
  140. if (ek)
  141. expkey_put(&ek->h, &svc_expkey_cache);
  142. } else {
  143. struct nameidata nd;
  144. struct svc_expkey *ek;
  145. struct svc_export *exp;
  146. err = path_lookup(buf, 0, &nd);
  147. if (err)
  148. goto out;
  149. dprintk("Found the path %s\n", buf);
  150. exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
  151. err = -ENOENT;
  152. if (!exp)
  153. goto out_nd;
  154. key.ek_export = exp;
  155. dprintk("And found export\n");
  156. ek = svc_expkey_lookup(&key, 1);
  157. if (ek)
  158. expkey_put(&ek->h, &svc_expkey_cache);
  159. exp_put(exp);
  160. err = 0;
  161. out_nd:
  162. path_release(&nd);
  163. }
  164. cache_flush();
  165. out:
  166. if (dom)
  167. auth_domain_put(dom);
  168. if (buf)
  169. kfree(buf);
  170. return err;
  171. }
  172. static int expkey_show(struct seq_file *m,
  173. struct cache_detail *cd,
  174. struct cache_head *h)
  175. {
  176. struct svc_expkey *ek ;
  177. if (h ==NULL) {
  178. seq_puts(m, "#domain fsidtype fsid [path]\n");
  179. return 0;
  180. }
  181. ek = container_of(h, struct svc_expkey, h);
  182. seq_printf(m, "%s %d 0x%08x", ek->ek_client->name,
  183. ek->ek_fsidtype, ek->ek_fsid[0]);
  184. if (ek->ek_fsidtype != 1)
  185. seq_printf(m, "%08x", ek->ek_fsid[1]);
  186. if (ek->ek_fsidtype == 2)
  187. seq_printf(m, "%08x", ek->ek_fsid[2]);
  188. if (test_bit(CACHE_VALID, &h->flags) &&
  189. !test_bit(CACHE_NEGATIVE, &h->flags)) {
  190. seq_printf(m, " ");
  191. seq_path(m, ek->ek_export->ex_mnt, ek->ek_export->ex_dentry, "\\ \t\n");
  192. }
  193. seq_printf(m, "\n");
  194. return 0;
  195. }
  196. struct cache_detail svc_expkey_cache = {
  197. .hash_size = EXPKEY_HASHMAX,
  198. .hash_table = expkey_table,
  199. .name = "nfsd.fh",
  200. .cache_put = expkey_put,
  201. .cache_request = expkey_request,
  202. .cache_parse = expkey_parse,
  203. .cache_show = expkey_show,
  204. };
  205. static inline int svc_expkey_match (struct svc_expkey *a, struct svc_expkey *b)
  206. {
  207. if (a->ek_fsidtype != b->ek_fsidtype ||
  208. a->ek_client != b->ek_client ||
  209. memcmp(a->ek_fsid, b->ek_fsid, key_len(a->ek_fsidtype)) != 0)
  210. return 0;
  211. return 1;
  212. }
  213. static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *item)
  214. {
  215. cache_get(&item->ek_client->h);
  216. new->ek_client = item->ek_client;
  217. new->ek_fsidtype = item->ek_fsidtype;
  218. new->ek_fsid[0] = item->ek_fsid[0];
  219. new->ek_fsid[1] = item->ek_fsid[1];
  220. new->ek_fsid[2] = item->ek_fsid[2];
  221. }
  222. static inline void svc_expkey_update(struct svc_expkey *new, struct svc_expkey *item)
  223. {
  224. cache_get(&item->ek_export->h);
  225. new->ek_export = item->ek_export;
  226. }
  227. static DefineSimpleCacheLookup(svc_expkey,0) /* no inplace updates */
  228. #define EXPORT_HASHBITS 8
  229. #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
  230. #define EXPORT_HASHMASK (EXPORT_HASHMAX -1)
  231. static struct cache_head *export_table[EXPORT_HASHMAX];
  232. static inline int svc_export_hash(struct svc_export *item)
  233. {
  234. int rv;
  235. rv = hash_ptr(item->ex_client, EXPORT_HASHBITS);
  236. rv ^= hash_ptr(item->ex_dentry, EXPORT_HASHBITS);
  237. rv ^= hash_ptr(item->ex_mnt, EXPORT_HASHBITS);
  238. return rv;
  239. }
  240. void svc_export_put(struct cache_head *item, struct cache_detail *cd)
  241. {
  242. if (cache_put(item, cd)) {
  243. struct svc_export *exp = container_of(item, struct svc_export, h);
  244. dput(exp->ex_dentry);
  245. mntput(exp->ex_mnt);
  246. auth_domain_put(exp->ex_client);
  247. kfree(exp);
  248. }
  249. }
  250. static void svc_export_request(struct cache_detail *cd,
  251. struct cache_head *h,
  252. char **bpp, int *blen)
  253. {
  254. /* client path */
  255. struct svc_export *exp = container_of(h, struct svc_export, h);
  256. char *pth;
  257. qword_add(bpp, blen, exp->ex_client->name);
  258. pth = d_path(exp->ex_dentry, exp->ex_mnt, *bpp, *blen);
  259. if (IS_ERR(pth)) {
  260. /* is this correct? */
  261. (*bpp)[0] = '\n';
  262. return;
  263. }
  264. qword_add(bpp, blen, pth);
  265. (*bpp)[-1] = '\n';
  266. }
  267. static struct svc_export *svc_export_lookup(struct svc_export *, int);
  268. static int check_export(struct inode *inode, int flags)
  269. {
  270. /* We currently export only dirs and regular files.
  271. * This is what umountd does.
  272. */
  273. if (!S_ISDIR(inode->i_mode) &&
  274. !S_ISREG(inode->i_mode))
  275. return -ENOTDIR;
  276. /* There are two requirements on a filesystem to be exportable.
  277. * 1: We must be able to identify the filesystem from a number.
  278. * either a device number (so FS_REQUIRES_DEV needed)
  279. * or an FSID number (so NFSEXP_FSID needed).
  280. * 2: We must be able to find an inode from a filehandle.
  281. * This means that s_export_op must be set.
  282. */
  283. if (!(inode->i_sb->s_type->fs_flags & FS_REQUIRES_DEV) &&
  284. !(flags & NFSEXP_FSID)) {
  285. dprintk("exp_export: export of non-dev fs without fsid");
  286. return -EINVAL;
  287. }
  288. if (!inode->i_sb->s_export_op) {
  289. dprintk("exp_export: export of invalid fs type.\n");
  290. return -EINVAL;
  291. }
  292. /* Ok, we can export it */;
  293. if (!inode->i_sb->s_export_op->find_exported_dentry)
  294. inode->i_sb->s_export_op->find_exported_dentry =
  295. find_exported_dentry;
  296. return 0;
  297. }
  298. static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
  299. {
  300. /* client path expiry [flags anonuid anongid fsid] */
  301. char *buf;
  302. int len;
  303. int err;
  304. struct auth_domain *dom = NULL;
  305. struct nameidata nd;
  306. struct svc_export exp, *expp;
  307. int an_int;
  308. nd.dentry = NULL;
  309. if (mesg[mlen-1] != '\n')
  310. return -EINVAL;
  311. mesg[mlen-1] = 0;
  312. buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
  313. err = -ENOMEM;
  314. if (!buf) goto out;
  315. /* client */
  316. len = qword_get(&mesg, buf, PAGE_SIZE);
  317. err = -EINVAL;
  318. if (len <= 0) goto out;
  319. err = -ENOENT;
  320. dom = auth_domain_find(buf);
  321. if (!dom)
  322. goto out;
  323. /* path */
  324. err = -EINVAL;
  325. if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
  326. goto out;
  327. err = path_lookup(buf, 0, &nd);
  328. if (err) goto out;
  329. exp.h.flags = 0;
  330. exp.ex_client = dom;
  331. exp.ex_mnt = nd.mnt;
  332. exp.ex_dentry = nd.dentry;
  333. /* expiry */
  334. err = -EINVAL;
  335. exp.h.expiry_time = get_expiry(&mesg);
  336. if (exp.h.expiry_time == 0)
  337. goto out;
  338. /* flags */
  339. err = get_int(&mesg, &an_int);
  340. if (err == -ENOENT)
  341. set_bit(CACHE_NEGATIVE, &exp.h.flags);
  342. else {
  343. if (err || an_int < 0) goto out;
  344. exp.ex_flags= an_int;
  345. /* anon uid */
  346. err = get_int(&mesg, &an_int);
  347. if (err) goto out;
  348. exp.ex_anon_uid= an_int;
  349. /* anon gid */
  350. err = get_int(&mesg, &an_int);
  351. if (err) goto out;
  352. exp.ex_anon_gid= an_int;
  353. /* fsid */
  354. err = get_int(&mesg, &an_int);
  355. if (err) goto out;
  356. exp.ex_fsid = an_int;
  357. err = check_export(nd.dentry->d_inode, exp.ex_flags);
  358. if (err) goto out;
  359. }
  360. expp = svc_export_lookup(&exp, 1);
  361. if (expp)
  362. exp_put(expp);
  363. err = 0;
  364. cache_flush();
  365. out:
  366. if (nd.dentry)
  367. path_release(&nd);
  368. if (dom)
  369. auth_domain_put(dom);
  370. if (buf)
  371. kfree(buf);
  372. return err;
  373. }
  374. static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong);
  375. static int svc_export_show(struct seq_file *m,
  376. struct cache_detail *cd,
  377. struct cache_head *h)
  378. {
  379. struct svc_export *exp ;
  380. if (h ==NULL) {
  381. seq_puts(m, "#path domain(flags)\n");
  382. return 0;
  383. }
  384. exp = container_of(h, struct svc_export, h);
  385. seq_path(m, exp->ex_mnt, exp->ex_dentry, " \t\n\\");
  386. seq_putc(m, '\t');
  387. seq_escape(m, exp->ex_client->name, " \t\n\\");
  388. seq_putc(m, '(');
  389. if (test_bit(CACHE_VALID, &h->flags) &&
  390. !test_bit(CACHE_NEGATIVE, &h->flags))
  391. exp_flags(m, exp->ex_flags, exp->ex_fsid,
  392. exp->ex_anon_uid, exp->ex_anon_gid);
  393. seq_puts(m, ")\n");
  394. return 0;
  395. }
  396. struct cache_detail svc_export_cache = {
  397. .hash_size = EXPORT_HASHMAX,
  398. .hash_table = export_table,
  399. .name = "nfsd.export",
  400. .cache_put = svc_export_put,
  401. .cache_request = svc_export_request,
  402. .cache_parse = svc_export_parse,
  403. .cache_show = svc_export_show,
  404. };
  405. static inline int svc_export_match(struct svc_export *a, struct svc_export *b)
  406. {
  407. return a->ex_client == b->ex_client &&
  408. a->ex_dentry == b->ex_dentry &&
  409. a->ex_mnt == b->ex_mnt;
  410. }
  411. static inline void svc_export_init(struct svc_export *new, struct svc_export *item)
  412. {
  413. cache_get(&item->ex_client->h);
  414. new->ex_client = item->ex_client;
  415. new->ex_dentry = dget(item->ex_dentry);
  416. new->ex_mnt = mntget(item->ex_mnt);
  417. }
  418. static inline void svc_export_update(struct svc_export *new, struct svc_export *item)
  419. {
  420. new->ex_flags = item->ex_flags;
  421. new->ex_anon_uid = item->ex_anon_uid;
  422. new->ex_anon_gid = item->ex_anon_gid;
  423. new->ex_fsid = item->ex_fsid;
  424. }
  425. static DefineSimpleCacheLookup(svc_export,1) /* allow inplace updates */
  426. struct svc_expkey *
  427. exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
  428. {
  429. struct svc_expkey key, *ek;
  430. int err;
  431. if (!clp)
  432. return NULL;
  433. key.ek_client = clp;
  434. key.ek_fsidtype = fsid_type;
  435. memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
  436. ek = svc_expkey_lookup(&key, 0);
  437. if (ek != NULL)
  438. if ((err = cache_check(&svc_expkey_cache, &ek->h, reqp)))
  439. ek = ERR_PTR(err);
  440. return ek;
  441. }
  442. static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
  443. struct svc_export *exp)
  444. {
  445. struct svc_expkey key, *ek;
  446. key.ek_client = clp;
  447. key.ek_fsidtype = fsid_type;
  448. memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
  449. key.ek_export = exp;
  450. key.h.expiry_time = NEVER;
  451. key.h.flags = 0;
  452. ek = svc_expkey_lookup(&key, 1);
  453. if (ek) {
  454. expkey_put(&ek->h, &svc_expkey_cache);
  455. return 0;
  456. }
  457. return -ENOMEM;
  458. }
  459. /*
  460. * Find the client's export entry matching xdev/xino.
  461. */
  462. static inline struct svc_expkey *
  463. exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
  464. {
  465. u32 fsidv[3];
  466. if (old_valid_dev(dev)) {
  467. mk_fsid_v0(fsidv, dev, ino);
  468. return exp_find_key(clp, 0, fsidv, NULL);
  469. }
  470. mk_fsid_v3(fsidv, dev, ino);
  471. return exp_find_key(clp, 3, fsidv, NULL);
  472. }
  473. /*
  474. * Find the client's export entry matching fsid
  475. */
  476. static inline struct svc_expkey *
  477. exp_get_fsid_key(svc_client *clp, int fsid)
  478. {
  479. u32 fsidv[2];
  480. mk_fsid_v1(fsidv, fsid);
  481. return exp_find_key(clp, 1, fsidv, NULL);
  482. }
  483. svc_export *
  484. exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
  485. struct cache_req *reqp)
  486. {
  487. struct svc_export *exp, key;
  488. if (!clp)
  489. return NULL;
  490. key.ex_client = clp;
  491. key.ex_mnt = mnt;
  492. key.ex_dentry = dentry;
  493. exp = svc_export_lookup(&key, 0);
  494. if (exp != NULL)
  495. switch (cache_check(&svc_export_cache, &exp->h, reqp)) {
  496. case 0: break;
  497. case -EAGAIN:
  498. exp = ERR_PTR(-EAGAIN);
  499. break;
  500. default:
  501. exp = NULL;
  502. }
  503. return exp;
  504. }
  505. /*
  506. * Find the export entry for a given dentry.
  507. */
  508. struct svc_export *
  509. exp_parent(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry,
  510. struct cache_req *reqp)
  511. {
  512. svc_export *exp;
  513. dget(dentry);
  514. exp = exp_get_by_name(clp, mnt, dentry, reqp);
  515. while (exp == NULL && !IS_ROOT(dentry)) {
  516. struct dentry *parent;
  517. parent = dget_parent(dentry);
  518. dput(dentry);
  519. dentry = parent;
  520. exp = exp_get_by_name(clp, mnt, dentry, reqp);
  521. }
  522. dput(dentry);
  523. return exp;
  524. }
  525. /*
  526. * Hashtable locking. Write locks are placed only by user processes
  527. * wanting to modify export information.
  528. * Write locking only done in this file. Read locking
  529. * needed externally.
  530. */
  531. static DECLARE_RWSEM(hash_sem);
  532. void
  533. exp_readlock(void)
  534. {
  535. down_read(&hash_sem);
  536. }
  537. static inline void
  538. exp_writelock(void)
  539. {
  540. down_write(&hash_sem);
  541. }
  542. void
  543. exp_readunlock(void)
  544. {
  545. up_read(&hash_sem);
  546. }
  547. static inline void
  548. exp_writeunlock(void)
  549. {
  550. up_write(&hash_sem);
  551. }
  552. static void exp_fsid_unhash(struct svc_export *exp)
  553. {
  554. struct svc_expkey *ek;
  555. if ((exp->ex_flags & NFSEXP_FSID) == 0)
  556. return;
  557. ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
  558. if (ek && !IS_ERR(ek)) {
  559. ek->h.expiry_time = get_seconds()-1;
  560. expkey_put(&ek->h, &svc_expkey_cache);
  561. }
  562. svc_expkey_cache.nextcheck = get_seconds();
  563. }
  564. static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
  565. {
  566. u32 fsid[2];
  567. if ((exp->ex_flags & NFSEXP_FSID) == 0)
  568. return 0;
  569. mk_fsid_v1(fsid, exp->ex_fsid);
  570. return exp_set_key(clp, 1, fsid, exp);
  571. }
  572. static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
  573. {
  574. u32 fsid[2];
  575. struct inode *inode = exp->ex_dentry->d_inode;
  576. dev_t dev = inode->i_sb->s_dev;
  577. if (old_valid_dev(dev)) {
  578. mk_fsid_v0(fsid, dev, inode->i_ino);
  579. return exp_set_key(clp, 0, fsid, exp);
  580. }
  581. mk_fsid_v3(fsid, dev, inode->i_ino);
  582. return exp_set_key(clp, 3, fsid, exp);
  583. }
  584. static void exp_unhash(struct svc_export *exp)
  585. {
  586. struct svc_expkey *ek;
  587. struct inode *inode = exp->ex_dentry->d_inode;
  588. ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
  589. if (ek && !IS_ERR(ek)) {
  590. ek->h.expiry_time = get_seconds()-1;
  591. expkey_put(&ek->h, &svc_expkey_cache);
  592. }
  593. svc_expkey_cache.nextcheck = get_seconds();
  594. }
  595. /*
  596. * Export a file system.
  597. */
  598. int
  599. exp_export(struct nfsctl_export *nxp)
  600. {
  601. svc_client *clp;
  602. struct svc_export *exp = NULL;
  603. struct svc_export new;
  604. struct svc_expkey *fsid_key = NULL;
  605. struct nameidata nd;
  606. int err;
  607. /* Consistency check */
  608. err = -EINVAL;
  609. if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
  610. !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
  611. goto out;
  612. dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n",
  613. nxp->ex_client, nxp->ex_path,
  614. (unsigned)nxp->ex_dev, (long)nxp->ex_ino,
  615. nxp->ex_flags);
  616. /* Try to lock the export table for update */
  617. exp_writelock();
  618. /* Look up client info */
  619. if (!(clp = auth_domain_find(nxp->ex_client)))
  620. goto out_unlock;
  621. /* Look up the dentry */
  622. err = path_lookup(nxp->ex_path, 0, &nd);
  623. if (err)
  624. goto out_unlock;
  625. err = -EINVAL;
  626. exp = exp_get_by_name(clp, nd.mnt, nd.dentry, NULL);
  627. /* must make sure there won't be an ex_fsid clash */
  628. if ((nxp->ex_flags & NFSEXP_FSID) &&
  629. (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
  630. !IS_ERR(fsid_key) &&
  631. fsid_key->ek_export &&
  632. fsid_key->ek_export != exp)
  633. goto finish;
  634. if (exp) {
  635. /* just a flags/id/fsid update */
  636. exp_fsid_unhash(exp);
  637. exp->ex_flags = nxp->ex_flags;
  638. exp->ex_anon_uid = nxp->ex_anon_uid;
  639. exp->ex_anon_gid = nxp->ex_anon_gid;
  640. exp->ex_fsid = nxp->ex_dev;
  641. err = exp_fsid_hash(clp, exp);
  642. goto finish;
  643. }
  644. err = check_export(nd.dentry->d_inode, nxp->ex_flags);
  645. if (err) goto finish;
  646. err = -ENOMEM;
  647. dprintk("nfsd: creating export entry %p for client %p\n", exp, clp);
  648. new.h.expiry_time = NEVER;
  649. new.h.flags = 0;
  650. new.ex_client = clp;
  651. new.ex_mnt = nd.mnt;
  652. new.ex_dentry = nd.dentry;
  653. new.ex_flags = nxp->ex_flags;
  654. new.ex_anon_uid = nxp->ex_anon_uid;
  655. new.ex_anon_gid = nxp->ex_anon_gid;
  656. new.ex_fsid = nxp->ex_dev;
  657. exp = svc_export_lookup(&new, 1);
  658. if (exp == NULL)
  659. goto finish;
  660. err = 0;
  661. if (exp_hash(clp, exp) ||
  662. exp_fsid_hash(clp, exp)) {
  663. /* failed to create at least one index */
  664. exp_do_unexport(exp);
  665. cache_flush();
  666. err = -ENOMEM;
  667. }
  668. finish:
  669. if (exp)
  670. exp_put(exp);
  671. if (fsid_key && !IS_ERR(fsid_key))
  672. expkey_put(&fsid_key->h, &svc_expkey_cache);
  673. if (clp)
  674. auth_domain_put(clp);
  675. path_release(&nd);
  676. out_unlock:
  677. exp_writeunlock();
  678. out:
  679. return err;
  680. }
  681. /*
  682. * Unexport a file system. The export entry has already
  683. * been removed from the client's list of exported fs's.
  684. */
  685. static void
  686. exp_do_unexport(svc_export *unexp)
  687. {
  688. unexp->h.expiry_time = get_seconds()-1;
  689. svc_export_cache.nextcheck = get_seconds();
  690. exp_unhash(unexp);
  691. exp_fsid_unhash(unexp);
  692. }
  693. /*
  694. * unexport syscall.
  695. */
  696. int
  697. exp_unexport(struct nfsctl_export *nxp)
  698. {
  699. struct auth_domain *dom;
  700. svc_export *exp;
  701. struct nameidata nd;
  702. int err;
  703. /* Consistency check */
  704. if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
  705. !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
  706. return -EINVAL;
  707. exp_writelock();
  708. err = -EINVAL;
  709. dom = auth_domain_find(nxp->ex_client);
  710. if (!dom) {
  711. dprintk("nfsd: unexport couldn't find %s\n", nxp->ex_client);
  712. goto out_unlock;
  713. }
  714. err = path_lookup(nxp->ex_path, 0, &nd);
  715. if (err)
  716. goto out_domain;
  717. err = -EINVAL;
  718. exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL);
  719. path_release(&nd);
  720. if (!exp)
  721. goto out_domain;
  722. exp_do_unexport(exp);
  723. exp_put(exp);
  724. err = 0;
  725. out_domain:
  726. auth_domain_put(dom);
  727. cache_flush();
  728. out_unlock:
  729. exp_writeunlock();
  730. return err;
  731. }
  732. /*
  733. * Obtain the root fh on behalf of a client.
  734. * This could be done in user space, but I feel that it adds some safety
  735. * since its harder to fool a kernel module than a user space program.
  736. */
  737. int
  738. exp_rootfh(svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
  739. {
  740. struct svc_export *exp;
  741. struct nameidata nd;
  742. struct inode *inode;
  743. struct svc_fh fh;
  744. int err;
  745. err = -EPERM;
  746. /* NB: we probably ought to check that it's NUL-terminated */
  747. if (path_lookup(path, 0, &nd)) {
  748. printk("nfsd: exp_rootfh path not found %s", path);
  749. return err;
  750. }
  751. inode = nd.dentry->d_inode;
  752. dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n",
  753. path, nd.dentry, clp->name,
  754. inode->i_sb->s_id, inode->i_ino);
  755. exp = exp_parent(clp, nd.mnt, nd.dentry, NULL);
  756. if (!exp) {
  757. dprintk("nfsd: exp_rootfh export not found.\n");
  758. goto out;
  759. }
  760. /*
  761. * fh must be initialized before calling fh_compose
  762. */
  763. fh_init(&fh, maxsize);
  764. if (fh_compose(&fh, exp, nd.dentry, NULL))
  765. err = -EINVAL;
  766. else
  767. err = 0;
  768. memcpy(f, &fh.fh_handle, sizeof(struct knfsd_fh));
  769. fh_put(&fh);
  770. exp_put(exp);
  771. out:
  772. path_release(&nd);
  773. return err;
  774. }
  775. /*
  776. * Called when we need the filehandle for the root of the pseudofs,
  777. * for a given NFSv4 client. The root is defined to be the
  778. * export point with fsid==0
  779. */
  780. int
  781. exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
  782. struct cache_req *creq)
  783. {
  784. struct svc_expkey *fsid_key;
  785. int rv;
  786. u32 fsidv[2];
  787. mk_fsid_v1(fsidv, 0);
  788. fsid_key = exp_find_key(clp, 1, fsidv, creq);
  789. if (IS_ERR(fsid_key) && PTR_ERR(fsid_key) == -EAGAIN)
  790. return nfserr_dropit;
  791. if (!fsid_key || IS_ERR(fsid_key))
  792. return nfserr_perm;
  793. rv = fh_compose(fhp, fsid_key->ek_export,
  794. fsid_key->ek_export->ex_dentry, NULL);
  795. expkey_put(&fsid_key->h, &svc_expkey_cache);
  796. return rv;
  797. }
  798. /* Iterator */
  799. static void *e_start(struct seq_file *m, loff_t *pos)
  800. {
  801. loff_t n = *pos;
  802. unsigned hash, export;
  803. struct cache_head *ch;
  804. exp_readlock();
  805. read_lock(&svc_export_cache.hash_lock);
  806. if (!n--)
  807. return (void *)1;
  808. hash = n >> 32;
  809. export = n & ((1LL<<32) - 1);
  810. for (ch=export_table[hash]; ch; ch=ch->next)
  811. if (!export--)
  812. return ch;
  813. n &= ~((1LL<<32) - 1);
  814. do {
  815. hash++;
  816. n += 1LL<<32;
  817. } while(hash < EXPORT_HASHMAX && export_table[hash]==NULL);
  818. if (hash >= EXPORT_HASHMAX)
  819. return NULL;
  820. *pos = n+1;
  821. return export_table[hash];
  822. }
  823. static void *e_next(struct seq_file *m, void *p, loff_t *pos)
  824. {
  825. struct cache_head *ch = p;
  826. int hash = (*pos >> 32);
  827. if (p == (void *)1)
  828. hash = 0;
  829. else if (ch->next == NULL) {
  830. hash++;
  831. *pos += 1LL<<32;
  832. } else {
  833. ++*pos;
  834. return ch->next;
  835. }
  836. *pos &= ~((1LL<<32) - 1);
  837. while (hash < EXPORT_HASHMAX && export_table[hash] == NULL) {
  838. hash++;
  839. *pos += 1LL<<32;
  840. }
  841. if (hash >= EXPORT_HASHMAX)
  842. return NULL;
  843. ++*pos;
  844. return export_table[hash];
  845. }
  846. static void e_stop(struct seq_file *m, void *p)
  847. {
  848. read_unlock(&svc_export_cache.hash_lock);
  849. exp_readunlock();
  850. }
  851. static struct flags {
  852. int flag;
  853. char *name[2];
  854. } expflags[] = {
  855. { NFSEXP_READONLY, {"ro", "rw"}},
  856. { NFSEXP_INSECURE_PORT, {"insecure", ""}},
  857. { NFSEXP_ROOTSQUASH, {"root_squash", "no_root_squash"}},
  858. { NFSEXP_ALLSQUASH, {"all_squash", ""}},
  859. { NFSEXP_ASYNC, {"async", "sync"}},
  860. { NFSEXP_GATHERED_WRITES, {"wdelay", "no_wdelay"}},
  861. { NFSEXP_NOHIDE, {"nohide", ""}},
  862. { NFSEXP_CROSSMOUNT, {"crossmnt", ""}},
  863. { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
  864. { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
  865. #ifdef MSNFS
  866. { NFSEXP_MSNFS, {"msnfs", ""}},
  867. #endif
  868. { 0, {"", ""}}
  869. };
  870. static void exp_flags(struct seq_file *m, int flag, int fsid, uid_t anonu, uid_t anong)
  871. {
  872. int first = 0;
  873. struct flags *flg;
  874. for (flg = expflags; flg->flag; flg++) {
  875. int state = (flg->flag & flag)?0:1;
  876. if (*flg->name[state])
  877. seq_printf(m, "%s%s", first++?",":"", flg->name[state]);
  878. }
  879. if (flag & NFSEXP_FSID)
  880. seq_printf(m, "%sfsid=%d", first++?",":"", fsid);
  881. if (anonu != (uid_t)-2 && anonu != (0x10000-2))
  882. seq_printf(m, "%sanonuid=%d", first++?",":"", anonu);
  883. if (anong != (gid_t)-2 && anong != (0x10000-2))
  884. seq_printf(m, "%sanongid=%d", first++?",":"", anong);
  885. }
  886. static int e_show(struct seq_file *m, void *p)
  887. {
  888. struct cache_head *cp = p;
  889. struct svc_export *exp = container_of(cp, struct svc_export, h);
  890. svc_client *clp;
  891. if (p == (void *)1) {
  892. seq_puts(m, "# Version 1.1\n");
  893. seq_puts(m, "# Path Client(Flags) # IPs\n");
  894. return 0;
  895. }
  896. clp = exp->ex_client;
  897. cache_get(&exp->h);
  898. if (cache_check(&svc_export_cache, &exp->h, NULL))
  899. return 0;
  900. if (cache_put(&exp->h, &svc_export_cache)) BUG();
  901. return svc_export_show(m, &svc_export_cache, cp);
  902. }
  903. struct seq_operations nfs_exports_op = {
  904. .start = e_start,
  905. .next = e_next,
  906. .stop = e_stop,
  907. .show = e_show,
  908. };
  909. /*
  910. * Add or modify a client.
  911. * Change requests may involve the list of host addresses. The list of
  912. * exports and possibly existing uid maps are left untouched.
  913. */
  914. int
  915. exp_addclient(struct nfsctl_client *ncp)
  916. {
  917. struct auth_domain *dom;
  918. int i, err;
  919. /* First, consistency check. */
  920. err = -EINVAL;
  921. if (! exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
  922. goto out;
  923. if (ncp->cl_naddr > NFSCLNT_ADDRMAX)
  924. goto out;
  925. /* Lock the hashtable */
  926. exp_writelock();
  927. dom = unix_domain_find(ncp->cl_ident);
  928. err = -ENOMEM;
  929. if (!dom)
  930. goto out_unlock;
  931. /* Insert client into hashtable. */
  932. for (i = 0; i < ncp->cl_naddr; i++)
  933. auth_unix_add_addr(ncp->cl_addrlist[i], dom);
  934. auth_unix_forget_old(dom);
  935. auth_domain_put(dom);
  936. err = 0;
  937. out_unlock:
  938. exp_writeunlock();
  939. out:
  940. return err;
  941. }
  942. /*
  943. * Delete a client given an identifier.
  944. */
  945. int
  946. exp_delclient(struct nfsctl_client *ncp)
  947. {
  948. int err;
  949. struct auth_domain *dom;
  950. err = -EINVAL;
  951. if (!exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
  952. goto out;
  953. /* Lock the hashtable */
  954. exp_writelock();
  955. dom = auth_domain_find(ncp->cl_ident);
  956. /* just make sure that no addresses work
  957. * and that it will expire soon
  958. */
  959. if (dom) {
  960. err = auth_unix_forget_old(dom);
  961. dom->h.expiry_time = get_seconds();
  962. auth_domain_put(dom);
  963. }
  964. exp_writeunlock();
  965. out:
  966. return err;
  967. }
  968. /*
  969. * Verify that string is non-empty and does not exceed max length.
  970. */
  971. static int
  972. exp_verify_string(char *cp, int max)
  973. {
  974. int i;
  975. for (i = 0; i < max; i++)
  976. if (!cp[i])
  977. return i;
  978. cp[i] = 0;
  979. printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp);
  980. return 0;
  981. }
  982. /*
  983. * Initialize the exports module.
  984. */
  985. void
  986. nfsd_export_init(void)
  987. {
  988. dprintk("nfsd: initializing export module.\n");
  989. cache_register(&svc_export_cache);
  990. cache_register(&svc_expkey_cache);
  991. }
  992. /*
  993. * Flush exports table - called when last nfsd thread is killed
  994. */
  995. void
  996. nfsd_export_flush(void)
  997. {
  998. exp_writelock();
  999. cache_purge(&svc_expkey_cache);
  1000. cache_purge(&svc_export_cache);
  1001. exp_writeunlock();
  1002. }
  1003. /*
  1004. * Shutdown the exports module.
  1005. */
  1006. void
  1007. nfsd_export_shutdown(void)
  1008. {
  1009. dprintk("nfsd: shutting down export module.\n");
  1010. exp_writelock();
  1011. if (cache_unregister(&svc_expkey_cache))
  1012. printk(KERN_ERR "nfsd: failed to unregister expkey cache\n");
  1013. if (cache_unregister(&svc_export_cache))
  1014. printk(KERN_ERR "nfsd: failed to unregister export cache\n");
  1015. svcauth_unix_purge();
  1016. exp_writeunlock();
  1017. dprintk("nfsd: export shutdown complete.\n");
  1018. }