signal.c 45.4 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8
/*
 *  linux/kernel/signal.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  1997-11-02  Modified for POSIX.1b signals by Richard Henderson
 */

Ingo Molnar's avatar
Ingo Molnar committed
9 10
#define __KERNEL_SYSCALLS__

Linus Torvalds's avatar
Linus Torvalds committed
11 12 13 14 15 16 17
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/unistd.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/sched.h>
18
#include <linux/fs.h>
19 20
#include <linux/tty.h>
#include <linux/binfmts.h>
21
#include <linux/security.h>
Ingo Molnar's avatar
Ingo Molnar committed
22
#include <asm/param.h>
Linus Torvalds's avatar
Linus Torvalds committed
23
#include <asm/uaccess.h>
24
#include <asm/siginfo.h>
Linus Torvalds's avatar
Linus Torvalds committed
25 26 27 28 29 30 31 32 33 34

/*
 * SLAB caches for signal bits.
 */

static kmem_cache_t *sigqueue_cachep;

atomic_t nr_queued_signals;
int max_queued_signals = 1024;

Ingo Molnar's avatar
Ingo Molnar committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
/*********************************************************

    POSIX thread group signal behavior:

----------------------------------------------------------
|                    |  userspace       |  kernel        |
----------------------------------------------------------
|  SIGHUP            |  load-balance    |  kill-all      |
|  SIGINT            |  load-balance    |  kill-all      |
|  SIGQUIT           |  load-balance    |  kill-all+core |
|  SIGILL            |  specific        |  kill-all+core |
|  SIGTRAP           |  specific        |  kill-all+core |
|  SIGABRT/SIGIOT    |  specific        |  kill-all+core |
|  SIGBUS            |  specific        |  kill-all+core |
|  SIGFPE            |  specific        |  kill-all+core |
|  SIGKILL           |  n/a             |  kill-all      |
|  SIGUSR1           |  load-balance    |  kill-all      |
|  SIGSEGV           |  specific        |  kill-all+core |
|  SIGUSR2           |  load-balance    |  kill-all      |
|  SIGPIPE           |  specific        |  kill-all      |
|  SIGALRM           |  load-balance    |  kill-all      |
|  SIGTERM           |  load-balance    |  kill-all      |
|  SIGCHLD           |  load-balance    |  ignore        |
|  SIGCONT           |  specific        |  continue-all  |
|  SIGSTOP           |  n/a             |  stop-all      |
|  SIGTSTP           |  load-balance    |  stop-all      |
|  SIGTTIN           |  load-balance    |  stop-all      |
|  SIGTTOU           |  load-balance    |  stop-all      |
|  SIGURG            |  load-balance    |  ignore        |
|  SIGXCPU           |  specific        |  kill-all+core |
|  SIGXFSZ           |  specific        |  kill-all+core |
|  SIGVTALRM         |  load-balance    |  kill-all      |
|  SIGPROF           |  specific        |  kill-all      |
|  SIGPOLL/SIGIO     |  load-balance    |  kill-all      |
|  SIGSYS/SIGUNUSED  |  specific        |  kill-all+core |
|  SIGSTKFLT         |  specific        |  kill-all      |
|  SIGWINCH          |  load-balance    |  ignore        |
|  SIGPWR            |  load-balance    |  kill-all      |
|  SIGRTMIN-SIGRTMAX |  load-balance    |  kill-all      |
74 75 76 77 78 79 80 81
----------------------------------------------------------

    non-POSIX signal thread group behavior:

----------------------------------------------------------
|                    |  userspace       |  kernel        |
----------------------------------------------------------
|  SIGEMT            |  specific        |  kill-all+core |
Ingo Molnar's avatar
Ingo Molnar committed
82 83 84
----------------------------------------------------------
*/

85 86 87 88 89 90 91 92 93
/* Some systems do not have a SIGSTKFLT and the kernel never
 * generates such signals anyways.
 */
#ifdef SIGSTKFLT
#define M_SIGSTKFLT	M(SIGSTKFLT)
#else
#define M_SIGSTKFLT	0
#endif

94 95 96 97 98 99
#ifdef SIGEMT
#define M_SIGEMT	M(SIGEMT)
#else
#define M_SIGEMT	0
#endif

100 101 102
#if SIGRTMIN > BITS_PER_LONG
#define M(sig) (1ULL << (sig))
#else
Ingo Molnar's avatar
Ingo Molnar committed
103
#define M(sig) (1UL << (sig))
104 105
#endif
#define T(sig, mask) (M(sig) & mask)
Ingo Molnar's avatar
Ingo Molnar committed
106 107 108 109

#define SIG_USER_SPECIFIC_MASK (\
	M(SIGILL)    |  M(SIGTRAP)   |  M(SIGABRT)   |  M(SIGBUS)    | \
	M(SIGFPE)    |  M(SIGSEGV)   |  M(SIGPIPE)   |  M(SIGXFSZ)   | \
110 111
	M(SIGPROF)   |  M(SIGSYS)    |  M_SIGSTKFLT  |  M(SIGCONT)   | \
        M_SIGEMT )
Ingo Molnar's avatar
Ingo Molnar committed
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

#define SIG_USER_LOAD_BALANCE_MASK (\
        M(SIGHUP)    |  M(SIGINT)    |  M(SIGQUIT)   |  M(SIGUSR1)   | \
        M(SIGUSR2)   |  M(SIGALRM)   |  M(SIGTERM)   |  M(SIGCHLD)   | \
        M(SIGURG)    |  M(SIGVTALRM) |  M(SIGPOLL)   |  M(SIGWINCH)  | \
        M(SIGPWR)    |  M(SIGTSTP)   |  M(SIGTTIN)   |  M(SIGTTOU)   )

#define SIG_KERNEL_SPECIFIC_MASK (\
        M(SIGCHLD)   |   M(SIGURG)   |  M(SIGWINCH)                  )

#define SIG_KERNEL_BROADCAST_MASK (\
	M(SIGHUP)    |  M(SIGINT)    |  M(SIGQUIT)   |  M(SIGILL)    | \
	M(SIGTRAP)   |  M(SIGABRT)   |  M(SIGBUS)    |  M(SIGFPE)    | \
	M(SIGKILL)   |  M(SIGUSR1)   |  M(SIGSEGV)   |  M(SIGUSR2)   | \
	M(SIGPIPE)   |  M(SIGALRM)   |  M(SIGTERM)   |  M(SIGXCPU)   | \
	M(SIGXFSZ)   |  M(SIGVTALRM) |  M(SIGPROF)   |  M(SIGPOLL)   | \
128
	M(SIGSYS)    |  M_SIGSTKFLT  |  M(SIGPWR)    |  M(SIGCONT)   | \
129 130
        M(SIGSTOP)   |  M(SIGTSTP)   |  M(SIGTTIN)   |  M(SIGTTOU)   | \
        M_SIGEMT )
Ingo Molnar's avatar
Ingo Molnar committed
131 132 133 134 135 136 137

#define SIG_KERNEL_ONLY_MASK (\
	M(SIGKILL)   |  M(SIGSTOP)                                   )

#define SIG_KERNEL_COREDUMP_MASK (\
        M(SIGQUIT)   |  M(SIGILL)    |  M(SIGTRAP)   |  M(SIGABRT)   | \
        M(SIGFPE)    |  M(SIGSEGV)   |  M(SIGBUS)    |  M(SIGSYS)    | \
138
        M(SIGXCPU)   |  M(SIGXFSZ)   |  M_SIGEMT                     )
Ingo Molnar's avatar
Ingo Molnar committed
139

140 141
#define sig_user_specific(sig) \
		(((sig) < SIGRTMIN)  && T(sig, SIG_USER_SPECIFIC_MASK))
Ingo Molnar's avatar
Ingo Molnar committed
142
#define sig_user_load_balance(sig) \
143 144 145
		(((sig) >= SIGRTMIN) || T(sig, SIG_USER_LOAD_BALANCE_MASK))
