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