Linux block layer
 help / color / mirror / Atom feed
* [RESEND][SECURITY] block: double unpin in bounced direct reads
@ 2026-07-10 12:26 Neptune
  2026-07-13  9:29 ` Christoph Hellwig
  0 siblings, 1 reply; 4+ messages in thread
From: Neptune @ 2026-07-10 12:26 UTC (permalink / raw)
  To: Jens Axboe, Christoph Hellwig; +Cc: linux-block, security

[-- Attachment #1: Type: text/plain, Size: 5247 bytes --]

Resending in plain text because my first message was rejected by the
mailing list due to its MIME format. The technical content is
unchanged.

Hi Jens, Christoph,

I found a double-unpin in the block-layer read-bounce path that can be
reached by an unprivileged process through XFS direct I/O. I
reproduced it as a uid-1000 to uid-0 privilege escalation on mainline
commit 0e35b9b6ec0f. The bug was introduced by e7b8b3c5b2a6 ("block:
align down bounces bios"), which first appears in v7.1-rc4.

AI-assisted tooling was used during the source review and validation.
I independently verified the bug against the source, reproduced the
complete privilege-escalation chain, and tested the proposed fix. I am
treating the finding as public for coordination purposes, but I have
not included the reproducer or exploit in this message.

bio_iov_iter_bounce_read() stores the bounce folio in bi_io_vec[0],
while the extracted user bvecs start at bi_io_vec[1]. bi_vcnt counts
only those user bvecs. bio_iov_iter_align_down(), however, treats
bi_vcnt as the length of an array starting at slot zero and selects
the last vector with bio->bi_io_vec[bio->bi_vcnt - 1].

I create the partial extraction with three iovecs: a one-byte mapped
segment, a 512-byte mapped segment, and a 511-byte PROT_NONE segment.
The complete 1024-byte read is aligned, but pinning the third segment
fails after the first two segments have already produced 513 bytes.
This leaves the following state immediately before trimming:

    bi_size        = 513
    bi_vcnt        = 2
    len_align_mask = 511

    vec[0] = bounce folio,     len 513
    vec[1] = first user page,  len   1
    vec[2] = second user page, len 512

The one-byte remainder should be removed from vec[2], but the helper
selects vec[1]. Because that bvec is exactly one byte long, it is
removed and its page is unpinned. bi_vcnt becomes one, and read-bounce
completion subsequently walks the user array from vec[1] and unpins
the same page again. Once the partial-extraction state has been
created, the two unpins are deterministic and do not depend on a race.

The in-tree path I confirmed is xfs_file_dio_read() with
IOMAP_DIO_BOUNCE set when mapping_stable_writes() is true. The trigger
needs a non-DAX XFS file backed by an allocated extent on a device
that either provides an integrity checksum or advertises
BLK_FEAT_STABLE_WRITES. It only requires read access to that file and
an aligned O_DIRECT vectored read; raw block-device access and
capabilities are not required. In my test setup, queue/stable_writes
was zero, but the NVMe namespace exposed T10-DIF-TYPE1-CRC, which also
makes bdev_stable_writes() true.

For the privilege-escalation test, I registered the page backing the
one-byte first iovec as an io_uring fixed buffer before triggering the
bug. The DIO pin and the fixed-buffer pin account for two
GUP_PIN_COUNTING_BIAS references. GDB showed a refcount of 2050 at the
first erroneous unpin, followed by 2050 -> 1026 in the trim path and
1026 -> 2 in read-bounce completion. After munmap() and memfd
teardown, the page is freed while io_uring still retains its bvec and
old PFN.

I then reclaimed that PFN as the page-cache page containing the entry
point of a root-owned setuid ELF. IORING_OP_WRITE_FIXED was used as a
read oracle to confirm the reuse, and IORING_OP_READ_FIXED replaced
the entry point with a position-independent
setuid(0)/execve("/bin/sh") payload. This does not require a kernel
address leak or kernel control-flow hijacking.

The vulnerable kernel produced:

    $ id
    uid=1000(ctf) gid=1000(ctf) groups=1000(ctf)
    $ /bio_bounce_lpe
    [*] uid=1000
    [+] stale page hit
    [+] exec
    # id
    uid=0(root) gid=0(root) groups=1000(ctf)

With the proposed fix, using the same config, initramfs, NVMe PI
namespace and XFS setup, the exploit no longer obtains a stale page:

    $ /bio_bounce_lpe
    [*] uid=1000
    [-] stale page miss
    $ id
    uid=1000(ctf) gid=1000(ctf) groups=1000(ctf)

I repeated the fixed-kernel test on fresh images and obtained the same
result. The setuid target in the disposable VM was an unmodified
static BusyBox binary copied onto XFS and installed as root-owned mode
4755. It was only a convenient page-cache target: the exploit parses
the ELF entry point at runtime, does not depend on BusyBox behavior or
a hard-coded offset, and I also validated the same ending with a
dynamically linked PIE executable.

The attached patch changes bio_iov_iter_align_down() to accept the
index of the first vector it is allowed to trim. Existing callers pass
zero and read-bounce passes one. It also updates the bounce bvec
length after alignment and drops the bounce folio if alignment removes
all user data. I tested the resulting kernel in the same VM described
above.

I can provide the minimal trigger, full exploit, disposable initramfs,
exact QEMU command line, and the GDB transcript showing both unpins if
they would be useful for review.

Could you take a look at the analysis and patch? In particular, I
would appreciate your view on whether passing the first vector index
into the alignment helper is the right fix, or whether you would
prefer the read-bounce layout itself to be changed.

Regards,

0wnerD1ed
l7z@0b1t.tech

[-- Attachment #2: 0001-block-fix-bvec-offset-when-aligning-bounced-reads.patch --]
[-- Type: application/octet-stream, Size: 3538 bytes --]

From dae9025b3403bcecb2f1224306cb4b8b22a6c27c Mon Sep 17 00:00:00 2001
From: 0wnerD1ed <l7z@0b1t.tech>
Date: Fri, 10 Jul 2026 19:05:58 +0800
Subject: [PATCH] block: fix bvec offset when aligning bounced reads

bio_iov_iter_bounce_read() stores the bounce folio in bi_io_vec[0] and
extracts user bvecs starting at bi_io_vec[1].  bi_vcnt, however, counts
only the extracted user bvecs.

bio_iov_iter_align_down() assumes that the vectors it trims start at
index zero.  Thus, with two extracted user bvecs it selects index one as
the last vector instead of index two.  If the alignment remainder
consumes that vector, a pinned user page is released even though it is
still present in the completion-side vector array.  Completion releases
the same page again.

Pass the first vector index to the alignment helper and use an offset of
one for bounced reads.  After trimming, also synchronize the bounce
folio length with the aligned bio size.  Release the bounce folio if
alignment removes all user data.

Fixes: e7b8b3c5b2a6 ("block: align down bounces bios")
Cc: stable@vger.kernel.org
Signed-off-by: 0wnerD1ed <l7z@0b1t.tech>
---
 block/bio.c | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index f2a5f4d0a967..6b7d893df169 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1191,7 +1191,7 @@ void bio_iov_bvec_set(struct bio *bio, const struct iov_iter *iter)
  * for the next iteration.
  */
 static int bio_iov_iter_align_down(struct bio *bio, struct iov_iter *iter,
-			    unsigned len_align_mask)
+			    unsigned int len_align_mask, unsigned int first_vec)
 {
 	size_t nbytes = bio->bi_iter.bi_size & len_align_mask;
 
@@ -1201,7 +1201,8 @@ static int bio_iov_iter_align_down(struct bio *bio, struct iov_iter *iter,
 	iov_iter_revert(iter, nbytes);
 	bio->bi_iter.bi_size -= nbytes;
 	do {
-		struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
+		struct bio_vec *bv =
+			&bio->bi_io_vec[first_vec + bio->bi_vcnt - 1];
 
 		if (nbytes < bv->bv_len) {
 			bv->bv_len -= nbytes;
@@ -1276,7 +1277,7 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter,
 
 	if (is_pci_p2pdma_page(bio->bi_io_vec->bv_page))
 		bio->bi_opf |= REQ_NOMERGE;
-	return bio_iov_iter_align_down(bio, iter, len_align_mask);
+	return bio_iov_iter_align_down(bio, iter, len_align_mask, 0);
 }
 
 static struct folio *folio_alloc_greedy(gfp_t gfp, size_t *size,
@@ -1360,7 +1361,7 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
 
 	if (!bio->bi_iter.bi_size)
 		return -ENOMEM;
-	return bio_iov_iter_align_down(bio, iter, minsize - 1);
+	return bio_iov_iter_align_down(bio, iter, minsize - 1, 0);
 }
 
 static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
@@ -1368,6 +1369,7 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
 {
 	size_t len = min3(iov_iter_count(iter), maxlen, SZ_1M);
 	struct folio *folio;
+	int ret;
 
 	folio = folio_alloc_greedy(GFP_KERNEL, &len, minsize);
 	if (!folio)
@@ -1398,7 +1400,13 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
 	bvec_set_folio(&bio->bi_io_vec[0], folio, bio->bi_iter.bi_size, 0);
 	if (iov_iter_extract_will_pin(iter))
 		bio_set_flag(bio, BIO_PAGE_PINNED);
-	return bio_iov_iter_align_down(bio, iter, minsize - 1);
+	ret = bio_iov_iter_align_down(bio, iter, minsize - 1, 1);
+	if (ret) {
+		folio_put(folio);
+		return ret;
+	}
+	bio->bi_io_vec[0].bv_len = bio->bi_iter.bi_size;
+	return 0;
 }
 
 /**
-- 
2.34.1


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

* Re: [RESEND][SECURITY] block: double unpin in bounced direct reads
  2026-07-10 12:26 [RESEND][SECURITY] block: double unpin in bounced direct reads Neptune
@ 2026-07-13  9:29 ` Christoph Hellwig
  2026-07-13 10:20   ` Neptune
  0 siblings, 1 reply; 4+ messages in thread
From: Christoph Hellwig @ 2026-07-13  9:29 UTC (permalink / raw)
  To: Neptune; +Cc: Jens Axboe, Christoph Hellwig, linux-block, security

Does fix the issue for you?  

---
From dda17e13c91e917dd3e317dd740917849472994b Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@lst.de>
Date: Mon, 13 Jul 2026 10:42:34 +0200
Subject: block: fix aligning of bonced dio read bios

bio_iov_iter_align_down expects the "normal" biovec layout from vector 0,
while bio_iov_iter_bounce_read abuses vector 0 for a bounce buffer
allocation.  Pass an explicit bvec to bio_iov_iter_align_down to deal
with this case to avoid a double unpin.

Fixes: e7b8b3c5b2a6 ("block: align down bounces bios")
Reported-by: Neptune <z1281552865@gmail.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/bio.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index f2a5f4d0a967..885b01b6915d 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1191,7 +1191,7 @@ void bio_iov_bvec_set(struct bio *bio, const struct iov_iter *iter)
  * for the next iteration.
  */
 static int bio_iov_iter_align_down(struct bio *bio, struct iov_iter *iter,
-			    unsigned len_align_mask)
+				   struct bio_vec *bv, unsigned len_align_mask)
 {
 	size_t nbytes = bio->bi_iter.bi_size & len_align_mask;
 
@@ -1200,21 +1200,16 @@ static int bio_iov_iter_align_down(struct bio *bio, struct iov_iter *iter,
 
 	iov_iter_revert(iter, nbytes);
 	bio->bi_iter.bi_size -= nbytes;
-	do {
-		struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
-
-		if (nbytes < bv->bv_len) {
-			bv->bv_len -= nbytes;
-			break;
-		}
-
+	while (nbytes >= bv->bv_len) {
 		if (bio_flagged(bio, BIO_PAGE_PINNED))
 			unpin_user_page(bv->bv_page);
 
-		bio->bi_vcnt--;
 		nbytes -= bv->bv_len;
-	} while (nbytes);
+		bio->bi_vcnt--;
+		bv--;
+	}
 
+	bv->bv_len -= nbytes;
 	if (!bio->bi_vcnt)
 		return -EFAULT;
 	return 0;
@@ -1276,7 +1271,8 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter,
 
 	if (is_pci_p2pdma_page(bio->bi_io_vec->bv_page))
 		bio->bi_opf |= REQ_NOMERGE;
-	return bio_iov_iter_align_down(bio, iter, len_align_mask);
+	return bio_iov_iter_align_down(bio, iter,
+			&bio->bi_io_vec[bio->bi_vcnt - 1], len_align_mask);
 }
 
 static struct folio *folio_alloc_greedy(gfp_t gfp, size_t *size,
@@ -1360,7 +1356,8 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
 
 	if (!bio->bi_iter.bi_size)
 		return -ENOMEM;
-	return bio_iov_iter_align_down(bio, iter, minsize - 1);
+	return bio_iov_iter_align_down(bio, iter,
+			&bio->bi_io_vec[bio->bi_vcnt - 1], minsize - 1);
 }
 
 static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
@@ -1398,7 +1395,10 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
 	bvec_set_folio(&bio->bi_io_vec[0], folio, bio->bi_iter.bi_size, 0);
 	if (iov_iter_extract_will_pin(iter))
 		bio_set_flag(bio, BIO_PAGE_PINNED);
-	return bio_iov_iter_align_down(bio, iter, minsize - 1);
+
+	/* The first vec stores the bounce buffer, so do not subtract 1 here. */
+	return bio_iov_iter_align_down(bio, iter,
+			&bio->bi_io_vec[bio->bi_vcnt], minsize - 1);
 }
 
 /**
-- 
2.53.0


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

* Re: [RESEND][SECURITY] block: double unpin in bounced direct reads
  2026-07-13  9:29 ` Christoph Hellwig
