From d4317fe1725987671928b441ddd5040aab7befba Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Fri, 3 Nov 2023 09:17:48 +0100 Subject: [PATCH] nspawn: allow disabling os-release check Introduce a new env variable $SYSTEMD_NSPAWN_CHECK_OS_RELEASE, that can be used to disable the os-release check for bootable OS trees. Useful when trying to boot a container with empty /etc/ and bind-mounted /usr/. Resolves: #29185 --- docs/ENVIRONMENT.md | 4 ++++ src/nspawn/nspawn.c | 12 +++++++++++- test/units/testsuite-13.nspawn.sh | 32 ++++++++++++++++++++++++++++++- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md index a884ed86ac..56e79b9384 100644 --- a/docs/ENVIRONMENT.md +++ b/docs/ENVIRONMENT.md @@ -164,6 +164,10 @@ All tools: * `$SYSTEMD_NSPAWN_TMPFS_TMP=0` — if set, do not overmount `/tmp/` in the container with a tmpfs, but leave the directory from the image in place. +* `$SYSTEMD_NSPAWN_CHECK_OS_RELEASE=0` — if set, do not fail when trying to + boot an OS tree without an os-release file (useful when trying to boot a + container with empty `/etc/` and bind-mounted `/usr/`) + * `$SYSTEMD_SUPPRESS_SYNC=1` — if set, all disk synchronization syscalls are blocked to the container payload (e.g. `sync()`, `fsync()`, `syncfs()`, …) and the `O_SYNC`/`O_DSYNC` flags are made unavailable to `open()` and diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 8d12fd04cb..38196ef3d6 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -5574,6 +5574,7 @@ static int run(int argc, char *argv[]) { if (arg_start_mode == START_BOOT) { _cleanup_free_ char *b = NULL; const char *p; + int check_os_release, is_os_tree; if (arg_pivot_root_new) { b = path_join(arg_directory, arg_pivot_root_new); @@ -5586,7 +5587,16 @@ static int run(int argc, char *argv[]) { } else p = arg_directory; - if (path_is_os_tree(p) <= 0) { + check_os_release = getenv_bool("SYSTEMD_NSPAWN_CHECK_OS_RELEASE"); + if (check_os_release < 0 && check_os_release != -ENXIO) { + r = log_error_errno(check_os_release, "Failed to parse $SYSTEMD_NSPAWN_CHECK_OS_RELEASE: %m"); + goto finish; + } + + is_os_tree = path_is_os_tree(p); + if (is_os_tree == 0 && check_os_release == 0) + log_debug("Directory %s is missing an os-release file, continuing anyway.", p); + else if (is_os_tree <= 0) { r = log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Directory %s doesn't look like an OS root directory (os-release file is missing). Refusing.", p); goto finish; diff --git a/test/units/testsuite-13.nspawn.sh b/test/units/testsuite-13.nspawn.sh index 8d7a2e92ab..8a6fa84dc9 100755 --- a/test/units/testsuite-13.nspawn.sh +++ b/test/units/testsuite-13.nspawn.sh @@ -40,7 +40,7 @@ export SYSTEMD_LOG_TARGET=journal at_exit() { set +e - mountpoint -q /var/lib/machines && umount /var/lib/machines + mountpoint -q /var/lib/machines && umount --recursive /var/lib/machines rm -f /run/systemd/nspawn/*.nspawn } @@ -841,6 +841,36 @@ matrix_run_one() { return 0 } +testcase_check_os_release() { + # https://github.com/systemd/systemd/issues/29185 + local base common_opts root + + base="$(mktemp -d /var/lib/machines/testsuite-13.check_os_release_base.XXX)" + root="$(mktemp -d /var/lib/machines/testsuite-13.check_os_release.XXX)" + create_dummy_container "$base" + cp -d "$base"/{bin,sbin,lib,lib64} "$root/" + common_opts=( + --boot + --register=no + --directory="$root" + --bind-ro="$base/usr:/usr" + ) + + # Empty /etc/ & /usr/ + (! systemd-nspawn "${common_opts[@]}") + (! SYSTEMD_NSPAWN_CHECK_OS_RELEASE=1 systemd-nspawn "${common_opts[@]}") + (! SYSTEMD_NSPAWN_CHECK_OS_RELEASE=foo systemd-nspawn "${common_opts[@]}") + SYSTEMD_NSPAWN_CHECK_OS_RELEASE=0 systemd-nspawn "${common_opts[@]}" + + # Empty /usr/ + a broken /etc/os-release -> /usr/os-release symlink + ln -svrf "$root/etc/os-release" "$root/usr/os-release" + (! systemd-nspawn "${common_opts[@]}") + (! SYSTEMD_NSPAWN_CHECK_OS_RELEASE=1 systemd-nspawn "${common_opts[@]}") + SYSTEMD_NSPAWN_CHECK_OS_RELEASE=0 systemd-nspawn "${common_opts[@]}" + + rm -fr "$root" "$base" +} + run_testcases for api_vfs_writable in yes no network; do -- 2.25.1