Skip to contentSkip to conversation

jfs: jfs_dmap: Validate db_l2nbperpage while mounting

PATCH Superseded Siddh Raman Pant 2 participants 3 messages Jun 5, 2023 – Jun 19, 2023

Subsystems (2)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 jfs: jfs_dmap: Validate db_l2nbperpage while mounting

In jfs_dmap.c at line 381, BLKTODMAP is used to get a logical block number inside dbFree(). db_l2nbperpage, which is the log2 number of blocks per page, is passed as an argument to BLKTODMAP which uses it for shifting.

Syzbot reported a shift out-of-bounds crash because db_l2nbperpage is too big. This happens because the large value is set without any validation in dbMount() at line 181.

Thus, make sure that db_l2nbperpage is correct while mounting.

---
 fs/jfs/jfs_dmap.c | 6 ++++++
 1 file changed, 6 insertions(+)
fs/jfs/jfs_dmap.c +6 -0
index a3eb1e826947..62f058822a3a 100644
@@ -178,7 +178,13 @@ int dbMount(struct inode *ipbmap)
 	dbmp_le = (struct dbmap_disk *) mp->data;
 	bmp->db_mapsize = le64_to_cpu(dbmp_le->dn_mapsize);
 	bmp->db_nfree = le64_to_cpu(dbmp_le->dn_nfree);
+
 	bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage);
+	if (bmp->db_l2nbperpage > L2MAXL0SIZE) {
+		err = -EINVAL;
+		goto err_release_metapage;
+	}
+
 	bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag);
 	if (!bmp->db_numag) {
 		err = -EINVAL;
Signature · 1 line
2.39.2
#1 lore raw
Quoted 24 lines · Siddh Raman Pant

In jfs_dmap.c at line 381, BLKTODMAP is used to get a logical block number inside dbFree(). db_l2nbperpage, which is the log2 number of blocks per page, is passed as an argument to BLKTODMAP which uses it for shifting.

Syzbot reported a shift out-of-bounds crash because db_l2nbperpage is too big. This happens because the large value is set without any validation in dbMount() at line 181.

Thus, make sure that db_l2nbperpage is correct while mounting.

---
  fs/jfs/jfs_dmap.c | 6 ++++++
  1 file changed, 6 insertions(+)
fs/jfs/jfs_dmap.c +0 -0
index a3eb1e826947..62f058822a3a 100644

fs/jfs/jfs_dmap.c int dbMount(struct inode *ipbmap) · line 183

Quoted 6 lines
fs/jfs/jfs_dmap.c +2 -0
@@ -178,7 +178,13 @@ int dbMount(struct inode *ipbmap)
  	dbmp_le = (struct dbmap_disk *) mp->data;
  	bmp->db_mapsize = le64_to_cpu(dbmp_le->dn_mapsize);
  	bmp->db_nfree = le64_to_cpu(dbmp_le->dn_nfree);
+
  	bmp->db_l2nbperpage = le32_to_cpu(dbmp_le->dn_l2nbperpage);
+	if (bmp->db_l2nbperpage > L2MAXL0SIZE) {

Actually the sanity check should be much smaller. The maximum value should be L2PSIZE - log2(MINBLOCKSIZE). In reality, I think it's always zero.

Shaggy

Quoted 7 lines
fs/jfs/jfs_dmap.c +4 -0
+		err = -EINVAL;
+		goto err_release_metapage;
+	}
+
  	bmp->db_numag = le32_to_cpu(dbmp_le->dn_numag);
  	if (!bmp->db_numag) {
  		err = -EINVAL;
#2 lore raw
Quoted 3 lines · Dave Kleikamp

Actually the sanity check should be much smaller. The maximum value should be L2PSIZE - log2(MINBLOCKSIZE). In reality, I think it's always zero.

Thanks for the review, will amend the patch and send.

Thanks,
Siddh