[PATCH] dm-integrity: fix deadlock with overlapping I/O

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

 



Hi

I've found quite a serious bug in dm-integrity - it will deadlock when 
processing overlapping bios.

Please send this patch to Linus.

Mikulas



From: Mikulas Patocka <mpatocka@xxxxxxxxxx>

dm-integrity could deadlock with overlapping I/O, the bug was introduced
by a patch 724376a04d1a ("dm integrity: implement fair range locks").
Apparently, few users use overlapping I/O, so the bug went undetected for
so long.

In order to fix the bug, we fix the typos in the function ranges_overlap
and we remove a flawed ranges_overlap check in remove_range_unlocked. This
condition could leave unprocessed bios hanging on wait_list forever.

Signed-off-by: Mikulas Patocka <mpatocka@xxxxxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx	# v4.19+
Fixes: 724376a04d1a ("dm integrity: implement fair range locks")

---
 drivers/md/dm-integrity.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

Index: linux-2.6/drivers/md/dm-integrity.c
===================================================================
--- linux-2.6.orig/drivers/md/dm-integrity.c	2019-04-05 19:48:13.000000000 +0200
+++ linux-2.6/drivers/md/dm-integrity.c	2019-04-05 20:04:22.000000000 +0200
@@ -878,7 +878,7 @@ static void copy_from_journal(struct dm_
 static bool ranges_overlap(struct dm_integrity_range *range1, struct dm_integrity_range *range2)
 {
 	return range1->logical_sector < range2->logical_sector + range2->n_sectors &&
-	       range2->logical_sector + range2->n_sectors > range2->logical_sector;
+	       range1->logical_sector + range1->n_sectors > range2->logical_sector;
 }
 
 static bool add_new_range(struct dm_integrity_c *ic, struct dm_integrity_range *new_range, bool check_waiting)
@@ -924,8 +924,6 @@ static void remove_range_unlocked(struct
 		struct dm_integrity_range *last_range =
 			list_first_entry(&ic->wait_list, struct dm_integrity_range, wait_entry);
 		struct task_struct *last_range_task;
-		if (!ranges_overlap(range, last_range))
-			break;
 		last_range_task = last_range->task;
 		list_del(&last_range->wait_entry);
 		if (!add_new_range(ic, last_range, false)) {

--
dm-devel mailing list
dm-devel@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/dm-devel



[Index of Archives]     [DM Crypt]     [Fedora Desktop]     [ATA RAID]     [Fedora Marketing]     [Fedora Packaging]     [Fedora SELinux]     [Yosemite Discussion]     [KDE Users]     [Fedora Docs]

  Powered by Linux