From: Michael Tremer Date: Sat, 5 Oct 2024 17:15:22 +0000 (+0000) Subject: jail: Catch any PID events by the event loop X-Git-Tag: 0.9.30~1146 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=18f83ade8ff1ee9f799c0b775b15871a4f342827;p=pakfire.git jail: Catch any PID events by the event loop Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/jail.c b/src/libpakfire/jail.c index 38d80c6f9..a4a0499d6 100644 --- a/src/libpakfire/jail.c +++ b/src/libpakfire/jail.c @@ -161,9 +161,14 @@ struct pakfire_jail { }; struct pakfire_jail_exec { + struct pakfire_jail* jail; + sd_event* loop; int flags; + // Exit Code + int exit; + // PID (of the child) pid_t pid; int pidfd; @@ -171,9 +176,6 @@ struct pakfire_jail_exec { // Socket to pass FDs int socket[2]; - // Process status (from waitid) - siginfo_t status; - // FD to notify the client that the parent has finished initialization int completed_fd; @@ -1126,9 +1128,6 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec char garbage[8]; int r = 0; - // Fetch file descriptors from context - const int pidfd = ctx->pidfd; - // Fetch the UNIX domain socket const int socket_recv = pakfire_jail_get_pipe_to_read(jail, &ctx->socket); @@ -1143,9 +1142,6 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec // Timer { timerfd, EPOLLIN }, - // Child Process - { ctx->pidfd, EPOLLIN }, - // UNIX Domain Socket { socket_recv, EPOLLIN }, @@ -1232,21 +1228,6 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec goto ERROR; } - // Handle any changes to the PIDFD - } else if (pidfd == fd) { - if (e & EPOLLIN) { - // Call waidid() and store the result - r = waitid(P_PIDFD, ctx->pidfd, &ctx->status, WEXITED); - if (r) { - CTX_ERROR(jail->ctx, "waitid() failed: %m\n"); - goto ERROR; - } - - // Mark that we have ended so that we will process the remaining - // events from epoll() now, but won't restart the outer loop. - ended = 1; - } - // Handle timer events } else if (timerfd == fd) { if (e & EPOLLIN) { @@ -1265,7 +1246,7 @@ static int pakfire_jail_wait(struct pakfire_jail* jail, struct pakfire_jail_exec CTX_DEBUG(jail->ctx, "Terminating process...\n"); // Send SIGTERM to the process - r = pidfd_send_signal(pidfd, SIGKILL, NULL, 0); + r = pidfd_send_signal(ctx->pidfd, SIGKILL, NULL, 0); if (r) { CTX_ERROR(jail->ctx, "Could not kill process: %m\n"); goto ERROR; @@ -1863,12 +1844,47 @@ static int pakfire_jail_wait_for_signal(struct pakfire_jail* jail, int fd) { return r; } +static int pakfire_jail_exited(sd_event_source* source, const siginfo_t* si, void* data) { + struct pakfire_jail_exec* ctx = data; + struct pakfire_jail* jail = ctx->jail; + + switch (si->si_code) { + case CLD_EXITED: + CTX_DEBUG(jail->ctx, "Process has exited with status code %d\n", si->si_status); + + // Store the exit code + ctx->exit = si->si_status; + break; + + case CLD_KILLED: + CTX_ERROR(jail->ctx, "Process has been killed by signal %d\n", si->si_signo); + + // Store the exit code + ctx->exit = 139; + break; + + case CLD_DUMPED: + CTX_ERROR(jail->ctx, "The child process terminated abnormally\n"); + break; + } + + // Terminate the event loop + return sd_event_exit(sd_event_source_get_event(source), 0); +} + /* Performs the initialisation that needs to happen in the parent part */ static int pakfire_jail_parent(struct pakfire_jail* jail, struct pakfire_jail_exec* ctx) { int r; + // Register the PID file descriptor + r = sd_event_add_child_pidfd(ctx->loop, NULL, ctx->pidfd, WEXITED, pakfire_jail_exited, ctx); + if (r < 0) { + CTX_DEBUG(jail->ctx, "Could not register the child process with the event loop: %s\n", strerror(-r)); + return r; + } + // Setup UID mapping r = pakfire_jail_setup_uid_mapping(jail, ctx->pid); if (r) @@ -2221,7 +2237,6 @@ static int pakfire_jail_child(struct pakfire_jail* jail, struct pakfire_jail_exe // Run a command in the jail PAKFIRE_EXPORT int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv[], int flags) { - int exit = -1; int r; // Check if argv is valid @@ -2232,8 +2247,12 @@ PAKFIRE_EXPORT int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv // Initialize context for this call struct pakfire_jail_exec ctx = { + .jail = jail, .flags = flags, + // Exit Code + .exit = -1, + .socket = { -1, -1 }, .pidfd = -1, @@ -2363,31 +2382,6 @@ PAKFIRE_EXPORT int pakfire_jail_exec(struct pakfire_jail* jail, const char* argv if (r) goto ERROR; - // Handle exit status - switch (ctx.status.si_code) { - case CLD_EXITED: - CTX_DEBUG(jail->ctx, "The child process exited with code %d\n", - ctx.status.si_status); - - // Pass exit code - exit = ctx.status.si_status; - break; - - case CLD_KILLED: - CTX_ERROR(jail->ctx, "The child process was killed\n"); - exit = 139; - break; - - case CLD_DUMPED: - CTX_ERROR(jail->ctx, "The child process terminated abnormally\n"); - break; - - // Log anything else - default: - CTX_ERROR(jail->ctx, "Unknown child exit code: %d\n", ctx.status.si_code); - break; - } - ERROR: // Reset all callbacks pakfire_jail_set_stdin_callback(jail, NULL, NULL); @@ -2422,7 +2416,7 @@ ERROR: if (ctx.loop) sd_event_unref(ctx.loop); - return exit; + return ctx.exit; } static int pakfire_jail_exec_interactive(