]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nspawn: allow disabling os-release check
authorFrantisek Sumsal <frantisek@sumsal.cz>
Fri, 3 Nov 2023 08:17:48 +0000 (09:17 +0100)
committerLuca Boccassi <luca.boccassi@gmail.com>
Fri, 3 Nov 2023 16:05:14 +0000 (16:05 +0000)
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
src/nspawn/nspawn.c
test/units/testsuite-13.nspawn.sh

index a884ed86ac10a0a63ca4fec6080fd0ea2d93180e..56e79b938454daa213b97d99bd87c9275c241105 100644 (file)
@@ -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
index 8d12fd04cb7f04e141ed59ba457dc415844a5255..38196ef3d63e6d890bbb60e71b1ab30ead85d618 100644 (file)
@@ -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;
index 8d7a2e92ab0752fadfb680616fd874ea155ecc08..8a6fa84dc96ec70cb16795aa634f3cc5e23b3bb4 100755 (executable)
@@ -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