Re: [syzbot] [integrity?] [lsm?] INFO: task hung in process_measurement (2)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



#syz test
From c459223367da6df65ea254059424a86d8d2bf4f8 Mon Sep 17 00:00:00 2001
From: Yuezhang Mo <Yuezhang.Mo@xxxxxxxx>
Date: Tue, 10 Dec 2024 18:02:07 +0800
Subject: [PATCH] exfat: check cluster chain loop when freeing clusters

In order to avoid orphan clusters, clusters in the cluster chain
need to be freed until the EOF cluster is traversed. However, if
a cluster chain includes a loop in itself, the EOF cluster will
cannot be traversed, resulting in an infinite loop.

Signed-off-by: Yuezhang Mo <Yuezhang.Mo@xxxxxxxx>
---
 fs/exfat/balloc.c   | 13 +++++++++++++
 fs/exfat/exfat_fs.h |  1 +
 fs/exfat/fatent.c   |  8 ++++++++
 3 files changed, 22 insertions(+)

diff --git a/fs/exfat/balloc.c b/fs/exfat/balloc.c
index ce9be95c9172..398a05d2a2dd 100644
--- a/fs/exfat/balloc.c
+++ b/fs/exfat/balloc.c
@@ -173,6 +173,19 @@ void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync)
 	}
 }
 
+bool exfat_test_bitmap(struct super_block *sb, unsigned int clu)
+{
+	unsigned int map_i, map_b, bit;
+	struct exfat_sb_info *sbi = EXFAT_SB(sb);
+
+	bit = CLUSTER_TO_BITMAP_ENT(clu);
+	map_i = BITMAP_OFFSET_SECTOR_INDEX(sb, bit);
+	map_b = BITMAP_OFFSET_BYTE_IN_SECTOR(sb, bit);
+	bit &= (BITS_PER_BYTE - 1);
+
+	return *(sbi->vol_amap[map_i]->b_data + map_b) & BIT(bit);
+}
+
 /*
  * If the value of "clu" is 0, it means cluster 2 which is the first cluster of
  * the cluster heap.
diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h
index 78be6964a8a0..90d907609e47 100644
--- a/fs/exfat/exfat_fs.h
+++ b/fs/exfat/exfat_fs.h
@@ -457,6 +457,7 @@ int exfat_load_bitmap(struct super_block *sb);
 void exfat_free_bitmap(struct exfat_sb_info *sbi);
 int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync);
 void exfat_clear_bitmap(struct inode *inode, unsigned int clu, bool sync);
+bool exfat_test_bitmap(struct super_block *sb, unsigned int clu);
 unsigned int exfat_find_free_bitmap(struct super_block *sb, unsigned int clu);
 int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count);
 int exfat_trim_fs(struct inode *inode, struct fstrim_range *range);
diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c
index 56b870d9cc0d..5d8b7413d80d 100644
--- a/fs/exfat/fatent.c
+++ b/fs/exfat/fatent.c
@@ -199,6 +199,14 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain
 			unsigned int n_clu = clu;
 			int err = exfat_get_next_cluster(sb, &n_clu);
 
+			/*
+			 * To avoid the cluster chain itself including a loop
+			 * causing an infinite loop.
+			 */
+			if (num_clusters >= p_chain->size &&
+			    !exfat_test_bitmap(sb, clu))
+				break;
+
 			if (err || n_clu == EXFAT_EOF_CLUSTER)
 				sync = true;
 			else
-- 
2.43.0


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux Kernel]     [Linux Kernel Hardening]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux