diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index b99a394d..5be8a9f8 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -26,6 +26,7 @@ jobs: - { dir: 'uki', os: 'fedora' } - { dir: 'unified', os: 'fedora' } - { dir: 'unified-secureboot', os: 'fedora' } + - { dir: 'nofsverity', os: 'arch' } fail-fast: false steps: diff --git a/crates/cfsctl/src/main.rs b/crates/cfsctl/src/main.rs index e6495335..064b92ec 100644 --- a/crates/cfsctl/src/main.rs +++ b/crates/cfsctl/src/main.rs @@ -27,6 +27,9 @@ pub struct App { #[clap(long, group = "repopath")] system: bool, + #[clap(long)] + insecure: bool, + #[clap(subcommand)] cmd: Command, } @@ -160,7 +163,7 @@ async fn main() -> Result<()> { let args = App::parse(); - let repo: Repository = (if let Some(path) = &args.repo { + let mut repo: Repository = (if let Some(path) = &args.repo { Repository::open_path(CWD, path) } else if args.system { Repository::open_system() @@ -172,6 +175,8 @@ async fn main() -> Result<()> { Repository::open_user() })?; + repo.set_insecure(args.insecure); + match args.cmd { Command::Transaction => { // just wait for ^C @@ -339,7 +344,7 @@ async fn main() -> Result<()> { fs.print_dumpfile()?; } Command::Mount { name, mountpoint } => { - repo.mount(&name, &mountpoint)?; + repo.mount_at(&name, &mountpoint)?; } Command::ImageObjects { name } => { let objects = repo.objects_for_image(&name)?; diff --git a/crates/composefs-boot/src/write_boot.rs b/crates/composefs-boot/src/write_boot.rs index c8b24265..9ab4c89c 100644 --- a/crates/composefs-boot/src/write_boot.rs +++ b/crates/composefs-boot/src/write_boot.rs @@ -59,9 +59,14 @@ pub fn write_t2_simple( create_dir_all(&efi_linux)?; let filename = efi_linux.join(t2.filename.as_ref()); let content = read_file(&t2.file, repo)?; - let Some(composefs) = get_cmdline_value(uki::get_cmdline(&content)?, "composefs=") else { + let Some(mut composefs) = get_cmdline_value(uki::get_cmdline(&content)?, "composefs=") else { bail!("The UKI is missing a composefs= commandline parameter"); }; + + if let Some(stripped) = composefs.strip_prefix('?') { + composefs = stripped + } + let expected = root_id.to_hex(); ensure!( composefs == expected, diff --git a/crates/composefs-oci/src/lib.rs b/crates/composefs-oci/src/lib.rs index bcfcbcc9..4617f905 100644 --- a/crates/composefs-oci/src/lib.rs +++ b/crates/composefs-oci/src/lib.rs @@ -152,7 +152,7 @@ pub fn mount( let Some(id) = config.get_config_annotation("containers.composefs.fsverity") else { bail!("Can only mount sealed containers"); }; - repo.mount(id, mountpoint) + repo.mount_at(id, mountpoint) } #[cfg(test)] diff --git a/crates/composefs-setup-root/src/main.rs b/crates/composefs-setup-root/src/main.rs index f753688b..c853f28d 100644 --- a/crates/composefs-setup-root/src/main.rs +++ b/crates/composefs-setup-root/src/main.rs @@ -19,7 +19,7 @@ use serde::Deserialize; use composefs::{ fsverity::{FsVerityHashValue, Sha256HashValue}, - mount::{composefs_fsmount, mount_at, FsHandle}, + mount::{mount_at, FsHandle}, mountcompat::{overlayfs_set_fd, overlayfs_set_lower_and_data_fds, prepare_mount}, repository::Repository, }; @@ -164,10 +164,10 @@ fn open_root_fs(path: &Path) -> Result { Ok(rootfs) } -fn mount_composefs_image(sysroot: &OwnedFd, name: &str) -> Result { - let repo = Repository::::open_path(sysroot, "composefs")?; - let image = repo.open_image(name)?; - composefs_fsmount(image, name, repo.objects_dir()?).context("Failed to mount composefs image") +fn mount_composefs_image(sysroot: &OwnedFd, name: &str, insecure: bool) -> Result { + let mut repo = Repository::::open_path(sysroot, "composefs")?; + repo.set_insecure(insecure); + repo.mount(name).context("Failed to mount composefs image") } fn mount_subdir( @@ -198,12 +198,19 @@ fn mount_subdir( } // Implementation -fn parse_composefs_cmdline(cmdline: &str) -> Result { - let Some(digest) = get_cmdline_value(cmdline, "composefs=") else { +fn parse_composefs_cmdline(cmdline: &str) -> Result<(H, bool)> { + let Some(mut digest) = get_cmdline_value(cmdline, "composefs=") else { bail!("Unable to find composefs= cmdline parameter"); }; - H::from_hex(digest).context("Parsing composefs=") + let mut insecure = false; + if let Some(stripped) = digest.strip_prefix('?') { + digest = stripped; + insecure = true; + } + + let hash = H::from_hex(digest).context("Parsing composefs=")?; + Ok((hash, insecure)) } fn gpt_workaround() -> Result<()> { @@ -232,11 +239,12 @@ fn setup_root(args: Args) -> Result<()> { Some(cmdline) => cmdline, None => &std::fs::read_to_string("/proc/cmdline")?, }; - let image = parse_composefs_cmdline::(cmdline)?.to_hex(); + let (img, insecure) = parse_composefs_cmdline::(cmdline)?; + let image = img.to_hex(); let new_root = match args.root_fs { Some(path) => open_root_fs(&path).context("Failed to clone specified root fs")?, - None => mount_composefs_image(&sysroot, &image)?, + None => mount_composefs_image(&sysroot, &image, insecure)?, }; // we need to clone this before the next step to make sure we get the old one @@ -289,9 +297,8 @@ mod test { assert!(parse_composefs_cmdline::(case).is_err()); } let digest = "8b7df143d91c716ecfa5fc1730022f6b421b05cedee8fd52b1fc65a96030ad52"; - similar_asserts::assert_eq!( - parse_composefs_cmdline::(&format!("composefs={digest}")).unwrap(), - Sha256HashValue::from_hex(digest).unwrap() - ); + let (digest_cmdline, _) = + parse_composefs_cmdline::(&format!("composefs={digest}")).unwrap(); + similar_asserts::assert_eq!(digest_cmdline, Sha256HashValue::from_hex(digest).unwrap()); } } diff --git a/crates/composefs/src/mount.rs b/crates/composefs/src/mount.rs index 036a43ce..dfff4adf 100644 --- a/crates/composefs/src/mount.rs +++ b/crates/composefs/src/mount.rs @@ -78,14 +78,21 @@ pub fn erofs_mount(image: OwnedFd) -> Result { )?) } -pub fn composefs_fsmount(image: OwnedFd, name: &str, basedir: impl AsFd) -> Result { +pub fn composefs_fsmount( + image: OwnedFd, + name: &str, + basedir: impl AsFd, + enable_verity: bool, +) -> Result { let erofs_mnt = prepare_mount(erofs_mount(image)?)?; let overlayfs = FsHandle::open("overlay")?; fsconfig_set_string(overlayfs.as_fd(), "source", format!("composefs:{name}"))?; fsconfig_set_string(overlayfs.as_fd(), "metacopy", "on")?; fsconfig_set_string(overlayfs.as_fd(), "redirect_dir", "on")?; - fsconfig_set_string(overlayfs.as_fd(), "verity", "require")?; + if enable_verity { + fsconfig_set_string(overlayfs.as_fd(), "verity", "require")?; + } overlayfs_set_lower_and_data_fds(&overlayfs, &erofs_mnt, Some(&basedir))?; fsconfig_create(overlayfs.as_fd())?; @@ -101,7 +108,8 @@ pub fn mount_composefs_at( name: &str, basedir: impl AsFd, mountpoint: impl AsRef, + enable_verity: bool, ) -> Result<()> { - let mnt = composefs_fsmount(image, name, basedir)?; + let mnt = composefs_fsmount(image, name, basedir, enable_verity)?; Ok(mount_at(mnt, CWD, &canonicalize(mountpoint)?)?) } diff --git a/crates/composefs/src/repository.rs b/crates/composefs/src/repository.rs index f60bc8e2..c3636949 100644 --- a/crates/composefs/src/repository.rs +++ b/crates/composefs/src/repository.rs @@ -22,8 +22,9 @@ use sha2::{Digest, Sha256}; use crate::{ fsverity::{ compute_verity, enable_verity, ensure_verity_equal, measure_verity, FsVerityHashValue, + MeasureVerityError, }, - mount::mount_composefs_at, + mount::{composefs_fsmount, mount_composefs_at}, splitstream::{DigestMap, SplitStreamReader, SplitStreamWriter}, util::{proc_self_fd, Sha256Digest}, }; @@ -58,6 +59,7 @@ pub struct Repository { repository: OwnedFd, objects: OnceCell, _data: std::marker::PhantomData, + insecure: bool, } impl Drop for Repository { @@ -86,6 +88,7 @@ impl Repository { repository, objects: OnceCell::new(), _data: std::marker::PhantomData, + insecure: false, }) } @@ -127,7 +130,9 @@ impl Repository { Ok(fd) => { // measure the existing file to ensure that it's correct // TODO: try to replace file if it's broken? - ensure_verity_equal(fd, &id)?; + if !self.insecure { + ensure_verity_equal(fd, &id)?; + } return Ok(id); } Err(Errno::NOENT) => { @@ -151,8 +156,23 @@ impl Repository { )?; drop(file); - enable_verity::(&ro_fd).context("Enabling verity digest")?; - ensure_verity_equal(&ro_fd, &id).context("Double-checking verity digest")?; + if self.insecure { + match measure_verity::(&ro_fd) { + Ok(found) if found == FsVerityHashValue::from_hex(&path)? => { + // insecure but file sytem supports it, so enable it anyway + enable_verity::(&ro_fd).context("Enabling verity digest")?; + ensure_verity_equal(&ro_fd, &id).context("Double-checking verity digest")?; + } + Ok(_) => bail!("fs-verity content mismatch"), + Err(MeasureVerityError::VerityMissing) => { + // file system doesn't support it, just continue without + } + Err(other) => Err(other)?, + } + } else { + enable_verity::(&ro_fd).context("Enabling verity digest")?; + ensure_verity_equal(&ro_fd, &id).context("Double-checking verity digest")?; + } match linkat( CWD, @@ -175,10 +195,17 @@ impl Repository { fn open_with_verity(&self, filename: &str, expected_verity: &ObjectID) -> Result { let fd = self.openat(filename, OFlags::RDONLY)?; - ensure_verity_equal(&fd, expected_verity)?; + if !self.insecure { + ensure_verity_equal(&fd, expected_verity)?; + } Ok(fd) } + pub fn set_insecure(&mut self, insecure: bool) -> &mut Self { + self.insecure = insecure; + self + } + /// Creates a SplitStreamWriter for writing a split stream. /// You should write the data to the returned object and then pass it to .store_stream() to /// store the result. @@ -220,6 +247,10 @@ impl Repository { /// Basically the same as has_stream() except that it performs expensive verification pub fn check_stream(&self, sha256: &Sha256Digest) -> Result> { + if self.insecure { + return self.has_stream(sha256); + } + match self.openat(&format!("streams/{}", hex::encode(sha256)), OFlags::RDONLY) { Ok(stream) => { let measured_verity: ObjectID = measure_verity(&stream)?; @@ -383,24 +414,40 @@ impl Repository { self.write_image(Some(name), &data) } - pub fn open_image(&self, name: &str) -> Result { + fn open_image(&self, name: &str) -> Result<(OwnedFd, bool)> { let image = self.openat(&format!("images/{name}"), OFlags::RDONLY)?; - if !name.contains("/") { + if !name.contains("/") && !self.insecure { // A name with no slashes in it is taken to be a sha256 fs-verity digest ensure_verity_equal(&image, &ObjectID::from_hex(name)?)?; } - Ok(image) + match measure_verity::(&image) { + Ok(found) if found == FsVerityHashValue::from_hex(name)? => Ok((image, true)), + Ok(_) => bail!("fs-verity content mismatch"), + Err(MeasureVerityError::VerityMissing) if self.insecure => Ok((image, false)), + Err(other) => Err(other)?, + } + } + + pub fn mount(&self, name: &str) -> Result { + let (image, enable_verity) = self.open_image(name)?; + Ok(composefs_fsmount( + image, + name, + self.objects_dir()?, + enable_verity, + )?) } - pub fn mount(&self, name: &str, mountpoint: &str) -> Result<()> { - let image = self.open_image(name)?; + pub fn mount_at(&self, name: &str, mountpoint: &str) -> Result<()> { + let (image, enable_verity) = self.open_image(name)?; Ok(mount_composefs_at( image, name, self.objects_dir()?, mountpoint, + enable_verity, )?) } @@ -522,7 +569,7 @@ impl Repository { } pub fn objects_for_image(&self, name: &str) -> Result> { - let image = self.open_image(name)?; + let (image, _) = self.open_image(name)?; let mut data = vec![]; std::fs::File::from(image).read_to_end(&mut data)?; Ok(crate::erofs::reader::collect_objects(&data)?) diff --git a/examples/common/make-image b/examples/common/make-image index 5f4e5b19..7c4ded38 100755 --- a/examples/common/make-image +++ b/examples/common/make-image @@ -1,12 +1,47 @@ -#!/bin/sh +#!/bin/bash set -eux -output="$1" +FIX_VERITY=0 +SETUP_REPART=0 +FS_FORMAT=ext4 +parsecmd() { + while [ $# -gt 0 ]; do + case "$1" in + #CMDSTART + -fv|--fix-verity) # + # run run-repart with FIX_VERITY=1 + FIX_VERITY=1 + ;; + -sr|--setup-repart) # + # run run-repart with SETUP_REPART=1 + SETUP_REPART=1 + ;; + -h|--help) # + # this help + echo "Usage: $0 [OPTION]..." + printf "\nCommand line arguments:\n" + sed -rn '/CMDSTART/,/CMDEND/{/\) \#|^ +# /{s/\)? #//g;s/^ //;p}}' "$0" + exit 0 + ;; + *) + echo "Unknown parameter $1" + exit 1 + ;; + esac + #CMDEND + shift + done +} + +args=($@) +output="${args[-1]}" +parse_args=("${args[*]:0:${#args[@]}-1}") +parsecmd ${parse_args[@]} # check that the image doesn't have errors fsck.erofs tmp/sysroot/composefs/images/* -fakeroot "${0%/*}/run-repart" tmp/image.raw +SETUP_REPART=$SETUP_REPART FIX_VERITY=$FIX_VERITY fakeroot "${0%/*}/run-repart" tmp/image.raw qemu-img convert -f raw tmp/image.raw -O qcow2 "${output}" rm tmp/image.raw diff --git a/examples/common/run-repart b/examples/common/run-repart index 2d96e519..4857caee 100755 --- a/examples/common/run-repart +++ b/examples/common/run-repart @@ -9,7 +9,7 @@ chcon system_u:object_r:etc_t:s0 tmp/sysroot/state/*/etc/* definitions="${0%/*}/repart.d" -if [ "${FIX_VERITY:-}" = '1' ]; then +if [ "$SETUP_REPART" = '1' ]; then export SYSTEMD_REPART_MKFS_OPTIONS_EXT4='-O verity' cp -r "${definitions}" tmp/repart.d sed -i 's/:fsverity=copy//' tmp/repart.d/02-sysroot.conf diff --git a/examples/nofsverity/Containerfile.arch b/examples/nofsverity/Containerfile.arch new file mode 100644 index 00000000..04899c42 --- /dev/null +++ b/examples/nofsverity/Containerfile.arch @@ -0,0 +1,35 @@ +FROM archlinux AS base +COPY extra / +RUN < /etc/kernel/cmdline + pacman -Sy --noconfirm systemd-ukify + mkinitcpio -p linux +EOF + +FROM base AS bootable +COPY --from=kernel /boot /boot diff --git a/examples/nofsverity/build b/examples/nofsverity/build new file mode 100755 index 00000000..65947cc8 --- /dev/null +++ b/examples/nofsverity/build @@ -0,0 +1,56 @@ +#!/bin/sh + +set -eux + +os="${1:-fedora}" +cd "${0%/*}" + +FIX_VERITY=1 ../common/check-config + +case "${os}" in + arch) + containerfile='Containerfile.arch' + features='--features=pre-6.15' + ;; + *) + echo "*** unknown variant ${os}" + false + ;; +esac + +# https://github.com/containers/buildah/issues/5656 +PODMAN_BUILD="podman build --no-cache" + +cargo build --release "${features}" + +cp ../../target/release/cfsctl . +cp ../../target/release/composefs-setup-root extra/usr/lib/dracut/modules.d/37composefs/ +CFSCTL='./cfsctl --repo tmp/sysroot/composefs' + +rm -rf tmp +mkdir -p tmp/sysroot/composefs + +${PODMAN_BUILD} \ + --iidfile=tmp/base.iid \ + --target=base \ + -f "${containerfile}" \ + . + +BASE_ID="$(sed s/sha256:// tmp/base.iid)" +${CFSCTL} oci pull containers-storage:"${BASE_ID}" +BASE_IMAGE_FSVERITY="$(${CFSCTL} oci compute-id --bootable "${BASE_ID}")" + +${PODMAN_BUILD} \ + --iidfile=tmp/final.iid \ + --build-context=base="container-image://${BASE_ID}" \ + --build-arg=COMPOSEFS_FSVERITY="?${BASE_IMAGE_FSVERITY}" \ + --label=containers.composefs.fsverity="${BASE_IMAGE_FSVERITY}" \ + -f "${containerfile}" \ + . + +FINAL_ID="$(sed s/sha256:// tmp/final.iid)" +${CFSCTL} oci pull containers-storage:"${FINAL_ID}" +${CFSCTL} oci prepare-boot "${FINAL_ID}" --bootdir tmp/efi + +../common/install-systemd-boot +../common/make-image -sr "${os}-nofsverity-efi.qcow2" diff --git a/examples/nofsverity/extra/etc/dracut.conf.d/no-xattr.conf b/examples/nofsverity/extra/etc/dracut.conf.d/no-xattr.conf new file mode 100644 index 00000000..b8d114a9 --- /dev/null +++ b/examples/nofsverity/extra/etc/dracut.conf.d/no-xattr.conf @@ -0,0 +1 @@ +export DRACUT_NO_XATTR=1 diff --git a/examples/nofsverity/extra/etc/mkinitcpio.conf b/examples/nofsverity/extra/etc/mkinitcpio.conf new file mode 100644 index 00000000..6f4d4925 --- /dev/null +++ b/examples/nofsverity/extra/etc/mkinitcpio.conf @@ -0,0 +1,3 @@ +MODULES=(overlay erofs) +BINARIES=(strace) +HOOKS=(base udev composefs autodetect microcode modconf kms keyboard keymap block filesystems) diff --git a/examples/nofsverity/extra/etc/mkinitcpio.d/linux.preset b/examples/nofsverity/extra/etc/mkinitcpio.d/linux.preset new file mode 100644 index 00000000..87cd8792 --- /dev/null +++ b/examples/nofsverity/extra/etc/mkinitcpio.d/linux.preset @@ -0,0 +1,10 @@ +ALL_kver="/boot/vmlinuz-linux" + +MODULES=(ext4 overlay erofs) +BINARIES=(fsck.ext4 strace) +HOOKS=(base udev composefs autodetect microcode modconf kms keyboard keymap consolefont block filesystems fsck) + +PRESETS=('default') + +default_uki="/boot/EFI/Linux/arch-linux.efi" +default_options="--splash=/usr/share/systemd/bootctl/splash-arch.bmp" diff --git a/examples/nofsverity/extra/etc/resolv.conf b/examples/nofsverity/extra/etc/resolv.conf new file mode 120000 index 00000000..697ba64f --- /dev/null +++ b/examples/nofsverity/extra/etc/resolv.conf @@ -0,0 +1 @@ +../run/systemd/resolve/stub-resolv.conf \ No newline at end of file diff --git a/examples/nofsverity/extra/root/.ssh/authorized_keys b/examples/nofsverity/extra/root/.ssh/authorized_keys new file mode 100644 index 00000000..d60db7e4 --- /dev/null +++ b/examples/nofsverity/extra/root/.ssh/authorized_keys @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDUOtNJdBEXyKxBB898rdT54ULjMGuO6v4jLXmRsdRhR5Id/lKNc9hsdioPWUePgYlqML2iSV72vKQoVhkyYkpcsjr3zvBny9+5xej3+TBLoEMAm2hmllKPmxYJDU8jQJ7wJuRrOVOnk0iSNF+FcY/yaQ0owSF02Nphx47j2KWc0IjGGlt4fl0fmHJuZBA2afN/4IYIIsEWZziDewVtaEjWV3InMRLllfdqGMllhFR+ed2hQz9PN2QcapmEvUR4UCy/mJXrke5htyFyHi8ECfyMMyYeHwbWLFQIve4CWix9qtksvKjcetnxT+WWrutdr3c9cfIj/c0v/Zg/c4zETxtp cockpit-test diff --git a/examples/nofsverity/extra/usr/lib/dracut/dracut.conf.d/37composefs.conf b/examples/nofsverity/extra/usr/lib/dracut/dracut.conf.d/37composefs.conf new file mode 100644 index 00000000..1defe5de --- /dev/null +++ b/examples/nofsverity/extra/usr/lib/dracut/dracut.conf.d/37composefs.conf @@ -0,0 +1,6 @@ +# we want to make sure the virtio disk drivers get included +hostonly=no + +# we need to force these in via the initramfs because we don't have modules in +# the base image +force_drivers+=" virtio_net vfat " diff --git a/examples/nofsverity/extra/usr/lib/dracut/modules.d/37composefs/composefs-setup-root.service b/examples/nofsverity/extra/usr/lib/dracut/modules.d/37composefs/composefs-setup-root.service new file mode 100644 index 00000000..ffc404d6 --- /dev/null +++ b/examples/nofsverity/extra/usr/lib/dracut/modules.d/37composefs/composefs-setup-root.service @@ -0,0 +1,34 @@ +# Copyright (C) 2013 Colin Walters +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library. If not, see . + +[Unit] +DefaultDependencies=no +ConditionKernelCommandLine=composefs +ConditionPathExists=/etc/initrd-release +After=sysroot.mount +Requires=sysroot.mount +Before=initrd-root-fs.target +Before=initrd-switch-root.target + +OnFailure=emergency.target +OnFailureJobMode=isolate + +[Service] +Type=oneshot +ExecStart=/usr/bin/composefs-setup-root +StandardInput=null +StandardOutput=journal +StandardError=journal+console +RemainAfterExit=yes diff --git a/examples/nofsverity/extra/usr/lib/dracut/modules.d/37composefs/module-setup.sh b/examples/nofsverity/extra/usr/lib/dracut/modules.d/37composefs/module-setup.sh new file mode 100755 index 00000000..34c40a1c --- /dev/null +++ b/examples/nofsverity/extra/usr/lib/dracut/modules.d/37composefs/module-setup.sh @@ -0,0 +1,20 @@ +#!/usr/bin/bash + +check() { + return 0 +} + +depends() { + return 0 +} + +install() { + inst \ + "${moddir}/composefs-setup-root" /bin/composefs-setup-root + inst \ + "${moddir}/composefs-setup-root.service" \ + "${systemdsystemunitdir}/composefs-setup-root.service" + + $SYSTEMCTL -q --root "${initdir}" add-wants \ + 'initrd-root-fs.target' 'composefs-setup-root.service' +} diff --git a/examples/nofsverity/extra/usr/lib/initcpio/hooks/composefs b/examples/nofsverity/extra/usr/lib/initcpio/hooks/composefs new file mode 100644 index 00000000..775ea403 --- /dev/null +++ b/examples/nofsverity/extra/usr/lib/initcpio/hooks/composefs @@ -0,0 +1,12 @@ +#!/usr/bin/ash + +run_latehook() { + local composefs + + composefs="$(getarg composefs)" + if [ -z "$composefs" ]; then + return 0 + fi + + /usr/bin/composefs-setup-root --sysroot /new_root +} diff --git a/examples/nofsverity/extra/usr/lib/initcpio/install/composefs b/examples/nofsverity/extra/usr/lib/initcpio/install/composefs new file mode 100644 index 00000000..752a66db --- /dev/null +++ b/examples/nofsverity/extra/usr/lib/initcpio/install/composefs @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +build() { + add_binary "/usr/lib/dracut/modules.d/37composefs/composefs-setup-root" "/usr/bin/composefs-setup-root" + add_runscript +} diff --git a/examples/nofsverity/extra/usr/lib/kernel/install.conf.d/37composefs.conf b/examples/nofsverity/extra/usr/lib/kernel/install.conf.d/37composefs.conf new file mode 100644 index 00000000..4d12c4ec --- /dev/null +++ b/examples/nofsverity/extra/usr/lib/kernel/install.conf.d/37composefs.conf @@ -0,0 +1,2 @@ +layout = uki +uki_generator = ukify diff --git a/examples/nofsverity/extra/usr/lib/systemd/network/37-wired.network b/examples/nofsverity/extra/usr/lib/systemd/network/37-wired.network new file mode 100644 index 00000000..e4e05fd7 --- /dev/null +++ b/examples/nofsverity/extra/usr/lib/systemd/network/37-wired.network @@ -0,0 +1,9 @@ +[Match] +Type=ether + +[Link] +RequiredForOnline=routable + +[Network] +DHCP=yes + diff --git a/examples/nofsverity/extra/usr/lib/systemd/system/systemd-growfs-root.service.d/37-composefs.conf b/examples/nofsverity/extra/usr/lib/systemd/system/systemd-growfs-root.service.d/37-composefs.conf new file mode 100644 index 00000000..c387c18a --- /dev/null +++ b/examples/nofsverity/extra/usr/lib/systemd/system/systemd-growfs-root.service.d/37-composefs.conf @@ -0,0 +1,6 @@ +# Make sure we grow the right root filesystem + +[Service] +ExecStart= +ExecStart=/usr/lib/systemd/systemd-growfs /sysroot +