#define sig_kernel_specific(sig) \
		(((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_SPECIFIC_MASK))
Ingo Molnar's avatar
Ingo Molnar committed
146
#define sig_kernel_broadcast(sig) \
147 148 149 150 151
		(((sig) >= SIGRTMIN) || T(sig, SIG_KERNEL_BROADCAST_MASK))
#define sig_kernel_only(sig) \
		(((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_ONLY_MASK))
#define sig_kernel_coredump(sig) \
		(((sig) < SIGRTMIN)  && T(sig, SIG_KERNEL_COREDUMP_MASK))
Ingo Molnar's avatar
Ingo Molnar committed
152 153 154 155 156 157 158 159 160

#define sig_user_defined(t, sig) \
	(((t)->sig->action[(sig)-1].sa.sa_handler != SIG_DFL) &&	\
	 ((t)->sig->action[(sig)-1].sa.sa_handler != SIG_IGN))

#define sig_ignored(t, sig) \
	(((sig) != SIGCHLD) && \
		((t)->sig->action[(sig)-1].sa.sa_handler == SIG_IGN))

Ingo Molnar's avatar
Ingo Molnar committed
161 162
static int
__send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
Linus Torvalds's avatar
Linus Torvalds committed
163

164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
/*
 * Re-calculate pending state from the set of locally pending
 * signals, globally pending signals, and blocked signals.
 */
static inline int has_pending_signals(sigset_t *signal, sigset_t *blocked)
{
	unsigned long ready;
	long i;

	switch (_NSIG_WORDS) {
	default:
		for (i = _NSIG_WORDS, ready = 0; --i >= 0 ;)
			ready |= signal->sig[i] &~ blocked->sig[i];
		break;

	case 4: ready  = signal->sig[3] &~ blocked->sig[3];
		ready |= signal->sig[2] &~ blocked->sig[2];
		ready |= signal->sig[1] &~ blocked->sig[1];
		ready |= signal->sig[0] &~ blocked->sig[0];
		break;

	case 2: ready  = signal->sig[1] &~ blocked->sig[1];
		ready |= signal->sig[0] &~ blocked->sig[0];
		break;

	case 1: ready  = signal->sig[0] &~ blocked->sig[0];
	}
	return ready !=	0;
}

Ingo Molnar's avatar
Ingo Molnar committed
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
#define PENDING(p,b) has_pending_signals(&(p)->signal, (b))

void recalc_sigpending_tsk(struct task_struct *t)
{
	if (PENDING(&t->pending, &t->blocked) ||
			PENDING(&t->sig->shared_pending, &t->blocked))
		set_tsk_thread_flag(t, TIF_SIGPENDING);
	else
		clear_tsk_thread_flag(t, TIF_SIGPENDING);
}

void recalc_sigpending(void)
{
	if (PENDING(&current->pending, &current->blocked) ||
		    PENDING(&current->sig->shared_pending, &current->blocked))
		set_thread_flag(TIF_SIGPENDING);
	else
		clear_thread_flag(TIF_SIGPENDING);
}
Linus Torvalds's avatar
Linus Torvalds committed
213 214 215 216

/* Given the mask, find the first available signal that should be serviced. */

static int
Ingo Molnar's avatar
Ingo Molnar committed
217
next_signal(struct sigpending *pending, sigset_t *mask)
Linus Torvalds's avatar
Linus Torvalds committed
218 219 220 221
{
	unsigned long i, *s, *m, x;
	int sig = 0;
	
Ingo Molnar's avatar
Ingo Molnar committed
222
	s = pending->signal.sig;
Linus Torvalds's avatar
Linus Torvalds committed
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
	m = mask->sig;
	switch (_NSIG_WORDS) {
	default:
		for (i = 0; i < _NSIG_WORDS; ++i, ++s, ++m)
			if ((x = *s &~ *m) != 0) {
				sig = ffz(~x) + i*_NSIG_BPW + 1;
				break;
			}
		break;

	case 2: if ((x = s[0] &~ m[0]) != 0)
			sig = 1;
		else if ((x = s[1] &~ m[1]) != 0)
			sig = _NSIG_BPW + 1;
		else
			break;
		sig += ffz(~x);
		break;

	case 1: if ((x = *s &~ *m) != 0)
			sig = ffz(~x) + 1;
		break;
	}
	
	return sig;
}

static void flush_sigqueue(struct sigpending *queue)
{
	struct sigqueue *q, *n;

	sigemptyset(&queue->signal);
	q = queue->head;
	queue->head = NULL;
	queue->tail = &queue->head;

	while (q) {
		n = q->next;
		kmem_cache_free(sigqueue_cachep, q);
		atomic_dec(&nr_queued_signals);
		q = n;
	}
}

/*
 * Flush all pending signals for a task.
 */

void
flush_signals(struct task_struct *t)
{
274
	clear_tsk_thread_flag(t,TIF_SIGPENDING);
Linus Torvalds's avatar
Linus Torvalds committed
275 276 277
	flush_sigqueue(&t->pending);
}

278 279 280 281
/*
 * This function expects the tasklist_lock write-locked.
 */
void __exit_sighand(struct task_struct *tsk)
Linus Torvalds's avatar
Linus Torvalds committed
282 283 284
{
	struct signal_struct * sig = tsk->sig;

Ingo Molnar's avatar
Ingo Molnar committed
285 286 287 288
	if (!sig)
		BUG();
	if (!atomic_read(&sig->count))
		BUG();
289 290
	spin_lock(&sig->siglock);
	if (atomic_dec_and_test(&sig->count)) {
Ingo Molnar's avatar
Ingo Molnar committed
291 292
		if (tsk == sig->curr_target)
			sig->curr_target = next_thread(tsk);
293
		tsk->sig = NULL;
294 295 296 297
		spin_unlock(&sig->siglock);
		flush_sigqueue(&sig->shared_pending);
		kmem_cache_free(sigact_cachep, sig);
	} else {
298 299 300 301 302 303 304 305
		/*
		 * If there is any task waiting for the group exit
		 * then notify it:
		 */
		if (sig->group_exit_task && atomic_read(&sig->count) <= 2) {
			wake_up_process(sig->group_exit_task);
			sig->group_exit_task = NULL;
		}
Ingo Molnar's avatar
Ingo Molnar committed
306 307
		if (tsk == sig->curr_target)
			sig->curr_target = next_thread(tsk);
308 309
		tsk->sig = NULL;
		spin_unlock(&sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
310
	}
311
	clear_tsk_thread_flag(tsk,TIF_SIGPENDING);
Linus Torvalds's avatar
Linus Torvalds committed
312
	flush_sigqueue(&tsk->pending);
313 314 315 316 317 318 319
}

void exit_sighand(struct task_struct *tsk)
{
	write_lock_irq(&tasklist_lock);
	__exit_sighand(tsk);
	write_unlock_irq(&tasklist_lock);
Linus Torvalds's avatar
Linus Torvalds committed
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
}

/*
 * Flush all handlers for a task.
 */

void
flush_signal_handlers(struct task_struct *t)
{
	int i;
	struct k_sigaction *ka = &t->sig->action[0];
	for (i = _NSIG ; i != 0 ; i--) {
		if (ka->sa.sa_handler != SIG_IGN)
			ka->sa.sa_handler = SIG_DFL;
		ka->sa.sa_flags = 0;
		sigemptyset(&ka->sa.sa_mask);
		ka++;
	}
}

340 341 342 343 344 345 346 347
/*
 * sig_exit - cause the current task to exit due to a signal.
 */

void
sig_exit(int sig, int exit_code, struct siginfo *info)
{
	sigaddset(&current->pending.signal, sig);
348
	recalc_sigpending();
349 350
	current->flags |= PF_SIGNALED;

351 352 353
	if (current->sig->group_exit)
		exit_code = current->sig->group_exit_code;

354 355 356 357
	do_exit(exit_code);
	/* NOTREACHED */
}

Linus Torvalds's avatar
Linus Torvalds committed
358 359 360 361 362 363 364 365 366 367 368 369 370
/* 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.  */

void
block_all_signals(int (*notifier)(void *priv), void *priv, sigset_t *mask)
{
	unsigned long flags;

Ingo Molnar's avatar
Ingo Molnar committed
371
	spin_lock_irqsave(&current->sig->siglock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
372 373 374
	current->notifier_mask = mask;
	current->notifier_data = priv;
	current->notifier = notifier;
Ingo Molnar's avatar
Ingo Molnar committed
375
	spin_unlock_irqrestore(&current->sig->siglock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
376 377 378 379 380 381 382 383 384
}

/* Notify the system that blocking has ended. */

void
unblock_all_signals(void)
{
	unsigned long flags;

Ingo Molnar's avatar
Ingo Molnar committed
385
	spin_lock_irqsave(&current->sig->siglock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
386 387
	current->notifier = NULL;
	current->notifier_data = NULL;
388
	recalc_sigpending();
Ingo Molnar's avatar
Ingo Molnar committed
389
	spin_unlock_irqrestore(&current->sig->siglock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
390 391
}

Ingo Molnar's avatar
Ingo Molnar committed
392
static inline int collect_signal(int sig, struct sigpending *list, siginfo_t *info)
Linus Torvalds's avatar
Linus Torvalds committed
393 394 395 396 397 398 399 400 401 402 403
{
	if (sigismember(&list->signal, sig)) {
		/* Collect the siginfo appropriate to this signal.  */
		struct sigqueue *q, **pp;
		pp = &list->head;
		while ((q = *pp) != NULL) {
			if (q->info.si_signo == sig)
				goto found_it;
			pp = &q->next;
		}

Ingo Molnar's avatar
Ingo Molnar committed
404 405 406 407
		/* 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.
		 */
Linus Torvalds's avatar
Linus Torvalds committed
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
		sigdelset(&list->signal, sig);
		info->si_signo = sig;
		info->si_errno = 0;
		info->si_code = 0;
		info->si_pid = 0;
		info->si_uid = 0;
		return 1;

found_it:
		if ((*pp = q->next) == NULL)
			list->tail = pp;

		/* Copy the sigqueue information and free the queue entry */
		copy_siginfo(info, &q->info);
		kmem_cache_free(sigqueue_cachep,q);
		atomic_dec(&nr_queued_signals);

		/* Non-RT signals can exist multiple times.. */
		if (sig >= SIGRTMIN) {
			while ((q = *pp) != NULL) {
				if (q->info.si_signo == sig)
					goto found_another;
				pp = &q->next;
			}
		}

		sigdelset(&list->signal, sig);
found_another:
		return 1;
	}
	return 0;
}

Ingo Molnar's avatar
Ingo Molnar committed
441 442
static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
			siginfo_t *info)
Linus Torvalds's avatar
Linus Torvalds committed
443 444 445
{
	int sig = 0;

Ingo Molnar's avatar
Ingo Molnar committed
446
	sig = next_signal(pending, mask);
Linus Torvalds's avatar
Linus Torvalds committed
447 448 449 450
	if (sig) {
		if (current->notifier) {
			if (sigismember(current->notifier_mask, sig)) {
				if (!(current->notifier)(current->notifier_data)) {
451
					clear_thread_flag(TIF_SIGPENDING);
Linus Torvalds's avatar
Linus Torvalds committed
452 453
					return 0;
				}
Linus Torvalds's avatar
Linus Torvalds committed
454 455 456
			}
		}

Ingo Molnar's avatar
Ingo Molnar committed
457
		if (!collect_signal(sig, pending, info))
Linus Torvalds's avatar
Linus Torvalds committed
458 459 460 461 462
			sig = 0;
				
		/* XXX: Once POSIX.1b timers are in, if si_code == SI_TIMER,
		   we need to xchg out the timer overrun values.  */
	}
463
	recalc_sigpending();
Linus Torvalds's avatar
Linus Torvalds committed
464 465 466 467

	return sig;
}

Ingo Molnar's avatar
Ingo Molnar committed
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
/*
 * Dequeue a signal and return the element to the caller, which is 
 * expected to free it.
 *
 * All callers have to hold the siglock.
 */
int dequeue_signal(sigset_t *mask, siginfo_t *info)
{
	/*
	 * Here we handle shared pending signals. To implement the full
	 * semantics we need to unqueue and resend them. It will likely
	 * get into our own pending queue.
	 */
	if (current->sig->shared_pending.head) {
		int signr = __dequeue_signal(&current->sig->shared_pending, mask, info);
		if (signr)
			__send_sig_info(signr, info, current);
	}
	return __dequeue_signal(&current->pending, mask, info);
}

Linus Torvalds's avatar
Linus Torvalds committed
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516
static int rm_from_queue(int sig, struct sigpending *s)
{
	struct sigqueue *q, **pp;

	if (!sigismember(&s->signal, sig))
		return 0;

	sigdelset(&s->signal, sig);

	pp = &s->head;

	while ((q = *pp) != NULL) {
		if (q->info.si_signo == sig) {
			if ((*pp = q->next) == NULL)
				s->tail = pp;
			kmem_cache_free(sigqueue_cachep,q);
			atomic_dec(&nr_queued_signals);
			continue;
		}
		pp = &q->next;
	}
	return 1;
}

/*
 * Remove signal sig from t->pending.
 * Returns 1 if sig was found.
 *
Ingo Molnar's avatar
Ingo Molnar committed
517
 * All callers must be holding the siglock.
Linus Torvalds's avatar
Linus Torvalds committed
518 519 520 521 522 523 524 525 526
 */
static int rm_sig_from_queue(int sig, struct task_struct *t)
{
	return rm_from_queue(sig, &t->pending);
}

/*
 * Bad permissions for sending the signal
 */
Ingo Molnar's avatar
Ingo Molnar committed
527
static inline int bad_signal(int sig, struct siginfo *info, struct task_struct *t)
Linus Torvalds's avatar
Linus Torvalds committed
528
{
Ingo Molnar's avatar
Ingo Molnar committed
529 530
	return (!info || ((unsigned long)info != 1 &&
			(unsigned long)info != 2 && SI_FROMUSER(info)))
Linus Torvalds's avatar
Linus Torvalds committed
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
	    && ((sig != SIGCONT) || (current->session != t->session))
	    && (current->euid ^ t->suid) && (current->euid ^ t->uid)
	    && (current->uid ^ t->suid) && (current->uid ^ t->uid)
	    && !capable(CAP_KILL);
}

/*
 * Signal type:
 *    < 0 : global action (kill - spread to all non-blocked threads)
 *    = 0 : ignored
 *    > 0 : wake up.
 */
static int signal_type(int sig, struct signal_struct *signals)
{
	unsigned long handler;

	if (!signals)
		return 0;
	
	handler = (unsigned long) signals->action[sig-1].sa.sa_handler;
	if (handler > 1)
		return 1;

	/* "Ignore" handler.. Illogical, but that has an implicit handler for SIGCHLD */
	if (handler == 1)
		return sig == SIGCHLD;

	/* Default handler. Normally lethal, but.. */
	switch (sig) {

	/* Ignored */
	case SIGCONT: case SIGWINCH:
	case SIGCHLD: case SIGURG:
		return 0;

	/* Implicit behaviour */
	case SIGTSTP: case SIGTTIN: case SIGTTOU:
		return 1;

	/* Implicit actions (kill or do special stuff) */
	default:
		return -1;
	}
}
		

/*
 * Determine whether a signal should be posted or not.
 *
 * Signals with SIG_IGN can be ignored, except for the
 * special case of a SIGCHLD. 
 *
 * Some signals with SIG_DFL default to a non-action.
 */
static int ignored_signal(int sig, struct task_struct *t)
{
	/* Don't ignore traced or blocked signals */
	if ((t->ptrace & PT_PTRACED) || sigismember(&t->blocked, sig))
		return 0;

	return signal_type(sig, t->sig) == 0;
}

/*
 * Handle TASK_STOPPED cases etc implicit behaviour
 * of certain magical signals.
 *
 * SIGKILL gets spread out to every thread. 
 */
static void handle_stop_signal(int sig, struct task_struct *t)
{
	switch (sig) {
	case SIGKILL: case SIGCONT:
		/* Wake up the process if stopped.  */
		if (t->state == TASK_STOPPED)
			wake_up_process(t);
		t->exit_code = 0;
		rm_sig_from_queue(SIGSTOP, t);
		rm_sig_from_queue(SIGTSTP, t);
		rm_sig_from_queue(SIGTTOU, t);
		rm_sig_from_queue(SIGTTIN, t);
		break;

	case SIGSTOP: case SIGTSTP:
	case SIGTTIN: case SIGTTOU:
		/* If we're stopping again, cancel SIGCONT */
		rm_sig_from_queue(SIGCONT, t);
		break;
	}
}

static int send_signal(int sig, struct siginfo *info, struct sigpending *signals)
{
	struct sigqueue * q = NULL;

Ingo Molnar's avatar
Ingo Molnar committed
626 627 628 629 630 631 632
	/*
	 * fast-pathed signals for kernel-internal things like SIGSTOP
	 * or SIGKILL.
	 */
	if ((unsigned long)info == 2)
		goto out_set;

Linus Torvalds's avatar
Linus Torvalds committed
633 634 635 636 637 638 639 640
	/* 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.  */

Ingo Molnar's avatar
Ingo Molnar committed
641
	if (atomic_read(&nr_queued_signals) < max_queued_signals)
Linus Torvalds's avatar
Linus Torvalds committed
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668
		q = kmem_cache_alloc(sigqueue_cachep, GFP_ATOMIC);

	if (q) {
		atomic_inc(&nr_queued_signals);
		q->next = NULL;
		*signals->tail = q;
		signals->tail = &q->next;
		switch ((unsigned long) info) {
			case 0:
				q->info.si_signo = sig;
				q->info.si_errno = 0;
				q->info.si_code = SI_USER;
				q->info.si_pid = current->pid;
				q->info.si_uid = current->uid;
				break;
			case 1:
				q->info.si_signo = sig;
				q->info.si_errno = 0;
				q->info.si_code = SI_KERNEL;
				q->info.si_pid = 0;
				q->info.si_uid = 0;
				break;
			default:
				copy_siginfo(&q->info, info);
				break;
		}
	} else if (sig >= SIGRTMIN && info && (unsigned long)info != 1
Ingo Molnar's avatar
Ingo Molnar committed
669
		   && info->si_code != SI_USER)
Linus Torvalds's avatar
Linus Torvalds committed
670 671 672 673 674 675
		/*
		 * Queue overflow, abort.  We may abort if the signal was rt
		 * and sent by user using something other than kill().
		 */
		return -EAGAIN;

Ingo Molnar's avatar
Ingo Molnar committed
676
out_set:
Linus Torvalds's avatar
Linus Torvalds committed
677 678 679 680 681 682 683 684 685
	sigaddset(&signals->signal, sig);
	return 0;
}

/*
 * Tell a process that it has a new active signal..
 *
 * NOTE! we rely on the previous spin_lock to
 * lock interrupts for us! We can only be called with
Ingo Molnar's avatar
Ingo Molnar committed
686
 * "siglock" held, and the local interrupt must
Linus Torvalds's avatar
Linus Torvalds committed
687 688 689 690 691
 * have been disabled when that got acquired!
 *
 * No need to set need_resched since signal event passing
 * goes through ->blocked
 */
Pavel Machek's avatar
Pavel Machek committed
692
inline void signal_wake_up(struct task_struct *t)
Linus Torvalds's avatar
Linus Torvalds committed
693
{
694
	set_tsk_thread_flag(t,TIF_SIGPENDING);
Linus Torvalds's avatar
Linus Torvalds committed
695 696 697 698 699 700 701 702 703 704 705

	/*
	 * If the task is running on a different CPU 
	 * force a reschedule on the other CPU to make
	 * it notice the new signal quickly.
	 *
	 * The code below is a tad loose and might occasionally
	 * kick the wrong CPU if we catch the process in the
	 * process of changing - but no harm is done by that
	 * other than doing an extra (lightweight) IPI interrupt.
	 */
Ingo Molnar's avatar
Ingo Molnar committed
706
	if (t->state == TASK_RUNNING)
Linus Torvalds's avatar
Linus Torvalds committed
707
		kick_if_running(t);
Linus Torvalds's avatar
Linus Torvalds committed
708 709 710 711
	if (t->state & TASK_INTERRUPTIBLE) {
		wake_up_process(t);
		return;
	}
Linus Torvalds's avatar
Linus Torvalds committed
712 713 714 715 716 717 718 719 720 721 722 723
}

static int deliver_signal(int sig, struct siginfo *info, struct task_struct *t)
{
	int retval = send_signal(sig, info, &t->pending);

	if (!retval && !sigismember(&t->blocked, sig))
		signal_wake_up(t);

	return retval;
}

Ingo Molnar's avatar
Ingo Molnar committed
724
static int
Ingo Molnar's avatar
Ingo Molnar committed
725
specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t, int shared)
Linus Torvalds's avatar
Linus Torvalds committed
726 727 728
{
	int ret;

Ingo Molnar's avatar
Ingo Molnar committed
729 730 731 732 733
	if (!irqs_disabled())
		BUG();
#if CONFIG_SMP
	if (!spin_is_locked(&t->sig->siglock))
		BUG();
Linus Torvalds's avatar
Linus Torvalds committed
734 735 736
#endif
	ret = -EINVAL;
	if (sig < 0 || sig > _NSIG)
Ingo Molnar's avatar
Ingo Molnar committed
737
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
738 739 740
	/* The somewhat baroque permissions check... */
	ret = -EPERM;
	if (bad_signal(sig, info, t))
Ingo Molnar's avatar
Ingo Molnar committed
741
		goto out;
742 743
	ret = security_task_kill(t, info, sig);
	if (ret)
Ingo Molnar's avatar
Ingo Molnar committed
744
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
745

746
	/* The null signal is a permissions and process existence probe.
Linus Torvalds's avatar
Linus Torvalds committed
747 748 749
	   No signal is actually delivered.  Same goes for zombies. */
	ret = 0;
	if (!sig || !t->sig)
Ingo Molnar's avatar
Ingo Molnar committed
750
		goto out;
Linus Torvalds's avatar
Linus Torvalds committed
751 752 753 754 755 756 757 758 759 760

	handle_stop_signal(sig, t);

	/* Optimize away the signal, if it's a signal that can be
	   handled immediately (ie non-blocked and untraced) and
	   that is ignored (either explicitly or by default).  */

	if (ignored_signal(sig, t))
		goto out;

Ingo Molnar's avatar
Ingo Molnar committed
761 762 763 764 765 766 767 768 769
#define LEGACY_QUEUE(sigptr, sig) \
	(((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig)))

	if (!shared) {
		/* Support queueing exactly one non-rt signal, so that we
		   can get more detailed information about the cause of
		   the signal. */
		if (LEGACY_QUEUE(&t->pending, sig))
			goto out;
Linus Torvalds's avatar
Linus Torvalds committed
770

Ingo Molnar's avatar
Ingo Molnar committed
771 772 773 774 775 776
		ret = deliver_signal(sig, info, t);
	} else {
		if (LEGACY_QUEUE(&t->sig->shared_pending, sig))
			goto out;
		ret = send_signal(sig, info, &t->sig->shared_pending);
	}
Linus Torvalds's avatar
Linus Torvalds committed
777 778 779 780 781 782 783 784 785 786 787 788 789
out:
	return ret;
}

/*
 * Force a signal that the process can't ignore: if necessary
 * we unblock the signal and change any SIG_IGN to SIG_DFL.
 */

int
force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
{
	unsigned long int flags;
Ingo Molnar's avatar
Ingo Molnar committed
790
	int ret;
Linus Torvalds's avatar
Linus Torvalds committed
791

Ingo Molnar's avatar
Ingo Molnar committed
792
	spin_lock_irqsave(&t->sig->siglock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
793 794 795
	if (t->sig->action[sig-1].sa.sa_handler == SIG_IGN)
		t->sig->action[sig-1].sa.sa_handler = SIG_DFL;
	sigdelset(&t->blocked, sig);
796
	recalc_sigpending_tsk(t);
Ingo Molnar's avatar
Ingo Molnar committed
797 798
	ret = __send_sig_info(sig, info, t);
	spin_unlock_irqrestore(&t->sig->siglock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
799

Ingo Molnar's avatar
Ingo Molnar committed
800
	return ret;
Ingo Molnar's avatar
Ingo Molnar committed
801 802 803
}

static int
804
__specific_force_sig_info(int sig, struct task_struct *t)
Ingo Molnar's avatar
Ingo Molnar committed
805
{
Ingo Molnar's avatar
Ingo Molnar committed
806
	if (!t->sig)
Ingo Molnar's avatar
Ingo Molnar committed
807 808 809 810 811 812 813
		return -ESRCH;

	if (t->sig->action[sig-1].sa.sa_handler == SIG_IGN)
		t->sig->action[sig-1].sa.sa_handler = SIG_DFL;
	sigdelset(&t->blocked, sig);
	recalc_sigpending_tsk(t);

Ingo Molnar's avatar
Ingo Molnar committed
814
	return specific_send_sig_info(sig, (void *)2, t, 0);
Ingo Molnar's avatar
Ingo Molnar committed
815 816
}

817 818 819 820 821 822 823 824 825 826 827 828 829 830
void
force_sig_specific(int sig, struct task_struct *t)
{
	unsigned long int flags;

	spin_lock_irqsave(&t->sig->siglock, flags);
	if (t->sig->action[sig-1].sa.sa_handler == SIG_IGN)
		t->sig->action[sig-1].sa.sa_handler = SIG_DFL;
	sigdelset(&t->blocked, sig);
	recalc_sigpending_tsk(t);
	specific_send_sig_info(sig, (void *)2, t, 0);
	spin_unlock_irqrestore(&t->sig->siglock, flags);
}

Ingo Molnar's avatar
Ingo Molnar committed
831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
#define can_take_signal(p, sig)	\
	(((unsigned long) p->sig->action[sig-1].sa.sa_handler > 1) && \
	!sigismember(&p->blocked, sig) && (task_curr(p) || !signal_pending(p)))

static inline
int load_balance_thread_group(struct task_struct *p, int sig,
				struct siginfo *info)
{
	struct task_struct *tmp;
	int ret;

	/*
	 * if the specified thread is not blocking this signal
	 * then deliver it.
	 */
	if (can_take_signal(p, sig))
Ingo Molnar's avatar
Ingo Molnar committed
847
		return specific_send_sig_info(sig, info, p, 0);
Ingo Molnar's avatar
Ingo Molnar committed
848 849 850 851 852 853 854 855 856 857 858 859 860 861

	/*
	 * Otherwise try to find a suitable thread.
	 * If no such thread is found then deliver to
	 * the original thread.
	 */

	tmp = p->sig->curr_target;

	if (!tmp || tmp->tgid != p->tgid)
		/* restart balancing at this thread */
		p->sig->curr_target = p;

	else for (;;) {
862
		if (thread_group_empty(p))
Ingo Molnar's avatar
Ingo Molnar committed
863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
			BUG();
		if (!tmp || tmp->tgid != p->tgid)
			BUG();

		/*
		 * Do not send signals that are ignored or blocked,
		 * or to not-running threads that are overworked:
		 */
		if (!can_take_signal(tmp, sig)) {
			tmp = next_thread(tmp);
			p->sig->curr_target = tmp;
			if (tmp == p)
				break;
			continue;
		}
Ingo Molnar's avatar
Ingo Molnar committed
878
		ret = specific_send_sig_info(sig, info, tmp, 0);
Ingo Molnar's avatar
Ingo Molnar committed
879 880 881 882 883 884
		return ret;
	}
	/*
	 * No suitable thread was found - put the signal
	 * into the shared-pending queue.
	 */
Ingo Molnar's avatar
Ingo Molnar committed
885
	return specific_send_sig_info(sig, info, p, 1);
Ingo Molnar's avatar
Ingo Molnar committed
886 887 888 889 890
}

int __broadcast_thread_group(struct task_struct *p, int sig)
{
	struct task_struct *tmp;
891 892
	struct list_head *l;
	struct pid *pid;
Ingo Molnar's avatar
Ingo Molnar committed
893 894
	int err = 0;

895
	for_each_task_pid(p->tgid, PIDTYPE_TGID, tmp, l, pid)
896
		err = __specific_force_sig_info(sig, tmp);
897

Ingo Molnar's avatar
Ingo Molnar committed
898 899 900
	return err;
}

901 902 903 904 905 906 907
struct task_struct * find_unblocked_thread(struct task_struct *p, int signr)
{
	struct task_struct *tmp;
	struct list_head *l;
	struct pid *pid;

	for_each_task_pid(p->tgid, PIDTYPE_TGID, tmp, l, pid)
Ingo Molnar's avatar
Ingo Molnar committed
908
		if (!sigismember(&tmp->blocked, signr))
909 910 911 912
			return tmp;
	return NULL;
}

Ingo Molnar's avatar
Ingo Molnar committed
913 914
static int
__send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
Ingo Molnar's avatar
Ingo Molnar committed
915
{
916
	struct task_struct *t;
Ingo Molnar's avatar
Ingo Molnar committed
917 918
	int ret = 0;

Ingo Molnar's avatar
Ingo Molnar committed
919 920
#if CONFIG_SMP
	if (!spin_is_locked(&p->sig->siglock))
Ingo Molnar's avatar
Ingo Molnar committed
921
		BUG();
Ingo Molnar's avatar
Ingo Molnar committed
922
#endif
Ingo Molnar's avatar
Ingo Molnar committed
923
	/* not a thread group - normal signal behavior */
924
	if (thread_group_empty(p) || !sig)
Ingo Molnar's avatar
Ingo Molnar committed
925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941
		goto out_send;

	if (sig_user_defined(p, sig)) {
		if (sig_user_specific(sig))
			goto out_send;
		if (sig_user_load_balance(sig)) {
			ret = load_balance_thread_group(p, sig, info);
			goto out_unlock;
		}

		/* must not happen */
		BUG();
	}
	/* optimize away ignored signals: */
	if (sig_ignored(p, sig))
		goto out_unlock;

942
	if (sig_kernel_specific(sig))
Ingo Molnar's avatar
Ingo Molnar committed
943 944
		goto out_send;

945 946 947
	/* Does any of the threads unblock the signal? */
	t = find_unblocked_thread(p, sig);
	if (!t) {
Ingo Molnar's avatar
Ingo Molnar committed
948
		ret = specific_send_sig_info(sig, info, p, 1);
949 950
		goto out_unlock;
	}
Ingo Molnar's avatar
Ingo Molnar committed
951 952 953 954
	if (sigismember(&t->real_blocked,sig)) {
		ret = specific_send_sig_info(sig, info, t, 0);
		goto out_unlock;
	}
Ingo Molnar's avatar
Ingo Molnar committed
955 956 957 958 959 960 961 962
	if (sig_kernel_broadcast(sig) || sig_kernel_coredump(sig)) {
		ret = __broadcast_thread_group(p, sig);
		goto out_unlock;
	}

	/* must not happen */
	BUG();
out_send:
Ingo Molnar's avatar
Ingo Molnar committed
963
	ret = specific_send_sig_info(sig, info, p, 0);
Ingo Molnar's avatar
Ingo Molnar committed
964
out_unlock:
Ingo Molnar's avatar
Ingo Molnar committed
965 966 967 968 969 970 971 972 973 974 975
	return ret;
}

int
send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
{
	unsigned long flags;
	int ret;

	spin_lock_irqsave(&p->sig->siglock, flags);
	ret = __send_sig_info(sig, info, p);
Ingo Molnar's avatar
Ingo Molnar committed
976
	spin_unlock_irqrestore(&p->sig->siglock, flags);
Ingo Molnar's avatar
Ingo Molnar committed
977

Ingo Molnar's avatar
Ingo Molnar committed
978
	return ret;
Linus Torvalds's avatar
Linus Torvalds committed
979 980 981 982 983 984 985
}

/*
 * kill_pg_info() sends a signal to a process group: this is what the tty
 * control characters do (^C, ^Z etc)
 */

986
int __kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
Linus Torvalds's avatar
Linus Torvalds committed
987
{
988 989 990 991 992 993 994 995 996 997 998 999
	struct task_struct *p;
	struct list_head *l;
	struct pid *pid;
	int err, retval = -ESRCH;

	if (pgrp <= 0)
		return -EINVAL;

	for_each_task_pid(pgrp, PIDTYPE_PGID, p, l, pid) {
		err = send_sig_info(sig, info, p);
		if (retval)
			retval = err;
Linus Torvalds's avatar
Linus Torvalds committed
1000 1001 1002 1003
	}
	return retval;
}

1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
int
kill_pg_info(int sig, struct siginfo *info, pid_t pgrp)
{
	int retval;

	read_lock(&tasklist_lock);
	retval = __kill_pg_info(sig, info, pgrp);
	read_unlock(&tasklist_lock);

	return retval;
}

Linus Torvalds's avatar
Linus Torvalds committed
1016 1017 1018 1019 1020 1021
/*
 * kill_sl_info() sends a signal to the session leader: this is used
 * to send SIGHUP to the controlling process of a terminal when
 * the connection is lost.
 */

1022

Linus Torvalds's avatar
Linus Torvalds committed
1023
int
1024
kill_sl_info(int sig, struct siginfo *info, pid_t sid)
Linus Torvalds's avatar
Linus Torvalds committed
1025
{
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
	int err, retval = -EINVAL;
	struct pid *pid;
	struct list_head *l;
	struct task_struct *p;

	if (sid <= 0)
		goto out;

	retval = -ESRCH;
	read_lock(&tasklist_lock);
	for_each_task_pid(sid, PIDTYPE_SID, p, l, pid) {
		if (!p->leader)
			continue;
		err = send_sig_info(sig, info, p);
		if (retval)
			retval = err;
Linus Torvalds's avatar
Linus Torvalds committed
1042
	}
1043 1044
	read_unlock(&tasklist_lock);
out:
Linus Torvalds's avatar
Linus Torvalds committed
1045 1046 1047
	return retval;
}

1048
int
Linus Torvalds's avatar
Linus Torvalds committed
1049 1050 1051 1052 1053 1054 1055 1056
kill_proc_info(int sig, struct siginfo *info, pid_t pid)
{
	int error;
	struct task_struct *p;

	read_lock(&tasklist_lock);
	p = find_task_by_pid(pid);
	error = -ESRCH;
Ingo Molnar's avatar
Ingo Molnar committed
1057
	if (p)
Linus Torvalds's avatar
Linus Torvalds committed
1058 1059 1060 1061 1062 1063 1064 1065 1066
		error = send_sig_info(sig, info, p);
	read_unlock(&tasklist_lock);
	return error;
}


/*
 * kill_something_info() interprets pid in interesting ways just like kill(2).
 *
Linus Torvalds's avatar
Linus Torvalds committed
1067 1068
 * POSIX specifies that kill(-1,sig) is unspecified, but what we have
 * is probably wrong.  Should make it like BSD or SYSV.
Linus Torvalds's avatar
Linus Torvalds committed
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
 */

static int kill_something_info(int sig, struct siginfo *info, int pid)
{
	if (!pid) {
		return kill_pg_info(sig, info, current->pgrp);
	} else if (pid == -1) {
		int retval = 0, count = 0;
		struct task_struct * p;

		read_lock(&tasklist_lock);
Ingo Molnar's avatar
Ingo Molnar committed
1080 1081
		for_each_process(p) {
			if (p->pid > 1 && p != current) {
Linus Torvalds's avatar
Linus Torvalds committed
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134
				int err = send_sig_info(sig, info, p);
				++count;
				if (err != -EPERM)
					retval = err;
			}
		}
		read_unlock(&tasklist_lock);
		return count ? retval : -ESRCH;
	} else if (pid < 0) {
		return kill_pg_info(sig, info, -pid);
	} else {
		return kill_proc_info(sig, info, pid);
	}
}

/*
 * These are for backward compatibility with the rest of the kernel source.
 */

int
send_sig(int sig, struct task_struct *p, int priv)
{
	return send_sig_info(sig, (void*)(long)(priv != 0), p);
}

void
force_sig(int sig, struct task_struct *p)
{
	force_sig_info(sig, (void*)1L, p);
}

int
kill_pg(pid_t pgrp, int sig, int priv)
{
	return kill_pg_info(sig, (void *)(long)(priv != 0), pgrp);
}

int
kill_sl(pid_t sess, int sig, int priv)
{
	return kill_sl_info(sig, (void *)(long)(priv != 0), sess);
}

int
kill_proc(pid_t pid, int sig, int priv)
{
	return kill_proc_info(sig, (void *)(long)(priv != 0), pid);
}

/*
 * Joy. Or not. Pthread wants us to wake up every thread
 * in our parent group.
 */
Ingo Molnar's avatar
Ingo Molnar committed
1135
static inline void __wake_up_parent(struct task_struct *p)
Linus Torvalds's avatar
Linus Torvalds committed
1136
{
Ingo Molnar's avatar
Ingo Molnar committed
1137
	struct task_struct *parent = p->parent, *tsk = parent;
Linus Torvalds's avatar
Linus Torvalds committed
1138

Ingo Molnar's avatar
Ingo Molnar committed
1139 1140 1141 1142 1143 1144 1145
	/*
	 * Fortunately this is not necessary for thread groups:
	 */
	if (p->tgid == tsk->tgid) {
		wake_up_interruptible(&tsk->wait_chldexit);
		return;
	}
Ingo Molnar's avatar
Ingo Molnar committed
1146

Linus Torvalds's avatar
Linus Torvalds committed
1147 1148 1149
	do {
		wake_up_interruptible(&tsk->wait_chldexit);
		tsk = next_thread(tsk);
Ingo Molnar's avatar
Ingo Molnar committed
1150 1151
		if (tsk->sig != parent->sig)
			BUG();
Linus Torvalds's avatar
Linus Torvalds committed
1152 1153 1154 1155 1156 1157
	} while (tsk != parent);
}

/*
 * Let a parent know about a status change of a child.
 */
Ingo Molnar's avatar
Ingo Molnar committed
1158

Linus Torvalds's avatar
Linus Torvalds committed
1159 1160 1161
void do_notify_parent(struct task_struct *tsk, int sig)
{
	struct siginfo info;
Ingo Molnar's avatar
Ingo Molnar committed
1162
	unsigned long flags;
Linus Torvalds's avatar
Linus Torvalds committed
1163 1164
	int why, status;

1165
	if (sig == -1)
1166 1167
		BUG();

Linus Torvalds's avatar
Linus Torvalds committed
1168 1169 1170 1171 1172 1173
	info.si_signo = sig;
	info.si_errno = 0;
	info.si_pid = tsk->pid;
	info.si_uid = tsk->uid;

	/* FIXME: find out whether or not this is supposed to be c*time. */
1174 1175
	info.si_utime = tsk->utime;
	info.si_stime = tsk->stime;
Linus Torvalds's avatar
Linus Torvalds committed
1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201

	status = tsk->exit_code & 0x7f;
	why = SI_KERNEL;	/* shouldn't happen */
	switch (tsk->state) {
	case TASK_STOPPED:
		/* FIXME -- can we deduce CLD_TRAPPED or CLD_CONTINUED? */
		if (tsk->ptrace & PT_PTRACED)
			why = CLD_TRAPPED;
		else
			why = CLD_STOPPED;
		break;

	default:
		if (tsk->exit_code & 0x80)
			why = CLD_DUMPED;
		else if (tsk->exit_code & 0x7f)
			why = CLD_KILLED;
		else {
			why = CLD_EXITED;
			status = tsk->exit_code >> 8;
		}
		break;
	}
	info.si_code = why;
	info.si_status = status;

Ingo Molnar's avatar
Ingo Molnar committed
1202 1203 1204 1205
	spin_lock_irqsave(&tsk->parent->sig->siglock, flags);
	__send_sig_info(sig, &info, tsk->parent);
	__wake_up_parent(tsk);
	spin_unlock_irqrestore(&tsk->parent->sig->siglock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
}


/*
 * We need the tasklist lock because it's the only
 * thing that protects out "parent" pointer.
 *
 * exit.c calls "do_notify_parent()" directly, because
 * it already has the tasklist lock.
 */
void
notify_parent(struct task_struct *tsk, int sig)
{
1219 1220 1221 1222 1223
	if (sig != -1) {
		read_lock(&tasklist_lock);
		do_notify_parent(tsk, sig);
		read_unlock(&tasklist_lock);
	}
Linus Torvalds's avatar
Linus Torvalds committed
1224 1225
}

1226 1227 1228 1229
#ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER

int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs)
{
Ingo Molnar's avatar
Ingo Molnar committed
1230 1231
	sigset_t *mask = &current->blocked;

1232
	for (;;) {
Ingo Molnar's avatar
Ingo Molnar committed
1233
		unsigned long signr = 0;
1234 1235
		struct k_sigaction *ka;

Ingo Molnar's avatar
Ingo Molnar committed
1236
		spin_lock_irq(&current->sig->siglock);
Ingo Molnar's avatar
Ingo Molnar committed
1237
		signr = dequeue_signal(mask, info);
Ingo Molnar's avatar
Ingo Molnar committed
1238
		spin_unlock_irq(&current->sig->siglock);
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331

		if (!signr)
			break;

		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
			/* Let the debugger run.  */
			current->exit_code = signr;
			set_current_state(TASK_STOPPED);
			notify_parent(current, SIGCHLD);
			schedule();

			/* We're back.  Did the debugger cancel the sig?  */
			signr = current->exit_code;
			if (signr == 0)
				continue;
			current->exit_code = 0;

			/* The debugger continued.  Ignore SIGSTOP.  */
			if (signr == SIGSTOP)
				continue;

			/* Update the siginfo structure.  Is this good?  */
			if (signr != info->si_signo) {
				info->si_signo = signr;
				info->si_errno = 0;
				info->si_code = SI_USER;
				info->si_pid = current->parent->pid;
				info->si_uid = current->parent->uid;
			}

			/* If the (new) signal is now blocked, requeue it.  */
			if (sigismember(&current->blocked, signr)) {
				send_sig_info(signr, info, current);
				continue;
			}
		}

		ka = &current->sig->action[signr-1];
		if (ka->sa.sa_handler == SIG_IGN) {
			if (signr != SIGCHLD)
				continue;
			/* Check for SIGCHLD: it's special.  */
			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
				/* nothing */;
			continue;
		}

		if (ka->sa.sa_handler == SIG_DFL) {
			int exit_code = signr;

			/* Init gets no signals it doesn't want.  */
			if (current->pid == 1)
				continue;

			switch (signr) {
			case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
				continue;

			case SIGTSTP: case SIGTTIN: case SIGTTOU:
				if (is_orphaned_pgrp(current->pgrp))
					continue;
				/* FALLTHRU */

			case SIGSTOP: {
				struct signal_struct *sig;
				set_current_state(TASK_STOPPED);
				current->exit_code = signr;
				sig = current->parent->sig;
				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
					notify_parent(current, SIGCHLD);
				schedule();
				continue;
			}

			case SIGQUIT: case SIGILL: case SIGTRAP:
			case SIGABRT: case SIGFPE: case SIGSEGV:
			case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
				if (do_coredump(signr, regs))
					exit_code |= 0x80;
				/* FALLTHRU */

			default:
				sig_exit(signr, exit_code, info);
				/* NOTREACHED */
			}
		}
		return signr;
	}
	return 0;
}

#endif

1332
EXPORT_SYMBOL(recalc_sigpending);
Ingo Molnar's avatar
Ingo Molnar committed
1333
EXPORT_SYMBOL_GPL(dequeue_signal);
Linus Torvalds's avatar
Linus Torvalds committed
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
EXPORT_SYMBOL(flush_signals);
EXPORT_SYMBOL(force_sig);
EXPORT_SYMBOL(force_sig_info);
EXPORT_SYMBOL(kill_pg);
EXPORT_SYMBOL(kill_pg_info);
EXPORT_SYMBOL(kill_proc);
EXPORT_SYMBOL(kill_proc_info);
EXPORT_SYMBOL(kill_sl);
EXPORT_SYMBOL(kill_sl_info);
EXPORT_SYMBOL(notify_parent);
EXPORT_SYMBOL(send_sig);
EXPORT_SYMBOL(send_sig_info);
EXPORT_SYMBOL(block_all_signals);
EXPORT_SYMBOL(unblock_all_signals);


/*
 * System call entry points.
 */

1354 1355
asmlinkage long sys_restart_syscall(void)
{
1356 1357
	struct restart_block *restart = &current_thread_info()->restart_block;
	return restart->fn(restart);
1358 1359 1360 1361 1362 1363 1364 1365
}

long do_no_restart_syscall(struct restart_block *param)
{
	return -EINTR;
}


Linus Torvalds's avatar
Linus Torvalds committed
1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387
/*
 * 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)
 */

asmlinkage long
sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize)
{
	int error = -EINVAL;
	sigset_t old_set, new_set;

	/* XXX: Don't preclude handling different sized sigset_t's.  */
	if (sigsetsize != sizeof(sigset_t))
		goto out;

	if (set) {
		error = -EFAULT;
		if (copy_from_user(&new_set, set, sizeof(*set)))
			goto out;
		sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));

Ingo Molnar's avatar
Ingo Molnar committed
1388
		spin_lock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406
		old_set = current->blocked;

		error = 0;
		switch (how) {
		default:
			error = -EINVAL;
			break;
		case SIG_BLOCK:
			sigorsets(&new_set, &old_set, &new_set);
			break;
		case SIG_UNBLOCK:
			signandsets(&new_set, &old_set, &new_set);
			break;
		case SIG_SETMASK:
			break;
		}

		current->blocked = new_set;
1407
		recalc_sigpending();
Ingo Molnar's avatar
Ingo Molnar committed
1408
		spin_unlock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1409 1410 1411 1412 1413
		if (error)
			goto out;
		if (oset)
			goto set_old;
	} else if (oset) {
Ingo Molnar's avatar
Ingo Molnar committed
1414
		spin_lock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1415
		old_set = current->blocked;
Ingo Molnar's avatar
Ingo Molnar committed
1416
		spin_unlock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435

	set_old:
		error = -EFAULT;
		if (copy_to_user(oset, &old_set, sizeof(*oset)))
			goto out;
	}
	error = 0;
out:
	return error;
}

long do_sigpending(void *set, unsigned long sigsetsize)
{
	long error = -EINVAL;
	sigset_t pending;

	if (sigsetsize > sizeof(sigset_t))
		goto out;

Ingo Molnar's avatar
Ingo Molnar committed
1436
	spin_lock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1437
	sigandsets(&pending, &current->blocked, &current->pending.signal);
Ingo Molnar's avatar
Ingo Molnar committed
1438
	spin_unlock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452

	error = -EFAULT;
	if (!copy_to_user(set, &pending, sigsetsize))
		error = 0;
out:
	return error;
}	

asmlinkage long
sys_rt_sigpending(sigset_t *set, size_t sigsetsize)
{
	return do_sigpending(set, sigsetsize);
}

1453 1454 1455 1456
#ifndef HAVE_ARCH_COPY_SIGINFO_TO_USER

int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
{
1457 1458
	int err;

1459 1460 1461
	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
		return -EFAULT;
	if (from->si_code < 0)
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475
		return __copy_to_user(to, from, sizeof(siginfo_t))
			? -EFAULT : 0;
	/*
	 * If you change siginfo_t structure, please be sure
	 * this code is fixed accordingly.
	 * It should never copy any pad contained in the structure
	 * to avoid security leaks, but must copy the generic
	 * 3 ints plus the relevant union member.
	 */
	err = __put_user(from->si_signo, &to->si_signo);
	err |= __put_user(from->si_errno, &to->si_errno);
	err |= __put_user((short)from->si_code, &to->si_code);
	switch (from->si_code & __SI_MASK) {
	case __SI_KILL:
1476
		err |= __put_user(from->si_pid, &to->si_pid);
1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488
		err |= __put_user(from->si_uid, &to->si_uid);
		break;
	case __SI_TIMER:
		err |= __put_user(from->si_timer1, &to->si_timer1);
		err |= __put_user(from->si_timer2, &to->si_timer2);
		break;
	case __SI_POLL:
		err |= __put_user(from->si_band, &to->si_band);
		err |= __put_user(from->si_fd, &to->si_fd);
		break;
	case __SI_FAULT:
		err |= __put_user(from->si_addr, &to->si_addr);
1489 1490 1491
#ifdef __ARCH_SI_TRAPNO
		err |= __put_user(from->si_trapno, &to->si_trapno);
#endif
1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509
		break;
	case __SI_CHLD:
		err |= __put_user(from->si_pid, &to->si_pid);
		err |= __put_user(from->si_uid, &to->si_uid);
		err |= __put_user(from->si_status, &to->si_status);
		err |= __put_user(from->si_utime, &to->si_utime);
		err |= __put_user(from->si_stime, &to->si_stime);
		break;
	case __SI_RT: /* This is not generated by the kernel as of now. */
		err |= __put_user(from->si_pid, &to->si_pid);
		err |= __put_user(from->si_uid, &to->si_uid);
		err |= __put_user(from->si_int, &to->si_int);
		err |= __put_user(from->si_ptr, &to->si_ptr);
		break;
	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);
		break;
1510
	}
1511
	return err;
1512 1513 1514 1515
}

#endif

Linus Torvalds's avatar
Linus Torvalds committed
1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547
asmlinkage long
sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo,
		    const struct timespec *uts, size_t sigsetsize)
{
	int ret, sig;
	sigset_t these;
	struct timespec ts;
	siginfo_t info;
	long timeout = 0;

	/* XXX: Don't preclude handling different sized sigset_t's.  */
	if (sigsetsize != sizeof(sigset_t))
		return -EINVAL;

	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;
	}

Ingo Molnar's avatar
Ingo Molnar committed
1548
	spin_lock_irq(&current->sig->siglock);
Ingo Molnar's avatar
Ingo Molnar committed
1549
	sig = dequeue_signal(&these, &info);
Linus Torvalds's avatar
Linus Torvalds committed
1550 1551 1552 1553 1554 1555 1556 1557 1558 1559
	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.  */
Ingo Molnar's avatar
Ingo Molnar committed
1560
			current->real_blocked = current->blocked;
Linus Torvalds's avatar
Linus Torvalds committed
1561
			sigandsets(&current->blocked, &current->blocked, &these);
1562
			recalc_sigpending();
Ingo Molnar's avatar
Ingo Molnar committed
1563
			spin_unlock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1564 1565 1566 1567

			current->state = TASK_INTERRUPTIBLE;
			timeout = schedule_timeout(timeout);

Ingo Molnar's avatar
Ingo Molnar committed
1568
			spin_lock_irq(&current->sig->siglock);
Ingo Molnar's avatar
Ingo Molnar committed
1569
			sig = dequeue_signal(&these, &info);
Ingo Molnar's avatar
Ingo Molnar committed
1570 1571
			current->blocked = current->real_blocked;
			siginitset(&current->real_blocked, 0);
1572
			recalc_sigpending();
Linus Torvalds's avatar
Linus Torvalds committed
1573 1574
		}
	}
