git: 70569346989b - stable/13 - linux(4): Refactor signal send methods.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 17 Jun 2022 19:39:16 UTC
The branch stable/13 has been updated by dchagin:
URL: https://cgit.FreeBSD.org/src/commit/?id=70569346989bed9c3a69bce22c4d8588ed347a09
commit 70569346989bed9c3a69bce22c4d8588ed347a09
Author: Dmitry Chagin <dchagin@FreeBSD.org>
AuthorDate: 2022-04-25 07:22:51 +0000
Commit: Dmitry Chagin <dchagin@FreeBSD.org>
CommitDate: 2022-06-17 19:33:55 +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
(cherry picked from commit 6201a50d0d6d98633dba3db12dea2dfe95295e0e)
---
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));
+}