File 0019-metadump-Zero-unused-portions-of-inode-BMAP-and-allo.patch of Package xfsprogs.5309

From 20f35ef496057b98bd17081a05060f187181e060 Mon Sep 17 00:00:00 2001
From: Eric Sandeen <sandeen@sandeen.net>
Date: Thu, 30 Jul 2015 09:21:08 +1000
Subject: [PATCH 19/20] metadump: Zero unused portions of inode, BMAP, and
 allocation btree blocks
References: bsc#939367 CVE-2012-2150

Zero out the unused regions of these btree blocks, as
they may contain stale data.

Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Acked-by: Jan Kara <jack@suse.com>

---
 db/metadump.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 db/type.c     |   3 ++
 db/type.h     |   2 +-
 3 files changed, 128 insertions(+), 1 deletion(-)

diff --git a/db/metadump.c b/db/metadump.c
index d2935810733b..238f86407a27 100644
--- a/db/metadump.c
+++ b/db/metadump.c
@@ -245,6 +245,124 @@ write_buf(
 	return seenint() ? -EINTR : 0;
 }
 
+static void
+zero_btree_node(
+	struct xfs_btree_block	*block,
+	typnm_t			btype)
+{
+	int			nrecs;
+	xfs_bmbt_ptr_t		*bpp;
+	xfs_bmbt_key_t		*bkp;
+	xfs_inobt_ptr_t		*ipp;
+	xfs_inobt_key_t		*ikp;
+	xfs_alloc_ptr_t		*app;
+	xfs_alloc_key_t		*akp;
+	void			*zp1, *zp2;
+	int			zlen1, zlen2;
+
+	nrecs = be16_to_cpu(block->bb_numrecs);
+
+	switch (btype) {
+	case TYP_BMAPBTA:
+	case TYP_BMAPBTD:
+		bkp = XFS_BMBT_KEY_ADDR(mp, block, 1);
+		bpp = XFS_BMBT_PTR_ADDR(mp, block, 1, mp->m_bmap_dmxr[1]);
+		zp1 = &bkp[nrecs];
+		zlen1 = (char *)&bpp[0] - (char *)&bkp[nrecs];
+		zp2 = &bpp[nrecs];
+		zlen2 = (char *)block + mp->m_sb.sb_blocksize -
+							(char *)&bpp[nrecs];
+		break;
+	case TYP_INOBT:
+	case TYP_FINOBT:
+		ikp = XFS_INOBT_KEY_ADDR(mp, block, 1);
+		ipp = XFS_INOBT_PTR_ADDR(mp, block, 1, mp->m_inobt_mxr[1]);
+		zp1 = &ikp[nrecs];
+		zlen1 = (char *)&ipp[0] - (char *)&ikp[nrecs];
+		zp2 = &ipp[nrecs];
+		zlen2 = (char *)block + mp->m_sb.sb_blocksize -
+							(char *)&ipp[nrecs];
+		break;
+	case TYP_BNOBT:
+	case TYP_CNTBT:
+		akp = XFS_ALLOC_KEY_ADDR(mp, block, 1);
+		app = XFS_ALLOC_PTR_ADDR(mp, block, 1, mp->m_alloc_mxr[1]);
+		zp1 = &akp[nrecs];
+		zlen1 = (char *)&app[0] - (char *)&akp[nrecs];
+		zp2 = &app[nrecs];
+		zlen2 = (char *)block + mp->m_sb.sb_blocksize -
+							(char *)&app[nrecs];
+		break;
+	default:
+		zp1 = NULL;
+		break;
+	}
+
+	if (zp1 && zp2) {
+		/* Zero from end of keys to beginning of pointers */
+		memset(zp1, 0, zlen1);
+		/* Zero from end of pointers to end of block */
+		memset(zp2, 0, zlen2);
+	}
+}
+
+static void
+zero_btree_leaf(
+	struct xfs_btree_block	*block,
+	typnm_t			btype)
+{
+	int			nrecs;
+	struct xfs_bmbt_rec	*brp;
+	struct xfs_inobt_rec	*irp;
+	struct xfs_alloc_rec	*arp;
+	void			*zp;
+	int			zlen;
+
+	nrecs = be16_to_cpu(block->bb_numrecs);
+
+	switch (btype) {
+	case TYP_BMAPBTA:
+	case TYP_BMAPBTD:
+		brp = XFS_BMBT_REC_ADDR(mp, block, 1);
+		zp = &brp[nrecs];
+		zlen = (char *)block + mp->m_sb.sb_blocksize - (char *)&brp[nrecs];
+		break;
+	case TYP_INOBT:
+	case TYP_FINOBT:
+		irp = XFS_INOBT_REC_ADDR(mp, block, 1);
+		zp = &irp[nrecs];
+		zlen = (char *)block + mp->m_sb.sb_blocksize - (char *)&irp[nrecs];
+		break;
+	case TYP_BNOBT:
+	case TYP_CNTBT:
+		arp = XFS_ALLOC_REC_ADDR(mp, block, 1);
+		zp = &arp[nrecs];
+		zlen = (char *)block + mp->m_sb.sb_blocksize - (char *)&arp[nrecs];
+		break;
+	default:
+		zp = NULL;
+		break;
+	}
+
+	/* Zero from end of records to end of block */
+	if (zp && zlen < mp->m_sb.sb_blocksize)
+		memset(zp, 0, zlen);
+}
+
+static void
+zero_btree_block(
+	struct xfs_btree_block	*block,
+	typnm_t			btype)
+{
+	int			level;
+
+	level = be16_to_cpu(block->bb_level);
+
+	if (level > 0)
+		zero_btree_node(block, btype);
+	else
+		zero_btree_leaf(block, btype);
+}
 
 static int
 scan_btree(
@@ -271,6 +389,12 @@ scan_btree(
 		rval = !stop_on_read_error;
 		goto pop_out;
 	}
+
+	if (zero_stale_data) {
+		zero_btree_block(iocur_top->data, btype);
+		iocur_top->need_crc = 1;
+	}
+
 	if (write_buf(iocur_top))
 		goto pop_out;
 
diff --git a/db/type.c b/db/type.c
index b29f2a47a590..0aa3137f5f89 100644
--- a/db/type.c
+++ b/db/type.c
@@ -70,6 +70,7 @@ static const typ_t	__typtab[] = {
 	{ TYP_SB, "sb", handle_struct, sb_hfld, NULL },
 	{ TYP_SYMLINK, "symlink", handle_string, NULL, NULL },
 	{ TYP_TEXT, "text", handle_text, NULL, NULL },
+	{ TYP_FINOBT, "finobt", handle_struct, inobt_hfld, NULL },
 	{ TYP_NONE, NULL }
 };
 
@@ -104,6 +105,8 @@ static const typ_t	__typtab_crc[] = {
 	{ TYP_SYMLINK, "symlink", handle_struct, symlink_crc_hfld,
 		&xfs_symlink_buf_ops },
 	{ TYP_TEXT, "text", handle_text, NULL, NULL },
+	{ TYP_FINOBT, "finobt", handle_struct, inobt_crc_hfld,
+		&xfs_inobt_buf_ops },
 	{ TYP_NONE, NULL }
 };
 
diff --git a/db/type.h b/db/type.h
index 3bb26f174416..e8d8df718ac9 100644
--- a/db/type.h
+++ b/db/type.h
@@ -27,7 +27,7 @@ typedef enum typnm
 	TYP_BMAPBTD, TYP_BNOBT, TYP_CNTBT, TYP_DATA,
 	TYP_DIR2, TYP_DQBLK, TYP_INOBT, TYP_INODATA, TYP_INODE,
 	TYP_LOG, TYP_RTBITMAP, TYP_RTSUMMARY, TYP_SB, TYP_SYMLINK,
-	TYP_TEXT, TYP_NONE
+	TYP_TEXT, TYP_FINOBT, TYP_NONE
 } typnm_t;
 
 #define DB_WRITE 1
-- 
2.1.4

openSUSE Build Service is sponsored by