Linux block layer
 help / color / mirror / Atom feed
* [PATCH 0/2] loop: Fix teardown
@ 2026-09-16 19:51 Bart Van Assche
  2026-09-16 19:51 ` [PATCH 1/2] block: Add post_release() operation Bart Van Assche
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Bart Van Assche @ 2026-09-16 19:51 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-block, Christoph Hellwig, Tetsuo Handa, Nilay Shroff,
	Bart Van Assche

Hi Jens,

My attempts to help Tetsuo with fixing the issues in his loop driver patch
series have not been successful so far. Hence this patch series. (See also
https://lore.kernel.org/linux-block/60bf7af2-b84e-4056-9195-a26ad51ada46@I-love.SAKURA.ne.jp/).

When tearing down an autoclear loop device upon release, the loop driver
must drain in-flight I/O and flush workqueues to prevent NULL pointer
dereferences in lo_rw_aio() and related I/O paths.

However, the .release() block device callback is invoked while holding
disk->open_mutex. Freezing the request queue or draining workqueues under
disk->open_mutex causes lock inversion and circular locking dependencies
(e.g., when worker threads or I/O completion paths also acquire open_mutex
or interact with request queue synchronization).

This patch series resolves the lock inversion by:
1. Adding a .post_release() block device operation that is called
   synchronously from bdev_release() immediately after disk->open_mutex
   is released.
2. Migrating __loop_clr_fd() to .post_release(), allowing loop device
   teardown and queue freezing to happen outside of disk->open_mutex.

Please consider applying this patch series.

Thanks,

Bart.

Bart Van Assche (2):
  block: Add post_release() operation
  loop: Perform __loop_clr_fd() after disk->open_mutex is dropped

 block/bdev.c                     |  3 ++
 drivers/block/loop.c             | 51 +++++++++++++++++++++++---------
 include/linux/blkdev.h           |  5 ++++
 rust/kernel/block/mq/gen_disk.rs |  1 +
 4 files changed, 46 insertions(+), 14 deletions(-)


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

* [PATCH 1/2] block: Add post_release() operation
  2026-09-16 19:51 [PATCH 0/2] loop: Fix teardown Bart Van Assche
@ 2026-09-16 19:51 ` Bart Van Assche
  2026-09-16 19:51 ` [PATCH 2/2] loop: Perform __loop_clr_fd() after disk->open_mutex is dropped Bart Van Assche
  2026-09-19  2:48 ` [syzbot ci] Re: loop: Fix teardown syzbot ci
  2 siblings, 0 replies; 7+ messages in thread
From: Bart Van Assche @ 2026-09-16 19:51 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-block, Christoph Hellwig, Tetsuo Handa, Nilay Shroff,
	Bart Van Assche, Andreas Hindborg, Miguel Ojeda, Gary Guo,
	Haoze Xie, Ke Sun

Add post_release() block device operation which provides a hook for
performing synchronous cleanup without disk->open_mutex held.
This is needed by block drivers (such as the loop device) that must
drain in-flight I/O and perform synchronization after disk->open_mutex
has been released.

Suggested-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 block/bdev.c                     | 3 +++
 include/linux/blkdev.h           | 5 +++++
 rust/kernel/block/mq/gen_disk.rs | 1 +
 3 files changed, 9 insertions(+)

diff --git a/block/bdev.c b/block/bdev.c
index fac74319e9fb..350f3c29d682 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -1189,6 +1189,9 @@ void bdev_release(struct file *bdev_file)
 		blkdev_put_whole(bdev);
 	mutex_unlock(&disk->open_mutex);
 
+	if (disk->fops->post_release)
+		disk->fops->post_release(disk);
+
 	module_put(disk->fops->owner);
 put_no_open:
 	blkdev_put_no_open(bdev);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index d003a9d2d1f6..b35f8af1243e 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1580,6 +1580,11 @@ struct block_device_operations {
 			unsigned int flags);
 	int (*open)(struct gendisk *disk, blk_mode_t mode);
 	void (*release)(struct gendisk *disk);
