Changeset View
Standalone View
sys/kern/kern_sig.c
Show First 20 Lines • Show All 1,682 Lines • ▼ Show 20 Lines | |||||
* Common code for kill process group/broadcast kill. | * Common code for kill process group/broadcast kill. | ||||
* cp is calling process. | * cp is calling process. | ||||
*/ | */ | ||||
static int | static int | ||||
killpg1(struct thread *td, int sig, int pgid, int all, ksiginfo_t *ksi) | killpg1(struct thread *td, int sig, int pgid, int all, ksiginfo_t *ksi) | ||||
{ | { | ||||
struct proc *p; | struct proc *p; | ||||
struct pgrp *pgrp; | struct pgrp *pgrp; | ||||
int err; | int err, ret; | ||||
int ret; | bool sent, found; | ||||
ret = ESRCH; | ret = 0; | ||||
sent = found = false; | |||||
if (all) { | if (all) { | ||||
/* | /* | ||||
* broadcast | * broadcast | ||||
*/ | */ | ||||
sx_slock(&allproc_lock); | sx_slock(&allproc_lock); | ||||
FOREACH_PROC_IN_SYSTEM(p) { | FOREACH_PROC_IN_SYSTEM(p) { | ||||
if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || | if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || | ||||
p == td->td_proc || p->p_state == PRS_NEW) { | p == td->td_proc || p->p_state == PRS_NEW) { | ||||
continue; | continue; | ||||
} | } | ||||
found = true; | |||||
jilles: `found` should only be set to true if `p_cansignal()` does not return `ESRCH`, so we don't… | |||||
kibAuthorUnsubmitted Done Inline ActionsI was actually not quite sure does p_cansignal() and code which it calls like prison_<something> care about returning ESRCH when visibility is denied (vs. returning something else), but it seems fine. kib: I was actually not quite sure does p_cansignal() and code which it calls like… | |||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
err = p_cansignal(td, p, sig); | err = p_cansignal(td, p, sig); | ||||
if (err == 0) { | if (err == 0) { | ||||
if (sig) | if (sig != 0) | ||||
pksignal(p, sig, ksi); | pksignal(p, sig, ksi); | ||||
sent = true; | |||||
} else if (ret == 0 && err != ESRCH && err != EPERM) { | |||||
ret = err; | ret = err; | ||||
} | } | ||||
else if (ret == ESRCH) | |||||
ret = err; | |||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
} | } | ||||
sx_sunlock(&allproc_lock); | sx_sunlock(&allproc_lock); | ||||
} else { | } else { | ||||
sx_slock(&proctree_lock); | sx_slock(&proctree_lock); | ||||
if (pgid == 0) { | if (pgid == 0) { | ||||
/* | /* | ||||
* zero pgid means send to my process group. | * zero pgid means send to my process group. | ||||
Show All 10 Lines | if (all) { | ||||
sx_sunlock(&proctree_lock); | sx_sunlock(&proctree_lock); | ||||
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) { | LIST_FOREACH(p, &pgrp->pg_members, p_pglist) { | ||||
PROC_LOCK(p); | PROC_LOCK(p); | ||||
if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || | if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || | ||||
p->p_state == PRS_NEW) { | p->p_state == PRS_NEW) { | ||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
continue; | continue; | ||||
} | } | ||||
found = true; | |||||
err = p_cansignal(td, p, sig); | err = p_cansignal(td, p, sig); | ||||
if (err == 0) { | if (err == 0) { | ||||
if (sig) | if (sig != 0) | ||||
pksignal(p, sig, ksi); | pksignal(p, sig, ksi); | ||||
sent = true; | |||||
} else if (ret == 0 && err != ESRCH && err != EPERM) { | |||||
ret = err; | ret = err; | ||||
} | } | ||||
else if (ret == ESRCH) | |||||
ret = err; | |||||
PROC_UNLOCK(p); | PROC_UNLOCK(p); | ||||
} | } | ||||
PGRP_UNLOCK(pgrp); | PGRP_UNLOCK(pgrp); | ||||
} | } | ||||
MPASS(ret != 0 || found || !sent); | |||||
if (ret == 0 && !sent) | |||||
Not Done Inline ActionsPOSIX is pretty clear that any successful signal sent (or signal that could be sent, if sig == 0) will cause kill() to succeed (not return an error). Given that if sent_one is true, ret can either be EPERM or 0 (under the assumption that p_cansignal() returns 0, EPERM or ESRCH), the part ret == EPERM && is only for special cases. The question here is whether a "buggy" failure (such as because of an obscure edge case in locking which is not handled, or something) should be reported to the application, violating the letter of POSIX, or should be ignored if some other process was signalled, possibly confusing the application and making it hard to debug. jilles: POSIX is pretty clear that any successful signal sent (or signal that could be sent, if `sig ==… | |||||
ret = found ? EPERM : ESRCH; | |||||
return (ret); | return (ret); | ||||
} | } | ||||
#ifndef _SYS_SYSPROTO_H_ | #ifndef _SYS_SYSPROTO_H_ | ||||
struct kill_args { | struct kill_args { | ||||
int pid; | int pid; | ||||
int signum; | int signum; | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 2,138 Lines • Show Last 20 Lines |
found should only be set to true if p_cansignal() does not return ESRCH, so we don't admit a process exists when we should not due to restrictions like security.bsd.see_other_uids.