Ingo Molnar's avatar
Ingo Molnar committed
1575
	spin_unlock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605

	if (sig) {
		ret = sig;
		if (uinfo) {
			if (copy_siginfo_to_user(uinfo, &info))
				ret = -EFAULT;
		}
	} else {
		ret = -EAGAIN;
		if (timeout)
			ret = -EINTR;
	}

	return ret;
}

asmlinkage long
sys_kill(int pid, int sig)
{
	struct siginfo info;

	info.si_signo = sig;
	info.si_errno = 0;
	info.si_code = SI_USER;
	info.si_pid = current->pid;
	info.si_uid = current->uid;

	return kill_something_info(sig, &info, pid);
}

1606
/*
Ingo Molnar's avatar
Ingo Molnar committed
1607
 *  Send a signal to only one task, even if it's a CLONE_THREAD task.
1608 1609 1610 1611
 */
asmlinkage long
sys_tkill(int pid, int sig)
{
Ingo Molnar's avatar
Ingo Molnar committed
1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630
	struct siginfo info;
	int error;
	struct task_struct *p;

	/* This is only valid for single tasks */
	if (pid <= 0)
		return -EINVAL;

	info.si_signo = sig;
	info.si_errno = 0;
	info.si_code = SI_TKILL;
	info.si_pid = current->pid;
	info.si_uid = current->uid;

	read_lock(&tasklist_lock);
	p = find_task_by_pid(pid);
	error = -ESRCH;
	if (p) {
		spin_lock_irq(&p->sig->siglock);
Ingo Molnar's avatar
Ingo Molnar committed
1631
		error = specific_send_sig_info(sig, &info, p, 0);
Ingo Molnar's avatar
Ingo Molnar committed
1632 1633 1634 1635
		spin_unlock_irq(&p->sig->siglock);
	}
	read_unlock(&tasklist_lock);
	return error;
1636 1637
}

