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 16235094 : xchk_setup_symlink( 24 : struct xfs_scrub *sc) 25 : { 26 16235094 : unsigned int resblks = 0; 27 16235094 : int error; 28 : 29 : /* Allocate the buffer without the inode lock held. */ 30 16235094 : sc->buf = kvzalloc(XFS_SYMLINK_MAXLEN + 1, XCHK_GFP_FLAGS); 31 16235066 : if (!sc->buf) 32 : return -ENOMEM; 33 : 34 32470132 : if (xchk_could_repair(sc)) { 35 995970 : error = xrep_setup_symlink(sc, &resblks); 36 995971 : if (error) 37 : return error; 38 : } 39 : 40 16235067 : return xchk_setup_inode_contents(sc, resblks); 41 : } 42 : 43 : /* Symbolic links. */ 44 : 45 : int 46 16155875 : xchk_symlink( 47 : struct xfs_scrub *sc) 48 : { 49 16155875 : struct xfs_inode *ip = sc->ip; 50 16155875 : struct xfs_ifork *ifp; 51 16155875 : loff_t len; 52 16155875 : int error = 0; 53 : 54 16155875 : if (!S_ISLNK(VFS_I(ip)->i_mode)) 55 : return -ENOENT; 56 16131472 : ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK); 57 16131472 : len = ip->i_disk_size; 58 : 59 : /* Plausible size? */ 60 16131472 : 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 16131472 : if (ifp->if_format == XFS_DINODE_FMT_LOCAL) { 67 6232866 : if (len > xfs_inode_data_fork_size(ip) || 68 3116420 : 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 3116444 : goto out; 71 : } 72 : 73 : /* Remote symlink; must read the contents. */ 74 13015052 : error = xfs_symlink_remote_read(sc->ip, sc->buf); 75 13014885 : if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error)) 76 0 : goto out; 77 26029974 : if (strnlen(sc->buf, XFS_SYMLINK_MAXLEN) < len) 78 0 : xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0); 79 13014986 : out: 80 16131430 : return error; 81 : }