]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
dm-mirror: fix a tiny race condition
authorMikulas Patocka <mpatocka@redhat.com>
Tue, 3 Jun 2025 16:53:17 +0000 (18:53 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 27 Jun 2025 10:04:14 +0000 (11:04 +0100)
commit 829451beaed6165eb11d7a9fb4e28eb17f489980 upstream.

There's a tiny race condition in dm-mirror. The functions queue_bio and
write_callback grab a spinlock, add a bio to the list, drop the spinlock
and wake up the mirrord thread that processes bios in the list.

It may be possible that the mirrord thread processes the bio just after
spin_unlock_irqrestore is called, before wakeup_mirrord. This spurious
wake-up is normally harmless, however if the device mapper device is
unloaded just after the bio was processed, it may be possible that
wakeup_mirrord(ms) uses invalid "ms" pointer.

Fix this bug by moving wakeup_mirrord inside the spinlock.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/md/dm-raid1.c

index fa09bc4e4c54a14c0889b69843ad1693f880c1f4..a4578b3321de7e23e607d120c687f835cd6457c3 100644 (file)
@@ -128,10 +128,9 @@ static void queue_bio(struct mirror_set *ms, struct bio *bio, int rw)
        spin_lock_irqsave(&ms->lock, flags);
        should_wake = !(bl->head);
        bio_list_add(bl, bio);
-       spin_unlock_irqrestore(&ms->lock, flags);
-
        if (should_wake)
                wakeup_mirrord(ms);
+       spin_unlock_irqrestore(&ms->lock, flags);
 }
 
 static void dispatch_bios(void *context, struct bio_list *bio_list)
@@ -638,9 +637,9 @@ static void write_callback(unsigned long error, void *context)
        if (!ms->failures.head)
                should_wake = 1;
        bio_list_add(&ms->failures, bio);
-       spin_unlock_irqrestore(&ms->lock, flags);
        if (should_wake)
                wakeup_mirrord(ms);
+       spin_unlock_irqrestore(&ms->lock, flags);
 }
 
 static void do_write(struct mirror_set *ms, struct bio *bio)