Skip to content

Commit 2f02b5a

Browse files
TomRita999axboe
authored andcommitted
drbd: Fix atomicity violation in drbd_uuid_set_bm()
The violation of atomicity occurs when the drbd_uuid_set_bm function is executed simultaneously with modifying the value of device->ldev->md.uuid[UI_BITMAP]. Consider a scenario where, while device->ldev->md.uuid[UI_BITMAP] passes the validity check when its value is not zero, the value of device->ldev->md.uuid[UI_BITMAP] is written to zero. In this case, the check in drbd_uuid_set_bm might refer to the old value of device->ldev->md.uuid[UI_BITMAP] (before locking), which allows an invalid value to pass the validity check, resulting in inconsistency. To address this issue, it is recommended to include the data validity check within the locked section of the function. This modification ensures that the value of device->ldev->md.uuid[UI_BITMAP] does not change during the validation process, thereby maintaining its integrity. This possible bug is found by an experimental static analysis tool developed by our team. This tool analyzes the locking APIs to extract function pairs that can be concurrently executed, and then analyzes the instructions in the paired functions to identify possible concurrency bugs including data races and atomicity violations. Fixes: 9f2247b ("drbd: Protect accesses to the uuid set with a spinlock") Cc: stable@vger.kernel.org Signed-off-by: Qiu-ji Chen <chenqiuji666@gmail.com> Reviewed-by: Philipp Reisner <philipp.reisner@linbit.com> Link: https://lore.kernel.org/r/20240913083504.10549-1-chenqiuji666@gmail.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent e3accac commit 2f02b5a

File tree

1 file changed

+4
-2
lines changed

1 file changed

+4
-2
lines changed

drivers/block/drbd/drbd_main.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3399,10 +3399,12 @@ void drbd_uuid_new_current(struct drbd_device *device) __must_hold(local)
33993399
void drbd_uuid_set_bm(struct drbd_device *device, u64 val) __must_hold(local)
34003400
{
34013401
unsigned long flags;
3402-
if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0)
3402+
spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
3403+
if (device->ldev->md.uuid[UI_BITMAP] == 0 && val == 0) {
3404+
spin_unlock_irqrestore(&device->ldev->md.uuid_lock, flags);
34033405
return;
3406+
}
34043407

3405-
spin_lock_irqsave(&device->ldev->md.uuid_lock, flags);
34063408
if (val == 0) {
34073409
drbd_uuid_move_history(device);
34083410
device->ldev->md.uuid[UI_HISTORY_START] = device->ldev->md.uuid[UI_BITMAP];

0 commit comments

Comments
 (0)