diff options
Diffstat (limited to 'kernel/signal.c')
| -rw-r--r-- | kernel/signal.c | 1914 | 
1 files changed, 1393 insertions, 521 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 4e3cff10fdc..a4077e90f19 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -11,12 +11,13 @@   */  #include <linux/slab.h> -#include <linux/module.h> +#include <linux/export.h>  #include <linux/init.h>  #include <linux/sched.h>  #include <linux/fs.h>  #include <linux/tty.h>  #include <linux/binfmts.h> +#include <linux/coredump.h>  #include <linux/security.h>  #include <linux/syscalls.h>  #include <linux/ptrace.h> @@ -28,6 +29,12 @@  #include <linux/freezer.h>  #include <linux/pid_namespace.h>  #include <linux/nsproxy.h> +#include <linux/user_namespace.h> +#include <linux/uprobes.h> +#include <linux/compat.h> +#include <linux/cn_proc.h> +#include <linux/compiler.h> +  #define CREATE_TRACE_POINTS  #include <trace/events/signal.h> @@ -35,6 +42,7 @@  #include <asm/uaccess.h>  #include <asm/unistd.h>  #include <asm/siginfo.h> +#include <asm/cacheflush.h>  #include "audit.h"	/* audit_signal_info() */  /* @@ -57,21 +65,20 @@ static int sig_handler_ignored(void __user *handler, int sig)  		(handler == SIG_DFL && sig_kernel_ignore(sig));  } -static int sig_task_ignored(struct task_struct *t, int sig, -		int from_ancestor_ns) +static int sig_task_ignored(struct task_struct *t, int sig, bool force)  {  	void __user *handler;  	handler = sig_handler(t, sig);  	if (unlikely(t->signal->flags & SIGNAL_UNKILLABLE) && -			handler == SIG_DFL && !from_ancestor_ns) +			handler == SIG_DFL && !force)  		return 1;  	return sig_handler_ignored(handler, sig);  } -static int sig_ignored(struct task_struct *t, int sig, int from_ancestor_ns) +static int sig_ignored(struct task_struct *t, int sig, bool force)  {  	/*  	 * Blocked signals are never ignored, since the @@ -81,13 +88,13 @@ static int sig_ignored(struct task_struct *t, int sig, int from_ancestor_ns)  	if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))  		return 0; -	if (!sig_task_ignored(t, sig, from_ancestor_ns)) +	if (!sig_task_ignored(t, sig, force))  		return 0;  	/*  	 * Tracers may want to know about even ignored signals.  	 */ -	return !tracehook_consider_ignored_signal(t, sig); +	return !t->ptrace;  }  /* @@ -124,7 +131,7 @@ static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked)  static int recalc_sigpending_tsk(struct task_struct *t)  { -	if (t->signal->group_stop_count > 0 || +	if ((t->jobctl & JOBCTL_PENDING_MASK) ||  	    PENDING(&t->pending, &t->blocked) ||  	    PENDING(&t->signal->shared_pending, &t->blocked)) {  		set_tsk_thread_flag(t, TIF_SIGPENDING); @@ -150,9 +157,7 @@ void recalc_sigpending_and_wake(struct task_struct *t)  void recalc_sigpending(void)  { -	if (unlikely(tracehook_force_sigpending())) -		set_thread_flag(TIF_SIGPENDING); -	else if (!recalc_sigpending_tsk(current) && !freezing(current)) +	if (!recalc_sigpending_tsk(current) && !freezing(current))  		clear_thread_flag(TIF_SIGPENDING);  } @@ -161,7 +166,7 @@ void recalc_sigpending(void)  #define SYNCHRONOUS_MASK \  	(sigmask(SIGSEGV) | sigmask(SIGBUS) | sigmask(SIGILL) | \ -	 sigmask(SIGTRAP) | sigmask(SIGFPE)) +	 sigmask(SIGTRAP) | sigmask(SIGFPE) | sigmask(SIGSYS))  int next_signal(struct sigpending *pending, sigset_t *mask)  { @@ -223,10 +228,134 @@ static inline void print_dropped_signal(int sig)  				current->comm, current->pid, sig);  } +/** + * task_set_jobctl_pending - set jobctl pending bits + * @task: target task + * @mask: pending bits to set + * + * Clear @mask from @task->jobctl.  @mask must be subset of + * %JOBCTL_PENDING_MASK | %JOBCTL_STOP_CONSUME | %JOBCTL_STOP_SIGMASK | + * %JOBCTL_TRAPPING.  If stop signo is being set, the existing signo is + * cleared.  If @task is already being killed or exiting, this function + * becomes noop. + * + * CONTEXT: + * Must be called with @task->sighand->siglock held. + * + * RETURNS: + * %true if @mask is set, %false if made noop because @task was dying. + */ +bool task_set_jobctl_pending(struct task_struct *task, unsigned int mask) +{ +	BUG_ON(mask & ~(JOBCTL_PENDING_MASK | JOBCTL_STOP_CONSUME | +			JOBCTL_STOP_SIGMASK | JOBCTL_TRAPPING)); +	BUG_ON((mask & JOBCTL_TRAPPING) && !(mask & JOBCTL_PENDING_MASK)); + +	if (unlikely(fatal_signal_pending(task) || (task->flags & PF_EXITING))) +		return false; + +	if (mask & JOBCTL_STOP_SIGMASK) +		task->jobctl &= ~JOBCTL_STOP_SIGMASK; + +	task->jobctl |= mask; +	return true; +} + +/** + * task_clear_jobctl_trapping - clear jobctl trapping bit + * @task: target task + * + * If JOBCTL_TRAPPING is set, a ptracer is waiting for us to enter TRACED. + * Clear it and wake up the ptracer.  Note that we don't need any further + * locking.  @task->siglock guarantees that @task->parent points to the + * ptracer. + * + * CONTEXT: + * Must be called with @task->sighand->siglock held. + */ +void task_clear_jobctl_trapping(struct task_struct *task) +{ +	if (unlikely(task->jobctl & JOBCTL_TRAPPING)) { +		task->jobctl &= ~JOBCTL_TRAPPING; +		smp_mb();	/* advised by wake_up_bit() */ +		wake_up_bit(&task->jobctl, JOBCTL_TRAPPING_BIT); +	} +} + +/** + * task_clear_jobctl_pending - clear jobctl pending bits + * @task: target task + * @mask: pending bits to clear + * + * Clear @mask from @task->jobctl.  @mask must be subset of + * %JOBCTL_PENDING_MASK.  If %JOBCTL_STOP_PENDING is being cleared, other + * STOP bits are cleared together. + * + * If clearing of @mask leaves no stop or trap pending, this function calls + * task_clear_jobctl_trapping(). + * + * CONTEXT: + * Must be called with @task->sighand->siglock held. + */ +void task_clear_jobctl_pending(struct task_struct *task, unsigned int mask) +{ +	BUG_ON(mask & ~JOBCTL_PENDING_MASK); + +	if (mask & JOBCTL_STOP_PENDING) +		mask |= JOBCTL_STOP_CONSUME | JOBCTL_STOP_DEQUEUED; + +	task->jobctl &= ~mask; + +	if (!(task->jobctl & JOBCTL_PENDING_MASK)) +		task_clear_jobctl_trapping(task); +} + +/** + * task_participate_group_stop - participate in a group stop + * @task: task participating in a group stop + * + * @task has %JOBCTL_STOP_PENDING set and is participating in a group stop. + * Group stop states are cleared and the group stop count is consumed if + * %JOBCTL_STOP_CONSUME was set.  If the consumption completes the group + * stop, the appropriate %SIGNAL_* flags are set. + * + * CONTEXT: + * Must be called with @task->sighand->siglock held. + * + * RETURNS: + * %true if group stop completion should be notified to the parent, %false + * otherwise. + */ +static bool task_participate_group_stop(struct task_struct *task) +{ +	struct signal_struct *sig = task->signal; +	bool consume = task->jobctl & JOBCTL_STOP_CONSUME; + +	WARN_ON_ONCE(!(task->jobctl & JOBCTL_STOP_PENDING)); + +	task_clear_jobctl_pending(task, JOBCTL_STOP_PENDING); + +	if (!consume) +		return false; + +	if (!WARN_ON_ONCE(sig->group_stop_count == 0)) +		sig->group_stop_count--; + +	/* +	 * Tell the caller to notify completion iff we are entering into a +	 * fresh group stop.  Read comment in do_signal_stop() for details. +	 */ +	if (!sig->group_stop_count && !(sig->flags & SIGNAL_STOP_STOPPED)) { +		sig->flags = SIGNAL_STOP_STOPPED; +		return true; +	} +	return false; +} +  /*   * 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) @@ -360,6 +489,9 @@ flush_signal_handlers(struct task_struct *t, int force_default)  		if (force_default || ka->sa.sa_handler != SIG_IGN)  			ka->sa.sa_handler = SIG_DFL;  		ka->sa.sa_flags = 0; +#ifdef __ARCH_HAS_SA_RESTORER +		ka->sa.sa_restorer = NULL; +#endif  		sigemptyset(&ka->sa.sa_mask);  		ka++;  	} @@ -372,18 +504,19 @@ int unhandled_signal(struct task_struct *tsk, int sig)  		return 1;  	if (handler != SIG_IGN && handler != SIG_DFL)  		return 0; -	return !tracehook_consider_fatal_signal(tsk, sig); +	/* if ptraced, let the tracer determine */ +	return !tsk->ptrace;  } - -/* 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 +567,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 +602,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 +624,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 @@ -526,7 +660,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)  		 * is to alert stop-signal processing code when another  		 * processor has come along and cleared the flag.  		 */ -		tsk->signal->flags |= SIGNAL_STOP_DEQUEUED; +		current->jobctl |= JOBCTL_STOP_DEQUEUED;  	}  	if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) {  		/* @@ -553,23 +687,17 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)   * No need to set need_resched since signal event passing   * goes through ->blocked   */ -void signal_wake_up(struct task_struct *t, int resume) +void signal_wake_up_state(struct task_struct *t, unsigned int state)  { -	unsigned int mask; -  	set_tsk_thread_flag(t, TIF_SIGPENDING); -  	/* -	 * For SIGKILL, we want to wake it up in the stopped/traced/killable +	 * TASK_WAKEKILL also means wake it up in the stopped/traced/killable  	 * case. We don't check t->state here because there is a race with it  	 * executing another processor and just now entering stopped state.  	 * By using wake_up_state, we ensure the process will wake up and  	 * handle its death signal.  	 */ -	mask = TASK_INTERRUPTIBLE; -	if (resume) -		mask |= TASK_WAKEKILL; -	if (!wake_up_state(t, mask)) +	if (!wake_up_state(t, state | TASK_INTERRUPTIBLE))  		kick_process(t);  } @@ -578,11 +706,8 @@ void signal_wake_up(struct task_struct *t, int resume)   * Returns 1 if any signals were found.   *   * All callers must be holding the siglock. - * - * This version takes a sigset mask and looks at all signals, - * not just those in the first mask word.   */ -static int rm_from_queue_full(sigset_t *mask, struct sigpending *s) +static int flush_sigqueue_mask(sigset_t *mask, struct sigpending *s)  {  	struct sigqueue *q, *n;  	sigset_t m; @@ -591,7 +716,7 @@ static int rm_from_queue_full(sigset_t *mask, struct sigpending *s)  	if (sigisemptyset(&m))  		return 0; -	signandsets(&s->signal, &s->signal, mask); +	sigandnsets(&s->signal, &s->signal, mask);  	list_for_each_entry_safe(q, n, &s->list, list) {  		if (sigismember(mask, q->info.si_signo)) {  			list_del_init(&q->list); @@ -600,29 +725,6 @@ static int rm_from_queue_full(sigset_t *mask, struct sigpending *s)  	}  	return 1;  } -/* - * Remove signals in mask from the pending set and queue. - * Returns 1 if any signals were found. - * - * All callers must be holding the siglock. - */ -static int rm_from_queue(unsigned long mask, struct sigpending *s) -{ -	struct sigqueue *q, *n; - -	if (!sigtestsetmask(&s->signal, mask)) -		return 0; - -	sigdelsetmask(&s->signal, mask); -	list_for_each_entry_safe(q, n, &s->list, list) { -		if (q->info.si_signo < SIGRTMIN && -		    (mask & sigmask(q->info.si_signo))) { -			list_del_init(&q->list); -			__sigqueue_free(q); -		} -	} -	return 1; -}  static inline int is_si_special(const struct siginfo *info)  { @@ -636,13 +738,32 @@ static inline bool si_fromuser(const struct siginfo *info)  }  /* + * called with RCU read lock from check_kill_permission() + */ +static int kill_ok_by_cred(struct task_struct *t) +{ +	const struct cred *cred = current_cred(); +	const struct cred *tcred = __task_cred(t); + +	if (uid_eq(cred->euid, tcred->suid) || +	    uid_eq(cred->euid, tcred->uid)  || +	    uid_eq(cred->uid,  tcred->suid) || +	    uid_eq(cred->uid,  tcred->uid)) +		return 1; + +	if (ns_capable(tcred->user_ns, CAP_KILL)) +		return 1; + +	return 0; +} + +/*   * Bad permissions for sending the signal   * - the caller must hold the RCU read lock   */  static int check_kill_permission(int sig, struct siginfo *info,  				 struct task_struct *t)  { -	const struct cred *cred, *tcred;  	struct pid *sid;  	int error; @@ -656,14 +777,8 @@ static int check_kill_permission(int sig, struct siginfo *info,  	if (error)  		return error; -	cred = current_cred(); -	tcred = __task_cred(t);  	if (!same_thread_group(current, t) && -	    (cred->euid ^ tcred->suid) && -	    (cred->euid ^ tcred->uid) && -	    (cred->uid  ^ tcred->suid) && -	    (cred->uid  ^ tcred->uid) && -	    !capable(CAP_KILL)) { +	    !kill_ok_by_cred(t)) {  		switch (sig) {  		case SIGCONT:  			sid = task_session(t); @@ -681,6 +796,32 @@ static int check_kill_permission(int sig, struct siginfo *info,  	return security_task_kill(t, info, sig, 0);  } +/** + * ptrace_trap_notify - schedule trap to notify ptracer + * @t: tracee wanting to notify tracer + * + * This function schedules sticky ptrace trap which is cleared on the next + * TRAP_STOP to notify ptracer of an event.  @t must have been seized by + * ptracer. + * + * If @t is running, STOP trap will be taken.  If trapped for STOP and + * ptracer is listening for events, tracee is woken up so that it can + * re-trap for the new event.  If trapped otherwise, STOP trap will be + * eventually taken without returning to userland after the existing traps + * are finished by PTRACE_CONT. + * + * CONTEXT: + * Must be called with @task->sighand->siglock held. + */ +static void ptrace_trap_notify(struct task_struct *t) +{ +	WARN_ON_ONCE(!(t->ptrace & PT_SEIZED)); +	assert_spin_locked(&t->sighand->siglock); + +	task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); +	ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); +} +  /*   * Handle magic process-wide effects of stop/continue signals. Unlike   * the signal actions, these happen immediately at signal-generation @@ -691,12 +832,15 @@ static int check_kill_permission(int sig, struct siginfo *info,   * Returns true if the signal should be actually delivered, otherwise   * it should be dropped.   */ -static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns) +static bool prepare_signal(int sig, struct task_struct *p, bool force)  {  	struct signal_struct *signal = p->signal;  	struct task_struct *t; +	sigset_t flush; -	if (unlikely(signal->flags & SIGNAL_GROUP_EXIT)) { +	if (signal->flags & (SIGNAL_GROUP_EXIT | SIGNAL_GROUP_COREDUMP)) { +		if (signal->flags & SIGNAL_GROUP_COREDUMP) +			return sig == SIGKILL;  		/*  		 * The process is in the middle of dying, nothing to do.  		 */ @@ -704,43 +848,25 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns)  		/*  		 * This is a stop signal.  Remove SIGCONT from all queues.  		 */ -		rm_from_queue(sigmask(SIGCONT), &signal->shared_pending); -		t = p; -		do { -			rm_from_queue(sigmask(SIGCONT), &t->pending); -		} while_each_thread(p, t); +		siginitset(&flush, sigmask(SIGCONT)); +		flush_sigqueue_mask(&flush, &signal->shared_pending); +		for_each_thread(p, t) +			flush_sigqueue_mask(&flush, &t->pending);  	} else if (sig == SIGCONT) {  		unsigned int why;  		/* -		 * Remove all stop signals from all queues, -		 * and wake all threads. +		 * Remove all stop signals from all queues, wake all threads.  		 */ -		rm_from_queue(SIG_KERNEL_STOP_MASK, &signal->shared_pending); -		t = p; -		do { -			unsigned int state; -			rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); -			/* -			 * If there is a handler for SIGCONT, we must make -			 * sure that no thread returns to user mode before -			 * we post the signal, in case it was the only -			 * thread eligible to run the signal handler--then -			 * it must not do anything between resuming and -			 * running the handler.  With the TIF_SIGPENDING -			 * flag set, the thread will pause and acquire the -			 * siglock that we hold now and until we've queued -			 * the pending signal. -			 * -			 * Wake up the stopped thread _after_ setting -			 * TIF_SIGPENDING -			 */ -			state = __TASK_STOPPED; -			if (sig_user_defined(t, SIGCONT) && !sigismember(&t->blocked, SIGCONT)) { -				set_tsk_thread_flag(t, TIF_SIGPENDING); -				state |= TASK_INTERRUPTIBLE; -			} -			wake_up_state(t, state); -		} while_each_thread(p, t); +		siginitset(&flush, SIG_KERNEL_STOP_MASK); +		flush_sigqueue_mask(&flush, &signal->shared_pending); +		for_each_thread(p, t) { +			flush_sigqueue_mask(&flush, &t->pending); +			task_clear_jobctl_pending(t, JOBCTL_STOP_PENDING); +			if (likely(!(t->ptrace & PT_SEIZED))) +				wake_up_state(t, __TASK_STOPPED); +			else +				ptrace_trap_notify(t); +		}  		/*  		 * Notify the parent with CLD_CONTINUED if we were stopped. @@ -765,17 +891,10 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns)  			signal->flags = why | SIGNAL_STOP_CONTINUED;  			signal->group_stop_count = 0;  			signal->group_exit_code = 0; -		} else { -			/* -			 * We are not stopped, but there could be a stop -			 * signal in the middle of being processed after -			 * being removed from the queue.  Clear that too. -			 */ -			signal->flags &= ~SIGNAL_STOP_DEQUEUED;  		}  	} -	return !sig_ignored(p, sig, from_ancestor_ns); +	return !sig_ignored(p, sig, force);  }  /* @@ -843,8 +962,7 @@ static void complete_signal(int sig, struct task_struct *p, int group)  	if (sig_fatal(p, sig) &&  	    !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&  	    !sigismember(&t->real_blocked, sig) && -	    (sig == SIGKILL || -	     !tracehook_consider_fatal_signal(t, sig))) { +	    (sig == SIGKILL || !t->ptrace)) {  		/*  		 * This signal will be fatal to the whole group.  		 */ @@ -860,6 +978,7 @@ static void complete_signal(int sig, struct task_struct *p, int group)  			signal->group_stop_count = 0;  			t = p;  			do { +				task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK);  				sigaddset(&t->pending.signal, SIGKILL);  				signal_wake_up(t, 1);  			} while_each_thread(p, t); @@ -880,19 +999,41 @@ static inline int legacy_queue(struct sigpending *signals, int sig)  	return (sig < SIGRTMIN) && sigismember(&signals->signal, sig);  } +#ifdef CONFIG_USER_NS +static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) +{ +	if (current_user_ns() == task_cred_xxx(t, user_ns)) +		return; + +	if (SI_FROMKERNEL(info)) +		return; + +	rcu_read_lock(); +	info->si_uid = from_kuid_munged(task_cred_xxx(t, user_ns), +					make_kuid(current_user_ns(), info->si_uid)); +	rcu_read_unlock(); +} +#else +static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t) +{ +	return; +} +#endif +  static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,  			int group, int from_ancestor_ns)  {  	struct sigpending *pending;  	struct sigqueue *q;  	int override_rlimit; - -	trace_signal_generate(sig, info, t); +	int ret = 0, result;  	assert_spin_locked(&t->sighand->siglock); -	if (!prepare_signal(sig, t, from_ancestor_ns)) -		return 0; +	result = TRACE_SIGNAL_IGNORED; +	if (!prepare_signal(sig, t, +			from_ancestor_ns || (info == SEND_SIG_FORCED))) +		goto ret;  	pending = group ? &t->signal->shared_pending : &t->pending;  	/* @@ -900,8 +1041,11 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,  	 * exactly one non-rt signal, so that we can get more  	 * detailed information about the cause of the signal.  	 */ +	result = TRACE_SIGNAL_ALREADY_PENDING;  	if (legacy_queue(pending, sig)) -		return 0; +		goto ret; + +	result = TRACE_SIGNAL_DELIVERED;  	/*  	 * fast-pathed signals for kernel-internal things like SIGSTOP  	 * or SIGKILL. @@ -909,14 +1053,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 @@ -933,7 +1078,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,  			q->info.si_code = SI_USER;  			q->info.si_pid = task_tgid_nr_ns(current,  							task_active_pid_ns(t)); -			q->info.si_uid = current_uid(); +			q->info.si_uid = from_kuid_munged(current_user_ns(), current_uid());  			break;  		case (unsigned long) SEND_SIG_PRIV:  			q->info.si_signo = sig; @@ -948,6 +1093,9 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,  				q->info.si_pid = 0;  			break;  		} + +		userns_fixup_signal_uid(&q->info, t); +  	} else if (!is_si_special(info)) {  		if (sig >= SIGRTMIN && info->si_code != SI_USER) {  			/* @@ -955,14 +1103,15 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,  			 * signal was rt and sent by user using something  			 * other than kill().  			 */ -			trace_signal_overflow_fail(sig, group, info); -			return -EAGAIN; +			result = TRACE_SIGNAL_OVERFLOW_FAIL; +			ret = -EAGAIN; +			goto ret;  		} else {  			/*  			 * This is a silent loss of information.  We still  			 * send the signal, but the *info bits are lost.  			 */ -			trace_signal_lose_info(sig, group, info); +			result = TRACE_SIGNAL_LOSE_INFO;  		}  	} @@ -970,7 +1119,9 @@ out_set:  	signalfd_notify(t, sig);  	sigaddset(&pending->signal, sig);  	complete_signal(sig, t, group); -	return 0; +ret: +	trace_signal_generate(sig, info, t, group, result); +	return ret;  }  static int send_signal(int sig, struct siginfo *info, struct task_struct *t, @@ -986,13 +1137,13 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t,  	return __send_signal(sig, info, t, group, from_ancestor_ns);  } -static void print_fatal_signal(struct pt_regs *regs, int signr) +static void print_fatal_signal(int signr)  { -	printk("%s/%d: potentially unexpected fatal signal %d.\n", -		current->comm, task_pid_nr(current), signr); +	struct pt_regs *regs = signal_pt_regs(); +	printk(KERN_INFO "potentially unexpected fatal signal %d.\n", signr);  #if defined(__i386__) && !defined(__arch_um__) -	printk("code at %08lx: ", regs->ip); +	printk(KERN_INFO "code at %08lx: ", regs->ip);  	{  		int i;  		for (i = 0; i < 16; i++) { @@ -1000,11 +1151,11 @@ static void print_fatal_signal(struct pt_regs *regs, int signr)  			if (get_user(insn, (unsigned char *)(regs->ip + i)))  				break; -			printk("%02x ", insn); +			printk(KERN_CONT "%02x ", insn);  		}  	} +	printk(KERN_CONT "\n");  #endif -	printk("\n");  	preempt_disable();  	show_regs(regs);  	preempt_enable(); @@ -1093,6 +1244,7 @@ int zap_other_threads(struct task_struct *p)  	p->signal->group_stop_count = 0;  	while_each_thread(p, t) { +		task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK);  		count++;  		/* Don't bother with already dead threads */ @@ -1110,18 +1262,25 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk,  {  	struct sighand_struct *sighand; -	rcu_read_lock();  	for (;;) { +		local_irq_save(*flags); +		rcu_read_lock();  		sighand = rcu_dereference(tsk->sighand); -		if (unlikely(sighand == NULL)) +		if (unlikely(sighand == NULL)) { +			rcu_read_unlock(); +			local_irq_restore(*flags);  			break; +		} -		spin_lock_irqsave(&sighand->siglock, *flags); -		if (likely(sighand == tsk->sighand)) +		spin_lock(&sighand->siglock); +		if (likely(sighand == tsk->sighand)) { +			rcu_read_unlock();  			break; -		spin_unlock_irqrestore(&sighand->siglock, *flags); +		} +		spin_unlock(&sighand->siglock); +		rcu_read_unlock(); +		local_irq_restore(*flags);  	} -	rcu_read_unlock();  	return sighand;  } @@ -1187,8 +1346,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(); @@ -1197,13 +1355,22 @@ kill_proc_info(int sig, struct siginfo *info, pid_t pid)  	return error;  } +static int kill_as_cred_perm(const struct cred *cred, +			     struct task_struct *target) +{ +	const struct cred *pcred = __task_cred(target); +	if (!uid_eq(cred->euid, pcred->suid) && !uid_eq(cred->euid, pcred->uid) && +	    !uid_eq(cred->uid,  pcred->suid) && !uid_eq(cred->uid,  pcred->uid)) +		return 0; +	return 1; +} +  /* like kill_pid_info(), but doesn't use uid/euid of "current" */ -int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid, -		      uid_t uid, uid_t euid, u32 secid) +int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid, +			 const struct cred *cred, u32 secid)  {  	int ret = -EINVAL;  	struct task_struct *p; -	const struct cred *pcred;  	unsigned long flags;  	if (!valid_signal(sig)) @@ -1215,10 +1382,7 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,  		ret = -ESRCH;  		goto out_unlock;  	} -	pcred = __task_cred(p); -	if (si_fromuser(info) && -	    euid != pcred->suid && euid != pcred->uid && -	    uid  != pcred->suid && uid  != pcred->uid) { +	if (si_fromuser(info) && !kill_as_cred_perm(cred, p)) {  		ret = -EPERM;  		goto out_unlock;  	} @@ -1237,7 +1401,7 @@ out_unlock:  	rcu_read_unlock();  	return ret;  } -EXPORT_SYMBOL_GPL(kill_pid_info_as_uid); +EXPORT_SYMBOL_GPL(kill_pid_info_as_cred);  /*   * kill_something_info() interprets pid in interesting ways just like kill(2). @@ -1285,8 +1449,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 @@ -1354,7 +1517,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. @@ -1399,7 +1562,7 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)  	int sig = q->info.si_signo;  	struct sigpending *pending;  	unsigned long flags; -	int ret; +	int ret, result;  	BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); @@ -1408,7 +1571,8 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)  		goto ret;  	ret = 1; /* the signal is ignored */ -	if (!prepare_signal(sig, t, 0)) +	result = TRACE_SIGNAL_IGNORED; +	if (!prepare_signal(sig, t, false))  		goto out;  	ret = 0; @@ -1419,6 +1583,7 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)  		 */  		BUG_ON(q->info.si_code != SI_TIMER);  		q->info.si_overrun++; +		result = TRACE_SIGNAL_ALREADY_PENDING;  		goto out;  	}  	q->info.si_overrun = 0; @@ -1428,7 +1593,9 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group)  	list_add_tail(&q->list, &pending->list);  	sigaddset(&pending->signal, sig);  	complete_signal(sig, t, group); +	result = TRACE_SIGNAL_DELIVERED;  out: +	trace_signal_generate(sig, &q->info, t, group, result);  	unlock_task_sighand(t, &flags);  ret:  	return ret; @@ -1438,47 +1605,56 @@ ret:   * Let a parent know about the death of a child.   * For a stopped/continued status change, use do_notify_parent_cldstop instead.   * - * Returns -1 if our parent ignored us and so we've switched to - * self-reaping, or else @sig. + * Returns true if our parent ignored us and so we've switched to + * self-reaping.   */ -int do_notify_parent(struct task_struct *tsk, int sig) +bool do_notify_parent(struct task_struct *tsk, int sig)  {  	struct siginfo info;  	unsigned long flags;  	struct sighand_struct *psig; -	int ret = sig; +	bool autoreap = false; +	cputime_t utime, stime;  	BUG_ON(sig == -1);   	/* do_notify_parent_cldstop should have been called instead.  */   	BUG_ON(task_is_stopped_or_traced(tsk)); -	BUG_ON(!task_ptrace(tsk) && +	BUG_ON(!tsk->ptrace &&  	       (tsk->group_leader != tsk || !thread_group_empty(tsk))); +	if (sig != SIGCHLD) { +		/* +		 * This is only possible if parent == real_parent. +		 * Check if it has changed security domain. +		 */ +		if (tsk->parent_exec_id != tsk->parent->self_exec_id) +			sig = SIGCHLD; +	} +  	info.si_signo = sig;  	info.si_errno = 0;  	/* -	 * we are under tasklist_lock here so our parent is tied to -	 * us and cannot exit and release its namespace. +	 * We are under tasklist_lock here so our parent is tied to +	 * us and cannot change.  	 * -	 * the only it can is to switch its nsproxy with sys_unshare, -	 * bu uncharing pid namespaces is not allowed, so we'll always -	 * see relevant namespace +	 * task_active_pid_ns will always return the same pid namespace +	 * until a task passes through release_task.  	 *  	 * write_lock() currently calls preempt_disable() which is the  	 * same as rcu_read_lock(), but according to Oleg, this is not  	 * correct to rely on this  	 */  	rcu_read_lock(); -	info.si_pid = task_pid_nr_ns(tsk, tsk->parent->nsproxy->pid_ns); -	info.si_uid = __task_cred(tsk)->uid; +	info.si_pid = task_pid_nr_ns(tsk, task_active_pid_ns(tsk->parent)); +	info.si_uid = from_kuid_munged(task_cred_xxx(tsk->parent, user_ns), +				       task_uid(tsk));  	rcu_read_unlock(); -	info.si_utime = cputime_to_clock_t(cputime_add(tsk->utime, -				tsk->signal->utime)); -	info.si_stime = cputime_to_clock_t(cputime_add(tsk->stime, -				tsk->signal->stime)); +	task_cputime(tsk, &utime, &stime); +	info.si_utime = cputime_to_clock_t(utime + tsk->signal->utime); +	info.si_stime = cputime_to_clock_t(stime + tsk->signal->stime);  	info.si_status = tsk->exit_code & 0x7f;  	if (tsk->exit_code & 0x80) @@ -1492,7 +1668,7 @@ int do_notify_parent(struct task_struct *tsk, int sig)  	psig = tsk->parent->sighand;  	spin_lock_irqsave(&psig->siglock, flags); -	if (!task_ptrace(tsk) && sig == SIGCHLD && +	if (!tsk->ptrace && sig == SIGCHLD &&  	    (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN ||  	     (psig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT))) {  		/* @@ -1510,28 +1686,43 @@ int do_notify_parent(struct task_struct *tsk, int sig)  		 * is implementation-defined: we do (if you don't want  		 * it, just use SIG_IGN instead).  		 */ -		ret = tsk->exit_signal = -1; +		autoreap = true;  		if (psig->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) -			sig = -1; +			sig = 0;  	} -	if (valid_signal(sig) && sig > 0) +	if (valid_signal(sig) && sig)  		__group_send_sig_info(sig, &info, tsk->parent);  	__wake_up_parent(tsk, tsk->parent);  	spin_unlock_irqrestore(&psig->siglock, flags); -	return ret; +	return autoreap;  } -static void do_notify_parent_cldstop(struct task_struct *tsk, int why) +/** + * do_notify_parent_cldstop - notify parent of stopped/continued state change + * @tsk: task reporting the state change + * @for_ptracer: the notification is for ptracer + * @why: CLD_{CONTINUED|STOPPED|TRAPPED} to report + * + * Notify @tsk's parent that the stopped/continued state has changed.  If + * @for_ptracer is %false, @tsk's group leader notifies to its real parent. + * If %true, @tsk reports to @tsk->parent which should be the ptracer. + * + * CONTEXT: + * Must be called with tasklist_lock at least read locked. + */ +static void do_notify_parent_cldstop(struct task_struct *tsk, +				     bool for_ptracer, int why)  {  	struct siginfo info;  	unsigned long flags;  	struct task_struct *parent;  	struct sighand_struct *sighand; +	cputime_t utime, stime; -	if (task_ptrace(tsk)) +	if (for_ptracer) {  		parent = tsk->parent; -	else { +	} else {  		tsk = tsk->group_leader;  		parent = tsk->real_parent;  	} @@ -1539,15 +1730,16 @@ 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); -	info.si_uid = __task_cred(tsk)->uid; +	info.si_pid = task_pid_nr_ns(tsk, task_active_pid_ns(parent)); +	info.si_uid = from_kuid_munged(task_cred_xxx(parent, user_ns), task_uid(tsk));  	rcu_read_unlock(); -	info.si_utime = cputime_to_clock_t(tsk->utime); -	info.si_stime = cputime_to_clock_t(tsk->stime); +	task_cputime(tsk, &utime, &stime); +	info.si_utime = cputime_to_clock_t(utime); +	info.si_stime = cputime_to_clock_t(stime);   	info.si_code = why;   	switch (why) { @@ -1578,7 +1770,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk, int why)  static inline int may_ptrace_stop(void)  { -	if (!likely(task_ptrace(current))) +	if (!likely(current->ptrace))  		return 0;  	/*  	 * Are we in the middle of do_coredump? @@ -1588,6 +1780,10 @@ static inline int may_ptrace_stop(void)  	 * If SIGKILL was already sent before the caller unlocked  	 * ->siglock we must see ->core_state != NULL. Otherwise it  	 * is safe to enter schedule(). +	 * +	 * This is almost outdated, a task with the pending SIGKILL can't +	 * block in TASK_TRACED. But PTRACE_EVENT_EXIT can be reported +	 * after SIGKILL was already dequeued.  	 */  	if (unlikely(current->mm->core_state) &&  	    unlikely(current->mm == current->parent->mm)) @@ -1597,7 +1793,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) @@ -1617,10 +1813,12 @@ static int sigkill_pending(struct task_struct *tsk)   * If we actually decide not to stop at all because the tracer   * is gone, we keep current->exit_code unless clear_code.   */ -static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) +static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)  	__releases(¤t->sighand->siglock)  	__acquires(¤t->sighand->siglock)  { +	bool gstop_done = false; +  	if (arch_ptrace_stop_needed(exit_code, info)) {  		/*  		 * The arch code has something special to do before a @@ -1641,21 +1839,52 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info)  	}  	/* -	 * If there is a group stop in progress, -	 * we must participate in the bookkeeping. +	 * We're committing to trapping.  TRACED should be visible before +	 * TRAPPING is cleared; otherwise, the tracer might fail do_wait(). +	 * Also, transition to TRACED and updates to ->jobctl should be +	 * atomic with respect to siglock and should be done after the arch +	 * hook as siglock is released and regrabbed across it.  	 */ -	if (current->signal->group_stop_count > 0) -		--current->signal->group_stop_count; +	set_current_state(TASK_TRACED);  	current->last_siginfo = info;  	current->exit_code = exit_code; -	/* Let the debugger run.  */ -	__set_current_state(TASK_TRACED); +	/* +	 * If @why is CLD_STOPPED, we're trapping to participate in a group +	 * stop.  Do the bookkeeping.  Note that if SIGCONT was delievered +	 * across siglock relocks since INTERRUPT was scheduled, PENDING +	 * could be clear now.  We act as if SIGCONT is received after +	 * TASK_TRACED is entered - ignore it. +	 */ +	if (why == CLD_STOPPED && (current->jobctl & JOBCTL_STOP_PENDING)) +		gstop_done = task_participate_group_stop(current); + +	/* any trap clears pending STOP trap, STOP trap clears NOTIFY */ +	task_clear_jobctl_pending(current, JOBCTL_TRAP_STOP); +	if (info && info->si_code >> 8 == PTRACE_EVENT_STOP) +		task_clear_jobctl_pending(current, JOBCTL_TRAP_NOTIFY); + +	/* entering a trap, clear TRAPPING */ +	task_clear_jobctl_trapping(current); +  	spin_unlock_irq(¤t->sighand->siglock);  	read_lock(&tasklist_lock);  	if (may_ptrace_stop()) { -		do_notify_parent_cldstop(current, CLD_TRAPPED); +		/* +		 * Notify parents of the stop. +		 * +		 * While ptraced, there are two parents - the ptracer and +		 * the real_parent of the group_leader.  The ptracer should +		 * know about every stop while the real parent is only +		 * interested in the completion of group stop.  The states +		 * for the two don't interact with each other.  Notify +		 * separately unless they're gonna be duplicates. +		 */ +		do_notify_parent_cldstop(current, true, why); +		if (gstop_done && ptrace_reparented(current)) +			do_notify_parent_cldstop(current, false, why); +  		/*  		 * Don't want to allow preemption here, because  		 * sys_ptrace() needs this task to be inactive. @@ -1665,12 +1894,22 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info)  		preempt_disable();  		read_unlock(&tasklist_lock);  		preempt_enable_no_resched(); -		schedule(); +		freezable_schedule();  	} else {  		/*  		 * By the time we got the lock, our tracer went away.  		 * Don't drop the lock yet, another tracer may come. +		 * +		 * If @gstop_done, the ptracer went away between group stop +		 * completion and here.  During detach, it would have set +		 * JOBCTL_STOP_PENDING on us and we'll re-enter +		 * TASK_STOPPED in do_signal_stop() on return, so notifying +		 * the real parent of the group stop completion is enough.  		 */ +		if (gstop_done) +			do_notify_parent_cldstop(current, false, why); + +		/* tasklist protects us from ptrace_freeze_traced() */  		__set_current_state(TASK_RUNNING);  		if (clear_code)  			current->exit_code = 0; @@ -1678,13 +1917,6 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info)  	}  	/* -	 * While in TASK_TRACED, we were considered "frozen enough". -	 * Now that we woke up, it's crucial if we're supposed to be -	 * frozen that we freeze now before running anything substantial. -	 */ -	try_to_freeze(); - -	/*  	 * We are back.  Now reacquire the siglock before touching  	 * last_siginfo, so that we are sure to have synchronized with  	 * any signal-sending on another CPU that wants to examine it. @@ -1692,6 +1924,9 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info)  	spin_lock_irq(¤t->sighand->siglock);  	current->last_siginfo = NULL; +	/* LISTENING can be set only during STOP traps, clear it */ +	current->jobctl &= ~JOBCTL_LISTENING; +  	/*  	 * Queued signals ignored us while we were stopped for tracing.  	 * So check for any that we should take before resuming user mode. @@ -1700,107 +1935,203 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info)  	recalc_sigpending_tsk(current);  } -void ptrace_notify(int exit_code) +static void ptrace_do_notify(int signr, int exit_code, int why)  {  	siginfo_t info; -	BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP); -  	memset(&info, 0, sizeof info); -	info.si_signo = SIGTRAP; +	info.si_signo = signr;  	info.si_code = exit_code;  	info.si_pid = task_pid_vnr(current); -	info.si_uid = current_uid(); +	info.si_uid = from_kuid_munged(current_user_ns(), current_uid());  	/* Let the debugger run.  */ +	ptrace_stop(exit_code, why, 1, &info); +} + +void ptrace_notify(int exit_code) +{ +	BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP); +	if (unlikely(current->task_works)) +		task_work_run(); +  	spin_lock_irq(¤t->sighand->siglock); -	ptrace_stop(exit_code, 1, &info); +	ptrace_do_notify(SIGTRAP, exit_code, CLD_TRAPPED);  	spin_unlock_irq(¤t->sighand->siglock);  } -/* - * 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 zero if we didn't stop and still hold the siglock. +/** + * do_signal_stop - handle group stop for SIGSTOP and other stop signals + * @signr: signr causing group stop if initiating + * + * If %JOBCTL_STOP_PENDING is not set yet, initiate group stop with @signr + * and participate in it.  If already set, participate in the existing + * group stop.  If participated in a group stop (and thus slept), %true is + * returned with siglock released. + * + * If ptraced, this function doesn't handle stop itself.  Instead, + * %JOBCTL_TRAP_STOP is scheduled and %false is returned with siglock + * untouched.  The caller must ensure that INTERRUPT trap handling takes + * places afterwards. + * + * CONTEXT: + * Must be called with @current->sighand->siglock held, which is released + * on %true return. + * + * RETURNS: + * %false if group stop is already cancelled or ptrace trap is scheduled. + * %true if participated in group stop.   */ -static int do_signal_stop(int signr) +static bool do_signal_stop(int signr) +	__releases(¤t->sighand->siglock)  {  	struct signal_struct *sig = current->signal; -	int notify; -	if (!sig->group_stop_count) { +	if (!(current->jobctl & JOBCTL_STOP_PENDING)) { +		unsigned int gstop = JOBCTL_STOP_PENDING | JOBCTL_STOP_CONSUME;  		struct task_struct *t; -		if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) || +		/* signr will be recorded in task->jobctl for retries */ +		WARN_ON_ONCE(signr & ~JOBCTL_STOP_SIGMASK); + +		if (!likely(current->jobctl & JOBCTL_STOP_DEQUEUED) ||  		    unlikely(signal_group_exit(sig))) -			return 0; +			return false;  		/* -		 * There is no group stop already in progress. -		 * We must initiate one now. +		 * There is no group stop already in progress.  We must +		 * initiate one now. +		 * +		 * While ptraced, a task may be resumed while group stop is +		 * still in effect and then receive a stop signal and +		 * initiate another group stop.  This deviates from the +		 * usual behavior as two consecutive stop signals can't +		 * cause two group stops when !ptraced.  That is why we +		 * also check !task_is_stopped(t) below. +		 * +		 * The condition can be distinguished by testing whether +		 * SIGNAL_STOP_STOPPED is already set.  Don't generate +		 * group_exit_code in such case. +		 * +		 * This is not necessary for SIGNAL_STOP_CONTINUED because +		 * an intervening stop signal is required to cause two +		 * continued events regardless of ptrace.  		 */ -		sig->group_exit_code = signr; +		if (!(sig->flags & SIGNAL_STOP_STOPPED)) +			sig->group_exit_code = signr; + +		sig->group_stop_count = 0; -		sig->group_stop_count = 1; -		for (t = next_thread(current); t != current; t = next_thread(t)) +		if (task_set_jobctl_pending(current, signr | gstop)) +			sig->group_stop_count++; + +		t = current; +		while_each_thread(current, t) {  			/*  			 * Setting state to TASK_STOPPED for a group  			 * stop is always done with the siglock held,  			 * so this check has no races.  			 */ -			if (!(t->flags & PF_EXITING) && -			    !task_is_stopped_or_traced(t)) { +			if (!task_is_stopped(t) && +			    task_set_jobctl_pending(t, signr | gstop)) {  				sig->group_stop_count++; -				signal_wake_up(t, 0); +				if (likely(!(t->ptrace & PT_SEIZED))) +					signal_wake_up(t, 0); +				else +					ptrace_trap_notify(t);  			} +		}  	} -	/* -	 * If there are no other threads in the group, or if there is -	 * a group stop in progress and we are the last to stop, report -	 * to the parent.  When ptraced, every thread reports itself. -	 */ -	notify = sig->group_stop_count == 1 ? CLD_STOPPED : 0; -	notify = tracehook_notify_jctl(notify, CLD_STOPPED); -	/* -	 * tracehook_notify_jctl() can drop and reacquire siglock, so -	 * we keep ->group_stop_count != 0 before the call. If SIGCONT -	 * or SIGKILL comes in between ->group_stop_count == 0. -	 */ -	if (sig->group_stop_count) { -		if (!--sig->group_stop_count) -			sig->flags = SIGNAL_STOP_STOPPED; -		current->exit_code = sig->group_exit_code; -		__set_current_state(TASK_STOPPED); -	} -	spin_unlock_irq(¤t->sighand->siglock); -	if (notify) { -		read_lock(&tasklist_lock); -		do_notify_parent_cldstop(current, notify); -		read_unlock(&tasklist_lock); -	} +	if (likely(!current->ptrace)) { +		int notify = 0; -	/* Now we don't run again until woken by SIGCONT or SIGKILL */ -	do { -		schedule(); -	} while (try_to_freeze()); +		/* +		 * If there are no other threads in the group, or if there +		 * is a group stop in progress and we are the last to stop, +		 * report to the parent. +		 */ +		if (task_participate_group_stop(current)) +			notify = CLD_STOPPED; -	tracehook_finish_jctl(); -	current->exit_code = 0; +		__set_current_state(TASK_STOPPED); +		spin_unlock_irq(¤t->sighand->siglock); -	return 1; +		/* +		 * Notify the parent of the group stop completion.  Because +		 * we're not holding either the siglock or tasklist_lock +		 * here, ptracer may attach inbetween; however, this is for +		 * group stop and should always be delivered to the real +		 * parent of the group leader.  The new ptracer will get +		 * its notification when this task transitions into +		 * TASK_TRACED. +		 */ +		if (notify) { +			read_lock(&tasklist_lock); +			do_notify_parent_cldstop(current, false, notify); +			read_unlock(&tasklist_lock); +		} + +		/* Now we don't run again until woken by SIGCONT or SIGKILL */ +		freezable_schedule(); +		return true; +	} else { +		/* +		 * While ptraced, group stop is handled by STOP trap. +		 * Schedule it and let the caller deal with it. +		 */ +		task_set_jobctl_pending(current, JOBCTL_TRAP_STOP); +		return false; +	}  } -static int ptrace_signal(int signr, siginfo_t *info, -			 struct pt_regs *regs, void *cookie) +/** + * do_jobctl_trap - take care of ptrace jobctl traps + * + * When PT_SEIZED, it's used for both group stop and explicit + * SEIZE/INTERRUPT traps.  Both generate PTRACE_EVENT_STOP trap with + * accompanying siginfo.  If stopped, lower eight bits of exit_code contain + * the stop signal; otherwise, %SIGTRAP. + * + * When !PT_SEIZED, it's used only for group stop trap with stop signal + * number as exit_code and no siginfo. + * + * CONTEXT: + * Must be called with @current->sighand->siglock held, which may be + * released and re-acquired before returning with intervening sleep. + */ +static void do_jobctl_trap(void)  { -	if (!task_ptrace(current)) -		return signr; - -	ptrace_signal_deliver(regs, cookie); +	struct signal_struct *signal = current->signal; +	int signr = current->jobctl & JOBCTL_STOP_SIGMASK; + +	if (current->ptrace & PT_SEIZED) { +		if (!signal->group_stop_count && +		    !(signal->flags & SIGNAL_STOP_STOPPED)) +			signr = SIGTRAP; +		WARN_ON_ONCE(!signr); +		ptrace_do_notify(signr, signr | (PTRACE_EVENT_STOP << 8), +				 CLD_STOPPED); +	} else { +		WARN_ON_ONCE(!signr); +		ptrace_stop(signr, CLD_STOPPED, 0, NULL); +		current->exit_code = 0; +	} +} -	/* Let the debugger run.  */ -	ptrace_stop(signr, 0, info); +static int ptrace_signal(int signr, siginfo_t *info) +{ +	ptrace_signal_deliver(); +	/* +	 * We do not check sig_kernel_stop(signr) but set this marker +	 * unconditionally because we do not know whether debugger will +	 * change signr. This flag has no meaning unless we are going +	 * to stop after return from ptrace_stop(). In this case it will +	 * be checked in do_signal_stop(), we should only stop if it was +	 * not cleared by SIGCONT while we were sleeping. See also the +	 * comment in dequeue_signal(). +	 */ +	current->jobctl |= JOBCTL_STOP_DEQUEUED; +	ptrace_stop(signr, CLD_TRAPPED, 0, info);  	/* We're back.  Did the debugger cancel the sig?  */  	signr = current->exit_code; @@ -1809,16 +2140,21 @@ 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;  		info->si_code = SI_USER; +		rcu_read_lock();  		info->si_pid = task_pid_vnr(current->parent); -		info->si_uid = task_uid(current->parent); +		info->si_uid = from_kuid_munged(current_user_ns(), +						task_uid(current->parent)); +		rcu_read_unlock();  	}  	/* If the (new) signal is now blocked, requeue it.  */ @@ -1837,15 +2173,20 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,  	struct signal_struct *signal = current->signal;  	int signr; -relock: +	if (unlikely(current->task_works)) +		task_work_run(); + +	if (unlikely(uprobe_deny_signal())) +		return 0; +  	/* -	 * We'll jump back here after any time we were stopped in TASK_STOPPED. -	 * While in TASK_STOPPED, we were considered "frozen enough". -	 * Now that we woke up, it's crucial if we're supposed to be -	 * frozen that we freeze now before running anything substantial. +	 * Do this once, we can't return to user-mode if freezing() == T. +	 * do_signal_stop() and ptrace_stop() do freezable_schedule() and +	 * thus do not need another check after return.  	 */  	try_to_freeze(); +relock:  	spin_lock_irq(&sighand->siglock);  	/*  	 * Every stopped thread goes here after wakeup. Check to see if @@ -1853,54 +2194,62 @@ relock:  	 * the CLD_ si_code into SIGNAL_CLD_MASK bits.  	 */  	if (unlikely(signal->flags & SIGNAL_CLD_MASK)) { -		int why = (signal->flags & SIGNAL_STOP_CONTINUED) -				? CLD_CONTINUED : CLD_STOPPED; +		int why; + +		if (signal->flags & SIGNAL_CLD_CONTINUED) +			why = CLD_CONTINUED; +		else +			why = CLD_STOPPED; +  		signal->flags &= ~SIGNAL_CLD_MASK; -		why = tracehook_notify_jctl(why, CLD_CONTINUED);  		spin_unlock_irq(&sighand->siglock); -		if (why) { -			read_lock(&tasklist_lock); -			do_notify_parent_cldstop(current->group_leader, why); -			read_unlock(&tasklist_lock); -		} +		/* +		 * Notify the parent that we're continuing.  This event is +		 * always per-process and doesn't make whole lot of sense +		 * for ptracers, who shouldn't consume the state via +		 * wait(2) either, but, for backward compatibility, notify +		 * the ptracer of the group leader too unless it's gonna be +		 * a duplicate. +		 */ +		read_lock(&tasklist_lock); +		do_notify_parent_cldstop(current, false, why); + +		if (ptrace_reparented(current->group_leader)) +			do_notify_parent_cldstop(current->group_leader, +						true, why); +		read_unlock(&tasklist_lock); +  		goto relock;  	}  	for (;;) {  		struct k_sigaction *ka; -		/* -		 * Tracing can induce an artifical signal and choose sigaction. -		 * The return value in @signr determines the default action, -		 * but @info->si_signo is the signal number we will report. -		 */ -		signr = tracehook_get_signal(current, regs, info, return_ka); -		if (unlikely(signr < 0)) + +		if (unlikely(current->jobctl & JOBCTL_STOP_PENDING) && +		    do_signal_stop(0))  			goto relock; -		if (unlikely(signr != 0)) -			ka = return_ka; -		else { -			if (unlikely(signal->group_stop_count > 0) && -			    do_signal_stop(0)) -				goto relock; -			signr = dequeue_signal(current, ¤t->blocked, -					       info); +		if (unlikely(current->jobctl & JOBCTL_TRAP_MASK)) { +			do_jobctl_trap(); +			spin_unlock_irq(&sighand->siglock); +			goto relock; +		} -			if (!signr) -				break; /* will return 0 */ +		signr = dequeue_signal(current, ¤t->blocked, info); -			if (signr != SIGKILL) { -				signr = ptrace_signal(signr, info, -						      regs, cookie); -				if (!signr) -					continue; -			} +		if (!signr) +			break; /* will return 0 */ -			ka = &sighand->action[signr-1]; +		if (unlikely(current->ptrace) && signr != SIGKILL) { +			signr = ptrace_signal(signr, info); +			if (!signr) +				continue;  		} +		ka = &sighand->action[signr-1]; +  		/* Trace actually delivered signals. */  		trace_signal_deliver(signr, info, ka); @@ -1979,7 +2328,8 @@ relock:  		if (sig_kernel_coredump(signr)) {  			if (print_fatal_signals) -				print_fatal_signal(regs, info->si_signo); +				print_fatal_signal(info->si_signo); +			proc_coredump_connector(current);  			/*  			 * If it was able to dump core, this kills all  			 * other threads in the group and synchronizes with @@ -1988,7 +2338,7 @@ relock:  			 * first and our do_group_exit call below will use  			 * that value and ignore the one we pass it.  			 */ -			do_coredump(info->si_signo, info->si_signo, regs); +			do_coredump(info);  		}  		/* @@ -2001,13 +2351,92 @@ relock:  	return signr;  } +/** + * signal_delivered -  + * @sig:		number of signal being delivered + * @info:		siginfo_t of signal being delivered + * @ka:			sigaction setting that chose the handler + * @regs:		user register state + * @stepping:		nonzero if debugger single-step or block-step in use + * + * This function should be called when a signal has successfully been + * delivered. It updates the blocked signals accordingly (@ka->sa.sa_mask + * is always blocked, and the signal itself is blocked unless %SA_NODEFER + * is set in @ka->sa.sa_flags.  Tracing is notified. + */ +void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, +			struct pt_regs *regs, int stepping) +{ +	sigset_t blocked; + +	/* A signal was successfully delivered, and the +	   saved sigmask was stored on the signal frame, +	   and will be restored by sigreturn.  So we can +	   simply clear the restore sigmask flag.  */ +	clear_restore_sigmask(); + +	sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask); +	if (!(ka->sa.sa_flags & SA_NODEFER)) +		sigaddset(&blocked, sig); +	set_current_blocked(&blocked); +	tracehook_signal_handler(sig, info, ka, regs, stepping); +} + +void signal_setup_done(int failed, struct ksignal *ksig, int stepping) +{ +	if (failed) +		force_sigsegv(ksig->sig, current); +	else +		signal_delivered(ksig->sig, &ksig->info, &ksig->ka, +			signal_pt_regs(), stepping); +} + +/* + * It could be that complete_signal() picked us to notify about the + * group-wide signal. Other threads should be notified now to take + * the shared signals in @which since we will not. + */ +static void retarget_shared_pending(struct task_struct *tsk, sigset_t *which) +{ +	sigset_t retarget; +	struct task_struct *t; + +	sigandsets(&retarget, &tsk->signal->shared_pending.signal, which); +	if (sigisemptyset(&retarget)) +		return; + +	t = tsk; +	while_each_thread(tsk, t) { +		if (t->flags & PF_EXITING) +			continue; + +		if (!has_pending_signals(&retarget, &t->blocked)) +			continue; +		/* Remove the signals this thread can handle. */ +		sigandsets(&retarget, &retarget, &t->blocked); + +		if (!signal_pending(t)) +			signal_wake_up(t, 0); + +		if (sigisemptyset(&retarget)) +			break; +	} +} +  void exit_signals(struct task_struct *tsk)  {  	int group_stop = 0; -	struct task_struct *t; +	sigset_t unblocked; + +	/* +	 * @tsk is about to have PF_EXITING set - lock out users which +	 * expect stable threadgroup. +	 */ +	threadgroup_change_begin(tsk);  	if (thread_group_empty(tsk) || signal_group_exit(tsk->signal)) {  		tsk->flags |= PF_EXITING; +		threadgroup_change_end(tsk);  		return;  	} @@ -2017,28 +2446,29 @@ void exit_signals(struct task_struct *tsk)  	 * see wants_signal(), do_signal_stop().  	 */  	tsk->flags |= PF_EXITING; + +	threadgroup_change_end(tsk); +  	if (!signal_pending(tsk))  		goto out; -	/* 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. -	 */ -	for (t = tsk; (t = next_thread(t)) != tsk; ) -		if (!signal_pending(t) && !(t->flags & PF_EXITING)) -			recalc_sigpending_and_wake(t); +	unblocked = tsk->blocked; +	signotset(&unblocked); +	retarget_shared_pending(tsk, &unblocked); -	if (unlikely(tsk->signal->group_stop_count) && -			!--tsk->signal->group_stop_count) { -		tsk->signal->flags = SIGNAL_STOP_STOPPED; -		group_stop = tracehook_notify_jctl(CLD_STOPPED, CLD_STOPPED); -	} +	if (unlikely(tsk->jobctl & JOBCTL_STOP_PENDING) && +	    task_participate_group_stop(tsk)) +		group_stop = CLD_STOPPED;  out:  	spin_unlock_irq(&tsk->sighand->siglock); +	/* +	 * If group stop has completed, deliver the notification.  This +	 * should always go to the real parent of the group leader. +	 */  	if (unlikely(group_stop)) {  		read_lock(&tasklist_lock); -		do_notify_parent_cldstop(tsk, group_stop); +		do_notify_parent_cldstop(tsk, false, group_stop);  		read_unlock(&tasklist_lock);  	}  } @@ -2058,6 +2488,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; @@ -2069,11 +2502,39 @@ long do_no_restart_syscall(struct restart_block *param)  	return -EINTR;  } -/* - * We don't need to get the kernel lock - this is all local to this - * particular thread.. (and that's good, because this is _heavily_ - * used by various programs) +static void __set_task_blocked(struct task_struct *tsk, const sigset_t *newset) +{ +	if (signal_pending(tsk) && !thread_group_empty(tsk)) { +		sigset_t newblocked; +		/* A set of now blocked but previously unblocked signals. */ +		sigandnsets(&newblocked, newset, ¤t->blocked); +		retarget_shared_pending(tsk, &newblocked); +	} +	tsk->blocked = *newset; +	recalc_sigpending(); +} + +/** + * set_current_blocked - change current->blocked mask + * @newset: new mask + * + * It is wrong to change ->blocked directly, this helper should be used + * to ensure the process can't miss a shared signal we are going to block.   */ +void set_current_blocked(sigset_t *newset) +{ +	sigdelsetmask(newset, sigmask(SIGKILL) | sigmask(SIGSTOP)); +	__set_current_blocked(newset); +} + +void __set_current_blocked(const sigset_t *newset) +{ +	struct task_struct *tsk = current; + +	spin_lock_irq(&tsk->sighand->siglock); +	__set_task_blocked(tsk, newset); +	spin_unlock_irq(&tsk->sighand->siglock); +}  /*   * This is also useful for kernel threads that want to temporarily @@ -2085,100 +2546,161 @@ long do_no_restart_syscall(struct restart_block *param)   */  int sigprocmask(int how, sigset_t *set, sigset_t *oldset)  { -	int error; +	struct task_struct *tsk = current; +	sigset_t newset; -	spin_lock_irq(¤t->sighand->siglock); +	/* Lockless, only current can change ->blocked, never from irq */  	if (oldset) -		*oldset = current->blocked; +		*oldset = tsk->blocked; -	error = 0;  	switch (how) {  	case SIG_BLOCK: -		sigorsets(¤t->blocked, ¤t->blocked, set); +		sigorsets(&newset, &tsk->blocked, set);  		break;  	case SIG_UNBLOCK: -		signandsets(¤t->blocked, ¤t->blocked, set); +		sigandnsets(&newset, &tsk->blocked, set);  		break;  	case SIG_SETMASK: -		current->blocked = *set; +		newset = *set;  		break;  	default: -		error = -EINVAL; +		return -EINVAL;  	} -	recalc_sigpending(); -	spin_unlock_irq(¤t->sighand->siglock); -	return error; +	__set_current_blocked(&newset); +	return 0;  } -SYSCALL_DEFINE4(rt_sigprocmask, int, how, sigset_t __user *, set, +/** + *  sys_rt_sigprocmask - change the list of currently blocked signals + *  @how: whether to add, remove, or set signals + *  @nset: 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 *, nset,  		sigset_t __user *, oset, size_t, sigsetsize)  { -	int error = -EINVAL;  	sigset_t old_set, new_set; +	int error;  	/* XXX: Don't preclude handling different sized sigset_t's.  */  	if (sigsetsize != sizeof(sigset_t)) -		goto out; +		return -EINVAL; -	if (set) { -		error = -EFAULT; -		if (copy_from_user(&new_set, set, sizeof(*set))) -			goto out; +	old_set = current->blocked; + +	if (nset) { +		if (copy_from_user(&new_set, nset, sizeof(sigset_t))) +			return -EFAULT;  		sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP)); -		error = sigprocmask(how, &new_set, &old_set); +		error = sigprocmask(how, &new_set, NULL);  		if (error) -			goto out; -		if (oset) -			goto set_old; -	} else if (oset) { -		spin_lock_irq(¤t->sighand->siglock); -		old_set = current->blocked; -		spin_unlock_irq(¤t->sighand->siglock); +			return error; +	} -	set_old: -		error = -EFAULT; -		if (copy_to_user(oset, &old_set, sizeof(*oset))) -			goto out; +	if (oset) { +		if (copy_to_user(oset, &old_set, sizeof(sigset_t))) +			return -EFAULT;  	} -	error = 0; -out: -	return error; + +	return 0;  } -long do_sigpending(void __user *set, unsigned long sigsetsize) +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset, +		compat_sigset_t __user *, oset, compat_size_t, sigsetsize)  { -	long error = -EINVAL; -	sigset_t pending; +#ifdef __BIG_ENDIAN +	sigset_t old_set = current->blocked; + +	/* XXX: Don't preclude handling different sized sigset_t's.  */ +	if (sigsetsize != sizeof(sigset_t)) +		return -EINVAL; + +	if (nset) { +		compat_sigset_t new32; +		sigset_t new_set; +		int error; +		if (copy_from_user(&new32, nset, sizeof(compat_sigset_t))) +			return -EFAULT; +		sigset_from_compat(&new_set, &new32); +		sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP)); + +		error = sigprocmask(how, &new_set, NULL); +		if (error) +			return error; +	} +	if (oset) { +		compat_sigset_t old32; +		sigset_to_compat(&old32, &old_set); +		if (copy_to_user(oset, &old32, sizeof(compat_sigset_t))) +			return -EFAULT; +	} +	return 0; +#else +	return sys_rt_sigprocmask(how, (sigset_t __user *)nset, +				  (sigset_t __user *)oset, sigsetsize); +#endif +} +#endif + +static int do_sigpending(void *set, unsigned long sigsetsize) +{  	if (sigsetsize > sizeof(sigset_t)) -		goto out; +		return -EINVAL;  	spin_lock_irq(¤t->sighand->siglock); -	sigorsets(&pending, ¤t->pending.signal, +	sigorsets(set, ¤t->pending.signal,  		  ¤t->signal->shared_pending.signal);  	spin_unlock_irq(¤t->sighand->siglock);  	/* Outside the lock because only this thread touches it.  */ -	sigandsets(&pending, ¤t->blocked, &pending); - -	error = -EFAULT; -	if (!copy_to_user(set, &pending, sigsetsize)) -		error = 0; +	sigandsets(set, ¤t->blocked, set); +	return 0; +} -out: -	return error; -}	 +/** + *  sys_rt_sigpending - examine a pending signal that has been raised + *			while blocked + *  @uset: stores pending signals + *  @sigsetsize: size of sigset_t type or larger + */ +SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize) +{ +	sigset_t set; +	int err = do_sigpending(&set, sigsetsize); +	if (!err && copy_to_user(uset, &set, sigsetsize)) +		err = -EFAULT; +	return err; +} -SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, set, size_t, sigsetsize) +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset, +		compat_size_t, sigsetsize)  { -	return do_sigpending(set, sigsetsize); +#ifdef __BIG_ENDIAN +	sigset_t set; +	int err = do_sigpending(&set, sigsetsize); +	if (!err) { +		compat_sigset_t set32; +		sigset_to_compat(&set32, &set); +		/* we can get here only if sigsetsize <= sizeof(set) */ +		if (copy_to_user(uset, &set32, sigsetsize)) +			err = -EFAULT; +	} +	return err; +#else +	return sys_rt_sigpending((sigset_t __user *)uset, sigsetsize); +#endif  } +#endif  #ifndef HAVE_ARCH_COPY_SIGINFO_TO_USER -int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from) +int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)  {  	int err; @@ -2219,9 +2741,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); @@ -2240,6 +2762,13 @@ int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from)  		err |= __put_user(from->si_uid, &to->si_uid);  		err |= __put_user(from->si_ptr, &to->si_ptr);  		break; +#ifdef __ARCH_SIGSYS +	case __SI_SYS: +		err |= __put_user(from->si_call_addr, &to->si_call_addr); +		err |= __put_user(from->si_syscall, &to->si_syscall); +		err |= __put_user(from->si_arch, &to->si_arch); +		break; +#endif  	default: /* this is just in case for now ... */  		err |= __put_user(from->si_pid, &to->si_pid);  		err |= __put_user(from->si_uid, &to->si_uid); @@ -2250,15 +2779,82 @@ int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from)  #endif +/** + *  do_sigtimedwait - wait for queued signals specified in @which + *  @which: queued signals to wait for + *  @info: if non-null, the signal's siginfo is returned here + *  @ts: upper bound on process time suspension + */ +int do_sigtimedwait(const sigset_t *which, siginfo_t *info, +			const struct timespec *ts) +{ +	struct task_struct *tsk = current; +	long timeout = MAX_SCHEDULE_TIMEOUT; +	sigset_t mask = *which; +	int sig; + +	if (ts) { +		if (!timespec_valid(ts)) +			return -EINVAL; +		timeout = timespec_to_jiffies(ts); +		/* +		 * We can be close to the next tick, add another one +		 * to ensure we will wait at least the time asked for. +		 */ +		if (ts->tv_sec || ts->tv_nsec) +			timeout++; +	} + +	/* +	 * Invert the set of allowed signals to get those we want to block. +	 */ +	sigdelsetmask(&mask, sigmask(SIGKILL) | sigmask(SIGSTOP)); +	signotset(&mask); + +	spin_lock_irq(&tsk->sighand->siglock); +	sig = dequeue_signal(tsk, &mask, info); +	if (!sig && timeout) { +		/* +		 * None ready, temporarily unblock those we're interested +		 * while we are sleeping in so that we'll be awakened when +		 * they arrive. Unblocking is always fine, we can avoid +		 * set_current_blocked(). +		 */ +		tsk->real_blocked = tsk->blocked; +		sigandsets(&tsk->blocked, &tsk->blocked, &mask); +		recalc_sigpending(); +		spin_unlock_irq(&tsk->sighand->siglock); + +		timeout = freezable_schedule_timeout_interruptible(timeout); + +		spin_lock_irq(&tsk->sighand->siglock); +		__set_task_blocked(tsk, &tsk->real_blocked); +		sigemptyset(&tsk->real_blocked); +		sig = dequeue_signal(tsk, &mask, info); +	} +	spin_unlock_irq(&tsk->sighand->siglock); + +	if (sig) +		return sig; +	return timeout ? -EINTR : -EAGAIN; +} + +/** + *  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)  { -	int ret, sig;  	sigset_t these;  	struct timespec ts;  	siginfo_t info; -	long timeout = 0; +	int ret;  	/* XXX: Don't preclude handling different sized sigset_t's.  */  	if (sigsetsize != sizeof(sigset_t)) @@ -2266,65 +2862,27 @@ 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. -	 */ -	sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP)); -	signotset(&these);  	if (uts) {  		if (copy_from_user(&ts, uts, sizeof(ts)))  			return -EFAULT; -		if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0 -		    || ts.tv_sec < 0) -			return -EINVAL;  	} -	spin_lock_irq(¤t->sighand->siglock); -	sig = dequeue_signal(current, &these, &info); -	if (!sig) { -		timeout = MAX_SCHEDULE_TIMEOUT; -		if (uts) -			timeout = (timespec_to_jiffies(&ts) -				   + (ts.tv_sec || ts.tv_nsec)); - -		if (timeout) { -			/* None ready -- temporarily unblock those we're -			 * interested while we are sleeping in so that we'll -			 * be awakened when they arrive.  */ -			current->real_blocked = current->blocked; -			sigandsets(¤t->blocked, ¤t->blocked, &these); -			recalc_sigpending(); -			spin_unlock_irq(¤t->sighand->siglock); - -			timeout = schedule_timeout_interruptible(timeout); - -			spin_lock_irq(¤t->sighand->siglock); -			sig = dequeue_signal(current, &these, &info); -			current->blocked = current->real_blocked; -			siginitset(¤t->real_blocked, 0); -			recalc_sigpending(); -		} -	} -	spin_unlock_irq(¤t->sighand->siglock); +	ret = do_sigtimedwait(&these, &info, uts ? &ts : NULL); -	if (sig) { -		ret = sig; -		if (uinfo) { -			if (copy_siginfo_to_user(uinfo, &info)) -				ret = -EFAULT; -		} -	} else { -		ret = -EAGAIN; -		if (timeout) -			ret = -EINTR; +	if (ret > 0 && uinfo) { +		if (copy_siginfo_to_user(uinfo, &info)) +			ret = -EFAULT;  	}  	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; @@ -2333,7 +2891,7 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)  	info.si_errno = 0;  	info.si_code = SI_USER;  	info.si_pid = task_tgid_vnr(current); -	info.si_uid = current_uid(); +	info.si_uid = from_kuid_munged(current_user_ns(), current_uid());  	return kill_something_info(sig, &info, pid);  } @@ -2370,13 +2928,13 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)  static int do_tkill(pid_t tgid, pid_t pid, int sig)  { -	struct siginfo info; +	struct siginfo info = {};  	info.si_signo = sig;  	info.si_errno = 0;  	info.si_code = SI_TKILL;  	info.si_pid = task_tgid_vnr(current); -	info.si_uid = current_uid(); +	info.si_uid = from_kuid_munged(current_user_ns(), current_uid());  	return do_send_specific(tgid, pid, sig, &info);  } @@ -2400,7 +2958,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) @@ -2412,34 +2974,67 @@ SYSCALL_DEFINE2(tkill, pid_t, pid, int, sig)  	return do_tkill(0, pid, sig);  } +static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info) +{ +	/* Not even root can pretend to send signals from the kernel. +	 * Nor can they impersonate a kill()/tgkill(), which adds source info. +	 */ +	if ((info->si_code >= 0 || info->si_code == SI_TKILL) && +	    (task_pid_vnr(current) != pid)) { +		/* We used to allow any < 0 si_code */ +		WARN_ON_ONCE(info->si_code < 0); +		return -EPERM; +	} +	info->si_signo = sig; + +	/* POSIX.1b doesn't mention process groups.  */ +	return kill_proc_info(sig, info, pid); +} + +/** + *  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)  {  	siginfo_t info; -  	if (copy_from_user(&info, uinfo, sizeof(siginfo_t)))  		return -EFAULT; +	return do_rt_sigqueueinfo(pid, sig, &info); +} -	/* Not even root can pretend to send signals from the kernel. -	   Nor can they impersonate a kill(), which adds source info.  */ -	if (info.si_code >= 0) -		return -EPERM; -	info.si_signo = sig; - -	/* POSIX.1b doesn't mention process groups.  */ -	return kill_proc_info(sig, &info, pid); +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo, +			compat_pid_t, pid, +			int, sig, +			struct compat_siginfo __user *, uinfo) +{ +	siginfo_t info; +	int ret = copy_siginfo_from_user32(&info, uinfo); +	if (unlikely(ret)) +		return ret; +	return do_rt_sigqueueinfo(pid, sig, &info);  } +#endif -long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info) +static int do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info)  {  	/* This is only valid for single tasks */  	if (pid <= 0 || tgid <= 0)  		return -EINVAL;  	/* Not even root can pretend to send signals from the kernel. -	   Nor can they impersonate a kill(), which adds source info.  */ -	if (info->si_code >= 0) +	 * Nor can they impersonate a kill()/tgkill(), which adds source info. +	 */ +	if (((info->si_code >= 0 || info->si_code == SI_TKILL)) && +	    (task_pid_vnr(current) != pid)) { +		/* We used to allow any < 0 si_code */ +		WARN_ON_ONCE(info->si_code < 0);  		return -EPERM; +	}  	info->si_signo = sig;  	return do_send_specific(tgid, pid, sig, info); @@ -2456,18 +3051,54 @@ SYSCALL_DEFINE4(rt_tgsigqueueinfo, pid_t, tgid, pid_t, pid, int, sig,  	return do_rt_tgsigqueueinfo(tgid, pid, sig, &info);  } +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo, +			compat_pid_t, tgid, +			compat_pid_t, pid, +			int, sig, +			struct compat_siginfo __user *, uinfo) +{ +	siginfo_t info; + +	if (copy_siginfo_from_user32(&info, uinfo)) +		return -EFAULT; +	return do_rt_tgsigqueueinfo(tgid, pid, sig, &info); +} +#endif + +/* + * For kthreads only, must not be used if cloned with CLONE_SIGHAND + */ +void kernel_sigaction(int sig, __sighandler_t action) +{ +	spin_lock_irq(¤t->sighand->siglock); +	current->sighand->action[sig - 1].sa.sa_handler = action; +	if (action == SIG_IGN) { +		sigset_t mask; + +		sigemptyset(&mask); +		sigaddset(&mask, sig); + +		flush_sigqueue_mask(&mask, ¤t->signal->shared_pending); +		flush_sigqueue_mask(&mask, ¤t->pending); +		recalc_sigpending(); +	} +	spin_unlock_irq(¤t->sighand->siglock); +} +EXPORT_SYMBOL(kernel_sigaction); +  int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)  { -	struct task_struct *t = current; +	struct task_struct *p = current, *t;  	struct k_sigaction *k;  	sigset_t mask;  	if (!valid_signal(sig) || sig < 1 || (act && sig_kernel_only(sig)))  		return -EINVAL; -	k = &t->sighand->action[sig-1]; +	k = &p->sighand->action[sig-1]; -	spin_lock_irq(¤t->sighand->siglock); +	spin_lock_irq(&p->sighand->siglock);  	if (oact)  		*oact = *k; @@ -2486,22 +3117,20 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)  		 *   (for example, SIGCHLD), shall cause the pending signal to  		 *   be discarded, whether or not it is blocked"  		 */ -		if (sig_handler_ignored(sig_handler(t, sig), sig)) { +		if (sig_handler_ignored(sig_handler(p, sig), sig)) {  			sigemptyset(&mask);  			sigaddset(&mask, sig); -			rm_from_queue_full(&mask, &t->signal->shared_pending); -			do { -				rm_from_queue_full(&mask, &t->pending); -				t = next_thread(t); -			} while (t != current); +			flush_sigqueue_mask(&mask, &p->signal->shared_pending); +			for_each_thread(p, t) +				flush_sigqueue_mask(&mask, &t->pending);  		}  	} -	spin_unlock_irq(¤t->sighand->siglock); +	spin_unlock_irq(&p->sighand->siglock);  	return 0;  } -int  +static int  do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long sp)  {  	stack_t oss; @@ -2531,12 +3160,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; @@ -2567,71 +3195,149 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s  out:  	return error;  } +SYSCALL_DEFINE2(sigaltstack,const stack_t __user *,uss, stack_t __user *,uoss) +{ +	return do_sigaltstack(uss, uoss, current_user_stack_pointer()); +} + +int restore_altstack(const stack_t __user *uss) +{ +	int err = do_sigaltstack(uss, NULL, current_user_stack_pointer()); +	/* squash all but EFAULT for now */ +	return err == -EFAULT ? err : 0; +} + +int __save_altstack(stack_t __user *uss, unsigned long sp) +{ +	struct task_struct *t = current; +	return  __put_user((void __user *)t->sas_ss_sp, &uss->ss_sp) | +		__put_user(sas_ss_flags(sp), &uss->ss_flags) | +		__put_user(t->sas_ss_size, &uss->ss_size); +} + +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE2(sigaltstack, +			const compat_stack_t __user *, uss_ptr, +			compat_stack_t __user *, uoss_ptr) +{ +	stack_t uss, uoss; +	int ret; +	mm_segment_t seg; + +	if (uss_ptr) { +		compat_stack_t uss32; + +		memset(&uss, 0, sizeof(stack_t)); +		if (copy_from_user(&uss32, uss_ptr, sizeof(compat_stack_t))) +			return -EFAULT; +		uss.ss_sp = compat_ptr(uss32.ss_sp); +		uss.ss_flags = uss32.ss_flags; +		uss.ss_size = uss32.ss_size; +	} +	seg = get_fs(); +	set_fs(KERNEL_DS); +	ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL), +			     (stack_t __force __user *) &uoss, +			     compat_user_stack_pointer()); +	set_fs(seg); +	if (ret >= 0 && uoss_ptr)  { +		if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(compat_stack_t)) || +		    __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) || +		    __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) || +		    __put_user(uoss.ss_size, &uoss_ptr->ss_size)) +			ret = -EFAULT; +	} +	return ret; +} + +int compat_restore_altstack(const compat_stack_t __user *uss) +{ +	int err = compat_sys_sigaltstack(uss, NULL); +	/* squash all but -EFAULT for now */ +	return err == -EFAULT ? err : 0; +} + +int __compat_save_altstack(compat_stack_t __user *uss, unsigned long sp) +{ +	struct task_struct *t = current; +	return  __put_user(ptr_to_compat((void __user *)t->sas_ss_sp), &uss->ss_sp) | +		__put_user(sas_ss_flags(sp), &uss->ss_flags) | +		__put_user(t->sas_ss_size, &uss->ss_size); +} +#endif  #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)); +	return sys_rt_sigpending((sigset_t __user *)set, sizeof(old_sigset_t));   }  #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 + *  @nset: 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, +SYSCALL_DEFINE3(sigprocmask, int, how, old_sigset_t __user *, nset,  		old_sigset_t __user *, oset)  { -	int error;  	old_sigset_t old_set, new_set; +	sigset_t new_blocked; -	if (set) { -		error = -EFAULT; -		if (copy_from_user(&new_set, set, sizeof(*set))) -			goto out; -		new_set &= ~(sigmask(SIGKILL) | sigmask(SIGSTOP)); +	old_set = current->blocked.sig[0]; -		spin_lock_irq(¤t->sighand->siglock); -		old_set = current->blocked.sig[0]; +	if (nset) { +		if (copy_from_user(&new_set, nset, sizeof(*nset))) +			return -EFAULT; + +		new_blocked = current->blocked; -		error = 0;  		switch (how) { -		default: -			error = -EINVAL; -			break;  		case SIG_BLOCK: -			sigaddsetmask(¤t->blocked, new_set); +			sigaddsetmask(&new_blocked, new_set);  			break;  		case SIG_UNBLOCK: -			sigdelsetmask(¤t->blocked, new_set); +			sigdelsetmask(&new_blocked, new_set);  			break;  		case SIG_SETMASK: -			current->blocked.sig[0] = new_set; +			new_blocked.sig[0] = new_set;  			break; +		default: +			return -EINVAL;  		} -		recalc_sigpending(); -		spin_unlock_irq(¤t->sighand->siglock); -		if (error) -			goto out; -		if (oset) -			goto set_old; -	} else if (oset) { -		old_set = current->blocked.sig[0]; -	set_old: -		error = -EFAULT; +		set_current_blocked(&new_blocked); +	} + +	if (oset) {  		if (copy_to_user(oset, &old_set, sizeof(*oset))) -			goto out; +			return -EFAULT;  	} -	error = 0; -out: -	return error; + +	return 0;  }  #endif /* __ARCH_WANT_SYS_SIGPROCMASK */ -#ifdef __ARCH_WANT_SYS_RT_SIGACTION +#ifndef CONFIG_ODD_RT_SIGACTION +/** + *  sys_rt_sigaction - alter an action taken by a process + *  @sig: signal to be sent + *  @act: new sigaction + *  @oact: used to save the previous sigaction + *  @sigsetsize: size of sigset_t type + */  SYSCALL_DEFINE4(rt_sigaction, int, sig,  		const struct sigaction __user *, act,  		struct sigaction __user *, oact, @@ -2658,9 +3364,134 @@ SYSCALL_DEFINE4(rt_sigaction, int, sig,  out:  	return ret;  } -#endif /* __ARCH_WANT_SYS_RT_SIGACTION */ +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig, +		const struct compat_sigaction __user *, act, +		struct compat_sigaction __user *, oact, +		compat_size_t, sigsetsize) +{ +	struct k_sigaction new_ka, old_ka; +	compat_sigset_t mask; +#ifdef __ARCH_HAS_SA_RESTORER +	compat_uptr_t restorer; +#endif +	int ret; + +	/* XXX: Don't preclude handling different sized sigset_t's.  */ +	if (sigsetsize != sizeof(compat_sigset_t)) +		return -EINVAL; -#ifdef __ARCH_WANT_SYS_SGETMASK +	if (act) { +		compat_uptr_t handler; +		ret = get_user(handler, &act->sa_handler); +		new_ka.sa.sa_handler = compat_ptr(handler); +#ifdef __ARCH_HAS_SA_RESTORER +		ret |= get_user(restorer, &act->sa_restorer); +		new_ka.sa.sa_restorer = compat_ptr(restorer); +#endif +		ret |= copy_from_user(&mask, &act->sa_mask, sizeof(mask)); +		ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags); +		if (ret) +			return -EFAULT; +		sigset_from_compat(&new_ka.sa.sa_mask, &mask); +	} + +	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); +	if (!ret && oact) { +		sigset_to_compat(&mask, &old_ka.sa.sa_mask); +		ret = put_user(ptr_to_compat(old_ka.sa.sa_handler),  +			       &oact->sa_handler); +		ret |= copy_to_user(&oact->sa_mask, &mask, sizeof(mask)); +		ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags); +#ifdef __ARCH_HAS_SA_RESTORER +		ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer), +				&oact->sa_restorer); +#endif +	} +	return ret; +} +#endif +#endif /* !CONFIG_ODD_RT_SIGACTION */ + +#ifdef CONFIG_OLD_SIGACTION +SYSCALL_DEFINE3(sigaction, int, sig, +		const struct old_sigaction __user *, act, +	        struct old_sigaction __user *, oact) +{ +	struct k_sigaction new_ka, old_ka; +	int ret; + +	if (act) { +		old_sigset_t mask; +		if (!access_ok(VERIFY_READ, act, sizeof(*act)) || +		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) || +		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || +		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) || +		    __get_user(mask, &act->sa_mask)) +			return -EFAULT; +#ifdef __ARCH_HAS_KA_RESTORER +		new_ka.ka_restorer = NULL; +#endif +		siginitset(&new_ka.sa.sa_mask, mask); +	} + +	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + +	if (!ret && oact) { +		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || +		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || +		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || +		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || +		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) +			return -EFAULT; +	} + +	return ret; +} +#endif +#ifdef CONFIG_COMPAT_OLD_SIGACTION +COMPAT_SYSCALL_DEFINE3(sigaction, int, sig, +		const struct compat_old_sigaction __user *, act, +	        struct compat_old_sigaction __user *, oact) +{ +	struct k_sigaction new_ka, old_ka; +	int ret; +	compat_old_sigset_t mask; +	compat_uptr_t handler, restorer; + +	if (act) { +		if (!access_ok(VERIFY_READ, act, sizeof(*act)) || +		    __get_user(handler, &act->sa_handler) || +		    __get_user(restorer, &act->sa_restorer) || +		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) || +		    __get_user(mask, &act->sa_mask)) +			return -EFAULT; + +#ifdef __ARCH_HAS_KA_RESTORER +		new_ka.ka_restorer = NULL; +#endif +		new_ka.sa.sa_handler = compat_ptr(handler); +		new_ka.sa.sa_restorer = compat_ptr(restorer); +		siginitset(&new_ka.sa.sa_mask, mask); +	} + +	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + +	if (!ret && oact) { +		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || +		    __put_user(ptr_to_compat(old_ka.sa.sa_handler), +			       &oact->sa_handler) || +		    __put_user(ptr_to_compat(old_ka.sa.sa_restorer), +			       &oact->sa_restorer) || +		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || +		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) +			return -EFAULT; +	} +	return ret; +} +#endif + +#ifdef CONFIG_SGETMASK_SYSCALL  /*   * For backwards compatibility.  Functionality superseded by sigprocmask. @@ -2673,19 +3504,15 @@ SYSCALL_DEFINE0(sgetmask)  SYSCALL_DEFINE1(ssetmask, int, newmask)  { -	int old; +	int old = current->blocked.sig[0]; +	sigset_t newset; -	spin_lock_irq(¤t->sighand->siglock); -	old = current->blocked.sig[0]; - -	siginitset(¤t->blocked, newmask & ~(sigmask(SIGKILL)| -						  sigmask(SIGSTOP))); -	recalc_sigpending(); -	spin_unlock_irq(¤t->sighand->siglock); +	siginitset(&newset, newmask); +	set_current_blocked(&newset);  	return old;  } -#endif /* __ARCH_WANT_SGETMASK */ +#endif /* CONFIG_SGETMASK_SYSCALL */  #ifdef __ARCH_WANT_SYS_SIGNAL  /* @@ -2710,14 +3537,32 @@ SYSCALL_DEFINE2(signal, int, sig, __sighandler_t, handler)  SYSCALL_DEFINE0(pause)  { -	current->state = TASK_INTERRUPTIBLE; -	schedule(); +	while (!signal_pending(current)) { +		current->state = TASK_INTERRUPTIBLE; +		schedule(); +	}  	return -ERESTARTNOHAND;  }  #endif -#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND +int sigsuspend(sigset_t *set) +{ +	current->saved_sigmask = current->blocked; +	set_current_blocked(set); + +	current->state = TASK_INTERRUPTIBLE; +	schedule(); +	set_restore_sigmask(); +	return -ERESTARTNOHAND; +} + +/** + *  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; @@ -2728,22 +3573,49 @@ SYSCALL_DEFINE2(rt_sigsuspend, sigset_t __user *, unewset, size_t, sigsetsize)  	if (copy_from_user(&newset, unewset, sizeof(newset)))  		return -EFAULT; -	sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); +	return sigsuspend(&newset); +} +  +#ifdef CONFIG_COMPAT +COMPAT_SYSCALL_DEFINE2(rt_sigsuspend, compat_sigset_t __user *, unewset, compat_size_t, sigsetsize) +{ +#ifdef __BIG_ENDIAN +	sigset_t newset; +	compat_sigset_t newset32; -	spin_lock_irq(¤t->sighand->siglock); -	current->saved_sigmask = current->blocked; -	current->blocked = newset; -	recalc_sigpending(); -	spin_unlock_irq(¤t->sighand->siglock); +	/* XXX: Don't preclude handling different sized sigset_t's.  */ +	if (sigsetsize != sizeof(sigset_t)) +		return -EINVAL; -	current->state = TASK_INTERRUPTIBLE; -	schedule(); -	set_restore_sigmask(); -	return -ERESTARTNOHAND; +	if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t))) +		return -EFAULT; +	sigset_from_compat(&newset, &newset32); +	return sigsuspend(&newset); +#else +	/* on little-endian bitmaps don't care about granularity */ +	return sys_rt_sigsuspend((sigset_t __user *)unewset, sigsetsize); +#endif +} +#endif + +#ifdef CONFIG_OLD_SIGSUSPEND +SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask) +{ +	sigset_t blocked; +	siginitset(&blocked, mask); +	return sigsuspend(&blocked);  } -#endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */ +#endif +#ifdef CONFIG_OLD_SIGSUSPEND3 +SYSCALL_DEFINE3(sigsuspend, int, unused1, int, unused2, old_sigset_t, mask) +{ +	sigset_t blocked; +	siginitset(&blocked, mask); +	return sigsuspend(&blocked); +} +#endif -__attribute__((weak)) const char *arch_vma_name(struct vm_area_struct *vma) +__weak const char *arch_vma_name(struct vm_area_struct *vma)  {  	return NULL;  }  | 
