mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-03 07:04:53 +00:00
Among signal generation syscalls, only sigqueue(2) is allowed by POSIX
to fail due to lack of resources to queue siginfo. Add KSI_SIGQ flag that allows sigqueue_add() to fail while trying to allocate memory for new siginfo. When the flag is not set, behaviour is the same as for KSI_TRAP: if memory cannot be allocated, set bit in sq_kill. KSI_TRAP is kept to preserve KBI. Add SI_KERNEL si_code, to be used in siginfo.si_code when signal is generated by kernel. Deliver siginfo when signal is generated by kill(2) family of syscalls (SI_USER with properly filled si_uid and si_pid), or by kernel (SI_KERNEL, mostly job control or SIGIO). Since KSI_SIGQ flag is not set for the ksi, low memory condition cause old behaviour. Keep psignal(9) KBI intact, but modify it to generate SI_KERNEL si_code. Pgsignal(9) and gsignal(9) now take ksi explicitely. Add pksignal(9) that behaves like psignal but takes ksi, and ddb kill command implemented as pksignal(..., ksi = NULL) to not do allocation while in debugger. While there, remove some register specifiers and use ANSI C prototypes. Reviewed by: davidxu MFC after: 1 month
This commit is contained in:
parent
5b412ffb6b
commit
a3de221dbe
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=199355
|
@ -652,7 +652,7 @@ db_kill(dummy1, dummy2, dummy3, dummy4)
|
||||||
if (PROC_TRYLOCK(p) == 0)
|
if (PROC_TRYLOCK(p) == 0)
|
||||||
DB_ERROR(("Can't lock process with pid %ld\n", (long) pid));
|
DB_ERROR(("Can't lock process with pid %ld\n", (long) pid));
|
||||||
else {
|
else {
|
||||||
psignal(p, sig);
|
pksignal(p, sig, NULL);
|
||||||
PROC_UNLOCK(p);
|
PROC_UNLOCK(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,8 @@ SDT_PROBE_ARGTYPE(proc, kernel, , signal_discard, 2, "int");
|
||||||
|
|
||||||
static int coredump(struct thread *);
|
static int coredump(struct thread *);
|
||||||
static char *expand_name(const char *, uid_t, pid_t);
|
static char *expand_name(const char *, uid_t, pid_t);
|
||||||
static int killpg1(struct thread *td, int sig, int pgid, int all);
|
static int killpg1(struct thread *td, int sig, int pgid, int all,
|
||||||
|
ksiginfo_t *ksi);
|
||||||
static int issignal(struct thread *td, int stop_allowed);
|
static int issignal(struct thread *td, int stop_allowed);
|
||||||
static int sigprop(int sig);
|
static int sigprop(int sig);
|
||||||
static void tdsigwakeup(struct thread *, int, sig_t, int);
|
static void tdsigwakeup(struct thread *, int, sig_t, int);
|
||||||
|
@ -381,7 +382,8 @@ sigqueue_add(sigqueue_t *sq, int signo, ksiginfo_t *si)
|
||||||
ksi->ksi_sigq = sq;
|
ksi->ksi_sigq = sq;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((si->ksi_flags & KSI_TRAP) != 0) {
|
if ((si->ksi_flags & KSI_TRAP) != 0 ||
|
||||||
|
(si->ksi_flags & KSI_SIGQ) == 0) {
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
SIGADDSET(sq->sq_kill, signo);
|
SIGADDSET(sq->sq_kill, signo);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
@ -1611,11 +1613,9 @@ kern_sigaltstack(struct thread *td, stack_t *ss, stack_t *oss)
|
||||||
* cp is calling process.
|
* cp is calling process.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
killpg1(td, sig, pgid, all)
|
killpg1(struct thread *td, int sig, int pgid, int all, ksiginfo_t *ksi)
|
||||||
register struct thread *td;
|
|
||||||
int sig, pgid, all;
|
|
||||||
{
|
{
|
||||||
register struct proc *p;
|
struct proc *p;
|
||||||
struct pgrp *pgrp;
|
struct pgrp *pgrp;
|
||||||
int nfound = 0;
|
int nfound = 0;
|
||||||
|
|
||||||
|
@ -1634,7 +1634,7 @@ killpg1(td, sig, pgid, all)
|
||||||
if (p_cansignal(td, p, sig) == 0) {
|
if (p_cansignal(td, p, sig) == 0) {
|
||||||
nfound++;
|
nfound++;
|
||||||
if (sig)
|
if (sig)
|
||||||
psignal(p, sig);
|
pksignal(p, sig, ksi);
|
||||||
}
|
}
|
||||||
PROC_UNLOCK(p);
|
PROC_UNLOCK(p);
|
||||||
}
|
}
|
||||||
|
@ -1665,7 +1665,7 @@ killpg1(td, sig, pgid, all)
|
||||||
if (p_cansignal(td, p, sig) == 0) {
|
if (p_cansignal(td, p, sig) == 0) {
|
||||||
nfound++;
|
nfound++;
|
||||||
if (sig)
|
if (sig)
|
||||||
psignal(p, sig);
|
pksignal(p, sig, ksi);
|
||||||
}
|
}
|
||||||
PROC_UNLOCK(p);
|
PROC_UNLOCK(p);
|
||||||
}
|
}
|
||||||
|
@ -1682,11 +1682,10 @@ struct kill_args {
|
||||||
#endif
|
#endif
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
int
|
int
|
||||||
kill(td, uap)
|
kill(struct thread *td, struct kill_args *uap)
|
||||||
register struct thread *td;
|
|
||||||
register struct kill_args *uap;
|
|
||||||
{
|
{
|
||||||
register struct proc *p;
|
ksiginfo_t ksi;
|
||||||
|
struct proc *p;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
AUDIT_ARG_SIGNUM(uap->signum);
|
AUDIT_ARG_SIGNUM(uap->signum);
|
||||||
|
@ -1694,6 +1693,12 @@ kill(td, uap)
|
||||||
if ((u_int)uap->signum > _SIG_MAXSIG)
|
if ((u_int)uap->signum > _SIG_MAXSIG)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
|
ksiginfo_init(&ksi);
|
||||||
|
ksi.ksi_signo = uap->signum;
|
||||||
|
ksi.ksi_code = SI_USER;
|
||||||
|
ksi.ksi_pid = td->td_proc->p_pid;
|
||||||
|
ksi.ksi_uid = td->td_ucred->cr_ruid;
|
||||||
|
|
||||||
if (uap->pid > 0) {
|
if (uap->pid > 0) {
|
||||||
/* kill single process */
|
/* kill single process */
|
||||||
if ((p = pfind(uap->pid)) == NULL) {
|
if ((p = pfind(uap->pid)) == NULL) {
|
||||||
|
@ -1703,17 +1708,17 @@ kill(td, uap)
|
||||||
AUDIT_ARG_PROCESS(p);
|
AUDIT_ARG_PROCESS(p);
|
||||||
error = p_cansignal(td, p, uap->signum);
|
error = p_cansignal(td, p, uap->signum);
|
||||||
if (error == 0 && uap->signum)
|
if (error == 0 && uap->signum)
|
||||||
psignal(p, uap->signum);
|
pksignal(p, uap->signum, &ksi);
|
||||||
PROC_UNLOCK(p);
|
PROC_UNLOCK(p);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
switch (uap->pid) {
|
switch (uap->pid) {
|
||||||
case -1: /* broadcast signal */
|
case -1: /* broadcast signal */
|
||||||
return (killpg1(td, uap->signum, 0, 1));
|
return (killpg1(td, uap->signum, 0, 1, &ksi));
|
||||||
case 0: /* signal own process group */
|
case 0: /* signal own process group */
|
||||||
return (killpg1(td, uap->signum, 0, 0));
|
return (killpg1(td, uap->signum, 0, 0, &ksi));
|
||||||
default: /* negative explicit process group */
|
default: /* negative explicit process group */
|
||||||
return (killpg1(td, uap->signum, -uap->pid, 0));
|
return (killpg1(td, uap->signum, -uap->pid, 0, &ksi));
|
||||||
}
|
}
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
@ -1727,17 +1732,21 @@ struct okillpg_args {
|
||||||
#endif
|
#endif
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
int
|
int
|
||||||
okillpg(td, uap)
|
okillpg(struct thread *td, struct okillpg_args *uap)
|
||||||
struct thread *td;
|
|
||||||
register struct okillpg_args *uap;
|
|
||||||
{
|
{
|
||||||
|
ksiginfo_t ksi;
|
||||||
|
|
||||||
AUDIT_ARG_SIGNUM(uap->signum);
|
AUDIT_ARG_SIGNUM(uap->signum);
|
||||||
AUDIT_ARG_PID(uap->pgid);
|
AUDIT_ARG_PID(uap->pgid);
|
||||||
if ((u_int)uap->signum > _SIG_MAXSIG)
|
if ((u_int)uap->signum > _SIG_MAXSIG)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
return (killpg1(td, uap->signum, uap->pgid, 0));
|
ksiginfo_init(&ksi);
|
||||||
|
ksi.ksi_signo = uap->signum;
|
||||||
|
ksi.ksi_code = SI_USER;
|
||||||
|
ksi.ksi_pid = td->td_proc->p_pid;
|
||||||
|
ksi.ksi_uid = td->td_ucred->cr_ruid;
|
||||||
|
return (killpg1(td, uap->signum, uap->pgid, 0, &ksi));
|
||||||
}
|
}
|
||||||
#endif /* COMPAT_43 */
|
#endif /* COMPAT_43 */
|
||||||
|
|
||||||
|
@ -1772,6 +1781,7 @@ sigqueue(struct thread *td, struct sigqueue_args *uap)
|
||||||
error = p_cansignal(td, p, uap->signum);
|
error = p_cansignal(td, p, uap->signum);
|
||||||
if (error == 0 && uap->signum != 0) {
|
if (error == 0 && uap->signum != 0) {
|
||||||
ksiginfo_init(&ksi);
|
ksiginfo_init(&ksi);
|
||||||
|
ksi.ksi_flags = KSI_SIGQ;
|
||||||
ksi.ksi_signo = uap->signum;
|
ksi.ksi_signo = uap->signum;
|
||||||
ksi.ksi_code = SI_QUEUE;
|
ksi.ksi_code = SI_QUEUE;
|
||||||
ksi.ksi_pid = td->td_proc->p_pid;
|
ksi.ksi_pid = td->td_proc->p_pid;
|
||||||
|
@ -1787,8 +1797,7 @@ sigqueue(struct thread *td, struct sigqueue_args *uap)
|
||||||
* Send a signal to a process group.
|
* Send a signal to a process group.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
gsignal(pgid, sig)
|
gsignal(int pgid, int sig, ksiginfo_t *ksi)
|
||||||
int pgid, sig;
|
|
||||||
{
|
{
|
||||||
struct pgrp *pgrp;
|
struct pgrp *pgrp;
|
||||||
|
|
||||||
|
@ -1797,7 +1806,7 @@ gsignal(pgid, sig)
|
||||||
pgrp = pgfind(pgid);
|
pgrp = pgfind(pgid);
|
||||||
sx_sunlock(&proctree_lock);
|
sx_sunlock(&proctree_lock);
|
||||||
if (pgrp != NULL) {
|
if (pgrp != NULL) {
|
||||||
pgsignal(pgrp, sig, 0);
|
pgsignal(pgrp, sig, 0, ksi);
|
||||||
PGRP_UNLOCK(pgrp);
|
PGRP_UNLOCK(pgrp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1808,18 +1817,16 @@ gsignal(pgid, sig)
|
||||||
* limit to members which have a controlling terminal.
|
* limit to members which have a controlling terminal.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
pgsignal(pgrp, sig, checkctty)
|
pgsignal(struct pgrp *pgrp, int sig, int checkctty, ksiginfo_t *ksi)
|
||||||
struct pgrp *pgrp;
|
|
||||||
int sig, checkctty;
|
|
||||||
{
|
{
|
||||||
register struct proc *p;
|
struct proc *p;
|
||||||
|
|
||||||
if (pgrp) {
|
if (pgrp) {
|
||||||
PGRP_LOCK_ASSERT(pgrp, MA_OWNED);
|
PGRP_LOCK_ASSERT(pgrp, MA_OWNED);
|
||||||
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
|
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
|
||||||
PROC_LOCK(p);
|
PROC_LOCK(p);
|
||||||
if (checkctty == 0 || p->p_flag & P_CONTROLT)
|
if (checkctty == 0 || p->p_flag & P_CONTROLT)
|
||||||
psignal(p, sig);
|
pksignal(p, sig, ksi);
|
||||||
PROC_UNLOCK(p);
|
PROC_UNLOCK(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1940,7 +1947,19 @@ sigtd(struct proc *p, int sig, int prop)
|
||||||
void
|
void
|
||||||
psignal(struct proc *p, int sig)
|
psignal(struct proc *p, int sig)
|
||||||
{
|
{
|
||||||
(void) tdsignal(p, NULL, sig, NULL);
|
ksiginfo_t ksi;
|
||||||
|
|
||||||
|
ksiginfo_init(&ksi);
|
||||||
|
ksi.ksi_signo = sig;
|
||||||
|
ksi.ksi_code = SI_KERNEL;
|
||||||
|
(void) tdsignal(p, NULL, sig, &ksi);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pksignal(struct proc *p, int sig, ksiginfo_t *ksi)
|
||||||
|
{
|
||||||
|
|
||||||
|
(void) tdsignal(p, NULL, sig, ksi);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -3143,8 +3162,13 @@ pgsigio(sigiop, sig, checkctty)
|
||||||
struct sigio **sigiop;
|
struct sigio **sigiop;
|
||||||
int sig, checkctty;
|
int sig, checkctty;
|
||||||
{
|
{
|
||||||
|
ksiginfo_t ksi;
|
||||||
struct sigio *sigio;
|
struct sigio *sigio;
|
||||||
|
|
||||||
|
ksiginfo_init(&ksi);
|
||||||
|
ksi.ksi_signo = sig;
|
||||||
|
ksi.ksi_code = SI_KERNEL;
|
||||||
|
|
||||||
SIGIO_LOCK();
|
SIGIO_LOCK();
|
||||||
sigio = *sigiop;
|
sigio = *sigiop;
|
||||||
if (sigio == NULL) {
|
if (sigio == NULL) {
|
||||||
|
|
|
@ -355,6 +355,7 @@ tty_wait_background(struct tty *tp, struct thread *td, int sig)
|
||||||
{
|
{
|
||||||
struct proc *p = td->td_proc;
|
struct proc *p = td->td_proc;
|
||||||
struct pgrp *pg;
|
struct pgrp *pg;
|
||||||
|
ksiginfo_t ksi;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
MPASS(sig == SIGTTIN || sig == SIGTTOU);
|
MPASS(sig == SIGTTIN || sig == SIGTTOU);
|
||||||
|
@ -396,8 +397,14 @@ tty_wait_background(struct tty *tp, struct thread *td, int sig)
|
||||||
* Send the signal and sleep until we're the new
|
* Send the signal and sleep until we're the new
|
||||||
* foreground process group.
|
* foreground process group.
|
||||||
*/
|
*/
|
||||||
|
if (sig != 0) {
|
||||||
|
ksiginfo_init(&ksi);
|
||||||
|
ksi.ksi_code = SI_KERNEL;
|
||||||
|
ksi.ksi_signo = sig;
|
||||||
|
sig = 0;
|
||||||
|
}
|
||||||
PGRP_LOCK(pg);
|
PGRP_LOCK(pg);
|
||||||
pgsignal(pg, sig, 1);
|
pgsignal(pg, ksi.ksi_signo, 1, &ksi);
|
||||||
PGRP_UNLOCK(pg);
|
PGRP_UNLOCK(pg);
|
||||||
|
|
||||||
error = tty_wait(tp, &tp->t_bgwait);
|
error = tty_wait(tp, &tp->t_bgwait);
|
||||||
|
@ -1240,6 +1247,8 @@ tty_signal_sessleader(struct tty *tp, int sig)
|
||||||
void
|
void
|
||||||
tty_signal_pgrp(struct tty *tp, int sig)
|
tty_signal_pgrp(struct tty *tp, int sig)
|
||||||
{
|
{
|
||||||
|
ksiginfo_t ksi;
|
||||||
|
|
||||||
tty_lock_assert(tp, MA_OWNED);
|
tty_lock_assert(tp, MA_OWNED);
|
||||||
MPASS(sig >= 1 && sig < NSIG);
|
MPASS(sig >= 1 && sig < NSIG);
|
||||||
|
|
||||||
|
@ -1249,8 +1258,11 @@ tty_signal_pgrp(struct tty *tp, int sig)
|
||||||
if (sig == SIGINFO && !(tp->t_termios.c_lflag & NOKERNINFO))
|
if (sig == SIGINFO && !(tp->t_termios.c_lflag & NOKERNINFO))
|
||||||
tty_info(tp);
|
tty_info(tp);
|
||||||
if (tp->t_pgrp != NULL) {
|
if (tp->t_pgrp != NULL) {
|
||||||
|
ksiginfo_init(&ksi);
|
||||||
|
ksi.ksi_signo = sig;
|
||||||
|
ksi.ksi_code = SI_KERNEL;
|
||||||
PGRP_LOCK(tp->t_pgrp);
|
PGRP_LOCK(tp->t_pgrp);
|
||||||
pgsignal(tp->t_pgrp, sig, 1);
|
pgsignal(tp->t_pgrp, sig, 1, &ksi);
|
||||||
PGRP_UNLOCK(tp->t_pgrp);
|
PGRP_UNLOCK(tp->t_pgrp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,6 +338,7 @@ struct sigaction {
|
||||||
/* an asynchronous I/O request.*/
|
/* an asynchronous I/O request.*/
|
||||||
#define SI_MESGQ 0x10005 /* Signal generated by arrival of a */
|
#define SI_MESGQ 0x10005 /* Signal generated by arrival of a */
|
||||||
/* message on an empty message queue. */
|
/* message on an empty message queue. */
|
||||||
|
#define SI_KERNEL 0x10006
|
||||||
#endif
|
#endif
|
||||||
#if __BSD_VISIBLE
|
#if __BSD_VISIBLE
|
||||||
#define SI_UNDEFINED 0
|
#define SI_UNDEFINED 0
|
||||||
|
|
|
@ -233,7 +233,8 @@ typedef struct ksiginfo {
|
||||||
#define KSI_TRAP 0x01 /* Generated by trap. */
|
#define KSI_TRAP 0x01 /* Generated by trap. */
|
||||||
#define KSI_EXT 0x02 /* Externally managed ksi. */
|
#define KSI_EXT 0x02 /* Externally managed ksi. */
|
||||||
#define KSI_INS 0x04 /* Directly insert ksi, not the copy */
|
#define KSI_INS 0x04 /* Directly insert ksi, not the copy */
|
||||||
#define KSI_COPYMASK KSI_TRAP
|
#define KSI_SIGQ 0x08 /* Generated by sigqueue, might ret EGAIN. */
|
||||||
|
#define KSI_COPYMASK (KSI_TRAP|KSI_SIGQ)
|
||||||
|
|
||||||
#define KSI_ONQ(ksi) ((ksi)->ksi_sigq != NULL)
|
#define KSI_ONQ(ksi) ((ksi)->ksi_sigq != NULL)
|
||||||
|
|
||||||
|
@ -326,10 +327,11 @@ extern int kern_logsigexit; /* Sysctl variable kern.logsigexit */
|
||||||
*/
|
*/
|
||||||
int cursig(struct thread *td, int stop_allowed);
|
int cursig(struct thread *td, int stop_allowed);
|
||||||
void execsigs(struct proc *p);
|
void execsigs(struct proc *p);
|
||||||
void gsignal(int pgid, int sig);
|
void gsignal(int pgid, int sig, ksiginfo_t *ksi);
|
||||||
void killproc(struct proc *p, char *why);
|
void killproc(struct proc *p, char *why);
|
||||||
|
void pksignal(struct proc *p, int sig, ksiginfo_t *ksi);
|
||||||
void pgsigio(struct sigio **, int signum, int checkctty);
|
void pgsigio(struct sigio **, int signum, int checkctty);
|
||||||
void pgsignal(struct pgrp *pgrp, int sig, int checkctty);
|
void pgsignal(struct pgrp *pgrp, int sig, int checkctty, ksiginfo_t *ksi);
|
||||||
int postsig(int sig);
|
int postsig(int sig);
|
||||||
void psignal(struct proc *p, int sig);
|
void psignal(struct proc *p, int sig);
|
||||||
int psignal_event(struct proc *p, struct sigevent *, ksiginfo_t *);
|
int psignal_event(struct proc *p, struct sigevent *, ksiginfo_t *);
|
||||||
|
|
Loading…
Reference in a new issue