+	/*
+	 * Called after disk->open_mutex is released in the bdev_release() path,
+	 * after .release(). Implementations may sleep.
+	 */
+	void (*post_release)(struct gendisk *disk);
 	int (*ioctl)(struct block_device *bdev, blk_mode_t mode,
 			unsigned cmd, unsigned long arg);
 	int (*compat_ioctl)(struct block_device *bdev, blk_mode_t mode,
diff --git a/rust/kernel/block/mq/gen_disk.rs b/rust/kernel/block/mq/gen_disk.rs
index fc97dd873974..2ff77ef49781 100644
--- a/rust/kernel/block/mq/gen_disk.rs
+++ b/rust/kernel/block/mq/gen_disk.rs
@@ -129,6 +129,7 @@ pub fn build<T: Operations>(
             submit_bio: None,
             open: None,
             release: None,
+            post_release: None,
             ioctl: None,
             compat_ioctl: None,
             check_events: None,

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

* [PATCH 2/2] loop: Perform __loop_clr_fd() after disk->open_mutex is dropped
  2026-09-16 19:51 [PATCH 0/2] loop: Fix teardown Bart Van Assche
  2026-09-16 19:51 ` [PATCH 1/2] block: Add post_release() operation Bart Van Assche
@ 2026-09-16 19:51 ` Bart Van Assche
  2026-09-16 22:47   ` Tetsuo Handa
  2026-09-19  2:48 ` [syzbot ci] Re: loop: Fix teardown syzbot ci
  2 siblings, 1 reply; 7+ messages in thread
From: Bart Van Assche @ 2026-09-16 19:51 UTC (permalink / raw)
  To: Jens Axboe
  Cc: linux-block, Christoph Hellwig, Tetsuo Handa, Nilay Shroff,
	Bart Van Assche

In order to prevent NULL pointer dereferences in lo_rw_aio() when tearing
down a loop device, outstanding I/O must be flushed before clearing the
backing file and device state. However, calling blk_mq_wait_quiesce_done(),
drain_workqueue(), or blk_mq_freeze_queue() with disk->open_mutex held
causes lockdep warnings and potential deadlocks.

Use the .post_release() block device operation to execute __loop_clr_fd()
synchronously after disk->open_mutex has been released by the block layer.
Inside __loop_clr_fd(), outstanding I/O is flushed and the request queue
is frozen before acquiring disk->open_mutex to perform the remaining
device teardown and partition rescans.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
 drivers/block/loop.c | 51 ++++++++++++++++++++++++++++++++------------
 1 file changed, 37 insertions(+), 14 deletions(-)

diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 758c20678bf6..d3e686bebcd3 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1138,11 +1138,33 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode,
 
 static void __loop_clr_fd(struct loop_device *lo)
 {
+	struct gendisk *disk = lo->lo_disk;
 	struct queue_limits lim;
 	struct file *filp;
 	gfp_t gfp = lo->old_gfp_mask;
+	unsigned int memflags;
 	int err;
 
+	WARN_ON_ONCE(READ_ONCE(lo->lo_state) != Lo_rundown);
+
+	/*
+	 * Wait for ongoing loop_queue_rq() calls. Subsequent loop_queue_rq()
+	 * calls which are made after this call returned will see lo->lo_state
+	 * != Lo_bound and return with BLK_STS_IOERR.
+	 */
+	blk_mq_wait_quiesce_done(&lo->tag_set);
+
+	/* loop_queue_rq() queues work on lo->workqueue, hence drain it. */
+	drain_workqueue(lo->workqueue);
+
+	lim = queue_limits_start_update(lo->lo_queue);
+
+	/*
+	 * Freeze the request queue while updating parameters used while
+	 * processing requests.
+	 */
+	memflags = blk_mq_freeze_queue(lo->lo_queue);
+
 	spin_lock_irq(&lo->lo_lock);
 	filp = lo->lo_backing_file;
 	lo->lo_backing_file = NULL;
@@ -1153,18 +1175,17 @@ static void __loop_clr_fd(struct loop_device *lo)
 	lo->lo_sizelimit = 0;
 	memset(lo->lo_file_name, 0, LO_NAME_SIZE);
 
-	/*
-	 * Reset the block size to the default.
-	 *
-	 * No queue freezing needed because this is called from the final
-	 * ->release call only, so there can't be any outstanding I/O.
-	 */
-	lim = queue_limits_start_update(lo->lo_queue);
+	/* Reset the block size to the default. */
 	lim.logical_block_size = SECTOR_SIZE;
 	lim.physical_block_size = SECTOR_SIZE;
 	lim.io_min = SECTOR_SIZE;
 	queue_limits_commit_update(lo->lo_queue, &lim);
 
+	blk_mq_unfreeze_queue(lo->lo_queue, memflags);
+
+	/* Serialize against concurrent bdev_open() calls. */
+	mutex_lock(&disk->open_mutex);
+
 	invalidate_disk(lo->lo_disk);
 	loop_sysfs_exit(lo);
 	/* let user-space know about this change */
@@ -1178,9 +1199,6 @@ static void __loop_clr_fd(struct loop_device *lo)
 	/*
 	 * Remove all partitions, including partitions added manually with
 	 * BLKPG, which may exist even if LO_FLAGS_PARTSCAN is not set.
-	 *
-	 * open_mutex has been held already in release path, so don't acquire
-	 * it here.
 	 */
 	err = bdev_disk_changed(lo->lo_disk, false);
 	if (err)
@@ -1197,6 +1215,8 @@ static void __loop_clr_fd(struct loop_device *lo)
 	lo->lo_flags = 0;
 	if (!part_shift)
 		set_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state);
+	mutex_unlock(&disk->open_mutex);
+
 	mutex_lock(&lo->lo_mutex);
 	WRITE_ONCE(lo->lo_state, Lo_unbound);
 	mutex_unlock(&lo->lo_mutex);
@@ -1754,7 +1774,6 @@ static int lo_open(struct gendisk *disk, blk_mode_t mode)
 static void lo_release(struct gendisk *disk)
 {
 	struct loop_device *lo = disk->private_data;
-	bool need_clear = false;
 
 	if (disk_openers(disk) > 0)
 		return;
@@ -1767,11 +1786,14 @@ static void lo_release(struct gendisk *disk)
 	mutex_lock(&lo->lo_mutex);
 	if (lo->lo_state == Lo_bound && (lo->lo_flags & LO_FLAGS_AUTOCLEAR))
 		WRITE_ONCE(lo->lo_state, Lo_rundown);
-
-	need_clear = (lo->lo_state == Lo_rundown);
 	mutex_unlock(&lo->lo_mutex);
+}
+
+static void lo_post_release(struct gendisk *disk)
+{
+	struct loop_device *lo = disk->private_data;
 
-	if (need_clear)
+	if (READ_ONCE(lo->lo_state) == Lo_rundown)
 		__loop_clr_fd(lo);
 }
 
@@ -1791,6 +1813,7 @@ static const struct block_device_operations lo_fops = {
 	.owner =	THIS_MODULE,
 	.open =         lo_open,
 	.release =	lo_release,
+	.post_release = lo_post_release,
 	.ioctl =	lo_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl =	lo_compat_ioctl,

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

* Re: [PATCH 2/2] loop: Perform __loop_clr_fd() after disk->open_mutex is dropped
  2026-09-16 19:51 ` [PATCH 2/2] loop: Perform __loop_clr_fd() after disk->open_mutex is dropped Bart Van Assche
@ 2026-09-16 22:47   ` Tetsuo Handa
  2026-09-16 23:05     ` Bart Van Assche
  0 siblings, 1 reply; 7+ messages in thread
From: Tetsuo Handa @ 2026-09-16 22:47 UTC (permalink / raw)
  To: Bart Van Assche, Jens Axboe, Linus Torvalds
  Cc: linux-block, Christoph Hellwig, Nilay Shroff

On 2026/09/17 4:51, Bart Van Assche wrote:
> In order to prevent NULL pointer dereferences in lo_rw_aio() when tearing
> down a loop device, outstanding I/O must be flushed before clearing the
> backing file and device state. However, calling blk_mq_wait_quiesce_done(),
> drain_workqueue(), or blk_mq_freeze_queue() with disk->open_mutex held
> causes lockdep warnings and potential deadlocks.
> 
> Use the .post_release() block device operation to execute __loop_clr_fd()
> synchronously after disk->open_mutex has been released by the block layer.
> Inside __loop_clr_fd(), outstanding I/O is flushed and the request queue
> is frozen before acquiring disk->open_mutex to perform the remaining
> device teardown and partition rescans.
> 
> Signed-off-by: Bart Van Assche <bvanassche@acm.org>

Nacked-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>

Please stop stealing my series and stop proposing broken series.
Instead of spreading lies claiming that my patch series hasn't been working,
please answer my questions.

Your proposed patch introduces a critical concurrency regression that results in
kernel crash (NULL-filp dereference).

Since .post_release is called entirely outside of disk->open_mutex, multiple
non-final close() threads can concurrently invoke lo_post_release() and race
inside __loop_clr_fd() without any serialization. Specifically, Thread 1 can
nullify lo->lo_backing_file under lo->lo_lock. A concurrent Thread 2 will then
fetch lo_backing_file as NULL, yet immediately attempt to dereference it inside
mapping_set_gfp_mask(filp->f_mapping, ...). This triggers an instantaneous NULL
pointer dereference (Oops) and panics the kernel.

The "post_release() operation is intended for performing only idempotent actions
such as flush_work()" in my series is a requirement. Note that concurrently calling
flush_work() from lo_post_release() is safe.

> ---
>  drivers/block/loop.c | 51 ++++++++++++++++++++++++++++++++------------
>  1 file changed, 37 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/block/loop.c b/drivers/block/loop.c
> index 758c20678bf6..d3e686bebcd3 100644
> --- a/drivers/block/loop.c
> +++ b/drivers/block/loop.c
> @@ -1138,11 +1138,33 @@ static int loop_configure(struct loop_device *lo, blk_mode_t mode,
>  
>  static void __loop_clr_fd(struct loop_device *lo)
>  {
> +	struct gendisk *disk = lo->lo_disk;
>  	struct queue_limits lim;
>  	struct file *filp;
>  	gfp_t gfp = lo->old_gfp_mask;
> +	unsigned int memflags;
>  	int err;
>  
> +	WARN_ON_ONCE(READ_ONCE(lo->lo_state) != Lo_rundown);
> +
> +	/*
> +	 * Wait for ongoing loop_queue_rq() calls. Subsequent loop_queue_rq()
> +	 * calls which are made after this call returned will see lo->lo_state
> +	 * != Lo_bound and return with BLK_STS_IOERR.
> +	 */
> +	blk_mq_wait_quiesce_done(&lo->tag_set);
> +
> +	/* loop_queue_rq() queues work on lo->workqueue, hence drain it. */
> +	drain_workqueue(lo->workqueue);
> +
> +	lim = queue_limits_start_update(lo->lo_queue);
> +
> +	/*
> +	 * Freeze the request queue while updating parameters used while
> +	 * processing requests.
> +	 */
> +	memflags = blk_mq_freeze_queue(lo->lo_queue);
> +
>  	spin_lock_irq(&lo->lo_lock);
>  	filp = lo->lo_backing_file;
>  	lo->lo_backing_file = NULL;
> @@ -1153,18 +1175,17 @@ static void __loop_clr_fd(struct loop_device *lo)
>  	lo->lo_sizelimit = 0;
>  	memset(lo->lo_file_name, 0, LO_NAME_SIZE);
>  
> -	/*
> -	 * Reset the block size to the default.
> -	 *
> -	 * No queue freezing needed because this is called from the final
> -	 * ->release call only, so there can't be any outstanding I/O.
> -	 */
> -	lim = queue_limits_start_update(lo->lo_queue);
> +	/* Reset the block size to the default. */
>  	lim.logical_block_size = SECTOR_SIZE;
>  	lim.physical_block_size = SECTOR_SIZE;
>  	lim.io_min = SECTOR_SIZE;
>  	queue_limits_commit_update(lo->lo_queue, &lim);
>  
> +	blk_mq_unfreeze_queue(lo->lo_queue, memflags);
> +
> +	/* Serialize against concurrent bdev_open() calls. */
> +	mutex_lock(&disk->open_mutex);
> +
>  	invalidate_disk(lo->lo_disk);
>  	loop_sysfs_exit(lo);
>  	/* let user-space know about this change */
> @@ -1178,9 +1199,6 @@ static void __loop_clr_fd(struct loop_device *lo)
>  	/*
>  	 * Remove all partitions, including partitions added manually with
>  	 * BLKPG, which may exist even if LO_FLAGS_PARTSCAN is not set.
> -	 *
> -	 * open_mutex has been held already in release path, so don't acquire
> -	 * it here.
>  	 */
>  	err = bdev_disk_changed(lo->lo_disk, false);
>  	if (err)
> @@ -1197,6 +1215,8 @@ static void __loop_clr_fd(struct loop_device *lo)
>  	lo->lo_flags = 0;
>  	if (!part_shift)
>  		set_bit(GD_SUPPRESS_PART_SCAN, &lo->lo_disk->state);
> +	mutex_unlock(&disk->open_mutex);
> +
>  	mutex_lock(&lo->lo_mutex);
>  	WRITE_ONCE(lo->lo_state, Lo_unbound);
>  	mutex_unlock(&lo->lo_mutex);
> @@ -1754,7 +1774,6 @@ static int lo_open(struct gendisk *disk, blk_mode_t mode)
>  static void lo_release(struct gendisk *disk)
>  {
>  	struct loop_device *lo = disk->private_data;
> -	bool need_clear = false;
>  
>  	if (disk_openers(disk) > 0)
>  		return;
> @@ -1767,11 +1786,14 @@ static void lo_release(struct gendisk *disk)
>  	mutex_lock(&lo->lo_mutex);
>  	if (lo->lo_state == Lo_bound && (lo->lo_flags & LO_FLAGS_AUTOCLEAR))
>  		WRITE_ONCE(lo->lo_state, Lo_rundown);
> -
> -	need_clear = (lo->lo_state == Lo_rundown);
>  	mutex_unlock(&lo->lo_mutex);
> +}
> +
> +static void lo_post_release(struct gendisk *disk)
> +{
> +	struct loop_device *lo = disk->private_data;
>  
> -	if (need_clear)
> +	if (READ_ONCE(lo->lo_state) == Lo_rundown)
>  		__loop_clr_fd(lo);
>  }
>  
> @@ -1791,6 +1813,7 @@ static const struct block_device_operations lo_fops = {
>  	.owner =	THIS_MODULE,
>  	.open =         lo_open,
>  	.release =	lo_release,
> +	.post_release = lo_post_release,
>  	.ioctl =	lo_ioctl,
>  #ifdef CONFIG_COMPAT
>  	.compat_ioctl =	lo_compat_ioctl,


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

* Re: [PATCH 2/2] loop: Perform __loop_clr_fd() after disk->open_mutex is dropped
  2026-09-16 22:47   ` Tetsuo Handa
@ 2026-09-16 23:05     ` Bart Van Assche
  2026-09-17  0:16       ` Tetsuo Handa
  0 siblings, 1 reply; 7+ messages in thread
From: Bart Van Assche @ 2026-09-16 23:05 UTC (permalink / raw)
  To: Tetsuo Handa, Jens Axboe, Linus Torvalds
  Cc: linux-block, Christoph Hellwig, Nilay Shroff

On 9/16/26 3:47 PM, Tetsuo Handa wrote:
> Please stop stealing my series

No, I'm not stealing your work. I credited you in the first patch with a
Suggested-by.

> and stop proposing broken series.

I think we disagree. My view is that your series is broken.
Additionally, I have explained multiple times in detail why I think
your series is broken but you chose to ignore my feedback.

> Since .post_release is called entirely outside of disk->open_mutex, multiple
> non-final close() threads can concurrently invoke lo_post_release() and race
> inside __loop_clr_fd() without any serialization.

This is wrong. The .release() and .post_release() callbacks are only
called once. The following code from fs/file_table.c illustrates this:

void fput(struct file *file)
{
	if (unlikely(file_ref_put(&file->f_ref)))
		__fput_deferred(file);
}

/* the real guts of fput() - releasing the last reference to file */
static void __fput(struct file *file)
{
	[ ... ]
	if (file->f_op->release)
		file->f_op->release(inode, file);
	[ ... ]
}

Thanks,

Bart.

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

* Re: [PATCH 2/2] loop: Perform __loop_clr_fd() after disk->open_mutex is dropped
  2026-09-16 23:05     ` Bart Van Assche
@ 2026-09-17  0:16       ` Tetsuo Handa
  0 siblings, 0 replies; 7+ messages in thread
From: Tetsuo Handa @ 2026-09-17  0:16 UTC (permalink / raw)
  To: Bart Van Assche, Jens Axboe, Linus Torvalds
  Cc: linux-block, Christoph Hellwig, Nilay Shroff

On 2026/09/17 8:05, Bart Van Assche wrote:
>> Since .post_release is called entirely outside of disk->open_mutex, multiple
>> non-final close() threads can concurrently invoke lo_post_release() and race
>> inside __loop_clr_fd() without any serialization.
> 
> This is wrong. The .release() and .post_release() callbacks are only
> called once. The following code from fs/file_table.c illustrates this:
> 
> void fput(struct file *file)
> {
>     if (unlikely(file_ref_put(&file->f_ref)))
>         __fput_deferred(file);
> }
> 
> /* the real guts of fput() - releasing the last reference to file */
> static void __fput(struct file *file)
> {
>     [ ... ]
>     if (file->f_op->release)
>         file->f_op->release(inode, file);
>     [ ... ]
> }

You are misunderstanding bdev_release() concurrency for the same "struct gendisk"
even if __fput() for the same "struct file" does not run concurrently.

Two processes can obtain file descriptor of the same loop device using open() syscall.
Two processes can release that file descriptor using close() syscall.

While __fput() is serialized within each thread because it runs under the task work context,
lo_post_release() (for the same "struct loop_device" which can be derived from "struct gendisk")
is not serialized between two processes.


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

* [syzbot ci] Re: loop: Fix teardown
  2026-09-16 19:51 [PATCH 0/2] loop: Fix teardown Bart Van Assche
  2026-09-16 19:51 ` [PATCH 1/2] block: Add post_release() operation Bart Van Assche
  2026-09-16 19:51 ` [PATCH 2/2] loop: Perform __loop_clr_fd() after disk->open_mutex is dropped Bart Van Assche
@ 2026-09-19  2:48 ` syzbot ci
  2 siblings, 0 replies; 7+ messages in thread
From: syzbot ci @ 2026-09-19  2:48 UTC (permalink / raw)
  To: a.hindborg, axboe, bvanassche, gary, hch, linux-block, nilay,
	ojeda, penguin-kernel, royenheart, sunke
  Cc: syzbot, syzkaller-bugs

syzbot ci has tested the following series

[v1] loop: Fix teardown
https://lore.kernel.org/all/cover.1789587960.git.bvanassche@acm.org
* [PATCH 1/2] block: Add post_release() operation
* [PATCH 2/2] loop: Perform __loop_clr_fd() after disk->open_mutex is dropped

and found the following issue:
general protection fault in lo_post_release

Full report is available here:
https://ci.syzbot.org/series/81bfb244-11b0-4b8a-aa02-a212681ff0af

***

general protection fault in lo_post_release

tree:      axboe
URL:       https://kernel.googlesource.com/pub/scm/linux/kernel/git/axboe/linux.git
base:      2dd9768a37dbb99398c5e332485dbb107ac397c8
arch:      amd64
compiler:  Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
config:    https://ci.syzbot.org/builds/e21a78bb-e498-4518-8734-d31ae58a2538/config

Oops: general protection fault, probably for non-canonical address 0xdffffc000000000a: 0000 [#1] SMP KASAN PTI
KASAN: null-ptr-deref in range [0x0000000000000050-0x0000000000000057]
CPU: 0 UID: 0 PID: 26297 Comm: udevd Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
RIP: 0010:lo_post_release+0x498/0x7f0
Code: 4c 89 ff e8 7a 73 f9 fb bf e0 01 00 00 49 03 3f be 02 00 00 00 e8 18 05 9e 05 48 8b 44 24 10 4c 8d 60 50 4c 89 e0 48 c1 e8 03 <42> 80 3c 30 00 74 08 4c 89 e7 e8 49 73 f9 fb 41 bf e8 00 00 00 4d
RSP: 0018:ffffc90003d6fb60 EFLAGS: 00010206
RAX: 000000000000000a RBX: ffff8881699b3000 RCX: 0000000000000046
RDX: 0000000000000006 RSI: ffffffff8e414976 RDI: ffffffff8c6da780
RBP: ffffc90003d6fd08 R08: ffffffff907a477f R09: 1ffffffff20f48ef
R10: dffffc0000000000 R11: fffffbfff20f48f0 R12: 0000000000000050
R13: 1ffff920007adf74 R14: dffffc0000000000 R15: ffff888169a02080
FS:  00007fa1afb46c80(0000) GS:ffff88818d6ce000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f0d423a8440 CR3: 00000001bee1a000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 bdev_release+0x59a/0x6b0
 blkdev_release+0x15/0x20
 __fput+0x418/0xa50
 fput_close_sync+0x11f/0x240
 __x64_sys_close+0x7e/0x110
 do_syscall_64+0x166/0x520
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fa1af7170a8
Code: 48 8b 05 83 9d 0d 00 64 c7 00 16 00 00 00 83 c8 ff 48 83 c4 20 5b c3 64 8b 04 25 18 00 00 00 85 c0 75 20 b8 03 00 00 00 0f 05 <48> 3d 00 f0 ff ff 76 5b 48 8b 15 51 9d 0d 00 f7 d8 64 89 02 48 83
RSP: 002b:00007ffeef68bbb8 EFLAGS: 00000246 ORIG_RAX: 0000000000000003
RAX: ffffffffffffffda RBX: 00007fa1afb46ae0 RCX: 00007fa1af7170a8
RDX: 0000559097caaeb5 RSI: 00007ffeef68b3b8 RDI: 0000000000000008
RBP: 00005595ce9a3e90 R08: 0000000000000006 R09: a8cc15e7d6acaf3b
R10: 000000000000010f R11: 0000000000000246 R12: 0000000000000002
R13: 00005595ce999920 R14: 0000000000000008 R15: 00005595ce964910
 </TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
RIP: 0010:lo_post_release+0x498/0x7f0
Code: 4c 89 ff e8 7a 73 f9 fb bf e0 01 00 00 49 03 3f be 02 00 00 00 e8 18 05 9e 05 48 8b 44 24 10 4c 8d 60 50 4c 89 e0 48 c1 e8 03 <42> 80 3c 30 00 74 08 4c 89 e7 e8 49 73 f9 fb 41 bf e8 00 00 00 4d
RSP: 0018:ffffc90003d6fb60 EFLAGS: 00010206
RAX: 000000000000000a RBX: ffff8881699b3000 RCX: 0000000000000046
RDX: 0000000000000006 RSI: ffffffff8e414976 RDI: ffffffff8c6da780
RBP: ffffc90003d6fd08 R08: ffffffff907a477f R09: 1ffffffff20f48ef
R10: dffffc0000000000 R11: fffffbfff20f48f0 R12: 0000000000000050
R13: 1ffff920007adf74 R14: dffffc0000000000 R15: ffff888169a02080
FS:  00007fa1afb46c80(0000) GS:ffff88818d6ce000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000055556cac6a68 CR3: 00000001bee1a000 CR4: 00000000000006f0


***

If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
  Tested-by: syzbot@syzkaller.appspotmail.com

---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.

To test a fix for this bug, please reply with `#syz test`
(on a separate line) and attach the patch to the email.

Notes:
- The patch will be applied on top of the tested series (as an
  incremental fix).
- To test a new version of the whole series, please send it directly
  to syzbot@lists.linux.dev.
- Arguments like custom git repos and branches are not supported.

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

end of thread, other threads:[~2026-09-19  2:48 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-16 19:51 [PATCH 0/2] loop: Fix teardown Bart Van Assche
2026-09-16 19:51 ` [PATCH 1/2] block: Add post_release() operation Bart Van Assche
2026-09-16 19:51 ` [PATCH 2/2] loop: Perform __loop_clr_fd() after disk->open_mutex is dropped Bart Van Assche
2026-09-16 22:47   ` Tetsuo Handa
2026-09-16 23:05     ` Bart Van Assche
2026-09-17  0:16       ` Tetsuo Handa
2026-09-19  2:48 ` [syzbot ci] Re: loop: Fix teardown syzbot ci

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