@ 2026-07-13 10:20   ` Neptune
  2026-07-13 12:47     ` Christoph Hellwig
  0 siblings, 1 reply; 4+ messages in thread
From: Neptune @ 2026-07-13 10:20 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Jens Axboe, linux-block, security

Hi Christoph,

On Mon, Jul 13, 2026 at 11:29 AM Christoph Hellwig <hch@lst.de> wrote:
> Does fix the issue for you?

Yes, it fixes the reported double-unpin in my original reproducer. I
applied the patch to the vulnerable parent, built an x86-64 KASAN
kernel, and reran the test with the same QEMU NVMe PI namespace and
XFS setup. The exploit now reports a stale page miss and the process
remains uid 1000.

I did find a boundary bug in the rewritten alignment loop. If the bio
contains a single one-byte bvec and nbytes is also one, the first
iteration consumes that bvec, decrements bi_vcnt to zero, and moves bv
before the vector array. The next while condition then dereferences
the invalid bv before the later bi_vcnt check can run.

I reproduced this on the patched kernel with a 512-byte O_DIRECT pread
from a raw virtio block device. The destination starts at the last
byte of a mapped 4 KiB page and the following page is PROT_NONE,
leaving one bvec with bv_len=1 and bv_offset=4095. Immediately before
the loop, GEF showed bi_vcnt=1, nbytes=1, and bv_len=1. After that
bvec was consumed, GEF caught another call to unpin_user_page() with
page=0x100020000, bi_vcnt=0, and nbytes=0; KASAN then reported a
general protection fault from unpin_user_page() through
bio_iov_iter_get_pages().

