From 0c7f085de1687defda6c2c7cf29696b80fe35751 Mon Sep 17 00:00:00 2001 From: jca Date: Mon, 27 Jun 2016 19:55:02 +0000 Subject: [PATCH] Repair kill(2) on zombie processes. 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 | 16 +++++++++++++++- sys/kern/kern_sig.c | 13 +++++++++---- sys/sys/proc.h | 3 ++- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index b1d474c8cf0..bb18000ac04 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -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 diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index db92fb2d715..ad89f681555 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -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); } diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 9b5263ec889..7c3b7f056b9 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -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, -- 2.20.1