symlink.c 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (C) 2017 Oracle. All Rights Reserved.
  4. * Author: Darrick J. Wong <[email protected]>
  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_log_format.h"
  13. #include "xfs_inode.h"
  14. #include "xfs_symlink.h"
  15. #include "scrub/scrub.h"
  16. #include "scrub/common.h"
  17. /* Set us up to scrub a symbolic link. */
  18. int
  19. xchk_setup_symlink(
  20. struct xfs_scrub *sc)
  21. {
  22. /* Allocate the buffer without the inode lock held. */
  23. sc->buf = kvzalloc(XFS_SYMLINK_MAXLEN + 1, GFP_KERNEL);
  24. if (!sc->buf)
  25. return -ENOMEM;
  26. return xchk_setup_inode_contents(sc, 0);
  27. }
  28. /* Symbolic links. */
  29. int
  30. xchk_symlink(
  31. struct xfs_scrub *sc)
  32. {
  33. struct xfs_inode *ip = sc->ip;
  34. struct xfs_ifork *ifp;
  35. loff_t len;
  36. int error = 0;
  37. if (!S_ISLNK(VFS_I(ip)->i_mode))
  38. return -ENOENT;
  39. ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
  40. len = ip->i_disk_size;
  41. /* Plausible size? */
  42. if (len > XFS_SYMLINK_MAXLEN || len <= 0) {
  43. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  44. goto out;
  45. }
  46. /* Inline symlink? */
  47. if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
  48. if (len > xfs_inode_data_fork_size(ip) ||
  49. len > strnlen(ifp->if_u1.if_data, xfs_inode_data_fork_size(ip)))
  50. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  51. goto out;
  52. }
  53. /* Remote symlink; must read the contents. */
  54. error = xfs_readlink_bmap_ilocked(sc->ip, sc->buf);
  55. if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
  56. goto out;
  57. if (strnlen(sc->buf, XFS_SYMLINK_MAXLEN) < len)
  58. xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
  59. out:
  60. return error;
  61. }