Linus Torvalds's avatar
Linus Torvalds committed
1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660
asmlinkage long
sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo)
{
	siginfo_t info;

	if (copy_from_user(&info, uinfo, sizeof(siginfo_t)))
		return -EFAULT;

	/* 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);
}

int
do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact)
{
	struct k_sigaction *k;

Ingo Molnar's avatar
Ingo Molnar committed
1661
	if (sig < 1 || sig > _NSIG || (act && sig_kernel_only(sig)))
Linus Torvalds's avatar
Linus Torvalds committed
1662 1663 1664 1665
		return -EINVAL;

	k = &current->sig->action[sig-1];

Ingo Molnar's avatar
Ingo Molnar committed
1666
	spin_lock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695

	if (oact)
		*oact = *k;

	if (act) {
		*k = *act;
		sigdelsetmask(&k->sa.sa_mask, sigmask(SIGKILL) | sigmask(SIGSTOP));

		/*
		 * POSIX 3.3.1.3:
		 *  "Setting a signal action to SIG_IGN for a signal that is
		 *   pending shall cause the pending signal to be discarded,
		 *   whether or not it is blocked."
		 *
		 *  "Setting a signal action to SIG_DFL for a signal that is
		 *   pending and whose default action is to ignore the signal
		 *   (for example, SIGCHLD), shall cause the pending signal to
		 *   be discarded, whether or not it is blocked"
		 *
		 * Note the silly behaviour of SIGCHLD: SIG_IGN means that the
		 * signal isn't actually ignored, but does automatic child
		 * reaping, while SIG_DFL is explicitly said by POSIX to force
		 * the signal to be ignored.
		 */

		if (k->sa.sa_handler == SIG_IGN
		    || (k->sa.sa_handler == SIG_DFL
			&& (sig == SIGCONT ||
			    sig == SIGCHLD ||
1696 1697
			    sig == SIGWINCH ||
			    sig == SIGURG))) {
Linus Torvalds's avatar
Linus Torvalds committed
1698
			if (rm_sig_from_queue(sig, current))
1699
				recalc_sigpending();
Linus Torvalds's avatar
Linus Torvalds committed
1700 1701 1702
		}
	}

