Repair kill(2) on zombie processes.
authorjca <jca@openbsd.org>
Mon, 27 Jun 2016 19:55:02 +0000 (19:55 +0000)
committerjca <jca@openbsd.org>
Mon, 27 Jun 2016 19:55:02 +0000 (19:55 +0000)
kill(2) is supposed to find zombie processes, this probably got broken
when the process reaper was introduced.  As a temporary(tm) workaround,
walk the list of zombie processes if we can't find the target pid in the
main process list.

Problem with zsh initially reported by Geoff Wozniak on misc@, analysis
done by naddy@.  ok kettenis@ tedu@

sys/kern/kern_proc.c
sys/kern/kern_sig.c
sys/sys/proc.h

index b1d474c..bb18000 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_proc.c,v 1.66 2016/03/04 14:09:37 deraadt Exp $  */
+/*     $OpenBSD: kern_proc.c,v 1.67 2016/06/27 19:55:02 jca Exp $      */
 /*     $NetBSD: kern_proc.c,v 1.14 1996/02/09 18:59:41 christos Exp $  */
 
 /*
@@ -204,6 +204,20 @@ pgfind(pid_t pgid)
        return (NULL);
 }
 
+/*
+ * Locate a zombie process
+ */
+struct process *
+zombiefind(pid_t pid)
+{
+       struct process *pr;
+
+       LIST_FOREACH(pr, &zombprocess, ps_list)
+               if (pr->ps_mainproc->p_pid == pid)
+                       return (pr);
+       return (NULL);
+}
+
 /*
  * Move p to a new or existing process group (and session)
  * Caller provides a pre-allocated pgrp and session that should
index db92fb2..ad89f68 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_sig.c,v 1.199 2016/06/27 16:49:45 jsing Exp $    */
+/*     $OpenBSD: kern_sig.c,v 1.200 2016/06/27 19:55:02 jca Exp $      */
 /*     $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $   */
 
 /*
@@ -627,19 +627,24 @@ sys_kill(struct proc *cp, void *v, register_t *retval)
        int pid = SCARG(uap, pid);
        int signum = SCARG(uap, signum);
        int error;
+       int zombie = 0;
 
        if ((error = pledge_kill(cp, pid)) != 0)
                return (error);
        if (((u_int)signum) >= NSIG)
                return (EINVAL);
        if (pid > 0) {
-               if ((pr = prfind(pid)) == NULL)
-                       return (ESRCH);
+               if ((pr = prfind(pid)) == NULL) {
+                       if ((pr = zombiefind(pid)) == NULL)
+                               return (ESRCH);
+                       else
+                               zombie = 1;
+               }
                if (!cansignal(cp, pr, signum))
                        return (EPERM);
 
                /* kill single process */
-               if (signum)
+               if (signum && !zombie)
                        prsignal(pr, signum);
                return (0);
        }
index 9b5263e..7c3b7f0 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: proc.h,v 1.223 2016/05/30 21:31:27 deraadt Exp $      */
+/*     $OpenBSD: proc.h,v 1.224 2016/06/27 19:55:02 jca Exp $  */
 /*     $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $       */
 
 /*-
@@ -482,6 +482,7 @@ pid_t       allocpid(void);
 void   freepid(pid_t);
 
 struct process *prfind(pid_t); /* Find process by id. */
+struct process *zombiefind(pid_t); /* Find zombie process by id. */
 struct proc *pfind(pid_t);     /* Find thread by id. */
 struct pgrp *pgfind(pid_t);    /* Find process group by id. */
 void   proc_printit(struct proc *p, const char *modif,