portable: fail attach/reattach if the profile does not exist
Before this commit, if you attach a portable service using a profile that doesn't exist, it just doesn't add the profile dropin and no warning nor anything is shown: $ portablectl attach -p nonexistent xxx (Matching unit files with prefix 'xxx'.) Created directory /etc/systemd/system.attached. Created directory /etc/systemd/system.attached/xxx-capsule.service.d. Written /etc/systemd/system.attached/xxx-capsule.service.d/20-portable.conf. Copied /etc/systemd/system.attached/xxx-capsule.service. Created symlink /etc/portables/xxx.raw → /var/lib/portables/xxx.raw. $ ls /etc/systemd/system.attached/xxx-capsule.service.d/ 20-portable.conf The 10-profile.conf is not added. If no profile is attached, the /run bind mount is not added and then lot of things inside fail in ways that don't make sense. This patch just makes portable_attach() and reattach check the profile exists. If it doesn't exist, it shows this error now: # portablectl -p doesntexists reattach xxx (Matching unit files with prefix 'xxx'.) ReattachImage failed: Profile 'doesntexists' does not exist, refusing. (Available profiles are: default, nonetwork, strict, trusted) In reattach we do it early, before detach, so we don't detach and then fail to attach it and leave the service detached. An empty profile name is rejected too by the call to filename_is_valid(). portablectl already rejects empty profile names. Please note that we don't change install_profile_dropin(), as that skips non-existing profiles because that is done at the unit type level and it's okay if it doesn't exist for some unit types. For example, /usr/lib/systemd/portable/profile/trusted/ ships a service.conf, but not timer.conf, socket.conf, etc. (cherry picked from commit 5642eb3d848300f7225dff25fdd82940e55101c9)
This commit is contained in:
committed by
Luca Boccassi
parent
2832b3f2c9
commit
92d54a0d3d
+2
-1
@@ -320,7 +320,8 @@
|
||||
<term><option>--profile=<replaceable>PROFILE</replaceable></option></term>
|
||||
|
||||
<listitem><para>When attaching an image, select the profile to use. By default, the <literal>default</literal>
|
||||
profile is used. For details about profiles, see below.</para>
|
||||
profile is used. Attaching fails if the selected profile does not exist. For details about profiles, see
|
||||
below.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v239"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "nsresource.h"
|
||||
#include "os-util.h"
|
||||
#include "path-lookup.h"
|
||||
#include "path-util.h"
|
||||
#include "pidref.h"
|
||||
#include "portable.h"
|
||||
#include "portable-util.h"
|
||||
@@ -2055,6 +2056,10 @@ int portable_attach(
|
||||
|
||||
assert(scope < _RUNTIME_SCOPE_MAX);
|
||||
|
||||
r = portable_profile_validate(scope, profile, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = extract_image_and_extensions(
|
||||
scope,
|
||||
name_or_path,
|
||||
@@ -2660,6 +2665,36 @@ int portable_get_profiles(RuntimeScope scope, char ***ret) {
|
||||
return conf_files_list_strv(ret, NULL, NULL, CONF_FILES_DIRECTORY|CONF_FILES_BASENAME|CONF_FILES_FILTER_MASKED, (const char* const*) dirs);
|
||||
}
|
||||
|
||||
int portable_profile_validate(RuntimeScope scope, const char *profile, sd_bus_error *reterr_error) {
|
||||
_cleanup_strv_free_ char **profiles = NULL;
|
||||
int r;
|
||||
|
||||
assert(scope < _RUNTIME_SCOPE_MAX);
|
||||
|
||||
if (!filename_is_valid(profile))
|
||||
return sd_bus_error_setf(reterr_error, SD_BUS_ERROR_INVALID_ARGS, "Profile name '%s' is not valid.", profile);
|
||||
|
||||
r = portable_get_profiles(scope, &profiles);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(reterr_error, r, "Failed to enumerate portable profiles: %m");
|
||||
|
||||
if (strv_contains(profiles, profile))
|
||||
return 0;
|
||||
|
||||
_cleanup_free_ char *joined = strv_join(profiles, ", ");
|
||||
if (!joined)
|
||||
return -ENOMEM;
|
||||
|
||||
return sd_bus_error_setf(
|
||||
reterr_error,
|
||||
SD_BUS_ERROR_INVALID_ARGS,
|
||||
"Profile '%s' does not exist, refusing.%s%s%s",
|
||||
profile,
|
||||
isempty(joined) ? "" : " (Available profiles are: ",
|
||||
strempty(joined),
|
||||
isempty(joined) ? "" : ")");
|
||||
}
|
||||
|
||||
static const char* const portable_change_type_table[_PORTABLE_CHANGE_TYPE_MAX] = {
|
||||
[PORTABLE_COPY] = "copy",
|
||||
[PORTABLE_MKDIR] = "mkdir",
|
||||
|
||||
@@ -111,6 +111,7 @@ int portable_get_state(
|
||||
sd_bus_error *error);
|
||||
|
||||
int portable_get_profiles(RuntimeScope scope, char ***ret);
|
||||
int portable_profile_validate(RuntimeScope scope, const char *profile, sd_bus_error *reterr_error);
|
||||
|
||||
void portable_changes_free(PortableChange *array, size_t n);
|
||||
|
||||
|
||||
@@ -714,6 +714,11 @@ int bus_image_common_reattach(
|
||||
if (r == 0) /* Will call us back */
|
||||
return 1;
|
||||
|
||||
/* portable_attach() checks this too, but by then the image is detached already. */
|
||||
r = portable_profile_validate(m->runtime_scope, profile, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = portable_detach(
|
||||
m->runtime_scope,
|
||||
sd_bus_message_get_bus(message),
|
||||
|
||||
Reference in New Issue
Block a user