Only return EPERM from kill(-pid) when no process was signalled.
As mandated by POSIX. Also clarify the kill(2) manpage. While there, restructure the code in killpg1() to use helper which keeps overall state of the process list iteration in the killpg1_ctx structued, later used to infer the error returned. Reported by: amdmi3 Reviewed by: jilles Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D22621
This commit is contained in:
parent
624e87b673
commit
0cc9fb7551
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=355500
@ -28,7 +28,7 @@
|
|||||||
.\" @(#)kill.2 8.3 (Berkeley) 4/19/94
|
.\" @(#)kill.2 8.3 (Berkeley) 4/19/94
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd December 1, 2017
|
.Dd December 1, 2019
|
||||||
.Dt KILL 2
|
.Dt KILL 2
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -105,12 +105,11 @@ process with ID 1
|
|||||||
.Xr init 8 ) ,
|
.Xr init 8 ) ,
|
||||||
and the process sending the signal.
|
and the process sending the signal.
|
||||||
If the user is not the super user, the signal is sent to all processes
|
If the user is not the super user, the signal is sent to all processes
|
||||||
with the same uid as the user excluding the process sending the signal.
|
which the caller has permissions to, excluding the process sending the signal.
|
||||||
No error is returned if any process could be signaled.
|
No error is returned if any process could be signaled.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
For compatibility with System V,
|
If the process number is negative but not -1,
|
||||||
if the process number is negative but not -1,
|
|
||||||
the signal is sent to all processes whose process group ID
|
the signal is sent to all processes whose process group ID
|
||||||
is equal to the absolute value of the process number.
|
is equal to the absolute value of the process number.
|
||||||
This is a variant of
|
This is a variant of
|
||||||
@ -134,7 +133,7 @@ No process or process group can be found corresponding to that specified by
|
|||||||
.It Bq Er EPERM
|
.It Bq Er EPERM
|
||||||
The sending process does not have permission to send
|
The sending process does not have permission to send
|
||||||
.Va sig
|
.Va sig
|
||||||
to the receiving process.
|
to any receiving process.
|
||||||
.El
|
.El
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr getpgrp 2 ,
|
.Xr getpgrp 2 ,
|
||||||
|
@ -1679,6 +1679,36 @@ kern_sigaltstack(struct thread *td, stack_t *ss, stack_t *oss)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct killpg1_ctx {
|
||||||
|
struct thread *td;
|
||||||
|
ksiginfo_t *ksi;
|
||||||
|
int sig;
|
||||||
|
bool sent;
|
||||||
|
bool found;
|
||||||
|
int ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
killpg1_sendsig(struct proc *p, bool notself, struct killpg1_ctx *arg)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (p->p_pid <= 1 || (p->p_flag & P_SYSTEM) != 0 ||
|
||||||
|
(notself && p == arg->td->td_proc) || p->p_state == PRS_NEW)
|
||||||
|
return;
|
||||||
|
PROC_LOCK(p);
|
||||||
|
err = p_cansignal(arg->td, p, arg->sig);
|
||||||
|
if (err == 0 && arg->sig != 0)
|
||||||
|
pksignal(p, arg->sig, arg->ksi);
|
||||||
|
PROC_UNLOCK(p);
|
||||||
|
if (err != ESRCH)
|
||||||
|
arg->found = true;
|
||||||
|
if (err == 0)
|
||||||
|
arg->sent = true;
|
||||||
|
else if (arg->ret == 0 && err != ESRCH && err != EPERM)
|
||||||
|
arg->ret = err;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Common code for kill process group/broadcast kill.
|
* Common code for kill process group/broadcast kill.
|
||||||
* cp is calling process.
|
* cp is calling process.
|
||||||
@ -1688,30 +1718,21 @@ 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;
|
struct killpg1_ctx arg;
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = ESRCH;
|
arg.td = td;
|
||||||
|
arg.ksi = ksi;
|
||||||
|
arg.sig = sig;
|
||||||
|
arg.sent = false;
|
||||||
|
arg.found = false;
|
||||||
|
arg.ret = 0;
|
||||||
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 ||
|
killpg1_sendsig(p, true, &arg);
|
||||||
p == td->td_proc || p->p_state == PRS_NEW) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
PROC_LOCK(p);
|
|
||||||
err = p_cansignal(td, p, sig);
|
|
||||||
if (err == 0) {
|
|
||||||
if (sig)
|
|
||||||
pksignal(p, sig, ksi);
|
|
||||||
ret = err;
|
|
||||||
}
|
|
||||||
else if (ret == ESRCH)
|
|
||||||
ret = err;
|
|
||||||
PROC_UNLOCK(p);
|
|
||||||
}
|
}
|
||||||
sx_sunlock(&allproc_lock);
|
sx_sunlock(&allproc_lock);
|
||||||
} else {
|
} else {
|
||||||
@ -1731,25 +1752,14 @@ killpg1(struct thread *td, int sig, int pgid, int all, ksiginfo_t *ksi)
|
|||||||
}
|
}
|
||||||
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);
|
killpg1_sendsig(p, false, &arg);
|
||||||
if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
|
|
||||||
p->p_state == PRS_NEW) {
|
|
||||||
PROC_UNLOCK(p);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
err = p_cansignal(td, p, sig);
|
|
||||||
if (err == 0) {
|
|
||||||
if (sig)
|
|
||||||
pksignal(p, sig, ksi);
|
|
||||||
ret = err;
|
|
||||||
}
|
|
||||||
else if (ret == ESRCH)
|
|
||||||
ret = err;
|
|
||||||
PROC_UNLOCK(p);
|
|
||||||
}
|
}
|
||||||
PGRP_UNLOCK(pgrp);
|
PGRP_UNLOCK(pgrp);
|
||||||
}
|
}
|
||||||
return (ret);
|
MPASS(arg.ret != 0 || arg.found || !arg.sent);
|
||||||
|
if (arg.ret == 0 && !arg.sent)
|
||||||
|
arg.ret = arg.found ? EPERM : ESRCH;
|
||||||
|
return (arg.ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _SYS_SYSPROTO_H_
|
#ifndef _SYS_SYSPROTO_H_
|
||||||
|
Loading…
Reference in New Issue
Block a user