Author: kib
Date: Sat Dec 21 15:33:19 2019
New Revision: 355981
URL: https://svnweb.freebsd.org/changeset/base/355981

Log:
  MFC r355500:
  Only return EPERM from kill(-pid) when no process was signalled.

Modified:
  stable/12/lib/libc/sys/kill.2
  stable/12/sys/kern/kern_sig.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/lib/libc/sys/kill.2
==============================================================================
--- stable/12/lib/libc/sys/kill.2       Sat Dec 21 11:38:48 2019        
(r355980)
+++ stable/12/lib/libc/sys/kill.2       Sat Dec 21 15:33:19 2019        
(r355981)
@@ -28,7 +28,7 @@
 .\"     @(#)kill.2     8.3 (Berkeley) 4/19/94
 .\" $FreeBSD$
 .\"
-.Dd December 1, 2017
+.Dd December 1, 2019
 .Dt KILL 2
 .Os
 .Sh NAME
@@ -105,12 +105,11 @@ process with ID 1
 .Xr init 8 ) ,
 and the process sending the signal.
 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.
 .El
 .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
 is equal to the absolute value of the process number.
 This is a variant of
@@ -134,7 +133,7 @@ No process or process group can be found corresponding
 .It Bq Er EPERM
 The sending process does not have permission to send
 .Va sig
-to the receiving process.
+to any receiving process.
 .El
 .Sh SEE ALSO
 .Xr getpgrp 2 ,

Modified: stable/12/sys/kern/kern_sig.c
==============================================================================
--- stable/12/sys/kern/kern_sig.c       Sat Dec 21 11:38:48 2019        
(r355980)
+++ stable/12/sys/kern/kern_sig.c       Sat Dec 21 15:33:19 2019        
(r355981)
@@ -1679,6 +1679,36 @@ kern_sigaltstack(struct thread *td, stack_t *ss, stack
        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.
  * cp is calling process.
@@ -1688,30 +1718,21 @@ killpg1(struct thread *td, int sig, int pgid, int all,
 {
        struct proc *p;
        struct pgrp *pgrp;
-       int err;
-       int ret;
+       struct killpg1_ctx arg;
 
-       ret = ESRCH;
+       arg.td = td;
+       arg.ksi = ksi;
+       arg.sig = sig;
+       arg.sent = false;
+       arg.found = false;
+       arg.ret = 0;
        if (all) {
                /*
                 * broadcast
                 */
                sx_slock(&allproc_lock);
                FOREACH_PROC_IN_SYSTEM(p) {
-                       if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
-                           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);
+                       killpg1_sendsig(p, true, &arg);
                }
                sx_sunlock(&allproc_lock);
        } else {
@@ -1731,25 +1752,14 @@ killpg1(struct thread *td, int sig, int pgid, int all,
                }
                sx_sunlock(&proctree_lock);
                LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
-                       PROC_LOCK(p);
-                       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);
+                       killpg1_sendsig(p, false, &arg);
                }
                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_
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to