The branch main has been updated by dchagin:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=6201a50d0d6d98633dba3db12dea2dfe95295e0e

commit 6201a50d0d6d98633dba3db12dea2dfe95295e0e
Author:     Dmitry Chagin <[email protected]>
AuthorDate: 2022-04-25 07:22:51 +0000
Commit:     Dmitry Chagin <[email protected]>
CommitDate: 2022-04-25 07:22:51 +0000

    linux(4): Refactor signal send methods.
    
    Created a couple of helpers to send signals to the specific thread or to
    the whole process. Use helpers in the corresponding syscalls.
    This fixes the confusion where a signal destined for a whole process
    was sent to a specific thread and vice versa.
    There is an exclusion for the linux_kill() syscall that takes a pid
    argument and should send a signal to the whole process, but I know
    at least one example where kill() takes tid.
    
    MFC after:              2 weeks
---
 sys/compat/linux/linux_signal.c | 170 +++++++++++++++++++++++-----------------
 1 file changed, 98 insertions(+), 72 deletions(-)

diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c
index 786bcab2bf5e..c506edae0fc9 100644
--- a/sys/compat/linux/linux_signal.c
+++ b/sys/compat/linux/linux_signal.c
@@ -58,8 +58,13 @@ __FBSDID("$FreeBSD$");
 #include <compat/linux/linux_emul.h>
 #include <compat/linux/linux_misc.h>
 
