Merge branch 'drm-fixes-5.0' of git://people.freedesktop.org/~agd5f/linux into drm...
[linux-2.6-block.git] / fs / xfs / scrub / symlink.c
CommitLineData
0b61f8a4 1// SPDX-License-Identifier: GPL-2.0+
2a721dbb
DW
2/*
3 * Copyright (C) 2017 Oracle. All Rights Reserved.
2a721dbb 4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
2a721dbb
DW
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
26/* Set us up to scrub a symbolic link. */
27int
c517b3aa 28xchk_setup_symlink(
1d8a748a 29 struct xfs_scrub *sc,
032d91f9 30 struct xfs_inode *ip)
2a721dbb
DW
31{
32 /* Allocate the buffer without the inode lock held. */
33 sc->buf = kmem_zalloc_large(XFS_SYMLINK_MAXLEN + 1, KM_SLEEP);
34 if (!sc->buf)
35 return -ENOMEM;
36
c517b3aa 37 return xchk_setup_inode_contents(sc, ip, 0);
2a721dbb
DW
38}
39
40/* Symbolic links. */
41
42int
c517b3aa 43xchk_symlink(
1d8a748a 44 struct xfs_scrub *sc)
2a721dbb 45{
032d91f9
DW
46 struct xfs_inode *ip = sc->ip;
47 struct xfs_ifork *ifp;
48 loff_t len;
49 int error = 0;
2a721dbb
DW
50
51 if (!S_ISLNK(VFS_I(ip)->i_mode))
52 return -ENOENT;
53 ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
54 len = ip->i_d.di_size;
55
56 /* Plausible size? */
57 if (len > XFS_SYMLINK_MAXLEN || len <= 0) {
c517b3aa 58 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
2a721dbb
DW
59 goto out;
60 }
61
62 /* Inline symlink? */
63 if (ifp->if_flags & XFS_IFINLINE) {
64 if (len > XFS_IFORK_DSIZE(ip) ||
65 len > strnlen(ifp->if_u1.if_data, XFS_IFORK_DSIZE(ip)))
c517b3aa 66 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
2a721dbb
DW
67 goto out;
68 }
69
70 /* Remote symlink; must read the contents. */
71 error = xfs_readlink_bmap_ilocked(sc->ip, sc->buf);
c517b3aa 72 if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
2a721dbb
DW
73 goto out;
74 if (strnlen(sc->buf, XFS_SYMLINK_MAXLEN) < len)
c517b3aa 75 xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
2a721dbb
DW
76out:
77 return error;
78}