Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,10 @@ jobs:
run: |
set -xeuo pipefail
sudo ./scripts/test-uefi-vm-boot.sh "$IMG_NAME" "ostree"
sudo ./scripts/test-uefi-vm-boot.sh "$IMG_NAME" "composefs"

# TODO: Skip composefs tests for C10S as bootc 1.16.3 uses composefs.digest=
# cmdline, but for some reason that cmdline is not mentioned in
# bootc-root-setup.service
if [[ "${{ matrix.stream }}" != "10" ]]; then
sudo ./scripts/test-uefi-vm-boot.sh "$IMG_NAME" "composefs"
fi
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ if [ "$ID" = "centos" ]; then
dnf -y copr enable rhcontainerbot/bootc centos-stream-${VERSION_ID}-$(uname -m)
fi
dnf -y install bootc
# The copr bootc can be newer than the one in the base image's initramfs;
# a newer bootc with an older initramfs is unsupported (e.g. it can write
# composefs kargs the old initramfs doesn't recognize), so regenerate it.
kver=$(cd /usr/lib/modules && echo *)
dracut --force --kver "$kver" "/usr/lib/modules/$kver/initramfs.img"
dnf clean all
rm -rf /var/log
rm -rf /var/lib
Expand Down
2 changes: 2 additions & 0 deletions src/aleph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

use anyhow::{Context, Result};
use chrono::prelude::*;
use fn_error_context::context;
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::path::Path;
Expand All @@ -36,6 +37,7 @@ const ALEPH_PATHS: &[&str] = &[
"sysroot/.bootc-aleph.json",
];

#[context("Getting aleph version")]
pub(crate) fn get_aleph_version(root: &Path) -> Result<Option<AlephWithTimestamp>> {
for aleph_path in ALEPH_PATHS {
let path = &root.join(aleph_path);
Expand Down
50 changes: 41 additions & 9 deletions src/grubconfigs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,27 +174,41 @@ fn write_grubenv(grubdir: &Dir) -> Result<()> {
.run_inherited_with_cmd_context()
}

#[context("Ensure file permissions are 0600")]
#[context("Ensure file permissions are {GRUBCONFIG_FILE_MODE:04o}")]
fn ensure_file_permissions(target_dir: &Dir, target_file: &str) -> Result<()> {
let metadata = match target_dir.metadata(target_file) {
use std::os::unix::fs::PermissionsExt;

// grub.cfg may be a symlink pointing outside this Dir cap_std refuses to traverse
// such symlinks via openat, so resolve through /proc/self/fd
let absolute_path = format!("/proc/self/fd/{}/{target_file}", target_dir.as_raw_fd());

let metadata = match std::fs::metadata(&absolute_path) {
Ok(metadata) => metadata,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
// Silently return if file doesn't exist
log::debug!("File {target_file} not found");
return Ok(());
}
Err(e) => return Err(e).context(format!("Reading {} metadata", target_file)),
};

let mode = metadata.permissions().mode() & 0o777;
if mode != GRUBCONFIG_FILE_MODE {
target_dir
.set_permissions(target_file, Permissions::from_mode(GRUBCONFIG_FILE_MODE))
.with_context(|| format!("Setting {} permissions to 0600", target_file))?;
std::fs::set_permissions(
absolute_path,
std::fs::Permissions::from_mode(GRUBCONFIG_FILE_MODE),
)
.with_context(|| {
format!(
"Setting {} permissions to {GRUBCONFIG_FILE_MODE:04o}",
target_file
)
})?;
}
Ok(())
}

#[context("Ensure grub files permissions are 0600")]
#[context("Ensure grub files permissions are {GRUBCONFIG_FILE_MODE:04o}")]
pub(crate) fn ensure_grub_permissions(grub_dir: &Dir) -> Result<()> {
for file_name in GRUB_FILES.iter() {
ensure_file_permissions(&grub_dir, file_name)
Expand Down Expand Up @@ -251,7 +265,7 @@ mod tests {
{
let metadata = td.metadata("grubenv")?;
let mode = metadata.permissions().mode() & 0o777;
assert_eq!(mode, 0o600);
assert_eq!(mode, GRUBCONFIG_FILE_MODE);
}
Ok(())
}
Expand Down Expand Up @@ -285,11 +299,29 @@ mod tests {

// Verify grubenv was fixed to 0o600
let metadata = grub_dir.metadata("grubenv")?;
assert_eq!(metadata.permissions().mode() & 0o777, 0o600);
assert_eq!(metadata.permissions().mode() & 0o777, GRUBCONFIG_FILE_MODE);

// Verify grub.cfg was fixed 0o600
let metadata = grub_dir.metadata("grub.cfg")?;
assert_eq!(metadata.permissions().mode() & 0o777, 0o600);
assert_eq!(metadata.permissions().mode() & 0o777, GRUBCONFIG_FILE_MODE);

use std::os::unix::fs::PermissionsExt;

// Test it with symlinks pointing outside the grub2 dir
// Create the symlink target outside the grub2 dir, with wrong perms
let external_target = tdp.join("external-grub.cfg");
std::fs::write(&external_target, "external grub.cfg content")?;
std::fs::set_permissions(&external_target, std::fs::Permissions::from_mode(0o644))?;

grub_dir.remove_file("grub.cfg")?;
std::os::unix::fs::symlink(&external_target, grub.join("grub.cfg"))?;

ensure_grub_permissions(&grub_dir)?;

// Verify grub.cfg was fixed 0o600
let metadata = std::fs::metadata(&external_target)?;
assert_eq!(metadata.permissions().mode() & 0o777, GRUBCONFIG_FILE_MODE);

Ok(())
}
}