Skip to content

Commit

Permalink
core: stop wrapping kernel-install when layout=ostree is set
Browse files Browse the repository at this point in the history
Co-authored-by: Colin Walters <[email protected]>
Signed-off-by: Colin Walters <[email protected]>
Signed-off-by: Joseph Marrero <[email protected]>
  • Loading branch information
cgwalters authored and jmarrero committed Jan 8, 2025
1 parent 8a5dfc0 commit a560bfa
Show file tree
Hide file tree
Showing 15 changed files with 307 additions and 58 deletions.
4 changes: 4 additions & 0 deletions docs/treefile.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ It supports the following parameters:
this for new systems, and systems that don't need to be upgraded
from very old libostree versions. This is the default for editions 2024
and above.
* "kernel-install": The system is integrated with `/sbin/kernel-install`
from systemd. You likely want to additionally pair this with configuring `layout=ostree`
in `/usr/lib/kernel/install.conf`, and adding a wrapper script to
`/usr/lib/kernel/install.d/05-rpmostree.install`

* `etc-group-members`: Array of strings, optional: Unix groups in this
list will be stored in `/etc/group` instead of `/usr/lib/group`. Use
Expand Down
17 changes: 14 additions & 3 deletions rpmostree-cxxrs.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1783,6 +1783,7 @@ struct Treefile final : public ::rust::Opaque
bool get_machineid_compat () const noexcept;
::rust::Vec< ::rust::String> get_etc_group_members () const noexcept;
bool get_boot_location_is_modules () const noexcept;
bool use_kernel_install () const noexcept;
bool get_ima () const noexcept;
::rust::String get_releasever () const noexcept;
::rpmostreecxx::RepoMetadataTarget get_repo_metadata_target () const noexcept;
Expand Down Expand Up @@ -2432,7 +2433,8 @@ extern "C"
::rpmostreecxx::TokioEnterGuard *
rpmostreecxx$cxxbridge1$TokioHandle$enter (::rpmostreecxx::TokioHandle const &self) noexcept;

bool rpmostreecxx$cxxbridge1$script_is_ignored (::rust::Str pkg, ::rust::Str script) noexcept;
bool rpmostreecxx$cxxbridge1$script_is_ignored (::rust::Str pkg, ::rust::Str script,
bool use_kernel_install) noexcept;

::rust::repr::PtrLen
rpmostreecxx$cxxbridge1$testutils_entrypoint (::rust::Vec< ::rust::String> *argv) noexcept;
Expand Down Expand Up @@ -2633,6 +2635,9 @@ extern "C"
bool rpmostreecxx$cxxbridge1$Treefile$get_boot_location_is_modules (
::rpmostreecxx::Treefile const &self) noexcept;

bool rpmostreecxx$cxxbridge1$Treefile$use_kernel_install (
::rpmostreecxx::Treefile const &self) noexcept;

bool rpmostreecxx$cxxbridge1$Treefile$get_ima (::rpmostreecxx::Treefile const &self) noexcept;

void rpmostreecxx$cxxbridge1$Treefile$get_releasever (::rpmostreecxx::Treefile const &self,
Expand Down Expand Up @@ -4648,9 +4653,9 @@ TokioHandle::enter () const noexcept
}

bool
script_is_ignored (::rust::Str pkg, ::rust::Str script) noexcept
script_is_ignored (::rust::Str pkg, ::rust::Str script, bool use_kernel_install) noexcept
{
return rpmostreecxx$cxxbridge1$script_is_ignored (pkg, script);
return rpmostreecxx$cxxbridge1$script_is_ignored (pkg, script, use_kernel_install);
}

void
Expand Down Expand Up @@ -5203,6 +5208,12 @@ Treefile::get_boot_location_is_modules () const noexcept
return rpmostreecxx$cxxbridge1$Treefile$get_boot_location_is_modules (*this);
}

bool
Treefile::use_kernel_install () const noexcept
{
return rpmostreecxx$cxxbridge1$Treefile$use_kernel_install (*this);
}

