symlink.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2017 Oracle. All Rights Reserved.
  4. * Author: Darrick J. Wong <darrick.wong@oracle.com>
  5. */
  6. #include "xfs.h"
  7. #include "xfs_fs.h"
  8. #include "xfs_shared.h"
  9. #include "xfs_format.h"
  10. #include "xfs_trans_resv.h"
  11. #include "xfs_mount.h"
  12. #include "xfs_defer.h"
  13. #include "xfs_btree.h"
  14. #include "xfs_bit.h"
  15. #include "xfs_log_format.h"
  16. #include "xfs_trans.h"
  17. #include "xfs_sb.h"
  18. #include "xfs_inode.h"
  19. #include "xfs_inode_fork.h"
  20. #include "xfs_symlink.h"
  21. #include "scrub/xfs_scrub.h"
  22. #include "scrub/scrub.h"
  23. #include "scrub/common.h"
  24. #include "scrub/trace.h"
  25. /* Set us up to scrub a symbolic link. */
  26. int
  27. xchk_setup_symlink(
  28. struct xfs_scrub *sc,
  29. struct xfs_inode *ip)
  30. {
  31. /* Allocate the buffer without the inode lock held. */
  32. sc->buf = kmem_zalloc_large(XFS_SYMLINK_MAXLEN + 1, KM_SLEEP);
  33. if (!sc->buf)
  34. return -ENOMEM;
  35. return xchk_setup_inode_contents(sc, ip, 0);
  36. }
  37. /* Symbolic links. */
  38. int
  39. xchk_symlink(
  40. struct xfs_scrub *sc)
  41. {
  42. struct xfs_inode *ip = sc->ip;
  43. struct xfs_ifork *ifp;
  44. loff_t len;
  45. int error = 0;
  46. if (!S_ISLNK(VFS_I(ip)->i_mode))
  47. return -ENOENT;
  48. ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
  49. len = ip->i_d.di_size;
  50. /* Plausible size? */
  51. if (len > XFS_SYMLINK_MAXLEN || len <= 0) {
  52. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  53. goto out;
  54. }
  55. /* Inline symlink? */
  56. if (ifp->if_flags & XFS_IFINLINE) {
  57. if (len > XFS_IFORK_DSIZE(ip) ||
  58. len > strnlen(ifp->if_u1.if_data, XFS_IFORK_DSIZE(ip)))
  59. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  60. goto out;
  61. }
  62. /* Remote symlink; must read the contents. */
  63. error = xfs_readlink_bmap_ilocked(sc->ip, sc->buf);
  64. if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
  65. goto out;
  66. if (strnlen(sc->buf, XFS_SYMLINK_MAXLEN) < len)
  67. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  68. out:
  69. return error;
  70. }