]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pid1: add DBUS method to mount image inside a running service namespace
authorLuca Boccassi <luca.boccassi@microsoft.com>
Thu, 21 Jan 2021 18:36:33 +0000 (18:36 +0000)
committerLuca Boccassi <luca.boccassi@microsoft.com>
Thu, 21 Jan 2021 18:37:00 +0000 (18:37 +0000)
Follow the same pattern as the BindMount method.

man/org.freedesktop.systemd1.xml
src/core/dbus-manager.c
src/core/dbus-service.c
src/core/dbus-service.h
src/core/org.freedesktop.systemd1.conf

index 90d0d664147af798eab66aa454ec53e07c3cc1c2..c4e1d1f94acc3a3d0c75f401d83072c7f37a9dde 100644 (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>
index 4b88f0d9f0786d2905555f8583cc3f8d7a64ddaf..eeb74353da5a9057211f6a3251f83858883a7d78 100644 (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),
index 6df93e44a43b7a8ee47d39e4778d5812e09dcb3f..f7cdb51eba883c83b8472173dc01342f47326788 100644 (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),
index 5b7b7b757be6b3ed4c19dd8ba5641b59282c1a17..9a054658025b9d5d3368530d68ca5e8fa882c1fd 100644 (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);
index 0cea4d2b02419b6378115d9819804c2d5643fb4f..f405b276589a9cd3d8acc0f8699415e7e2dc5f73 100644 (file)
                        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"/>
                        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"