machine-dbus.c revision d84401767785a8380700d5d9c805c36f5fc63980
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt/***
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt This file is part of systemd.
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt Copyright 2011 Lennart Poettering
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt systemd is free software; you can redistribute it and/or modify it
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt under the terms of the GNU Lesser General Public License as published by
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt the Free Software Foundation; either version 2.1 of the License, or
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt (at your option) any later version.
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt systemd is distributed in the hope that it will be useful, but
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt WITHOUT ANY WARRANTY; without even the implied warranty of
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt Lesser General Public License for more details.
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt You should have received a copy of the GNU Lesser General Public License
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt along with systemd; If not, see <http://www.gnu.org/licenses/>.
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering***/
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include <errno.h>
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include <string.h>
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include <sys/mount.h>
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt/* When we include libgen.h because we need dirname() we immediately
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt * undefine basename() since libgen.h defines it as a macro to the POSIX
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt * version which is really broken. We prefer GNU basename(). */
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include <libgen.h>
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#undef basename
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "bus-util.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "bus-label.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "strv.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "bus-common-errors.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "copy.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "fileio.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "in-addr-util.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "local-addresses.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "path-util.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "mkdir.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "bus-internal.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "machine.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "machine-dbus.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "formats-util.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt#include "process-util.h"
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidtstatic int property_get_id(
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt sd_bus *bus,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *path,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *interface,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *property,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt sd_bus_message *reply,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt void *userdata,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt sd_bus_error *error) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt Machine *m = userdata;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(bus);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(reply);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(m);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_message_append_array(reply, 'y', &m->id, 16);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt}
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidtstatic int property_get_state(
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt sd_bus *bus,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *path,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *interface,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *property,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt sd_bus_message *reply,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt void *userdata,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt sd_bus_error *error) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt Machine *m = userdata;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *state;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt int r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(bus);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(reply);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(m);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt state = machine_state_to_string(machine_get_state(m));
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_message_append_basic(reply, 's', state);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return 1;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt}
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidtstatic int property_get_netif(
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt sd_bus *bus,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *path,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *interface,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *property,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt sd_bus_message *reply,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt void *userdata,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt sd_bus_error *error) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt Machine *m = userdata;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(bus);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(reply);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(m);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert_cc(sizeof(int) == sizeof(int32_t));
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_message_append_array(reply, 'i', m->netif, m->n_netif * sizeof(int));
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt}
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidtstatic BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidtint bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt Machine *m = userdata;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt int r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(message);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(m);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = bus_verify_polkit_async(
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt message,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt CAP_KILL,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt "org.freedesktop.machine1.manage-machines",
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt false,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt UID_INVALID,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt &m->manager->polkit_registry,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt error);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r == 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return 1; /* Will call us back */
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = machine_stop(m);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_reply_method_return(message, NULL);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt}
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidtint bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt Machine *m = userdata;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *swho;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt int32_t signo;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt KillWho who;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt int r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(message);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(m);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_message_read(message, "si", &swho, &signo);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (isempty(swho))
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt who = KILL_ALL;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt else {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt who = kill_who_from_string(swho);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (who < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (signo <= 0 || signo >= _NSIG)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = bus_verify_polkit_async(
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt message,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt CAP_KILL,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt "org.freedesktop.machine1.manage-machines",
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt false,
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt UID_INVALID,
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt &m->manager->polkit_registry,
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt error);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r == 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return 1; /* Will call us back */
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = machine_kill(m, who, signo);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return sd_bus_reply_method_return(message, NULL);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt}
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidtint bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt _cleanup_close_pair_ int pair[2] = { -1, -1 };
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt _cleanup_free_ char *us = NULL, *them = NULL;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt _cleanup_close_ int netns_fd = -1;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt Machine *m = userdata;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt const char *p;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt siginfo_t si;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt pid_t child;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt int r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt assert(message);
e80afdb3e4a1239ce0bffa4215d6a227caf3d833Michal Schmidt assert(m);
e80afdb3e4a1239ce0bffa4215d6a227caf3d833Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (m->class != MACHINE_CONTAINER)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting IP address data is only supported on container machines.");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = readlink_malloc("/proc/self/ns/net", &us);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt p = procfs_file_alloca(m->leader, "ns/net");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = readlink_malloc(p, &them);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (streq(us, them))
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = namespace_open(m->leader, NULL, NULL, &netns_fd, NULL);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return -errno;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt child = fork();
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (child < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (child == 0) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _cleanup_free_ struct local_address *addresses = NULL;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt struct local_address *a;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt int i, n;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt pair[0] = safe_close(pair[0]);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = namespace_enter(-1, -1, netns_fd, -1);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt _exit(EXIT_FAILURE);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt n = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (n < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _exit(EXIT_FAILURE);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt for (a = addresses, i = 0; i < n; a++, i++) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt struct iovec iov[2] = {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt { .iov_base = &a->family, .iov_len = sizeof(a->family) },
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt { .iov_base = &a->address, .iov_len = FAMILY_ADDRESS_SIZE(a->family) },
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt };
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = writev(pair[1], iov, 2);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
435fc3176520a58f1c20ccb983c9fb40b30a1471Martin Pitt _exit(EXIT_FAILURE);
435fc3176520a58f1c20ccb983c9fb40b30a1471Martin Pitt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
61c81750217af7492be86adde81b28e310cd5e82Tom Gundersen pair[1] = safe_close(pair[1]);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _exit(EXIT_SUCCESS);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt pair[1] = safe_close(pair[1]);
435fc3176520a58f1c20ccb983c9fb40b30a1471Martin Pitt
435fc3176520a58f1c20ccb983c9fb40b30a1471Martin Pitt r = sd_bus_message_new_method_return(message, &reply);
435fc3176520a58f1c20ccb983c9fb40b30a1471Martin Pitt if (r < 0)
435fc3176520a58f1c20ccb983c9fb40b30a1471Martin Pitt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_message_open_container(reply, 'a', "(iay)");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt for (;;) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt int family;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt ssize_t n;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt union in_addr_union in_addr;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt struct iovec iov[2];
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt struct msghdr mh = {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt .msg_iov = iov,
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt .msg_iovlen = 2,
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt };
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt iov[0] = (struct iovec) { .iov_base = &family, .iov_len = sizeof(family) };
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt iov[1] = (struct iovec) { .iov_base = &in_addr, .iov_len = sizeof(in_addr) };
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt n = recvmsg(pair[0], &mh, 0);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (n < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return -errno;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if ((size_t) n < sizeof(family))
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt break;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_message_open_container(reply, 'r', "iay");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_message_append(reply, "i", family);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt switch (family) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt case AF_INET:
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (n != sizeof(struct in_addr) + sizeof(family))
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return -EIO;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_message_append_array(reply, 'y', &in_addr.in, sizeof(in_addr.in));
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt break;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt case AF_INET6:
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (n != sizeof(struct in6_addr) + sizeof(family))
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return -EIO;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_message_append_array(reply, 'y', &in_addr.in6, sizeof(in_addr.in6));
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt break;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt }
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_message_close_container(reply);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt }
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = wait_for_terminate(child, &si);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return sd_bus_error_set_errnof(error, r, "Failed to wait for client: %m");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_message_close_container(reply);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return sd_bus_send(NULL, reply, NULL);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt}
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidtint bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt _cleanup_close_ int mntns_fd = -1, root_fd = -1;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt _cleanup_close_pair_ int pair[2] = { -1, -1 };
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt _cleanup_strv_free_ char **l = NULL;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt _cleanup_fclose_ FILE *f = NULL;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt Machine *m = userdata;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt char **k, **v;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt siginfo_t si;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt pid_t child;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt int r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt assert(message);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt assert(m);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (m->class != MACHINE_CONTAINER)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting OS release data is only supported on container machines.");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = namespace_open(m->leader, NULL, &mntns_fd, NULL, &root_fd);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return -errno;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt child = fork();
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (child < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (child == 0) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt _cleanup_close_ int fd = -1;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt pair[0] = safe_close(pair[0]);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = namespace_enter(-1, mntns_fd, -1, root_fd);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt _exit(EXIT_FAILURE);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt fd = open("/etc/os-release", O_RDONLY|O_CLOEXEC);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (fd < 0) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt fd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (fd < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _exit(EXIT_FAILURE);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = copy_bytes(fd, pair[1], (off_t) -1, false);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _exit(EXIT_FAILURE);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt _exit(EXIT_SUCCESS);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt }
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt pair[1] = safe_close(pair[1]);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt f = fdopen(pair[0], "re");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (!f)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return -errno;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt pair[0] = -1;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = load_env_file_pairs(f, "/etc/os-release", NULL, &l);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = wait_for_terminate(child, &si);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return sd_bus_error_set_errnof(error, r, "Failed to wait for client: %m");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_message_new_method_return(message, &reply);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_message_open_container(reply, 'a', "{ss}");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt STRV_FOREACH_PAIR(k, v, l) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_message_append(reply, "{ss}", *k, *v);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt }
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_message_close_container(reply);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt return r;
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt return sd_bus_send(NULL, reply, NULL);
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt}
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidtint bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt _cleanup_free_ char *pty_name = NULL;
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt _cleanup_close_ int master = -1;
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt Machine *m = userdata;
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt int r;
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt assert(message);
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt assert(m);
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt if (m->class != MACHINE_CONTAINER)
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Opening pseudo TTYs is only supported on container machines.");
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt
e1323fbfbe8a574f28b704f2df8ce7f99e3a28f5Michal Schmidt master = openpt_in_namespace(m->leader, O_RDWR|O_NOCTTY|O_CLOEXEC);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (master < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return master;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = ptsname_malloc(master, &pty_name);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_message_new_method_return(message, &reply);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_message_append(reply, "hs", master, pty_name);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_send(NULL, reply, NULL);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt}
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidtint bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bus_error *error) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _cleanup_free_ char *pty_name = NULL, *getty = NULL;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _cleanup_bus_unref_ sd_bus *container_bus = NULL;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _cleanup_close_ int master = -1;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt Machine *m = userdata;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *p;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt char *address;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt int r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(message);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(m);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (m->class != MACHINE_CONTAINER)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Opening logins is only supported on container machines.");
8927b1dad2d4a7330174cb924090b4635a2547fbDavid Herrmann
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = bus_verify_polkit_async(
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt message,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt CAP_SYS_ADMIN,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt "org.freedesktop.machine1.login",
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt false,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt UID_INVALID,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt &m->manager->polkit_registry,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt error);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r == 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return 1; /* Will call us back */
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt master = openpt_in_namespace(m->leader, O_RDWR|O_NOCTTY|O_CLOEXEC);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (master < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return master;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = ptsname_malloc(master, &pty_name);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt p = path_startswith(pty_name, "/dev/pts/");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (!p)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PTS name %s is invalid", pty_name);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (unlockpt(master) < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return -errno;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_new(&container_bus);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt# define ADDRESS_FMT "x-machine-kernel:pid=%1$" PID_PRI ";x-machine-unix:pid=%1$" PID_PRI
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (asprintf(&address, ADDRESS_FMT, m->leader) < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return log_oom();
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt container_bus->address = address;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt container_bus->bus_client = true;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt container_bus->trusted = false;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt container_bus->is_system = true;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_start(container_bus);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt getty = strjoin("container-getty@", p, ".service", NULL);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (!getty)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return log_oom();
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_call_method(
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt container_bus,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt "org.freedesktop.systemd1",
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt "/org/freedesktop/systemd1",
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt "org.freedesktop.systemd1.Manager",
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt "StartUnit",
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt error, NULL,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt "ss", getty, "replace");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt container_bus = sd_bus_unref(container_bus);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_message_new_method_return(message, &reply);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_message_append(reply, "hs", master, pty_name);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_send(NULL, reply, NULL);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt}
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidtint bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt bool mount_slave_created = false, mount_slave_mounted = false,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt mount_tmp_created = false, mount_tmp_mounted = false,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt mount_outside_created = false, mount_outside_mounted = false;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *dest, *src;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt Machine *m = userdata;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt int read_only, make_directory;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt pid_t child;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt siginfo_t si;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt int r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(message);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(m);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (m->class != MACHINE_CONTAINER)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Bind mounting is only supported on container machines.");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_message_read(message, "ssbb", &src, &dest, &read_only, &make_directory);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (!path_is_absolute(src) || !path_is_safe(src))
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and not contain ../.");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (isempty(dest))
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt dest = src;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt else if (!path_is_absolute(dest) || !path_is_safe(dest))
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and not contain ../.");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = bus_verify_polkit_async(
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt message,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt CAP_SYS_ADMIN,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt "org.freedesktop.machine1.manage-machines",
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt false,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt UID_INVALID,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt &m->manager->polkit_registry,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt error);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r == 0)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt return 1; /* Will call us back */
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt /* One day, when bind mounting /proc/self/fd/n works across
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt * namespace boundaries we should rework this logic to make
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt * use of it... */
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt p = strjoina("/run/systemd/nspawn/propagate/", m->name, "/");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (laccess(p, F_OK) < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Container does not allow propagation of mount points.");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt /* Our goal is to install a new bind mount into the container,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt possibly read-only. This is irritatingly complex
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt unfortunately, currently.
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt First, we start by creating a private playground in /tmp,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt that we can mount MS_SLAVE. (Which is necessary, since
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt MS_MOUNT cannot be applied to mounts with MS_SHARED parent
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt mounts.) */
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (!mkdtemp(mount_slave))
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_set_errnof(error, errno, "Failed to create playground %s: %m", mount_slave);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt mount_slave_created = true;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_error_set_errnof(error, errno, "Failed to make bind mount %s: %m", mount_slave);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt goto finish;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt mount_slave_mounted = true;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_error_set_errnof(error, errno, "Failed to remount slave %s: %m", mount_slave);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt goto finish;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt /* Second, we mount the source directory to a directory inside
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt of our MS_SLAVE playground. */
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt mount_tmp = strjoina(mount_slave, "/mount");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (mkdir(mount_tmp, 0700) < 0) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount point %s: %m", mount_tmp);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt goto finish;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt mount_tmp_created = true;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (mount(src, mount_tmp, NULL, MS_BIND, NULL) < 0) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_error_set_errnof(error, errno, "Failed to overmount %s: %m", mount_tmp);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt goto finish;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt mount_tmp_mounted = true;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt /* Third, we remount the new bind mount read-only if requested. */
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (read_only)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_error_set_errnof(error, errno, "Failed to remount read-only %s: %m", mount_tmp);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt goto finish;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt /* Fourth, we move the new bind mount into the propagation
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt * directory. This way it will appear there read-only
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt * right-away. */
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt mount_outside = strjoina("/run/systemd/nspawn/propagate/", m->name, "/XXXXXX");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (!mkdtemp(mount_outside)) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_error_set_errnof(error, errno, "Cannot create propagation directory %s: %m", mount_outside);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt goto finish;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt mount_outside_created = true;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_error_set_errnof(error, errno, "Failed to move %s to %s: %m", mount_tmp, mount_outside);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt goto finish;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt mount_outside_mounted = true;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt mount_tmp_mounted = false;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt (void) rmdir(mount_tmp);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt mount_tmp_created = false;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt (void) umount(mount_slave);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt mount_slave_mounted = false;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt (void) rmdir(mount_slave);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt mount_slave_created = false;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt goto finish;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt }
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt child = fork();
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (child < 0) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt goto finish;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt }
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (child == 0) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt const char *mount_inside;
b669934fae49c9158c35e612e54e1765edca8584Thomas Hindoe Paaboel Andersen int mntfd;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt const char *q;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt q = procfs_file_alloca(m->leader, "ns/mnt");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (mntfd < 0) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen goto child_fail;
b826ab586c9e0a9c0d438a75c28cf3a8ab485929Tom Gundersen }
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (setns(mntfd, CLONE_NEWNS) < 0) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = log_error_errno(errno, "Failed to join namespace of leader: %m");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt goto child_fail;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt }
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (make_directory)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt (void) mkdir_p(dest, 0755);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt /* Fifth, move the mount to the right place inside */
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt mount_inside = strjoina("/run/systemd/nspawn/incoming/", basename(mount_outside));
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = log_error_errno(errno, "Failed to mount: %m");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt goto child_fail;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt }
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
11de3decc9357714498f96e13f1c1c2da1046811Michal Schmidt _exit(EXIT_SUCCESS);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt child_fail:
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt (void) write(errno_pipe_fd[1], &r, sizeof(r));
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _exit(EXIT_FAILURE);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt }
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = wait_for_terminate(child, &si);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r < 0) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_error_set_errnof(error, r, "Failed to wait for client: %m");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt goto finish;
ce79279bff6e7a1a17070509a039ab635796f129Michal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (si.si_code != CLD_EXITED) {
ce79279bff6e7a1a17070509a039ab635796f129Michal Schmidt r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt goto finish;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt }
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (si.si_status != EXIT_SUCCESS) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (read(errno_pipe_fd[0], &r, sizeof(r)) == sizeof(r))
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_error_set_errnof(error, r, "Failed to mount: %m");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt else
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client failed.");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt goto finish;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt }
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt r = sd_bus_reply_method_return(message, NULL);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidtfinish:
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (mount_outside_mounted)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt umount(mount_outside);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (mount_outside_created)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt rmdir(mount_outside);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (mount_tmp_mounted)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt umount(mount_tmp);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (mount_tmp_created)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt rmdir(mount_tmp);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (mount_slave_mounted)
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt umount(mount_slave);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (mount_slave_created)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt rmdir(mount_slave);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt}
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidtstatic int machine_operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt MachineOperation *o = userdata;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt int r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(o);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(si);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt o->pid = 0;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (si->si_code != CLD_EXITED) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt goto fail;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (si->si_status != EXIT_SUCCESS) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (read(o->errno_fd, &r, sizeof(r)) == sizeof(r))
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_error_set_errnof(&error, r, "%m");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt else
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Client failed.");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt goto fail;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_reply_method_return(o->message, NULL);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt log_error_errno(r, "Failed to reply to message: %m");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt machine_operation_unref(o);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return 0;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidtfail:
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_reply_method_error(o->message, &error);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt log_error_errno(r, "Failed to reply to message: %m");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt machine_operation_unref(o);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return 0;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt}
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidtint bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_error *error) {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt const char *src, *dest, *host_path, *container_path, *host_basename, *host_dirname, *container_basename, *container_dirname;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt _cleanup_close_ int hostfd = -1;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt Machine *m = userdata;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt MachineOperation *o;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt bool copy_from;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt pid_t child;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt char *t;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt int r;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(message);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt assert(m);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (m->n_operations >= MACHINE_OPERATIONS_MAX)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing copies.");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (m->class != MACHINE_CONTAINER)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Copying files is only supported on container machines.");
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt r = sd_bus_message_read(message, "ss", &src, &dest);
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt if (r < 0)
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt return r;
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt if (!path_is_absolute(src))
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute.");
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt if (isempty(dest))
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt dest = src;
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt else if (!path_is_absolute(dest))
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute.");
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt r = bus_verify_polkit_async(
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt message,
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt CAP_SYS_ADMIN,
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt "org.freedesktop.machine1.manage-machines",
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt false,
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt UID_INVALID,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt &m->manager->polkit_registry,
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt error);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (r < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return r;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (r == 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return 1; /* Will call us back */
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt copy_from = strstr(sd_bus_message_get_member(message), "CopyFrom");
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt if (copy_from) {
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt container_path = src;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt host_path = dest;
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt } else {
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt host_path = src;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt container_path = dest;
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt }
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt host_basename = basename(host_path);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt t = strdupa(host_path);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt host_dirname = dirname(t);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt container_basename = basename(container_path);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt t = strdupa(container_path);
9ba81d5a61b7c992a1d2e5e02f334b8e2a0b0c22Michal Schmidt container_dirname = dirname(t);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt hostfd = open(host_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (hostfd < 0)
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt return sd_bus_error_set_errnof(error, errno, "Failed to open host directory %s: %m", host_dirname);
8f88aed740ded77af443bb1b7c79bb229b50f8f8Michal Schmidt
32a4456cc252689f51f383d150d34ed636bfec4dMichal Schmidt if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
child = fork();
if (child < 0)
return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
if (child == 0) {
int containerfd;
const char *q;
int mntfd;
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
q = procfs_file_alloca(m->leader, "ns/mnt");
mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
if (mntfd < 0) {
r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
goto child_fail;
}
if (setns(mntfd, CLONE_NEWNS) < 0) {
r = log_error_errno(errno, "Failed to join namespace of leader: %m");
goto child_fail;
}
containerfd = open(container_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
if (containerfd < 0) {
r = log_error_errno(errno, "Failed top open destination directory: %m");
goto child_fail;
}
if (copy_from)
r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, true);
else
r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, true);
hostfd = safe_close(hostfd);
containerfd = safe_close(containerfd);
if (r < 0) {
r = log_error_errno(r, "Failed to copy tree: %m");
goto child_fail;
}
_exit(EXIT_SUCCESS);
child_fail:
(void) write(errno_pipe_fd[1], &r, sizeof(r));
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
_exit(EXIT_FAILURE);
}
errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
/* Copying might take a while, hence install a watch the
* child, and return */
o = new0(MachineOperation, 1);
if (!o)
return log_oom();
o->pid = child;
o->message = sd_bus_message_ref(message);
o->errno_fd = errno_pipe_fd[0];
errno_pipe_fd[0] = -1;
r = sd_event_add_child(m->manager->event, &o->event_source, child, WEXITED, machine_operation_done, o);
if (r < 0) {
machine_operation_unref(o);
return log_oom();
}
LIST_PREPEND(operations, m->operations, o);
m->n_operations++;
o->machine = m;
return 1;
}
const sd_bus_vtable machine_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Id", "ay", property_get_id, 0, SD_BUS_VTABLE_PROPERTY_CONST),
BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Machine, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Machine, service), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Unit", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
SD_BUS_PROPERTY("Leader", "u", NULL, offsetof(Machine, leader), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("NetworkInterfaces", "ai", property_get_netif, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
SD_BUS_METHOD("Terminate", NULL, NULL, bus_machine_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Kill", "si", NULL, bus_machine_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetAddresses", NULL, "a(iay)", bus_machine_method_get_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_machine_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("OpenPTY", NULL, "hs", bus_machine_method_open_pty, 0),
SD_BUS_METHOD("OpenLogin", NULL, "hs", bus_machine_method_open_login, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("BindMount", "ssbb", NULL, bus_machine_method_bind_mount, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CopyFrom", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CopyTo", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
};
int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
Manager *m = userdata;
Machine *machine;
int r;
assert(bus);
assert(path);
assert(interface);
assert(found);
assert(m);
if (streq(path, "/org/freedesktop/machine1/machine/self")) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
sd_bus_message *message;
pid_t pid;
message = sd_bus_get_current_message(bus);
if (!message)
return 0;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
if (r < 0)
return r;
r = sd_bus_creds_get_pid(creds, &pid);
if (r < 0)
return r;
r = manager_get_machine_by_pid(m, pid, &machine);
if (r <= 0)
return 0;
} else {
_cleanup_free_ char *e = NULL;
const char *p;
p = startswith(path, "/org/freedesktop/machine1/machine/");
if (!p)
return 0;
e = bus_label_unescape(p);
if (!e)
return -ENOMEM;
machine = hashmap_get(m->machines, e);
if (!machine)
return 0;
}
*found = machine;
return 1;
}
char *machine_bus_path(Machine *m) {
_cleanup_free_ char *e = NULL;
assert(m);
e = bus_label_escape(m->name);
if (!e)
return NULL;
return strappend("/org/freedesktop/machine1/machine/", e);
}
int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
_cleanup_strv_free_ char **l = NULL;
Machine *machine = NULL;
Manager *m = userdata;
Iterator i;
int r;
assert(bus);
assert(path);
assert(nodes);
HASHMAP_FOREACH(machine, m->machines, i) {
char *p;
p = machine_bus_path(machine);
if (!p)
return -ENOMEM;
r = strv_consume(&l, p);
if (r < 0)
return r;
}
*nodes = l;
l = NULL;
return 1;
}
int machine_send_signal(Machine *m, bool new_machine) {
_cleanup_free_ char *p = NULL;
assert(m);
p = machine_bus_path(m);
if (!p)
return -ENOMEM;
return sd_bus_emit_signal(
m->manager->bus,
"/org/freedesktop/machine1",
"org.freedesktop.machine1.Manager",
new_machine ? "MachineNew" : "MachineRemoved",
"so", m->name, p);
}
int machine_send_create_reply(Machine *m, sd_bus_error *error) {
_cleanup_bus_message_unref_ sd_bus_message *c = NULL;
_cleanup_free_ char *p = NULL;
assert(m);
if (!m->create_message)
return 0;
c = m->create_message;
m->create_message = NULL;
if (error)
return sd_bus_reply_method_error(c, error);
/* Update the machine state file before we notify the client
* about the result. */
machine_save(m);
p = machine_bus_path(m);
if (!p)
return -ENOMEM;
return sd_bus_reply_method_return(c, "o", p);
}