79 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			79 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0+
 | 
						|
/*
 | 
						|
 * Copyright (C) 2017 Oracle.  All Rights Reserved.
 | 
						|
 * Author: Darrick J. Wong <darrick.wong@oracle.com>
 | 
						|
 */
 | 
						|
#include "xfs.h"
 | 
						|
#include "xfs_fs.h"
 | 
						|
#include "xfs_shared.h"
 | 
						|
#include "xfs_format.h"
 | 
						|
#include "xfs_trans_resv.h"
 | 
						|
#include "xfs_mount.h"
 | 
						|
#include "xfs_defer.h"
 | 
						|
#include "xfs_btree.h"
 | 
						|
#include "xfs_bit.h"
 | 
						|
#include "xfs_log_format.h"
 | 
						|
#include "xfs_trans.h"
 | 
						|
#include "xfs_sb.h"
 | 
						|
#include "xfs_inode.h"
 | 
						|
#include "xfs_inode_fork.h"
 | 
						|
#include "xfs_symlink.h"
 | 
						|
#include "scrub/xfs_scrub.h"
 | 
						|
#include "scrub/scrub.h"
 | 
						|
#include "scrub/common.h"
 | 
						|
#include "scrub/trace.h"
 | 
						|
 | 
						|
/* Set us up to scrub a symbolic link. */
 | 
						|
int
 | 
						|
xchk_setup_symlink(
 | 
						|
	struct xfs_scrub	*sc,
 | 
						|
	struct xfs_inode	*ip)
 | 
						|
{
 | 
						|
	/* Allocate the buffer without the inode lock held. */
 | 
						|
	sc->buf = kmem_zalloc_large(XFS_SYMLINK_MAXLEN + 1, KM_SLEEP);
 | 
						|
	if (!sc->buf)
 | 
						|
		return -ENOMEM;
 | 
						|
 | 
						|
	return xchk_setup_inode_contents(sc, ip, 0);
 | 
						|
}
 | 
						|
 | 
						|
/* Symbolic links. */
 | 
						|
 | 
						|
int
 | 
						|
xchk_symlink(
 | 
						|
	struct xfs_scrub	*sc)
 | 
						|
{
 | 
						|
	struct xfs_inode	*ip = sc->ip;
 | 
						|
	struct xfs_ifork	*ifp;
 | 
						|
	loff_t			len;
 | 
						|
	int			error = 0;
 | 
						|
 | 
						|
	if (!S_ISLNK(VFS_I(ip)->i_mode))
 | 
						|
		return -ENOENT;
 | 
						|
	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
 | 
						|
	len = ip->i_d.di_size;
 | 
						|
 | 
						|
	/* Plausible size? */
 | 
						|
	if (len > XFS_SYMLINK_MAXLEN || len <= 0) {
 | 
						|
		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Inline symlink? */
 | 
						|
	if (ifp->if_flags & XFS_IFINLINE) {
 | 
						|
		if (len > XFS_IFORK_DSIZE(ip) ||
 | 
						|
		    len > strnlen(ifp->if_u1.if_data, XFS_IFORK_DSIZE(ip)))
 | 
						|
			xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
 | 
						|
		goto out;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Remote symlink; must read the contents. */
 | 
						|
	error = xfs_readlink_bmap_ilocked(sc->ip, sc->buf);
 | 
						|
	if (!xchk_fblock_process_error(sc, XFS_DATA_FORK, 0, &error))
 | 
						|
		goto out;
 | 
						|
	if (strnlen(sc->buf, XFS_SYMLINK_MAXLEN) < len)
 | 
						|
		xchk_fblock_set_corrupt(sc, XFS_DATA_FORK, 0);
 | 
						|
out:
 | 
						|
	return error;
 | 
						|
}
 |