Commit | Line | Data |
---|---|---|
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. */ | |
27 | int | |
c517b3aa | 28 | xchk_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 | ||
42 | int | |
c517b3aa | 43 | xchk_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 |
76 | out: |
77 | return error; | |
78 | } |