1 /* SPDX-License-Identifier: LGPL-2.1+ */
8 #include "sd-messages.h"
10 #include "alloc-util.h"
11 #include "bus-error.h"
15 #include "extract-word.h"
18 #include "format-util.h"
20 #include "machine-dbus.h"
23 #include "parse-util.h"
24 #include "process-util.h"
25 #include "serialize.h"
27 #include "stdio-util.h"
28 #include "string-table.h"
29 #include "terminal-util.h"
30 #include "tmpfile-util.h"
31 #include "unit-name.h"
32 #include "user-util.h"
35 Machine
* machine_new(Manager
*manager
, MachineClass
class, const char *name
) {
39 assert(class < _MACHINE_CLASS_MAX
);
42 /* Passing class == _MACHINE_CLASS_INVALID here is fine. It
43 * means as much as "we don't know yet", and that we'll figure
44 * it out later when loading the state file. */
50 m
->name
= strdup(name
);
54 if (class != MACHINE_HOST
) {
55 m
->state_file
= strappend("/run/systemd/machines/", m
->name
);
62 if (hashmap_put(manager
->machines
, m
->name
, m
) < 0)
75 void machine_free(Machine
*m
) {
79 operation_free(m
->operations
);
82 LIST_REMOVE(gc_queue
, m
->manager
->machine_gc_queue
, m
);
84 machine_release_unit(m
);
88 (void) hashmap_remove(m
->manager
->machines
, m
->name
);
90 if (m
->manager
->host_machine
== m
)
91 m
->manager
->host_machine
= NULL
;
94 (void) hashmap_remove_value(m
->manager
->machine_leaders
, PID_TO_PTR(m
->leader
), m
);
96 sd_bus_message_unref(m
->create_message
);
101 free(m
->root_directory
);
106 int machine_save(Machine
*m
) {
107 _cleanup_free_
char *temp_path
= NULL
;
108 _cleanup_fclose_
FILE *f
= NULL
;
119 r
= mkdir_safe_label("/run/systemd/machines", 0755, 0, 0, MKDIR_WARN_MODE
);
123 r
= fopen_temporary(m
->state_file
, &f
, &temp_path
);
127 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
128 (void) fchmod(fileno(f
), 0644);
131 "# This is private data. Do not parse.\n"
136 _cleanup_free_
char *escaped
;
138 escaped
= cescape(m
->unit
);
144 fprintf(f
, "SCOPE=%s\n", escaped
); /* We continue to call this "SCOPE=" because it is internal only, and we want to stay compatible with old files */
148 fprintf(f
, "SCOPE_JOB=%s\n", m
->scope_job
);
151 _cleanup_free_
char *escaped
;
153 escaped
= cescape(m
->service
);
158 fprintf(f
, "SERVICE=%s\n", escaped
);
161 if (m
->root_directory
) {
162 _cleanup_free_
char *escaped
;
164 escaped
= cescape(m
->root_directory
);
169 fprintf(f
, "ROOT=%s\n", escaped
);
172 if (!sd_id128_is_null(m
->id
))
173 fprintf(f
, "ID=" SD_ID128_FORMAT_STR
"\n", SD_ID128_FORMAT_VAL(m
->id
));
176 fprintf(f
, "LEADER="PID_FMT
"\n", m
->leader
);
178 if (m
->class != _MACHINE_CLASS_INVALID
)
179 fprintf(f
, "CLASS=%s\n", machine_class_to_string(m
->class));
181 if (dual_timestamp_is_set(&m
->timestamp
))
183 "REALTIME="USEC_FMT
"\n"
184 "MONOTONIC="USEC_FMT
"\n",
185 m
->timestamp
.realtime
,
186 m
->timestamp
.monotonic
);
188 if (m
->n_netif
> 0) {
193 for (i
= 0; i
< m
->n_netif
; i
++) {
197 fprintf(f
, "%i", m
->netif
[i
]);
203 r
= fflush_and_check(f
);
207 if (rename(temp_path
, m
->state_file
) < 0) {
215 /* Create a symlink from the unit name to the machine
216 * name, so that we can quickly find the machine for
217 * each given unit. Ignore error. */
218 sl
= strjoina("/run/systemd/machines/unit:", m
->unit
);
219 (void) symlink(m
->name
, sl
);
225 (void) unlink(m
->state_file
);
228 (void) unlink(temp_path
);
230 return log_error_errno(r
, "Failed to save machine data %s: %m", m
->state_file
);
233 static void machine_unlink(Machine
*m
) {
239 sl
= strjoina("/run/systemd/machines/unit:", m
->unit
);
244 (void) unlink(m
->state_file
);
247 int machine_load(Machine
*m
) {
248 _cleanup_free_
char *realtime
= NULL
, *monotonic
= NULL
, *id
= NULL
, *leader
= NULL
, *class = NULL
, *netif
= NULL
;
256 r
= parse_env_file(NULL
, m
->state_file
,
258 "SCOPE_JOB", &m
->scope_job
,
259 "SERVICE", &m
->service
,
260 "ROOT", &m
->root_directory
,
264 "REALTIME", &realtime
,
265 "MONOTONIC", &monotonic
,
271 return log_error_errno(r
, "Failed to read %s: %m", m
->state_file
);
275 sd_id128_from_string(id
, &m
->id
);
278 parse_pid(leader
, &m
->leader
);
283 c
= machine_class_from_string(class);
289 (void) deserialize_usec(realtime
, &m
->timestamp
.realtime
);
291 (void) deserialize_usec(monotonic
, &m
->timestamp
.monotonic
);
294 size_t allocated
= 0, nr
= 0;
300 _cleanup_free_
char *word
= NULL
;
303 r
= extract_first_word(&p
, &word
, NULL
, 0);
309 log_warning_errno(r
, "Failed to parse NETIF: %s", netif
);
313 if (parse_ifindex(word
, &ifi
) < 0)
316 if (!GREEDY_REALLOC(ni
, allocated
, nr
+1)) {
332 static int machine_start_scope(Machine
*m
, sd_bus_message
*properties
, sd_bus_error
*error
) {
334 assert(m
->class != MACHINE_HOST
);
337 _cleanup_free_
char *escaped
= NULL
, *scope
= NULL
;
338 char *description
, *job
= NULL
;
341 escaped
= unit_name_escape(m
->name
);
345 scope
= strjoin("machine-", escaped
, ".scope");
349 description
= strjoina(m
->class == MACHINE_VM
? "Virtual Machine " : "Container ", m
->name
);
351 r
= manager_start_scope(m
->manager
, scope
, m
->leader
, SPECIAL_MACHINE_SLICE
, description
, properties
, error
, &job
);
353 return log_error_errno(r
, "Failed to start machine scope: %s", bus_error_message(error
, r
));
355 m
->unit
= TAKE_PTR(scope
);
356 free_and_replace(m
->scope_job
, job
);
360 hashmap_put(m
->manager
->machine_units
, m
->unit
, m
);
365 int machine_start(Machine
*m
, sd_bus_message
*properties
, sd_bus_error
*error
) {
370 if (!IN_SET(m
->class, MACHINE_CONTAINER
, MACHINE_VM
))
376 r
= hashmap_put(m
->manager
->machine_leaders
, PID_TO_PTR(m
->leader
), m
);
381 r
= machine_start_scope(m
, properties
, error
);
386 "MESSAGE_ID=" SD_MESSAGE_MACHINE_START_STR
,
388 "LEADER="PID_FMT
, m
->leader
,
389 LOG_MESSAGE("New machine %s.", m
->name
));
391 if (!dual_timestamp_is_set(&m
->timestamp
))
392 dual_timestamp_get(&m
->timestamp
);
396 /* Save new machine data */
399 machine_send_signal(m
, true);
404 static int machine_stop_scope(Machine
*m
) {
405 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
410 assert(m
->class != MACHINE_HOST
);
415 r
= manager_stop_unit(m
->manager
, m
->unit
, &error
, &job
);
417 log_error_errno(r
, "Failed to stop machine scope: %s", bus_error_message(&error
, r
));
418 sd_bus_error_free(&error
);
420 free_and_replace(m
->scope_job
, job
);
422 q
= manager_unref_unit(m
->manager
, m
->unit
, &error
);
424 log_warning_errno(q
, "Failed to drop reference to machine scope, ignoring: %s", bus_error_message(&error
, r
));
429 int machine_stop(Machine
*m
) {
433 if (!IN_SET(m
->class, MACHINE_CONTAINER
, MACHINE_VM
))
436 r
= machine_stop_scope(m
);
445 int machine_finalize(Machine
*m
) {
450 "MESSAGE_ID=" SD_MESSAGE_MACHINE_STOP_STR
,
452 "LEADER="PID_FMT
, m
->leader
,
453 LOG_MESSAGE("Machine %s terminated.", m
->name
));
456 machine_add_to_gc_queue(m
);
459 machine_send_signal(m
, false);
466 bool machine_may_gc(Machine
*m
, bool drop_not_started
) {
469 if (m
->class == MACHINE_HOST
)
472 if (drop_not_started
&& !m
->started
)
475 if (m
->scope_job
&& manager_job_is_active(m
->manager
, m
->scope_job
))
478 if (m
->unit
&& manager_unit_is_active(m
->manager
, m
->unit
))
484 void machine_add_to_gc_queue(Machine
*m
) {
490 LIST_PREPEND(gc_queue
, m
->manager
->machine_gc_queue
, m
);
491 m
->in_gc_queue
= true;
494 MachineState
machine_get_state(Machine
*s
) {
497 if (s
->class == MACHINE_HOST
)
498 return MACHINE_RUNNING
;
501 return MACHINE_CLOSING
;
504 return MACHINE_OPENING
;
506 return MACHINE_RUNNING
;
509 int machine_kill(Machine
*m
, KillWho who
, int signo
) {
512 if (!IN_SET(m
->class, MACHINE_VM
, MACHINE_CONTAINER
))
518 if (who
== KILL_LEADER
) {
519 /* If we shall simply kill the leader, do so directly */
521 if (kill(m
->leader
, signo
) < 0)
527 /* Otherwise, make PID 1 do it for us, for the entire cgroup */
528 return manager_kill_unit(m
->manager
, m
->unit
, signo
, NULL
);
531 int machine_openpt(Machine
*m
, int flags
) {
539 fd
= posix_openpt(flags
);
543 if (unlockpt(fd
) < 0)
549 case MACHINE_CONTAINER
:
553 return openpt_in_namespace(m
->leader
, flags
);
560 int machine_open_terminal(Machine
*m
, const char *path
, int mode
) {
566 return open_terminal(path
, mode
);
568 case MACHINE_CONTAINER
:
572 return open_terminal_in_namespace(m
->leader
, path
, mode
);
579 void machine_release_unit(Machine
*m
) {
585 (void) hashmap_remove(m
->manager
->machine_units
, m
->unit
);
586 m
->unit
= mfree(m
->unit
);
589 int machine_get_uid_shift(Machine
*m
, uid_t
*ret
) {
590 char p
[STRLEN("/proc//uid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
591 uid_t uid_base
, uid_shift
, uid_range
;
592 gid_t gid_base
, gid_shift
, gid_range
;
593 _cleanup_fclose_
FILE *f
= NULL
;
599 /* Return the base UID/GID of the specified machine. Note that this only works for containers with simple
600 * mappings. In most cases setups should be simple like this, and administrators should only care about the
601 * basic offset a container has relative to the host. This is what this function exposes.
603 * If we encounter any more complex mappings we politely refuse this with ENXIO. */
605 if (m
->class == MACHINE_HOST
) {
610 if (m
->class != MACHINE_CONTAINER
)
613 xsprintf(p
, "/proc/" PID_FMT
"/uid_map", m
->leader
);
616 if (errno
== ENOENT
) {
617 /* If the file doesn't exist, user namespacing is off in the kernel, return a zero mapping hence. */
625 /* Read the first line. There's at least one. */
627 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
"\n", &uid_base
, &uid_shift
, &uid_range
);
635 /* Not a mapping starting at 0? Then it's a complex mapping we can't expose here. */
638 /* Insist that at least the nobody user is mapped, everything else is weird, and hence complex, and we don't support it */
639 if (uid_range
< UID_NOBODY
)
642 /* If there's more than one line, then we don't support this mapping. */
648 xsprintf(p
, "/proc/" PID_FMT
"/gid_map", m
->leader
);
653 /* Read the first line. There's at least one. */
655 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
"\n", &gid_base
, &gid_shift
, &gid_range
);
663 /* If there's more than one line, then we don't support this file. */
667 /* If the UID and GID mapping doesn't match, we don't support this mapping. */
668 if (uid_base
!= (uid_t
) gid_base
)
670 if (uid_shift
!= (uid_t
) gid_shift
)
672 if (uid_range
!= (uid_t
) gid_range
)
679 static const char* const machine_class_table
[_MACHINE_CLASS_MAX
] = {
680 [MACHINE_CONTAINER
] = "container",
682 [MACHINE_HOST
] = "host",
685 DEFINE_STRING_TABLE_LOOKUP(machine_class
, MachineClass
);
687 static const char* const machine_state_table
[_MACHINE_STATE_MAX
] = {
688 [MACHINE_OPENING
] = "opening",
689 [MACHINE_RUNNING
] = "running",
690 [MACHINE_CLOSING
] = "closing"
693 DEFINE_STRING_TABLE_LOOKUP(machine_state
, MachineState
);
695 static const char* const kill_who_table
[_KILL_WHO_MAX
] = {
696 [KILL_LEADER
] = "leader",
700 DEFINE_STRING_TABLE_LOOKUP(kill_who
, KillWho
);