0001
0002
0003
0004
0005
0006 #include "xfs.h"
0007 #include "xfs_fs.h"
0008 #include "xfs_shared.h"
0009 #include "xfs_format.h"
0010 #include "xfs_trans_resv.h"
0011 #include "xfs_mount.h"
0012 #include "xfs_log_format.h"
0013 #include "xfs_inode.h"
0014 #include "xfs_symlink.h"
0015 #include "scrub/scrub.h"
0016 #include "scrub/common.h"
0017
0018
0019 int
0020 xchk_setup_symlink(
0021 struct xfs_scrub *sc)
0022 {
0023
0024 sc->buf = kvzalloc(XFS_SYMLINK_MAXLEN + 1, GFP_KERNEL);
0025 if (!sc->buf)
0026 return -ENOMEM;
0027
0028 return xchk_setup_inode_contents(sc, 0);
0029 }
0030
0031
0032
0033 int
0034 xchk_symlink(
0035 struct xfs_scrub *sc)
0036 {
0037 struct xfs_inode *ip = sc->ip;
0038 struct xfs_ifork *ifp;
0039 loff_t len;
0040 int error = 0;
0041
0042 if (!S_ISLNK(VFS_I(ip)->i_mode))
0043 return -ENOENT;
0044 ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
0045 len = ip->i_disk_size;
0046
0047
0048 if (len > XFS_SYMLINK_MAXLEN || len <= 0) {
0049 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
0050 goto out;
0051 }
0052
0053
0054 if (ifp->if_format == XFS_DINODE_FMT_LOCAL) {
0055 if (len > xfs_inode_data_fork_size(ip) ||
0056 len > strnlen(ifp->if_u1.if_data, xfs_inode_data_fork_size(ip)))
0057 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
0058 goto out;
0059 }
0060
0061
0062 error = xfs_readlink_bmap_ilocked(sc->ip, sc->buf);
0063 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
0064 goto out;
0065 if (strnlen(sc->buf, XFS_SYMLINK_MAXLEN) < len)
0066 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
0067 out:
0068 return error;
0069 }