diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2018-05-02 16:15:12 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2018-05-02 16:15:12 +0200 |
commit | e6d9e7073ea1e23a3b22440fa69ce92691ca328d (patch) | |
tree | 3fb974880b1ba48f06a5ce430ff0d5983008c180 /src/jail.c | |
parent | 3ef3c65b4d19df39e020c1d5f778dafdf493a635 (diff) |
POTD skeleton #40.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Diffstat (limited to 'src/jail.c')
-rw-r--r-- | src/jail.c | 55 |
1 files changed, 33 insertions, 22 deletions
@@ -16,16 +16,17 @@ #include "log.h" typedef struct jail_prisoner_process { - pid_t prisoner_pid; psocket client_psock; char host_buf[NI_MAXHOST], service_buf[NI_MAXSERV]; char *newroot; } jail_prisoner_process; -static int jail_mainloop_epoll(int epoll_fd, jail_ctx *ctx[], size_t siz); +static int jail_mainloop_epoll(int epoll_fd, jail_ctx *ctx[], size_t siz) + __attribute__((noreturn)); static int jail_accept_client(jail_ctx *ctx[], size_t siz, struct epoll_event *event); -static int jail_childfn(void *arg); +static int jail_childfn(void *arg) + __attribute__((noreturn)); void jail_init_ctx(jail_ctx **ctx, size_t stacksize) @@ -144,12 +145,15 @@ pid_t jail_daemonize(int epoll_fd, jail_ctx *ctx[], size_t siz) W_STRERR("%s", "Jail daemonize"); return -1; case 0: - N("%s", "Jail daemon mainloop"); + N("Jail daemon mainloop on Epoll fd %d", epoll_fd); jail_mainloop_epoll(epoll_fd, ctx, siz); - break; } D2("Jail daemon pid: %d", p); + close(epoll_fd); + for (i = 0; i < siz; ++i) + socket_close(&ctx[i]->sock); + return p; } @@ -169,7 +173,6 @@ static int jail_mainloop_epoll(int epoll_fd, jail_ctx *ctx[], size_t siz) assert( set_child_sighandler() == 0 ); sigemptyset(&eset); - D2("Epoll fd: %d", epoll_fd); while (1) { int n, i; @@ -205,10 +208,9 @@ error: static int jail_accept_client(jail_ctx *ctx[], size_t siz, struct epoll_event *event) { - int clone_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC| - CLONE_NEWNS|CLONE_NEWNET; size_t i, rc = 0; int s; + pid_t prisoner_pid; jail_prisoner_process *args; for (i = 0; i < siz; ++i) { @@ -234,8 +236,15 @@ static int jail_accept_client(jail_ctx *ctx[], ctx[i]->host_buf, ctx[i]->service_buf, args->client_psock.fd); - args->prisoner_pid = clone(jail_childfn, ctx[i]->stack_beg, - SIGCHLD|clone_flags, args); + prisoner_pid = fork(); + switch (prisoner_pid) { + case -1: + W_STRERR("%s", "Jail client fork"); + goto error; + case 0: + jail_childfn(args); + } + N2("Jail prisoner pid %d", prisoner_pid); rc = 1; error: @@ -256,21 +265,26 @@ static int jail_childfn(void *arg) int s, term_fd; struct termios *term = NULL; struct winsize *win = NULL; - pid_t child_pid; + int unshare_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC| + CLONE_NEWNS|CLONE_NEWNET; + pid_t self_pid, child_pid; assert(arg); args = (jail_prisoner_process *) arg; + self_pid = getpid(); if (prctl(PR_SET_PDEATHSIG, SIGKILL) != 0) - FATAL("Jail child prctl for pid %d", args->prisoner_pid); + FATAL("Jail child prctl for pid %d", self_pid); if (!args->newroot) - FATAL("New root set for pid %d", args->prisoner_pid); + FATAL("New root set for pid %d", self_pid); + + D2("Unshare prisoner %d", self_pid); + if (unshare(unshare_flags)) + FATAL("Unshare prisoner %d", self_pid); D2("Safe change root to: '%s'", args->newroot); - if (safe_chroot(args->newroot)) { - E2("Safe jail chroot to '%s' failed", args->newroot); - exit(EXIT_FAILURE); - } + if (safe_chroot(args->newroot)) + FATAL("Safe jail chroot to '%s' failed", args->newroot); D2("Mounting rootfs to '%s'", args->newroot); mount_root(); @@ -305,19 +319,16 @@ static int jail_childfn(void *arg) switch (child_pid) { case -1: FATAL("Forking a new pseudo terminal for pid %d", - args->prisoner_pid); + self_pid); break; case 0: D2("Executing '%s'", "/bin/bash"); if (execl("/bin(bash", "/bin/bash", (char *) NULL)) - FATAL("Execute a shell for pid %d", args->prisoner_pid); + FATAL("Execute a shell for pid %d", self_pid); break; default: waitpid(child_pid, &s, 0); } -printf("_%d,%d_\n", child_pid, getuid()); -sleep(10); - exit(EXIT_FAILURE); } |