Re: [RFC PATCH v2 0/4] init: boot image-based systems without an initramfs (rootimage=)
Christian Brauner <[email protected]> Thu, 30 Jul 2026 12:58:09 +0200
| Newsgroups | org.ozlabs.lists.linux-erofs,dev.linux.lists.fsverity,org.kernel.vger.linux-doc,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260730-bachbett-erwarben-harmonie-e6b8ebf05969@brauner> |
On 2026-07-27 11:48 +0100, Eric Curtin wrote: > Changes since v1 (https://lore.kernel.org/all/[email protected]/), > following Christian Brauner's review > (https://lore.kernel.org/all/20260727-gepaukt-eislauf-waran-7c03f0e47609@brauner/): > > The goal is unchanged: A/B image updates from a single partition, > without paying for a second userspace spin-up at boot. What changed is > how rootimage=/rootimageverity= get from "here is a path" to "here is > the verified, mounted root", which is what most of the v1 review was > about. > > - Patches 1-2 are new: they add generic, reusable VFS infrastructure > (struct fs_context::source_file, path_mount_file()/ > init_mount_file(), vfs_parse_fs_param_file()) that lets an in-kernel > caller hand a filesystem an already-open struct file as its mount > source instead of a path, and convert erofs's existing file-backed > mount support to use it when given. This is the "new infrastructure > available to any fs" asked for, so that init/do_mounts.c never has > to independently re-resolve a path that something else already > opened and validated. > > - Patch 3 (rootimage=) now opens the image file exactly once and > mounts that same struct file via the above, instead of opening it, > doing nothing with the open, and separately handing erofs a path > that it re-resolved on its own with no guaranteed relationship to > what was checked - which is what v1 did, and which is where most of > the "second lookup" / "weak assumptions" findings came from. There > is no fd-vs-path race left because there is no second lookup left. > > rootimagesrcdir= is now mandatory (rootimagesrcdir=none opts out > explicitly) instead of silently detaching the carrier by default, > so there's no more zombie superblock/dangling mountpoint by > default; you have to ask for that outcome by name. > > - Patch 4 (rootimageverity=) is mostly unchanged in what it checks, > but now runs on the exact file patch 3 mounts, so the digest check > and the mount are guaranteed to agree on what "the image" is. It > also now refuses rootimageverity= together with rootimageflags= > containing device= (multi-device erofs images), since the digest > only ever covers the primary image file and silently ignoring the > rest would be a false sense of integrity. > > Not changed / not attempting to fix in this version, per the v1 > discussion: > > - The carrier filesystem itself is still fully parsed (superblock, > directory entries, extents) before rootimageverity= gets to check > anything, since reaching the image file at all requires that. This > is structural to a file-backed image sitting on a general-purpose > writable filesystem, the same way a dm-verity root still needs a > trusted block layer under it; rootimage=/rootimageverity= are meant dm-verity reads opaque sectors whereas this runs superblock/extent/directory parsers running on attacker-writable data. The mitigation mentioned below kinda defeats the feature... The filesystem that contains the image files is writable and the whole rootimagesrcdir= exists to keep it reachable. If you could dm-verity is as stated below, you would just dm-verity the root and used dm-mod.create= All of the other issues: * init suddenly becomes deployment policy * things shipped as modules * composefs can't use this * the alternative to achieve the same thing via CONFIG_INITRAMFS_SOURCE / UKI signed initrd completely ignored /me walks away from this LLM hell.