CVE-2026-46089
Description
In the Linux kernel, the following vulnerability has been resolved:
zram: do not forget to endio for partial discard requests
As reported by Qu Wenruo and Avinesh Kumar, the following
getconf PAGESIZE 65536 blkdiscard -p 4k /dev/zram0
takes literally forever to complete. zram doesn't support partial discards and just returns immediately w/o doing any discard work in such cases. The problem is that we forget to endio on our way out, so blkdiscard sleeps forever in submit_bio_wait(). Fix this by jumping to end_bio label, which does bio_endio().
Affected products
2- Range: >=6.12,<6.12.6
Patches
10e3668b371329zram: do not forget to endio for partial discard requests
1 file changed · +2 −2
drivers/block/zram/zram_drv.c+2 −2 modifieddiff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index c2afd1c34f4a6f..43b68fdd95d6df 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -2678,7 +2678,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) */ if (offset) { if (n <= (PAGE_SIZE - offset)) - return; + goto end_bio; n -= (PAGE_SIZE - offset); index++; @@ -2693,6 +2693,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) n -= PAGE_SIZE; } +end_bio: bio_endio(bio); } -- cgit 1.3-korg
2d1f18efccdbzram: do not forget to endio for partial discard requests
1 file changed · +2 −2
drivers/block/zram/zram_drv.c+2 −2 modifieddiff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 44cf0e51d7db62..6584c1ca5a17d3 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -1880,7 +1880,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) */ if (offset) { if (n <= (PAGE_SIZE - offset)) - return; + goto end_bio; n -= (PAGE_SIZE - offset); index++; @@ -1895,6 +1895,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) n -= PAGE_SIZE; } +end_bio: bio_endio(bio); } -- cgit 1.3-korg
35d3300f6357zram: do not forget to endio for partial discard requests
1 file changed · +2 −2
drivers/block/zram/zram_drv.c+2 −2 modifieddiff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 76b326ddd75c47..cbb613f7968b8b 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -2017,7 +2017,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) */ if (offset) { if (n <= (PAGE_SIZE - offset)) - return; + goto end_bio; n -= (PAGE_SIZE - offset); index++; @@ -2032,6 +2032,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) n -= PAGE_SIZE; } +end_bio: bio_endio(bio); } -- cgit 1.3-korg
a02363f71a79zram: do not forget to endio for partial discard requests
1 file changed · +2 −2
drivers/block/zram/zram_drv.c+2 −2 modifieddiff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index a430746575312d..dc6a53c9166aa4 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -2308,7 +2308,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) */ if (offset) { if (n <= (PAGE_SIZE - offset)) - return; + goto end_bio; n -= (PAGE_SIZE - offset); index++; @@ -2323,6 +2323,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) n -= PAGE_SIZE; } +end_bio: bio_endio(bio); } -- cgit 1.3-korg
68ce397e8236zram: do not forget to endio for partial discard requests
1 file changed · +2 −2
drivers/block/zram/zram_drv.c+2 −2 modifieddiff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index af679375b19359..85943da0cdca88 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -2697,7 +2697,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) */ if (offset) { if (n <= (PAGE_SIZE - offset)) - return; + goto end_bio; n -= (PAGE_SIZE - offset); index++; @@ -2712,6 +2712,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) n -= PAGE_SIZE; } +end_bio: bio_endio(bio); } -- cgit 1.3-korg
35d3300f6357zram: do not forget to endio for partial discard requests
1 file changed · +2 −2
drivers/block/zram/zram_drv.c+2 −2 modifieddiff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 76b326ddd75c47..cbb613f7968b8b 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -2017,7 +2017,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) */ if (offset) { if (n <= (PAGE_SIZE - offset)) - return; + goto end_bio; n -= (PAGE_SIZE - offset); index++; @@ -2032,6 +2032,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) n -= PAGE_SIZE; } +end_bio: bio_endio(bio); } -- cgit 1.3-korg
2d1f18efccdbzram: do not forget to endio for partial discard requests
1 file changed · +2 −2
drivers/block/zram/zram_drv.c+2 −2 modifieddiff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 44cf0e51d7db62..6584c1ca5a17d3 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -1880,7 +1880,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) */ if (offset) { if (n <= (PAGE_SIZE - offset)) - return; + goto end_bio; n -= (PAGE_SIZE - offset); index++; @@ -1895,6 +1895,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) n -= PAGE_SIZE; } +end_bio: bio_endio(bio); } -- cgit 1.3-korg
68ce397e8236zram: do not forget to endio for partial discard requests
1 file changed · +2 −2
drivers/block/zram/zram_drv.c+2 −2 modifieddiff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index af679375b19359..85943da0cdca88 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -2697,7 +2697,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) */ if (offset) { if (n <= (PAGE_SIZE - offset)) - return; + goto end_bio; n -= (PAGE_SIZE - offset); index++; @@ -2712,6 +2712,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) n -= PAGE_SIZE; } +end_bio: bio_endio(bio); } -- cgit 1.3-korg
a02363f71a79zram: do not forget to endio for partial discard requests
1 file changed · +2 −2
drivers/block/zram/zram_drv.c+2 −2 modifieddiff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index a430746575312d..dc6a53c9166aa4 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -2308,7 +2308,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) */ if (offset) { if (n <= (PAGE_SIZE - offset)) - return; + goto end_bio; n -= (PAGE_SIZE - offset); index++; @@ -2323,6 +2323,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) n -= PAGE_SIZE; } +end_bio: bio_endio(bio); } -- cgit 1.3-korg
e3668b371329zram: do not forget to endio for partial discard requests
1 file changed · +2 −2
drivers/block/zram/zram_drv.c+2 −2 modifieddiff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index c2afd1c34f4a6f..43b68fdd95d6df 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -2678,7 +2678,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) */ if (offset) { if (n <= (PAGE_SIZE - offset)) - return; + goto end_bio; n -= (PAGE_SIZE - offset); index++; @@ -2693,6 +2693,7 @@ static void zram_bio_discard(struct zram *zram, struct bio *bio) n -= PAGE_SIZE; } +end_bio: bio_endio(bio); } -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing bio_endio() call on the early-return path for partial discard requests in zram_bio_discard()."
Attack vector
An attacker with access to a zram block device can issue a discard (BLKDISCARD) request whose size is smaller than the system page size (e.g. `blkdiscard -p 4k` on a 64 KiB page system). Because zram does not support partial discards, the function `zram_bio_discard` returns immediately without calling `bio_endio()`. The caller, `submit_bio_wait()`, blocks indefinitely waiting for the bio to complete, causing a permanent hang. No special privileges beyond the ability to open the zram device are required.
Affected code
The vulnerability is in `drivers/block/zram/zram_drv.c` in the function `zram_bio_discard()`. The early-return path taken when a partial discard is detected (offset is non-zero and the remaining length `n` fits within the remainder of the page) omitted the `bio_endio()` call.
What the fix does
The patch changes the early-return statement `return;` to `goto end_bio;` in the partial-discard path of `zram_bio_discard()` [patch_id=2659788]. A new `end_bio:` label is added just before the existing `bio_endio(bio)` call at the end of the function. This ensures that every code path — including the partial-discard early exit — completes the bio by calling `bio_endio()`, which wakes up the waiting caller and prevents the hang.
Preconditions
- accessAttacker must have access to a zram block device (e.g., /dev/zram0).
- configSystem page size must be larger than the discard request size (e.g., 64 KiB page with a 4 KiB discard).
- inputAttacker issues a BLKDISCARD ioctl with a partial size (e.g., blkdiscard -p 4k).
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/2d1f18efccdb8b29552399d024c36b705447e975nvd
- git.kernel.org/stable/c/35d3300f6357cfaa72db2721dc2b345b19bac5dfnvd
- git.kernel.org/stable/c/68ce397e8236088fc53b9532d383a722288c8194nvd
- git.kernel.org/stable/c/a02363f71a79b755daa78a70d6b217f9c13c8c85nvd
- git.kernel.org/stable/c/e3668b371329ea036ff022ce8ecc82f8befcf003nvd
News mentions
0No linked articles in our index yet.