1
0
mirror of https://github.com/containers/bootc.git synced 2026-02-05 06:45:13 +01:00

lib: Fix bootc status on non-bootc systems

Previously, `BootedStorage::new()` unconditionally tried to open
`/sysroot` before checking the environment type. This caused
`bootc status` to fail on non-ostree/composefs systems.

(We did work in containers and we had tests for that; but
 the container case is special cased even earlier)

Fixes: https://issues.redhat.com/browse/RHEL-135687

Assisted-by: Claude Code (Opus 4.5)
Signed-off-by: Colin Walters <walters@verbum.org>
This commit is contained in:
Colin Walters
2025-12-12 15:30:50 -05:00
parent 68d5cea970
commit 3efcbddeb3
3 changed files with 48 additions and 14 deletions

View File

@@ -145,28 +145,27 @@ pub(crate) enum BootedStorageKind<'a> {
Composefs(BootedComposefs),
}
/// Open the physical root (/sysroot) and /run directories for a booted system.
fn get_physical_root_and_run() -> Result<(Dir, Dir)> {
let physical_root = {
let d = Dir::open_ambient_dir("/sysroot", cap_std::ambient_authority())
.context("Opening /sysroot")?;
open_dir_remount_rw(&d, ".".into())?
};
let run =
Dir::open_ambient_dir("/run", cap_std::ambient_authority()).context("Opening /run")?;
Ok((physical_root, run))
}
impl BootedStorage {
/// Create a new booted storage accessor for the given environment.
///
/// The caller must have already called `prepare_for_write()` if
/// `env.needs_mount_namespace()` is true.
pub(crate) async fn new(env: Environment) -> Result<Option<Self>> {
let physical_root = {
let d = Dir::open_ambient_dir("/sysroot", cap_std::ambient_authority())
.context("Opening /sysroot")?;
// Remount /sysroot rw only if we are in a new mount ns
if env.needs_mount_namespace() {
open_dir_remount_rw(&d, ".".into())?
} else {
d
}
};
let run =
Dir::open_ambient_dir("/run", cap_std::ambient_authority()).context("Opening /run")?;
let r = match &env {
Environment::ComposefsBooted(cmdline) => {
let (physical_root, run) = get_physical_root_and_run()?;
let mut composefs = ComposefsRepository::open_path(&physical_root, COMPOSEFS)?;
if cmdline.insecure {
composefs.set_insecure(true);
@@ -204,6 +203,7 @@ impl BootedStorage {
// remount /sysroot as writable, and we call set_mount_namespace_in_use()
// to indicate we're in a mount namespace. Without actually being in a
// mount namespace, this would leave the global /sysroot writable.
let (physical_root, run) = get_physical_root_and_run()?;
let sysroot = ostree::Sysroot::new_default();
sysroot.set_mount_namespace_in_use();
@@ -223,6 +223,7 @@ impl BootedStorage {
Some(Self { storage })
}
// For container or non-bootc environments, there's no storage
Environment::Container | Environment::Other => None,
};
Ok(r)

View File

@@ -4,6 +4,9 @@ set -exuo pipefail
# Check environment
printenv
# This must work outside of a container too
bootc status
# temp folder to save building files and folders
BOOTC_TEMPDIR=$(mktemp -d)
trap 'rm -rf -- "$BOOTC_TEMPDIR"' EXIT

View File

@@ -0,0 +1,30 @@
#!/bin/bash
# Test that `bootc status` works on a non-bootc-deployed system.
#
# This simulates a "package mode" environment where bootc is installed
# via RPM on a traditional system (not deployed via ostree/composefs).
# The key is hiding /run/.containerenv so bootc doesn't think it's in a container.
#
# xref: https://issues.redhat.com/browse/RHEL-135687
set -euo pipefail
image=$1
# Run the container with:
# - A tmpfs over /run to hide .containerenv (simulates bare metal)
# - Unset the 'container' environment variable
# - No /sysroot (simulates package mode)
# Use --format=humanreadable to get consistent output
output=$(podman run --rm \
--tmpfs /run \
--env container= \
"$image" \
bootc status --format=humanreadable 2>&1)
# Verify the output indicates this is not a bootc-deployed system
if echo "$output" | grep -q "System is not deployed via bootc"; then
echo "ok status-outside-container: correctly reports non-bootc system"
else
echo "FAIL: unexpected output from bootc status:" >&2
echo "$output" >&2
exit 1
fi