Ingo Molnar's avatar
Ingo Molnar committed
1703
	spin_unlock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791
	return 0;
}

int 
do_sigaltstack (const stack_t *uss, stack_t *uoss, unsigned long sp)
{
	stack_t oss;
	int error;

	if (uoss) {
		oss.ss_sp = (void *) current->sas_ss_sp;
		oss.ss_size = current->sas_ss_size;
		oss.ss_flags = sas_ss_flags(sp);
	}

	if (uss) {
		void *ss_sp;
		size_t ss_size;
		int ss_flags;

		error = -EFAULT;
		if (verify_area(VERIFY_READ, uss, sizeof(*uss))
		    || __get_user(ss_sp, &uss->ss_sp)
		    || __get_user(ss_flags, &uss->ss_flags)
		    || __get_user(ss_size, &uss->ss_size))
			goto out;

		error = -EPERM;
		if (on_sig_stack (sp))
			goto out;

		error = -EINVAL;
		/*
		 *
		 * 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
		 */
		if (ss_flags != SS_DISABLE && ss_flags != SS_ONSTACK && ss_flags != 0)
			goto out;

		if (ss_flags == SS_DISABLE) {
			ss_size = 0;
			ss_sp = NULL;
		} else {
			error = -ENOMEM;
			if (ss_size < MINSIGSTKSZ)
				goto out;
		}

		current->sas_ss_sp = (unsigned long) ss_sp;
		current->sas_ss_size = ss_size;
	}

	if (uoss) {
		error = -EFAULT;
		if (copy_to_user(uoss, &oss, sizeof(oss)))
			goto out;
	}

	error = 0;
out:
	return error;
}

