xfs_handle.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (c) 2000-2005 Silicon Graphics, Inc.
  4. * Copyright (c) 2022-2024 Oracle.
  5. * All rights reserved.
  6. */
  7. #include "xfs.h"
  8. #include "xfs_fs.h"
  9. #include "xfs_format.h"
  10. #include "xfs_log_format.h"
  11. #include "xfs_shared.h"
  12. #include "xfs_trans_resv.h"
  13. #include "xfs_mount.h"
  14. #include "xfs_bmap_btree.h"
  15. #include "xfs_inode.h"
  16. #include "xfs_error.h"
  17. #include "xfs_trace.h"
  18. #include "xfs_trans.h"
  19. #include "xfs_da_format.h"
  20. #include "xfs_da_btree.h"
  21. #include "xfs_attr.h"
  22. #include "xfs_ioctl.h"
  23. #include "xfs_parent.h"
  24. #include "xfs_handle.h"
  25. #include "xfs_health.h"
  26. #include "xfs_icache.h"
  27. #include "xfs_export.h"
  28. #include "xfs_xattr.h"
  29. #include "xfs_acl.h"
  30. #include <linux/namei.h>
  31. static inline size_t
  32. xfs_filehandle_fid_len(void)
  33. {
  34. struct xfs_handle *handle = NULL;
  35. return sizeof(struct xfs_fid) - sizeof(handle->ha_fid.fid_len);
  36. }
  37. static inline size_t
  38. xfs_filehandle_init(
  39. struct xfs_mount *mp,
  40. xfs_ino_t ino,
  41. uint32_t gen,
  42. struct xfs_handle *handle)
  43. {
  44. memcpy(&handle->ha_fsid, mp->m_fixedfsid, sizeof(struct xfs_fsid));
  45. handle->ha_fid.fid_len = xfs_filehandle_fid_len();
  46. handle->ha_fid.fid_pad = 0;
  47. handle->ha_fid.fid_gen = gen;
  48. handle->ha_fid.fid_ino = ino;
  49. return sizeof(struct xfs_handle);
  50. }
  51. static inline size_t
  52. xfs_fshandle_init(
  53. struct xfs_mount *mp,
  54. struct xfs_handle *handle)
  55. {
  56. memcpy(&handle->ha_fsid, mp->m_fixedfsid, sizeof(struct xfs_fsid));
  57. memset(&handle->ha_fid, 0, sizeof(handle->ha_fid));
  58. return sizeof(struct xfs_fsid);
  59. }
  60. /*
  61. * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to
  62. * a file or fs handle.
  63. *
  64. * XFS_IOC_PATH_TO_FSHANDLE
  65. * returns fs handle for a mount point or path within that mount point
  66. * XFS_IOC_FD_TO_HANDLE
  67. * returns full handle for a FD opened in user space
  68. * XFS_IOC_PATH_TO_HANDLE
  69. * returns full handle for a path
  70. */
  71. int
  72. xfs_find_handle(
  73. unsigned int cmd,
  74. xfs_fsop_handlereq_t *hreq)
  75. {
  76. int hsize;
  77. xfs_handle_t handle;
  78. struct inode *inode;
  79. struct fd f = EMPTY_FD;
  80. struct path path;
  81. int error;
  82. struct xfs_inode *ip;
  83. if (cmd == XFS_IOC_FD_TO_HANDLE) {
  84. f = fdget(hreq->fd);
  85. if (!fd_file(f))
  86. return -EBADF;
  87. inode = file_inode(fd_file(f));
  88. } else {
  89. error = user_path_at(AT_FDCWD, hreq->path, 0, &path);
  90. if (error)
  91. return error;
  92. inode = d_inode(path.dentry);
  93. }
  94. ip = XFS_I(inode);
  95. /*
  96. * We can only generate handles for inodes residing on a XFS filesystem,
  97. * and only for regular files, directories or symbolic links.
  98. */
  99. error = -EINVAL;
  100. if (inode->i_sb->s_magic != XFS_SB_MAGIC)
  101. goto out_put;
  102. error = -EBADF;
  103. if (!S_ISREG(inode->i_mode) &&
  104. !S_ISDIR(inode->i_mode) &&
  105. !S_ISLNK(inode->i_mode))
  106. goto out_put;
  107. memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t));
  108. if (cmd == XFS_IOC_PATH_TO_FSHANDLE)
  109. hsize = xfs_fshandle_init(ip->i_mount, &handle);
  110. else
  111. hsize = xfs_filehandle_init(ip->i_mount, ip->i_ino,
  112. inode->i_generation, &handle);
  113. error = -EFAULT;
  114. if (copy_to_user(hreq->ohandle, &handle, hsize) ||
  115. copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32)))
  116. goto out_put;
  117. error = 0;
  118. out_put:
  119. if (cmd == XFS_IOC_FD_TO_HANDLE)
  120. fdput(f);
  121. else
  122. path_put(&path);
  123. return error;
  124. }
  125. /*
  126. * No need to do permission checks on the various pathname components
  127. * as the handle operations are privileged.
  128. */
  129. STATIC int
  130. xfs_handle_acceptable(
  131. void *context,
  132. struct dentry *dentry)
  133. {
  134. return 1;
  135. }
  136. /* Convert handle already copied to kernel space into a dentry. */
  137. static struct dentry *
  138. xfs_khandle_to_dentry(
  139. struct file *file,
  140. struct xfs_handle *handle)
  141. {
  142. struct xfs_fid64 fid = {
  143. .ino = handle->ha_fid.fid_ino,
  144. .gen = handle->ha_fid.fid_gen,
  145. };
  146. /*
  147. * Only allow handle opens under a directory.
  148. */
  149. if (!S_ISDIR(file_inode(file)->i_mode))
  150. return ERR_PTR(-ENOTDIR);
  151. if (handle->ha_fid.fid_len != xfs_filehandle_fid_len())
  152. return ERR_PTR(-EINVAL);
  153. return exportfs_decode_fh(file->f_path.mnt, (struct fid *)&fid, 3,
  154. FILEID_INO32_GEN | XFS_FILEID_TYPE_64FLAG,
  155. xfs_handle_acceptable, NULL);
  156. }
  157. /* Convert handle already copied to kernel space into an xfs_inode. */
  158. static struct xfs_inode *
  159. xfs_khandle_to_inode(
  160. struct file *file,
  161. struct xfs_handle *handle)
  162. {
  163. struct xfs_inode *ip = XFS_I(file_inode(file));
  164. struct xfs_mount *mp = ip->i_mount;
  165. struct inode *inode;
  166. if (!S_ISDIR(VFS_I(ip)->i_mode))
  167. return ERR_PTR(-ENOTDIR);
  168. if (handle->ha_fid.fid_len != xfs_filehandle_fid_len())
  169. return ERR_PTR(-EINVAL);
  170. inode = xfs_nfs_get_inode(mp->m_super, handle->ha_fid.fid_ino,
  171. handle->ha_fid.fid_gen);
  172. if (IS_ERR(inode))
  173. return ERR_CAST(inode);
  174. return XFS_I(inode);
  175. }
  176. /*
  177. * Convert userspace handle data into a dentry.
  178. */
  179. struct dentry *
  180. xfs_handle_to_dentry(
  181. struct file *parfilp,
  182. void __user *uhandle,
  183. u32 hlen)
  184. {
  185. xfs_handle_t handle;
  186. if (hlen != sizeof(xfs_handle_t))
  187. return ERR_PTR(-EINVAL);
  188. if (copy_from_user(&handle, uhandle, hlen))
  189. return ERR_PTR(-EFAULT);
  190. return xfs_khandle_to_dentry(parfilp, &handle);
  191. }
  192. STATIC struct dentry *
  193. xfs_handlereq_to_dentry(
  194. struct file *parfilp,
  195. xfs_fsop_handlereq_t *hreq)
  196. {
  197. return xfs_handle_to_dentry(parfilp, hreq->ihandle, hreq->ihandlen);
  198. }
  199. int
  200. xfs_open_by_handle(
  201. struct file *parfilp,
  202. xfs_fsop_handlereq_t *hreq)
  203. {
  204. const struct cred *cred = current_cred();
  205. int error;
  206. int fd;
  207. int permflag;
  208. struct file *filp;
  209. struct inode *inode;
  210. struct dentry *dentry;
  211. fmode_t fmode;
  212. struct path path;
  213. if (!capable(CAP_SYS_ADMIN))
  214. return -EPERM;
  215. dentry = xfs_handlereq_to_dentry(parfilp, hreq);
  216. if (IS_ERR(dentry))
  217. return PTR_ERR(dentry);
  218. inode = d_inode(dentry);
  219. /* Restrict xfs_open_by_handle to directories & regular files. */
  220. if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) {
  221. error = -EPERM;
  222. goto out_dput;
  223. }
  224. #if BITS_PER_LONG != 32
  225. hreq->oflags |= O_LARGEFILE;
  226. #endif
  227. permflag = hreq->oflags;
  228. fmode = OPEN_FMODE(permflag);
  229. if ((!(permflag & O_APPEND) || (permflag & O_TRUNC)) &&
  230. (fmode & FMODE_WRITE) && IS_APPEND(inode)) {
  231. error = -EPERM;
  232. goto out_dput;
  233. }
  234. if ((fmode & FMODE_WRITE) && IS_IMMUTABLE(inode)) {
  235. error = -EPERM;
  236. goto out_dput;
  237. }
  238. /* Can't write directories. */
  239. if (S_ISDIR(inode->i_mode) && (fmode & FMODE_WRITE)) {
  240. error = -EISDIR;
  241. goto out_dput;
  242. }
  243. fd = get_unused_fd_flags(0);
  244. if (fd < 0) {
  245. error = fd;
  246. goto out_dput;
  247. }
  248. path.mnt = parfilp->f_path.mnt;
  249. path.dentry = dentry;
  250. filp = dentry_open(&path, hreq->oflags, cred);
  251. dput(dentry);
  252. if (IS_ERR(filp)) {
  253. put_unused_fd(fd);
  254. return PTR_ERR(filp);
  255. }
  256. if (S_ISREG(inode->i_mode)) {
  257. filp->f_flags |= O_NOATIME;
  258. filp->f_mode |= FMODE_NOCMTIME;
  259. }
  260. fd_install(fd, filp);
  261. return fd;
  262. out_dput:
  263. dput(dentry);
  264. return error;
  265. }
  266. int
  267. xfs_readlink_by_handle(
  268. struct file *parfilp,
  269. xfs_fsop_handlereq_t *hreq)
  270. {
  271. struct dentry *dentry;
  272. __u32 olen;
  273. int error;
  274. if (!capable(CAP_SYS_ADMIN))
  275. return -EPERM;
  276. dentry = xfs_handlereq_to_dentry(parfilp, hreq);
  277. if (IS_ERR(dentry))
  278. return PTR_ERR(dentry);
  279. /* Restrict this handle operation to symlinks only. */
  280. if (!d_is_symlink(dentry)) {
  281. error = -EINVAL;
  282. goto out_dput;
  283. }
  284. if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) {
  285. error = -EFAULT;
  286. goto out_dput;
  287. }
  288. error = vfs_readlink(dentry, hreq->ohandle, olen);
  289. out_dput:
  290. dput(dentry);
  291. return error;
  292. }
  293. /*
  294. * Format an attribute and copy it out to the user's buffer.
  295. * Take care to check values and protect against them changing later,
  296. * we may be reading them directly out of a user buffer.
  297. */
  298. static void
  299. xfs_ioc_attr_put_listent(
  300. struct xfs_attr_list_context *context,
  301. int flags,
  302. unsigned char *name,
  303. int namelen,
  304. void *value,
  305. int valuelen)
  306. {
  307. struct xfs_attrlist *alist = context->buffer;
  308. struct xfs_attrlist_ent *aep;
  309. int arraytop;
  310. ASSERT(!context->seen_enough);
  311. ASSERT(context->count >= 0);
  312. ASSERT(context->count < (ATTR_MAX_VALUELEN/8));
  313. ASSERT(context->firstu >= sizeof(*alist));
  314. ASSERT(context->firstu <= context->bufsize);
  315. /*
  316. * Only list entries in the right namespace.
  317. */
  318. if (context->attr_filter != (flags & XFS_ATTR_NSP_ONDISK_MASK))
  319. return;
  320. arraytop = sizeof(*alist) +
  321. context->count * sizeof(alist->al_offset[0]);
  322. /* decrement by the actual bytes used by the attr */
  323. context->firstu -= round_up(offsetof(struct xfs_attrlist_ent, a_name) +
  324. namelen + 1, sizeof(uint32_t));
  325. if (context->firstu < arraytop) {
  326. trace_xfs_attr_list_full(context);
  327. alist->al_more = 1;
  328. context->seen_enough = 1;
  329. return;
  330. }
  331. aep = context->buffer + context->firstu;
  332. aep->a_valuelen = valuelen;
  333. memcpy(aep->a_name, name, namelen);
  334. aep->a_name[namelen] = 0;
  335. alist->al_offset[context->count++] = context->firstu;
  336. alist->al_count = context->count;
  337. trace_xfs_attr_list_add(context);
  338. }
  339. static unsigned int
  340. xfs_attr_filter(
  341. u32 ioc_flags)
  342. {
  343. if (ioc_flags & XFS_IOC_ATTR_ROOT)
  344. return XFS_ATTR_ROOT;
  345. if (ioc_flags & XFS_IOC_ATTR_SECURE)
  346. return XFS_ATTR_SECURE;
  347. return 0;
  348. }
  349. static inline enum xfs_attr_update
  350. xfs_xattr_flags(
  351. u32 ioc_flags,
  352. void *value)
  353. {
  354. if (!value)
  355. return XFS_ATTRUPDATE_REMOVE;
  356. if (ioc_flags & XFS_IOC_ATTR_CREATE)
  357. return XFS_ATTRUPDATE_CREATE;
  358. if (ioc_flags & XFS_IOC_ATTR_REPLACE)
  359. return XFS_ATTRUPDATE_REPLACE;
  360. return XFS_ATTRUPDATE_UPSERT;
  361. }
  362. int
  363. xfs_ioc_attr_list(
  364. struct xfs_inode *dp,
  365. void __user *ubuf,
  366. size_t bufsize,
  367. int flags,
  368. struct xfs_attrlist_cursor __user *ucursor)
  369. {
  370. struct xfs_attr_list_context context = { };
  371. struct xfs_attrlist *alist;
  372. void *buffer;
  373. int error;
  374. if (bufsize < sizeof(struct xfs_attrlist) ||
  375. bufsize > XFS_XATTR_LIST_MAX)
  376. return -EINVAL;
  377. /*
  378. * Reject flags, only allow namespaces.
  379. */
  380. if (flags & ~(XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
  381. return -EINVAL;
  382. if (flags == (XFS_IOC_ATTR_ROOT | XFS_IOC_ATTR_SECURE))
  383. return -EINVAL;
  384. /*
  385. * Validate the cursor.
  386. */
  387. if (copy_from_user(&context.cursor, ucursor, sizeof(context.cursor)))
  388. return -EFAULT;
  389. if (context.cursor.pad1 || context.cursor.pad2)
  390. return -EINVAL;
  391. if (!context.cursor.initted &&
  392. (context.cursor.hashval || context.cursor.blkno ||
  393. context.cursor.offset))
  394. return -EINVAL;
  395. buffer = kvzalloc(bufsize, GFP_KERNEL);
  396. if (!buffer)
  397. return -ENOMEM;
  398. /*
  399. * Initialize the output buffer.
  400. */
  401. context.dp = dp;
  402. context.resynch = 1;
  403. context.attr_filter = xfs_attr_filter(flags);
  404. context.buffer = buffer;
  405. context.bufsize = round_down(bufsize, sizeof(uint32_t));
  406. context.firstu = context.bufsize;
  407. context.put_listent = xfs_ioc_attr_put_listent;
  408. alist = context.buffer;
  409. alist->al_count = 0;
  410. alist->al_more = 0;
  411. alist->al_offset[0] = context.bufsize;
  412. error = xfs_attr_list(&context);
  413. if (error)
  414. goto out_free;
  415. if (copy_to_user(ubuf, buffer, bufsize) ||
  416. copy_to_user(ucursor, &context.cursor, sizeof(context.cursor)))
  417. error = -EFAULT;
  418. out_free:
  419. kvfree(buffer);
  420. return error;
  421. }
  422. int
  423. xfs_attrlist_by_handle(
  424. struct file *parfilp,
  425. struct xfs_fsop_attrlist_handlereq __user *p)
  426. {
  427. struct xfs_fsop_attrlist_handlereq al_hreq;
  428. struct dentry *dentry;
  429. int error = -ENOMEM;
  430. if (!capable(CAP_SYS_ADMIN))
  431. return -EPERM;
  432. if (copy_from_user(&al_hreq, p, sizeof(al_hreq)))
  433. return -EFAULT;
  434. dentry = xfs_handlereq_to_dentry(parfilp, &al_hreq.hreq);
  435. if (IS_ERR(dentry))
  436. return PTR_ERR(dentry);
  437. error = xfs_ioc_attr_list(XFS_I(d_inode(dentry)), al_hreq.buffer,
  438. al_hreq.buflen, al_hreq.flags, &p->pos);
  439. dput(dentry);
  440. return error;
  441. }
  442. static int
  443. xfs_attrmulti_attr_get(
  444. struct inode *inode,
  445. unsigned char *name,
  446. unsigned char __user *ubuf,
  447. uint32_t *len,
  448. uint32_t flags)
  449. {
  450. struct xfs_da_args args = {
  451. .dp = XFS_I(inode),
  452. .attr_filter = xfs_attr_filter(flags),
  453. .name = name,
  454. .namelen = strlen(name),
  455. .valuelen = *len,
  456. };
  457. int error;
  458. if (*len > XFS_XATTR_SIZE_MAX)
  459. return -EINVAL;
  460. error = xfs_attr_get(&args);
  461. if (error)
  462. goto out_kfree;
  463. *len = args.valuelen;
  464. if (copy_to_user(ubuf, args.value, args.valuelen))
  465. error = -EFAULT;
  466. out_kfree:
  467. kvfree(args.value);
  468. return error;
  469. }
  470. static int
  471. xfs_attrmulti_attr_set(
  472. struct inode *inode,
  473. unsigned char *name,
  474. const unsigned char __user *ubuf,
  475. uint32_t len,
  476. uint32_t flags)
  477. {
  478. struct xfs_da_args args = {
  479. .dp = XFS_I(inode),
  480. .attr_filter = xfs_attr_filter(flags),
  481. .name = name,
  482. .namelen = strlen(name),
  483. };
  484. int error;
  485. if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  486. return -EPERM;
  487. if (ubuf) {
  488. if (len > XFS_XATTR_SIZE_MAX)
  489. return -EINVAL;
  490. args.value = memdup_user(ubuf, len);
  491. if (IS_ERR(args.value))
  492. return PTR_ERR(args.value);
  493. args.valuelen = len;
  494. }
  495. error = xfs_attr_change(&args, xfs_xattr_flags(flags, args.value));
  496. if (!error && (flags & XFS_IOC_ATTR_ROOT))
  497. xfs_forget_acl(inode, name);
  498. kfree(args.value);
  499. return error;
  500. }
  501. int
  502. xfs_ioc_attrmulti_one(
  503. struct file *parfilp,
  504. struct inode *inode,
  505. uint32_t opcode,
  506. void __user *uname,
  507. void __user *value,
  508. uint32_t *len,
  509. uint32_t flags)
  510. {
  511. unsigned char *name;
  512. int error;
  513. if ((flags & XFS_IOC_ATTR_ROOT) && (flags & XFS_IOC_ATTR_SECURE))
  514. return -EINVAL;
  515. name = strndup_user(uname, MAXNAMELEN);
  516. if (IS_ERR(name))
  517. return PTR_ERR(name);
  518. switch (opcode) {
  519. case ATTR_OP_GET:
  520. error = xfs_attrmulti_attr_get(inode, name, value, len, flags);
  521. break;
  522. case ATTR_OP_REMOVE:
  523. value = NULL;
  524. *len = 0;
  525. fallthrough;
  526. case ATTR_OP_SET:
  527. error = mnt_want_write_file(parfilp);
  528. if (error)
  529. break;
  530. error = xfs_attrmulti_attr_set(inode, name, value, *len, flags);
  531. mnt_drop_write_file(parfilp);
  532. break;
  533. default:
  534. error = -EINVAL;
  535. break;
  536. }
  537. kfree(name);
  538. return error;
  539. }
  540. int
  541. xfs_attrmulti_by_handle(
  542. struct file *parfilp,
  543. void __user *arg)
  544. {
  545. int error;
  546. xfs_attr_multiop_t *ops;
  547. xfs_fsop_attrmulti_handlereq_t am_hreq;
  548. struct dentry *dentry;
  549. unsigned int i, size;
  550. if (!capable(CAP_SYS_ADMIN))
  551. return -EPERM;
  552. if (copy_from_user(&am_hreq, arg, sizeof(xfs_fsop_attrmulti_handlereq_t)))
  553. return -EFAULT;
  554. /* overflow check */
  555. if (am_hreq.opcount >= INT_MAX / sizeof(xfs_attr_multiop_t))
  556. return -E2BIG;
  557. dentry = xfs_handlereq_to_dentry(parfilp, &am_hreq.hreq);
  558. if (IS_ERR(dentry))
  559. return PTR_ERR(dentry);
  560. error = -E2BIG;
  561. size = am_hreq.opcount * sizeof(xfs_attr_multiop_t);
  562. if (!size || size > 16 * PAGE_SIZE)
  563. goto out_dput;
  564. ops = memdup_user(am_hreq.ops, size);
  565. if (IS_ERR(ops)) {
  566. error = PTR_ERR(ops);
  567. goto out_dput;
  568. }
  569. error = 0;
  570. for (i = 0; i < am_hreq.opcount; i++) {
  571. ops[i].am_error = xfs_ioc_attrmulti_one(parfilp,
  572. d_inode(dentry), ops[i].am_opcode,
  573. ops[i].am_attrname, ops[i].am_attrvalue,
  574. &ops[i].am_length, ops[i].am_flags);
  575. }
  576. if (copy_to_user(am_hreq.ops, ops, size))
  577. error = -EFAULT;
  578. kfree(ops);
  579. out_dput:
  580. dput(dentry);
  581. return error;
  582. }
  583. struct xfs_getparents_ctx {
  584. struct xfs_attr_list_context context;
  585. struct xfs_getparents_by_handle gph;
  586. /* File to target */
  587. struct xfs_inode *ip;
  588. /* Internal buffer where we format records */
  589. void *krecords;
  590. /* Last record filled out */
  591. struct xfs_getparents_rec *lastrec;
  592. unsigned int count;
  593. };
  594. static inline unsigned int
  595. xfs_getparents_rec_sizeof(
  596. unsigned int namelen)
  597. {
  598. return round_up(sizeof(struct xfs_getparents_rec) + namelen + 1,
  599. sizeof(uint64_t));
  600. }
  601. static void
  602. xfs_getparents_put_listent(
  603. struct xfs_attr_list_context *context,
  604. int flags,
  605. unsigned char *name,
  606. int namelen,
  607. void *value,
  608. int valuelen)
  609. {
  610. struct xfs_getparents_ctx *gpx =
  611. container_of(context, struct xfs_getparents_ctx, context);
  612. struct xfs_inode *ip = context->dp;
  613. struct xfs_mount *mp = ip->i_mount;
  614. struct xfs_getparents *gp = &gpx->gph.gph_request;
  615. struct xfs_getparents_rec *gpr = gpx->krecords + context->firstu;
  616. unsigned short reclen =
  617. xfs_getparents_rec_sizeof(namelen);
  618. xfs_ino_t ino;
  619. uint32_t gen;
  620. int error;
  621. if (!(flags & XFS_ATTR_PARENT))
  622. return;
  623. error = xfs_parent_from_attr(mp, flags, name, namelen, value, valuelen,
  624. &ino, &gen);
  625. if (error) {
  626. xfs_inode_mark_sick(ip, XFS_SICK_INO_PARENT);
  627. context->seen_enough = -EFSCORRUPTED;
  628. return;
  629. }
  630. /*
  631. * We found a parent pointer, but we've filled up the buffer. Signal
  632. * to the caller that we did /not/ reach the end of the parent pointer
  633. * recordset.
  634. */
  635. if (context->firstu > context->bufsize - reclen) {
  636. context->seen_enough = 1;
  637. return;
  638. }
  639. /* Format the parent pointer directly into the caller buffer. */
  640. gpr->gpr_reclen = reclen;
  641. xfs_filehandle_init(mp, ino, gen, &gpr->gpr_parent);
  642. memcpy(gpr->gpr_name, name, namelen);
  643. gpr->gpr_name[namelen] = 0;
  644. trace_xfs_getparents_put_listent(ip, gp, context, gpr);
  645. context->firstu += reclen;
  646. gpx->count++;
  647. gpx->lastrec = gpr;
  648. }
  649. /* Expand the last record to fill the rest of the caller's buffer. */
  650. static inline void
  651. xfs_getparents_expand_lastrec(
  652. struct xfs_getparents_ctx *gpx)
  653. {
  654. struct xfs_getparents *gp = &gpx->gph.gph_request;
  655. struct xfs_getparents_rec *gpr = gpx->lastrec;
  656. if (!gpx->lastrec)
  657. gpr = gpx->krecords;
  658. gpr->gpr_reclen = gp->gp_bufsize - ((void *)gpr - gpx->krecords);
  659. trace_xfs_getparents_expand_lastrec(gpx->ip, gp, &gpx->context, gpr);
  660. }
  661. /* Retrieve the parent pointers for a given inode. */
  662. STATIC int
  663. xfs_getparents(
  664. struct xfs_getparents_ctx *gpx)
  665. {
  666. struct xfs_getparents *gp = &gpx->gph.gph_request;
  667. struct xfs_inode *ip = gpx->ip;
  668. struct xfs_mount *mp = ip->i_mount;
  669. size_t bufsize;
  670. int error;
  671. /* Check size of buffer requested by user */
  672. if (gp->gp_bufsize > XFS_XATTR_LIST_MAX)
  673. return -ENOMEM;
  674. if (gp->gp_bufsize < xfs_getparents_rec_sizeof(1))
  675. return -EINVAL;
  676. if (gp->gp_iflags & ~XFS_GETPARENTS_IFLAGS_ALL)
  677. return -EINVAL;
  678. if (gp->gp_reserved)
  679. return -EINVAL;
  680. bufsize = round_down(gp->gp_bufsize, sizeof(uint64_t));
  681. gpx->krecords = kvzalloc(bufsize, GFP_KERNEL);
  682. if (!gpx->krecords) {
  683. bufsize = min(bufsize, PAGE_SIZE);
  684. gpx->krecords = kvzalloc(bufsize, GFP_KERNEL);
  685. if (!gpx->krecords)
  686. return -ENOMEM;
  687. }
  688. gpx->context.dp = ip;
  689. gpx->context.resynch = 1;
  690. gpx->context.put_listent = xfs_getparents_put_listent;
  691. gpx->context.bufsize = bufsize;
  692. /* firstu is used to track the bytes filled in the buffer */
  693. gpx->context.firstu = 0;
  694. /* Copy the cursor provided by caller */
  695. memcpy(&gpx->context.cursor, &gp->gp_cursor,
  696. sizeof(struct xfs_attrlist_cursor));
  697. gpx->count = 0;
  698. gp->gp_oflags = 0;
  699. trace_xfs_getparents_begin(ip, gp, &gpx->context.cursor);
  700. error = xfs_attr_list(&gpx->context);
  701. if (error)
  702. goto out_free_buf;
  703. if (gpx->context.seen_enough < 0) {
  704. error = gpx->context.seen_enough;
  705. goto out_free_buf;
  706. }
  707. xfs_getparents_expand_lastrec(gpx);
  708. /* Update the caller with the current cursor position */
  709. memcpy(&gp->gp_cursor, &gpx->context.cursor,
  710. sizeof(struct xfs_attrlist_cursor));
  711. /* Is this the root directory? */
  712. if (ip->i_ino == mp->m_sb.sb_rootino)
  713. gp->gp_oflags |= XFS_GETPARENTS_OFLAG_ROOT;
  714. if (gpx->context.seen_enough == 0) {
  715. /*
  716. * If we did not run out of buffer space, then we reached the
  717. * end of the pptr recordset, so set the DONE flag.
  718. */
  719. gp->gp_oflags |= XFS_GETPARENTS_OFLAG_DONE;
  720. } else if (gpx->count == 0) {
  721. /*
  722. * If we ran out of buffer space before copying any parent
  723. * pointers at all, the caller's buffer was too short. Tell
  724. * userspace that, erm, the message is too long.
  725. */
  726. error = -EMSGSIZE;
  727. goto out_free_buf;
  728. }
  729. trace_xfs_getparents_end(ip, gp, &gpx->context.cursor);
  730. ASSERT(gpx->context.firstu <= gpx->gph.gph_request.gp_bufsize);
  731. /* Copy the records to userspace. */
  732. if (copy_to_user(u64_to_user_ptr(gpx->gph.gph_request.gp_buffer),
  733. gpx->krecords, gpx->context.firstu))
  734. error = -EFAULT;
  735. out_free_buf:
  736. kvfree(gpx->krecords);
  737. gpx->krecords = NULL;
  738. return error;
  739. }
  740. /* Retrieve the parents of this file and pass them back to userspace. */
  741. int
  742. xfs_ioc_getparents(
  743. struct file *file,
  744. struct xfs_getparents __user *ureq)
  745. {
  746. struct xfs_getparents_ctx gpx = {
  747. .ip = XFS_I(file_inode(file)),
  748. };
  749. struct xfs_getparents *kreq = &gpx.gph.gph_request;
  750. struct xfs_mount *mp = gpx.ip->i_mount;
  751. int error;
  752. if (!capable(CAP_SYS_ADMIN))
  753. return -EPERM;
  754. if (!xfs_has_parent(mp))
  755. return -EOPNOTSUPP;
  756. if (copy_from_user(kreq, ureq, sizeof(*kreq)))
  757. return -EFAULT;
  758. error = xfs_getparents(&gpx);
  759. if (error)
  760. return error;
  761. if (copy_to_user(ureq, kreq, sizeof(*kreq)))
  762. return -EFAULT;
  763. return 0;
  764. }
  765. /* Retrieve the parents of this file handle and pass them back to userspace. */
  766. int
  767. xfs_ioc_getparents_by_handle(
  768. struct file *file,
  769. struct xfs_getparents_by_handle __user *ureq)
  770. {
  771. struct xfs_getparents_ctx gpx = { };
  772. struct xfs_inode *ip = XFS_I(file_inode(file));
  773. struct xfs_mount *mp = ip->i_mount;
  774. struct xfs_getparents_by_handle *kreq = &gpx.gph;
  775. struct xfs_handle *handle = &kreq->gph_handle;
  776. int error;
  777. if (!capable(CAP_SYS_ADMIN))
  778. return -EPERM;
  779. if (!xfs_has_parent(mp))
  780. return -EOPNOTSUPP;
  781. if (copy_from_user(kreq, ureq, sizeof(*kreq)))
  782. return -EFAULT;
  783. /*
  784. * We don't use exportfs_decode_fh because it does too much work here.
  785. * If the handle refers to a directory, the exportfs code will walk
  786. * upwards through the directory tree to connect the dentries to the
  787. * root directory dentry. For GETPARENTS we don't care about that
  788. * because we're not actually going to open a file descriptor; we only
  789. * want to open an inode and read its parent pointers.
  790. *
  791. * Note that xfs_scrub uses GETPARENTS to log that it will try to fix a
  792. * corrupted file's metadata. For this usecase we would really rather
  793. * userspace single-step the path reconstruction to avoid loops or
  794. * other strange things if the directory tree is corrupt.
  795. */
  796. gpx.ip = xfs_khandle_to_inode(file, handle);
  797. if (IS_ERR(gpx.ip))
  798. return PTR_ERR(gpx.ip);
  799. error = xfs_getparents(&gpx);
  800. if (error)
  801. goto out_rele;
  802. if (copy_to_user(ureq, kreq, sizeof(*kreq)))
  803. error = -EFAULT;
  804. out_rele:
  805. xfs_irele(gpx.ip);
  806. return error;
  807. }