1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-09 01:18:19 +03:00

pid1: add DBUS method to mount image inside a running service namespace

Follow the same pattern as the BindMount method.
This commit is contained in:
Luca Boccassi 2021-01-21 18:36:33 +00:00
parent 7059996766
commit af47713952
5 changed files with 90 additions and 15 deletions

View File

@ -121,6 +121,12 @@ node /org/freedesktop/systemd1 {
in s destination,
in b read_only,
in b mkdir);
MountImageUnit(in s name,
in s source,
in s destination,
in b read_only,
in b mkdir,
in a(ss) options);
RefUnit(in s name);
UnrefUnit(in s name);
StartTransientUnit(in s name,
@ -774,6 +780,8 @@ node /org/freedesktop/systemd1 {
<variablelist class="dbus-method" generated="True" extra-ref="BindMountUnit()"/>
<variablelist class="dbus-method" generated="True" extra-ref="MountImageUnit()"/>
<variablelist class="dbus-method" generated="True" extra-ref="RefUnit()"/>
<variablelist class="dbus-method" generated="True" extra-ref="UnrefUnit()"/>
@ -1166,6 +1174,9 @@ node /org/freedesktop/systemd1 {
<para><function>BindMountUnit()</function> can be used to bind mount new files or directories into
a running service mount namespace.</para>
<para><function>MountImageUnit()</function> can be used to mount new images into a running service
mount namespace.</para>
<para><function>KillUnit()</function> may be used to kill (i.e. send a signal to) all processes of a
unit. It takes the unit <varname>name</varname>, an enum <varname>who</varname> and a UNIX
<varname>signal</varname> number to send. The <varname>who</varname> enum is one of
@ -2207,6 +2218,11 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
in s destination,
in b read_only,
in b mkdir);
MountImage(in s source,
in s destination,
in b read_only,
in b mkdir,
in a(ss) options);
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
@ -3268,6 +3284,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-method" generated="True" extra-ref="BindMount()"/>
<variablelist class="dbus-method" generated="True" extra-ref="MountImage()"/>
<variablelist class="dbus-method" generated="True" extra-ref="GetProcesses()"/>
<variablelist class="dbus-method" generated="True" extra-ref="AttachProcesses()"/>
@ -3829,12 +3847,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<refsect2>
<title>Methods</title>
<para><function>BindMount()</function> implements the same operation as the respective method on the
<interfacename>Manager</interfacename> object (see above). However, this method operates on the service
object and hence does not take a unit name parameter. Invoking the methods directly on the Manager
object has the advantage of not requiring a <function>GetUnit()</function> call to get the unit object
for a specific unit name. Calling the methods on the Manager object is hence a round trip
optimization.</para>
<para><function>BindMount()</function> and <function>MountImage()</function> implement the same operations
as the respective methods on the <interfacename>Manager</interfacename> object (see above). However, these
methods operate on the service object and hence do not take a unit name parameter. Invoking the methods
directly on the Manager object has the advantage of not requiring a <function>GetUnit()</function> call
to get the unit object for a specific unit name. Calling the methods on the Manager object is hence a round
trip optimization.</para>
</refsect2>
<refsect2>

View File

@ -731,6 +731,11 @@ static int method_bind_mount_unit(sd_bus_message *message, void *userdata, sd_bu
return method_generic_unit_operation(message, userdata, error, bus_service_method_bind_mount, GENERIC_UNIT_VALIDATE_LOADED);
}
static int method_mount_image_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
/* Only add mounts on fully loaded units */
return method_generic_unit_operation(message, userdata, error, bus_service_method_mount_image, GENERIC_UNIT_VALIDATE_LOADED);
}
static int method_ref_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
/* Only allow reffing of fully loaded units, and make sure reffing a unit loads it. */
return method_generic_unit_operation(message, userdata, error, bus_unit_method_ref, GENERIC_UNIT_LOAD|GENERIC_UNIT_VALIDATE_LOADED);
@ -2776,6 +2781,17 @@ const sd_bus_vtable bus_manager_vtable[] = {
NULL,,
method_bind_mount_unit,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("MountImageUnit",
"sssbba(ss)",
SD_BUS_PARAM(name)
SD_BUS_PARAM(source)
SD_BUS_PARAM(destination)
SD_BUS_PARAM(read_only)
SD_BUS_PARAM(mkdir)
SD_BUS_PARAM(options),
NULL,,
method_mount_image_unit,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("RefUnit",
"s",
SD_BUS_PARAM(name),

View File

@ -95,9 +95,10 @@ static int property_get_exit_status_set(
return sd_bus_message_close_container(reply);
}
int bus_service_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error) {
int read_only, make_file_or_directory;
static int bus_service_method_mount(sd_bus_message *message, void *userdata, sd_bus_error *error, bool is_image) {
_cleanup_(mount_options_free_allp) MountOptions *options = NULL;
const char *dest, *src, *propagate_directory;
int read_only, make_file_or_directory;
Unit *u = userdata;
ExecContext *c;
pid_t unit_pid;
@ -120,16 +121,22 @@ int bus_service_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
if (!path_is_absolute(src) || !path_is_normalized(src))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and normalized.");
if (isempty(dest))
if (!is_image && isempty(dest))
dest = src;
else if (!path_is_absolute(dest) || !path_is_normalized(dest))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and normalized.");
if (is_image) {
r = bus_read_mount_options(message, error, &options, NULL, "");
if (r < 0)
return r;
}
r = bus_verify_manage_units_async_full(
u,
"bind-mount",
is_image ? "mount-image" : "bind-mount",
CAP_SYS_ADMIN,
N_("Authentication is required to bind mount on '$(unit)'."),
N_("Authentication is required to mount on '$(unit)'."),
true,
message,
error);
@ -158,16 +165,30 @@ int bus_service_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unit is not running");
propagate_directory = strjoina("/run/systemd/propagate/", u->id);
r = bind_mount_in_namespace(unit_pid,
propagate_directory,
"/run/systemd/incoming/",
src, dest, read_only, make_file_or_directory);
if (is_image)
r = mount_image_in_namespace(unit_pid,
propagate_directory,
"/run/systemd/incoming/",
src, dest, read_only, make_file_or_directory, options);
else
r = bind_mount_in_namespace(unit_pid,
propagate_directory,
"/run/systemd/incoming/",
src, dest, read_only, make_file_or_directory);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to mount %s on %s in unit's namespace: %m", src, dest);
return sd_bus_reply_method_return(message, NULL);
}
int bus_service_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return bus_service_method_mount(message, userdata, error, false);
}
int bus_service_method_mount_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
return bus_service_method_mount(message, userdata, error, true);
}
const sd_bus_vtable bus_service_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
@ -233,6 +254,17 @@ const sd_bus_vtable bus_service_vtable[] = {
bus_service_method_bind_mount,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_NAMES("MountImage",
"ssbba(ss)",
SD_BUS_PARAM(source)
SD_BUS_PARAM(destination)
SD_BUS_PARAM(read_only)
SD_BUS_PARAM(mkdir)
SD_BUS_PARAM(options),
NULL,,
bus_service_method_mount_image,
SD_BUS_VTABLE_UNPRIVILEGED),
/* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */
SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_ratelimit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_ratelimit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),

View File

@ -10,4 +10,5 @@ extern const sd_bus_vtable bus_service_vtable[];
int bus_service_set_property(Unit *u, const char *name, sd_bus_message *i, UnitWriteFlags flags, sd_bus_error *error);
int bus_service_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_service_method_mount_image(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_service_commit_properties(Unit *u);

View File

@ -226,6 +226,10 @@
send_interface="org.freedesktop.systemd1.Manager"
send_member="BindMountUnit"/>
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager"
send_member="MountImageUnit"/>
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager"
send_member="KillUnit"/>
@ -400,6 +404,10 @@
send_interface="org.freedesktop.systemd1.Service"
send_member="BindMount"/>
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Service"
send_member="MountImage"/>
<!-- Managed via polkit or other criteria: org.freedesktop.systemd1.Scope interface -->
<allow send_destination="org.freedesktop.systemd1"