LCOV - code coverage report
Current view: top level - nspawn - nspawn-register.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 162 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 6 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include "sd-bus.h"
       4             : 
       5             : #include "bus-error.h"
       6             : #include "bus-unit-util.h"
       7             : #include "bus-util.h"
       8             : #include "bus-wait-for-jobs.h"
       9             : #include "nspawn-register.h"
      10             : #include "special.h"
      11             : #include "stat-util.h"
      12             : #include "strv.h"
      13             : #include "util.h"
      14             : 
      15           0 : static int append_machine_properties(
      16             :                 sd_bus_message *m,
      17             :                 CustomMount *mounts,
      18             :                 unsigned n_mounts,
      19             :                 int kill_signal) {
      20             : 
      21             :         unsigned j;
      22             :         int r;
      23             : 
      24           0 :         assert(m);
      25             : 
      26           0 :         r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed");
      27           0 :         if (r < 0)
      28           0 :                 return bus_log_create_error(r);
      29             : 
      30             :         /* If you make changes here, also make sure to update systemd-nspawn@.service, to keep the device policies in
      31             :          * sync regardless if we are run with or without the --keep-unit switch. */
      32           0 :         r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 2,
      33             :                                   /* Allow the container to
      34             :                                    * access and create the API
      35             :                                    * device nodes, so that
      36             :                                    * PrivateDevices= in the
      37             :                                    * container can work
      38             :                                    * fine */
      39             :                                   "/dev/net/tun", "rwm",
      40             :                                   /* Allow the container
      41             :                                    * access to ptys. However,
      42             :                                    * do not permit the
      43             :                                    * container to ever create
      44             :                                    * these device nodes. */
      45             :                                   "char-pts", "rw");
      46           0 :         if (r < 0)
      47           0 :                 return bus_log_create_error(r);
      48             : 
      49           0 :         for (j = 0; j < n_mounts; j++) {
      50           0 :                 CustomMount *cm = mounts + j;
      51             : 
      52           0 :                 if (cm->type != CUSTOM_MOUNT_BIND)
      53           0 :                         continue;
      54             : 
      55           0 :                 r = is_device_node(cm->source);
      56           0 :                 if (r == -ENOENT) {
      57             :                         /* The bind source might only appear as the image is put together, hence don't complain */
      58           0 :                         log_debug_errno(r, "Bind mount source %s not found, ignoring: %m", cm->source);
      59           0 :                         continue;
      60             :                 }
      61           0 :                 if (r < 0)
      62           0 :                         return log_error_errno(r, "Failed to stat %s: %m", cm->source);
      63             : 
      64           0 :                 if (r) {
      65           0 :                         r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
      66           0 :                                                   cm->source, cm->read_only ? "r" : "rw");
      67           0 :                         if (r < 0)
      68           0 :                                 return log_error_errno(r, "Failed to append message arguments: %m");
      69             :                 }
      70             :         }
      71             : 
      72           0 :         if (kill_signal != 0) {
      73           0 :                 r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
      74           0 :                 if (r < 0)
      75           0 :                         return bus_log_create_error(r);
      76             : 
      77           0 :                 r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
      78           0 :                 if (r < 0)
      79           0 :                         return bus_log_create_error(r);
      80             :         }
      81             : 
      82           0 :         return 0;
      83             : }
      84             : 
      85           0 : static int append_controller_property(sd_bus *bus, sd_bus_message *m) {
      86             :         const char *unique;
      87             :         int r;
      88             : 
      89           0 :         assert(bus);
      90           0 :         assert(m);
      91             : 
      92           0 :         r = sd_bus_get_unique_name(bus, &unique);
      93           0 :         if (r < 0)
      94           0 :                 return log_error_errno(r, "Failed to get unique name: %m");
      95             : 
      96           0 :         r = sd_bus_message_append(m, "(sv)", "Controller", "s", unique);
      97           0 :         if (r < 0)
      98           0 :                 return bus_log_create_error(r);
      99             : 
     100           0 :         return 0;
     101             : }
     102             : 
     103           0 : int register_machine(
     104             :                 sd_bus *bus,
     105             :                 const char *machine_name,
     106             :                 pid_t pid,
     107             :                 const char *directory,
     108             :                 sd_id128_t uuid,
     109             :                 int local_ifindex,
     110             :                 const char *slice,
     111             :                 CustomMount *mounts,
     112             :                 unsigned n_mounts,
     113             :                 int kill_signal,
     114             :                 char **properties,
     115             :                 sd_bus_message *properties_message,
     116             :                 bool keep_unit,
     117             :                 const char *service) {
     118             : 
     119           0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     120             :         int r;
     121             : 
     122           0 :         assert(bus);
     123             : 
     124           0 :         if (keep_unit) {
     125           0 :                 r = sd_bus_call_method(
     126             :                                 bus,
     127             :                                 "org.freedesktop.machine1",
     128             :                                 "/org/freedesktop/machine1",
     129             :                                 "org.freedesktop.machine1.Manager",
     130             :                                 "RegisterMachineWithNetwork",
     131             :                                 &error,
     132             :                                 NULL,
     133             :                                 "sayssusai",
     134             :                                 machine_name,
     135           0 :                                 SD_BUS_MESSAGE_APPEND_ID128(uuid),
     136             :                                 service,
     137             :                                 "container",
     138             :                                 (uint32_t) pid,
     139             :                                 strempty(directory),
     140             :                                 local_ifindex > 0 ? 1 : 0, local_ifindex);
     141             :         } else {
     142           0 :                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
     143             : 
     144           0 :                 r = sd_bus_message_new_method_call(
     145             :                                 bus,
     146             :                                 &m,
     147             :                                 "org.freedesktop.machine1",
     148             :                                 "/org/freedesktop/machine1",
     149             :                                 "org.freedesktop.machine1.Manager",
     150             :                                 "CreateMachineWithNetwork");
     151           0 :                 if (r < 0)
     152           0 :                         return bus_log_create_error(r);
     153             : 
     154           0 :                 r = sd_bus_message_append(
     155             :                                 m,
     156             :                                 "sayssusai",
     157             :                                 machine_name,
     158           0 :                                 SD_BUS_MESSAGE_APPEND_ID128(uuid),
     159             :                                 service,
     160             :                                 "container",
     161             :                                 (uint32_t) pid,
     162             :                                 strempty(directory),
     163             :                                 local_ifindex > 0 ? 1 : 0, local_ifindex);
     164           0 :                 if (r < 0)
     165           0 :                         return bus_log_create_error(r);
     166             : 
     167           0 :                 r = sd_bus_message_open_container(m, 'a', "(sv)");
     168           0 :                 if (r < 0)
     169           0 :                         return bus_log_create_error(r);
     170             : 
     171           0 :                 if (!isempty(slice)) {
     172           0 :                         r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
     173           0 :                         if (r < 0)
     174           0 :                                 return bus_log_create_error(r);
     175             :                 }
     176             : 
     177           0 :                 r = append_controller_property(bus, m);
     178           0 :                 if (r < 0)
     179           0 :                         return r;
     180             : 
     181           0 :                 r = append_machine_properties(
     182             :                                 m,
     183             :                                 mounts,
     184             :                                 n_mounts,
     185             :                                 kill_signal);
     186           0 :                 if (r < 0)
     187           0 :                         return r;
     188             : 
     189           0 :                 if (properties_message) {
     190           0 :                         r = sd_bus_message_copy(m, properties_message, true);
     191           0 :                         if (r < 0)
     192           0 :                                 return bus_log_create_error(r);
     193             :                 }
     194             : 
     195           0 :                 r = bus_append_unit_property_assignment_many(m, UNIT_SERVICE, properties);
     196           0 :                 if (r < 0)
     197           0 :                         return r;
     198             : 
     199           0 :                 r = sd_bus_message_close_container(m);
     200           0 :                 if (r < 0)
     201           0 :                         return bus_log_create_error(r);
     202             : 
     203           0 :                 r = sd_bus_call(bus, m, 0, &error, NULL);
     204             :         }
     205             : 
     206           0 :         if (r < 0)
     207           0 :                 return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
     208             : 
     209           0 :         return 0;
     210             : }
     211             : 
     212           0 : int terminate_machine(
     213             :                 sd_bus *bus,
     214             :                 const char *machine_name) {
     215             : 
     216           0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     217             :         int r;
     218             : 
     219           0 :         assert(bus);
     220             : 
     221           0 :         r = sd_bus_call_method(
     222             :                         bus,
     223             :                         "org.freedesktop.machine1",
     224             :                         "/org/freedesktop/machine1",
     225             :                         "org.freedesktop.machine1.Manager",
     226             :                         "TerminateMachine",
     227             :                         &error,
     228             :                         NULL,
     229             :                         "s",
     230             :                         machine_name);
     231           0 :         if (r < 0)
     232           0 :                 log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
     233             : 
     234           0 :         return 0;
     235             : }
     236             : 
     237           0 : int allocate_scope(
     238             :                 sd_bus *bus,
     239             :                 const char *machine_name,
     240             :                 pid_t pid,
     241             :                 const char *slice,
     242             :                 CustomMount *mounts,
     243             :                 unsigned n_mounts,
     244             :                 int kill_signal,
     245             :                 char **properties,
     246             :                 sd_bus_message *properties_message) {
     247             : 
     248           0 :         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
     249           0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     250           0 :         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
     251           0 :         _cleanup_free_ char *scope = NULL;
     252             :         const char *description, *object;
     253             :         int r;
     254             : 
     255           0 :         assert(bus);
     256             : 
     257           0 :         r = bus_wait_for_jobs_new(bus, &w);
     258           0 :         if (r < 0)
     259           0 :                 return log_error_errno(r, "Could not watch job: %m");
     260             : 
     261           0 :         r = unit_name_mangle_with_suffix(machine_name, 0, ".scope", &scope);
     262           0 :         if (r < 0)
     263           0 :                 return log_error_errno(r, "Failed to mangle scope name: %m");
     264             : 
     265           0 :         r = sd_bus_message_new_method_call(
     266             :                         bus,
     267             :                         &m,
     268             :                         "org.freedesktop.systemd1",
     269             :                         "/org/freedesktop/systemd1",
     270             :                         "org.freedesktop.systemd1.Manager",
     271             :                         "StartTransientUnit");
     272           0 :         if (r < 0)
     273           0 :                 return bus_log_create_error(r);
     274             : 
     275           0 :         r = sd_bus_message_append(m, "ss", scope, "fail");
     276           0 :         if (r < 0)
     277           0 :                 return bus_log_create_error(r);
     278             : 
     279             :         /* Properties */
     280           0 :         r = sd_bus_message_open_container(m, 'a', "(sv)");
     281           0 :         if (r < 0)
     282           0 :                 return bus_log_create_error(r);
     283             : 
     284           0 :         description = strjoina("Container ", machine_name);
     285             : 
     286           0 :         r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)(sv)(sv)",
     287             :                                   "PIDs", "au", 1, pid,
     288             :                                   "Description", "s", description,
     289             :                                   "Delegate", "b", 1,
     290             :                                   "CollectMode", "s", "inactive-or-failed",
     291             :                                   "AddRef", "b", 1,
     292           0 :                                   "Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice);
     293           0 :         if (r < 0)
     294           0 :                 return bus_log_create_error(r);
     295             : 
     296           0 :         r = append_controller_property(bus, m);
     297           0 :         if (r < 0)
     298           0 :                 return r;
     299             : 
     300           0 :         if (properties_message) {
     301           0 :                 r = sd_bus_message_copy(m, properties_message, true);
     302           0 :                 if (r < 0)
     303           0 :                         return bus_log_create_error(r);
     304             :         }
     305             : 
     306           0 :         r = append_machine_properties(
     307             :                         m,
     308             :                         mounts,
     309             :                         n_mounts,
     310             :                         kill_signal);
     311           0 :         if (r < 0)
     312           0 :                 return r;
     313             : 
     314           0 :         r = bus_append_unit_property_assignment_many(m, UNIT_SCOPE, properties);
     315           0 :         if (r < 0)
     316           0 :                 return r;
     317             : 
     318           0 :         r = sd_bus_message_close_container(m);
     319           0 :         if (r < 0)
     320           0 :                 return bus_log_create_error(r);
     321             : 
     322             :         /* No auxiliary units */
     323           0 :         r = sd_bus_message_append(
     324             :                         m,
     325             :                         "a(sa(sv))",
     326             :                         0);
     327           0 :         if (r < 0)
     328           0 :                 return bus_log_create_error(r);
     329             : 
     330           0 :         r = sd_bus_call(bus, m, 0, &error, &reply);
     331           0 :         if (r < 0)
     332           0 :                 return log_error_errno(r, "Failed to allocate scope: %s", bus_error_message(&error, r));
     333             : 
     334           0 :         r = sd_bus_message_read(reply, "o", &object);
     335           0 :         if (r < 0)
     336           0 :                 return bus_log_parse_error(r);
     337             : 
     338           0 :         r = bus_wait_for_jobs_one(w, object, false);
     339           0 :         if (r < 0)
     340           0 :                 return r;
     341             : 
     342           0 :         return 0;
     343             : }
     344             : 
     345           0 : int terminate_scope(
     346             :                 sd_bus *bus,
     347             :                 const char *machine_name) {
     348             : 
     349           0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
     350           0 :         _cleanup_free_ char *scope = NULL;
     351             :         int r;
     352             : 
     353           0 :         r = unit_name_mangle_with_suffix(machine_name, 0, ".scope", &scope);
     354           0 :         if (r < 0)
     355           0 :                 return log_error_errno(r, "Failed to mangle scope name: %m");
     356             : 
     357           0 :         r = sd_bus_call_method(
     358             :                         bus,
     359             :                         "org.freedesktop.systemd1",
     360             :                         "/org/freedesktop/systemd1",
     361             :                         "org.freedesktop.systemd1.Manager",
     362             :                         "AbandonScope",
     363             :                         &error,
     364             :                         NULL,
     365             :                         "s",
     366             :                         scope);
     367           0 :         if (r < 0) {
     368           0 :                 log_debug_errno(r, "Failed to abandon scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
     369           0 :                 sd_bus_error_free(&error);
     370             :         }
     371             : 
     372           0 :         r = sd_bus_call_method(
     373             :                         bus,
     374             :                         "org.freedesktop.systemd1",
     375             :                         "/org/freedesktop/systemd1",
     376             :                         "org.freedesktop.systemd1.Manager",
     377             :                         "KillUnit",
     378             :                         &error,
     379             :                         NULL,
     380             :                         "ssi",
     381             :                         scope,
     382             :                         "all",
     383             :                         (int32_t) SIGKILL);
     384           0 :         if (r < 0) {
     385           0 :                 log_debug_errno(r, "Failed to SIGKILL scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
     386           0 :                 sd_bus_error_free(&error);
     387             :         }
     388             : 
     389           0 :         r = sd_bus_call_method(
     390             :                         bus,
     391             :                         "org.freedesktop.systemd1",
     392             :                         "/org/freedesktop/systemd1",
     393             :                         "org.freedesktop.systemd1.Manager",
     394             :                         "UnrefUnit",
     395             :                         &error,
     396             :                         NULL,
     397             :                         "s",
     398             :                         scope);
     399           0 :         if (r < 0)
     400           0 :                 log_debug_errno(r, "Failed to drop reference to scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
     401             : 
     402           0 :         return 0;
     403             : }

Generated by: LCOV version 1.14