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
We also correctly parse the arguments passed on kernel-install.
  • Loading branch information
jmarrero committed Dec 10, 2024
1 parent f446a22 commit 3a4f740
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 14 deletions.
3 changes: 2 additions & 1 deletion docs/treefile.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ 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.
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
Expand Down
43 changes: 32 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 @@ -48,6 +49,8 @@ const USERMOD_WRAPPER: &[u8] = include_bytes!("../../src/libpriv/usermod-wrapper
const KERNEL_INSTALL_PATH: &str = "usr/bin/kernel-install";
const KERNEL_INSTALL_WRAPPER: &[u8] = include_bytes!("../../src/libpriv/kernel-install-wrapper.sh");

// ## Check for layout and wrap if =ostree

const RPMOSTREE_CORE_STAGED_RPMS_DIR: &str = "rpm-ostree/staged-rpms";

pub(crate) const OSTREE_BOOTED: &str = "/run/ostree-booted";
Expand Down Expand Up @@ -166,9 +169,11 @@ impl FilesystemScriptPrep {
(SYSTEMCTL_PATH, SYSTEMCTL_WRAPPER),
(USERADD_PATH, USERADD_WRAPPER),
(USERMOD_PATH, USERMOD_WRAPPER),
(KERNEL_INSTALL_PATH, KERNEL_INSTALL_WRAPPER),
];

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 +193,16 @@ impl FilesystemScriptPrep {
rootfs.atomic_write_with_perms(path, contents, mode)?;
}
}
if std::path::Path::new(OSTREE_BOOTED).exists() && !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 +487,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 std::path::Path::new(OSTREE_BOOTED).exists() && !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
33 changes: 31 additions & 2 deletions rust/src/kernel_install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT

use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::process::Command;

use anyhow::{Context, Result};
Expand All @@ -29,13 +32,36 @@ const SKIP: u8 = 77;
const MODULES: &str = "usr/lib/modules";
/// The default name for the initramfs.
const INITRAMFS: &str = "initramfs.img";
/// The path to the instal.conf that sets layout.
const KERNEL_INSTALL_CONF: &str = "/usr/lib/kernel/install.conf";

#[context("Verifying kernel-install layout file")]
pub fn is_ostree_layout() -> Result<bool> {
let install_conf = Path::new(KERNEL_INSTALL_CONF);
if !install_conf.is_file() {
println!("can not read /usr/lib/kernel/install.conf");
return Ok(false);
}
let buff = BufReader::new(
File::open(install_conf).context("Failed to open /usr/lib/kernel/install.conf")?,
);
// Check for "layout=ostree" in the file
for line in buff.lines() {
let line = line.context("Failed to read line")?;
if line.trim() == "layout=ostree" {
return Ok(true);
}
}
Ok(false)
}

#[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");
};
tracing::debug!("Installing kernel kver={kver}");
println!("Generating initramfs");
crate::initramfs::run_dracut(root, &kver)?;
println!("Running depmod");
Expand All @@ -51,6 +77,7 @@ fn add(root: &Dir, argv: &[&str]) -> Result<()> {

#[context("Removing kernel")]
fn remove(root: &Dir, kver: &str) -> Result<()> {
tracing::debug!("Removing kernel kver={kver}");
let kdir = format!("{MODULES}/{kver}");
let Some(kernel_dir) = root.open_dir_optional(&kdir)? else {
return Ok(());
Expand All @@ -66,6 +93,7 @@ pub fn main(argv: &[&str]) -> Result<u8> {
let Some(layout) = std::env::var_os(LAYOUT_VAR) else {
return Ok(0);
};
tracing::debug!("The LAYOUT_OSTREE is: {:?}", layout.to_str());
if !matches!(layout.to_str(), Some(LAYOUT_OSTREE)) {
return Ok(0);
}
Expand All @@ -76,14 +104,15 @@ pub fn main(argv: &[&str]) -> Result<u8> {
return Ok(0);
}
let root = &Dir::open_ambient_dir("/", cap_std::ambient_authority())?;
tracing::debug!("argv={argv:?}");
match argv {
["add", rest @ ..] => {
[_, _, "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", kver, ..] => {
remove(root, kver)?;
Ok(0)
}
Expand Down

0 comments on commit 3a4f740

Please sign in to comment.