From ca0279be7037b3f8bf659ef8b073ea847d0d8553 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 26 May 2014 20:46:30 -0700 Subject: [PATCH] Don't kill already-reaped process. * process.c (process_send_signal): Fix race condition where a subprocess was reaped by a signal handler between the check for liveness and calling 'kill', which meant that Emacs could in theory kill an innocent bystander process. Do the fix by blocking SIGCHLD in a critical section that checks liveness before killing. Fixes: debbugs:17561 --- src/ChangeLog | 9 +++++++++ src/process.c | 35 +++++++++++++++-------------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 247ec1c34b4..d2db6ccebd6 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,12 @@ +2014-05-27 Paul Eggert + + Don't kill already-reaped process (Bug#17561). + * process.c (process_send_signal): Fix race condition where a + subprocess was reaped by a signal handler between the check for + liveness and calling 'kill', which meant that Emacs could in + theory kill an innocent bystander process. Do the fix by blocking + SIGCHLD in a critical section that checks liveness before killing. + 2014-05-26 Eli Zaretskii * w32.c (_ANONYMOUS_UNION, _ANONYMOUS_STRUCT): Define only if diff --git a/src/process.c b/src/process.c index fdb0501f9ec..561aefc6c9f 100644 --- a/src/process.c +++ b/src/process.c @@ -5833,30 +5833,25 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, } #endif +#ifdef TIOCSIGSEND + /* Work around a HP-UX 7.0 bug that mishandles signals to subjobs. + We don't know whether the bug is fixed in later HP-UX versions. */ + if (! NILP (current_group) && ioctl (p->infd, TIOCSIGSEND, signo) != -1) + return; +#endif + /* If we don't have process groups, send the signal to the immediate subprocess. That isn't really right, but it's better than any obvious alternative. */ - if (no_pgrp) - { - kill (p->pid, signo); - return; - } + pid_t pid = no_pgrp ? gid : - gid; - /* gid may be a pid, or minus a pgrp's number */ -#ifdef TIOCSIGSEND - if (!NILP (current_group)) - { - if (ioctl (p->infd, TIOCSIGSEND, signo) == -1) - kill (-gid, signo); - } - else - { - gid = - p->pid; - kill (gid, signo); - } -#else /* ! defined (TIOCSIGSEND) */ - kill (-gid, signo); -#endif /* ! defined (TIOCSIGSEND) */ + /* Do not kill an already-reaped process, as that could kill an + innocent bystander that happens to have the same process ID. */ + sigset_t oldset; + block_child_signal (&oldset); + if (p->alive) + kill (pid, signo); + unblock_child_signal (&oldset); } DEFUN ("interrupt-process", Finterrupt_process, Sinterrupt_process, 0, 2, 0, -- 2.39.2