sysext: Check for /etc/initrd-release in given --root= tree (#39473)
This commit is contained in:
@@ -619,6 +619,7 @@ static int image_make(
|
||||
static int pick_image_search_path(
|
||||
RuntimeScope scope,
|
||||
ImageClass class,
|
||||
const char *root,
|
||||
char ***ret) {
|
||||
|
||||
int r;
|
||||
@@ -635,11 +636,11 @@ static int pick_image_search_path(
|
||||
if (scope < 0) {
|
||||
_cleanup_strv_free_ char **a = NULL, **b = NULL;
|
||||
|
||||
r = pick_image_search_path(RUNTIME_SCOPE_USER, class, &a);
|
||||
r = pick_image_search_path(RUNTIME_SCOPE_USER, class, root, &a);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pick_image_search_path(RUNTIME_SCOPE_SYSTEM, class, &b);
|
||||
r = pick_image_search_path(RUNTIME_SCOPE_SYSTEM, class, root, &b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -655,8 +656,15 @@ static int pick_image_search_path(
|
||||
|
||||
case RUNTIME_SCOPE_SYSTEM: {
|
||||
const char *ns;
|
||||
bool is_initrd;
|
||||
|
||||
r = chase_and_access("/etc/initrd-release", root, CHASE_PREFIX_ROOT, F_OK, /* ret_path= */ NULL);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return r;
|
||||
is_initrd = r >= 0;
|
||||
|
||||
/* Use the initrd search path if there is one, otherwise use the common one */
|
||||
ns = in_initrd() && image_search_path_initrd[class] ?
|
||||
ns = is_initrd && image_search_path_initrd[class] ?
|
||||
image_search_path_initrd[class] :
|
||||
image_search_path[class];
|
||||
if (!ns)
|
||||
@@ -763,7 +771,7 @@ int image_find(RuntimeScope scope,
|
||||
return -ENOMEM;
|
||||
|
||||
_cleanup_strv_free_ char **search = NULL;
|
||||
r = pick_image_search_path(scope, class, &search);
|
||||
r = pick_image_search_path(scope, class, root, &search);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -954,7 +962,7 @@ int image_discover(
|
||||
assert(images);
|
||||
|
||||
_cleanup_strv_free_ char **search = NULL;
|
||||
r = pick_image_search_path(scope, class, &search);
|
||||
r = pick_image_search_path(scope, class, root, &search);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@@ -2101,7 +2109,7 @@ bool image_in_search_path(
|
||||
assert(image);
|
||||
|
||||
_cleanup_strv_free_ char **search = NULL;
|
||||
r = pick_image_search_path(scope, class, &search);
|
||||
r = pick_image_search_path(scope, class, root, &search);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
+11
-3
@@ -1707,9 +1707,11 @@ static const ImagePolicy *pick_image_policy(const Image *img) {
|
||||
|
||||
/* If located in /.extra/ in the initrd, then it was placed there by systemd-stub, and was
|
||||
* picked up from an untrusted ESP. Thus, require a stricter policy by default for them. (For the
|
||||
* other directories we assume the appropriate level of trust was already established already. */
|
||||
* other directories we assume the appropriate level of trust was already established.)
|
||||
* With --root= we default to the regular policy, though. (To change that, the check would need
|
||||
* to prepend (or cut away) arg_root.) */
|
||||
|
||||
if (in_initrd()) {
|
||||
if (in_initrd() && !arg_root) {
|
||||
if (path_startswith(img->path, "/.extra/sysext/"))
|
||||
return &image_policy_sysext_strict;
|
||||
if (path_startswith(img->path, "/.extra/global_sysext/"))
|
||||
@@ -1905,13 +1907,19 @@ static int merge_subprocess(
|
||||
if (force)
|
||||
log_debug("Force mode enabled, skipping version validation.");
|
||||
else {
|
||||
bool is_initrd;
|
||||
r = chase_and_access("/etc/initrd-release", arg_root, CHASE_PREFIX_ROOT, F_OK, /* ret_path= */ NULL);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return log_error_errno(r, "Failed to check for /etc/initrd-release: %m");
|
||||
is_initrd = r >= 0;
|
||||
|
||||
r = extension_release_validate(
|
||||
img->name,
|
||||
host_os_release_id,
|
||||
host_os_release_id_like,
|
||||
host_os_release_version_id,
|
||||
host_os_release_api_level,
|
||||
in_initrd() ? "initrd" : "system",
|
||||
is_initrd ? "initrd" : "system",
|
||||
image_extension_release(img, image_class),
|
||||
image_class);
|
||||
if (r < 0)
|
||||
|
||||
@@ -1130,10 +1130,13 @@ extension_verify_after_unmerge "$fake_root" "$hierarchy" -h
|
||||
fake_root=${roots_dir:+"$roots_dir/mutable-directory-with-invalid-permissions"}
|
||||
hierarchy=/opt
|
||||
extension_data_dir="$fake_root/var/lib/extensions.mutable$hierarchy"
|
||||
extension_data_dir_usr="$fake_root/var/lib/extensions.mutable/usr"
|
||||
|
||||
prepare_root "$fake_root" "$hierarchy"
|
||||
prepare_extension_image "$fake_root" "$hierarchy"
|
||||
prepare_extension_mutable_dir "$extension_data_dir"
|
||||
prepend_trap "rm -rf ${extension_data_dir@Q}"
|
||||
prepend_trap "rm -rf ${extension_data_dir_usr@Q}"
|
||||
prepare_hierarchy "$fake_root" "$hierarchy"
|
||||
|
||||
old_mode=$(stat --format '%#a' "$fake_root$hierarchy")
|
||||
@@ -1144,6 +1147,29 @@ chmod 0700 "$extension_data_dir"
|
||||
(! run_systemd_sysext "$fake_root" --mutable=yes merge)
|
||||
)
|
||||
|
||||
( init_trap
|
||||
: "Check if merging fails in case of --root= being an initrd but the extension is not for it"
|
||||
# Since this is really about whether --root= gets prepended for the /etc/initrd-release check,
|
||||
# this also tests the more interesting reverse case that we are in the initrd and prepare
|
||||
# the mounts for the final system with --root=/sysroot
|
||||
fake_root=${roots_dir:+"$roots_dir/initrd-env-with-non-initrd-extension"}
|
||||
hierarchy=/opt
|
||||
|
||||
prepare_root "$fake_root" "$hierarchy"
|
||||
prepare_extension_image "$fake_root" "$hierarchy"
|
||||
mkdir -p "${fake_root}/etc"
|
||||
touch "${fake_root}/etc/initrd-release"
|
||||
prepare_read_only_hierarchy "$fake_root" "$hierarchy"
|
||||
|
||||
# Should be a no-op, thus we also don't run unmerge afterwards (otherwise the test is broken)
|
||||
run_systemd_sysext "$fake_root" merge
|
||||
if run_systemd_sysext "$fake_root" status --json=pretty | jq -r '.[].extensions' | grep -v '^none$' ; then
|
||||
echo >&2 "Extension got loaded for an initrd structure passed as --root= while the extension does not declare itself compatible with the initrd scope"
|
||||
exit 1
|
||||
fi
|
||||
rm "${fake_root}/etc/initrd-release"
|
||||
)
|
||||
|
||||
} # End of run_sysext_tests
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user