This boundary test requires permission to open the raw block device.
It is a correctness regression in the proposed loop and is separate
from the original unprivileged XFS entry point.

Keeping the loop driven by nbytes, with the old partial-bvec check
inside it, should avoid evaluating bv after the last vector has been
consumed. The callers can still pass an explicit starting bvec, but
the loop needs to stop as soon as nbytes reaches zero.

I also noticed two read-bounce cleanup details while reviewing the
error paths. If alignment removes every user bvec,
bio_iov_iter_bounce_read() returns the error without dropping the
allocated bounce folio. If alignment succeeds after trimming bytes,
bi_io_vec[0].bv_len retains the pre-trim length even though
bio_iov_iter_unbounce_read() later uses it as the copy length. The
error path appears to need a folio_put(), and the successful path
needs to synchronize vector zero's length with bio->bi_iter.bi_size.

AI assistance disclosure: I used OpenAI Codex to help inspect the
patch and organize the test results. I independently applied and built
the patch, ran the tests, and verified the KASAN and GEF results
described above.

Regards,

0wnerD1ed
l7z@0b1t.tech

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

* Re: [RESEND][SECURITY] block: double unpin in bounced direct reads
  2026-07-13 10:20   ` Neptune
@ 2026-07-13 12:47     ` Christoph Hellwig
  0 siblings, 0 replies; 4+ messages in thread
