]> git.ipfire.org Git - thirdparty/public-inbox.git/commitdiff
spawn: do not block ABRT/BUS/ILL/SEGV signals
authorEric Wong <e@80x24.org>
Mon, 11 Sep 2023 09:41:32 +0000 (09:41 +0000)
committerEric Wong <e@80x24.org>
Mon, 11 Sep 2023 18:51:17 +0000 (18:51 +0000)
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.

lib/PublicInbox/Spawn.pm
lib/PublicInbox/SpawnPP.pm

index 17d87f57cb38e256b1b846dbb519e648211e24e2..ed698afc6c8e3d80b24674386a2e5df5707cc8ac 100644 (file)
@@ -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) {
index d6c863f81e201ef63f3345363b1e6810a131cb06..e7174d6f0cfadd545c9be8e619ac6e7aab6d25b9 100644 (file)
@@ -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: $!";