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 *);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to