[1/2] udf: add helper function udf_check_tagged_bh to check tagged page

Message ID 20230613032254.1235752-2-haowenchao2@huawei.com
State New
Headers
Series Fix out-of-bound access if pagecache of udf device is corrupted |

Commit Message

Wenchao Hao June 13, 2023, 3:22 a.m. UTC
  This helper function is used to check if a buffer head's data is valid
and would be called in future.

Signed-off-by: Wenchao Hao <haowenchao2@huawei.com>
---
 fs/udf/misc.c    | 60 ++++++++++++++++++++++++++++--------------------
 fs/udf/udfdecl.h |  1 +
 2 files changed, 36 insertions(+), 25 deletions(-)
  

Patch

diff --git a/fs/udf/misc.c b/fs/udf/misc.c
index 3777468d06ce..b20b53fc8d41 100644
--- a/fs/udf/misc.c
+++ b/fs/udf/misc.c
@@ -179,6 +179,40 @@  struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type,
 	return NULL;
 }
 
+bool udf_check_tagged_bh(struct super_block *sb, struct buffer_head *bh)
+{
+	u8 checksum;
+	struct tag *tag_p = (struct tag *)(bh->b_data);
+
+	/* Verify the tag checksum */
+	checksum = udf_tag_checksum(tag_p);
+	if (checksum != tag_p->tagChecksum) {
+		udf_err(sb, "tag checksum failed, block %llu: 0x%02x != 0x%02x\n",
+			bh->b_blocknr, checksum, tag_p->tagChecksum);
+		return false;
+	}
+
+	/* Verify the tag version */
+	if (tag_p->descVersion != cpu_to_le16(0x0002U) &&
+	    tag_p->descVersion != cpu_to_le16(0x0003U)) {
+		udf_err(sb, "tag version 0x%04x != 0x0002 || 0x0003, block %llu\n",
+			le16_to_cpu(tag_p->descVersion), bh->b_blocknr);
+		return false;
+	}
+
+	/* Verify the descriptor CRC */
+	if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize ||
+	    le16_to_cpu(tag_p->descCRC) == crc_itu_t(0,
+					bh->b_data + sizeof(struct tag),
+					le16_to_cpu(tag_p->descCRCLength)))
+		return true;
+
+	udf_debug("Crc failure block %llu: crc = %u, crclen = %u\n", bh->b_blocknr,
+		  le16_to_cpu(tag_p->descCRC),
+		  le16_to_cpu(tag_p->descCRCLength));
+	return false;
+}
+
 /*
  * udf_read_tagged
  *
@@ -194,7 +228,6 @@  struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
 {
 	struct tag *tag_p;
 	struct buffer_head *bh = NULL;
-	u8 checksum;
 
 	/* Read the block */
 	if (block == 0xFFFFFFFF)
@@ -217,32 +250,9 @@  struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
 		goto error_out;
 	}
 
-	/* Verify the tag checksum */
-	checksum = udf_tag_checksum(tag_p);
-	if (checksum != tag_p->tagChecksum) {
-		udf_err(sb, "tag checksum failed, block %u: 0x%02x != 0x%02x\n",
-			block, checksum, tag_p->tagChecksum);
-		goto error_out;
-	}
-
-	/* Verify the tag version */
-	if (tag_p->descVersion != cpu_to_le16(0x0002U) &&
-	    tag_p->descVersion != cpu_to_le16(0x0003U)) {
-		udf_err(sb, "tag version 0x%04x != 0x0002 || 0x0003, block %u\n",
-			le16_to_cpu(tag_p->descVersion), block);
-		goto error_out;
-	}
-
-	/* Verify the descriptor CRC */
-	if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize ||
-	    le16_to_cpu(tag_p->descCRC) == crc_itu_t(0,
-					bh->b_data + sizeof(struct tag),
-					le16_to_cpu(tag_p->descCRCLength)))
+	if (udf_check_tagged_bh(sb, bh))
 		return bh;
 
-	udf_debug("Crc failure block %u: crc = %u, crclen = %u\n", block,
-		  le16_to_cpu(tag_p->descCRC),
-		  le16_to_cpu(tag_p->descCRCLength));
 error_out:
 	brelse(bh);
 	return NULL;
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 88692512a466..fb269752b9c6 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -180,6 +180,7 @@  extern struct genericFormat *udf_add_extendedattr(struct inode *, uint32_t,
 						  uint32_t, uint8_t);
 extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t,
 						  uint8_t);
+extern bool udf_check_tagged_bh(struct super_block *sb, struct buffer_head *bh);
 extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t,
 					   uint32_t, uint16_t *);
 extern struct buffer_head *udf_read_ptagged(struct super_block *,