diff options
Diffstat (limited to 'kernel/signal.c')
| -rw-r--r-- | kernel/signal.c | 153 | 
1 files changed, 110 insertions, 43 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 1186cf7fac7..dc17929ab78 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -226,7 +226,7 @@ static inline void print_dropped_signal(int sig)  /*   * allocate a new signal queue record   * - this may be called without locks if and only if t == current, otherwise an - *   appopriate lock must be held to stop the target task from exiting + *   appropriate lock must be held to stop the target task from exiting   */  static struct sigqueue *  __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimit) @@ -375,15 +375,15 @@ int unhandled_signal(struct task_struct *tsk, int sig)  	return !tracehook_consider_fatal_signal(tsk, sig);  } - -/* Notify the system that a driver wants to block all signals for this +/* + * 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.  */ - + * can use to determine if the signal should be blocked or not. + */  void  block_all_signals(int (*notifier)(void *priv), void *priv, sigset_t *mask)  { @@ -434,9 +434,10 @@ still_pending:  		copy_siginfo(info, &first->info);  		__sigqueue_free(first);  	} 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. +		/* +		 * 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.  		 */  		info->si_signo = sig;  		info->si_errno = 0; @@ -468,7 +469,7 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,  }  /* - * Dequeue a signal and return the element to the caller, which is  + * Dequeue a signal and return the element to the caller, which is   * expected to free it.   *   * All callers have to hold the siglock. @@ -490,7 +491,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)  		 * itimers are process shared and we restart periodic  		 * itimers in the signal delivery path to prevent DoS  		 * attacks in the high resolution timer case. This is -		 * compliant with the old way of self restarting +		 * compliant with the old way of self-restarting  		 * itimers, as the SIGALRM is a legacy signal and only  		 * queued once. Changing the restart behaviour to  		 * restart the timer in the signal dequeue path is @@ -923,14 +924,15 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,  	if (info == SEND_SIG_FORCED)  		goto out_set; -	/* Real-time signals must be queued if sent by sigqueue, or -	   some other real-time mechanism.  It is implementation -	   defined whether kill() does so.  We attempt to do so, on -	   the principle of least surprise, but since kill is not -	   allowed to fail with EAGAIN when low on memory we just -	   make sure at least one signal gets delivered and don't -	   pass on the info struct.  */ - +	/* +	 * Real-time signals must be queued if sent by sigqueue, or +	 * some other real-time mechanism.  It is implementation +	 * defined whether kill() does so.  We attempt to do so, on +	 * the principle of least surprise, but since kill is not +	 * allowed to fail with EAGAIN when low on memory we just +	 * make sure at least one signal gets delivered and don't +	 * pass on the info struct. +	 */  	if (sig < SIGRTMIN)  		override_rlimit = (is_si_special(info) || info->si_code >= 0);  	else @@ -1201,8 +1203,7 @@ retry:  	return error;  } -int -kill_proc_info(int sig, struct siginfo *info, pid_t pid) +int kill_proc_info(int sig, struct siginfo *info, pid_t pid)  {  	int error;  	rcu_read_lock(); @@ -1299,8 +1300,7 @@ static int kill_something_info(int sig, struct siginfo *info, pid_t pid)   * These are for backward compatibility with the rest of the kernel source.   */ -int -send_sig_info(int sig, struct siginfo *info, struct task_struct *p) +int send_sig_info(int sig, struct siginfo *info, struct task_struct *p)  {  	/*  	 * Make sure legacy kernel users don't send in bad values @@ -1368,7 +1368,7 @@ EXPORT_SYMBOL(kill_pid);   * These functions support sending signals using preallocated sigqueue   * structures.  This is needed "because realtime applications cannot   * afford to lose notifications of asynchronous events, like timer - * expirations or I/O completions".  In the case of Posix Timers + * expirations or I/O completions".  In the case of POSIX Timers   * we allocate the sigqueue structure from the timer_create.  If this   * allocation fails we are able to report the failure to the application   * with an EAGAIN error. @@ -1553,7 +1553,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why)  	info.si_signo = SIGCHLD;  	info.si_errno = 0;  	/* -	 * see comment in do_notify_parent() abot the following 3 lines +	 * see comment in do_notify_parent() about the following 4 lines  	 */  	rcu_read_lock();  	info.si_pid = task_pid_nr_ns(tsk, parent->nsproxy->pid_ns); @@ -1611,7 +1611,7 @@ static inline int may_ptrace_stop(void)  }  /* - * Return nonzero if there is a SIGKILL that should be waking us up. + * Return non-zero if there is a SIGKILL that should be waking us up.   * Called with the siglock held.   */  static int sigkill_pending(struct task_struct *tsk) @@ -1735,7 +1735,7 @@ void ptrace_notify(int exit_code)  /*   * This performs the stopping for SIGSTOP and other stop signals.   * We have to stop all threads in the thread group. - * Returns nonzero if we've actually stopped and released the siglock. + * Returns non-zero if we've actually stopped and released the siglock.   * Returns zero if we didn't stop and still hold the siglock.   */  static int do_signal_stop(int signr) @@ -1823,10 +1823,12 @@ static int ptrace_signal(int signr, siginfo_t *info,  	current->exit_code = 0; -	/* Update the siginfo structure if the signal has -	   changed.  If the debugger wanted something -	   specific in the siginfo structure then it should -	   have updated *info via PTRACE_SETSIGINFO.  */ +	/* +	 * Update the siginfo structure if the signal has +	 * changed.  If the debugger wanted something +	 * specific in the siginfo structure then it should +	 * have updated *info via PTRACE_SETSIGINFO. +	 */  	if (signr != info->si_signo) {  		info->si_signo = signr;  		info->si_errno = 0; @@ -2034,7 +2036,8 @@ void exit_signals(struct task_struct *tsk)  	if (!signal_pending(tsk))  		goto out; -	/* It could be that __group_complete_signal() choose us to +	/* +	 * It could be that __group_complete_signal() choose us to  	 * notify about group-wide signal. Another thread should be  	 * woken now to take the signal since we will not.  	 */ @@ -2072,6 +2075,9 @@ EXPORT_SYMBOL(unblock_all_signals);   * System call entry points.   */ +/** + *  sys_restart_syscall - restart a system call + */  SYSCALL_DEFINE0(restart_syscall)  {  	struct restart_block *restart = ¤t_thread_info()->restart_block; @@ -2125,6 +2131,13 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset)  	return error;  } +/** + *  sys_rt_sigprocmask - change the list of currently blocked signals + *  @how: whether to add, remove, or set signals + *  @set: stores pending signals + *  @oset: previous value of signal mask if non-null + *  @sigsetsize: size of sigset_t type + */  SYSCALL_DEFINE4(rt_sigprocmask, int, how, sigset_t __user *, set,  		sigset_t __user *, oset, size_t, sigsetsize)  { @@ -2183,8 +2196,14 @@ long do_sigpending(void __user *set, unsigned long sigsetsize)  out:  	return error; -}	 +} +/** + *  sys_rt_sigpending - examine a pending signal that has been raised + *			while blocked + *  @set: stores pending signals + *  @sigsetsize: size of sigset_t type or larger + */  SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, set, size_t, sigsetsize)  {  	return do_sigpending(set, sigsetsize); @@ -2233,9 +2252,9 @@ int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from)  		err |= __put_user(from->si_trapno, &to->si_trapno);  #endif  #ifdef BUS_MCEERR_AO -		/*  +		/*  		 * Other callers might not initialize the si_lsb field, -	 	 * so check explicitely for the right codes here. +		 * so check explicitly for the right codes here.  		 */  		if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)  			err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb); @@ -2264,6 +2283,14 @@ int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from)  #endif +/** + *  sys_rt_sigtimedwait - synchronously wait for queued signals specified + *			in @uthese + *  @uthese: queued signals to wait for + *  @uinfo: if non-null, the signal's siginfo is returned here + *  @uts: upper bound on process time suspension + *  @sigsetsize: size of sigset_t type + */  SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,  		siginfo_t __user *, uinfo, const struct timespec __user *, uts,  		size_t, sigsetsize) @@ -2280,7 +2307,7 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,  	if (copy_from_user(&these, uthese, sizeof(these)))  		return -EFAULT; -		 +  	/*  	 * Invert the set of allowed signals to get those we  	 * want to block. @@ -2305,9 +2332,11 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,  				   + (ts.tv_sec || ts.tv_nsec));  		if (timeout) { -			/* None ready -- temporarily unblock those we're +			/* +			 * None ready -- temporarily unblock those we're  			 * interested while we are sleeping in so that we'll -			 * be awakened when they arrive.  */ +			 * be awakened when they arrive. +			 */  			current->real_blocked = current->blocked;  			sigandsets(¤t->blocked, ¤t->blocked, &these);  			recalc_sigpending(); @@ -2339,6 +2368,11 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,  	return ret;  } +/** + *  sys_kill - send a signal to a process + *  @pid: the PID of the process + *  @sig: signal to be sent + */  SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)  {  	struct siginfo info; @@ -2414,7 +2448,11 @@ SYSCALL_DEFINE3(tgkill, pid_t, tgid, pid_t, pid, int, sig)  	return do_tkill(tgid, pid, sig);  } -/* +/** + *  sys_tkill - send signal to one specific task + *  @pid: the PID of the task + *  @sig: signal to be sent + *   *  Send a signal to only one task, even if it's a CLONE_THREAD task.   */  SYSCALL_DEFINE2(tkill, pid_t, pid, int, sig) @@ -2426,6 +2464,12 @@ SYSCALL_DEFINE2(tkill, pid_t, pid, int, sig)  	return do_tkill(0, pid, sig);  } +/** + *  sys_rt_sigqueueinfo - send signal information to a signal + *  @pid: the PID of the thread + *  @sig: signal to be sent + *  @uinfo: signal info to be sent + */  SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig,  		siginfo_t __user *, uinfo)  { @@ -2553,12 +2597,11 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s  		error = -EINVAL;  		/* -		 * -		 * Note - this code used to test ss_flags incorrectly +		 * Note - this code used to test ss_flags incorrectly:  		 *  	  old code may have been written using ss_flags==0  		 *	  to mean ss_flags==SS_ONSTACK (as this was the only  		 *	  way that worked) - this fix preserves that older -		 *	  mechanism +		 *	  mechanism.  		 */  		if (ss_flags != SS_DISABLE && ss_flags != SS_ONSTACK && ss_flags != 0)  			goto out; @@ -2592,6 +2635,10 @@ out:  #ifdef __ARCH_WANT_SYS_SIGPENDING +/** + *  sys_sigpending - examine pending signals + *  @set: where mask of pending signal is returned + */  SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, set)  {  	return do_sigpending(set, sizeof(*set)); @@ -2600,8 +2647,15 @@ SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, set)  #endif  #ifdef __ARCH_WANT_SYS_SIGPROCMASK -/* Some platforms have their own version with special arguments others -   support only sys_rt_sigprocmask.  */ +/** + *  sys_sigprocmask - examine and change blocked signals + *  @how: whether to add, remove, or set signals + *  @set: signals to add or remove (if non-null) + *  @oset: previous value of signal mask if non-null + * + * Some platforms have their own version with special arguments; + * others support only sys_rt_sigprocmask. + */  SYSCALL_DEFINE3(sigprocmask, int, how, old_sigset_t __user *, set,  		old_sigset_t __user *, oset) @@ -2654,6 +2708,13 @@ out:  #endif /* __ARCH_WANT_SYS_SIGPROCMASK */  #ifdef __ARCH_WANT_SYS_RT_SIGACTION +/** + *  sys_rt_sigaction - alter an action taken by a process + *  @sig: signal to be sent + *  @act: the thread group ID of the thread + *  @oact: the PID of the thread + *  @sigsetsize: size of sigset_t type + */  SYSCALL_DEFINE4(rt_sigaction, int, sig,  		const struct sigaction __user *, act,  		struct sigaction __user *, oact, @@ -2740,6 +2801,12 @@ SYSCALL_DEFINE0(pause)  #endif  #ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND +/** + *  sys_rt_sigsuspend - replace the signal mask for a value with the + *	@unewset value until a signal is received + *  @unewset: new signal mask value + *  @sigsetsize: size of sigset_t type + */  SYSCALL_DEFINE2(rt_sigsuspend, sigset_t __user *, unewset, size_t, sigsetsize)  {  	sigset_t newset;  |