aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2018-02-26 22:43:18 -0600
committerEric Sandeen <sandeen@redhat.com>2018-02-26 22:43:18 -0600
commitf596a90d3d7a03f42cedcbc9b505fefe5da5df08 (patch)
treef2f3f37a544638a4f50f13be99085546a90d2b69
parentb67317ef3c22d69e0c29a5c624a84dc37e9c6ffd (diff)
downloadxfsprogs-dev-f596a90d3d7a03f42cedcbc9b505fefe5da5df08.tar.gz
xfs: attr leaf verifier needs to check for obviously bad count
Source kernel commit: 79a69bf8dc240ebeb105226a8a8540df136bf987 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: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
-rw-r--r--libxfs/xfs_attr_leaf.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c
index 072e3b0a23..d0bf4cf77e 100644
--- a/libxfs/xfs_attr_leaf.c
+++ b/libxfs/xfs_attr_leaf.c
@@ -244,12 +244,13 @@ xfs_attr3_leaf_hdr_to_disk(
static xfs_failaddr_t
xfs_attr3_leaf_verify(
- struct xfs_buf *bp)
+ struct xfs_buf *bp)
{
- struct xfs_mount *mp = bp->b_target->bt_mount;
- struct xfs_attr_leafblock *leaf = bp->b_addr;
- struct xfs_perag *pag = bp->b_pag;
- struct xfs_attr3_icleaf_hdr ichdr;
+ struct xfs_attr3_icleaf_hdr ichdr;
+ struct xfs_mount *mp = bp->b_target->bt_mount;
+ struct xfs_attr_leafblock *leaf = bp->b_addr;
+ struct xfs_perag *pag = bp->b_pag;
+ struct xfs_attr_leaf_entry *entries;
xfs_attr3_leaf_hdr_from_disk(mp->m_attr_geo, &ichdr, leaf);
@@ -277,6 +278,21 @@ xfs_attr3_leaf_verify(
if (pag && pag->pagf_init && ichdr.count == 0)
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: hash order check? */