From nobody Thu Apr 9 04:03:24 2026 Received: from m16.mail.163.com (m16.mail.163.com [117.135.210.3]) (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 42B5D3921DF; Wed, 11 Mar 2026 08:04:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=117.135.210.3 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773216286; cv=none; b=U50be8ZCZewv3Ga3f8lo2fI4JEcldkNOIKFnyQ+fcIfWdTHr+TTPJ+75tV6suprJyOm4OGlREbZ7UuoP/5UrOANk57Gv3QcVvgAlEkwXocFowvbMBQhjjWFiCbgA48i01p8n2DF5Ljny3fwenM8DAZ4+VBGfWiclE0llTEVF+GM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773216286; c=relaxed/simple; bh=+E5DpfCv7Ox1aDkAin9IDLNUQmMwpLrYcvS2dvIFLN4=; h=Date:From:To:Subject:Content-Type:MIME-Version:Message-ID; b=Vo0DK7iat8fGAA6RqGdRr+XJHJ99L4H9GHBCEb4mmjczNe6lNb5uO5TkDkDxPFYov8B5DHu93kIloTXshObxOsq7apvrcVN1vrwcut5KGovSw15/pFtCYTYbbsp8dk4vbqvkJwbPLkIU3l12ldHRQg1sJBvjbNbjK5zFduR6Hlk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com; spf=pass smtp.mailfrom=163.com; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b=N1atNHDG; arc=none smtp.client-ip=117.135.210.3 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=163.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=163.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=163.com header.i=@163.com header.b="N1atNHDG" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=Date:From:To:Subject:Content-Type:MIME-Version: Message-ID; bh=+E5DpfCv7Ox1aDkAin9IDLNUQmMwpLrYcvS2dvIFLN4=; b=N 1atNHDGI2FYi+yL+lebGm5w7S7mv5X0RODLpBvj8y3khE8Uob+AAGa2DL6Mea2BC iRdACMu0CAcW/cKxFlDxgb5NqwRFT7AGuqqHXNLAH4Qr5/J8/eXTpQFuNwWMFSSR ojg16LGiqb87JxM2Z22hgJe7dkQASv+rgdMHcTxXUM= Received: from luckd0g$163.com ( [183.205.138.18] ) by ajax-webmail-wmsvr-40-127 (Coremail) ; Wed, 11 Mar 2026 16:04:28 +0800 (CST) Date: Wed, 11 Mar 2026 16:04:28 +0800 (CST) From: "Jianzhou Zhao" To: tytso@mit.edu, adilger.kernel@dilger.ca, linux-ext4@vger.kernel.org, linux-kernel@vger.kernel.org Subject: BUG: KCSAN: data-race in _copy_to_iter / ext4_generic_delete_entry X-Priority: 3 X-Mailer: Coremail Webmail Server Version 2023.4-cmXT build 20251222(83accb85) Copyright (c) 2002-2026 www.mailtech.cn 163com X-NTES-SC: AL_Qu2cAf6auUot7iCQYOkfmU4Rhug7UMO3uf8n24JfPJ9wjA/p2yseUUF9NmPf88CwFTuXvxiGfTNO1/ZAU5BifrwxwJGENm9gOqVAJ3BA52RGZA== Content-Transfer-Encoding: quoted-printable Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <6c4b2013.6d16.19cdbecff3e.Coremail.luckd0g@163.com> X-Coremail-Locale: zh_CN X-CM-TRANSID: fygvCgDXP5UMIrFp+cN2AA--.25578W X-CM-SenderInfo: poxfyvkqj6il2tof0z/xtbC9gxS3GmxIgz8FAAA3q X-Coremail-Antispam: 1U5529EdanIXcx71UUUUU7vcSsGvfC2KfnxnUU== Content-Type: text/plain; charset="utf-8" Subject: [BUG] ext4: KCSAN: data-race in _copy_to_iter / ext4_generic_delet= e_entry Dear Maintainers, We are writing to report a KCSAN-detected data race vulnerability within `e= xt4` and the block device layer. This bug was found by our custom fuzzing t= ool, RacePilot. The race occurs when `ext4_generic_delete_entry` modifies t= he `rec_len` of a previous directory entry (via a 2-byte write) during a pa= th unlink operation, while a concurrent thread directly accesses the raw bl= ock device of the mounted filesystem (via `read()`), executing `_copy_to_it= er()` which blindly bulk-reads the buffer underlying the filesystem page ca= che. We observed this bug on the Linux kernel version 6.18.0-08691-g2061f18= ad76e-dirty. Call Trace & Context =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D BUG: KCSAN: data-race in _copy_to_iter / ext4_generic_delete_entry write to 0xffff888033da2010 of 2 bytes by task 5608 on cpu 0: ext4_generic_delete_entry+0x358/0x470 fs/ext4/namei.c:2670 ext4_delete_entry+0x16d/0x280 fs/ext4/namei.c:2724 __ext4_unlink+0x504/0x6e0 fs/ext4/namei.c:3263 ext4_unlink+0x25d/0x280 fs/ext4/namei.c:3312 vfs_unlink+0x323/0x710 fs/namei.c:5409 do_unlinkat+0x301/0x540 fs/namei.c:5480 ... __x64_sys_unlink+0x7d/0xa0 fs/namei.c:5513 read to 0xffff888033da2000 of 1377 bytes by task 4793 on cpu 1: instrument_copy_to_user include/linux/instrumented.h:113 [inline] copy_to_user_iter lib/iov_iter.c:29 [inline] iterate_ubuf include/linux/iov_iter.h:31 [inline] iterate_and_advance2 include/linux/iov_iter.h:304 [inline] iterate_and_advance include/linux/iov_iter.h:332 [inline] _copy_to_iter+0x210/0xf10 lib/iov_iter.c:231 copy_page_to_iter lib/iov_iter.c:412 [inline] copy_page_to_iter+0xd1/0x150 lib/iov_iter.c:399 copy_folio_to_iter include/linux/uio.h:204 [inline] filemap_read+0x46e/0x8f0 mm/filemap.c:2899 blkdev_read_iter+0x114/0x360 block/fops.c:868 new_sync_read fs/read_write.c:502 [inline] vfs_read+0x5c8/0x820 fs/read_write.c:583 ksys_read+0xbe/0x190 fs/read_write.c:730 ... __x64_sys_read+0x41/0x50 fs/read_write.c:737 Reported by Kernel Concurrency Sanitizer on: CPU: 1 UID: 0 PID: 4793 Comm: systemd-udevd Not tainted 6.18.0-08691-g2061f= 18ad76e-dirty #50 PREEMPT(voluntary)=20 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/= 2014 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Execution Flow & Code Context When deleting an entry from a directory block, `ext4_generic_delete_entry()= ` merges the deleted target into the preceding directory entry (`pde`) by e= xtending its `rec_len`.=20 ```c // fs/ext4/namei.c int ext4_generic_delete_entry(...) { ... if (de =3D=3D de_del) { if (pde) { pde->rec_len =3D ext4_rec_len_to_disk( // <-- Plain concurrent 2-byte w= rite ext4_rec_len_from_disk(pde->rec_len, blocksize) + ext4_rec_len_from_disk(de->rec_len, blocksize), blocksize); /* wipe entire dir_entry */ memset(de, 0, ...); } ... } ``` Meanwhile, a secondary application accesses the underlying block device nod= es (e.g. `/dev/sda1` mapped to the mount). The buffer structures managing t= he directory metadata pages are shared in physical memory between the `ext4= ` filesystem instance and the raw block device layer. Invoking `sys_read` d= rops into `blkdev_read_iter()`, which accesses the page/buffer mapping via = lockless algorithms or asynchronous chunk reads. Eventually `copy_page_to_i= ter` reads the exact memory span being manipulated. Root Cause Analysis A KCSAN data race arises because one thread (the raw block device reader) e= xecutes an unannotated bulk copy (`_copy_to_iter`) of physical pages simult= aneously while the filesystem actively modifies the active directory entrie= s (`pde->rec_len`) over the same page cache mapped structures. Reading raw = block devices underpinning actively mounted filesystems is intrinsically ra= cy and officially unsupported for data coherence in Linux; however, without= compiler barriers, this specific mutation can suffer load tearing or gener= ate severe KCSAN spam. Unfortunately, we were unable to generate a reproducer for this bug. Potential Impact This data race is benign. Raw device readers to live filesystems accept tha= t data may be torn or in-transition when extracted locklessly. For the file= system itself, it relies on journal commits and directory locks, so ext4 co= nsistency is untampered. But, unannotated mutations trigger compiler optimi= zation alarms within the sanitization toolchains.=20 Proposed Fix While disabling direct block access to mounted filesystems is the broader a= rchitectural shift, to silence KCSAN localized tearing warnings on this com= monly active mutation path, `WRITE_ONCE` explicitly encodes the volatile me= mory constraint for the record length modification.=20 ```diff --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2667,12 +2667,12 @@ int ext4_generic_delete_entry(struct inode *dir, return -EFSCORRUPTED; if (de =3D=3D de_del) { if (pde) { - pde->rec_len =3D ext4_rec_len_to_disk( + WRITE_ONCE(pde->rec_len, ext4_rec_len_to_disk( ext4_rec_len_from_disk(pde->rec_len, blocksize) + ext4_rec_len_from_disk(de->rec_len, blocksize), - blocksize); + blocksize)); =20 /* wipe entire dir_entry */ memset(de, 0, ext4_rec_len_from_disk(de->rec_len, ``` We would be highly honored if this could be of any help. Best regards, RacePilot Team