export.c 26 KB

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