mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-23 17:34:00 +03:00
nspawn: split out machined registration code to nspawn-register.[ch]
This commit is contained in:
parent
34829a324b
commit
b7103bc5f4
@ -2789,6 +2789,8 @@ systemd_nspawn_SOURCES = \
|
||||
src/nspawn/nspawn-expose-ports.h \
|
||||
src/nspawn/nspawn-cgroup.c \
|
||||
src/nspawn/nspawn-cgroup.h \
|
||||
src/nspawn/nspawn-register.c \
|
||||
src/nspawn/nspawn-register.h \
|
||||
src/core/mount-setup.c \
|
||||
src/core/mount-setup.h \
|
||||
src/core/loopback-setup.c \
|
||||
|
245
src/nspawn/nspawn-register.c
Normal file
245
src/nspawn/nspawn-register.c
Normal file
@ -0,0 +1,245 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2015 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "strv.h"
|
||||
#include "bus-util.h"
|
||||
#include "bus-error.h"
|
||||
|
||||
#include "nspawn.h"
|
||||
#include "nspawn-register.h"
|
||||
|
||||
int register_machine(
|
||||
const char *machine_name,
|
||||
pid_t pid,
|
||||
const char *directory,
|
||||
sd_id128_t uuid,
|
||||
int local_ifindex,
|
||||
const char *slice,
|
||||
CustomMount *mounts,
|
||||
unsigned n_mounts,
|
||||
int kill_signal,
|
||||
char **properties,
|
||||
bool keep_unit) {
|
||||
|
||||
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
|
||||
int r;
|
||||
|
||||
r = sd_bus_default_system(&bus);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open system bus: %m");
|
||||
|
||||
if (keep_unit) {
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.machine1",
|
||||
"/org/freedesktop/machine1",
|
||||
"org.freedesktop.machine1.Manager",
|
||||
"RegisterMachineWithNetwork",
|
||||
&error,
|
||||
NULL,
|
||||
"sayssusai",
|
||||
machine_name,
|
||||
SD_BUS_MESSAGE_APPEND_ID128(uuid),
|
||||
"nspawn",
|
||||
"container",
|
||||
(uint32_t) pid,
|
||||
strempty(directory),
|
||||
local_ifindex > 0 ? 1 : 0, local_ifindex);
|
||||
} else {
|
||||
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
|
||||
char **i;
|
||||
unsigned j;
|
||||
|
||||
r = sd_bus_message_new_method_call(
|
||||
bus,
|
||||
&m,
|
||||
"org.freedesktop.machine1",
|
||||
"/org/freedesktop/machine1",
|
||||
"org.freedesktop.machine1.Manager",
|
||||
"CreateMachineWithNetwork");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append(
|
||||
m,
|
||||
"sayssusai",
|
||||
machine_name,
|
||||
SD_BUS_MESSAGE_APPEND_ID128(uuid),
|
||||
"nspawn",
|
||||
"container",
|
||||
(uint32_t) pid,
|
||||
strempty(directory),
|
||||
local_ifindex > 0 ? 1 : 0, local_ifindex);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_open_container(m, 'a', "(sv)");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
if (!isempty(slice)) {
|
||||
r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "strict");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
/* If you make changes here, also make sure to update
|
||||
* systemd-nspawn@.service, to keep the device
|
||||
* policies in sync regardless if we are run with or
|
||||
* without the --keep-unit switch. */
|
||||
r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 9,
|
||||
/* Allow the container to
|
||||
* access and create the API
|
||||
* device nodes, so that
|
||||
* PrivateDevices= in the
|
||||
* container can work
|
||||
* fine */
|
||||
"/dev/null", "rwm",
|
||||
"/dev/zero", "rwm",
|
||||
"/dev/full", "rwm",
|
||||
"/dev/random", "rwm",
|
||||
"/dev/urandom", "rwm",
|
||||
"/dev/tty", "rwm",
|
||||
"/dev/net/tun", "rwm",
|
||||
/* Allow the container
|
||||
* access to ptys. However,
|
||||
* do not permit the
|
||||
* container to ever create
|
||||
* these device nodes. */
|
||||
"/dev/pts/ptmx", "rw",
|
||||
"char-pts", "rw");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
for (j = 0; j < n_mounts; j++) {
|
||||
CustomMount *cm = mounts + j;
|
||||
|
||||
if (cm->type != CUSTOM_MOUNT_BIND)
|
||||
continue;
|
||||
|
||||
r = is_device_node(cm->source);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to stat %s: %m", cm->source);
|
||||
|
||||
if (r) {
|
||||
r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
|
||||
cm->source, cm->read_only ? "r" : "rw");
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to append message arguments: %m");
|
||||
}
|
||||
}
|
||||
|
||||
if (kill_signal != 0) {
|
||||
r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
STRV_FOREACH(i, properties) {
|
||||
r = sd_bus_message_open_container(m, 'r', "sv");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = bus_append_unit_property_assignment(m, *i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_call(bus, m, 0, &error, NULL);
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
log_error("Failed to register machine: %s", bus_error_message(&error, r));
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int terminate_machine(pid_t pid) {
|
||||
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
|
||||
_cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
|
||||
const char *path;
|
||||
int r;
|
||||
|
||||
r = sd_bus_default_system(&bus);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open system bus: %m");
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.machine1",
|
||||
"/org/freedesktop/machine1",
|
||||
"org.freedesktop.machine1.Manager",
|
||||
"GetMachineByPID",
|
||||
&error,
|
||||
&reply,
|
||||
"u",
|
||||
(uint32_t) pid);
|
||||
if (r < 0) {
|
||||
/* Note that the machine might already have been
|
||||
* cleaned up automatically, hence don't consider it a
|
||||
* failure if we cannot get the machine object. */
|
||||
log_debug("Failed to get machine: %s", bus_error_message(&error, r));
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_bus_message_read(reply, "o", &path);
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.machine1",
|
||||
path,
|
||||
"org.freedesktop.machine1.Machine",
|
||||
"Terminate",
|
||||
&error,
|
||||
NULL,
|
||||
NULL);
|
||||
if (r < 0) {
|
||||
log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
31
src/nspawn/nspawn-register.h
Normal file
31
src/nspawn/nspawn-register.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2015 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "nspawn-mount.h"
|
||||
|
||||
int register_machine(const char *machine_name, pid_t pid, const char *directory, sd_id128_t uuid, int local_ifindex, const char *slice, CustomMount *mounts, unsigned n_mounts, int kill_signal, char **properties, bool keep_unit);
|
||||
int terminate_machine(pid_t pid);
|
@ -102,6 +102,7 @@
|
||||
#include "nspawn-network.h"
|
||||
#include "nspawn-expose-ports.h"
|
||||
#include "nspawn-cgroup.h"
|
||||
#include "nspawn-register.h"
|
||||
|
||||
typedef enum ContainerStatus {
|
||||
CONTAINER_TERMINATED,
|
||||
@ -1515,220 +1516,6 @@ static int drop_capabilities(void) {
|
||||
return capability_bounding_set_drop(~arg_retain, false);
|
||||
}
|
||||
|
||||
static int register_machine(pid_t pid, int local_ifindex) {
|
||||
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
|
||||
int r;
|
||||
|
||||
if (!arg_register)
|
||||
return 0;
|
||||
|
||||
r = sd_bus_default_system(&bus);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open system bus: %m");
|
||||
|
||||
if (arg_keep_unit) {
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.machine1",
|
||||
"/org/freedesktop/machine1",
|
||||
"org.freedesktop.machine1.Manager",
|
||||
"RegisterMachineWithNetwork",
|
||||
&error,
|
||||
NULL,
|
||||
"sayssusai",
|
||||
arg_machine,
|
||||
SD_BUS_MESSAGE_APPEND_ID128(arg_uuid),
|
||||
"nspawn",
|
||||
"container",
|
||||
(uint32_t) pid,
|
||||
strempty(arg_directory),
|
||||
local_ifindex > 0 ? 1 : 0, local_ifindex);
|
||||
} else {
|
||||
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
|
||||
char **i;
|
||||
unsigned j;
|
||||
|
||||
r = sd_bus_message_new_method_call(
|
||||
bus,
|
||||
&m,
|
||||
"org.freedesktop.machine1",
|
||||
"/org/freedesktop/machine1",
|
||||
"org.freedesktop.machine1.Manager",
|
||||
"CreateMachineWithNetwork");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append(
|
||||
m,
|
||||
"sayssusai",
|
||||
arg_machine,
|
||||
SD_BUS_MESSAGE_APPEND_ID128(arg_uuid),
|
||||
"nspawn",
|
||||
"container",
|
||||
(uint32_t) pid,
|
||||
strempty(arg_directory),
|
||||
local_ifindex > 0 ? 1 : 0, local_ifindex);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_open_container(m, 'a', "(sv)");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
if (!isempty(arg_slice)) {
|
||||
r = sd_bus_message_append(m, "(sv)", "Slice", "s", arg_slice);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "strict");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
/* If you make changes here, also make sure to update
|
||||
* systemd-nspawn@.service, to keep the device
|
||||
* policies in sync regardless if we are run with or
|
||||
* without the --keep-unit switch. */
|
||||
r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 9,
|
||||
/* Allow the container to
|
||||
* access and create the API
|
||||
* device nodes, so that
|
||||
* PrivateDevices= in the
|
||||
* container can work
|
||||
* fine */
|
||||
"/dev/null", "rwm",
|
||||
"/dev/zero", "rwm",
|
||||
"/dev/full", "rwm",
|
||||
"/dev/random", "rwm",
|
||||
"/dev/urandom", "rwm",
|
||||
"/dev/tty", "rwm",
|
||||
"/dev/net/tun", "rwm",
|
||||
/* Allow the container
|
||||
* access to ptys. However,
|
||||
* do not permit the
|
||||
* container to ever create
|
||||
* these device nodes. */
|
||||
"/dev/pts/ptmx", "rw",
|
||||
"char-pts", "rw");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
for (j = 0; j < arg_n_custom_mounts; j++) {
|
||||
CustomMount *cm = &arg_custom_mounts[j];
|
||||
|
||||
if (cm->type != CUSTOM_MOUNT_BIND)
|
||||
continue;
|
||||
|
||||
r = is_device_node(cm->source);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to stat %s: %m", cm->source);
|
||||
|
||||
if (r) {
|
||||
r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
|
||||
cm->source, cm->read_only ? "r" : "rw");
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to append message arguments: %m");
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_kill_signal != 0) {
|
||||
r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", arg_kill_signal);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
STRV_FOREACH(i, arg_property) {
|
||||
r = sd_bus_message_open_container(m, 'r', "sv");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = bus_append_unit_property_assignment(m, *i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = sd_bus_call(bus, m, 0, &error, NULL);
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
log_error("Failed to register machine: %s", bus_error_message(&error, r));
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int terminate_machine(pid_t pid) {
|
||||
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
|
||||
_cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
|
||||
const char *path;
|
||||
int r;
|
||||
|
||||
if (!arg_register)
|
||||
return 0;
|
||||
|
||||
/* If we are reusing the unit, then just exit, systemd will do
|
||||
* the right thing when we exit. */
|
||||
if (arg_keep_unit)
|
||||
return 0;
|
||||
|
||||
r = sd_bus_default_system(&bus);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to open system bus: %m");
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.machine1",
|
||||
"/org/freedesktop/machine1",
|
||||
"org.freedesktop.machine1.Manager",
|
||||
"GetMachineByPID",
|
||||
&error,
|
||||
&reply,
|
||||
"u",
|
||||
(uint32_t) pid);
|
||||
if (r < 0) {
|
||||
/* Note that the machine might already have been
|
||||
* cleaned up automatically, hence don't consider it a
|
||||
* failure if we cannot get the machine object. */
|
||||
log_debug("Failed to get machine: %s", bus_error_message(&error, r));
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = sd_bus_message_read(reply, "o", &path);
|
||||
if (r < 0)
|
||||
return bus_log_parse_error(r);
|
||||
|
||||
r = sd_bus_call_method(
|
||||
bus,
|
||||
"org.freedesktop.machine1",
|
||||
path,
|
||||
"org.freedesktop.machine1.Machine",
|
||||
"Terminate",
|
||||
&error,
|
||||
NULL,
|
||||
NULL);
|
||||
if (r < 0) {
|
||||
log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int reset_audit_loginuid(void) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int r;
|
||||
@ -3904,9 +3691,21 @@ int main(int argc, char *argv[]) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = register_machine(pid, ifi);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
if (arg_register) {
|
||||
r = register_machine(
|
||||
arg_machine,
|
||||
pid,
|
||||
arg_directory,
|
||||
arg_uuid,
|
||||
ifi,
|
||||
arg_slice,
|
||||
arg_custom_mounts, arg_n_custom_mounts,
|
||||
arg_kill_signal,
|
||||
arg_property,
|
||||
arg_keep_unit);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = sync_cgroup(pid, arg_unified_cgroup_hierarchy);
|
||||
if (r < 0)
|
||||
@ -4000,7 +3799,8 @@ int main(int argc, char *argv[]) {
|
||||
putc('\n', stdout);
|
||||
|
||||
/* Kill if it is not dead yet anyway */
|
||||
terminate_machine(pid);
|
||||
if (arg_register && !arg_keep_unit)
|
||||
terminate_machine(pid);
|
||||
|
||||
/* Normally redundant, but better safe than sorry */
|
||||
kill(pid, SIGKILL);
|
||||
|
Loading…
Reference in New Issue
Block a user