machine-dbus.c revision 385080c09e48ea62a80525197f66f3347d96d2ce
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2011 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/* When we include libgen.h because we need dirname() we immediately
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * undefine basename() since libgen.h defines it as a macro to the POSIX
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * version which is really broken. We prefer GNU basename(). */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return sd_bus_message_append_array(reply, 'y', &m->id, 16);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering state = machine_state_to_string(machine_get_state(m));
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering r = sd_bus_message_append_basic(reply, 's', state);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert_cc(sizeof(int) == sizeof(int32_t));
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering return sd_bus_message_append_array(reply, 'i', m->netif, m->n_netif * sizeof(int));
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringstatic BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poetteringint bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering "org.freedesktop.machine1.manage-machines",
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return sd_bus_reply_method_return(message, NULL);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringint bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering r = sd_bus_message_read(message, "si", &swho, &signo);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering "org.freedesktop.machine1.manage-machines",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return sd_bus_reply_method_return(message, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "(iay)");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering n = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (a = addresses, i = 0; i < n; a++, i++) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = sd_bus_message_open_container(reply, 'r', "iay");
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = sd_bus_message_append(reply, "i", addresses[i].family);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = sd_bus_message_append_array(reply, 'y', &addresses[i].address, FAMILY_ADDRESS_SIZE(addresses[i].family));
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = sd_bus_message_close_container(reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_close_pair_ int pair[2] = { -1, -1 };
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering _cleanup_free_ char *us = NULL, *them = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *p;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = readlink_malloc("/proc/self/ns/net", &us);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering p = procfs_file_alloca(m->leader, "ns/net");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = namespace_open(m->leader, NULL, NULL, &netns_fd, NULL, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ struct local_address *addresses = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = namespace_enter(-1, -1, netns_fd, -1, -1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering n = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (a = addresses, i = 0; i < n; a++, i++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering { .iov_base = &a->family, .iov_len = sizeof(a->family) },
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering { .iov_base = &a->address, .iov_len = FAMILY_ADDRESS_SIZE(a->family) },
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering iov[0] = (struct iovec) { .iov_base = &family, .iov_len = sizeof(family) };
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering iov[1] = (struct iovec) { .iov_base = &in_addr, .iov_len = sizeof(in_addr) };
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering r = sd_bus_message_open_container(reply, 'r', "iay");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_message_append(reply, "i", family);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (n != sizeof(struct in_addr) + sizeof(family))
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering r = sd_bus_message_append_array(reply, 'y', &in_addr.in, sizeof(in_addr.in));
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (n != sizeof(struct in6_addr) + sizeof(family))
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = sd_bus_message_append_array(reply, 'y', &in_addr.in6, sizeof(in_addr.in6));
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = sd_bus_message_close_container(reply);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return sd_bus_error_set_errnof(error, r, "Failed to wait for client: %m");
8d90c8a8d6867ffcfb61a11b73205cd7b1a72f3aLennart Poettering if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
8d90c8a8d6867ffcfb61a11b73205cd7b1a72f3aLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting IP address data is only supported on container machines.");
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = sd_bus_message_close_container(reply);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringint bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering char **k, **v;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = load_env_file_pairs(NULL, "/etc/os-release", NULL, &l);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_close_ int mntns_fd = -1, root_fd = -1;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering _cleanup_close_pair_ int pair[2] = { -1, -1 };
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = namespace_open(m->leader, NULL, &mntns_fd, NULL, NULL, &root_fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = namespace_enter(-1, mntns_fd, -1, -1, root_fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fd = open("/etc/os-release", O_RDONLY|O_CLOEXEC);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering fd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = copy_bytes(fd, pair[1], (off_t) -1, false);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = load_env_file_pairs(f, "/etc/os-release", NULL, &l);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return sd_bus_error_set_errnof(error, r, "Failed to wait for client: %m");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting OS release data is only supported on container machines.");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "{ss}");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = sd_bus_message_append(reply, "{ss}", *k, *v);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = sd_bus_message_close_container(reply);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringint bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-open-pty" : "org.freedesktop.machine1.open-pty",
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering r = ptsname_namespace(master, &pty_name);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = sd_bus_message_append(reply, "hs", master, pty_name);
40205d706e1210763ff4c98a317556375bd04bcdLennart Poetteringstatic int container_bus_new(Machine *m, sd_bus_error *error, sd_bus **ret) {
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering if (asprintf(&address, "x-machine-kernel:pid=%1$" PID_PRI ";x-machine-unix:pid=%1$" PID_PRI, m->leader) < 0)
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering return sd_bus_error_set_errnof(error, r, "There is no system bus in container %s.", m->name);
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poetteringint bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bus_error *error) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering _cleanup_bus_flush_close_unref_ sd_bus *allocated_bus = NULL;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering const char *p, *getty;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-login" : "org.freedesktop.machine1.login",
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = ptsname_namespace(master, &pty_name);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering p = path_startswith(pty_name, "/dev/pts/");
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PTS name %s is invalid", pty_name);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = container_bus_new(m, error, &allocated_bus);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering container_bus = allocated_bus ?: m->manager->bus;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering getty = strjoina("container-getty@", p, ".service");
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering "org.freedesktop.systemd1.Manager",
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = sd_bus_message_append(reply, "hs", master, pty_name);
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poetteringint bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bus_error *error) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *tm = NULL;
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering _cleanup_bus_flush_close_unref_ sd_bus *allocated_bus = NULL;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering _cleanup_strv_free_ char **env = NULL, **args = NULL;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering const char *p, *unit, *user, *path, *description, *utmp_id;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = sd_bus_message_read(message, "ss", &user, &path);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified path '%s' is not absolute", path);
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering r = sd_bus_message_read_strv(message, &args);
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering args[0][0] = '-'; /* Tell /bin/sh that this shall be a login shell */
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = sd_bus_message_read_strv(message, &env);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-shell" : "org.freedesktop.machine1.shell",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC);
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering r = ptsname_namespace(master, &pty_name);
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering p = path_startswith(pty_name, "/dev/pts/");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PTS name %s is invalid", pty_name);
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering utmp_id = path_startswith(pty_name, "/dev/");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = container_bus_new(m, error, &allocated_bus);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering container_bus = allocated_bus ?: m->manager->bus;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "org.freedesktop.systemd1.Manager",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering "StartTransientUnit");
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering /* Name and mode */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering unit = strjoina("container-shell@", p, ".service", NULL);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_message_append(tm, "ss", unit, "fail");
554604b3073467af75dc94fac9e2343148603289Lennart Poettering /* Properties */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_message_open_container(tm, 'a', "(sv)");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering description = strjoina("Shell for User ", isempty(user) ? "root" : user);
554604b3073467af75dc94fac9e2343148603289Lennart Poettering "(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_message_append(tm, "(sv)", "User", "s", isempty(user) ? "root" : user);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_message_open_container(tm, 'r', "sv");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_message_append(tm, "s", "Environment");
554604b3073467af75dc94fac9e2343148603289Lennart Poettering r = sd_bus_message_open_container(tm, 'v', "as");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Exec container */
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering r = sd_bus_message_open_container(tm, 'r', "sv");
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering r = sd_bus_message_append(tm, "s", "ExecStart");
554604b3073467af75dc94fac9e2343148603289Lennart Poettering r = sd_bus_message_open_container(tm, 'v', "a(sasb)");
554604b3073467af75dc94fac9e2343148603289Lennart Poettering r = sd_bus_message_open_container(tm, 'a', "(sasb)");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_open_container(tm, 'r', "sasb");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_append(tm, "s", path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_append_strv(tm, args);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_append(tm, "b", true);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Auxiliary units */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_message_append(tm, "a(sa(sv))", 0);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_call(container_bus, tm, 0, error, NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
554604b3073467af75dc94fac9e2343148603289Lennart Poettering r = sd_bus_message_append(reply, "hs", master, pty_name);
554604b3073467af75dc94fac9e2343148603289Lennart Poetteringint bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error) {
554604b3073467af75dc94fac9e2343148603289Lennart Poettering _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
554604b3073467af75dc94fac9e2343148603289Lennart Poettering char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering bool mount_slave_created = false, mount_slave_mounted = false,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering mount_tmp_created = false, mount_tmp_mounted = false,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering mount_outside_created = false, mount_outside_mounted = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Bind mounting is only supported on container machines.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_message_read(message, "ssbb", &src, &dest, &read_only, &make_directory);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!path_is_absolute(src) || !path_is_safe(src))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and not contain ../.");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else if (!path_is_absolute(dest) || !path_is_safe(dest))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and not contain ../.");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering "org.freedesktop.machine1.manage-machines",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* One day, when bind mounting /proc/self/fd/n works across
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * namespace boundaries we should rework this logic to make
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * use of it... */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering p = strjoina("/run/systemd/nspawn/propagate/", m->name, "/");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Container does not allow propagation of mount points.");
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering /* Our goal is to install a new bind mount into the container,
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering possibly read-only. This is irritatingly complex
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering unfortunately, currently.
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering First, we start by creating a private playground in /tmp,
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering that we can mount MS_SLAVE. (Which is necessary, since
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering MS_MOUNT cannot be applied to mounts with MS_SHARED parent
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return sd_bus_error_set_errnof(error, errno, "Failed to create playground %s: %m", mount_slave);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_error_set_errnof(error, errno, "Failed to make bind mount %s: %m", mount_slave);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_error_set_errnof(error, errno, "Failed to remount slave %s: %m", mount_slave);
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering /* Second, we mount the source directory to a directory inside
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering of our MS_SLAVE playground. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mount_tmp = strjoina(mount_slave, "/mount");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount point %s: %m", mount_tmp);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (mount(src, mount_tmp, NULL, MS_BIND, NULL) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_error_set_errnof(error, errno, "Failed to overmount %s: %m", mount_tmp);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Third, we remount the new bind mount read-only if requested. */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_error_set_errnof(error, errno, "Failed to remount read-only %s: %m", mount_tmp);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Fourth, we move the new bind mount into the propagation
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * directory. This way it will appear there read-only
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * right-away. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering mount_outside = strjoina("/run/systemd/nspawn/propagate/", m->name, "/XXXXXX");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = sd_bus_error_set_errnof(error, errno, "Cannot create propagation directory %s: %m", mount_outside);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_error_set_errnof(error, errno, "Failed to move %s to %s: %m", mount_tmp, mount_outside);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering q = procfs_file_alloca(m->leader, "ns/mnt");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = log_error_errno(errno, "Failed to join namespace of leader: %m");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* Fifth, move the mount to the right place inside */
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek mount_inside = strjoina("/run/systemd/nspawn/incoming/", basename(mount_outside));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = log_error_errno(errno, "Failed to mount: %m");
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (r < 0) {
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers r = sd_bus_error_set_errnof(error, r, "Failed to wait for client: %m");
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (read(errno_pipe_fd[0], &r, sizeof(r)) == sizeof(r))
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers r = sd_bus_error_set_errnof(error, r, "Failed to mount: %m");
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client failed.");
if (mount_slave_mounted)
if (mount_slave_created)
assert(o);
o->pid = 0;
goto fail;
goto fail;
fail:
const char *src, *dest, *host_path, *container_path, *host_basename, *host_dirname, *container_basename, *container_dirname;
MachineOperation *o;
bool copy_from;
assert(m);
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Copying files is only supported on container machines.");
NULL,
error);
if (copy_from) {
if (hostfd < 0)
if (child < 0)
if (child == 0) {
int containerfd;
int mntfd;
if (mntfd < 0) {
goto child_fail;
goto child_fail;
if (containerfd < 0) {
goto child_fail;
if (copy_from)
goto child_fail;
return log_oom();
r = sd_event_add_child(m->manager->event, &o->event_source, child, WEXITED, machine_operation_done, o);
return log_oom();
m->n_operations++;
o->machine = m;
BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Machine, timestamp), 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("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_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("OpenShell", "ssasas", "hs", bus_machine_method_open_shell, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("BindMount", "ssbb", NULL, bus_machine_method_bind_mount, SD_BUS_VTABLE_UNPRIVILEGED),
int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
assert(m);
if (!message)
e = bus_label_unescape(p);
return -ENOMEM;
if (!machine)
assert(m);
return NULL;
int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
Iterator i;
return -ENOMEM;
r = strv_consume(&l, p);
*nodes = l;
l = NULL;
assert(m);
p = machine_bus_path(m);
return -ENOMEM;
return sd_bus_emit_signal(
"/org/freedesktop/machine1",
assert(m);
if (!m->create_message)
c = m->create_message;
if (error)
machine_save(m);
p = machine_bus_path(m);
return -ENOMEM;