kern/142757: commit references a PR

dfilter service dfilter at FreeBSD.ORG
Wed Jan 20 12:00:22 UTC 2010


The following reply was made to PR kern/142757; it has been noted by GNATS.

From: dfilter at FreeBSD.ORG (dfilter service)
To: bug-followup at FreeBSD.org
Cc:  
Subject: Re: kern/142757: commit references a PR
Date: Wed, 20 Jan 2010 11:58:16 +0000 (UTC)

 Author: kib
 Date: Wed Jan 20 11:58:04 2010
 New Revision: 202692
 URL: http://svn.freebsd.org/changeset/base/202692
 
 Log:
   When traced process is about to receive the signal, the process is
   stopped and debugger may modify or drop the signal. After the changes to
   keep process-targeted signals on the process sigqueue, another thread
   may note the old signal on the queue and act before the thread removes
   changed or dropped signal from the process queue. Since process is
   traced, it usually gets stopped. Or, if the same signal is delivered
   while process was stopped, the thread may erronously remove it,
   intending to remove the original signal.
   
   Remove the signal from the queue before notifying the debugger. Restore
   the siginfo to the head of sigqueue when signal is allowed to be
   delivered to the debugee, using newly introduced KSI_HEAD ksiginfo_t
   flag. This preserves required order of delivery. Always restore the
   unchanged signal on the curthread sigqueue, not to the process queue,
   since the thread is about to get it anyway, because sigmask cannot be
   changed.
   
   Handle failure of reinserting the siginfo into the queue by falling
   back to sq_kill method, calling sigqueue_add with NULL ksi.
   
   If debugger changed the signal to be delivered, use sigqueue_add()
   with NULL ksi instead of only setting sq_signals bit.
   
   Reported by:	Gardner Bell <gbell72 rogers com>
   Analyzed and first version of fix by:	Tijl Coosemans <tijl coosemans org>
   PR:	142757
   Reviewed by:	davidxu
   MFC after:	2 weeks
 
 Modified:
   head/sys/kern/kern_sig.c
   head/sys/sys/signalvar.h
 
 Modified: head/sys/kern/kern_sig.c
 ==============================================================================
 --- head/sys/kern/kern_sig.c	Wed Jan 20 11:55:14 2010	(r202691)
 +++ head/sys/kern/kern_sig.c	Wed Jan 20 11:58:04 2010	(r202692)
 @@ -357,7 +357,10 @@ sigqueue_add(sigqueue_t *sq, int signo, 
  
  	/* directly insert the ksi, don't copy it */
  	if (si->ksi_flags & KSI_INS) {
 -		TAILQ_INSERT_TAIL(&sq->sq_list, si, ksi_link);
 +		if (si->ksi_flags & KSI_HEAD)
 +			TAILQ_INSERT_HEAD(&sq->sq_list, si, ksi_link);
 +		else
 +			TAILQ_INSERT_TAIL(&sq->sq_list, si, ksi_link);
  		si->ksi_sigq = sq;
  		goto out_set_bit;
  	}
 @@ -378,7 +381,10 @@ sigqueue_add(sigqueue_t *sq, int signo, 
  			p->p_pendingcnt++;
  		ksiginfo_copy(si, ksi);
  		ksi->ksi_signo = signo;
 -		TAILQ_INSERT_TAIL(&sq->sq_list, ksi, ksi_link);
 +		if (si->ksi_flags & KSI_HEAD)
 +			TAILQ_INSERT_HEAD(&sq->sq_list, ksi, ksi_link);
 +		else
 +			TAILQ_INSERT_TAIL(&sq->sq_list, ksi, ksi_link);
  		ksi->ksi_sigq = sq;
  	}
  
 @@ -2492,6 +2498,7 @@ issignal(struct thread *td, int stop_all
  	struct sigacts *ps;
  	struct sigqueue *queue;
  	sigset_t sigpending;
 +	ksiginfo_t ksi;
  	int sig, prop, newsig;
  
  	p = td->td_proc;
 @@ -2529,24 +2536,22 @@ issignal(struct thread *td, int stop_all
  		if (p->p_flag & P_TRACED && (p->p_flag & P_PPWAIT) == 0) {
  			/*
  			 * If traced, always stop.
 +			 * Remove old signal from queue before the stop.
 +			 * XXX shrug off debugger, it causes siginfo to
 +			 * be thrown away.
  			 */
 +			queue = &td->td_sigqueue;
 +			ksi.ksi_signo = 0;
 +			if (sigqueue_get(queue, sig, &ksi) == 0) {
 +				queue = &p->p_sigqueue;
 +				sigqueue_get(queue, sig, &ksi);
 +			}
 +
  			mtx_unlock(&ps->ps_mtx);
  			newsig = ptracestop(td, sig);
  			mtx_lock(&ps->ps_mtx);
  
  			if (sig != newsig) {
 -				ksiginfo_t ksi;
 -
 -				queue = &td->td_sigqueue;
 -				/*
 -				 * clear old signal.
 -				 * XXX shrug off debugger, it causes siginfo to
 -				 * be thrown away.
 -				 */
 -				if (sigqueue_get(queue, sig, &ksi) == 0) {
 -					queue = &p->p_sigqueue;
 -					sigqueue_get(queue, sig, &ksi);
 -				}
  
  				/*
  				 * If parent wants us to take the signal,
 @@ -2561,10 +2566,20 @@ issignal(struct thread *td, int stop_all
  				 * Put the new signal into td_sigqueue. If the
  				 * signal is being masked, look for other signals.
  				 */
 -				SIGADDSET(queue->sq_signals, sig);
 +				sigqueue_add(queue, sig, NULL);
  				if (SIGISMEMBER(td->td_sigmask, sig))
  					continue;
  				signotify(td);
 +			} else {
 +				if (ksi.ksi_signo != 0) {
 +					ksi.ksi_flags |= KSI_HEAD;
 +					if (sigqueue_add(&td->td_sigqueue, sig,
 +					    &ksi) != 0)
 +						ksi.ksi_signo = 0;
 +				}
 +				if (ksi.ksi_signo == 0)
 +					sigqueue_add(&td->td_sigqueue, sig,
 +					    NULL);
  			}
  
  			/*
 
 Modified: head/sys/sys/signalvar.h
 ==============================================================================
 --- head/sys/sys/signalvar.h	Wed Jan 20 11:55:14 2010	(r202691)
 +++ head/sys/sys/signalvar.h	Wed Jan 20 11:58:04 2010	(r202692)
 @@ -234,6 +234,7 @@ typedef struct ksiginfo {
  #define	KSI_EXT		0x02	/* Externally managed ksi. */
  #define KSI_INS		0x04	/* Directly insert ksi, not the copy */
  #define	KSI_SIGQ	0x08	/* Generated by sigqueue, might ret EGAIN. */
 +#define	KSI_HEAD	0x10	/* Insert into head, not tail. */
  #define	KSI_COPYMASK	(KSI_TRAP|KSI_SIGQ)
  
  #define	KSI_ONQ(ksi)	((ksi)->ksi_sigq != NULL)
 _______________________________________________
 svn-src-all at freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe at freebsd.org"
 


More information about the freebsd-bugs mailing list