bool
Treefile::get_ima () const noexcept
{
Expand Down
3 changes: 2 additions & 1 deletion rpmostree-cxxrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1560,6 +1560,7 @@ struct Treefile final : public ::rust::Opaque
bool get_machineid_compat () const noexcept;
::rust::Vec< ::rust::String> get_etc_group_members () const noexcept;
bool get_boot_location_is_modules () const noexcept;
bool use_kernel_install () const noexcept;
bool get_ima () const noexcept;
::rust::String get_releasever () const noexcept;
::rpmostreecxx::RepoMetadataTarget get_repo_metadata_target () const noexcept;
Expand Down Expand Up @@ -1976,7 +1977,7 @@ void history_prune ();

::rust::Box< ::rpmostreecxx::TokioHandle> tokio_handle_get () noexcept;

bool script_is_ignored (::rust::Str pkg, ::rust::Str script) noexcept;
bool script_is_ignored (::rust::Str pkg, ::rust::Str script, bool use_kernel_install) noexcept;

void testutils_entrypoint (::rust::Vec< ::rust::String> argv);

Expand Down
39 changes: 33 additions & 6 deletions rust/src/cliwrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ use std::io::prelude::*;
mod cliutil;
mod dracut;
mod grubby;
mod kernel_install;
mod kernel_install_wrap;
mod rpm;
mod yumdnf;
use crate::cxxrsutil::CxxResult;
use crate::ffi::SystemHostType;
use crate::ffiutil::*;
use crate::kernel_install::is_ostree_layout;

/// Location for the underlying (not wrapped) binaries.
pub const CLIWRAP_DESTDIR: &str = "usr/libexec/rpm-ostree/wrapped";
Expand All @@ -29,7 +30,10 @@ pub const CLIWRAP_DESTDIR: &str = "usr/libexec/rpm-ostree/wrapped";
static WRAPPED_BINARIES: &[&str] = &["usr/bin/rpm", "usr/bin/dracut", "usr/sbin/grubby"];

/// Binaries we will wrap, or create if they don't exist.
static MUSTWRAP_BINARIES: &[&str] = &["usr/bin/yum", "usr/bin/dnf", "usr/bin/kernel-install"];
static MUSTWRAP_BINARIES: &[&str] = &["usr/bin/yum", "usr/bin/dnf"];

/// Binaries we will wrap only if ostree layout is not specified.
static NON_OSTREE_LAYOUT_WRAP_BINARIES: &[&str] = &["usr/bin/kernel-install"];

#[derive(Debug, PartialEq)]
pub(crate) enum RunDisposition {
Expand Down Expand Up @@ -74,7 +78,7 @@ pub fn entrypoint(args: &[&str]) -> Result<()> {
"yum" | "dnf" => Ok(self::yumdnf::main(host_type, args)?),
"dracut" => Ok(self::dracut::main(args)?),
"grubby" => Ok(self::grubby::main(args)?),
"kernel-install" => Ok(self::kernel_install::main(args)?),
"kernel-install" if !is_ostree_layout()? => Ok(self::kernel_install_wrap::main(args)?),
_ => Err(anyhow!("Unknown wrapped binary: {}", name)),
}
} else {
Expand Down Expand Up @@ -153,12 +157,21 @@ fn write_wrappers(rootfs_dfd: &Dir, allowlist: Option<&HashSet<&str>>) -> Result

let all_wrapped = WRAPPED_BINARIES.iter().map(Utf8Path::new);
let all_mustwrap = MUSTWRAP_BINARIES.iter().map(Utf8Path::new);
let all_names = all_wrapped
let all_non_ostree_layout_wrap = NON_OSTREE_LAYOUT_WRAP_BINARIES.iter().map(Utf8Path::new);
let mut all_names = all_wrapped
.clone()
.chain(all_mustwrap.clone())
.map(|p| p.file_name().unwrap())
.collect::<HashSet<_>>();

if !is_ostree_layout()? {
all_names.extend(
all_non_ostree_layout_wrap
.clone()
.map(|p| p.file_name().unwrap()),
);
}

if let Some(allowlist) = allowlist.as_ref() {
for k in allowlist.iter() {
if !all_names.contains(k) {
Expand All @@ -170,16 +183,30 @@ fn write_wrappers(rootfs_dfd: &Dir, allowlist: Option<&HashSet<&str>>) -> Result
let allowlist_contains =
|v: &(&Utf8Path, bool)| allowlist.map_or(true, |l| l.contains(v.0.file_name().unwrap()));

WRAPPED_BINARIES
let final_binaries = WRAPPED_BINARIES
.par_iter()
.map(|p| (Utf8Path::new(p), true))
.chain(
MUSTWRAP_BINARIES
.par_iter()
.map(|p| (Utf8Path::new(p), false)),
)
.chain(if !is_ostree_layout()? {
NON_OSTREE_LAYOUT_WRAP_BINARIES
.par_iter()
.map(|p| (Utf8Path::new(p), false))
.collect::<Vec<_>>()
.into_par_iter()
} else {
Vec::new().into_par_iter()
});

final_binaries
.filter(allowlist_contains)
.try_for_each(|(binpath, allow_noent)| write_one_wrapper(rootfs_dfd, binpath, allow_noent))
.try_for_each(|(binpath, allow_noent)| {
write_one_wrapper(rootfs_dfd, binpath, allow_noent)
})?;
Ok(())
}

pub(crate) fn cliwrap_write_wrappers(rootfs_dfd: i32) -> CxxResult<()> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use crate::cliwrap::cliutil;
use anyhow::Result;
use camino::Utf8Path;
use cap_std::fs::Dir as StdDir;
use cap_std::fs::FileType;
use cap_std::fs_utf8::Dir as Utf8Dir;
use cap_std_ext::cap_std;
Expand Down Expand Up @@ -39,7 +40,8 @@ pub(crate) fn main(argv: &[&str]) -> Result<()> {
}
if let Some(k) = new_kernel {
undo_systemctl_wrap()?;
crate::initramfs::run_dracut(&k)?;
let root_fs = StdDir::open_ambient_dir("/", cap_std::ambient_authority())?;
crate::initramfs::run_dracut(&root_fs, &k)?;
redo_systemctl_wrap()?;
}
Ok(())
Expand Down
42 changes: 31 additions & 11 deletions rust/src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use crate::cxxrsutil::*;
use crate::ffiutil;
use crate::kernel_install::is_ostree_layout;
use anyhow::Context;
use anyhow::{anyhow, Result};
use camino::Utf8Path;
Expand Down Expand Up @@ -166,9 +167,12 @@ impl FilesystemScriptPrep {
(SYSTEMCTL_PATH, SYSTEMCTL_WRAPPER),
(USERADD_PATH, USERADD_WRAPPER),
(USERMOD_PATH, USERMOD_WRAPPER),
(KERNEL_INSTALL_PATH, KERNEL_INSTALL_WRAPPER),
];

// Separate const as is used only to wrap kernel-install if !is_ostree_layout()
const REPLACE_KERNEL_PATHS: &'static [(&'static str, &'static [u8])] =
&[(KERNEL_INSTALL_PATH, KERNEL_INSTALL_WRAPPER)];

fn saved_name(name: &str) -> String {
format!("{}.rpmostreesave", name)
}
Expand All @@ -188,6 +192,16 @@ impl FilesystemScriptPrep {
rootfs.atomic_write_with_perms(path, contents, mode)?;
}
}
if !is_ostree_layout()? {
for &(path, contents) in Self::REPLACE_KERNEL_PATHS {
let mode = Permissions::from_mode(0o755);
let saved = &Self::saved_name(path);
if rootfs.try_exists(path)? {
rootfs.rename(path, &rootfs, saved)?;
rootfs.atomic_write_with_perms(path, contents, mode)?;
}
}
}
Ok(Box::new(Self {
rootfs,
enabled: true,
Expand Down Expand Up @@ -472,16 +486,22 @@ mod test {
}
// Replaced kernel-install.
{
let original_kernel_install = "original kernel_install";
d.atomic_write_with_perms(super::KERNEL_INSTALL_PATH, original_kernel_install, mode)?;
let contents = d.read_to_string(super::KERNEL_INSTALL_PATH)?;
assert_eq!(contents, original_kernel_install);
let mut g = super::prepare_filesystem_script_prep(d.as_raw_fd())?;
let contents = d.read_to_string(super::KERNEL_INSTALL_PATH)?;
assert_eq!(contents.as_bytes(), super::KERNEL_INSTALL_WRAPPER);
g.undo()?;
let contents = d.read_to_string(super::KERNEL_INSTALL_PATH)?;
assert_eq!(contents, original_kernel_install);
if !is_ostree_layout()? {
let original_kernel_install = "original kernel_install";
d.atomic_write_with_perms(
super::KERNEL_INSTALL_PATH,
original_kernel_install,
mode,
)?;
let contents = d.read_to_string(super::KERNEL_INSTALL_PATH)?;
assert_eq!(contents, original_kernel_install);
let mut g = super::prepare_filesystem_script_prep(d.as_raw_fd())?;
let contents = d.read_to_string(super::KERNEL_INSTALL_PATH)?;
assert_eq!(contents.as_bytes(), super::KERNEL_INSTALL_WRAPPER);
g.undo()?;
let contents = d.read_to_string(super::KERNEL_INSTALL_PATH)?;
assert_eq!(contents, original_kernel_install);
}
}
Ok(())
}
Expand Down
5 changes: 2 additions & 3 deletions rust/src/initramfs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use crate::cxxrsutil::*;
use anyhow::{anyhow, Context, Result};
use camino::Utf8Path;
use cap_std::fs_utf8::Dir as Utf8Dir;
use cap_std::fs::Dir;
use cap_std::io_lifetimes::AsFilelike;
use cap_std_ext::cap_std;
use cap_std_ext::prelude::CapStdExtCommandExt;
Expand Down Expand Up @@ -185,8 +185,7 @@ pub(crate) fn initramfs_overlay_generate(
}

#[context("Running dracut")]
pub(crate) fn run_dracut(kernel_dir: &str) -> Result<()> {
let root_fs = Utf8Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
pub(crate) fn run_dracut(root_fs: &Dir, kernel_dir: &str) -> Result<()> {
let tmp_dir = tempfile::tempdir()?;
let tmp_initramfs_path = tmp_dir.path().join("initramfs.img");

Expand Down
Loading

0 comments on commit a560bfa

Please sign in to comment.