* [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