Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79a69bf8 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: attr leaf verifier needs to check for obviously bad count



In the attribute leaf verifier, we can check for obviously bad values of
firstused and count so that later attempts at lasthash don't run off the
end of the memory buffer.  Found by ones fuzzing hdr.count in xfs/400 with
KASAN.

Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
parent ce92d29d
Loading
Loading
Loading
Loading
+21 −5
Original line number Original line Diff line number Diff line
@@ -251,10 +251,11 @@ static xfs_failaddr_t
xfs_attr3_leaf_verify(
xfs_attr3_leaf_verify(
	struct xfs_buf			*bp)
	struct xfs_buf			*bp)
{
{
	struct xfs_attr3_icleaf_hdr	ichdr;
	struct xfs_mount		*mp = bp->b_target->bt_mount;
	struct xfs_mount		*mp = bp->b_target->bt_mount;
	struct xfs_attr_leafblock	*leaf = bp->b_addr;
	struct xfs_attr_leafblock	*leaf = bp->b_addr;
	struct xfs_perag		*pag = bp->b_pag;
	struct xfs_perag		*pag = bp->b_pag;
	struct xfs_attr3_icleaf_hdr ichdr;
	struct xfs_attr_leaf_entry	*entries;


	xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
	xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);


@@ -282,6 +283,21 @@ xfs_attr3_leaf_verify(
	if (pag && pag->pagf_init && ichdr.count == 0)
	if (pag && pag->pagf_init && ichdr.count == 0)
		return __this_address;
		return __this_address;


	/*
	 * firstused is the block offset of the first name info structure.
	 * Make sure it doesn't go off the block or crash into the header.
	 */
	if (ichdr.firstused > mp->m_attr_geo->blksize)
		return __this_address;
	if (ichdr.firstused < xfs_attr3_leaf_hdr_size(leaf))
		return __this_address;

	/* Make sure the entries array doesn't crash into the name info. */
	entries = xfs_attr3_leaf_entryp(bp->b_addr);
	if ((char *)&entries[ichdr.count] >
	    (char *)bp->b_addr + ichdr.firstused)
		return __this_address;

	/* XXX: need to range check rest of attr header values */
	/* XXX: need to range check rest of attr header values */
	/* XXX: hash order check? */
	/* XXX: hash order check? */