#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>
struct pakfire_cgroup* cgroup;
struct pakfire_cgroup_stats cgroup_stats;
+
+ // Console
+ char console[PATH_MAX];
+ int consolefd;
};
static int clone3(struct clone_args* args, size_t size) {
return -1;
}
-// Signals
-
-#if 0
-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;
-}
-#endif
-
/*
This function replaces any logging in the child process.
const int log_DEBUG = pakfire_jail_get_pipe_to_read(jail, &ctx->pipes.log_DEBUG);
#endif /* ENABLE_DEBUG */
-#if 0
- // Signals
- const int signalfd = pakfire_jail_handle_signals(jail);
-#endif
-
// Make a list of all file descriptors we are interested in
const struct pakfire_wait_fds {
const int fd;
// Child Processes
{ ctx->pidfd1, EPOLLIN },
-#if 0
- // Signals
- { signafd, EPOLLIN },
-#endif
-
// Log Pipes
{ log_INFO, EPOLLIN },
{ log_ERROR, EPOLLIN },
// There is nothing else to do
continue;
-#if 0
- // 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 %u\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 %u\n",
- siginfo.ssi_signo);
- break;
- }
-
- // Don't fall through to log processing
- continue;
-#endif
-
// Handle socket messages
} else if (fd == socket_recv) {
// Receive the FD of the second child process
close(epollfd);
if (timerfd >= 0)
close(timerfd);
-#if 0
- if (signalfd >= 0)
- close(signalfd);
-#endif
return r;
}
flags |= PAKFIRE_MOUNT_LOOP_DEVICES;
// Mount all default stuff
- r = pakfire_mount_all(jail->pakfire, flags);
+ r = pakfire_mount_all(jail->pakfire, PAKFIRE_MNTNS_OUTER, flags);
+ if (r)
+ return r;
+
+ // Populate /dev
+ r = pakfire_populate_dev(jail->pakfire, flags);
+ if (r)
+ return r;
+
+ // Mount the interpreter (if needed)
+ r = pakfire_mount_interpreter(jail->pakfire);
if (r)
return r;
return r;
}
- // Log all mountpoints
- pakfire_mount_list(jail->pakfire);
-
return 0;
}
static int pakfire_jail_setgroups(struct pakfire_jail* jail, pid_t pid) {
char path[PATH_MAX];
- int r = 1;
+ int r;
// Make path
r = pakfire_string_format(path, "/proc/%d/setgroups", pid);
if (r)
return r;
- // Open file for writing
- FILE* f = fopen(path, "w");
- if (!f) {
- ERROR(jail->pakfire, "Could not open %s for writing: %m\n", path);
- goto ERROR;
- }
-
- // Write content
- int bytes_written = fprintf(f, "deny\n");
- if (bytes_written <= 0) {
- ERROR(jail->pakfire, "Could not write to %s: %m\n", path);
- goto ERROR;
- }
-
- r = fclose(f);
- f = NULL;
+ r = pakfire_file_write(jail->pakfire, path, 0, 0, 0, "deny\n");
if (r) {
- ERROR(jail->pakfire, "Could not close %s: %m\n", path);
- goto ERROR;
+ CTX_ERROR(jail->ctx, "Could not set setgroups to deny: %s\n", strerror(errno));
+ r = -errno;
}
-ERROR:
- if (f)
- fclose(f);
-
return r;
}
return 0;
}
+#if 0
+static int pakfire_jail_open_pty(struct pakfire_jail* jail, struct pakfire_jail_exec* ctx) {
+ int r;
+
+ // Allocate a new PTY
+ ctx->consolefd = posix_openpt(O_RDWR|O_NONBLOCK|O_NOCTTY|O_CLOEXEC);
+ if (ctx->consolefd < 0)
+ return -errno;
+
+ // Fetch the path
+ r = ptsname_r(ctx->consolefd, ctx->console, sizeof(ctx->console));
+ if (r)
+ return -r;
+
+ CTX_DEBUG(jail->ctx, "Allocated console at %s (%d)\n", ctx->console, ctx->consolefd);
+
+ // Create a symlink
+ r = pakfire_symlink(jail->ctx, "/dev/console", ctx->console);
+ if (r)
+ return r;
+
+ return r;
+}
+#endif
+
/*
Called by the parent that sets up the second child process...
*/
CTX_DEBUG(jail->ctx, "Launched child process in jail with PID %d\n", pid);
- // Die with parent
- r = prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
- if (r) {
- CTX_ERROR(jail->ctx, "Could not configure to die with parent: %m\n");
- return 126;
- }
-
// Make this process dumpable
r = prctl (PR_SET_DUMPABLE, 1, 0, 0, 0);
if (r) {
DEBUG(jail->pakfire, " UID: %u (effective %u)\n", uid, euid);
DEBUG(jail->pakfire, " GID: %u (effective %u)\n", gid, egid);
+ // Log all mountpoints
+ pakfire_mount_list(jail->ctx);
+
// Fail if we are not PID 1
if (pid != 1) {
CTX_ERROR(jail->ctx, "Child process is not PID 1\n");
- //return 126;
+ return 126;
}
// Fail if we are not running as root
if (uid || gid || euid || egid) {
ERROR(jail->pakfire, "Child process is not running as root\n");
- //return 126;
+ return 126;
+ }
+
+ // Mount all default stuff
+ r = pakfire_mount_all(jail->pakfire, PAKFIRE_MNTNS_INNER, 0);
+ if (r)
+ return 126;
+
+#if 0
+ // Create a new session
+ r = setsid();
+ if (r < 0) {
+ CTX_ERROR(jail->ctx, "Could not create a new session: %s\n", strerror(errno));
+ return 126;
}
+ // Allocate a new PTY
+ r = pakfire_jail_open_pty(jail, ctx);
+ if (r) {
+ CTX_ERROR(jail->ctx, "Could not allocate a new PTY: %s\n", strerror(-r));
+ return 126;
+ }
+#endif
+
const char* arch = pakfire_get_effective_arch(jail->pakfire);
// Set personality
if (r)
goto ERROR;
+ // XXX setup keyring
+
+
+
// chroot()
r = pakfire_jail_switch_root(jail, root);
if (r)
ERROR:
// Destroy the temporary cgroup (if any)
if (ctx.cgroup) {
-#if 0
- // XXX this is currently disabled because it overwrites r
// Read cgroup stats
- r = pakfire_cgroup_stat(ctx.cgroup, &ctx.cgroup_stats);
- if (r) {
- ERROR(jail->pakfire, "Could not read cgroup stats: %m\n");
- } else {
- pakfire_cgroup_stat_dump(ctx.cgroup, &ctx.cgroup_stats);
- }
-#endif
-
+ pakfire_cgroup_stat(ctx.cgroup, &ctx.cgroup_stats);
+ pakfire_cgroup_stat_dump(ctx.cgroup, &ctx.cgroup_stats);
pakfire_cgroup_destroy(ctx.cgroup);
pakfire_cgroup_unref(ctx.cgroup);
}