/* SPDX-License-Identifier: LGPL-2.1+ */
-/***
- This file is part of systemd.
-
- Copyright 2011 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
#include <errno.h>
#include <string.h>
#include "bus-label.h"
#include "bus-util.h"
#include "copy.h"
+#include "env-file.h"
#include "env-util.h"
#include "fd-util.h"
-#include "fileio.h"
#include "format-util.h"
#include "fs-util.h"
#include "in-addr-util.h"
+#include "io-util.h"
#include "local-addresses.h"
#include "machine-dbus.h"
#include "machine.h"
+#include "missing_capability.h"
#include "mkdir.h"
+#include "namespace-util.h"
+#include "os-util.h"
#include "path-util.h"
#include "process-util.h"
#include "signal-util.h"
#include "strv.h"
#include "terminal-util.h"
+#include "tmpfile-util.h"
#include "user-util.h"
-static int property_get_state(
- sd_bus *bus,
- const char *path,
- const char *interface,
- const char *property,
- sd_bus_message *reply,
- void *userdata,
- sd_bus_error *error) {
-
- Machine *m = userdata;
- const char *state;
- int r;
-
- assert(bus);
- assert(reply);
- assert(m);
-
- state = machine_state_to_string(machine_get_state(m));
-
- r = sd_bus_message_append_basic(reply, 's', state);
- if (r < 0)
- return r;
-
- return 1;
-}
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
+static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", Machine, machine_get_state, machine_state_to_string);
static int property_get_netif(
sd_bus *bus,
return sd_bus_message_append_array(reply, 'i', m->netif, m->n_netif * sizeof(int));
}
-static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
-
int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Machine *m = userdata;
int r;
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
return -errno;
- r = safe_fork("(sd-addr)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
+ r = namespace_fork("(sd-addrns)", "(sd-addr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
+ -1, -1, netns_fd, -1, -1, &child);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
if (r == 0) {
pair[0] = safe_close(pair[0]);
- r = namespace_enter(-1, -1, netns_fd, -1, -1);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
n = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
if (n < 0)
_exit(EXIT_FAILURE);
.msg_iovlen = 2,
};
- iov[0] = (struct iovec) { .iov_base = &family, .iov_len = sizeof(family) };
- iov[1] = (struct iovec) { .iov_base = &in_addr, .iov_len = sizeof(in_addr) };
+ iov[0] = IOVEC_MAKE(&family, sizeof(family));
+ iov[1] = IOVEC_MAKE(&in_addr, sizeof(in_addr));
n = recvmsg(pair[0], &mh, 0);
if (n < 0)
return r;
}
- r = wait_for_terminate_and_check("(sd-addr)", child, 0);
+ r = wait_for_terminate_and_check("(sd-addrns)", child, 0);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
if (r != EXIT_SUCCESS)
switch (m->class) {
case MACHINE_HOST:
- r = load_env_file_pairs(NULL, "/etc/os-release", NULL, &l);
+ r = load_os_release_pairs(NULL, &l);
if (r < 0)
return r;
break;
case MACHINE_CONTAINER: {
- _cleanup_close_ int mntns_fd = -1, root_fd = -1;
+ _cleanup_close_ int mntns_fd = -1, root_fd = -1, pidns_fd = -1;
_cleanup_close_pair_ int pair[2] = { -1, -1 };
_cleanup_fclose_ FILE *f = NULL;
pid_t child;
- r = namespace_open(m->leader, NULL, &mntns_fd, NULL, NULL, &root_fd);
+ r = namespace_open(m->leader, &pidns_fd, &mntns_fd, NULL, NULL, &root_fd);
if (r < 0)
return r;
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
return -errno;
- r = safe_fork("(sd-osrel)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
+ r = namespace_fork("(sd-osrelns)", "(sd-osrel)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
+ pidns_fd, mntns_fd, -1, -1, root_fd,
+ &child);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
if (r == 0) {
pair[0] = safe_close(pair[0]);
- r = namespace_enter(-1, mntns_fd, -1, -1, root_fd);
+ r = open_os_release(NULL, NULL, &fd);
+ if (r == -ENOENT)
+ _exit(EXIT_NOT_FOUND);
if (r < 0)
_exit(EXIT_FAILURE);
- fd = open("/etc/os-release", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0 && errno == ENOENT) {
- fd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC|O_NOCTTY);
- if (fd < 0 && errno == ENOENT)
- _exit(EXIT_NOT_FOUND);
- }
- if (fd < 0)
- _exit(EXIT_FAILURE);
-
r = copy_bytes(fd, pair[1], (uint64_t) -1, 0);
if (r < 0)
_exit(EXIT_FAILURE);
pair[1] = safe_close(pair[1]);
- f = fdopen(pair[0], "re");
+ f = fdopen(pair[0], "r");
if (!f)
return -errno;
pair[0] = -1;
- r = load_env_file_pairs(f, "/etc/os-release", NULL, &l);
+ r = load_env_file_pairs(f, "/etc/os-release", &l);
if (r < 0)
return r;
- r = wait_for_terminate_and_check("(sd-osrel)", child, 0);
+ r = wait_for_terminate_and_check("(sd-osrelns)", child, 0);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
if (r == EXIT_NOT_FOUND)
if (r == 0)
return 1; /* Will call us back */
- master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC);
+ master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name);
if (master < 0)
return master;
- r = ptsname_namespace(master, &pty_name);
- if (r < 0)
- return r;
-
r = sd_bus_message_new_method_return(message, &reply);
if (r < 0)
return r;
break;
case MACHINE_CONTAINER: {
- _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
+ _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL;
char *address;
r = sd_bus_new(&bus);
if (r < 0)
return r;
- *ret = bus;
- bus = NULL;
+ *ret = TAKE_PTR(bus);
break;
}
if (r == 0)
return 1; /* Will call us back */
- master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC);
+ master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name);
if (master < 0)
return master;
- r = ptsname_namespace(master, &pty_name);
- if (r < 0)
- return r;
-
p = path_startswith(pty_name, "/dev/pts/");
- if (!p)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PTS name %s is invalid", pty_name);
+ assert(p);
r = container_bus_new(m, error, &allocated_bus);
if (r < 0)
} else {
if (!path_is_absolute(path))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified path '%s' is not absolute", path);
- args = args_wire;
- args_wire = NULL;
+ args = TAKE_PTR(args_wire);
if (strv_isempty(args)) {
args = strv_free(args);
- args = strv_new(path, NULL);
+ args = strv_new(path);
if (!args)
return -ENOMEM;
}
if (r == 0)
return 1; /* Will call us back */
- master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC);
+ master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC, &pty_name);
if (master < 0)
return master;
- r = ptsname_namespace(master, &pty_name);
- if (r < 0)
- return r;
-
p = path_startswith(pty_name, "/dev/pts/");
assert(p);
}
int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_error *error) {
- const char *src, *dest, *host_path, *container_path, *host_basename, *host_dirname, *container_basename, *container_dirname;
+ const char *src, *dest, *host_path, *container_path, *host_basename, *container_basename, *container_dirname;
_cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
CopyFlags copy_flags = COPY_REFLINK|COPY_MERGE;
_cleanup_close_ int hostfd = -1;
}
host_basename = basename(host_path);
- t = strdupa(host_path);
- host_dirname = dirname(t);
container_basename = basename(container_path);
t = strdupa(container_path);
container_dirname = dirname(t);
- hostfd = open(host_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
+ hostfd = open_parent(host_path, O_CLOEXEC, 0);
if (hostfd < 0)
- return sd_bus_error_set_errnof(error, errno, "Failed to open host directory %s: %m", host_dirname);
+ return sd_bus_error_set_errnof(error, hostfd, "Failed to open host directory %s: %m", host_path);
if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
return -errno;
- r = safe_fork("(sd-openroot)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
+ r = namespace_fork("(sd-openrootns)", "(sd-openroot)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
+ -1, mntns_fd, -1, -1, root_fd, &child);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
if (r == 0) {
pair[0] = safe_close(pair[0]);
- r = namespace_enter(-1, mntns_fd, -1, -1, root_fd);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
dfd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
if (dfd < 0)
_exit(EXIT_FAILURE);
pair[1] = safe_close(pair[1]);
- r = wait_for_terminate_and_check("(sd-openroot)", child, 0);
+ r = wait_for_terminate_and_check("(sd-openrootns)", child, 0);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
if (r != EXIT_SUCCESS)
if (!m->create_message)
return 0;
- c = m->create_message;
- m->create_message = NULL;
+ c = TAKE_PTR(m->create_message);
if (error)
return sd_bus_reply_method_error(c, error);