From: Michael Tremer Date: Fri, 8 Dec 2023 15:29:45 +0000 (+0000) Subject: jail: Bring back the UNIX domain socket between child/parent X-Git-Tag: 0.9.30~1290 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8f49d2542017a0eb56e3102850f1e7ba38108a87;p=pakfire.git jail: Bring back the UNIX domain socket between child/parent We will need this later to pass around file descriptors. Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/jail.c b/src/libpakfire/jail.c index 5cc1dd753..5d091c58c 100644 --- a/src/libpakfire/jail.c +++ b/src/libpakfire/jail.c @@ -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; }