#include <signal.h>
#include <stdlib.h>
#include <syscall.h>
+#include <sys/eventfd.h>
#include <sys/types.h>
#include <sys/wait.h>
return pakfire_jail_write_uidgid_mapping(jail, path, mapped_gid, length);
}
+static int pakfire_jail_send_signal(struct pakfire_jail* jail, int fd) {
+ const int val = 1;
+
+ DEBUG(jail->pakfire, "Sending signal...\n");
+
+ write(fd, &val, sizeof(val));
+ close(fd);
+
+ return 0;
+}
+
+static int pakfire_jail_wait_for_signal(struct pakfire_jail* jail, int fd) {
+ int val = 0;
+
+ DEBUG(jail->pakfire, "Waiting for signal...\n");
+
+ read(fd, &val, sizeof(val));
+ close(fd);
+
+ return 0;
+}
+
/*
Performs the initialisation that needs to happen in the parent part
*/
-static int pakfire_jail_parent(struct pakfire_jail* jail, pid_t pid) {
+static int pakfire_jail_parent(struct pakfire_jail* jail, pid_t pid, int completed_fd) {
int r;
// Setup UID mapping
if (r)
return r;
+ // Parent has finished initialisation
+ DEBUG(jail->pakfire, "Parent has finished initialization\n");
+
+ // Send signal to client
+ r = pakfire_jail_send_signal(jail, completed_fd);
+ if (r)
+ return r;
+
return 0;
}
-static int pakfire_jail_child(struct pakfire_jail* jail, const char* argv[]) {
+static int pakfire_jail_child(struct pakfire_jail* jail, const char* argv[], int completed_fd) {
+ int r;
+
// XXX do we have to reconfigure logging here?
DEBUG(jail->pakfire, "Launched child process in jail with PID %d\n", getpid());
+ // Wait for the parent to finish initialization
+ r = pakfire_jail_wait_for_signal(jail, completed_fd);
+ if (r)
+ return r;
+
return 0;
}
DEBUG(jail->pakfire, "Executing jail...\n");
+ /*
+ Setup a file descriptor which can be used to notify the client that the parent
+ has completed configuration.
+ */
+ int completed_fd = eventfd(0, EFD_CLOEXEC);
+ if (completed_fd < 0) {
+ ERROR(jail->pakfire, "eventfd() failed: %m\n");
+ return -1;
+ }
+
// Configure child process
struct clone_args args = {
.flags =
// Child process
} else if (pid == 0) {
- r = pakfire_jail_child(jail, argv);
+ r = pakfire_jail_child(jail, argv, completed_fd);
_exit(r);
}
// Parent process
- r = pakfire_jail_parent(jail, pid);
+ r = pakfire_jail_parent(jail, pid, completed_fd);
if (r)
goto ERROR;
return exit;
ERROR:
-
return -1;
}