2551 lines · 65.0 KB · C
RawDownload
/* *  linux/kernel/signal.c * *  Copyright (C) 1991, 1992  Linus Torvalds * *  1997-11-02  Modified for POSIX.1b signals by Richard Henderson * *  2003-06-02  Jim Houston - Concurrent Computer Corp. *		Changes to use preallocated sigqueue structures *		to allow signals to be sent reliably. */ #include <linux/config.h>#include <linux/slab.h>#include <linux/module.h>#include <linux/smp_lock.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/tty.h>#include <linux/binfmts.h>#include <linux/security.h>#include <linux/syscalls.h>#include <linux/ptrace.h>#include <linux/signal.h>#include <linux/capability.h>#include <asm/param.h>#include <asm/uaccess.h>#include <asm/unistd.h>#include <asm/siginfo.h>#include "audit.h"	/* audit_signal_info() */ /* * SLAB caches for signal bits. */ static kmem_cache_t *sigqueue_cachep; /* * In POSIX a signal is sent either to a specific thread (Linux task) * or to the process as a whole (Linux thread group).  How the signal * is sent determines whether it's to one thread or the whole group, * which determines which signal mask(s) are involved in blocking it * from being delivered until later.  When the signal is delivered, * either it's caught or ignored by a user handler or it has a default * effect that applies to the whole thread group (POSIX process). * * The possible effects an unblocked signal set to SIG_DFL can have are: *   ignore	- Nothing Happens *   terminate	- kill the process, i.e. all threads in the group, * 		  similar to exit_group.  The group leader (only) reports *		  WIFSIGNALED status to its parent. *   coredump	- write a core dump file describing all threads using *		  the same mm and then kill all those threads *   stop 	- stop all the threads in the group, i.e. TASK_STOPPED state * * SIGKILL and SIGSTOP cannot be caught, blocked, or ignored. * Other signals when not blocked and set to SIG_DFL behaves as follows. * The job control signals also have other special effects. * *	+--------------------+------------------+ *	|  POSIX signal      |  default action  | *	+--------------------+------------------+ *	|  SIGHUP            |  terminate	| *	|  SIGINT            |	terminate	| *	|  SIGQUIT           |	coredump 	| *	|  SIGILL            |	coredump 	| *	|  SIGTRAP           |	coredump 	| *	|  SIGABRT/SIGIOT    |	coredump 	| *	|  SIGBUS            |	coredump 	| *	|  SIGFPE            |	coredump 	| *	|  SIGKILL           |	terminate(+)	| *	|  SIGUSR1           |	terminate	| *	|  SIGSEGV           |	coredump 	| *	|  SIGUSR2           |	terminate	| *	|  SIGPIPE           |	terminate	| *	|  SIGALRM           |	terminate	| *	|  SIGTERM           |	terminate	| *	|  SIGCHLD           |	ignore   	| *	|  SIGCONT           |	ignore(*)	| *	|  SIGSTOP           |	stop(*)(+)  	| *	|  SIGTSTP           |	stop(*)  	| *	|  SIGTTIN           |	stop(*)  	| *	|  SIGTTOU           |	stop(*)  	| *	|  SIGURG            |	ignore   	| *	|  SIGXCPU           |	coredump 	| *	|  SIGXFSZ           |	coredump 	| *	|  SIGVTALRM         |	terminate	| *	|  SIGPROF           |	terminate	| *	|  SIGPOLL/SIGIO     |	terminate	| *	|  SIGSYS/SIGUNUSED  |	coredump 	| *	|  SIGSTKFLT         |	terminate	| *	|  SIGWINCH          |	ignore   	| *	|  SIGPWR            |	terminate	| *	|  SIGRTMIN-SIGRTMAX |	terminate       | *	+--------------------+------------------+ *	|  non-POSIX signal  |  default action  | *	+--------------------+------------------+ *	|  SIGEMT            |  coredump	| *	+--------------------+------------------+ * * (+) For SIGKILL and SIGSTOP the action is "always", not just "default". * (*) Special job control effects: * When SIGCONT is sent, it resumes the process (all threads in the group) * from TASK_STOPPED state and also clears any pending/queued stop signals * (any of those marked with "stop(*)").  This happens regardless of blocking, * catching, or ignoring SIGCONT.  When any stop signal is sent, it clears * any pending/queued SIGCONT signals; this happens regardless of blocking, * catching, or ignored the stop signal, though (except for SIGSTOP) the * default action of stopping the process may happen later or never. */ #ifdef SIGEMT#define M_SIGEMT	M(SIGEMT)#else#define M_SIGEMT	0#endif #if SIGRTMIN > BITS_PER_LONG#define M(sig) (1ULL << ((sig)-1))#else#define M(sig) (1UL << ((sig)-1))#endif#define T(sig, mask) (M(sig) & (mask)) #define SIG_KERNEL_ONLY_MASK (\	M(SIGKILL)   |  M(SIGSTOP)                                   ) #define SIG_KERNEL_STOP_MASK (\	M(SIGSTOP)   |  M(SIGTSTP)   |  M(SIGTTIN)   |  M(SIGTTOU)   ) #define SIG_KERNEL_COREDUMP_MASK (\        M(SIGQUIT)   |  M(SIGILL)    |  M(SIGTRAP)   |  M(SIGABRT)   | \        M(SIGFPE)    |  M(SIGSEGV)   |  M(SIGBUS)    |  M(SIGSYS)    | \        M(SIGXCPU)   |  M(SIGXFSZ)   |  M_SIGEMT                     ) #define SIG_KERNEL_IGNORE_MASK (\        M(SIGCONT)   |  M(SIGCHLD)   |  M(SIGWINCH)  |  M(SIGURG)    ) #define sig_kernel_only(sig) \		(((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_ONLY_MASK))#define sig_kernel_coredump(sig) \		(((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_COREDUMP_MASK))#define sig_kernel_ignore(sig) \		(((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_IGNORE_MASK))#define sig_kernel_stop(sig) \		(((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_STOP_MASK)) #define sig_needs_tasklist(sig)	((sig) == SIGCONT) #define sig_user_defined(t, signr) \	(((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_DFL) &&	\	 ((t)->sighand->action[(signr)-1].sa.sa_handler != SIG_IGN)) #define sig_fatal(t, signr) \	(!T(signr, SIG_KERNEL_IGNORE_MASK|SIG_KERNEL_STOP_MASK) && \	 (t)->sighand->action[(signr)-1].sa.sa_handler == SIG_DFL) static int sig_ignored(struct task_struct *t, int sig){	void __user * handler; 	/*	 * Tracers always want to know about signals..	 */	if (t->ptrace & PT_PTRACED)		return 0; 	/*	 * Blocked signals are never ignored, since the	 * signal handler may change by the time it is	 * unblocked.	 */	if (sigismember(&t->blocked, sig))		return 0; 	/* Is it explicitly or implicitly ignored? */	handler = t->sighand->action[sig-1].sa.sa_handler;	return   handler == SIG_IGN ||		(handler == SIG_DFL && sig_kernel_ignore(sig));} /* * Re-calculate pending state from the set of locally pending * signals, globally pending signals, and blocked signals. */static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked){	unsigned long ready;	long i; 	switch (_NSIG_WORDS) {	default:		for (i = _NSIG_WORDS, ready = 0; --i >= 0 ;)			ready |= signal->sig[i] &~ blocked->sig[i];		break; 	case 4: ready  = signal->sig[3] &~ blocked->sig[3];		ready |= signal->sig[2] &~ blocked->sig[2];		ready |= signal->sig[1] &~ blocked->sig[1];		ready |= signal->sig[0] &~ blocked->sig[0];		break; 	case 2: ready  = signal->sig[1] &~ blocked->sig[1];		ready |= signal->sig[0] &~ blocked->sig[0];		break; 	case 1: ready  = signal->sig[0] &~ blocked->sig[0];	}	return ready !=	0;} #define PENDING(p,b) has_pending_signals(&(p)->signal, (b)) fastcall void recalc_sigpending_tsk(struct task_struct *t){	if (t->signal->group_stop_count > 0 ||	    (freezing(t)) ||	    PENDING(&t->pending, &t->blocked) ||	    PENDING(&t->signal->shared_pending, &t->blocked))		set_tsk_thread_flag(t, TIF_SIGPENDING);	else		clear_tsk_thread_flag(t, TIF_SIGPENDING);} void recalc_sigpending(void){	recalc_sigpending_tsk(current);} /* Given the mask, find the first available signal that should be serviced. */ static intnext_signal(struct sigpending *pending, sigset_t *mask){	unsigned long i, *s, *m, x;	int sig = 0;		s = pending->signal.sig;	m = mask->sig;	switch (_NSIG_WORDS) {	default:		for (i = 0; i < _NSIG_WORDS; ++i, ++s, ++m)			if ((x = *s &~ *m) != 0) {				sig = ffz(~x) + i*_NSIG_BPW + 1;				break;			}		break; 	case 2: if ((x = s[0] &~ m[0]) != 0)			sig = 1;		else if ((x = s[1] &~ m[1]) != 0)			sig = _NSIG_BPW + 1;		else			break;		sig += ffz(~x);		break; 	case 1: if ((x = *s &~ *m) != 0)			sig = ffz(~x) + 1;		break;	}		return sig;} static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags,					 int override_rlimit){	struct sigqueue *q = NULL; 	atomic_inc(&t->user->sigpending);	if (override_rlimit ||	    atomic_read(&t->user->sigpending) <=			t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur)		q = kmem_cache_alloc(sigqueue_cachep, flags);	if (unlikely(q == NULL)) {		atomic_dec(&t->user->sigpending);	} else {		INIT_LIST_HEAD(&q->list);		q->flags = 0;		q->user = get_uid(t->user);	}	return(q);} static void __sigqueue_free(struct sigqueue *q){	if (q->flags & SIGQUEUE_PREALLOC)		return;	atomic_dec(&q->user->sigpending);	free_uid(q->user);	kmem_cache_free(sigqueue_cachep, q);} void flush_sigqueue(struct sigpending *queue){	struct sigqueue *q; 	sigemptyset(&queue->signal);	while (!list_empty(&queue->list)) {		q = list_entry(queue->list.next, struct sigqueue , list);		list_del_init(&q->list);		__sigqueue_free(q);	}} /* * Flush all pending signals for a task. */void flush_signals(struct task_struct *t){	unsigned long flags; 	spin_lock_irqsave(&t->sighand->siglock, flags);	clear_tsk_thread_flag(t,TIF_SIGPENDING);	flush_sigqueue(&t->pending);	flush_sigqueue(&t->signal->shared_pending);	spin_unlock_irqrestore(&t->sighand->siglock, flags);} /* * Flush all handlers for a task. */ voidflush_signal_handlers(struct task_struct *t, int force_default){	int i;	struct k_sigaction *ka = &t->sighand->action[0];	for (i = _NSIG ; i != 0 ; i--) {		if (force_default || ka->sa.sa_handler != SIG_IGN)			ka->sa.sa_handler = SIG_DFL;		ka->sa.sa_flags = 0;		sigemptyset(&ka->sa.sa_mask);		ka++;	}}  /* Notify the system that a driver wants to block all signals for this * process, and wants to be notified if any signals at all were to be * sent/acted upon.  If the notifier routine returns non-zero, then the * signal will be acted upon after all.  If the notifier routine returns 0, * then then signal will be blocked.  Only one block per process is * allowed.  priv is a pointer to private data that the notifier routine * can use to determine if the signal should be blocked or not.  */ voidblock_all_signals(int (*notifier)(void *priv), void *priv, sigset_t *mask){	unsigned long flags; 	spin_lock_irqsave(&current->sighand->siglock, flags);	current->notifier_mask = mask;	current->notifier_data = priv;	current->notifier = notifier;	spin_unlock_irqrestore(&current->sighand->siglock, flags);} /* Notify the system that blocking has ended. */ voidunblock_all_signals(void){	unsigned long flags; 	spin_lock_irqsave(&current->sighand->siglock, flags);	current->notifier = NULL;	current->notifier_data = NULL;	recalc_sigpending();	spin_unlock_irqrestore(&current->sighand->siglock, flags);} static int collect_signal(int sig, struct sigpending *list, siginfo_t *info){	struct sigqueue *q, *first = NULL;	int still_pending = 0; 	if (unlikely(!sigismember(&list->signal, sig)))		return 0; 	/*	 * Collect the siginfo appropriate to this signal.  Check if	 * there is another siginfo for the same signal.	*/	list_for_each_entry(q, &list->list, list) {		if (q->info.si_signo == sig) {			if (first) {				still_pending = 1;				break;			}			first = q;		}	}	if (first) {		list_del_init(&first->list);		copy_siginfo(info, &first->info);		__sigqueue_free(first);		if (!still_pending)			sigdelset(&list->signal, sig);	} else { 		/* Ok, it wasn't in the queue.  This must be		   a fast-pathed signal or we must have been		   out of queue space.  So zero out the info.		 */		sigdelset(&list->signal, sig);		info->si_signo = sig;		info->si_errno = 0;		info->si_code = 0;		info->si_pid = 0;		info->si_uid = 0;	}	return 1;} static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,			siginfo_t *info){	int sig = 0; 	sig = next_signal(pending, mask);	if (sig) {		if (current->notifier) {			if (sigismember(current->notifier_mask, sig)) {				if (!(current->notifier)(current->notifier_data)) {					clear_thread_flag(TIF_SIGPENDING);					return 0;				}			}		} 		if (!collect_signal(sig, pending, info))			sig = 0;					}	recalc_sigpending(); 	return sig;} /* * Dequeue a signal and return the element to the caller, which is  * expected to free it. * * All callers have to hold the siglock. */int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info){	int signr = __dequeue_signal(&tsk->pending, mask, info);	if (!signr)		signr = __dequeue_signal(&tsk->signal->shared_pending,					 mask, info); 	if (signr && unlikely(sig_kernel_stop(signr))) { 		/* 		 * Set a marker that we have dequeued a stop signal.  Our 		 * caller might release the siglock and then the pending 		 * stop signal it is about to process is no longer in the 		 * pending bitmasks, but must still be cleared by a SIGCONT 		 * (and overruled by a SIGKILL).  So those cases clear this 		 * shared flag after we've set it.  Note that this flag may 		 * remain set after the signal we return is ignored or 		 * handled.  That doesn't matter because its only purpose 		 * is to alert stop-signal processing code when another 		 * processor has come along and cleared the flag. 		 */ 		if (!(tsk->signal->flags & SIGNAL_GROUP_EXIT)) 			tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; 	}	if ( signr &&	     ((info->si_code & __SI_MASK) == __SI_TIMER) &&	     info->si_sys_private){		/*		 * Release the siglock to ensure proper locking order		 * of timer locks outside of siglocks.  Note, we leave		 * irqs disabled here, since the posix-timers code is		 * about to disable them again anyway.		 */		spin_unlock(&tsk->sighand->siglock);		do_schedule_next_timer(info);		spin_lock(&tsk->sighand->siglock);	}	return signr;} /* * Tell a process that it has a new active signal.. * * NOTE! we rely on the previous spin_lock to * lock interrupts for us! We can only be called with * "siglock" held, and the local interrupt must * have been disabled when that got acquired! * * No need to set need_resched since signal event passing * goes through ->blocked */void signal_wake_up(struct task_struct *t, int resume){	unsigned int mask;

Lines 1–500 of 2551.