svn commit: r199355 - in head/sys: ddb kern sys

Konstantin Belousov kib at FreeBSD.org
Tue Nov 17 11:39:16 UTC 2009


Author: kib
Date: Tue Nov 17 11:39:15 2009
New Revision: 199355
URL: http://svn.freebsd.org/changeset/base/199355

Log:
  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

Modified:
  head/sys/ddb/db_command.c
  head/sys/kern/kern_sig.c
  head/sys/kern/tty.c
  head/sys/sys/signal.h
  head/sys/sys/signalvar.h

Modified: head/sys/ddb/db_command.c
==============================================================================
--- head/sys/ddb/db_command.c	Tue Nov 17 10:59:51 2009	(r199354)
+++ head/sys/ddb/db_command.c	Tue Nov 17 11:39:15 2009	(r199355)
@@ -652,7 +652,7 @@ db_kill(dummy1, dummy2, dummy3, dummy4)
 	if (PROC_TRYLOCK(p) == 0)
 		DB_ERROR(("Can't lock process with pid %ld\n", (long) pid));
 	else {
-		psignal(p, sig);
+		pksignal(p, sig, NULL);
 		PROC_UNLOCK(p);
 	}
 

Modified: head/sys/kern/kern_sig.c
==============================================================================
--- head/sys/kern/kern_sig.c	Tue Nov 17 10:59:51 2009	(r199354)
+++ head/sys/kern/kern_sig.c	Tue Nov 17 11:39:15 2009	(r199355)
@@ -99,7 +99,8 @@ SDT_PROBE_ARGTYPE(proc, kernel, , signal
 
 static int	coredump(struct thread *);
 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	sigprop(int sig);
 static void	tdsigwakeup(struct thread *, int, sig_t, int);
@@ -381,7 +382,8 @@ sigqueue_add(sigqueue_t *sq, int signo, 
 		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)
 			SIGADDSET(sq->sq_kill, signo);
 		ret = 0;
@@ -1611,11 +1613,9 @@ kern_sigaltstack(struct thread *td, stac
  * cp is calling process.
  */
 static int
-killpg1(td, sig, pgid, all)
-	register struct thread *td;
-	int sig, pgid, all;
+killpg1(struct thread *td, int sig, int pgid, int all, ksiginfo_t *ksi)
 {
-	register struct proc *p;
+	struct proc *p;
 	struct pgrp *pgrp;
 	int nfound = 0;
 
@@ -1634,7 +1634,7 @@ killpg1(td, sig, pgid, all)
 			if (p_cansignal(td, p, sig) == 0) {
 				nfound++;
 				if (sig)
-					psignal(p, sig);
+					pksignal(p, sig, ksi);
 			}
 			PROC_UNLOCK(p);
 		}
@@ -1665,7 +1665,7 @@ killpg1(td, sig, pgid, all)
 			if (p_cansignal(td, p, sig) == 0) {
 				nfound++;
 				if (sig)
-					psignal(p, sig);
+					pksignal(p, sig, ksi);
 			}
 			PROC_UNLOCK(p);
 		}
@@ -1682,11 +1682,10 @@ struct kill_args {
 #endif
 /* ARGSUSED */
 int
-kill(td, uap)
-	register struct thread *td;
-	register struct kill_args *uap;
+kill(struct thread *td, struct kill_args *uap)
 {
-	register struct proc *p;
+	ksiginfo_t ksi;
+	struct proc *p;
 	int error;
 
 	AUDIT_ARG_SIGNUM(uap->signum);
@@ -1694,6 +1693,12 @@ kill(td, uap)
 	if ((u_int)uap->signum > _SIG_MAXSIG)
 		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) {
 		/* kill single process */
 		if ((p = pfind(uap->pid)) == NULL) {
@@ -1703,17 +1708,17 @@ kill(td, uap)
 		AUDIT_ARG_PROCESS(p);
 		error = p_cansignal(td, p, uap->signum);
 		if (error == 0 && uap->signum)
-			psignal(p, uap->signum);
+			pksignal(p, uap->signum, &ksi);
 		PROC_UNLOCK(p);
 		return (error);
 	}
 	switch (uap->pid) {
 	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 */
-		return (killpg1(td, uap->signum, 0, 0));
+		return (killpg1(td, uap->signum, 0, 0, &ksi));
 	default:		/* negative explicit process group */
-		return (killpg1(td, uap->signum, -uap->pid, 0));
+		return (killpg1(td, uap->signum, -uap->pid, 0, &ksi));
 	}
 	/* NOTREACHED */
 }
@@ -1727,17 +1732,21 @@ struct okillpg_args {
 #endif
 /* ARGSUSED */
 int
-okillpg(td, uap)
-	struct thread *td;
-	register struct okillpg_args *uap;
+okillpg(struct thread *td, struct okillpg_args *uap)
 {
+	ksiginfo_t ksi;
 
 	AUDIT_ARG_SIGNUM(uap->signum);
 	AUDIT_ARG_PID(uap->pgid);
 	if ((u_int)uap->signum > _SIG_MAXSIG)
 		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 */
 
@@ -1772,6 +1781,7 @@ sigqueue(struct thread *td, struct sigqu
 	error = p_cansignal(td, p, uap->signum);
 	if (error == 0 && uap->signum != 0) {
 		ksiginfo_init(&ksi);
+		ksi.ksi_flags = KSI_SIGQ;
 		ksi.ksi_signo = uap->signum;
 		ksi.ksi_code = SI_QUEUE;
 		ksi.ksi_pid = td->td_proc->p_pid;
@@ -1787,8 +1797,7 @@ sigqueue(struct thread *td, struct sigqu
  * Send a signal to a process group.
  */
 void
-gsignal(pgid, sig)
-	int pgid, sig;
+gsignal(int pgid, int sig, ksiginfo_t *ksi)
 {
 	struct pgrp *pgrp;
 
@@ -1797,7 +1806,7 @@ gsignal(pgid, sig)
 		pgrp = pgfind(pgid);
 		sx_sunlock(&proctree_lock);
 		if (pgrp != NULL) {
-			pgsignal(pgrp, sig, 0);
+			pgsignal(pgrp, sig, 0, ksi);
 			PGRP_UNLOCK(pgrp);
 		}
 	}
@@ -1808,18 +1817,16 @@ gsignal(pgid, sig)
  * limit to members which have a controlling terminal.
  */
 void
-pgsignal(pgrp, sig, checkctty)
-	struct pgrp *pgrp;
-	int sig, checkctty;
+pgsignal(struct pgrp *pgrp, int sig, int checkctty, ksiginfo_t *ksi)
 {
-	register struct proc *p;
+	struct proc *p;
 
 	if (pgrp) {
 		PGRP_LOCK_ASSERT(pgrp, MA_OWNED);
 		LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
 			PROC_LOCK(p);
 			if (checkctty == 0 || p->p_flag & P_CONTROLT)
-				psignal(p, sig);
+				pksignal(p, sig, ksi);
 			PROC_UNLOCK(p);
 		}
 	}
@@ -1940,7 +1947,19 @@ sigtd(struct proc *p, int sig, int prop)
 void
 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
@@ -3143,8 +3162,13 @@ pgsigio(sigiop, sig, checkctty)
 	struct sigio **sigiop;
 	int sig, checkctty;
 {
+	ksiginfo_t ksi;
 	struct sigio *sigio;
 
+	ksiginfo_init(&ksi);
+	ksi.ksi_signo = sig;
+	ksi.ksi_code = SI_KERNEL;
+
 	SIGIO_LOCK();
 	sigio = *sigiop;
 	if (sigio == NULL) {

Modified: head/sys/kern/tty.c
==============================================================================
--- head/sys/kern/tty.c	Tue Nov 17 10:59:51 2009	(r199354)
+++ head/sys/kern/tty.c	Tue Nov 17 11:39:15 2009	(r199355)
@@ -355,6 +355,7 @@ tty_wait_background(struct tty *tp, stru
 {
 	struct proc *p = td->td_proc;
 	struct pgrp *pg;
+	ksiginfo_t ksi;
 	int error;
 
 	MPASS(sig == SIGTTIN || sig == SIGTTOU);
@@ -396,8 +397,14 @@ tty_wait_background(struct tty *tp, stru
 		 * Send the signal and sleep until we're the new
 		 * foreground process group.
 		 */
+		if (sig != 0) {
+			ksiginfo_init(&ksi);
+			ksi.ksi_code = SI_KERNEL;
+			ksi.ksi_signo = sig;
+			sig = 0;
+		}
 		PGRP_LOCK(pg);
-		pgsignal(pg, sig, 1);
+		pgsignal(pg, ksi.ksi_signo, 1, &ksi);
 		PGRP_UNLOCK(pg);
 
 		error = tty_wait(tp, &tp->t_bgwait);
@@ -1240,6 +1247,8 @@ tty_signal_sessleader(struct tty *tp, in
 void
 tty_signal_pgrp(struct tty *tp, int sig)
 {
+	ksiginfo_t ksi;
+
 	tty_lock_assert(tp, MA_OWNED);
 	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))
 		tty_info(tp);
 	if (tp->t_pgrp != NULL) {
+		ksiginfo_init(&ksi);
+		ksi.ksi_signo = sig;
+		ksi.ksi_code = SI_KERNEL;
 		PGRP_LOCK(tp->t_pgrp);
-		pgsignal(tp->t_pgrp, sig, 1);
+		pgsignal(tp->t_pgrp, sig, 1, &ksi);
 		PGRP_UNLOCK(tp->t_pgrp);
 	}
 }

Modified: head/sys/sys/signal.h
==============================================================================
--- head/sys/sys/signal.h	Tue Nov 17 10:59:51 2009	(r199354)
+++ head/sys/sys/signal.h	Tue Nov 17 11:39:15 2009	(r199355)
@@ -338,6 +338,7 @@ struct sigaction {
 					/* an asynchronous I/O request.*/
 #define	SI_MESGQ	0x10005		/* Signal generated by arrival of a */
 					/* message on an empty message queue. */
+#define	SI_KERNEL	0x10006
 #endif
 #if __BSD_VISIBLE
 #define	SI_UNDEFINED	0

Modified: head/sys/sys/signalvar.h
==============================================================================
--- head/sys/sys/signalvar.h	Tue Nov 17 10:59:51 2009	(r199354)
+++ head/sys/sys/signalvar.h	Tue Nov 17 11:39:15 2009	(r199355)
@@ -233,7 +233,8 @@ typedef struct ksiginfo {
 #define KSI_TRAP	0x01	/* Generated by trap. */
 #define	KSI_EXT		0x02	/* Externally managed ksi. */
 #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)
 
@@ -326,10 +327,11 @@ extern int kern_logsigexit;	/* Sysctl va
  */
 int	cursig(struct thread *td, int stop_allowed);
 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	pksignal(struct proc *p, int sig, ksiginfo_t *ksi);
 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);
 void	psignal(struct proc *p, int sig);
 int	psignal_event(struct proc *p, struct sigevent *, ksiginfo_t *);


More information about the svn-src-all mailing list