about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2023-09-11 09:41:32 +0000
committerEric Wong <e@80x24.org>2023-09-11 18:51:17 +0000
commit6b278252cd994a866bd4cf15025033dd8afbd02b (patch)
tree4b2a945bffb6e66eba6a9e5b27c49291c5221a89
parent54929c5ed9c91eb23660a9822829d2a3170ef0e9 (diff)
downloadpublic-inbox-6b278252cd994a866bd4cf15025033dd8afbd02b.tar.gz
SIGABRT, SIGBUS, SIGILL, and SIGSEGV may all happen if we
introduce bugs in the section where signals are blocked.

We can delay handling of SIGFPE, SIGXCPU and SIGXFSZ since
there's no floating point operations; while SIGXCPU and
SIGXFSZ are safe to delay, especially in the absence of
threads in our current code paths.
-rw-r--r--lib/PublicInbox/Spawn.pm11
-rw-r--r--lib/PublicInbox/SpawnPP.pm4
2 files changed, 12 insertions, 3 deletions
diff --git a/lib/PublicInbox/Spawn.pm b/lib/PublicInbox/Spawn.pm
index 17d87f57..ed698afc 100644
--- a/lib/PublicInbox/Spawn.pm
+++ b/lib/PublicInbox/Spawn.pm
@@ -92,18 +92,23 @@ int pi_fork_exec(SV *redirref, SV *file, SV *cmdref, SV *envref, SV *rlimref,
         sigset_t set, old;
         int ret, perrnum;
         volatile int cerrnum = 0; /* shared due to vfork */
-        int chld_is_member;
+        int chld_is_member; /* needed due to shared memory w/ vfork */
         I32 max_fd = av_len(redir);
 
         AV2C_COPY(argv, cmd);
         AV2C_COPY(envp, env);
 
         if (sigfillset(&set)) return -1;
+        if (sigdelset(&set, SIGABRT)) return -1;
+        if (sigdelset(&set, SIGBUS)) return -1;
+        if (sigdelset(&set, SIGFPE)) return -1;
+        if (sigdelset(&set, SIGILL)) return -1;
+        if (sigdelset(&set, SIGSEGV)) return -1;
+        /* no XCPU/XFSZ here */
         if (sigprocmask(SIG_SETMASK, &set, &old)) return -1;
         chld_is_member = sigismember(&old, SIGCHLD);
         if (chld_is_member < 0) return -1;
-        if (chld_is_member > 0)
-                sigdelset(&old, SIGCHLD);
+        if (chld_is_member > 0 && sigdelset(&old, SIGCHLD)) return -1;
 
         pid = vfork();
         if (pid == 0) {
diff --git a/lib/PublicInbox/SpawnPP.pm b/lib/PublicInbox/SpawnPP.pm
index d6c863f8..e7174d6f 100644
--- a/lib/PublicInbox/SpawnPP.pm
+++ b/lib/PublicInbox/SpawnPP.pm
@@ -15,6 +15,10 @@ sub pi_fork_exec ($$$$$$$) {
         my $old = POSIX::SigSet->new();
         my $set = POSIX::SigSet->new();
         $set->fillset or die "sigfillset: $!";
+        for (POSIX::SIGABRT, POSIX::SIGBUS, POSIX::SIGFPE,
+                        POSIX::SIGILL, POSIX::SIGSEGV) {
+                $set->delset($_) or die "delset($_): $!";
+        }
         sigprocmask(SIG_SETMASK, $set, $old) or die "SIG_SETMASK(set): $!";
         my $syserr;
         pipe(my ($r, $w)) or die "pipe: $!";