* [PATCH] block/loop: Fix NULL pointer dereference in lo_rw_aio()
@ 2026-05-19 4:01 Hongling Zeng
2026-05-19 4:42 ` Ming Lei
0 siblings, 1 reply; 7+ messages in thread
From: Hongling Zeng @ 2026-05-19 4:01 UTC (permalink / raw)
To: axboe, ming.lei; +Cc: linux-block, linux-kernel, zhongling0719, Hongling Zeng
lo->lo_backing_file can be NULL when the loop device is being cleared,
causing NULL pointer dereference in lo_rw_aio(). Add a defensive check
to prevent kernel crash.
Also fix loop_attr_backing_file_show() to use PTR_ERR_OR_ZERO()
for correct NULL pointer handling.
Fixes: bc07c10a3603a ("block: loop: support DIO & AIO")
Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
---
drivers/block/loop.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 0000913f7efc..d8db1b0d8018 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -397,6 +397,9 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
cmd->iocb.ki_flags = 0;
}
+ if (!file)
+ return -EIO;
+
if (rw == ITER_SOURCE) {
kiocb_start_write(&cmd->iocb);
ret = file->f_op->write_iter(&cmd->iocb, &iter);
@@ -662,7 +665,7 @@ static ssize_t loop_attr_backing_file_show(struct loop_device *lo, char *buf)
spin_unlock_irq(&lo->lo_lock);
if (IS_ERR_OR_NULL(p))
- ret = PTR_ERR(p);
+ ret = PTR_ERR_OR_ZERO(p);
else {
ret = strlen(p);
memmove(buf, p, ret);
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] block/loop: Fix NULL pointer dereference in lo_rw_aio()
2026-05-19 4:01 [PATCH] block/loop: Fix NULL pointer dereference in lo_rw_aio() Hongling Zeng
@ 2026-05-19 4:42 ` Ming Lei
2026-05-19 6:06 ` Hongling Zeng
0 siblings, 1 reply; 7+ messages in thread
From: Ming Lei @ 2026-05-19 4:42 UTC (permalink / raw)
To: Hongling Zeng; +Cc: axboe, ming.lei, linux-block, linux-kernel, zhongling0719
On Tue, May 19, 2026 at 12:01:03PM +0800, Hongling Zeng wrote:
> lo->lo_backing_file can be NULL when the loop device is being cleared,
> causing NULL pointer dereference in lo_rw_aio(). Add a defensive check
> to prevent kernel crash.
In v7.1-rc tree, lo->lo_backing_file is cleared in __loop_clr_fd(), which
is called from lo_release() only, when it is guaranteed that there isn't
inflight IO.
So care to share your stack trace?
>
> Also fix loop_attr_backing_file_show() to use PTR_ERR_OR_ZERO()
> for correct NULL pointer handling.
>
> Fixes: bc07c10a3603a ("block: loop: support DIO & AIO")
Can you explain how the issue is introduced in above commit?
> Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
> ---
> drivers/block/loop.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/block/loop.c b/drivers/block/loop.c
> index 0000913f7efc..d8db1b0d8018 100644
> --- a/drivers/block/loop.c
> +++ b/drivers/block/loop.c
> @@ -397,6 +397,9 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
> cmd->iocb.ki_flags = 0;
> }
>
> + if (!file)
> + return -EIO;
If lo->lo_backing_file may become NULL, it isn't enough to add check here
only, cause it can be observed in lo_req_flush() & lo_fallocate() too.
Thanks,
Ming
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] block/loop: Fix NULL pointer dereference in lo_rw_aio()
2026-05-19 4:42 ` Ming Lei
@ 2026-05-19 6:06 ` Hongling Zeng
2026-05-19 8:33 ` Ming Lei
0 siblings, 1 reply; 7+ messages in thread
From: Hongling Zeng @ 2026-05-19 6:06 UTC (permalink / raw)
To: Ming Lei, Hongling Zeng; +Cc: axboe, ming.lei, linux-block, linux-kernel
Hi,
Thank you for the review.
在 2026年05月19日 12:42, Ming Lei 写道:
> On Tue, May 19, 2026 at 12:01:03PM +0800, Hongling Zeng wrote:
>> lo->lo_backing_file can be NULL when the loop device is being cleared,
>> causing NULL pointer dereference in lo_rw_aio(). Add a defensive check
>> to prevent kernel crash.
>>
>> In v7.1-rc tree, lo->lo_backing_file is cleared in __loop_clr_fd(), which
>> is called from lo_release() only, when it is guaranteed that there isn't
>> inflight IO.
>>
>> So care to share your stack trace?
Syzkaller has managed to trigger NULL pointer dereference in lo_rw_aio().
Tetsuo Handa encountered the same issue (commit 1a83d226268cf), but his
patch only adds diagnostic logging and is marked "not for upstream".
>> Also fix loop_attr_backing_file_show() to use PTR_ERR_OR_ZERO()
>> for correct NULL pointer handling.
>>
>> Fixes: bc07c10a3603a ("block: loop: support DIO & AIO")
> Can you explain how the issue is introduced in above commit?
The issue was introduced when lo_rw_aio() was added in that commit,
which dereferences lo->lo_backing_file without NULL checks. While the
design assumes no inflight IO during __loop_clr_fd(), fuzzers have
found edge cases where this assumption doesn't hold.
>> Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
>> ---
>> drivers/block/loop.c | 5 ++++-
>> 1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/block/loop.c b/drivers/block/loop.c
>> index 0000913f7efc..d8db1b0d8018 100644
>> --- a/drivers/block/loop.c
>> +++ b/drivers/block/loop.c
>> @@ -397,6 +397,9 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
>> cmd->iocb.ki_flags = 0;
>> }
>>
>> + if (!file)
>> + return -EIO;
> If lo->lo_backing_file may become NULL, it isn't enough to add check here
> only, cause it can be observed in lo_req_flush() & lo_fallocate() too.
>
>
> Thanks,
> Ming
You're absolutely right. Tetsuo's approach only adds logging to help
diagnose the issue (and he marked it "not for upstream"), but it doesn't
prevent the crash.
To properly fix this, I need to add NULL checks to all functions that
dereference lo->lo_backing_file:
- lo_rw_aio()
- lo_req_flush()
- lo_fallocate()
- loop_update_limits()
- lo_can_use_dio()
What's your preferred approach?
1. Simple NULL checks in all functions
2. A helper function with proper locking
3. Your recommendation
Let me know which approach you think is best, and I'll update the patch
accordingly.
Regards,
Hongling
~
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] block/loop: Fix NULL pointer dereference in lo_rw_aio()
2026-05-19 6:06 ` Hongling Zeng
@ 2026-05-19 8:33 ` Ming Lei
[not found] ` <6A0C29F6.5080704@126.com>
0 siblings, 1 reply; 7+ messages in thread
From: Ming Lei @ 2026-05-19 8:33 UTC (permalink / raw)
To: Hongling Zeng; +Cc: Hongling Zeng, axboe, ming.lei, linux-block, linux-kernel
On Tue, May 19, 2026 at 02:06:26PM +0800, Hongling Zeng wrote:
> Hi,
>
> Thank you for the review.
>
> 在 2026年05月19日 12:42, Ming Lei 写道:
> > On Tue, May 19, 2026 at 12:01:03PM +0800, Hongling Zeng wrote:
> > > lo->lo_backing_file can be NULL when the loop device is being cleared,
> > > causing NULL pointer dereference in lo_rw_aio(). Add a defensive check
> > > to prevent kernel crash.
> > >
> > > In v7.1-rc tree, lo->lo_backing_file is cleared in __loop_clr_fd(), which
> > > is called from lo_release() only, when it is guaranteed that there isn't
> > > inflight IO.
> > >
> > > So care to share your stack trace?
> Syzkaller has managed to trigger NULL pointer dereference in lo_rw_aio().
> Tetsuo Handa encountered the same issue (commit 1a83d226268cf), but his
> patch only adds diagnostic logging and is marked "not for upstream".
> > > Also fix loop_attr_backing_file_show() to use PTR_ERR_OR_ZERO()
> > > for correct NULL pointer handling.
> > >
> > > Fixes: bc07c10a3603a ("block: loop: support DIO & AIO")
> > Can you explain how the issue is introduced in above commit?
> The issue was introduced when lo_rw_aio() was added in that commit,
> which dereferences lo->lo_backing_file without NULL checks. While the
> design assumes no inflight IO during __loop_clr_fd(), fuzzers have
> found edge cases where this assumption doesn't hold.
What are the edge cases?
>
> > > Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
> > > ---
> > > drivers/block/loop.c | 5 ++++-
> > > 1 file changed, 4 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/block/loop.c b/drivers/block/loop.c
> > > index 0000913f7efc..d8db1b0d8018 100644
> > > --- a/drivers/block/loop.c
> > > +++ b/drivers/block/loop.c
> > > @@ -397,6 +397,9 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
> > > cmd->iocb.ki_flags = 0;
> > > }
> > > + if (!file)
> > > + return -EIO;
> > If lo->lo_backing_file may become NULL, it isn't enough to add check here
> > only, cause it can be observed in lo_req_flush() & lo_fallocate() too.
> >
> >
> > Thanks,
> > Ming
> You're absolutely right. Tetsuo's approach only adds logging to help
> diagnose the issue (and he marked it "not for upstream"), but it doesn't
> prevent the crash.
>
> To properly fix this, I need to add NULL checks to all functions that
> dereference lo->lo_backing_file:
> - lo_rw_aio()
> - lo_req_flush()
> - lo_fallocate()
> - loop_update_limits()
> - lo_can_use_dio()
>
> What's your preferred approach?
> 1. Simple NULL checks in all functions
> 2. A helper function with proper locking
> 3. Your recommendation
>
> Let me know which approach you think is best, and I'll update the patch
> accordingly.
It isn't supposed to happen, so please root-cause first before sending
any workaround.
Thanks,
Ming
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] block/loop: Fix NULL pointer dereference in lo_rw_aio()
[not found] ` <6A0C29F6.5080704@126.com>
@ 2026-05-19 11:28 ` Ming Lei
2026-05-19 12:37 ` Tetsuo Handa
0 siblings, 1 reply; 7+ messages in thread
From: Ming Lei @ 2026-05-19 11:28 UTC (permalink / raw)
To: Hongling Zeng
Cc: Hongling Zeng, axboe, ming.lei, linux-block, linux-kernel,
Tetsuo Handa
On Tue, May 19, 2026 at 05:14:30PM +0800, Hongling Zeng wrote:
> Hi Ming,
>
> Tetsuo’s syzkaller trace confirms the root cause:
>
> Timeline:
> T6142: lo_rw_aio(loop3) starting read with raw_refcnt=0x0, refcnt=1
> T44: lo_rw_aio(loop3) starting read with raw_refcnt=0x0, refcnt=1
> T6148: __loop_clr_fd(loop3) clearing lo_backing_file with raw_refcnt=0x0,
> refcnt=1
> T180: lo_rw_aio(loop3) starting write with NULL file (already cleared?)
> T180: CRASH - null-ptr-deref
IO could be from writeback or early close, so the following patch should help:
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 0000913f7efc..24654a03db71 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1118,6 +1118,8 @@ static void __loop_clr_fd(struct loop_device *lo)
struct file *filp;
gfp_t gfp = lo->old_gfp_mask;
+ drain_workqueue(lo->workqueue);
+
spin_lock_irq(&lo->lo_lock);
filp = lo->lo_backing_file;
lo->lo_backing_file = NULL;
@@ -1857,9 +1859,6 @@ static blk_status_t loop_queue_rq(struct blk_mq_hw_ctx *hctx,
blk_mq_start_request(rq);
- if (data_race(READ_ONCE(lo->lo_state)) != Lo_bound)
- return BLK_STS_IOERR;
-
switch (req_op(rq)) {
case REQ_OP_FLUSH:
case REQ_OP_DISCARD:
@@ -1901,6 +1900,11 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
int ret = 0;
struct mem_cgroup *old_memcg = NULL;
+ if (data_race(READ_ONCE(lo->lo_state)) != Lo_bound) {
+ ret = -EIO;
+ goto failed;
+ }
+
if (write && (lo->lo_flags & LO_FLAGS_READ_ONLY)) {
ret = -EIO;
goto failed;
>
> Key anomaly: |raw_refcnt=0|while |refcnt=1|.
> This means |__loop_clr_fd()|runs while I/O is still active.
> Regression introduced by:
> 6050fa4c84cc ("loop: don't hold lo_mutex during __loop_clr_fd()")
Why do you conclude it is caused by above commit?
Thanks,
Ming
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH] block/loop: Fix NULL pointer dereference in lo_rw_aio()
2026-05-19 11:28 ` Ming Lei
@ 2026-05-19 12:37 ` Tetsuo Handa
2026-05-20 3:20 ` Hongling Zeng
0 siblings, 1 reply; 7+ messages in thread
From: Tetsuo Handa @ 2026-05-19 12:37 UTC (permalink / raw)
To: Ming Lei, Hongling Zeng
Cc: Hongling Zeng, axboe, ming.lei, linux-block, linux-kernel
On 2026/05/19 20:28, Ming Lei wrote:
>> This means |__loop_clr_fd()|runs while I/O is still active.
>> Regression introduced by:
>> 6050fa4c84cc ("loop: don't hold lo_mutex during __loop_clr_fd()")
>
> Why do you conclude it is caused by above commit?
Some commit in the merge window for 7.1 broke the loop driver.
Even synchronize_rcu() + drain_workqueue(lo->workqueue) is not sufficient.
Please see a thread at https://lkml.kernel.org/r/d43125ff-cc66-49b7-b16d-1b2650c68c23@I-love.SAKURA.ne.jp .
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] block/loop: Fix NULL pointer dereference in lo_rw_aio()
2026-05-19 12:37 ` Tetsuo Handa
@ 2026-05-20 3:20 ` Hongling Zeng
0 siblings, 0 replies; 7+ messages in thread
From: Hongling Zeng @ 2026-05-20 3:20 UTC (permalink / raw)
To: Tetsuo Handa, Ming Lei
Cc: Hongling Zeng, axboe, ming.lei, linux-block, linux-kernel
Thanks, I'll review Tetsuo's analysis to better understand
the full scope of the issue.
在 2026年05月19日 20:37, Tetsuo Handa 写道:
> On 2026/05/19 20:28, Ming Lei wrote:
>>> This means |__loop_clr_fd()|runs while I/O is still active.
>>> Regression introduced by:
>>> 6050fa4c84cc ("loop: don't hold lo_mutex during __loop_clr_fd()")
>> Why do you conclude it is caused by above commit?
> Some commit in the merge window for 7.1 broke the loop driver.
> Even synchronize_rcu() + drain_workqueue(lo->workqueue) is not sufficient.
> Please see a thread at https://lkml.kernel.org/r/d43125ff-cc66-49b7-b16d-1b2650c68c23@I-love.SAKURA.ne.jp .
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-05-20 3:20 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-19 4:01 [PATCH] block/loop: Fix NULL pointer dereference in lo_rw_aio() Hongling Zeng
2026-05-19 4:42 ` Ming Lei
2026-05-19 6:06 ` Hongling Zeng
2026-05-19 8:33 ` Ming Lei
[not found] ` <6A0C29F6.5080704@126.com>
2026-05-19 11:28 ` Ming Lei
2026-05-19 12:37 ` Tetsuo Handa
2026-05-20 3:20 ` Hongling Zeng
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox