Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-or-later 2 : /* 3 : * Copyright (C) 2017-2023 Oracle. All Rights Reserved. 4 : * Author: Darrick J. Wong <djwong@kernel.org> 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_trans.h" 14 : #include "xfs_inode.h" 15 : #include "xfs_symlink.h" 16 : #include "xfs_symlink_remote.h" 17 : #include "scrub/scrub.h" 18 : #include "scrub/common.h" 19 : #include "scrub/repair.h" 20 : 21 : /* Set us up to scrub a symbolic link. */ 22 : int 23 14059112 : xchk_setup_symlink( 24 : struct xfs_scrub *sc) 25 : { 26 14059112 : unsigned int resblks = 0; 27 14059112 : int error; 28 : 29 : /* Allocate the buffer without the inode lock held. */ 30 14059112 : sc->buf = kvzalloc(XFS_SYMLINK_MAXLEN + 1, XCHK_GFP_FLAGS); 31 14061353 : if (!sc->buf) 32 : return -ENOMEM; 33 : 34 28122706 : if (xchk_could_repair(sc)) { 35 144580 : error = xrep_setup_symlink(sc, &resblks); 36 144691 : if (error) 37 : return error; 38 : } 39 : 40 14061464 : return xchk_setup_inode_contents(sc, resblks); 41 : } 42 : 43 : /* Symbolic links. */ 44 : 45 : int 46 13954433 : xchk_symlink( 47 : struct xfs_scrub *sc) 48 : { 49 13954433 : struct xfs_inode *ip = sc->ip; 50 13954433 : struct xfs_ifork *ifp; 51 13954433 : loff_t len; 52 13954433 : int error = 0; 53 : 54 13954433 : if (!S_ISLNK(VFS_I(ip)->i_mode)) 55 : return -ENOENT; 56 13925735 : ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK); 57 13925735 : len = ip->i_disk_size; 58 : 59 : /* Plausible size? */ 60 13925735 : if (len > XFS_SYMLINK_MAXLEN || len <= 0) { 61 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0); 62 0 : goto out; 63 : } 64 : 65 : /* Inline symlink? */ 66 13925735 : if (ifp->if_format == XFS_DINODE_FMT_LOCAL) { 67 6891187 : if (len > xfs_inode_data_fork_size(ip) || 68 3445279 : len > strnlen(ifp->if_u1.if_data, xfs_inode_data_fork_size(ip))) 69 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0); 70 3445793 : goto out; 71 : } 72 : 73 : /* Remote symlink; must read the contents. */ 74 10480456 : error = xfs_symlink_remote_read(sc->ip, sc->buf); 75 10479933 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error)) 76 0 : goto out; 77 20962191 : if (strnlen(sc->buf, XFS_SYMLINK_MAXLEN) < len) 78 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0); 79 10484158 : out: 80 13929951 : return error; 81 : }