[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <20250528215559.1983214-9-sashal@kernel.org>
Date: Wed, 28 May 2025 17:55:59 -0400
From: Sasha Levin <sashal@...nel.org>
To: patches@...ts.linux.dev,
stable@...r.kernel.org
Cc: Ming Lei <ming.lei@...hat.com>,
Hannes Reinecke <hare@...e.de>,
Nilay Shroff <nilay@...ux.ibm.com>,
Christoph Hellwig <hch@....de>,
Jens Axboe <axboe@...nel.dk>,
Sasha Levin <sashal@...nel.org>,
linux-block@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH AUTOSEL 6.15 9/9] block: use q->elevator with ->elevator_lock held in elv_iosched_show()
From: Ming Lei <ming.lei@...hat.com>
[ Upstream commit 94209d27d14104ed828ca88cd5403a99162fe51a ]
Use q->elevator with ->elevator_lock held in elv_iosched_show(), since
the local cached elevator reference may become stale after getting
->elevator_lock.
Reviewed-by: Hannes Reinecke <hare@...e.de>
Reviewed-by: Nilay Shroff <nilay@...ux.ibm.com>
Reviewed-by: Christoph Hellwig <hch@....de>
Signed-off-by: Ming Lei <ming.lei@...hat.com>
Link: https://lore.kernel.org/r/20250505141805.2751237-5-ming.lei@redhat.com
Signed-off-by: Jens Axboe <axboe@...nel.dk>
Signed-off-by: Sasha Levin <sashal@...nel.org>
---
The environment variable is set. Now let me analyze the commit mentioned
in the prompt: **Subject**: block: use q->elevator with ->elevator_lock
held in elv_iosched_show() **Analysis of the code changes**: The commit
fixes a race condition in the block elevator subsystem in
`elv_iosched_show()`. Here's what it does: 1. **Removes local cached
variable**: The commit removes the local variable `struct elevator_queue
*eq = q->elevator;` that was caching the elevator queue reference. 2.
**Accesses q->elevator under lock**: Instead of using the cached
`eq->type`, it now directly accesses `q->elevator->type` while holding
the `->elevator_lock` mutex. 3. **Fixes race condition**: The old code
had a time-of-check-time-of-use (TOCTOU) race where the cached `eq`
could become stale after acquiring the `->elevator_lock`, but before
actually using `eq->type`. **Analysis of backport suitability**: Looking
at similar commits in the reference history: - Similar Commit #4 was
marked YES for backporting because it fixed a real bug with clear user
impact - The other similar commits were marked NO because they were code
cleanups/optimizations without fixing actual bugs This commit: 1.
**Fixes a real race condition bug** - The cached elevator reference
could become invalid between when it's stored and when it's used 2.
**Has clear user impact** - Race conditions in the elevator code could
lead to crashes or memory corruption when users access
`/sys/block/*/queue/scheduler` 3. **Is a small, contained fix** - Only
changes a few lines in one function 4. **Has minimal regression risk** -
Simply ensures proper locking is used when accessing shared data 5.
**Follows stable tree rules** - It's an important bugfix with minimal
risk The commit message explicitly states the problem: "the local cached
elevator reference may become stale after getting ->elevator_lock" -
this is a classic race condition that could cause system instability.
**YES** This commit should be backported to stable kernel trees. It
fixes a race condition in the block elevator subsystem where a cached
elevator reference could become stale between the time it's stored and
when it's actually used, even after acquiring the elevator lock. The fix
is minimal and safe - it simply ensures that `q->elevator->type` is
accessed directly while holding the lock rather than using a potentially
stale cached reference. This prevents potential crashes or memory
corruption when users access the scheduler interface in
`/sys/block/*/queue/scheduler`. The change is small, contained to a
single function, has clear bug-fixing intent, and follows stable tree
criteria of being an important bugfix with minimal regression risk.
block/elevator.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/block/elevator.c b/block/elevator.c
index b4d08026b02ce..dc4cadef728e5 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -744,7 +744,6 @@ ssize_t elv_iosched_store(struct gendisk *disk, const char *buf,
ssize_t elv_iosched_show(struct gendisk *disk, char *name)
{
struct request_queue *q = disk->queue;
- struct elevator_queue *eq = q->elevator;
struct elevator_type *cur = NULL, *e;
int len = 0;
@@ -753,7 +752,7 @@ ssize_t elv_iosched_show(struct gendisk *disk, char *name)
len += sprintf(name+len, "[none] ");
} else {
len += sprintf(name+len, "none ");
- cur = eq->type;
+ cur = q->elevator->type;
}
spin_lock(&elv_list_lock);
--
2.39.5
Powered by blists - more mailing lists