-static int     linux_do_tkill(struct thread *td, struct thread *tdt,
+static int     linux_pksignal(struct thread *td, int pid, int sig,
                    ksiginfo_t *ksi);
+static int     linux_psignal(struct thread *td, int pid, int sig);
+static int     linux_tdksignal(struct thread *td, lwpid_t tid,
+                   int tgid, int sig, ksiginfo_t *ksi);
+static int     linux_tdsignal(struct thread *td, lwpid_t tid,
+                   int tgid, int sig);
 static void    sicode_to_lsicode(int si_code, int *lsi_code);
 static int     linux_common_rt_sigtimedwait(struct thread *,
                    l_sigset_t *, struct timespec *, l_siginfo_t *,
@@ -510,7 +515,7 @@ linux_rt_sigtimedwait_time64(struct thread *td,
 int
 linux_kill(struct thread *td, struct linux_kill_args *args)
 {
-       int l_signum;
+       int sig;
 
        /*
         * Allow signal 0 as a means to check for privileges
@@ -519,40 +524,19 @@ linux_kill(struct thread *td, struct linux_kill_args 
*args)
                return (EINVAL);
 
        if (args->signum > 0)
-               l_signum = linux_to_bsd_signal(args->signum);
+               sig = linux_to_bsd_signal(args->signum);
        else
-               l_signum = 0;
-
-       return (kern_kill(td, args->pid, l_signum));
-}
-
-static int
-linux_do_tkill(struct thread *td, struct thread *tdt, ksiginfo_t *ksi)
-{
-       struct proc *p;
-       int error;
-
-       p = tdt->td_proc;
-       AUDIT_ARG_SIGNUM(ksi->ksi_signo);
-       AUDIT_ARG_PID(p->p_pid);
-       AUDIT_ARG_PROCESS(p);
-
-       error = p_cansignal(td, p, ksi->ksi_signo);
-       if (error != 0 || ksi->ksi_signo == 0)
-               goto out;
-
-       tdksignal(tdt, ksi->ksi_signo, ksi);
+               sig = 0;
 
-out:
-       PROC_UNLOCK(p);
-       return (error);
+       if (args->pid > PID_MAX)
+               return (linux_psignal(td, args->pid, sig));
+       else
+               return (kern_kill(td, args->pid, sig));
 }
 
 int
 linux_tgkill(struct thread *td, struct linux_tgkill_args *args)
 {
-       struct thread *tdt;
-       ksiginfo_t ksi;
        int sig;
 
        if (args->pid <= 0 || args->tgid <=0)
@@ -569,17 +553,7 @@ linux_tgkill(struct thread *td, struct linux_tgkill_args 
*args)
        else
                sig = 0;
 
-       tdt = linux_tdfind(td, args->pid, args->tgid);
-       if (tdt == NULL)
-               return (ESRCH);
-
-       ksiginfo_init(&ksi);
-       ksi.ksi_signo = sig;
-       ksi.ksi_code = SI_LWP;
-       ksi.ksi_errno = 0;
-       ksi.ksi_pid = td->td_proc->p_pid;
-       ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
-       return (linux_do_tkill(td, tdt, &ksi));
+       return (linux_tdsignal(td, args->pid, args->tgid, sig));
 }
 
 /*
@@ -588,8 +562,6 @@ linux_tgkill(struct thread *td, struct linux_tgkill_args 
*args)
 int
 linux_tkill(struct thread *td, struct linux_tkill_args *args)
 {
-       struct thread *tdt;
-       ksiginfo_t ksi;
        int sig;
 
        if (args->tid <= 0)
@@ -600,17 +572,7 @@ linux_tkill(struct thread *td, struct linux_tkill_args 
*args)
 
        sig = linux_to_bsd_signal(args->sig);
 
-       tdt = linux_tdfind(td, args->tid, -1);
-       if (tdt == NULL)
-               return (ESRCH);
-
-       ksiginfo_init(&ksi);
-       ksi.ksi_signo = sig;
-       ksi.ksi_code = SI_LWP;
-       ksi.ksi_errno = 0;
-       ksi.ksi_pid = td->td_proc->p_pid;
-       ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
-       return (linux_do_tkill(td, tdt, &ksi));
+       return (linux_tdsignal(td, args->tid, -1, sig));
 }
 
 static void
@@ -756,7 +718,6 @@ int
 linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args 
*args)
 {
        l_siginfo_t linfo;
-       struct proc *p;
        ksiginfo_t ksi;
        int error;
        int sig;
@@ -778,25 +739,13 @@ linux_rt_sigqueueinfo(struct thread *td, struct 
linux_rt_sigqueueinfo_args *args
        if (error != 0)
                return (error);
 
-       error = ESRCH;
-       if ((p = pfind_any(args->pid)) != NULL) {
-               error = p_cansignal(td, p, sig);
-               if (error != 0) {
-                       PROC_UNLOCK(p);
-                       return (error);
-               }
-               error = tdsendsignal(p, NULL, sig, &ksi);
-               PROC_UNLOCK(p);
-       }
-
-       return (error);
+       return (linux_pksignal(td, args->pid, sig, &ksi));
 }
 
 int
 linux_rt_tgsigqueueinfo(struct thread *td, struct linux_rt_tgsigqueueinfo_args 
*args)
 {
        l_siginfo_t linfo;
-       struct thread *tds;
        ksiginfo_t ksi;
        int error;
        int sig;
@@ -817,11 +766,7 @@ linux_rt_tgsigqueueinfo(struct thread *td, struct 
linux_rt_tgsigqueueinfo_args *
        if (error != 0)
                return (error);
 
-       tds = linux_tdfind(td, args->tid, args->tgid);
-       if (tds == NULL)
-               return (ESRCH);
-
-       return (linux_do_tkill(td, tds, &ksi));
+       return (linux_tdksignal(td, args->tid, args->tgid, sig, &ksi));
 }
 
 int
@@ -841,3 +786,84 @@ linux_rt_sigsuspend(struct thread *td, struct 
linux_rt_sigsuspend_args *uap)
        linux_to_bsd_sigset(&lmask, &sigmask);
        return (kern_sigsuspend(td, sigmask));
 }
+
+static int
+linux_tdksignal(struct thread *td, lwpid_t tid, int tgid, int sig,
+    ksiginfo_t *ksi)
+{
+       struct thread *tdt;
+       struct proc *p;
+       int error;
+
+       tdt = linux_tdfind(td, tid, tgid);
+       if (tdt == NULL)
+               return (ESRCH);
+
+       p = tdt->td_proc;
+       AUDIT_ARG_SIGNUM(sig);
+       AUDIT_ARG_PID(p->p_pid);
+       AUDIT_ARG_PROCESS(p);
+
+       error = p_cansignal(td, p, sig);
+       if (error != 0 || sig == 0)
+               goto out;
+
+       tdksignal(tdt, sig, ksi);
+
+out:
+       PROC_UNLOCK(p);
+       return (error);
+}
+
+static int
+linux_tdsignal(struct thread *td, lwpid_t tid, int tgid, int sig)
+{
+       ksiginfo_t ksi;
+
+       ksiginfo_init(&ksi);
+       ksi.ksi_signo = sig;
+       ksi.ksi_code = SI_LWP;
+       ksi.ksi_pid = td->td_proc->p_pid;
+       ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
+       return (linux_tdksignal(td, tid, tgid, sig, &ksi));
+}
+
+static int
+linux_pksignal(struct thread *td, int pid, int sig, ksiginfo_t *ksi)
+{
+       struct thread *tdt;
+       struct proc *p;
+       int error;
+
+       tdt = linux_tdfind(td, pid, -1);
+       if (tdt == NULL)
+               return (ESRCH);
+
+       p = tdt->td_proc;
+       AUDIT_ARG_SIGNUM(sig);
+       AUDIT_ARG_PID(p->p_pid);
+       AUDIT_ARG_PROCESS(p);
+
+       error = p_cansignal(td, p, sig);
+       if (error != 0 || sig == 0)
+               goto out;
+
+       pksignal(p, sig, ksi);
+
+out:
+       PROC_UNLOCK(p);
+       return (error);
+}
+
+static int
+linux_psignal(struct thread *td, int pid, int sig)
+{
+       ksiginfo_t ksi;
+
+       ksiginfo_init(&ksi);
+       ksi.ksi_signo = sig;
+       ksi.ksi_code = SI_LWP;
+       ksi.ksi_pid = td->td_proc->p_pid;
+       ksi.ksi_uid = td->td_proc->p_ucred->cr_ruid;
+       return (linux_pksignal(td, pid, sig, &ksi));
+}

Reply via email to