asmlinkage long
sys_sigpending(old_sigset_t *set)
{
	return do_sigpending(set, sizeof(*set));
}

#if !defined(__alpha__)
/* Alpha has its own versions with special arguments.  */

asmlinkage long
sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset)
{
	int error;
	old_sigset_t old_set, new_set;

	if (set) {
		error = -EFAULT;
		if (copy_from_user(&new_set, set, sizeof(*set)))
			goto out;
		new_set &= ~(sigmask(SIGKILL)|sigmask(SIGSTOP));

Ingo Molnar's avatar
Ingo Molnar committed
1792
		spin_lock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810
		old_set = current->blocked.sig[0];

		error = 0;
		switch (how) {
		default:
			error = -EINVAL;
			break;
		case SIG_BLOCK:
			sigaddsetmask(&current->blocked, new_set);
			break;
		case SIG_UNBLOCK:
			sigdelsetmask(&current->blocked, new_set);
			break;
		case SIG_SETMASK:
			current->blocked.sig[0] = new_set;
			break;
		}

1811
		recalc_sigpending();
Ingo Molnar's avatar
Ingo Molnar committed
1812
		spin_unlock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857
		if (error)
			goto out;
		if (oset)
			goto set_old;
	} else if (oset) {
		old_set = current->blocked.sig[0];
	set_old:
		error = -EFAULT;
		if (copy_to_user(oset, &old_set, sizeof(*oset)))
			goto out;
	}
	error = 0;
out:
	return error;
}

