Copy-on-read for untrusted image mounts, and differentiating between metadata and user data writes.

Demi Marie Obenour
2026-04-29T15:06:22Z

[-- Attachment #1.1.1: Type: text/plain, Size: 4202 bytes --]

On 4/25/26 14:00, Demi Marie Obenour wrote:
> On 4/21/26 08:20, Theodore Tso wrote:
>> On Tue, Apr 21, 2026 at 07:32:43PM +0800, Zw Tang wrote:
>>> This looks like an ext4 inline-data boundary/state inconsistency triggered
>>> while writing to an ext4 image crafted by syzkaller. The later
>>> KASAN: slab-use-after-free in rwsem_down_write_slowpath() appears to be a
>>> secondary effect after the primary ext4 BUG, likely during teardown/unlink
>>> after the filesystem failure.
>>
>> Writing to a mounted image is not something that we consider a valid
>> threat model. If you can write to a mounted image, there are a
>> zillion different ways that you can creash the kernel, or you can
>> create a setuid shell, etc.
>>
>> The upstream syzkaller bot makes sure that CONFIG_BLK_DEV_WRITE_MOUNTED
>> is not defined to avoid syzkaller noise.
>
> CONFIG_BLK_DEV_WRITE_MOUNTED only blocks writing via the specific block
> device that is mounted. It doesn't block writing via other methods.
> If I recall correctly, its purpose was to prevent writing to the
> buffer cache used by the filesystem driver.
>
> Changing block devices that are mounted is also reachable via USB.
> Yes, some distros may disable automount, but users who have stuff to
> get done will mount USB devices anyway. Telling users "don't do this"
> very rarely works in practice.

So this gave me an idea that might work in practice, without requiring
any additional work from the ext4 (or XFS) developers.

My understanding is that:

1. e2fsck *is* intended to be secure against malicious filesystem
images (though not TOCTOU).

2. Mounting with nosuid,noexec,nodev,nosymfollow can mitigate
VFS-level attacks.

This means that the following should be a safe way to mount an
untrusted ext4 filesystem:

1. Copy it to trusted storage.
2. Run 'e2fsck -f -n' (or 'e2fsck -f -p') on the image.
3. Mount it with nosuid,noexec,nodev,nosymfollow.

The first step protects against TOCTOU, and the second protects
against metadata parsing attacks.

It's possible to optimize this by using a virtual block device that:

1. When data is read for the first time, copies it from the untrusted
device to the trusted device. Subsequent reads come from the
trusted device.

2. When data is written, it is written to both the untrusted and
trusted devices.
However, if one is mounting read-only, one can actually go further than
that for ext4. ext4 doesn't care about file contents, only metadata.
So TOCTOU attacks on file contents can't affect it.

Furthermore, e2fsck must read all metadata in order to do its job.
After all, the safety of step 3 in the above procedure depends on step
2 doing exactly that. If the filesystem is mounted with 'ro,noatime',
then (IIUC) the only change that the ext4 driver will need to make
to the filesystem is journal replay. But e2fsck has to do that to
check the integrity of the filesystem.

This means that copy-on-read is only necessary while e2fsck is running.
Afterwards, it's no longer necessary to copy newly-accessed data to
the trusted device. Erroring any writes to data that was not already
read will ensure that further metadata (that needs TOCTOU protection)
is not written out.

This doesn't protect against TOCTOU attacks on applications, but for
at least some backup workloads that is not an issue.

With minimal cooperation from the filesystem, one can do even better.
If the device knew what was metadata and what was file contents,
it could do better by only storing metadata on trusted storage,
while file contents are allowed to be written to untrusted storage.

his has many applications in the server world! It's
quite possible that one wants to treat metadata and file contents
differently. For instance, one might want to put the metadata on a
fast NVMe drive (or a RAID 1 of two or more such drives), while the
file contents are on a RAID 6 on HDDs. This keeps metadata access
(lots of random reads and writes) fast, while bulk data access (likely
sequential and performance-insensitive) can go on cheap bulk storage.
--
Sincerely,
Demi Marie Obenour (she/her/hers)

[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 7253 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]