From: Christoph Hellwig @ 2026-07-13 12:47 UTC (permalink / raw)
  To: Neptune; +Cc: Christoph Hellwig, Jens Axboe, linux-block, security

On Mon, Jul 13, 2026 at 06:20:13PM +0800, Neptune wrote:
> Hi Christoph,
> 
> On Mon, Jul 13, 2026 at 11:29 AM Christoph Hellwig <hch@lst.de> wrote:
> > Does fix the issue for you?
> 
> Yes, it fixes the reported double-unpin in my original reproducer. I
> applied the patch to the vulnerable parent, built an x86-64 KASAN
> kernel, and reran the test with the same QEMU NVMe PI namespace and
> XFS setup. The exploit now reports a stale page miss and the process
> remains uid 1000.
> 
> I did find a boundary bug in the rewritten alignment loop. If the bio
> contains a single one-byte bvec and nbytes is also one, the first
> iteration consumes that bvec, decrements bi_vcnt to zero, and moves bv
> before the vector array. The next while condition then dereferences
> the invalid bv before the later bi_vcnt check can run.
> 
> I reproduced this on the patched kernel with a 512-byte O_DIRECT pread
> from a raw virtio block device. The destination starts at the last
> byte of a mapped 4 KiB page and the following page is PROT_NONE,
> leaving one bvec with bv_len=1 and bv_offset=4095. Immediately before
> the loop, GEF showed bi_vcnt=1, nbytes=1, and bv_len=1. After that
> bvec was consumed, GEF caught another call to unpin_user_page() with
> page=0x100020000, bi_vcnt=0, and nbytes=0; KASAN then reported a
> general protection fault from unpin_user_page() through
> bio_iov_iter_get_pages().
> 
> This boundary test requires permission to open the raw block device.
> It is a correctness regression in the proposed loop and is separate
> from the original unprivileged XFS entry point.
> 
> Keeping the loop driven by nbytes, with the old partial-bvec check
> inside it, should avoid evaluating bv after the last vector has been
> consumed. The callers can still pass an explicit starting bvec, but
> the loop needs to stop as soon as nbytes reaches zero.

