On kdbus user credentials are not translated across PID namespaces, but
simply invalidated if sender and receiver namespaces don't match. This
makes it impossible to properly authenticate requests from different PID
namespaces (which is probably a good thing). Hence, register the machine
in the parent and not the client and properly synchronize this.
#include <sys/un.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <linux/netlink.h>
+#include <sys/eventfd.h>
#include "sd-daemon.h"
#include "sd-bus.h"
#include "sd-daemon.h"
#include "sd-bus.h"
return capability_bounding_set_drop(~arg_retain, false);
}
return capability_bounding_set_drop(~arg_retain, false);
}
-static int register_machine(void) {
+static int register_machine(pid_t pid) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_unref_ sd_bus *bus = NULL;
int r;
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_unref_ sd_bus *bus = NULL;
int r;
SD_BUS_MESSAGE_APPEND_ID128(arg_uuid),
"nspawn",
"container",
SD_BUS_MESSAGE_APPEND_ID128(arg_uuid),
"nspawn",
"container",
strempty(arg_directory),
!isempty(arg_slice), "Slice", "s", arg_slice);
if (r < 0) {
strempty(arg_directory),
!isempty(arg_slice), "Slice", "s", arg_slice);
if (r < 0) {
int main(int argc, char *argv[]) {
pid_t pid = 0;
int r = EXIT_FAILURE, k;
int main(int argc, char *argv[]) {
pid_t pid = 0;
int r = EXIT_FAILURE, k;
- _cleanup_close_ int master = -1, kdbus_fd = -1;
+ _cleanup_close_ int master = -1, kdbus_fd = -1, sync_fd = -1;
int n_fd_passed;
const char *console = NULL;
sigset_t mask;
int n_fd_passed;
const char *console = NULL;
sigset_t mask;
log_debug("Successfully created kdbus namespace as %s", kdbus_namespace);
if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) {
log_debug("Successfully created kdbus namespace as %s", kdbus_namespace);
if (socketpair(AF_UNIX, SOCK_DGRAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, kmsg_socket_pair) < 0) {
- log_error("Failed to create kmsg socket pair.");
+ log_error("Failed to create kmsg socket pair: %m");
+ goto finish;
+ }
+
+ sync_fd = eventfd(0, EFD_CLOEXEC);
+ if (sync_fd < 0) {
+ log_error("Failed to create event fd: %m");
envp[n_env] = strv_find_prefix(environ, "TERM=");
if (envp[n_env])
envp[n_env] = strv_find_prefix(environ, "TERM=");
if (envp[n_env])
- r = register_machine();
- if (r < 0)
- goto finish;
-
/* Mark everything as slave, so that we still
* receive mounts from the real root, but don't
* propagate mounts to the real root. */
/* Mark everything as slave, so that we still
* receive mounts from the real root, but don't
* propagate mounts to the real root. */
+ eventfd_read(sync_fd, &x);
+ close_nointr_nofail(sync_fd);
+ sync_fd = -1;
+
if (!strv_isempty(arg_setenv)) {
char **n;
if (!strv_isempty(arg_setenv)) {
char **n;
fdset_free(fds);
fds = NULL;
fdset_free(fds);
fds = NULL;
+ r = register_machine(pid);
+ if (r < 0)
+ goto finish;
+
+ eventfd_write(sync_fd, 1);
+ close_nointr_nofail(sync_fd);
+ sync_fd = -1;
+
k = process_pty(master, &mask, arg_boot ? pid : 0, SIGRTMIN+3);
if (k < 0) {
r = EXIT_FAILURE;
k = process_pty(master, &mask, arg_boot ? pid : 0, SIGRTMIN+3);
if (k < 0) {
r = EXIT_FAILURE;