diff mbox series

[1/2] dm-integrity: Avoid divide by zero in table status in Inline mode

Message ID 20250216104210.572120-1-gmazyland@gmail.com (mailing list archive)
State Accepted, archived
Delegated to: Mikulas Patocka
Headers show
Series [1/2] dm-integrity: Avoid divide by zero in table status in Inline mode | expand

Commit Message

Milan Broz Feb. 16, 2025, 10:42 a.m. UTC
In Inline mode, the journal is unused, and journal_sectors is zero.

Calculating the journal watermark requires dividing by journal_sectors,
which should be done only if the journal is configured.

Otherwise, a simple table query (dmsetup table) can cause OOPS.

This bug did not show on some systems, perhaps only due to
compiler optimization.

On my 32-bit testing machine, this reliably crashes with the following:

 : Oops: divide error: 0000 [#1] PREEMPT SMP
 : CPU: 0 UID: 0 PID: 2450 Comm: dmsetup Not tainted 6.14.0-rc2+ #959
 : EIP: dm_integrity_status+0x2f8/0xab0 [dm_integrity]
 ...

Signed-off-by: Milan Broz <gmazyland@gmail.com>
Fixes: fb0987682c62 ("dm-integrity: introduce the Inline mode")
Cc: stable@vger.kernel.org # 6.11+
---
 drivers/md/dm-integrity.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

Comments

Mikulas Patocka Feb. 17, 2025, 10:37 a.m. UTC | #1
On Sun, 16 Feb 2025, Milan Broz wrote:

> In Inline mode, the journal is unused, and journal_sectors is zero.
> 
> Calculating the journal watermark requires dividing by journal_sectors,
> which should be done only if the journal is configured.
> 
> Otherwise, a simple table query (dmsetup table) can cause OOPS.
> 
> This bug did not show on some systems, perhaps only due to
> compiler optimization.
> 
> On my 32-bit testing machine, this reliably crashes with the following:
> 
>  : Oops: divide error: 0000 [#1] PREEMPT SMP
>  : CPU: 0 UID: 0 PID: 2450 Comm: dmsetup Not tainted 6.14.0-rc2+ #959
>  : EIP: dm_integrity_status+0x2f8/0xab0 [dm_integrity]
>  ...
> 
> Signed-off-by: Milan Broz <gmazyland@gmail.com>
> Fixes: fb0987682c62 ("dm-integrity: introduce the Inline mode")
> Cc: stable@vger.kernel.org # 6.11+

Both patches applied, thanks.

Mikulas
diff mbox series

Patch

diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index ee9f7cecd78e..555dc06b9422 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -3790,10 +3790,6 @@  static void dm_integrity_status(struct dm_target *ti, status_type_t type,
 		break;
 
 	case STATUSTYPE_TABLE: {
-		__u64 watermark_percentage = (__u64)(ic->journal_entries - ic->free_sectors_threshold) * 100;
-
-		watermark_percentage += ic->journal_entries / 2;
-		do_div(watermark_percentage, ic->journal_entries);
 		arg_count = 3;
 		arg_count += !!ic->meta_dev;
 		arg_count += ic->sectors_per_block != 1;
@@ -3826,6 +3822,10 @@  static void dm_integrity_status(struct dm_target *ti, status_type_t type,
 		DMEMIT(" interleave_sectors:%u", 1U << ic->sb->log2_interleave_sectors);
 		DMEMIT(" buffer_sectors:%u", 1U << ic->log2_buffer_sectors);
 		if (ic->mode == 'J') {
+			__u64 watermark_percentage = (__u64)(ic->journal_entries - ic->free_sectors_threshold) * 100;
+
+			watermark_percentage += ic->journal_entries / 2;
+			do_div(watermark_percentage, ic->journal_entries);
 			DMEMIT(" journal_watermark:%u", (unsigned int)watermark_percentage);
 			DMEMIT(" commit_time:%u", ic->autocommit_msec);
 		}