nfsfh.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. /*
  2. * linux/fs/nfsd/nfsfh.c
  3. *
  4. * NFS server file handle treatment.
  5. *
  6. * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  7. * Portions Copyright (C) 1999 G. Allen Morris III <gam3@acm.org>
  8. * Extensive rewrite by Neil Brown <neilb@cse.unsw.edu.au> Southern-Spring 1999
  9. * ... and again Southern-Winter 2001 to support export_operations
  10. */
  11. #include <linux/sched.h>
  12. #include <linux/slab.h>
  13. #include <linux/smp_lock.h>
  14. #include <linux/fs.h>
  15. #include <linux/unistd.h>
  16. #include <linux/string.h>
  17. #include <linux/stat.h>
  18. #include <linux/dcache.h>
  19. #include <linux/mount.h>
  20. #include <asm/pgtable.h>
  21. #include <linux/sunrpc/clnt.h>
  22. #include <linux/sunrpc/svc.h>
  23. #include <linux/nfsd/nfsd.h>
  24. #define NFSDDBG_FACILITY NFSDDBG_FH
  25. static int nfsd_nr_verified;
  26. static int nfsd_nr_put;
  27. extern struct export_operations export_op_default;
  28. #define CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
  29. /*
  30. * our acceptability function.
  31. * if NOSUBTREECHECK, accept anything
  32. * if not, require that we can walk up to exp->ex_dentry
  33. * doing some checks on the 'x' bits
  34. */
  35. static int nfsd_acceptable(void *expv, struct dentry *dentry)
  36. {
  37. struct svc_export *exp = expv;
  38. int rv;
  39. struct dentry *tdentry;
  40. struct dentry *parent;
  41. if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
  42. return 1;
  43. tdentry = dget(dentry);
  44. while (tdentry != exp->ex_dentry && ! IS_ROOT(tdentry)) {
  45. /* make sure parents give x permission to user */
  46. int err;
  47. parent = dget_parent(tdentry);
  48. err = permission(parent->d_inode, MAY_EXEC, NULL);
  49. if (err < 0) {
  50. dput(parent);
  51. break;
  52. }
  53. dput(tdentry);
  54. tdentry = parent;
  55. }
  56. if (tdentry != exp->ex_dentry)
  57. dprintk("nfsd_acceptable failed at %p %s\n", tdentry, tdentry->d_name.name);
  58. rv = (tdentry == exp->ex_dentry);
  59. dput(tdentry);
  60. return rv;
  61. }
  62. /* Type check. The correct error return for type mismatches does not seem to be
  63. * generally agreed upon. SunOS seems to use EISDIR if file isn't S_IFREG; a
  64. * comment in the NFSv3 spec says this is incorrect (implementation notes for
  65. * the write call).
  66. */
  67. static inline __be32
  68. nfsd_mode_check(struct svc_rqst *rqstp, umode_t mode, int type)
  69. {
  70. /* Type can be negative when creating hardlinks - not to a dir */
  71. if (type > 0 && (mode & S_IFMT) != type) {
  72. if (rqstp->rq_vers == 4 && (mode & S_IFMT) == S_IFLNK)
  73. return nfserr_symlink;
  74. else if (type == S_IFDIR)
  75. return nfserr_notdir;
  76. else if ((mode & S_IFMT) == S_IFDIR)
  77. return nfserr_isdir;
  78. else
  79. return nfserr_inval;
  80. }
  81. if (type < 0 && (mode & S_IFMT) == -type) {
  82. if (rqstp->rq_vers == 4 && (mode & S_IFMT) == S_IFLNK)
  83. return nfserr_symlink;
  84. else if (type == -S_IFDIR)
  85. return nfserr_isdir;
  86. else
  87. return nfserr_notdir;
  88. }
  89. return 0;
  90. }
  91. /*
  92. * Perform sanity checks on the dentry in a client's file handle.
  93. *
  94. * Note that the file handle dentry may need to be freed even after
  95. * an error return.
  96. *
  97. * This is only called at the start of an nfsproc call, so fhp points to
  98. * a svc_fh which is all 0 except for the over-the-wire file handle.
  99. */
  100. __be32
  101. fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
  102. {
  103. struct knfsd_fh *fh = &fhp->fh_handle;
  104. struct svc_export *exp = NULL;
  105. struct dentry *dentry;
  106. __be32 error = 0;
  107. dprintk("nfsd: fh_verify(%s)\n", SVCFH_fmt(fhp));
  108. if (!fhp->fh_dentry) {
  109. __u32 *datap=NULL;
  110. __u32 tfh[3]; /* filehandle fragment for oldstyle filehandles */
  111. int fileid_type;
  112. int data_left = fh->fh_size/4;
  113. error = nfserr_stale;
  114. if (rqstp->rq_client == NULL)
  115. goto out;
  116. if (rqstp->rq_vers > 2)
  117. error = nfserr_badhandle;
  118. if (rqstp->rq_vers == 4 && fh->fh_size == 0)
  119. return nfserr_nofilehandle;
  120. if (fh->fh_version == 1) {
  121. int len;
  122. datap = fh->fh_auth;
  123. if (--data_left<0) goto out;
  124. switch (fh->fh_auth_type) {
  125. case 0: break;
  126. default: goto out;
  127. }
  128. len = key_len(fh->fh_fsid_type) / 4;
  129. if (len == 0) goto out;
  130. if (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
  131. /* deprecated, convert to type 3 */
  132. len = key_len(FSID_ENCODE_DEV)/4;
  133. fh->fh_fsid_type = FSID_ENCODE_DEV;
  134. fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl(fh->fh_fsid[0]), ntohl(fh->fh_fsid[1])));
  135. fh->fh_fsid[1] = fh->fh_fsid[2];
  136. }
  137. if ((data_left -= len)<0) goto out;
  138. exp = exp_find(rqstp->rq_client, fh->fh_fsid_type, datap, &rqstp->rq_chandle);
  139. datap += len;
  140. } else {
  141. dev_t xdev;
  142. ino_t xino;
  143. if (fh->fh_size != NFS_FHSIZE)
  144. goto out;
  145. /* assume old filehandle format */
  146. xdev = old_decode_dev(fh->ofh_xdev);
  147. xino = u32_to_ino_t(fh->ofh_xino);
  148. mk_fsid(FSID_DEV, tfh, xdev, xino, 0, NULL);
  149. exp = exp_find(rqstp->rq_client, FSID_DEV, tfh,
  150. &rqstp->rq_chandle);
  151. }
  152. if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
  153. || PTR_ERR(exp) == -ETIMEDOUT)) {
  154. error = nfserrno(PTR_ERR(exp));
  155. goto out;
  156. }
  157. error = nfserr_stale;
  158. if (!exp || IS_ERR(exp))
  159. goto out;
  160. /* Check if the request originated from a secure port. */
  161. error = nfserr_perm;
  162. if (!rqstp->rq_secure && EX_SECURE(exp)) {
  163. char buf[RPC_MAX_ADDRBUFLEN];
  164. printk(KERN_WARNING
  165. "nfsd: request from insecure port %s!\n",
  166. svc_print_addr(rqstp, buf, sizeof(buf)));
  167. goto out;
  168. }
  169. /* Set user creds for this exportpoint */
  170. error = nfserrno(nfsd_setuser(rqstp, exp));
  171. if (error)
  172. goto out;
  173. /*
  174. * Look up the dentry using the NFS file handle.
  175. */
  176. error = nfserr_stale;
  177. if (rqstp->rq_vers > 2)
  178. error = nfserr_badhandle;
  179. if (fh->fh_version != 1) {
  180. tfh[0] = fh->ofh_ino;
  181. tfh[1] = fh->ofh_generation;
  182. tfh[2] = fh->ofh_dirino;
  183. datap = tfh;
  184. data_left = 3;
  185. if (fh->ofh_dirino == 0)
  186. fileid_type = 1;
  187. else
  188. fileid_type = 2;
  189. } else
  190. fileid_type = fh->fh_fileid_type;
  191. if (fileid_type == 0)
  192. dentry = dget(exp->ex_dentry);
  193. else {
  194. struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
  195. dentry = CALL(nop,decode_fh)(exp->ex_mnt->mnt_sb,
  196. datap, data_left,
  197. fileid_type,
  198. nfsd_acceptable, exp);
  199. }
  200. if (dentry == NULL)
  201. goto out;
  202. if (IS_ERR(dentry)) {
  203. if (PTR_ERR(dentry) != -EINVAL)
  204. error = nfserrno(PTR_ERR(dentry));
  205. goto out;
  206. }
  207. if (S_ISDIR(dentry->d_inode->i_mode) &&
  208. (dentry->d_flags & DCACHE_DISCONNECTED)) {
  209. printk("nfsd: find_fh_dentry returned a DISCONNECTED directory: %s/%s\n",
  210. dentry->d_parent->d_name.name, dentry->d_name.name);
  211. }
  212. fhp->fh_dentry = dentry;
  213. fhp->fh_export = exp;
  214. nfsd_nr_verified++;
  215. } else {
  216. /* just rechecking permissions
  217. * (e.g. nfsproc_create calls fh_verify, then nfsd_create does as well)
  218. */
  219. dprintk("nfsd: fh_verify - just checking\n");
  220. dentry = fhp->fh_dentry;
  221. exp = fhp->fh_export;
  222. /* Set user creds for this exportpoint; necessary even
  223. * in the "just checking" case because this may be a
  224. * filehandle that was created by fh_compose, and that
  225. * is about to be used in another nfsv4 compound
  226. * operation */
  227. error = nfserrno(nfsd_setuser(rqstp, exp));
  228. if (error)
  229. goto out;
  230. }
  231. cache_get(&exp->h);
  232. error = nfsd_mode_check(rqstp, dentry->d_inode->i_mode, type);
  233. if (error)
  234. goto out;
  235. /* Finally, check access permissions. */
  236. error = nfsd_permission(exp, dentry, access);
  237. if (error) {
  238. dprintk("fh_verify: %s/%s permission failure, "
  239. "acc=%x, error=%d\n",
  240. dentry->d_parent->d_name.name,
  241. dentry->d_name.name,
  242. access, ntohl(error));
  243. }
  244. out:
  245. if (exp && !IS_ERR(exp))
  246. exp_put(exp);
  247. if (error == nfserr_stale)
  248. nfsdstats.fh_stale++;
  249. return error;
  250. }
  251. /*
  252. * Compose a file handle for an NFS reply.
  253. *
  254. * Note that when first composed, the dentry may not yet have
  255. * an inode. In this case a call to fh_update should be made
  256. * before the fh goes out on the wire ...
  257. */
  258. static inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
  259. __u32 *datap, int *maxsize)
  260. {
  261. struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
  262. if (dentry == exp->ex_dentry) {
  263. *maxsize = 0;
  264. return 0;
  265. }
  266. return CALL(nop,encode_fh)(dentry, datap, maxsize,
  267. !(exp->ex_flags&NFSEXP_NOSUBTREECHECK));
  268. }
  269. /*
  270. * for composing old style file handles
  271. */
  272. static inline void _fh_update_old(struct dentry *dentry,
  273. struct svc_export *exp,
  274. struct knfsd_fh *fh)
  275. {
  276. fh->ofh_ino = ino_t_to_u32(dentry->d_inode->i_ino);
  277. fh->ofh_generation = dentry->d_inode->i_generation;
  278. if (S_ISDIR(dentry->d_inode->i_mode) ||
  279. (exp->ex_flags & NFSEXP_NOSUBTREECHECK))
  280. fh->ofh_dirino = 0;
  281. }
  282. __be32
  283. fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
  284. struct svc_fh *ref_fh)
  285. {
  286. /* ref_fh is a reference file handle.
  287. * if it is non-null and for the same filesystem, then we should compose
  288. * a filehandle which is of the same version, where possible.
  289. * Currently, that means that if ref_fh->fh_handle.fh_version == 0xca
  290. * Then create a 32byte filehandle using nfs_fhbase_old
  291. *
  292. */
  293. u8 version = 1;
  294. u8 fsid_type = 0;
  295. struct inode * inode = dentry->d_inode;
  296. struct dentry *parent = dentry->d_parent;
  297. __u32 *datap;
  298. dev_t ex_dev = exp->ex_dentry->d_inode->i_sb->s_dev;
  299. int root_export = (exp->ex_dentry == exp->ex_dentry->d_sb->s_root);
  300. dprintk("nfsd: fh_compose(exp %02x:%02x/%ld %s/%s, ino=%ld)\n",
  301. MAJOR(ex_dev), MINOR(ex_dev),
  302. (long) exp->ex_dentry->d_inode->i_ino,
  303. parent->d_name.name, dentry->d_name.name,
  304. (inode ? inode->i_ino : 0));
  305. /* Choose filehandle version and fsid type based on
  306. * the reference filehandle (if it is in the same export)
  307. * or the export options.
  308. */
  309. if (ref_fh && ref_fh->fh_export == exp) {
  310. version = ref_fh->fh_handle.fh_version;
  311. if (version == 0xca)
  312. fsid_type = FSID_DEV;
  313. else
  314. fsid_type = ref_fh->fh_handle.fh_fsid_type;
  315. /* We know this version/type works for this export
  316. * so there is no need for further checks.
  317. */
  318. } else if (exp->ex_uuid) {
  319. if (fhp->fh_maxsize >= 64) {
  320. if (root_export)
  321. fsid_type = FSID_UUID16;
  322. else
  323. fsid_type = FSID_UUID16_INUM;
  324. } else {
  325. if (root_export)
  326. fsid_type = FSID_UUID8;
  327. else
  328. fsid_type = FSID_UUID4_INUM;
  329. }
  330. } else if (exp->ex_flags & NFSEXP_FSID)
  331. fsid_type = FSID_NUM;
  332. else if (!old_valid_dev(ex_dev))
  333. /* for newer device numbers, we must use a newer fsid format */
  334. fsid_type = FSID_ENCODE_DEV;
  335. else
  336. fsid_type = FSID_DEV;
  337. if (ref_fh == fhp)
  338. fh_put(ref_fh);
  339. if (fhp->fh_locked || fhp->fh_dentry) {
  340. printk(KERN_ERR "fh_compose: fh %s/%s not initialized!\n",
  341. parent->d_name.name, dentry->d_name.name);
  342. }
  343. if (fhp->fh_maxsize < NFS_FHSIZE)
  344. printk(KERN_ERR "fh_compose: called with maxsize %d! %s/%s\n",
  345. fhp->fh_maxsize,
  346. parent->d_name.name, dentry->d_name.name);
  347. fhp->fh_dentry = dget(dentry); /* our internal copy */
  348. fhp->fh_export = exp;
  349. cache_get(&exp->h);
  350. if (version == 0xca) {
  351. /* old style filehandle please */
  352. memset(&fhp->fh_handle.fh_base, 0, NFS_FHSIZE);
  353. fhp->fh_handle.fh_size = NFS_FHSIZE;
  354. fhp->fh_handle.ofh_dcookie = 0xfeebbaca;
  355. fhp->fh_handle.ofh_dev = old_encode_dev(ex_dev);
  356. fhp->fh_handle.ofh_xdev = fhp->fh_handle.ofh_dev;
  357. fhp->fh_handle.ofh_xino =
  358. ino_t_to_u32(exp->ex_dentry->d_inode->i_ino);
  359. fhp->fh_handle.ofh_dirino = ino_t_to_u32(parent_ino(dentry));
  360. if (inode)
  361. _fh_update_old(dentry, exp, &fhp->fh_handle);
  362. } else {
  363. int len;
  364. fhp->fh_handle.fh_version = 1;
  365. fhp->fh_handle.fh_auth_type = 0;
  366. datap = fhp->fh_handle.fh_auth+0;
  367. fhp->fh_handle.fh_fsid_type = fsid_type;
  368. mk_fsid(fsid_type, datap, ex_dev,
  369. exp->ex_dentry->d_inode->i_ino,
  370. exp->ex_fsid, exp->ex_uuid);
  371. len = key_len(fsid_type);
  372. datap += len/4;
  373. fhp->fh_handle.fh_size = 4 + len;
  374. if (inode) {
  375. int size = (fhp->fh_maxsize-len-4)/4;
  376. fhp->fh_handle.fh_fileid_type =
  377. _fh_update(dentry, exp, datap, &size);
  378. fhp->fh_handle.fh_size += size*4;
  379. }
  380. if (fhp->fh_handle.fh_fileid_type == 255)
  381. return nfserr_opnotsupp;
  382. }
  383. nfsd_nr_verified++;
  384. return 0;
  385. }
  386. /*
  387. * Update file handle information after changing a dentry.
  388. * This is only called by nfsd_create, nfsd_create_v3 and nfsd_proc_create
  389. */
  390. __be32
  391. fh_update(struct svc_fh *fhp)
  392. {
  393. struct dentry *dentry;
  394. __u32 *datap;
  395. if (!fhp->fh_dentry)
  396. goto out_bad;
  397. dentry = fhp->fh_dentry;
  398. if (!dentry->d_inode)
  399. goto out_negative;
  400. if (fhp->fh_handle.fh_version != 1) {
  401. _fh_update_old(dentry, fhp->fh_export, &fhp->fh_handle);
  402. } else {
  403. int size;
  404. if (fhp->fh_handle.fh_fileid_type != 0)
  405. goto out;
  406. datap = fhp->fh_handle.fh_auth+
  407. fhp->fh_handle.fh_size/4 -1;
  408. size = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
  409. fhp->fh_handle.fh_fileid_type =
  410. _fh_update(dentry, fhp->fh_export, datap, &size);
  411. fhp->fh_handle.fh_size += size*4;
  412. if (fhp->fh_handle.fh_fileid_type == 255)
  413. return nfserr_opnotsupp;
  414. }
  415. out:
  416. return 0;
  417. out_bad:
  418. printk(KERN_ERR "fh_update: fh not verified!\n");
  419. goto out;
  420. out_negative:
  421. printk(KERN_ERR "fh_update: %s/%s still negative!\n",
  422. dentry->d_parent->d_name.name, dentry->d_name.name);
  423. goto out;
  424. }
  425. /*
  426. * Release a file handle.
  427. */
  428. void
  429. fh_put(struct svc_fh *fhp)
  430. {
  431. struct dentry * dentry = fhp->fh_dentry;
  432. struct svc_export * exp = fhp->fh_export;
  433. if (dentry) {
  434. fh_unlock(fhp);
  435. fhp->fh_dentry = NULL;
  436. dput(dentry);
  437. #ifdef CONFIG_NFSD_V3
  438. fhp->fh_pre_saved = 0;
  439. fhp->fh_post_saved = 0;
  440. #endif
  441. nfsd_nr_put++;
  442. }
  443. if (exp) {
  444. cache_put(&exp->h, &svc_export_cache);
  445. fhp->fh_export = NULL;
  446. }
  447. return;
  448. }
  449. /*
  450. * Shorthand for dprintk()'s
  451. */
  452. char * SVCFH_fmt(struct svc_fh *fhp)
  453. {
  454. struct knfsd_fh *fh = &fhp->fh_handle;
  455. static char buf[80];
  456. sprintf(buf, "%d: %08x %08x %08x %08x %08x %08x",
  457. fh->fh_size,
  458. fh->fh_base.fh_pad[0],
  459. fh->fh_base.fh_pad[1],
  460. fh->fh_base.fh_pad[2],
  461. fh->fh_base.fh_pad[3],
  462. fh->fh_base.fh_pad[4],
  463. fh->fh_base.fh_pad[5]);
  464. return buf;
  465. }
  466. enum fsid_source fsid_source(struct svc_fh *fhp)
  467. {
  468. if (fhp->fh_handle.fh_version != 1)
  469. return FSIDSOURCE_DEV;
  470. switch(fhp->fh_handle.fh_fsid_type) {
  471. case FSID_DEV:
  472. case FSID_ENCODE_DEV:
  473. case FSID_MAJOR_MINOR:
  474. return FSIDSOURCE_DEV;
  475. case FSID_NUM:
  476. return FSIDSOURCE_FSID;
  477. default:
  478. if (fhp->fh_export->ex_flags & NFSEXP_FSID)
  479. return FSIDSOURCE_FSID;
  480. else
  481. return FSIDSOURCE_UUID;
  482. }
  483. }