From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mx5.sberdevices.ru (mx5.sberdevices.ru [95.181.183.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A92FC351C09 for ; Fri, 10 Apr 2026 08:51:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.181.183.35 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775811091; cv=none; b=ZnaQ/MuTHZfszE+1t1c3KXLcC7L9S1MN5DMLJAFEqR54ubHHH6adc/UE1Lf8g6IeQivk0u4xI6R37ioy1ZVgvEZtHee3PPAJkxwwMyfNEgcut/bETBS7VMXvllxtdSP8E5tGDMc5bWVLRHiQiQZ7/LofHUnc+BjLh1nFDl3FrYc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775811091; c=relaxed/simple; bh=R3Yd92cqFfj/TC2KeTVp+KZOWAdMNn79jiIh7o7ekLs=; h=Message-ID:Date:MIME-Version:Subject:To:CC:References:From: In-Reply-To:Content-Type; b=tdoYXz3bRXS/xNDg/GUP42pQzqewAwvfFAZzxp+v4V4sumKfS0dxtUp7UHkyVtMAqYvCuhyA1ZranRgr+y955AmKonNMnU6xdHjC+huaymkbBQKAWQwFqNNqTeyXDvFvD2tP7tY7pl9TrldPsEdu+sCyv++o8YGVkRNU+fxnnec= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=salutedevices.com; spf=pass smtp.mailfrom=salutedevices.com; dkim=pass (2048-bit key) header.d=salutedevices.com header.i=@salutedevices.com header.b=T/gnVsR6; arc=none smtp.client-ip=95.181.183.35 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=salutedevices.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=salutedevices.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=salutedevices.com header.i=@salutedevices.com header.b="T/gnVsR6" Received: from p-antispam-ksmg-gc-msk01.sberdevices.ru (localhost [127.0.0.1]) by mx5.sberdevices.ru (Postfix) with ESMTP id 8EFED240019; Fri, 10 Apr 2026 11:51:26 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 mx5.sberdevices.ru 8EFED240019 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=salutedevices.com; s=post; t=1775811086; bh=gqbMceSH5uoMJWGDuIsCQknTnKGK80NcwgxS62ejdrQ=; h=Message-ID:Date:MIME-Version:Subject:To:From:Content-Type:From; b=T/gnVsR6SOLvZR9K4hBp1w3LgbyJTHIHbRgTl8+Q/+5V0ZMuzGsTa+2McJySU/KWF bjA0KkLNKpE5KcyoP7+Or4ImXZ9+EYgHkTrR4X44zFzI+grDoI0rOhKgZG4t6eFHZH UuuDCTEfPLlWpGN56fSrhQAQOgW6qtboPQOx1agTzc5jUUiX7TTJBY3I8qG1nqCurU lP+3J1Bi/aSd8lNrd+QKeMhE0NzyHG7AaCahqPd8sl7k71mZkWxEmsKRxEfPraWF5l PDFQOgFXYV0WZ5Fe5QqKit1U4ZJZoaPl43os84IRMIJmcqd8XbSrjc+N9zlJkxQjMb 7evVEKxSqoczg== Received: from smtp.sberdevices.ru (p-exch-cas-a-m1.sberdevices.ru [172.24.201.216]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "sberdevices.ru", Issuer "R12" (not verified)) by mx5.sberdevices.ru (Postfix) with ESMTPS; Fri, 10 Apr 2026 11:51:25 +0300 (MSK) Message-ID: <31735f62-2008-4898-b548-0d546efb9120@salutedevices.com> Date: Fri, 10 Apr 2026 11:51:24 +0300 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: erofs pointer corruption and kernel crash Content-Language: ru To: Gao Xiang CC: , , , , Gao Xiang , Chao Yu , Yue Hu , Jeffle Xu , Sandeep Dhavale , Hongbo Li , Sheng Yong References: <4a2f3801-fac1-42fe-ae75-da315822e088@salutedevices.com> From: Arseniy Krasnov In-Reply-To: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit X-ClientProxiedBy: p-exch-cas-a-m2.sberdevices.ru (172.24.201.210) To p-exch-cas-a-m1.sberdevices.ru (172.24.201.216) X-KSMG-AntiPhishing: NotDetected X-KSMG-AntiSpam-Auth: dkim=none X-KSMG-AntiSpam-Envelope-From: avkrasnov@salutedevices.com X-KSMG-AntiSpam-Info: LuaCore: 98 0.3.98 ca9d2f3beca9ca2a85e178af9d8e97d5fa2c38a3, {Tracking_from_domain_doesnt_match_to}, d41d8cd98f00b204e9800998ecf8427e.com:7.1.1;salutedevices.com:7.1.1;smtp.sberdevices.ru:7.1.1,5.0.1;127.0.0.199:7.1.2, FromAlignment: s X-KSMG-AntiSpam-Interceptor-Info: scan successful X-KSMG-AntiSpam-Lua-Profiles: 202164 [Apr 10 2026] X-KSMG-AntiSpam-Method: none X-KSMG-AntiSpam-Rate: 0 X-KSMG-AntiSpam-Status: not_detected X-KSMG-AntiSpam-Version: 6.1.1.22 X-KSMG-AntiVirus: Kaspersky Secure Mail Gateway, version 2.1.1.8310, bases: 2026/04/09 21:06:00 #28382314 X-KSMG-AntiVirus-Status: NotDetected, skipped X-KSMG-KATA-Status: Not Scanned X-KSMG-LinksScanning: NotDetected X-KSMG-Message-Action: skipped X-KSMG-Rule-ID: 5 10.04.2026 11:42, Gao Xiang wrote: > > > On 2026/4/10 16:31, Gao Xiang wrote: >> Hi, >> >> On 2026/4/10 16:13, Arseniy Krasnov wrote: >>> Hi, >>> >>> We found unexpected behaviour of erofs: >>> >>> There is function in erofs - 'erofs_onlinefolio_end()'. It has pointer to >>> 'struct folio' as first argument, and there is loop inside this function, >>> which updates 'private' field of provided folio: >>> >>>    do { >>>            orig = atomic_read((atomic_t *)&folio->private); >>>            DBG_BUGON(orig <= 0); >>>            v = dirty << EROFS_ONLINEFOLIO_DIRTY; >>>            v |= (orig - 1) | (!!err << EROFS_ONLINEFOLIO_EIO); >>>    } while (atomic_cmpxchg((atomic_t *)&folio->private, orig, v) != orig); >>> >>> Now, we see that in some rare case, this function processes folio, where >>> 'private' is pointer, and thus this loop will update some bits in this >>> pointer. Then later kernel dereferences such pointer and crashes. >>> >>> To catch this, the following small debug patch was used (e.g. we check that 'private' field is pointer): >>> >>> diff --git a/fs/erofs/data.c b/fs/erofs/data.c >>> index 33cb0a7330d2..b1d8deffec4d 100644 >>> --- a/fs/erofs/data.c >>> +++ b/fs/erofs/data.c >>> @@ -238,6 +238,11 @@ void erofs_onlinefolio_end(struct folio *folio, int err, bool dirty) >>>   { >>>       int orig, v; >>> +    if (((uintptr_t)folio->private) & 0xffff000000000000) { >> >> No, if erofs_onlinefolio_end() is called, `folio->private` >> shouldn't be a pointer, it's just a counter inside, and >> storing a pointer is unexpected. >> >> And since the folio is locked, it shouldn't call into >> try_to_free_buffers(). >> >> Is it easy to reproduce? if yes, can you print other >> values like `folio->mapping` and `folio->index` as >> well? >> >> I need more informations to find some clues. > > btw, is that an unmodified upstream kernel "6.15.11-sdkernel"? > Currently I never heard Android phone vendors using 6.12 LTS > for example hit this. If it can easily reproduced, is it > possible to reproduce with the upstream kernel? Yes, this is just upstream kernel, no vendor modifications. It is not android, just buildroot. > > And is the "0xffff000002b32468" pointer a valid pointer? what > does it point to? If it looks erofs pointer, the only one I > can think out is "struct z_erofs_pcluster", if it's not the > case, I think there should be other thing wrong if the kernel > is modified. Yes, this is valid pointer, need to check about that pointer. I'll feedback here. Thanks > >> >> Thanks, >> Gao Xiang >> >>> +        pr_emerg("\n[foliodbg] %s:%d EROFS FOLIO %px PRIVATE BEFORE %px\n", __func__, __LINE__, folio, folio->private); >>> +        dump_stack(); >>> +    } >>> + >>>       do { >>>           orig = atomic_read((atomic_t *)&folio->private); >>>           DBG_BUGON(orig <= 0); >>> @@ -245,6 +250,9 @@ void erofs_onlinefolio_end(struct folio *folio, int err, bool dirty) >>>           v |= (orig - 1) | (!!err << EROFS_ONLINEFOLIO_EIO); >>>       } while (atomic_cmpxchg((atomic_t *)&folio->private, orig, v) != orig); >>> +    if (((uintptr_t)folio->private) & 0xffff000000000000) >>> +        pr_emerg("\n[foliodbg] %s:%d EROFS FOLIO %px PRIVATE SET %px\n", __func__, __LINE__, folio, folio->private); >>> + >>>       if (v & (BIT(EROFS_ONLINEFOLIO_DIRTY) - 1)) >>>           return; >>>       folio->private = 0; >>> >>> >>> And it gives result: >>> >>> [][  T639] [foliodbg] erofs_onlinefolio_end:242 EROFS FOLIO fffffdffc0030440 PRIVATE BEFORE ffff000002b32468 >>> [][  T639] CPU: 0 UID: 0 PID: 639 Comm: kworker/0:6H Tainted: G O 6.15.11-sdkernel #1 PREEMPT >>> [][  T639] Tainted: [O]=OOT_MODULE >>> [][  T639] Workqueue: kverityd verity_work >>> [][  T639] Call trace: >>> [][  T639]  show_stack+0x18/0x30 (C) >>> [][  T639]  dump_stack_lvl+0x60/0x80 >>> [][  T639]  dump_stack+0x18/0x24 >>> [][  T639]  erofs_onlinefolio_end+0x124/0x130 >>> [][  T639]  z_erofs_decompress_queue+0x4b0/0x8c0 >>> [][  T639]  z_erofs_decompress_kickoff+0x88/0x150 >>> [][  T639]  z_erofs_endio+0x144/0x250 >>> [][  T639]  bio_endio+0x138/0x150 >>> [][  T639]  __dm_io_complete+0x1e0/0x2b0 >>> [][  T639]  clone_endio+0xd0/0x270 >>> [][  T639]  bio_endio+0x138/0x150 >>> [][  T639]  verity_finish_io+0x64/0xf0 >>> [][  T639]  verity_work+0x30/0x40 >>> [][  T639]  process_one_work+0x180/0x2e0 >>> [][  T639]  worker_thread+0x2c4/0x3f0 >>> [][  T639]  kthread+0x12c/0x210 >>> [][  T639]  ret_from_fork+0x10/0x20 >>> [][  T639] >>> [][  T639] [foliodbg] erofs_onlinefolio_end:254 EROFS FOLIO fffffdffc0030440 PRIVATE SET ffff000022b32467 >>> [][   T39] Unable to handle kernel paging request at virtual address ffff000022b32467 >>> [][   T39] Mem abort info: >>> [][   T39]   ESR = 0x0000000096000006 >>> [][   T39]   EC = 0x25: DABT (current EL), IL = 32 bits >>> [][   T39]   SET = 0, FnV = 0 >>> [][   T39]   EA = 0, S1PTW = 0 >>> [][   T39]   FSC = 0x06: level 2 translation fault >>> [][   T39] Data abort info: >>> [][   T39]   ISV = 0, ISS = 0x00000006, ISS2 = 0x00000000 >>> [][   T39]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0 >>> [][   T39]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 >>> [][   T39] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000001e36000 >>> [][   T39] [ffff000022b32467] pgd=1800000007fff403, p4d=1800000007fff403, pud=1800000007ffe403, pmd=0000000000000000 >>> [][   T39] Internal error: Oops: 0000000096000006 [#1]  SMP >>> [][   T39] Modules linked in: vlsicomm(O) >>> [][   T39] CPU: 1 UID: 0 PID: 39 Comm: kswapd0 Tainted: G O 6.15.11-sdkernel #1 PREEMPT >>> [][   T39] Tainted: [O]=OOT_MODULE >>> [][   T39] pstate: 00400005 (nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) >>> [][   T39] pc : drop_buffers.constprop.0+0x34/0x120 >>> [][   T39] lr : try_to_free_buffers+0xd0/0x100 >>> [][   T39] sp : ffff80008105b780 >>> [][   T39] x29: ffff80008105b780 x28: 0000000000000000 x27: fffffdffc0030448 >>> [][   T39] x26: ffff80008105b8a0 x25: ffff80008105b868 x24: 0000000000000001 >>> [][   T39] x23: fffffdffc0030440 x22: ffff80008105b7b0 x21: fffffdffc0030440 >>> [][   T39] x20: ffff000022b32467 x19: ffff000022b32467 x18: 0000000000000000 >>> [][   T39] x17: 0000000000000000 x16: 0000000000000000 x15: 00000000d69f4cc0 >>> [][   T39] x14: ffff0000000c5dc0 x13: 0000000000000000 x12: ffff800080d59b58 >>> [][   T39] x11: 00000000000000c0 x10: 0000000000000000 x9 : 0000000000000000 >>> [][   T39] x8 : ffff80008105b7d0 x7 : 0000000000000000 x6 : 000000000000003f >>> [][   T39] x5 : 0000000000000000 x4 : fffffdffc0030440 x3 : 1ff0000000004001 >>> [][   T39] x2 : 1ff0000000004001 x1 : ffff80008105b7b0 x0 : fffffdffc0030440 >>> [][   T39] Call trace: >>> [][   T39]  drop_buffers.constprop.0+0x34/0x120 (P) >>> [][   T39]  try_to_free_buffers+0xd0/0x100 >>> [][   T39]  filemap_release_folio+0x94/0xc0 >>> [][   T39]  shrink_folio_list+0x8c8/0xc40 >>> [][   T39]  shrink_lruvec+0x740/0xb80 >>> [][   T39]  shrink_node+0x2b8/0x9a0 >>> [][   T39]  balance_pgdat+0x3b8/0x760 >>> [][   T39]  kswapd+0x220/0x3b0 >>> [][   T39]  kthread+0x12c/0x210 >>> [][   T39]  ret_from_fork+0x10/0x20 >>> [][   T39] Code: 14000004 f9400673 eb13029f 54000180 (f9400262) >>> [][   T39] ---[ end trace 0000000000000000 ]--- >>> [][   T39] Kernel panic - not syncing: Oops: Fatal exception >>> [][   T39] SMP: stopping secondary CPUs >>> [][   T39] Kernel Offset: disabled >>> [][   T39] CPU features: 0x0000,00000000,01000000,0200420b >>> [][   T39] Memory Limit: none >>> [][   T39] Rebooting in 5 seconds.. >>> >>> So 'erofs_onlinefolio_end()' takes some folio with 'private' field contains >>> some pointer (0xffff000002b32468), "corrupts" this pointer (result will be >>> 0xffff000022b32467 - at least we see that 0x20000000 was ORed to original >>> pointer and this is (1 << EROFS_ONLINEFOLIO_DIRTY)), and then kernel crashes. >>> We guess it is not valid case when such folio is passed as argument to >>> 'erofs_onlinefolio_end()'. >>> >>> We have the following erofs configuration in buildroot: >>> >>> BR2_TARGET_ROOTFS_EROFS=y >>> BR2_TARGET_ROOTFS_EROFS_CUSTOM_COMPRESSION=y >>> BR2_TARGET_ROOTFS_EROFS_COMPRESSION_ALGORITHMS="zstd,22 --max-extent-bytes 65536 -E48bit" >>> BR2_TARGET_ROOTFS_EROFS_FRAGMENTS=y >>> BR2_TARGET_ROOTFS_EROFS_PCLUSTERSIZE=65536 >>> >>> >>> >>> May be You know how to fix it or some ideas? Because we are new at erofs and need to discover and >>> learn its source code. >>> >>> Thanks >> >