diff --git a/third_party/linenoise/linenoise.c b/third_party/linenoise/linenoise.c index 9ac615efd..cc7a0f94c 100644 --- a/third_party/linenoise/linenoise.c +++ b/third_party/linenoise/linenoise.c @@ -580,8 +580,9 @@ static char abGrow(struct abuf *a, int need) { int cap; char *b; cap = a->cap; - do cap += cap / 2; - while (cap < need); + do { + cap += cap / 2; + } while (cap < need); if (!(b = realloc(a->b, cap * sizeof(*a->b)))) return 0; a->cap = cap; a->b = b; @@ -824,8 +825,9 @@ static char linenoiseGrow(struct linenoiseState *ls, size_t n) { size_t m; m = ls->buflen; if (m >= n) return 1; - do m += m >> 1; - while (m < n); + do { + m += m >> 1; + } while (m < n); if (!(p = realloc(ls->buf, m * sizeof(*ls->buf)))) return 0; ls->buf = p; ls->buflen = m; @@ -855,8 +857,9 @@ static size_t Forward(struct linenoiseState *l, size_t pos) { static size_t Backward(struct linenoiseState *l, size_t pos) { if (pos) { - do --pos; - while (pos && (l->buf[pos] & 0300) == 0200); + do { + --pos; + } while (pos && (l->buf[pos] & 0300) == 0200); } return pos; } @@ -1461,8 +1464,9 @@ static size_t EscapeWord(struct linenoiseState *l) { if (iswseparator(r.c)) break; } if ((j = i)) { - do --j; - while (j && (l->buf[j] & 0300) == 0200); + do { + --j; + } while (j && (l->buf[j] & 0300) == 0200); r = GetUtf8(l->buf + j, l->len - j); if (iswseparator(r.c)) break; } @@ -1477,8 +1481,9 @@ static void linenoiseEditLeft(struct linenoiseState *l) { static void linenoiseEditRight(struct linenoiseState *l) { if (l->pos == l->len) return; - do l->pos++; - while (l->pos < l->len && (l->buf[l->pos] & 0300) == 0200); + do { + l->pos++; + } while (l->pos < l->len && (l->buf[l->pos] & 0300) == 0200); linenoiseRefreshLine(l); } @@ -2268,6 +2273,7 @@ char *linenoiseRaw(const char *prompt, int infd, int outfd) { buf = 0; raise(gotint); errno = EINTR; + gotint = 0; rc = -1; } if (rc != -1) { diff --git a/tool/build/jail.c b/tool/build/jail.c index f744decaa..f00ff37e0 100644 --- a/tool/build/jail.c +++ b/tool/build/jail.c @@ -17,9 +17,13 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" +#include "libc/calls/sigbits.h" #include "libc/calls/struct/filter.h" #include "libc/calls/struct/sigaction.h" +#include "libc/calls/struct/siginfo.h" +#include "libc/calls/struct/sigset.h" #include "libc/calls/struct/user_regs_struct.h" +#include "libc/calls/ucontext.h" #include "libc/dce.h" #include "libc/errno.h" #include "libc/intrin/kprintf.h" @@ -28,6 +32,7 @@ #include "libc/runtime/runtime.h" #include "libc/sysv/consts/pr.h" #include "libc/sysv/consts/ptrace.h" +#include "libc/sysv/consts/sa.h" #include "libc/sysv/consts/sig.h" #include "tool/net/sandbox.h" @@ -75,6 +80,7 @@ static const struct sock_filter kSandboxFilter[] = { _SECCOMP_ALLOW_SYSCALL(0x033), // getsockname _SECCOMP_ALLOW_SYSCALL(0x034), // getpeername _SECCOMP_ALLOW_SYSCALL(0x00f), // rt_sigreturn + _SECCOMP_ALLOW_SYSCALL(0x082), // rt_sigsuspend _SECCOMP_ALLOW_SYSCALL(0x0e4), // clock_gettime _SECCOMP_ALLOW_SYSCALL(0x060), // gettimeofday _SECCOMP_ALLOW_SYSCALL(0x03f), // uname @@ -110,7 +116,12 @@ static const struct sock_fprog kSandbox = { .filter = kSandboxFilter, }; +void OnSys(int sig, siginfo_t *si, ucontext_t *ctx) { + kprintf("Got SIGSYS%n"); +} + int main(int argc, char *argv[]) { + sigset_t mask, origmask; struct user_regs_struct regs; int child, evpid, signal, wstatus; @@ -122,30 +133,68 @@ int main(int argc, char *argv[]) { kprintf("Usage: %s PROGRAM [ARGS...]%n", argv[0]); return 1; } - ShowCrashReports(); - - CHECK_NE(-1, (child = fork())); - if (!child) { - if (ptrace(PTRACE_TRACEME) == -1) _Exit(124); - if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) _Exit(125); - if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &kSandbox) == -1) _Exit(126); - execvp(argv[1], argv + 1); - _Exit(127); - } + /* ShowCrashReports(); */ sigaction(SIGINT, &(struct sigaction){.sa_handler = SIG_IGN}, 0); sigaction(SIGQUIT, &(struct sigaction){.sa_handler = SIG_IGN}, 0); + sigaction(SIGSYS, + &((struct sigaction){ + .sa_sigaction = OnSys, + .sa_flags = SA_SIGINFO, + }), + 0); + + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + sigprocmask(SIG_BLOCK, &mask, &origmask); + + CHECK_NE(-1, (child = fork())); + if (!child) { + sigaction(SIGINT, &(struct sigaction){.sa_handler = SIG_DFL}, 0); + sigaction(SIGQUIT, &(struct sigaction){.sa_handler = SIG_DFL}, 0); + kprintf("CHILD ptrace(PTRACE_TRACEME)%n"); + if (ptrace(PTRACE_TRACEME) == -1) { + kprintf("CHILD ptrace(PTRACE_TRACEME) failed %m%n"); + _Exit(124); + } + kprintf("CHILD prctl(PR_SET_NO_NEW_PRIVS)%n"); + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) { + kprintf("CHILD prctl(PR_SET_NO_NEW_PRIVS) failed %m%n"); + _Exit(125); + } + kprintf("CHILD prctl(PR_SET_SECCOMP)%n"); + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &kSandbox) == -1) { + kprintf("CHILD prctl(PR_SET_SECCOMP) failed %m%n"); + _Exit(126); + } + kprintf("CHILD sigsuspend()%n"); + if (sigsuspend(0) == -1) { + kprintf("CHILD sigsuspend() failed %m%n"); + } + sigaction(SIGSYS, &(struct sigaction){.sa_handler = SIG_DFL}, 0); + sigprocmask(SIG_SETMASK, &origmask, 0); + execv(argv[1], argv + 1); + kprintf("CHILD execve(%#s) failed %m%n", argv[1]); + _Exit(127); + } // wait for ptrace(PTRACE_TRACEME) to be called + kprintf("PARENT waitpid(child, &wstatus)%n"); CHECK_EQ(child, waitpid(child, &wstatus, 0)); // configure linux process tracing + kprintf("PARENT ptrace(PTRACE_SETOPTIONS)%n"); CHECK_NE(-1, ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESECCOMP)); // continue child process + kprintf("PARENT ptrace(PTRACE_CONT)%n"); CHECK_NE(-1, ptrace(PTRACE_CONT, child, 0, 0)); + kprintf("PARENT kill(child, SIGSYS)%n"); + kill(child, SIGSYS); + for (;;) { + kprintf("PARENT waitpid()%n"); CHECK_NE(-1, (evpid = waitpid(-1, &wstatus, __WALL))); if (WIFSTOPPED(wstatus)) { signal = (wstatus >> 8) & 0xffff; diff --git a/tool/net/redbean.c b/tool/net/redbean.c index 15d3afd0d..ec74a20d7 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -6986,13 +6986,26 @@ static int EventLoop(int fd, int ms) { static void ReplEventLoop(void) { int status; + long double t; lua_State *L = GL; polls[0].fd = 0; __nomultics = 2; __replmode = true; lua_initrepl("redbean"); linenoiseSetPollCallback(EventLoop); - while ((status = lua_loadline(L)) != -1) { + for (;;) { + if ((status = lua_loadline(L)) == -1) { + if (errno = EINTR) { + LockInc(&shared->c.pollinterrupts); + if (terminated) { + break; + } else { + continue; + } + } else { + break; + } + } if (status == LUA_OK) { status = lua_runchunk(L, 0, LUA_MULTRET); }