Linux Btrfs filesystem development
 help / color / mirror / Atom feed
* [PATCH v2 0/2] btrfs: fix a couple races between scrub and the scrub progress ioctl
@ 2026-10-16 17:09 fdmanana
  2026-10-16 17:09 ` [PATCH v2 1/2] btrfs: scrub: fix race leading to use-after-free in " fdmanana
  2026-10-16 17:09 ` [PATCH v2 2/2] btrfs: scrub: fix race between scrub and " fdmanana
  0 siblings, 2 replies; 3+ messages in thread
From: fdmanana @ 2026-10-16 17:09 UTC (permalink / raw)
  To: linux-btrfs

From: Filipe Manana <fdmanana@suse.com>

Details in the change logs.

V2: Added a another patch to fix another race (patch 1/2).

Filipe Manana (2):
  btrfs: scrub: fix race leading to use-after-free in the scrub progress ioctl
  btrfs: scrub: fix race between scrub and scrub progress ioctl

 fs/btrfs/scrub.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

-- 
2.53.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v2 1/2] btrfs: scrub: fix race leading to use-after-free in the scrub progress ioctl
  2026-10-16 17:09 [PATCH v2 0/2] btrfs: fix a couple races between scrub and the scrub progress ioctl fdmanana
@ 2026-10-16 17:09 ` fdmanana
  2026-10-16 17:09 ` [PATCH v2 2/2] btrfs: scrub: fix race between scrub and " fdmanana
  1 sibling, 0 replies; 3+ messages in thread
From: fdmanana @ 2026-10-16 17:09 UTC (permalink / raw)
  To: linux-btrfs

From: Filipe Manana <fdmanana@suse.com>

If the scrub progress ioctl is called when replace is about to finish, we
have a race that can result in a use-after-free of the scrub context:

1) A scrub is finishing and is at btrfs_scrub_dev();

2) A concurrent task called the scrub progress ioctl and is in
   btrfs_scrub_progress(), where it takes the device_list_mutex and grabs
   the device. Then it starts using the device's scrub context (for a
   memcpy operation);

3) While the scrub progress ioctl task is running, the scrub task sets
   the device's scrub_ctx to NULL (acquiring fs_info->scrub_lock) and
   then calls scrub_put_ctx() against the scrub context, dropping the
   last reference and freeing the memory - while the scrub progress ioctl
   task is still using it, resulting in a use-after-free.

Fix this by changing btrfs_scrub_progress() to take fs_info->scrub_lock
before using the scrub context.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
 fs/btrfs/scrub.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 0eb30625439b..389ebb5f7d61 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -3293,10 +3293,13 @@ int btrfs_scrub_progress(struct btrfs_fs_info *fs_info, u64 devid,
 
 	mutex_lock(&fs_info->fs_devices->device_list_mutex);
 	dev = btrfs_find_device(fs_info->fs_devices, &args);
-	if (dev)
+	if (dev) {
+		mutex_lock(&fs_info->scrub_lock);
 		sctx = dev->scrub_ctx;
-	if (sctx)
-		memcpy(progress, &sctx->stat, sizeof(*progress));
+		if (sctx)
+			memcpy(progress, &sctx->stat, sizeof(*progress));
+		mutex_unlock(&fs_info->scrub_lock);
+	}
 	mutex_unlock(&fs_info->fs_devices->device_list_mutex);
 
 	return dev ? (sctx ? 0 : -ENOTCONN) : -ENODEV;
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH v2 2/2] btrfs: scrub: fix race between scrub and scrub progress ioctl
  2026-10-16 17:09 [PATCH v2 0/2] btrfs: fix a couple races between scrub and the scrub progress ioctl fdmanana
  2026-10-16 17:09 ` [PATCH v2 1/2] btrfs: scrub: fix race leading to use-after-free in " fdmanana
@ 2026-10-16 17:09 ` fdmanana
  1 sibling, 0 replies; 3+ messages in thread
From: fdmanana @ 2026-10-16 17:09 UTC (permalink / raw)
  To: linux-btrfs

From: Filipe Manana <fdmanana@suse.com>

The scrub progress ioctl is copying the scrub progress stats without
acquiring the spinlock that protects it and a concurrent scrub can be
updating the stats at the same time which can lead to load tearing
issues. So take the spinlock when copying the progress stats.

Signed-off-by: Filipe Manana <fdmanana@suse.com>
---
 fs/btrfs/scrub.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 389ebb5f7d61..e9ef17d4d43b 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -3296,8 +3296,11 @@ int btrfs_scrub_progress(struct btrfs_fs_info *fs_info, u64 devid,
 	if (dev) {
 		mutex_lock(&fs_info->scrub_lock);
 		sctx = dev->scrub_ctx;
-		if (sctx)
+		if (sctx) {
+			spin_lock(&sctx->stat_lock);
 			memcpy(progress, &sctx->stat, sizeof(*progress));
+			spin_unlock(&sctx->stat_lock);
+		}
 		mutex_unlock(&fs_info->scrub_lock);
 	}
 	mutex_unlock(&fs_info->fs_devices->device_list_mutex);
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-10-16 17:09 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 17:09 [PATCH v2 0/2] btrfs: fix a couple races between scrub and the scrub progress ioctl fdmanana
2026-10-16 17:09 ` [PATCH v2 1/2] btrfs: scrub: fix race leading to use-after-free in " fdmanana
2026-10-16 17:09 ` [PATCH v2 2/2] btrfs: scrub: fix race between scrub and " fdmanana

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox