1
0
mirror of https://github.com/systemd/systemd synced 2025-10-08 13:14:45 +02:00

Compare commits

..

No commits in common. "04b3529cf1dac9ced0358dddea802f7622dcad95" and "162e5e4a77931e4a7a7c9b6f86f09a70ec52a3e5" have entirely different histories.

10 changed files with 15 additions and 111 deletions

View File

@ -108,9 +108,8 @@
follows the syntax and rules as described in the <ulink
url="https://systemd.io/PORTABLE_SERVICES">Portable Services</ulink> page. The purpose of this
file is to identify the extension and to allow the operating system to verify that the extension image
matches the base OS. This is typically implemented by checking that the extension <varname>ID=</varname>
option either matches the host <varname>ID=</varname> option or is included the host <varname>ID_LIKE=</varname>
option, and either <varname>SYSEXT_LEVEL=</varname> exists and matches too, or if it is not present,
matches the base OS. This is typically implemented by checking that the <varname>ID=</varname> options
match, and either <varname>SYSEXT_LEVEL=</varname> exists and matches too, or if it is not present,
<varname>VERSION_ID=</varname> exists and matches. This ensures ABI/API compatibility between the
layers and prevents merging of an incompatible image in an overlay.</para>

View File

@ -1516,7 +1516,7 @@ static int mount_image(
const char *root_directory,
const ImagePolicy *image_policy) {
_cleanup_free_ char *host_os_release_id = NULL, *host_os_release_id_like = NULL, *host_os_release_version_id = NULL,
_cleanup_free_ char *host_os_release_id = NULL, *host_os_release_version_id = NULL,
*host_os_release_sysext_level = NULL, *host_os_release_confext_level = NULL,
*extension_name = NULL;
int r;
@ -1531,7 +1531,6 @@ static int mount_image(
r = parse_os_release(
empty_to_root(root_directory),
"ID", &host_os_release_id,
"ID_LIKE", &host_os_release_id_like,
"VERSION_ID", &host_os_release_version_id,
image_class_info[IMAGE_SYSEXT].level_env, &host_os_release_sysext_level,
image_class_info[IMAGE_CONFEXT].level_env, &host_os_release_confext_level,
@ -1543,13 +1542,12 @@ static int mount_image(
}
r = verity_dissect_and_mount(
/* src_fd= */ -EBADF,
/* src_fd= */ -1,
mount_entry_source(m),
mount_entry_path(m),
m->image_options_const,
image_policy,
host_os_release_id,
host_os_release_id_like,
host_os_release_version_id,
host_os_release_sysext_level,
host_os_release_confext_level,
@ -1560,10 +1558,9 @@ static int mount_image(
return 0;
if (r == -ESTALE && host_os_release_id)
return log_error_errno(r, // FIXME: this should not be logged ad LOG_ERR, as it will result in duplicate logging.
"Failed to mount image %s, extension-release metadata does not match the lower layer's: ID=%s ID_LIKE='%s'%s%s%s%s%s%s",
"Failed to mount image %s, extension-release metadata does not match the lower layer's: ID=%s%s%s%s%s%s%s",
mount_entry_source(m),
host_os_release_id,
strempty(host_os_release_id_like),
host_os_release_version_id ? " VERSION_ID=" : "",
strempty(host_os_release_version_id),
host_os_release_sysext_level ? image_class_info[IMAGE_SYSEXT].level_env_print : "",
@ -1738,9 +1735,8 @@ static int apply_one_mount(
break;
case MOUNT_EXTENSION_DIRECTORY: {
_cleanup_free_ char *host_os_release_id = NULL, *host_os_release_id_like = NULL,
*host_os_release_version_id = NULL, *host_os_release_level = NULL,
*extension_name = NULL;
_cleanup_free_ char *host_os_release_id = NULL, *host_os_release_version_id = NULL,
*host_os_release_level = NULL, *extension_name = NULL;
_cleanup_strv_free_ char **extension_release = NULL;
ImageClass class = IMAGE_SYSEXT;
@ -1772,7 +1768,6 @@ static int apply_one_mount(
r = parse_os_release(
empty_to_root(root_directory),
"ID", &host_os_release_id,
"ID_LIKE", &host_os_release_id_like,
"VERSION_ID", &host_os_release_version_id,
image_class_info[class].level_env, &host_os_release_level,
NULL);
@ -1784,7 +1779,6 @@ static int apply_one_mount(
r = extension_release_validate(
extension_name,
host_os_release_id,
host_os_release_id_like,
host_os_release_version_id,
host_os_release_level,
/* host_extension_scope = */ NULL, /* Leave empty, we need to accept both system and portable */

View File

@ -563,7 +563,7 @@ static int extract_image_and_extensions(
char ***ret_valid_prefixes,
sd_bus_error *error) {
_cleanup_free_ char *id = NULL, *id_like = NULL, *version_id = NULL, *sysext_level = NULL, *confext_level = NULL;
_cleanup_free_ char *id = NULL, *version_id = NULL, *sysext_level = NULL, *confext_level = NULL;
_cleanup_(portable_metadata_unrefp) PortableMetadata *os_release = NULL;
_cleanup_ordered_hashmap_free_ OrderedHashmap *extension_images = NULL, *extension_releases = NULL;
_cleanup_(pick_result_done) PickResult result = PICK_RESULT_NULL;
@ -664,7 +664,6 @@ static int extract_image_and_extensions(
r = parse_env_file_fd(os_release->fd, os_release->name,
"ID", &id,
"ID_LIKE", &id_like,
"VERSION_ID", &version_id,
"SYSEXT_LEVEL", &sysext_level,
"CONFEXT_LEVEL", &confext_level,
@ -711,9 +710,9 @@ static int extract_image_and_extensions(
return r;
if (validate_extension) {
r = extension_release_validate(ext->path, id, id_like, version_id, sysext_level, "portable", extension_release, IMAGE_SYSEXT);
r = extension_release_validate(ext->path, id, version_id, sysext_level, "portable", extension_release, IMAGE_SYSEXT);
if (r < 0)
r = extension_release_validate(ext->path, id, id_like, version_id, confext_level, "portable", extension_release, IMAGE_CONFEXT);
r = extension_release_validate(ext->path, id, version_id, confext_level, "portable", extension_release, IMAGE_CONFEXT);
if (r == 0)
return sd_bus_error_set_errnof(error, ESTALE, "Image %s extension-release metadata does not match the root's", ext->path);

View File

@ -4030,7 +4030,6 @@ int verity_dissect_and_mount(
const MountOptions *options,
const ImagePolicy *image_policy,
const char *required_host_os_release_id,
const char *required_host_os_release_id_like,
const char *required_host_os_release_version_id,
const char *required_host_os_release_sysext_level,
const char *required_host_os_release_confext_level,
@ -4159,7 +4158,6 @@ int verity_dissect_and_mount(
r = extension_release_validate(
dissected_image->image_name,
required_host_os_release_id,
required_host_os_release_id_like,
required_host_os_release_version_id,
class == IMAGE_SYSEXT ? required_host_os_release_sysext_level : required_host_os_release_confext_level,
required_sysext_scope,

View File

@ -226,7 +226,7 @@ bool dissected_image_verity_sig_ready(const DissectedImage *image, PartitionDesi
int mount_image_privately_interactively(const char *path, const ImagePolicy *image_policy, DissectImageFlags flags, char **ret_directory, int *ret_dir_fd, LoopDevice **ret_loop_device);
int verity_dissect_and_mount(int src_fd, const char *src, const char *dest, const MountOptions *options, const ImagePolicy *image_policy, const char *required_host_os_release_id, const char *required_host_os_release_id_like, const char *required_host_os_release_version_id, const char *required_host_os_release_sysext_level, const char *required_host_os_release_confext_level, const char *required_sysext_scope, VeritySettings *verity, DissectedImage **ret_image);
int verity_dissect_and_mount(int src_fd, const char *src, const char *dest, const MountOptions *options, const ImagePolicy *image_policy, const char *required_host_os_release_id, const char *required_host_os_release_version_id, const char *required_host_os_release_sysext_level, const char *required_host_os_release_confext_level, const char *required_sysext_scope, VeritySettings *verity, DissectedImage **ret_image);
int dissect_fstype_ok(const char *fstype);

View File

@ -12,7 +12,6 @@
int extension_release_validate(
const char *name,
const char *host_os_release_id,
const char *host_os_release_id_like,
const char *host_os_release_version_id,
const char *host_os_extension_release_level,
const char *host_extension_scope,
@ -22,7 +21,6 @@ int extension_release_validate(
const char *extension_release_id = NULL, *extension_release_level = NULL, *extension_architecture = NULL;
const char *extension_level = image_class == IMAGE_CONFEXT ? "CONFEXT_LEVEL" : "SYSEXT_LEVEL";
const char *extension_scope = image_class == IMAGE_CONFEXT ? "CONFEXT_SCOPE" : "SYSEXT_SCOPE";
_cleanup_strv_free_ char **id_like_l = NULL;
assert(name);
assert(!isempty(host_os_release_id));
@ -79,19 +77,9 @@ int extension_release_validate(
return 1;
}
/* Match extension OS ID against host OS ID or ID_LIKE */
if (host_os_release_id_like) {
id_like_l = strv_split(host_os_release_id_like, WHITESPACE);
if (!id_like_l)
return log_oom();
}
if (!streq(host_os_release_id, extension_release_id) && !strv_contains(id_like_l, extension_release_id)) {
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'%s%s%s.",
name, extension_release_id, host_os_release_id,
host_os_release_id_like ? " (like '" : "",
strempty(host_os_release_id_like),
host_os_release_id_like ? "')" : "");
if (!streq(host_os_release_id, extension_release_id)) {
log_debug("Extension '%s' is for OS '%s', but deployed on top of '%s'.",
name, extension_release_id, host_os_release_id);
return 0;
}

View File

@ -9,7 +9,6 @@
int extension_release_validate(
const char *name,
const char *host_os_release_id,
const char *host_os_release_id_like,
const char *host_os_release_version_id,
const char *host_os_extension_release_level,
const char *host_extension_scope,

View File

@ -929,7 +929,6 @@ static int mount_in_namespace_legacy(
options,
image_policy,
/* required_host_os_release_id= */ NULL,
/* required_host_os_release_id_like= */ NULL,
/* required_host_os_release_version_id= */ NULL,
/* required_host_os_release_sysext_level= */ NULL,
/* required_host_os_release_confext_level= */ NULL,
@ -1141,7 +1140,6 @@ static int mount_in_namespace(
options,
image_policy,
/* required_host_os_release_id= */ NULL,
/* required_host_os_release_id_like= */ NULL,
/* required_host_os_release_version_id= */ NULL,
/* required_host_os_release_sysext_level= */ NULL,
/* required_host_os_release_confext_level= */ NULL,

View File

@ -1638,9 +1638,7 @@ static int merge_subprocess(
Hashmap *images,
const char *workspace) {
_cleanup_free_ char *host_os_release_id = NULL, *host_os_release_id_like = NULL,
*host_os_release_version_id = NULL, *host_os_release_api_level = NULL,
*buf = NULL, *filename = NULL;
_cleanup_free_ char *host_os_release_id = NULL, *host_os_release_version_id = NULL, *host_os_release_api_level = NULL, *buf = NULL, *filename = NULL;
_cleanup_strv_free_ char **extensions = NULL, **extensions_v = NULL, **paths = NULL;
size_t n_extensions = 0;
unsigned n_ignored = 0;
@ -1672,7 +1670,6 @@ static int merge_subprocess(
r = parse_os_release(
arg_root,
"ID", &host_os_release_id,
"ID_LIKE", &host_os_release_id_like,
"VERSION_ID", &host_os_release_version_id,
image_class_info[image_class].level_env, &host_os_release_api_level);
if (r < 0)
@ -1807,7 +1804,6 @@ static int merge_subprocess(
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",

View File

@ -85,7 +85,6 @@ prepare_root() {
{
echo "ID=testtest"
echo "ID_LIKE=\"foobar test_alike something-else\""
echo "VERSION=1.2.3"
} >"$root/usr/lib/os-release"
@ -121,38 +120,6 @@ prepare_extension_image() {
prepend_trap "rm -rf ${ext_dir@Q}"
}
prepare_extension_image_with_matching_id() {
local root=${1:-}
local hierarchy=${2:?}
local ext_dir ext_release name
name="test-extension-matching-id"
ext_dir="$root/var/lib/extensions/$name"
ext_release="$ext_dir/usr/lib/extension-release.d/extension-release.$name"
mkdir -p "${ext_release%/*}"
echo "ID=testtest" >"$ext_release"
mkdir -p "$ext_dir/$hierarchy"
touch "$ext_dir$hierarchy/preexisting-file-in-extension-image"
prepend_trap "rm -rf ${ext_dir@Q}"
}
prepare_extension_image_with_matching_id_like() {
local root=${1:-}
local hierarchy=${2:?}
local ext_dir ext_release name
name="test-extension-matching-id-like"
ext_dir="$root/var/lib/extensions/$name"
ext_release="$ext_dir/usr/lib/extension-release.d/extension-release.$name"
mkdir -p "${ext_release%/*}"
echo "ID=test_alike" >"$ext_release"
mkdir -p "$ext_dir/$hierarchy"
touch "$ext_dir$hierarchy/preexisting-file-in-extension-image"
prepend_trap "rm -rf ${ext_dir@Q}"
}
prepare_extension_mutable_dir() {
local dir=${1:?}
@ -1014,40 +981,6 @@ for mutable_mode in no yes ephemeral; do
done
( init_trap
: "Check if merging an extension with matching ID succeeds"
fake_root=${roots_dir:+"$roots_dir/matching-id"}
hierarchy=/opt
prepare_root "$fake_root" "$hierarchy"
prepare_extension_image_with_matching_id "$fake_root" "$hierarchy"
prepare_read_only_hierarchy "$fake_root" "$hierarchy"
run_systemd_sysext "$fake_root" merge
extension_verify_after_merge "$fake_root" "$hierarchy" -e -h
run_systemd_sysext "$fake_root" unmerge
extension_verify_after_unmerge "$fake_root" "$hierarchy" -h
)
( init_trap
: "Check if merging an extension that matches host ID_LIKE succeeds"
fake_root=${roots_dir:+"$roots_dir/matching-id-like"}
hierarchy=/opt
prepare_root "$fake_root" "$hierarchy"
prepare_extension_image_with_matching_id_like "$fake_root" "$hierarchy"
prepare_read_only_hierarchy "$fake_root" "$hierarchy"
run_systemd_sysext "$fake_root" merge
extension_verify_after_merge "$fake_root" "$hierarchy" -e -h
run_systemd_sysext "$fake_root" unmerge
extension_verify_after_unmerge "$fake_root" "$hierarchy" -h
)
( init_trap
: "Check if merging fails in case of invalid mutable directory permissions"