#include <sys/personality.h>
#include <sys/prctl.h>
#include <sys/resource.h>
+#include <sys/signalfd.h>
#include <sys/timerfd.h>
#include <sys/types.h>
#include <sys/wait.h>
return -1;
}
+// Signals
+
+static int pakfire_jail_handle_signals(struct pakfire_jail* jail) {
+ sigset_t mask;
+ int r;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGINT);
+
+ // Block signals
+ r = sigprocmask(SIG_BLOCK, &mask, NULL);
+ if (r < 0) {
+ ERROR(jail->pakfire, "Failed to block signals: %m\n");
+ return r;
+ }
+
+ // Create a file descriptor
+ r = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC);
+ if (r < 0) {
+ ERROR(jail->pakfire, "Failed to create signalfd: %m\n");
+ return r;
+ }
+
+ return r;
+}
+
/*
This function replaces any logging in the child process.
int epollfd = -1;
struct epoll_event ev;
struct epoll_event events[EPOLL_MAX_EVENTS];
+ struct signalfd_siginfo siginfo;
char garbage[8];
int r = 0;
const int log_ERROR = pakfire_jail_get_pipe_to_read(jail, &ctx->pipes.log_ERROR);
const int log_DEBUG = pakfire_jail_get_pipe_to_read(jail, &ctx->pipes.log_DEBUG);
+ // Signals
+ const int signalfd = pakfire_jail_handle_signals(jail);
+
// Make a list of all file descriptors we are interested in
- int fds[] = {
- stdin, stdout, stderr, pidfd, timerfd, log_INFO, log_ERROR, log_DEBUG,
+ const int fds[] = {
+ stdin, stdout, stderr, pidfd, timerfd, signalfd, log_INFO, log_ERROR, log_DEBUG,
};
// Setup epoll
// There is nothing else to do
continue;
+ // Handle signals
+ } else if (fd == signalfd) {
+ // Read the signal
+ r = read(signalfd, &siginfo, sizeof(siginfo));
+ if (r < 1) {
+ ERROR(jail->pakfire, "Could not read signal: %m\n");
+ goto ERROR;
+ }
+
+ DEBUG(jail->pakfire, "Received signal %d\n", siginfo.ssi_signo);
+
+ // Handle signals
+ switch (siginfo.ssi_signo) {
+ // Pass SIGINT down to the child process
+ case SIGINT:
+ r = pidfd_send_signal(pidfd, siginfo.ssi_signo, NULL, 0);
+ if (r) {
+ ERROR(jail->pakfire, "Could not send signal to process: %m\n");
+ goto ERROR;
+ }
+ break;
+
+ default:
+ ERROR(jail->pakfire, "Received unhandled signal %d\n",
+ siginfo.ssi_signo);
+ break;
+ }
+
+ // Don't fall through to log processing
+ continue;
+
// Handle logging messages
} else if (fd == log_INFO) {
buffer = &ctx->buffers.log_INFO;
close(epollfd);
if (timerfd > 0)
close(timerfd);
+ if (signalfd > 0)
+ close(signalfd);
return r;
}