export.c 26 KB

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