* [PATCH] aoe: consolidate flags update to prevent race condition
@ 2024-06-11 3:52 Gui-Dong Han
2024-06-12 16:54 ` Jens Axboe
0 siblings, 1 reply; 3+ messages in thread
From: Gui-Dong Han @ 2024-06-11 3:52 UTC (permalink / raw)
To: justin, axboe; +Cc: linux-block, linux-kernel, baijiaju1990, Gui-Dong Han
In aoecmd_sleepwork, there is a race condition caused by two consecutive
writes to the 'flags' variable within a critical section. If a read
operation occurs between these writes, an intermediate state may be
read, potentially causing bugs.
To address this issue, the 'flags' variable should be updated in a
single operation to ensure atomicity and prevent any intermediate state
from being read.
Fixes: 3ae1c24e395b ("[PATCH] aoe [2/8]: support dynamic resizing of AoE devices")
Signed-off-by: Gui-Dong Han <hanguidong02@outlook.com>
---
drivers/block/aoe/aoecmd.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index cc9077b588d7..37d556f019c0 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -897,8 +897,7 @@ aoecmd_sleepwork(struct work_struct *work)
set_capacity_and_notify(d->gd, d->ssize);
spin_lock_irq(&d->lock);
- d->flags |= DEVFL_UP;
- d->flags &= ~DEVFL_NEWSIZE;
+ d->flags = (d->flags | DEVFL_UP) & ~DEVFL_NEWSIZE;
spin_unlock_irq(&d->lock);
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] aoe: consolidate flags update to prevent race condition
2024-06-11 3:52 [PATCH] aoe: consolidate flags update to prevent race condition Gui-Dong Han
@ 2024-06-12 16:54 ` Jens Axboe
2025-02-25 3:13 ` Gui-Dong Han
0 siblings, 1 reply; 3+ messages in thread
From: Jens Axboe @ 2024-06-12 16:54 UTC (permalink / raw)
To: Gui-Dong Han, justin; +Cc: linux-block, linux-kernel, baijiaju1990
On 6/10/24 9:52 PM, Gui-Dong Han wrote:
> In aoecmd_sleepwork, there is a race condition caused by two consecutive
> writes to the 'flags' variable within a critical section. If a read
> operation occurs between these writes, an intermediate state may be
> read, potentially causing bugs.
>
> To address this issue, the 'flags' variable should be updated in a
> single operation to ensure atomicity and prevent any intermediate state
> from being read.
>
> Fixes: 3ae1c24e395b ("[PATCH] aoe [2/8]: support dynamic resizing of AoE devices")
> Signed-off-by: Gui-Dong Han <hanguidong02@outlook.com>
> ---
> drivers/block/aoe/aoecmd.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
> index cc9077b588d7..37d556f019c0 100644
> --- a/drivers/block/aoe/aoecmd.c
> +++ b/drivers/block/aoe/aoecmd.c
> @@ -897,8 +897,7 @@ aoecmd_sleepwork(struct work_struct *work)
> set_capacity_and_notify(d->gd, d->ssize);
>
> spin_lock_irq(&d->lock);
> - d->flags |= DEVFL_UP;
> - d->flags &= ~DEVFL_NEWSIZE;
> + d->flags = (d->flags | DEVFL_UP) & ~DEVFL_NEWSIZE;
> spin_unlock_irq(&d->lock);
> }
It's modified under the lock, and any reader should do so as well. If
not, there's a race regardless of your change or not.
--
Jens Axboe
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] aoe: consolidate flags update to prevent race condition
2024-06-12 16:54 ` Jens Axboe
@ 2025-02-25 3:13 ` Gui-Dong Han
0 siblings, 0 replies; 3+ messages in thread
From: Gui-Dong Han @ 2025-02-25 3:13 UTC (permalink / raw)
To: Jens Axboe, justin@coraid.com
Cc: linux-block@vger.kernel.org, linux-kernel@vger.kernel.org,
baijiaju1990@gmail.com
Hi Jens,
Thank you for your feedback. Let me clarify the rationale behind this change.
On 2024-06-12 10:54, Jens Axboe wrote:
> It's modified under the lock, and any reader should do so as well. If
> not, there's a race regardless of your change or not.
The existing implementation contains multiple unsynchronized reads of d->flags.
For example, in aoecmd_sleepwork() itself:
void aoecmd_sleepwork(struct work_struct *work)
{
struct aoedev *d = container_of(work, struct aoedev, work);
/* These flag checks are performed WITHOUT LOCKING: */
if (d->flags & DEVFL_GDALLOC) <--- Unsynchronized read
aoeblk_gdalloc(d);
if (d->flags & DEVFL_NEWSIZE) { <--- Unsynchronized read
set_capacity_and_notify(d->gd, d->ssize);
spin_lock_irq(&d->lock);
d->flags |= DEVFL_UP; <--- Two separate writes
d->flags &= ~DEVFL_NEWSIZE; <--- to flags under lock
spin_unlock_irq(&d->lock);
}
}
The problematic sequence would be:
1. Thread A sets DEVFL_UP under lock
2. Thread B (or same thread) reads d->flags without lock, sees DEVFL_UP set but
DEVFL_NEWSIZE still present (before the second write clears it)
3. This could lead to unexpected behavior since DEVFL_NEWSIZE indicates a state
transition that should be atomic with DEVFL_UP setting
By consolidating the flag updates into a single atomic operation under lock:
d->flags = (d->flags | DEVFL_UP) & ~DEVFL_NEWSIZE;
We ensure any unsynchronized reader (like the DEVFL_NEWSIZE check in this same
function) will either see both changes or neither, avoiding intermediate states.
Would you agree this provides stronger consistency guarantees for readers that
(per current code) don't take the lock when checking flags?
Best regards,
Gui-Dong Han
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-02-25 3:13 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-11 3:52 [PATCH] aoe: consolidate flags update to prevent race condition Gui-Dong Han
2024-06-12 16:54 ` Jens Axboe
2025-02-25 3:13 ` Gui-Dong Han
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).