* [BUG] erofs: LZMA stream state NULL deref after failed dict grow
@ 2026-09-02 2:04 Qingyu Zhang
2026-09-02 2:20 ` Gao Xiang
0 siblings, 1 reply; 2+ messages in thread
From: Qingyu Zhang @ 2026-09-02 2:04 UTC (permalink / raw)
To: Gao Xiang, Chao Yu; +Cc: linux-erofs, linux-kernel
Hello,
z_erofs_load_lzma_config() can leave strm->state == NULL while still
publishing z_erofs_lzma_max_dictsize. The next mount of the same
image skips realloc and decompress NULL-derefs.
Type: null-pointer dereference
* Summary
for (strm = head; strm; strm = strm->next) {
if (strm->state)
xz_dec_microlzma_end(strm->state);
strm->state = xz_dec_microlzma_alloc(..., dict_size);
if (!strm->state)
err = -ENOMEM;
}
...
z_erofs_lzma_max_dictsize = dict_size; /* even if err */
On alloc failure the old state is already gone. The next mount sees
max_dictsize >= dict_size and returns 0 without retrying. Then:
xz_dec_microlzma_reset(strm->state, ...); /* state is NULL */
* Affected
622ceaddb764. Needs CONFIG_EROFS_FS_ZIP_LZMA, a microlzma image,
and a failed xz_dec_microlzma_alloc (fault injection or memory
pressure). KASAN recommended.
* Reproduction
1. mkfs.erofs -z lzma,dictsize=4096 lzma.img dir/
2. Force xz_dec_microlzma_alloc() to fail on first mount
(poc/fail_lzma.c: kprobe sets dict_size=0).
3. First mount returns -ENOMEM.
4. Disarm the probe, mount the same image again (succeeds via the
max_dictsize early-out).
5. cat /mnt/payload
KASAN: null-ptr-deref in xz_dec_microlzma_reset from
z_erofs_lzma_decompress.
PoC: poc/run.sh. Use lzma_streams=1 to keep the pool to one stream.
* Expected
Failed grow keeps the previous xz state (or retries next mount) and
does not bump z_erofs_lzma_max_dictsize.
* Actual
NULL state + published max_dictsize -> NPD on the next read.
Please consider the suggested patch.
Thanks.
Suggested patch
```
diff --git a/fs/erofs/decompressor_lzma.c b/fs/erofs/decompressor_lzma.c
index 6b0cdb446c6a..3719c6f83f8a 100644
--- a/fs/erofs/decompressor_lzma.c
+++ b/fs/erofs/decompressor_lzma.c
@@ -128,11 +128,16 @@ static int z_erofs_load_lzma_config(struct
super_block *sb,
err = 0;
/* 2. walk each isolated stream and grow max dict_size if needed */
for (strm = head; strm; strm = strm->next) {
+ struct xz_dec_microlzma *state;
+
+ state = xz_dec_microlzma_alloc(XZ_PREALLOC, dict_size);
+ if (!state) {
+ err = -ENOMEM;
+ continue;
+ }
if (strm->state)
xz_dec_microlzma_end(strm->state);
- strm->state = xz_dec_microlzma_alloc(XZ_PREALLOC, dict_size);
- if (!strm->state)
- err = -ENOMEM;
+ strm->state = state;
}
/* 3. push back all to the global list and update max dict_size */
@@ -142,7 +147,8 @@ static int z_erofs_load_lzma_config(struct super_block *sb,
spin_unlock(&z_erofs_lzma_lock);
wake_up_all(&z_erofs_lzma_wq);
- z_erofs_lzma_max_dictsize = dict_size;
+ if (!err)
+ z_erofs_lzma_max_dictsize = dict_size;
mutex_unlock(&lzma_resize_mutex);
return err;
}
```
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [BUG] erofs: LZMA stream state NULL deref after failed dict grow
2026-09-02 2:04 [BUG] erofs: LZMA stream state NULL deref after failed dict grow Qingyu Zhang
@ 2026-09-02 2:20 ` Gao Xiang
0 siblings, 0 replies; 2+ messages in thread
From: Gao Xiang @ 2026-09-02 2:20 UTC (permalink / raw)
To: Qingyu Zhang
Cc: Gao Xiang, Chao Yu, linux-erofs, linux-kernel, Nikhil Gurudasani
Hi,
On Wed, Sep 02, 2026 at 10:04:41AM +0800, Qingyu Zhang wrote:
> Hello,
>
> z_erofs_load_lzma_config() can leave strm->state == NULL while still
> publishing z_erofs_lzma_max_dictsize. The next mount of the same
> image skips realloc and decompress NULL-derefs.
>
> Type: null-pointer dereference
>
> * Summary
>
> for (strm = head; strm; strm = strm->next) {
> if (strm->state)
> xz_dec_microlzma_end(strm->state);
> strm->state = xz_dec_microlzma_alloc(..., dict_size);
> if (!strm->state)
> err = -ENOMEM;
> }
> ...
> z_erofs_lzma_max_dictsize = dict_size; /* even if err */
>
> On alloc failure the old state is already gone. The next mount sees
> max_dictsize >= dict_size and returns 0 without retrying. Then:
>
> xz_dec_microlzma_reset(strm->state, ...); /* state is NULL */
>
Actually there were similar reports:
https://sashiko.dev/#/patchset/20260714114729.3760594-1-michael.bommarito%40gmail.com
https://lore.kernel.org/r/20260830104109.60639-1-nikhilgurudasani314@gmail.com
I will reply Nikhil's patch soon.
Thanks,
Gao Xiang
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-02 2:20 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-02 2:04 [BUG] erofs: LZMA stream state NULL deref after failed dict grow Qingyu Zhang
2026-09-02 2:20 ` Gao Xiang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®