Skip to content

Commit

Permalink
cliwrap: remove kernel-install wrap for integration
Browse files Browse the repository at this point in the history
Signed-off-by: Colin Walters <[email protected]>
  • Loading branch information
cgwalters authored and jmarrero committed Dec 10, 2024
1 parent 94b701f commit f446a22
Show file tree
Hide file tree
Showing 14 changed files with 213 additions and 107 deletions.
7 changes: 5 additions & 2 deletions docs/treefile.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@ It supports the following parameters:
upgrading from very old versions of libostree.
* "modules": Kernel data goes just in `/usr/lib/modules`. Use
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.
from very old libostree versions.
* "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
4 changes: 1 addition & 3 deletions rust/src/cliwrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use std::io::prelude::*;
mod cliutil;
mod dracut;
mod grubby;
mod kernel_install;
mod rpm;
mod yumdnf;
use crate::cxxrsutil::CxxResult;
Expand All @@ -29,7 +28,7 @@ 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"];

#[derive(Debug, PartialEq)]
pub(crate) enum RunDisposition {
Expand Down Expand Up @@ -74,7 +73,6 @@ 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)?),
_ => Err(anyhow!("Unknown wrapped binary: {}", name)),
}
} else {
Expand Down
62 changes: 0 additions & 62 deletions rust/src/cliwrap/kernel_install.rs

This file was deleted.

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
92 changes: 92 additions & 0 deletions rust/src/kernel_install.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
//! Integration with the systemd-owned /sbin/kernel-install tooling.
//!
//! Note that there's two different phases of kernel handling:
//!
//! - build time
//! - deployment time (owned by ostree)
//!
//! This code is wholly concerned with "build time" today. The
//! "deployment time" logic is owned entirely by ostree.
//!
// SPDX-License-Identifier: Apache-2.0 OR MIT

use std::process::Command;

use anyhow::{Context, Result};
use cap_std::fs::Dir;
use cap_std_ext::cap_std;
use cap_std_ext::dirext::CapStdExtDirExt;
use fn_error_context::context;

/// Parsed by kernel-install and set in the environment
const LAYOUT_VAR: &str = "KERNEL_INSTALL_LAYOUT";
/// The value we expect to find for layout
const LAYOUT_OSTREE: &str = "ostree";
/// What we should emit to skip further processing
const SKIP: u8 = 77;
/// The path to the kernel modules
const MODULES: &str = "usr/lib/modules";
/// The default name for the initramfs.
const INITRAMFS: &str = "initramfs.img";

#[context("Adding kernel")]
fn add(root: &Dir, argv: &[&str]) -> Result<()> {
let mut argv_it = argv.iter().copied();
let Some(kver) = argv_it.next() else {
anyhow::bail!("No kernel version provided");
};
println!("Generating initramfs");
crate::initramfs::run_dracut(root, &kver)?;
println!("Running depmod");
let st = Command::new("depmod")
.args(["-a", kver])
.status()
.context("Invoking depmod")?;
if !st.success() {
anyhow::bail!("Failed to run depmod: {st:?}");
}
Ok(())
}

#[context("Removing kernel")]
fn remove(root: &Dir, kver: &str) -> Result<()> {
let kdir = format!("{MODULES}/{kver}");
let Some(kernel_dir) = root.open_dir_optional(&kdir)? else {
return Ok(());
};
// We generate the initramfs, so remove it if it exists.
kernel_dir.remove_file_optional(INITRAMFS)?;
Ok(())
}

/// Primary entrypoint to `/usr/lib/kernel-install.d/05-rpmostree.install`.
#[context("rpm-ostree kernel-install")]
pub fn main(argv: &[&str]) -> Result<u8> {
let Some(layout) = std::env::var_os(LAYOUT_VAR) else {
return Ok(0);
};
if !matches!(layout.to_str(), Some(LAYOUT_OSTREE)) {
return Ok(0);
}
if !ostree_ext::container_utils::is_ostree_container()? {
eprintln!(
"warning: confused state: {LAYOUT_VAR}={LAYOUT_OSTREE} but not in an ostree container"
);
return Ok(0);
}
let root = &Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
match argv {
["add", rest @ ..] => {
add(root, rest)?;
// In the case of adding a new kernel, we intercept everything else
// today. In the future we can try to ensure we reuse what bits are there.
Ok(SKIP)
}
["remove", kver] => {
remove(root, kver)?;
Ok(0)
}
_ => Ok(0),
}
}
4 changes: 3 additions & 1 deletion rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ pub mod ffi {

// scripts.rs
extern "Rust" {
fn script_is_ignored(pkg: &str, script: &str) -> bool;
fn script_is_ignored(pkg: &str, script: &str, use_kernel_install: bool) -> bool;
}

// testutils.rs
Expand Down Expand Up @@ -627,6 +627,7 @@ pub mod ffi {
fn get_machineid_compat(&self) -> bool;
fn get_etc_group_members(&self) -> Vec<String>;
fn get_boot_location_is_modules(&self) -> bool;
fn use_kernel_install(&self) -> bool;
fn get_ima(&self) -> bool;
fn get_releasever(&self) -> String;
fn get_repo_metadata_target(&self) -> RepoMetadataTarget;
Expand Down Expand Up @@ -990,6 +991,7 @@ mod initramfs;
pub(crate) use self::initramfs::*;
mod isolation;
mod journal;
pub mod kernel_install;
pub(crate) use self::journal::*;
mod kickstart;
mod lockfile;
Expand Down
1 change: 1 addition & 0 deletions rust/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ async fn inner_async_main(args: Vec<String>) -> Result<i32> {
match *arg {
// Add custom Rust commands here, and also in `libmain.cxx` if user-visible.
"countme" => rpmostree_rust::countme::entrypoint(args).map(|_| 0),
"kernel-install" => rpmostree_rust::kernel_install::main(args).map(Into::into),
"fix-shadow-perms" => rpmostree_rust::passwd::fix_shadow_perms_entrypoint(args).map(|_| 0),
"cliwrap" => rpmostree_rust::cliwrap::entrypoint(args).map(|_| 0),
// A hidden wrapper to intercept some binaries in RPM scriptlets.
Expand Down
50 changes: 42 additions & 8 deletions rust/src/scripts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,11 @@

use phf::phf_set;

/// Some RPM scripts we don't want to execute. A notable example is the kernel ones;
/// we want rpm-ostree to own running dracut, installing the kernel to /boot etc.
/// Ideally more of these migrate out, e.g. in the future we should change the kernel
/// package to do nothing if `/run/ostree-booted` exists.
/// If we're not using boot-location: kernel-install, then we take over the
/// kernel RPM scripts.
///
/// NOTE FOR GIT history: This list used to live in src/libpriv/rpmostree-script-gperf.gperf
static IGNORED_PKG_SCRIPTS: phf::Set<&'static str> = phf_set! {
"glibc.prein",
static IGNORED_KERNEL_SCRIPTS: phf::Set<&'static str> = phf_set! {
// We take over depmod/dracut etc. It's `kernel` in C7 and kernel-core in F25+
// XXX: we should probably change this to instead ignore based on the kernel virtual Provides
"kernel.posttrans",
Expand Down Expand Up @@ -50,6 +47,10 @@ static IGNORED_PKG_SCRIPTS: phf::Set<&'static str> = phf_set! {
"kernel-ml.posttrans",
"kernel-ml-core.posttrans",
"kernel-ml-modules.posttrans",
};

static IGNORED_PKG_SCRIPTS: phf::Set<&'static str> = phf_set! {
"glibc.prein",
// Legacy workaround
"glibc-headers.prein",
// workaround for old bug?
Expand Down Expand Up @@ -90,8 +91,41 @@ static IGNORED_PKG_SCRIPTS: phf::Set<&'static str> = phf_set! {

/// Returns true if we should simply ignore (not execute) an RPM script.
/// The format is <packagename>.<script>
pub(crate) fn script_is_ignored(pkg: &str, script: &str) -> bool {
pub(crate) fn script_is_ignored(pkg: &str, script: &str, use_kernel_install: bool) -> bool {
let script = script.trim_start_matches('%');
let pkgscript = format!("{}.{}", pkg, script);
IGNORED_PKG_SCRIPTS.contains(pkgscript.as_str())
if IGNORED_PKG_SCRIPTS.contains(&pkgscript) {
return true;
}
if !use_kernel_install {
return IGNORED_KERNEL_SCRIPTS.contains(&pkgscript);
}
return false;
}

#[cfg(test)]
mod test {
use crate::script_is_ignored;

#[test]
fn test_script_is_ignored() {
let ignored = ["microcode_ctl.post", "vagrant.prein"];
let not_ignored = ["foobar.post", "systemd.posttrans"];
let kernel_ignored = ["kernel-automotive-core.posttrans"];
for v in ignored {
let (pkg, script) = v.split_once('.').unwrap();
assert!(script_is_ignored(pkg, script, false));
assert!(script_is_ignored(pkg, script, true));
}
for v in not_ignored {
let (pkg, script) = v.split_once('.').unwrap();
assert!(!script_is_ignored(pkg, script, false));
assert!(!script_is_ignored(pkg, script, true));
}
for v in kernel_ignored {
let (pkg, script) = v.split_once('.').unwrap();
assert!(script_is_ignored(pkg, script, false));
assert!(!script_is_ignored(pkg, script, true));
}
}
}
Loading

0 comments on commit f446a22

Please sign in to comment.