* `$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
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);
} 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;
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
}
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