Yes, updated version below.

> I also noticed two read-bounce cleanup details while reviewing the
> error paths. If alignment removes every user bvec,
> bio_iov_iter_bounce_read() returns the error without dropping the
> allocated bounce folio. If alignment succeeds after trimming bytes,
> bi_io_vec[0].bv_len retains the pre-trim length even though
> bio_iov_iter_unbounce_read() later uses it as the copy length. The
> error path appears to need a folio_put(), and the successful path
> needs to synchronize vector zero's length with bio->bi_iter.bi_size.

I'll look into that next.

---
From 43e1b03b38264d8fb8c647c8a801bd1e81a4638a Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@lst.de>
Date: Mon, 13 Jul 2026 10:42:34 +0200
Subject: block: fix aligning of bounced dio read bios

bio_iov_iter_align_down expects the "normal" biovec layout from vector 0,
while bio_iov_iter_bounce_read abuses vector 0 for a bounce buffer
allocation.  Pass an explicit bvec to bio_iov_iter_align_down to deal
with this case to avoid a double unpin.

Fixes: e7b8b3c5b2a6 ("block: align down bounces bios")
Reported-by: Neptune <z1281552865@gmail.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 block/bio.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/block/bio.c b/block/bio.c
index f2a5f4d0a967..cc50c603a9f8 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1191,7 +1191,7 @@ void bio_iov_bvec_set(struct bio *bio, const struct iov_iter *iter)
  * for the next iteration.
  */
 static int bio_iov_iter_align_down(struct bio *bio, struct iov_iter *iter,
-			    unsigned len_align_mask)
+				   struct bio_vec *bv, unsigned len_align_mask)
 {
 	size_t nbytes = bio->bi_iter.bi_size & len_align_mask;
 
@@ -1200,9 +1200,7 @@ static int bio_iov_iter_align_down(struct bio *bio, struct iov_iter *iter,
 
 	iov_iter_revert(iter, nbytes);
 	bio->bi_iter.bi_size -= nbytes;
-	do {
-		struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
-
+	for (;;) {
 		if (nbytes < bv->bv_len) {
 			bv->bv_len -= nbytes;
 			break;
@@ -1211,9 +1209,10 @@ static int bio_iov_iter_align_down(struct bio *bio, struct iov_iter *iter,
 		if (bio_flagged(bio, BIO_PAGE_PINNED))
 			unpin_user_page(bv->bv_page);
 
-		bio->bi_vcnt--;
 		nbytes -= bv->bv_len;
-	} while (nbytes);
+		bio->bi_vcnt--;
+		bv--;
+	}
 
 	if (!bio->bi_vcnt)
 		return -EFAULT;
@@ -1276,7 +1275,8 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter,
 
 	if (is_pci_p2pdma_page(bio->bi_io_vec->bv_page))
 		bio->bi_opf |= REQ_NOMERGE;
-	return bio_iov_iter_align_down(bio, iter, len_align_mask);
+	return bio_iov_iter_align_down(bio, iter,
+			&bio->bi_io_vec[bio->bi_vcnt - 1], len_align_mask);
 }
 
 static struct folio *folio_alloc_greedy(gfp_t gfp, size_t *size,
@@ -1360,7 +1360,8 @@ static int bio_iov_iter_bounce_write(struct bio *bio, struct iov_iter *iter,
 
 	if (!bio->bi_iter.bi_size)
 		return -ENOMEM;
-	return bio_iov_iter_align_down(bio, iter, minsize - 1);
+	return bio_iov_iter_align_down(bio, iter,
+			&bio->bi_io_vec[bio->bi_vcnt - 1], minsize - 1);
 }
 
 static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
@@ -1398,7 +1399,10 @@ static int bio_iov_iter_bounce_read(struct bio *bio, struct iov_iter *iter,
 	bvec_set_folio(&bio->bi_io_vec[0], folio, bio->bi_iter.bi_size, 0);
 	if (iov_iter_extract_will_pin(iter))
 		bio_set_flag(bio, BIO_PAGE_PINNED);
-	return bio_iov_iter_align_down(bio, iter, minsize - 1);
+
+	/* The first vec stores the bounce buffer, so do not subtract 1 here. */
+	return bio_iov_iter_align_down(bio, iter,
+			&bio->bi_io_vec[bio->bi_vcnt], minsize - 1);
 }
 
 /**
-- 
2.53.0


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

end of thread, other threads:[~2026-07-13 12:47 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-10 12:26 [RESEND][SECURITY] block: double unpin in bounced direct reads Neptune
2026-07-13  9:29 ` Christoph Hellwig
2026-07-13 10:20   ` Neptune
2026-07-13 12:47     ` Christoph Hellwig

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