]> git.ipfire.org Git - pakfire.git/commitdiff
jail: Make the client process wait until the parent has finished initialization
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 2 Aug 2022 11:07:47 +0000 (11:07 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 2 Aug 2022 11:07:47 +0000 (11:07 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/jail.c

index e4b4798d284d85f194a926b65399dbb5f23a66b7..305a912ab387864a048711c4498c75f382ded089 100644 (file)
@@ -24,6 +24,7 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <syscall.h>
+#include <sys/eventfd.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
@@ -284,10 +285,32 @@ static int pakfire_jail_setup_gid_mapping(struct pakfire_jail* jail, pid_t pid)
        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
@@ -300,14 +323,29 @@ static int pakfire_jail_parent(struct pakfire_jail* jail, pid_t pid) {
        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;
 }
 
@@ -317,6 +355,16 @@ int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[]) {
 
        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 =
@@ -337,12 +385,12 @@ int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[]) {
 
        // 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;
 
@@ -369,6 +417,5 @@ int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[]) {
        return exit;
 
 ERROR:
-
        return -1;
 }