]> git.ipfire.org Git - pakfire.git/commitdiff
jail: Bring back the UNIX domain socket between child/parent
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 8 Dec 2023 15:29:45 +0000 (15:29 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 8 Dec 2023 15:29:45 +0000 (15:29 +0000)
We will need this later to pass around file descriptors.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/libpakfire/jail.c

index 5cc1dd753d366f1e62688e3705ad74073f375389..5d091c58c7dc5f699033fb59ceb2629c284b8ecf 100644 (file)
@@ -132,6 +132,9 @@ struct pakfire_jail_exec {
        pid_t pid;
        int pidfd;
 
+       // Socket to pass FDs
+       int socket[2];
+
        // Process status (from waitid)
        siginfo_t status;
 
@@ -679,6 +682,67 @@ static int pakfire_jail_stream_stdin(struct pakfire_jail* jail,
        return r;
 }
 
+static int pakfire_jail_recv_fd(struct pakfire_jail* jail, int socket, int* fd) {
+       const size_t payload_length = sizeof(fd);
+       char buffer[CMSG_SPACE(payload_length)];
+       int r;
+
+       struct msghdr msg = {
+               .msg_control    = buffer,
+               .msg_controllen = sizeof(buffer),
+       };
+
+       // Receive the message
+       r = recvmsg(socket, &msg, 0);
+       if (r) {
+               CTX_ERROR(jail->ctx, "Could not receive file descriptor: %s\n", strerror(errno));
+               return -errno;
+       }
+
+       // Fetch the payload
+       struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
+       if (!cmsg)
+               return -EBADMSG;
+
+       *fd = *((int*)CMSG_DATA(cmsg));
+
+       CTX_DEBUG(jail->ctx, "Received fd %d from socket %d\n", *fd, socket);
+
+       return 0;
+}
+
+static int pakfire_jail_send_fd(struct pakfire_jail* jail, int socket, int fd) {
+       const size_t payload_length = sizeof(fd);
+       char buffer[CMSG_SPACE(payload_length)];
+       int r;
+
+       CTX_DEBUG(jail->ctx, "Sending fd %d to socket %d\n", fd, socket);
+
+       // Header
+       struct msghdr msg = {
+               .msg_control    = buffer,
+               .msg_controllen = sizeof(buffer),
+       };
+
+       // Payload
+       struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
+       cmsg->cmsg_level = SOL_SOCKET;
+       cmsg->cmsg_type  = SCM_RIGHTS;
+       cmsg->cmsg_len   = CMSG_LEN(payload_length);
+
+       // Set payload
+       *((int*)CMSG_DATA(cmsg)) = fd;
+
+       // Send the message
+       r = sendmsg(socket, &msg, 0);
+       if (r) {
+               CTX_ERROR(jail->ctx, "Could not send file descriptor: %s\n", strerror(errno));
+               return -errno;
+       }
+
+       return 0;
+}
+
 static int pakfire_jail_setup_pipe(struct pakfire_jail* jail, int (*fds)[2], const int flags) {
        int r = pipe2(*fds, flags);
        if (r < 0) {
@@ -786,6 +850,9 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec
        const int stderr = pakfire_jail_get_pipe_to_read(jail, &ctx->pipes.stderr);
        const int pidfd  = ctx->pidfd;
 
+       // Fetch the UNIX domain socket
+       const int socket_recv = pakfire_jail_get_pipe_to_read(jail, &ctx->socket);
+
        // Timer
        const int timerfd = pakfire_jail_create_timer(jail);
 
@@ -819,6 +886,9 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec
                { log_DEBUG, EPOLLIN },
 #endif /* ENABLE_DEBUG */
 
+               // UNIX Domain Socket
+               { socket_recv, EPOLLIN },
+
                // Sentinel
                { -1, 0 },
        };
@@ -959,6 +1029,18 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec
                                                data     = jail->callbacks.log_data;
                                        }
 
+                               // Handle socket messages
+                               } else if (fd == socket_recv) {
+                                       // Receive the passed FD
+                                       r = pakfire_jail_recv_fd(jail, socket_recv, &fd);
+                                       if (r)
+                                               goto ERROR;
+
+                                       // XXX Do something with the file descriptor
+
+                                       // Don't fall through to log processing
+                                       continue;
+
                                } else {
                                        DEBUG(jail->pakfire, "Received invalid file descriptor %d\n", fd);
                                        continue;
@@ -1893,6 +1975,8 @@ static int __pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[],
        struct pakfire_jail_exec ctx = {
                .flags = flags,
 
+               .socket = { -1, -1 },
+
                .pipes = {
                        .stdin     = { -1, -1 },
                        .stdout    = { -1, -1 },
@@ -1929,6 +2013,14 @@ static int __pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[],
                return -1;
        }
 
+       // Create a UNIX domain socket
+       r = socketpair(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, ctx.socket);
+       if (r < 0) {
+               CTX_ERROR(jail->ctx, "Could not create UNIX socket: %s\n", strerror(errno));
+               r = -errno;
+               goto ERROR;
+       }
+
        // Create pipes to communicate with child process if we are not running interactively
        if (!interactive) {
                // stdin (only if callback is set)
@@ -2075,6 +2167,7 @@ ERROR:
 #ifdef ENABLE_DEBUG
        pakfire_jail_close_pipe(jail, ctx.pipes.log_DEBUG);
 #endif /* ENABLE_DEBUG */
+       pakfire_jail_close_pipe(jail, ctx.socket);
 
        return exit;
 }