1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2011 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include "sd-messages.h"
27 #include "alloc-util.h"
28 #include "bus-error.h"
31 #include "extract-word.h"
34 #include "format-util.h"
36 #include "machine-dbus.h"
39 #include "parse-util.h"
40 #include "process-util.h"
42 #include "stdio-util.h"
43 #include "string-table.h"
44 #include "terminal-util.h"
45 #include "unit-name.h"
46 #include "user-util.h"
49 Machine
* machine_new(Manager
*manager
, MachineClass
class, const char *name
) {
53 assert(class < _MACHINE_CLASS_MAX
);
56 /* Passing class == _MACHINE_CLASS_INVALID here is fine. It
57 * means as much as "we don't know yet", and that we'll figure
58 * it out later when loading the state file. */
64 m
->name
= strdup(name
);
68 if (class != MACHINE_HOST
) {
69 m
->state_file
= strappend("/run/systemd/machines/", m
->name
);
76 if (hashmap_put(manager
->machines
, m
->name
, m
) < 0)
89 void machine_free(Machine
*m
) {
93 operation_free(m
->operations
);
96 LIST_REMOVE(gc_queue
, m
->manager
->machine_gc_queue
, m
);
98 machine_release_unit(m
);
102 (void) hashmap_remove(m
->manager
->machines
, m
->name
);
104 if (m
->manager
->host_machine
== m
)
105 m
->manager
->host_machine
= NULL
;
108 (void) hashmap_remove_value(m
->manager
->machine_leaders
, PID_TO_PTR(m
->leader
), m
);
110 sd_bus_message_unref(m
->create_message
);
115 free(m
->root_directory
);
120 int machine_save(Machine
*m
) {
121 _cleanup_free_
char *temp_path
= NULL
;
122 _cleanup_fclose_
FILE *f
= NULL
;
133 r
= mkdir_safe_label("/run/systemd/machines", 0755, 0, 0, false);
137 r
= fopen_temporary(m
->state_file
, &f
, &temp_path
);
141 (void) fchmod(fileno(f
), 0644);
144 "# This is private data. Do not parse.\n"
149 _cleanup_free_
char *escaped
;
151 escaped
= cescape(m
->unit
);
157 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 */
161 fprintf(f
, "SCOPE_JOB=%s\n", m
->scope_job
);
164 _cleanup_free_
char *escaped
;
166 escaped
= cescape(m
->service
);
171 fprintf(f
, "SERVICE=%s\n", escaped
);
174 if (m
->root_directory
) {
175 _cleanup_free_
char *escaped
;
177 escaped
= cescape(m
->root_directory
);
182 fprintf(f
, "ROOT=%s\n", escaped
);
185 if (!sd_id128_is_null(m
->id
))
186 fprintf(f
, "ID=" SD_ID128_FORMAT_STR
"\n", SD_ID128_FORMAT_VAL(m
->id
));
189 fprintf(f
, "LEADER="PID_FMT
"\n", m
->leader
);
191 if (m
->class != _MACHINE_CLASS_INVALID
)
192 fprintf(f
, "CLASS=%s\n", machine_class_to_string(m
->class));
194 if (dual_timestamp_is_set(&m
->timestamp
))
196 "REALTIME="USEC_FMT
"\n"
197 "MONOTONIC="USEC_FMT
"\n",
198 m
->timestamp
.realtime
,
199 m
->timestamp
.monotonic
);
201 if (m
->n_netif
> 0) {
204 fputs_unlocked("NETIF=", f
);
206 for (i
= 0; i
< m
->n_netif
; i
++) {
208 fputc_unlocked(' ', f
);
210 fprintf(f
, "%i", m
->netif
[i
]);
213 fputc_unlocked('\n', f
);
216 r
= fflush_and_check(f
);
220 if (rename(temp_path
, m
->state_file
) < 0) {
228 /* Create a symlink from the unit name to the machine
229 * name, so that we can quickly find the machine for
230 * each given unit. Ignore error. */
231 sl
= strjoina("/run/systemd/machines/unit:", m
->unit
);
232 (void) symlink(m
->name
, sl
);
238 (void) unlink(m
->state_file
);
241 (void) unlink(temp_path
);
243 return log_error_errno(r
, "Failed to save machine data %s: %m", m
->state_file
);
246 static void machine_unlink(Machine
*m
) {
253 sl
= strjoina("/run/systemd/machines/unit:", m
->unit
);
258 (void) unlink(m
->state_file
);
261 int machine_load(Machine
*m
) {
262 _cleanup_free_
char *realtime
= NULL
, *monotonic
= NULL
, *id
= NULL
, *leader
= NULL
, *class = NULL
, *netif
= NULL
;
270 r
= parse_env_file(m
->state_file
, NEWLINE
,
272 "SCOPE_JOB", &m
->scope_job
,
273 "SERVICE", &m
->service
,
274 "ROOT", &m
->root_directory
,
278 "REALTIME", &realtime
,
279 "MONOTONIC", &monotonic
,
286 return log_error_errno(r
, "Failed to read %s: %m", m
->state_file
);
290 sd_id128_from_string(id
, &m
->id
);
293 parse_pid(leader
, &m
->leader
);
298 c
= machine_class_from_string(class);
304 timestamp_deserialize(realtime
, &m
->timestamp
.realtime
);
306 timestamp_deserialize(monotonic
, &m
->timestamp
.monotonic
);
309 size_t allocated
= 0, nr
= 0;
315 _cleanup_free_
char *word
= NULL
;
318 r
= extract_first_word(&p
, &word
, NULL
, 0);
324 log_warning_errno(r
, "Failed to parse NETIF: %s", netif
);
328 if (parse_ifindex(word
, &ifi
) < 0)
331 if (!GREEDY_REALLOC(ni
, allocated
, nr
+1)) {
347 static int machine_start_scope(Machine
*m
, sd_bus_message
*properties
, sd_bus_error
*error
) {
351 assert(m
->class != MACHINE_HOST
);
354 _cleanup_free_
char *escaped
= NULL
;
355 char *scope
, *description
, *job
= NULL
;
357 escaped
= unit_name_escape(m
->name
);
361 scope
= strjoin("machine-", escaped
, ".scope");
365 description
= strjoina(m
->class == MACHINE_VM
? "Virtual Machine " : "Container ", m
->name
);
367 r
= manager_start_scope(m
->manager
, scope
, m
->leader
, SPECIAL_MACHINE_SLICE
, description
, properties
, error
, &job
);
369 log_error("Failed to start machine scope: %s", bus_error_message(error
, r
));
381 hashmap_put(m
->manager
->machine_units
, m
->unit
, m
);
386 int machine_start(Machine
*m
, sd_bus_message
*properties
, sd_bus_error
*error
) {
391 if (!IN_SET(m
->class, MACHINE_CONTAINER
, MACHINE_VM
))
397 r
= hashmap_put(m
->manager
->machine_leaders
, PID_TO_PTR(m
->leader
), m
);
402 r
= machine_start_scope(m
, properties
, error
);
407 "MESSAGE_ID=" SD_MESSAGE_MACHINE_START_STR
,
409 "LEADER="PID_FMT
, m
->leader
,
410 LOG_MESSAGE("New machine %s.", m
->name
),
413 if (!dual_timestamp_is_set(&m
->timestamp
))
414 dual_timestamp_get(&m
->timestamp
);
418 /* Save new machine data */
421 machine_send_signal(m
, true);
426 static int machine_stop_scope(Machine
*m
) {
427 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
432 assert(m
->class != MACHINE_HOST
);
437 r
= manager_stop_unit(m
->manager
, m
->unit
, &error
, &job
);
439 log_error("Failed to stop machine scope: %s", bus_error_message(&error
, r
));
449 int machine_stop(Machine
*m
) {
453 if (!IN_SET(m
->class, MACHINE_CONTAINER
, MACHINE_VM
))
456 r
= machine_stop_scope(m
);
465 int machine_finalize(Machine
*m
) {
470 "MESSAGE_ID=" SD_MESSAGE_MACHINE_STOP_STR
,
472 "LEADER="PID_FMT
, m
->leader
,
473 LOG_MESSAGE("Machine %s terminated.", m
->name
),
477 machine_add_to_gc_queue(m
);
480 machine_send_signal(m
, false);
487 bool machine_check_gc(Machine
*m
, bool drop_not_started
) {
490 if (m
->class == MACHINE_HOST
)
493 if (drop_not_started
&& !m
->started
)
496 if (m
->scope_job
&& manager_job_is_active(m
->manager
, m
->scope_job
))
499 if (m
->unit
&& manager_unit_is_active(m
->manager
, m
->unit
))
505 void machine_add_to_gc_queue(Machine
*m
) {
511 LIST_PREPEND(gc_queue
, m
->manager
->machine_gc_queue
, m
);
512 m
->in_gc_queue
= true;
515 MachineState
machine_get_state(Machine
*s
) {
518 if (s
->class == MACHINE_HOST
)
519 return MACHINE_RUNNING
;
522 return MACHINE_CLOSING
;
525 return MACHINE_OPENING
;
527 return MACHINE_RUNNING
;
530 int machine_kill(Machine
*m
, KillWho who
, int signo
) {
533 if (!IN_SET(m
->class, MACHINE_VM
, MACHINE_CONTAINER
))
539 if (who
== KILL_LEADER
) {
540 /* If we shall simply kill the leader, do so directly */
542 if (kill(m
->leader
, signo
) < 0)
548 /* Otherwise, make PID 1 do it for us, for the entire cgroup */
549 return manager_kill_unit(m
->manager
, m
->unit
, signo
, NULL
);
552 int machine_openpt(Machine
*m
, int flags
) {
560 fd
= posix_openpt(flags
);
564 if (unlockpt(fd
) < 0)
570 case MACHINE_CONTAINER
:
574 return openpt_in_namespace(m
->leader
, flags
);
581 int machine_open_terminal(Machine
*m
, const char *path
, int mode
) {
587 return open_terminal(path
, mode
);
589 case MACHINE_CONTAINER
:
593 return open_terminal_in_namespace(m
->leader
, path
, mode
);
600 void machine_release_unit(Machine
*m
) {
606 (void) hashmap_remove(m
->manager
->machine_units
, m
->unit
);
607 m
->unit
= mfree(m
->unit
);
610 int machine_get_uid_shift(Machine
*m
, uid_t
*ret
) {
611 char p
[strlen("/proc//uid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
612 uid_t uid_base
, uid_shift
, uid_range
;
613 gid_t gid_base
, gid_shift
, gid_range
;
614 _cleanup_fclose_
FILE *f
= NULL
;
620 /* Return the base UID/GID of the specified machine. Note that this only works for containers with simple
621 * mappings. In most cases setups should be simple like this, and administrators should only care about the
622 * basic offset a container has relative to the host. This is what this function exposes.
624 * If we encounter any more complex mappings we politely refuse this with ENXIO. */
626 if (m
->class == MACHINE_HOST
) {
631 if (m
->class != MACHINE_CONTAINER
)
634 xsprintf(p
, "/proc/" PID_FMT
"/uid_map", m
->leader
);
637 if (errno
== ENOENT
) {
638 /* If the file doesn't exist, user namespacing is off in the kernel, return a zero mapping hence. */
646 /* Read the first line. There's at least one. */
648 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
"\n", &uid_base
, &uid_shift
, &uid_range
);
656 /* Not a mapping starting at 0? Then it's a complex mapping we can't expose here. */
659 /* Insist that at least the nobody user is mapped, everything else is weird, and hence complex, and we don't support it */
660 if (uid_range
< UID_NOBODY
)
663 /* If there's more than one line, then we don't support this mapping. */
669 xsprintf(p
, "/proc/" PID_FMT
"/gid_map", m
->leader
);
674 /* Read the first line. There's at least one. */
676 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
"\n", &gid_base
, &gid_shift
, &gid_range
);
684 /* If there's more than one line, then we don't support this file. */
688 /* If the UID and GID mapping doesn't match, we don't support this mapping. */
689 if (uid_base
!= (uid_t
) gid_base
)
691 if (uid_shift
!= (uid_t
) gid_shift
)
693 if (uid_range
!= (uid_t
) gid_range
)
700 static const char* const machine_class_table
[_MACHINE_CLASS_MAX
] = {
701 [MACHINE_CONTAINER
] = "container",
703 [MACHINE_HOST
] = "host",
706 DEFINE_STRING_TABLE_LOOKUP(machine_class
, MachineClass
);
708 static const char* const machine_state_table
[_MACHINE_STATE_MAX
] = {
709 [MACHINE_OPENING
] = "opening",
710 [MACHINE_RUNNING
] = "running",
711 [MACHINE_CLOSING
] = "closing"
714 DEFINE_STRING_TABLE_LOOKUP(machine_state
, MachineState
);
716 static const char* const kill_who_table
[_KILL_WHO_MAX
] = {
717 [KILL_LEADER
] = "leader",
721 DEFINE_STRING_TABLE_LOOKUP(kill_who
, KillWho
);