#ifndef __sparc__
asmlinkage long
sys_rt_sigaction(int sig, const struct sigaction *act, struct sigaction *oact,
		 size_t sigsetsize)
{
	struct k_sigaction new_sa, old_sa;
	int ret = -EINVAL;

	/* XXX: Don't preclude handling different sized sigset_t's.  */
	if (sigsetsize != sizeof(sigset_t))
		goto out;

	if (act) {
		if (copy_from_user(&new_sa.sa, act, sizeof(new_sa.sa)))
			return -EFAULT;
	}

	ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);

	if (!ret && oact) {
		if (copy_to_user(oact, &old_sa.sa, sizeof(old_sa.sa)))
			return -EFAULT;
	}
out:
	return ret;
}
#endif /* __sparc__ */
#endif

1858
#if !defined(__alpha__) && !defined(__ia64__) && !defined(__arm__)
Linus Torvalds's avatar
Linus Torvalds committed
1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873
/*
 * For backwards compatibility.  Functionality superseded by sigprocmask.
 */
asmlinkage long
sys_sgetmask(void)
{
	/* SMP safe */
	return current->blocked.sig[0];
}

asmlinkage long
sys_ssetmask(int newmask)
{
	int old;

Ingo Molnar's avatar
Ingo Molnar committed
1874
	spin_lock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1875 1876 1877 1878
	old = current->blocked.sig[0];

	siginitset(&current->blocked, newmask & ~(sigmask(SIGKILL)|
						  sigmask(SIGSTOP)));
1879
	recalc_sigpending();
Ingo Molnar's avatar
Ingo Molnar committed
1880
	spin_unlock_irq(&current->sig->siglock);
Linus Torvalds's avatar
Linus Torvalds committed
1881 1882 1883 1884 1885

	return old;
}
#endif /* !defined(__alpha__) */

