pid_t pid;
int pidfd;
+ // Socket to pass FDs
+ int socket[2];
+
// Process status (from waitid)
siginfo_t status;
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) {
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);
{ log_DEBUG, EPOLLIN },
#endif /* ENABLE_DEBUG */
+ // UNIX Domain Socket
+ { socket_recv, EPOLLIN },
+
// Sentinel
{ -1, 0 },
};
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;
struct pakfire_jail_exec ctx = {
.flags = flags,
+ .socket = { -1, -1 },
+
.pipes = {
.stdin = { -1, -1 },
.stdout = { -1, -1 },
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)
#ifdef ENABLE_DEBUG
pakfire_jail_close_pipe(jail, ctx.pipes.log_DEBUG);
#endif /* ENABLE_DEBUG */
+ pakfire_jail_close_pipe(jail, ctx.socket);
return exit;
}