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/>.
24 #include <stdio_ext.h>
26 #include "sd-messages.h"
28 #include "alloc-util.h"
29 #include "bus-error.h"
32 #include "extract-word.h"
35 #include "format-util.h"
37 #include "machine-dbus.h"
40 #include "parse-util.h"
41 #include "process-util.h"
43 #include "stdio-util.h"
44 #include "string-table.h"
45 #include "terminal-util.h"
46 #include "unit-name.h"
47 #include "user-util.h"
50 Machine
* machine_new(Manager
*manager
, MachineClass
class, const char *name
) {
54 assert(class < _MACHINE_CLASS_MAX
);
57 /* Passing class == _MACHINE_CLASS_INVALID here is fine. It
58 * means as much as "we don't know yet", and that we'll figure
59 * it out later when loading the state file. */
65 m
->name
= strdup(name
);
69 if (class != MACHINE_HOST
) {
70 m
->state_file
= strappend("/run/systemd/machines/", m
->name
);
77 if (hashmap_put(manager
->machines
, m
->name
, m
) < 0)
90 void machine_free(Machine
*m
) {
94 operation_free(m
->operations
);
97 LIST_REMOVE(gc_queue
, m
->manager
->machine_gc_queue
, m
);
99 machine_release_unit(m
);
103 (void) hashmap_remove(m
->manager
->machines
, m
->name
);
105 if (m
->manager
->host_machine
== m
)
106 m
->manager
->host_machine
= NULL
;
109 (void) hashmap_remove_value(m
->manager
->machine_leaders
, PID_TO_PTR(m
->leader
), m
);
111 sd_bus_message_unref(m
->create_message
);
116 free(m
->root_directory
);
121 int machine_save(Machine
*m
) {
122 _cleanup_free_
char *temp_path
= NULL
;
123 _cleanup_fclose_
FILE *f
= NULL
;
134 r
= mkdir_safe_label("/run/systemd/machines", 0755, 0, 0, false);
138 r
= fopen_temporary(m
->state_file
, &f
, &temp_path
);
142 (void) __fsetlocking(f
, FSETLOCKING_BYCALLER
);
143 (void) fchmod(fileno(f
), 0644);
146 "# This is private data. Do not parse.\n"
151 _cleanup_free_
char *escaped
;
153 escaped
= cescape(m
->unit
);
159 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 */
163 fprintf(f
, "SCOPE_JOB=%s\n", m
->scope_job
);
166 _cleanup_free_
char *escaped
;
168 escaped
= cescape(m
->service
);
173 fprintf(f
, "SERVICE=%s\n", escaped
);
176 if (m
->root_directory
) {
177 _cleanup_free_
char *escaped
;
179 escaped
= cescape(m
->root_directory
);
184 fprintf(f
, "ROOT=%s\n", escaped
);
187 if (!sd_id128_is_null(m
->id
))
188 fprintf(f
, "ID=" SD_ID128_FORMAT_STR
"\n", SD_ID128_FORMAT_VAL(m
->id
));
191 fprintf(f
, "LEADER="PID_FMT
"\n", m
->leader
);
193 if (m
->class != _MACHINE_CLASS_INVALID
)
194 fprintf(f
, "CLASS=%s\n", machine_class_to_string(m
->class));
196 if (dual_timestamp_is_set(&m
->timestamp
))
198 "REALTIME="USEC_FMT
"\n"
199 "MONOTONIC="USEC_FMT
"\n",
200 m
->timestamp
.realtime
,
201 m
->timestamp
.monotonic
);
203 if (m
->n_netif
> 0) {
208 for (i
= 0; i
< m
->n_netif
; i
++) {
212 fprintf(f
, "%i", m
->netif
[i
]);
218 r
= fflush_and_check(f
);
222 if (rename(temp_path
, m
->state_file
) < 0) {
230 /* Create a symlink from the unit name to the machine
231 * name, so that we can quickly find the machine for
232 * each given unit. Ignore error. */
233 sl
= strjoina("/run/systemd/machines/unit:", m
->unit
);
234 (void) symlink(m
->name
, sl
);
240 (void) unlink(m
->state_file
);
243 (void) unlink(temp_path
);
245 return log_error_errno(r
, "Failed to save machine data %s: %m", m
->state_file
);
248 static void machine_unlink(Machine
*m
) {
255 sl
= strjoina("/run/systemd/machines/unit:", m
->unit
);
260 (void) unlink(m
->state_file
);
263 int machine_load(Machine
*m
) {
264 _cleanup_free_
char *realtime
= NULL
, *monotonic
= NULL
, *id
= NULL
, *leader
= NULL
, *class = NULL
, *netif
= NULL
;
272 r
= parse_env_file(m
->state_file
, NEWLINE
,
274 "SCOPE_JOB", &m
->scope_job
,
275 "SERVICE", &m
->service
,
276 "ROOT", &m
->root_directory
,
280 "REALTIME", &realtime
,
281 "MONOTONIC", &monotonic
,
288 return log_error_errno(r
, "Failed to read %s: %m", m
->state_file
);
292 sd_id128_from_string(id
, &m
->id
);
295 parse_pid(leader
, &m
->leader
);
300 c
= machine_class_from_string(class);
306 timestamp_deserialize(realtime
, &m
->timestamp
.realtime
);
308 timestamp_deserialize(monotonic
, &m
->timestamp
.monotonic
);
311 size_t allocated
= 0, nr
= 0;
317 _cleanup_free_
char *word
= NULL
;
320 r
= extract_first_word(&p
, &word
, NULL
, 0);
326 log_warning_errno(r
, "Failed to parse NETIF: %s", netif
);
330 if (parse_ifindex(word
, &ifi
) < 0)
333 if (!GREEDY_REALLOC(ni
, allocated
, nr
+1)) {
349 static int machine_start_scope(Machine
*m
, sd_bus_message
*properties
, sd_bus_error
*error
) {
353 assert(m
->class != MACHINE_HOST
);
356 _cleanup_free_
char *escaped
= NULL
;
357 char *scope
, *description
, *job
= NULL
;
359 escaped
= unit_name_escape(m
->name
);
363 scope
= strjoin("machine-", escaped
, ".scope");
367 description
= strjoina(m
->class == MACHINE_VM
? "Virtual Machine " : "Container ", m
->name
);
369 r
= manager_start_scope(m
->manager
, scope
, m
->leader
, SPECIAL_MACHINE_SLICE
, description
, properties
, error
, &job
);
371 log_error("Failed to start machine scope: %s", bus_error_message(error
, r
));
383 hashmap_put(m
->manager
->machine_units
, m
->unit
, m
);
388 int machine_start(Machine
*m
, sd_bus_message
*properties
, sd_bus_error
*error
) {
393 if (!IN_SET(m
->class, MACHINE_CONTAINER
, MACHINE_VM
))
399 r
= hashmap_put(m
->manager
->machine_leaders
, PID_TO_PTR(m
->leader
), m
);
404 r
= machine_start_scope(m
, properties
, error
);
409 "MESSAGE_ID=" SD_MESSAGE_MACHINE_START_STR
,
411 "LEADER="PID_FMT
, m
->leader
,
412 LOG_MESSAGE("New machine %s.", m
->name
),
415 if (!dual_timestamp_is_set(&m
->timestamp
))
416 dual_timestamp_get(&m
->timestamp
);
420 /* Save new machine data */
423 machine_send_signal(m
, true);
428 static int machine_stop_scope(Machine
*m
) {
429 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
434 assert(m
->class != MACHINE_HOST
);
439 r
= manager_stop_unit(m
->manager
, m
->unit
, &error
, &job
);
441 log_error("Failed to stop machine scope: %s", bus_error_message(&error
, r
));
451 int machine_stop(Machine
*m
) {
455 if (!IN_SET(m
->class, MACHINE_CONTAINER
, MACHINE_VM
))
458 r
= machine_stop_scope(m
);
467 int machine_finalize(Machine
*m
) {
472 "MESSAGE_ID=" SD_MESSAGE_MACHINE_STOP_STR
,
474 "LEADER="PID_FMT
, m
->leader
,
475 LOG_MESSAGE("Machine %s terminated.", m
->name
),
479 machine_add_to_gc_queue(m
);
482 machine_send_signal(m
, false);
489 bool machine_check_gc(Machine
*m
, bool drop_not_started
) {
492 if (m
->class == MACHINE_HOST
)
495 if (drop_not_started
&& !m
->started
)
498 if (m
->scope_job
&& manager_job_is_active(m
->manager
, m
->scope_job
))
501 if (m
->unit
&& manager_unit_is_active(m
->manager
, m
->unit
))
507 void machine_add_to_gc_queue(Machine
*m
) {
513 LIST_PREPEND(gc_queue
, m
->manager
->machine_gc_queue
, m
);
514 m
->in_gc_queue
= true;
517 MachineState
machine_get_state(Machine
*s
) {
520 if (s
->class == MACHINE_HOST
)
521 return MACHINE_RUNNING
;
524 return MACHINE_CLOSING
;
527 return MACHINE_OPENING
;
529 return MACHINE_RUNNING
;
532 int machine_kill(Machine
*m
, KillWho who
, int signo
) {
535 if (!IN_SET(m
->class, MACHINE_VM
, MACHINE_CONTAINER
))
541 if (who
== KILL_LEADER
) {
542 /* If we shall simply kill the leader, do so directly */
544 if (kill(m
->leader
, signo
) < 0)
550 /* Otherwise, make PID 1 do it for us, for the entire cgroup */
551 return manager_kill_unit(m
->manager
, m
->unit
, signo
, NULL
);
554 int machine_openpt(Machine
*m
, int flags
) {
562 fd
= posix_openpt(flags
);
566 if (unlockpt(fd
) < 0)
572 case MACHINE_CONTAINER
:
576 return openpt_in_namespace(m
->leader
, flags
);
583 int machine_open_terminal(Machine
*m
, const char *path
, int mode
) {
589 return open_terminal(path
, mode
);
591 case MACHINE_CONTAINER
:
595 return open_terminal_in_namespace(m
->leader
, path
, mode
);
602 void machine_release_unit(Machine
*m
) {
608 (void) hashmap_remove(m
->manager
->machine_units
, m
->unit
);
609 m
->unit
= mfree(m
->unit
);
612 int machine_get_uid_shift(Machine
*m
, uid_t
*ret
) {
613 char p
[STRLEN("/proc//uid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
614 uid_t uid_base
, uid_shift
, uid_range
;
615 gid_t gid_base
, gid_shift
, gid_range
;
616 _cleanup_fclose_
FILE *f
= NULL
;
622 /* Return the base UID/GID of the specified machine. Note that this only works for containers with simple
623 * mappings. In most cases setups should be simple like this, and administrators should only care about the
624 * basic offset a container has relative to the host. This is what this function exposes.
626 * If we encounter any more complex mappings we politely refuse this with ENXIO. */
628 if (m
->class == MACHINE_HOST
) {
633 if (m
->class != MACHINE_CONTAINER
)
636 xsprintf(p
, "/proc/" PID_FMT
"/uid_map", m
->leader
);
639 if (errno
== ENOENT
) {
640 /* If the file doesn't exist, user namespacing is off in the kernel, return a zero mapping hence. */
648 /* Read the first line. There's at least one. */
650 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
"\n", &uid_base
, &uid_shift
, &uid_range
);
658 /* Not a mapping starting at 0? Then it's a complex mapping we can't expose here. */
661 /* Insist that at least the nobody user is mapped, everything else is weird, and hence complex, and we don't support it */
662 if (uid_range
< UID_NOBODY
)
665 /* If there's more than one line, then we don't support this mapping. */
671 xsprintf(p
, "/proc/" PID_FMT
"/gid_map", m
->leader
);
676 /* Read the first line. There's at least one. */
678 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
"\n", &gid_base
, &gid_shift
, &gid_range
);
686 /* If there's more than one line, then we don't support this file. */
690 /* If the UID and GID mapping doesn't match, we don't support this mapping. */
691 if (uid_base
!= (uid_t
) gid_base
)
693 if (uid_shift
!= (uid_t
) gid_shift
)
695 if (uid_range
!= (uid_t
) gid_range
)
702 static const char* const machine_class_table
[_MACHINE_CLASS_MAX
] = {
703 [MACHINE_CONTAINER
] = "container",
705 [MACHINE_HOST
] = "host",
708 DEFINE_STRING_TABLE_LOOKUP(machine_class
, MachineClass
);
710 static const char* const machine_state_table
[_MACHINE_STATE_MAX
] = {
711 [MACHINE_OPENING
] = "opening",
712 [MACHINE_RUNNING
] = "running",
713 [MACHINE_CLOSING
] = "closing"
716 DEFINE_STRING_TABLE_LOOKUP(machine_state
, MachineState
);
718 static const char* const kill_who_table
[_KILL_WHO_MAX
] = {
719 [KILL_LEADER
] = "leader",
723 DEFINE_STRING_TABLE_LOOKUP(kill_who
, KillWho
);