core: reload confexts when reloading notify-reload services
`ExtensionImages=` and `ExtensionDirectories=` now let you specify
vpick-named extensions; however, since they just get set up once when
the service is started, you can't see newer versions without restarting
the service entirely. Here, also reload confext extensions when you
reload a service. This allows you to deploy a new version of some
configuration and have it picked up at reload time without interruption
to your workload.
Right now, we would only reload confext extensions and leave the sysext
ones behind, since it didn't seem prudent to swap out what is likely
program code at reload. This is made possible by only going for the
`SYSTEMD_CONFEXT_HIERARCHIES` overlays (which only contains `/etc`).
Implementation wise, this uses the new kernel API and two collaborating
child processes under the host & child namespaces in order to gather the
right FDs needed:
- (1) In child, set up the extension images and directories in a slave
mountns, and obtain their FDs.
- (2) Fork into a grandchild under target process namespace, and do a
"fake" unmount to obtain the FD of the underlying target folder
say /etc).
- (3) In the child again, set up new overlay under host NS rights.
We do not want to do I/O heavy jobs inline in PID1 blocking the state
machine, so add separate async states to handle this case.
Co-authored-by: Luca Boccassi <luca.boccassi@gmail.com>
This commit is contained in:
committed by
Luca Boccassi
co-authored by
Luca Boccassi
parent
ab5cb21e32
commit
dfdeb0b1cb
+22
-15
@@ -4289,6 +4289,7 @@ int verity_dissect_and_mount(
|
||||
const ImagePolicy *image_policy,
|
||||
const ImageFilter *image_filter,
|
||||
const ExtensionReleaseData *extension_release_data,
|
||||
ImageClass required_class,
|
||||
VeritySettings *verity,
|
||||
DissectedImage **ret_image) {
|
||||
|
||||
@@ -4400,15 +4401,19 @@ int verity_dissect_and_mount(
|
||||
* extension-release.d/ content. Return -EINVAL if there's any mismatch.
|
||||
* First, check the distro ID. If that matches, then check the new SYSEXT_LEVEL value if
|
||||
* available, or else fallback to VERSION_ID. If neither is present (eg: rolling release),
|
||||
* then a simple match on the ID will be performed. */
|
||||
if (extension_release_data && extension_release_data->os_release_id) {
|
||||
* then a simple match on the ID will be performed. Also if an extension class was specified,
|
||||
* check that it matches or return ENOCSI (which looks like error-no-class if one squints enough). */
|
||||
if ((extension_release_data && extension_release_data->os_release_id) || required_class >= 0) {
|
||||
_cleanup_strv_free_ char **extension_release = NULL;
|
||||
ImageClass class = IMAGE_SYSEXT;
|
||||
|
||||
assert(!isempty(extension_release_data->os_release_id));
|
||||
|
||||
r = load_extension_release_pairs(dest, IMAGE_SYSEXT, dissected_image->image_name, relax_extension_release_check, &extension_release);
|
||||
r = load_extension_release_pairs(dest, required_class >= 0 ? required_class : IMAGE_SYSEXT, dissected_image->image_name, relax_extension_release_check, &extension_release);
|
||||
if (r == -ENOENT) {
|
||||
if (required_class >= 0)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENOCSI), "Image %s extension-release metadata does not match the expected class", dissected_image->image_name);
|
||||
|
||||
r = load_extension_release_pairs(dest, IMAGE_CONFEXT, dissected_image->image_name, relax_extension_release_check, &extension_release);
|
||||
if (r >= 0)
|
||||
class = IMAGE_CONFEXT;
|
||||
@@ -4416,18 +4421,20 @@ int verity_dissect_and_mount(
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to parse image %s extension-release metadata: %m", dissected_image->image_name);
|
||||
|
||||
r = extension_release_validate(
|
||||
dissected_image->image_name,
|
||||
extension_release_data->os_release_id,
|
||||
extension_release_data->os_release_version_id,
|
||||
class == IMAGE_SYSEXT ? extension_release_data->os_release_sysext_level : extension_release_data->os_release_confext_level,
|
||||
extension_release_data->os_release_extension_scope,
|
||||
extension_release,
|
||||
class);
|
||||
if (r == 0)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "Image %s extension-release metadata does not match the root's", dissected_image->image_name);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to compare image %s extension-release metadata with the root's os-release: %m", dissected_image->image_name);
|
||||
if (extension_release_data && !isempty(extension_release_data->os_release_id)) {
|
||||
r = extension_release_validate(
|
||||
dissected_image->image_name,
|
||||
extension_release_data->os_release_id,
|
||||
extension_release_data->os_release_version_id,
|
||||
class == IMAGE_SYSEXT ? extension_release_data->os_release_sysext_level : extension_release_data->os_release_confext_level,
|
||||
extension_release_data->os_release_extension_scope,
|
||||
extension_release,
|
||||
class);
|
||||
if (r == 0)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ESTALE), "Image %s extension-release metadata does not match the root's", dissected_image->image_name);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to compare image %s extension-release metadata with the root's os-release: %m", dissected_image->image_name);
|
||||
}
|
||||
}
|
||||
|
||||
r = dissected_image_relinquish(dissected_image);
|
||||
|
||||
@@ -255,7 +255,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 ImageFilter *image_filter, const ExtensionReleaseData *required_release_data, 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 ImageFilter *image_filter, const ExtensionReleaseData *required_release_data, ImageClass required_class, VeritySettings *verity, DissectedImage **ret_image);
|
||||
|
||||
int dissect_fstype_ok(const char *fstype);
|
||||
|
||||
|
||||
@@ -972,6 +972,7 @@ static int mount_in_namespace_legacy(
|
||||
image_policy,
|
||||
/* image_filter= */ NULL,
|
||||
/* extension_release_data= */ NULL,
|
||||
/* required_class= */ _IMAGE_CLASS_INVALID,
|
||||
/* verity= */ NULL,
|
||||
/* ret_image= */ NULL);
|
||||
else
|
||||
@@ -1193,6 +1194,7 @@ static int mount_in_namespace(
|
||||
image_policy,
|
||||
/* image_filter= */ NULL,
|
||||
/* extension_release_data= */ NULL,
|
||||
/* required_class= */ _IMAGE_CLASS_INVALID,
|
||||
/* verity= */ NULL,
|
||||
&img);
|
||||
if (r < 0)
|
||||
|
||||
Reference in New Issue
Block a user