1886 1887
#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && \
    !defined(__arm__)
Linus Torvalds's avatar
Linus Torvalds committed
1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903
/*
 * For backwards compatibility.  Functionality superseded by sigaction.
 */
asmlinkage unsigned long
sys_signal(int sig, __sighandler_t handler)
{
	struct k_sigaction new_sa, old_sa;
	int ret;

	new_sa.sa.sa_handler = handler;
	new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;

	ret = do_sigaction(sig, &new_sa, &old_sa);

	return ret ? ret : (unsigned long)old_sa.sa.sa_handler;
}
1904
#endif /* !alpha && !__ia64__ && !defined(__mips__) && !defined(__arm__) */
1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916

#ifndef HAVE_ARCH_SYS_PAUSE

asmlinkage int
sys_pause(void)
{
	current->state = TASK_INTERRUPTIBLE;
	schedule();
	return -ERESTARTNOHAND;
}

#endif /* HAVE_ARCH_SYS_PAUSE */
Ingo Molnar's avatar
Ingo Molnar committed
1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928

void __init signals_init(void)
{
	sigqueue_cachep =
		kmem_cache_create("sigqueue",
				  sizeof(struct sigqueue),
				  __alignof__(struct sigqueue),
				  0, NULL, NULL);
	if (!sigqueue_cachep)
		panic("signals_init(): cannot create sigqueue SLAB cache");
}