diff options
Diffstat (limited to 'kernel/signal.c')
| -rw-r--r-- | kernel/signal.c | 148 |
1 files changed, 51 insertions, 97 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 6904bbbfe116..1bf3c39d6109 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -277,7 +277,6 @@ static struct sigqueue *__sigqueue_alloc(struct task_struct *t, gfp_t flags, | |||
| 277 | } else { | 277 | } else { |
| 278 | INIT_LIST_HEAD(&q->list); | 278 | INIT_LIST_HEAD(&q->list); |
| 279 | q->flags = 0; | 279 | q->flags = 0; |
| 280 | q->lock = NULL; | ||
| 281 | q->user = get_uid(t->user); | 280 | q->user = get_uid(t->user); |
| 282 | } | 281 | } |
| 283 | return(q); | 282 | return(q); |
| @@ -652,8 +651,7 @@ static int check_kill_permission(int sig, struct siginfo *info, | |||
| 652 | if (!valid_signal(sig)) | 651 | if (!valid_signal(sig)) |
| 653 | return error; | 652 | return error; |
| 654 | error = -EPERM; | 653 | error = -EPERM; |
| 655 | if ((!info || ((unsigned long)info != 1 && | 654 | if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info))) |
| 656 | (unsigned long)info != 2 && SI_FROMUSER(info))) | ||
| 657 | && ((sig != SIGCONT) || | 655 | && ((sig != SIGCONT) || |
| 658 | (current->signal->session != t->signal->session)) | 656 | (current->signal->session != t->signal->session)) |
| 659 | && (current->euid ^ t->suid) && (current->euid ^ t->uid) | 657 | && (current->euid ^ t->suid) && (current->euid ^ t->uid) |
| @@ -790,7 +788,7 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
| 790 | * fast-pathed signals for kernel-internal things like SIGSTOP | 788 | * fast-pathed signals for kernel-internal things like SIGSTOP |
| 791 | * or SIGKILL. | 789 | * or SIGKILL. |
| 792 | */ | 790 | */ |
| 793 | if ((unsigned long)info == 2) | 791 | if (info == SEND_SIG_FORCED) |
| 794 | goto out_set; | 792 | goto out_set; |
| 795 | 793 | ||
| 796 | /* Real-time signals must be queued if sent by sigqueue, or | 794 | /* Real-time signals must be queued if sent by sigqueue, or |
| @@ -802,19 +800,19 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
| 802 | pass on the info struct. */ | 800 | pass on the info struct. */ |
| 803 | 801 | ||
| 804 | q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN && | 802 | q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN && |
| 805 | ((unsigned long) info < 2 || | 803 | (is_si_special(info) || |
| 806 | info->si_code >= 0))); | 804 | info->si_code >= 0))); |
| 807 | if (q) { | 805 | if (q) { |
| 808 | list_add_tail(&q->list, &signals->list); | 806 | list_add_tail(&q->list, &signals->list); |
| 809 | switch ((unsigned long) info) { | 807 | switch ((unsigned long) info) { |
| 810 | case 0: | 808 | case (unsigned long) SEND_SIG_NOINFO: |
| 811 | q->info.si_signo = sig; | 809 | q->info.si_signo = sig; |
| 812 | q->info.si_errno = 0; | 810 | q->info.si_errno = 0; |
| 813 | q->info.si_code = SI_USER; | 811 | q->info.si_code = SI_USER; |
| 814 | q->info.si_pid = current->pid; | 812 | q->info.si_pid = current->pid; |
| 815 | q->info.si_uid = current->uid; | 813 | q->info.si_uid = current->uid; |
| 816 | break; | 814 | break; |
| 817 | case 1: | 815 | case (unsigned long) SEND_SIG_PRIV: |
| 818 | q->info.si_signo = sig; | 816 | q->info.si_signo = sig; |
| 819 | q->info.si_errno = 0; | 817 | q->info.si_errno = 0; |
| 820 | q->info.si_code = SI_KERNEL; | 818 | q->info.si_code = SI_KERNEL; |
| @@ -825,20 +823,13 @@ static int send_signal(int sig, struct siginfo *info, struct task_struct *t, | |||
| 825 | copy_siginfo(&q->info, info); | 823 | copy_siginfo(&q->info, info); |
| 826 | break; | 824 | break; |
| 827 | } | 825 | } |
| 828 | } else { | 826 | } else if (!is_si_special(info)) { |
| 829 | if (sig >= SIGRTMIN && info && (unsigned long)info != 1 | 827 | if (sig >= SIGRTMIN && info->si_code != SI_USER) |
| 830 | && info->si_code != SI_USER) | ||
| 831 | /* | 828 | /* |
| 832 | * Queue overflow, abort. We may abort if the signal was rt | 829 | * Queue overflow, abort. We may abort if the signal was rt |
| 833 | * and sent by user using something other than kill(). | 830 | * and sent by user using something other than kill(). |
| 834 | */ | 831 | */ |
| 835 | return -EAGAIN; | 832 | return -EAGAIN; |
| 836 | if (((unsigned long)info > 1) && (info->si_code == SI_TIMER)) | ||
| 837 | /* | ||
| 838 | * Set up a return to indicate that we dropped | ||
| 839 | * the signal. | ||
| 840 | */ | ||
| 841 | ret = info->si_sys_private; | ||
| 842 | } | 833 | } |
| 843 | 834 | ||
| 844 | out_set: | 835 | out_set: |
| @@ -859,12 +850,6 @@ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) | |||
| 859 | BUG(); | 850 | BUG(); |
| 860 | assert_spin_locked(&t->sighand->siglock); | 851 | assert_spin_locked(&t->sighand->siglock); |
| 861 | 852 | ||
| 862 | if (((unsigned long)info > 2) && (info->si_code == SI_TIMER)) | ||
| 863 | /* | ||
| 864 | * Set up a return to indicate that we dropped the signal. | ||
| 865 | */ | ||
| 866 | ret = info->si_sys_private; | ||
| 867 | |||
| 868 | /* Short-circuit ignored signals. */ | 853 | /* Short-circuit ignored signals. */ |
| 869 | if (sig_ignored(t, sig)) | 854 | if (sig_ignored(t, sig)) |
| 870 | goto out; | 855 | goto out; |
| @@ -894,11 +879,13 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t) | |||
| 894 | int ret; | 879 | int ret; |
| 895 | 880 | ||
| 896 | spin_lock_irqsave(&t->sighand->siglock, flags); | 881 | spin_lock_irqsave(&t->sighand->siglock, flags); |
| 897 | if (sigismember(&t->blocked, sig) || t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) { | 882 | if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) { |
| 898 | t->sighand->action[sig-1].sa.sa_handler = SIG_DFL; | 883 | t->sighand->action[sig-1].sa.sa_handler = SIG_DFL; |
| 884 | } | ||
| 885 | if (sigismember(&t->blocked, sig)) { | ||
| 899 | sigdelset(&t->blocked, sig); | 886 | sigdelset(&t->blocked, sig); |
| 900 | recalc_sigpending_tsk(t); | ||
| 901 | } | 887 | } |
| 888 | recalc_sigpending_tsk(t); | ||
| 902 | ret = specific_send_sig_info(sig, info, t); | 889 | ret = specific_send_sig_info(sig, info, t); |
| 903 | spin_unlock_irqrestore(&t->sighand->siglock, flags); | 890 | spin_unlock_irqrestore(&t->sighand->siglock, flags); |
| 904 | 891 | ||
| @@ -908,15 +895,7 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t) | |||
| 908 | void | 895 | void |
| 909 | force_sig_specific(int sig, struct task_struct *t) | 896 | force_sig_specific(int sig, struct task_struct *t) |
| 910 | { | 897 | { |
| 911 | unsigned long int flags; | 898 | force_sig_info(sig, SEND_SIG_FORCED, t); |
| 912 | |||
| 913 | spin_lock_irqsave(&t->sighand->siglock, flags); | ||
| 914 | if (t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) | ||
| 915 | t->sighand->action[sig-1].sa.sa_handler = SIG_DFL; | ||
| 916 | sigdelset(&t->blocked, sig); | ||
| 917 | recalc_sigpending_tsk(t); | ||
| 918 | specific_send_sig_info(sig, (void *)2, t); | ||
| 919 | spin_unlock_irqrestore(&t->sighand->siglock, flags); | ||
| 920 | } | 899 | } |
| 921 | 900 | ||
| 922 | /* | 901 | /* |
| @@ -1051,12 +1030,6 @@ __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) | |||
| 1051 | assert_spin_locked(&p->sighand->siglock); | 1030 | assert_spin_locked(&p->sighand->siglock); |
| 1052 | handle_stop_signal(sig, p); | 1031 | handle_stop_signal(sig, p); |
| 1053 | 1032 | ||
| 1054 | if (((unsigned long)info > 2) && (info->si_code == SI_TIMER)) | ||
| 1055 | /* | ||
| 1056 | * Set up a return to indicate that we dropped the signal. | ||
| 1057 | */ | ||
| 1058 | ret = info->si_sys_private; | ||
| 1059 | |||
| 1060 | /* Short-circuit ignored signals. */ | 1033 | /* Short-circuit ignored signals. */ |
| 1061 | if (sig_ignored(p, sig)) | 1034 | if (sig_ignored(p, sig)) |
| 1062 | return ret; | 1035 | return ret; |
| @@ -1109,8 +1082,8 @@ void zap_other_threads(struct task_struct *p) | |||
| 1109 | if (t != p->group_leader) | 1082 | if (t != p->group_leader) |
| 1110 | t->exit_signal = -1; | 1083 | t->exit_signal = -1; |
| 1111 | 1084 | ||
| 1085 | /* SIGKILL will be handled before any pending SIGSTOP */ | ||
| 1112 | sigaddset(&t->pending.signal, SIGKILL); | 1086 | sigaddset(&t->pending.signal, SIGKILL); |
| 1113 | rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); | ||
| 1114 | signal_wake_up(t, 1); | 1087 | signal_wake_up(t, 1); |
| 1115 | } | 1088 | } |
| 1116 | } | 1089 | } |
| @@ -1286,10 +1259,13 @@ send_sig_info(int sig, struct siginfo *info, struct task_struct *p) | |||
| 1286 | return ret; | 1259 | return ret; |
| 1287 | } | 1260 | } |
| 1288 | 1261 | ||
| 1262 | #define __si_special(priv) \ | ||
| 1263 | ((priv) ? SEND_SIG_PRIV : SEND_SIG_NOINFO) | ||
| 1264 | |||
| 1289 | int | 1265 | int |
| 1290 | send_sig(int sig, struct task_struct *p, int priv) | 1266 | send_sig(int sig, struct task_struct *p, int priv) |
| 1291 | { | 1267 | { |
| 1292 | return send_sig_info(sig, (void*)(long)(priv != 0), p); | 1268 | return send_sig_info(sig, __si_special(priv), p); |
| 1293 | } | 1269 | } |
| 1294 | 1270 | ||
| 1295 | /* | 1271 | /* |
| @@ -1309,7 +1285,7 @@ send_group_sig_info(int sig, struct siginfo *info, struct task_struct *p) | |||
| 1309 | void | 1285 | void |
| 1310 | force_sig(int sig, struct task_struct *p) | 1286 | force_sig(int sig, struct task_struct *p) |
| 1311 | { | 1287 | { |
| 1312 | force_sig_info(sig, (void*)1L, p); | 1288 | force_sig_info(sig, SEND_SIG_PRIV, p); |
| 1313 | } | 1289 | } |
| 1314 | 1290 | ||
| 1315 | /* | 1291 | /* |
| @@ -1334,13 +1310,13 @@ force_sigsegv(int sig, struct task_struct *p) | |||
| 1334 | int | 1310 | int |
| 1335 | kill_pg(pid_t pgrp, int sig, int priv) | 1311 | kill_pg(pid_t pgrp, int sig, int priv) |
| 1336 | { | 1312 | { |
| 1337 | return kill_pg_info(sig, (void *)(long)(priv != 0), pgrp); | 1313 | return kill_pg_info(sig, __si_special(priv), pgrp); |
| 1338 | } | 1314 | } |
| 1339 | 1315 | ||
| 1340 | int | 1316 | int |
| 1341 | kill_proc(pid_t pid, int sig, int priv) | 1317 | kill_proc(pid_t pid, int sig, int priv) |
| 1342 | { | 1318 | { |
| 1343 | return kill_proc_info(sig, (void *)(long)(priv != 0), pid); | 1319 | return kill_proc_info(sig, __si_special(priv), pid); |
| 1344 | } | 1320 | } |
| 1345 | 1321 | ||
| 1346 | /* | 1322 | /* |
| @@ -1371,11 +1347,12 @@ void sigqueue_free(struct sigqueue *q) | |||
| 1371 | * pending queue. | 1347 | * pending queue. |
| 1372 | */ | 1348 | */ |
| 1373 | if (unlikely(!list_empty(&q->list))) { | 1349 | if (unlikely(!list_empty(&q->list))) { |
| 1374 | read_lock(&tasklist_lock); | 1350 | spinlock_t *lock = ¤t->sighand->siglock; |
| 1375 | spin_lock_irqsave(q->lock, flags); | 1351 | read_lock(&tasklist_lock); |
| 1352 | spin_lock_irqsave(lock, flags); | ||
| 1376 | if (!list_empty(&q->list)) | 1353 | if (!list_empty(&q->list)) |
| 1377 | list_del_init(&q->list); | 1354 | list_del_init(&q->list); |
| 1378 | spin_unlock_irqrestore(q->lock, flags); | 1355 | spin_unlock_irqrestore(lock, flags); |
| 1379 | read_unlock(&tasklist_lock); | 1356 | read_unlock(&tasklist_lock); |
| 1380 | } | 1357 | } |
| 1381 | q->flags &= ~SIGQUEUE_PREALLOC; | 1358 | q->flags &= ~SIGQUEUE_PREALLOC; |
| @@ -1414,7 +1391,6 @@ send_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) | |||
| 1414 | goto out; | 1391 | goto out; |
| 1415 | } | 1392 | } |
| 1416 | 1393 | ||
| 1417 | q->lock = &p->sighand->siglock; | ||
| 1418 | list_add_tail(&q->list, &p->pending.list); | 1394 | list_add_tail(&q->list, &p->pending.list); |
| 1419 | sigaddset(&p->pending.signal, sig); | 1395 | sigaddset(&p->pending.signal, sig); |
| 1420 | if (!sigismember(&p->blocked, sig)) | 1396 | if (!sigismember(&p->blocked, sig)) |
| @@ -1462,7 +1438,6 @@ send_group_sigqueue(int sig, struct sigqueue *q, struct task_struct *p) | |||
| 1462 | * We always use the shared queue for process-wide signals, | 1438 | * We always use the shared queue for process-wide signals, |
| 1463 | * to avoid several races. | 1439 | * to avoid several races. |
| 1464 | */ | 1440 | */ |
| 1465 | q->lock = &p->sighand->siglock; | ||
| 1466 | list_add_tail(&q->list, &p->signal->shared_pending.list); | 1441 | list_add_tail(&q->list, &p->signal->shared_pending.list); |
| 1467 | sigaddset(&p->signal->shared_pending.signal, sig); | 1442 | sigaddset(&p->signal->shared_pending.signal, sig); |
| 1468 | 1443 | ||
| @@ -1881,9 +1856,9 @@ relock: | |||
| 1881 | /* Let the debugger run. */ | 1856 | /* Let the debugger run. */ |
| 1882 | ptrace_stop(signr, signr, info); | 1857 | ptrace_stop(signr, signr, info); |
| 1883 | 1858 | ||
| 1884 | /* We're back. Did the debugger cancel the sig? */ | 1859 | /* We're back. Did the debugger cancel the sig or group_exit? */ |
| 1885 | signr = current->exit_code; | 1860 | signr = current->exit_code; |
| 1886 | if (signr == 0) | 1861 | if (signr == 0 || current->signal->flags & SIGNAL_GROUP_EXIT) |
| 1887 | continue; | 1862 | continue; |
| 1888 | 1863 | ||
| 1889 | current->exit_code = 0; | 1864 | current->exit_code = 0; |
| @@ -2285,26 +2260,13 @@ sys_kill(int pid, int sig) | |||
| 2285 | return kill_something_info(sig, &info, pid); | 2260 | return kill_something_info(sig, &info, pid); |
| 2286 | } | 2261 | } |
| 2287 | 2262 | ||
| 2288 | /** | 2263 | static int do_tkill(int tgid, int pid, int sig) |
| 2289 | * sys_tgkill - send signal to one specific thread | ||
| 2290 | * @tgid: the thread group ID of the thread | ||
| 2291 | * @pid: the PID of the thread | ||
| 2292 | * @sig: signal to be sent | ||
| 2293 | * | ||
| 2294 | * This syscall also checks the tgid and returns -ESRCH even if the PID | ||
| 2295 | * exists but it's not belonging to the target process anymore. This | ||
| 2296 | * method solves the problem of threads exiting and PIDs getting reused. | ||
| 2297 | */ | ||
| 2298 | asmlinkage long sys_tgkill(int tgid, int pid, int sig) | ||
| 2299 | { | 2264 | { |
| 2300 | struct siginfo info; | ||
| 2301 | int error; | 2265 | int error; |
| 2266 | struct siginfo info; | ||
| 2302 | struct task_struct *p; | 2267 | struct task_struct *p; |
| 2303 | 2268 | ||
| 2304 | /* This is only valid for single tasks */ | 2269 | error = -ESRCH; |
| 2305 | if (pid <= 0 || tgid <= 0) | ||
| 2306 | return -EINVAL; | ||
| 2307 | |||
| 2308 | info.si_signo = sig; | 2270 | info.si_signo = sig; |
| 2309 | info.si_errno = 0; | 2271 | info.si_errno = 0; |
| 2310 | info.si_code = SI_TKILL; | 2272 | info.si_code = SI_TKILL; |
| @@ -2313,8 +2275,7 @@ asmlinkage long sys_tgkill(int tgid, int pid, int sig) | |||
| 2313 | 2275 | ||
| 2314 | read_lock(&tasklist_lock); | 2276 | read_lock(&tasklist_lock); |
| 2315 | p = find_task_by_pid(pid); | 2277 | p = find_task_by_pid(pid); |
| 2316 | error = -ESRCH; | 2278 | if (p && (tgid <= 0 || p->tgid == tgid)) { |
| 2317 | if (p && (p->tgid == tgid)) { | ||
| 2318 | error = check_kill_permission(sig, &info, p); | 2279 | error = check_kill_permission(sig, &info, p); |
| 2319 | /* | 2280 | /* |
| 2320 | * The null signal is a permissions and process existence | 2281 | * The null signal is a permissions and process existence |
| @@ -2328,47 +2289,40 @@ asmlinkage long sys_tgkill(int tgid, int pid, int sig) | |||
| 2328 | } | 2289 | } |
| 2329 | } | 2290 | } |
| 2330 | read_unlock(&tasklist_lock); | 2291 | read_unlock(&tasklist_lock); |
| 2292 | |||
| 2331 | return error; | 2293 | return error; |
| 2332 | } | 2294 | } |
| 2333 | 2295 | ||
| 2296 | /** | ||
| 2297 | * sys_tgkill - send signal to one specific thread | ||
| 2298 | * @tgid: the thread group ID of the thread | ||
| 2299 | * @pid: the PID of the thread | ||
| 2300 | * @sig: signal to be sent | ||
| 2301 | * | ||
| 2302 | * This syscall also checks the tgid and returns -ESRCH even if the PID | ||
| 2303 | * exists but it's not belonging to the target process anymore. This | ||
| 2304 | * method solves the problem of threads exiting and PIDs getting reused. | ||
| 2305 | */ | ||
| 2306 | asmlinkage long sys_tgkill(int tgid, int pid, int sig) | ||
| 2307 | { | ||
| 2308 | /* This is only valid for single tasks */ | ||
| 2309 | if (pid <= 0 || tgid <= 0) | ||
| 2310 | return -EINVAL; | ||
| 2311 | |||
| 2312 | return do_tkill(tgid, pid, sig); | ||
| 2313 | } | ||
| 2314 | |||
| 2334 | /* | 2315 | /* |
| 2335 | * Send a signal to only one task, even if it's a CLONE_THREAD task. | 2316 | * Send a signal to only one task, even if it's a CLONE_THREAD task. |
| 2336 | */ | 2317 | */ |
| 2337 | asmlinkage long | 2318 | asmlinkage long |
| 2338 | sys_tkill(int pid, int sig) | 2319 | sys_tkill(int pid, int sig) |
| 2339 | { | 2320 | { |
| 2340 | struct siginfo info; | ||
| 2341 | int error; | ||
| 2342 | struct task_struct *p; | ||
| 2343 | |||
| 2344 | /* This is only valid for single tasks */ | 2321 | /* This is only valid for single tasks */ |
| 2345 | if (pid <= 0) | 2322 | if (pid <= 0) |
| 2346 | return -EINVAL; | 2323 | return -EINVAL; |
| 2347 | 2324 | ||
| 2348 | info.si_signo = sig; | 2325 | return do_tkill(0, pid, sig); |
| 2349 | info.si_errno = 0; | ||
| 2350 | info.si_code = SI_TKILL; | ||
| 2351 | info.si_pid = current->tgid; | ||
| 2352 | info.si_uid = current->uid; | ||
| 2353 | |||
| 2354 | read_lock(&tasklist_lock); | ||
| 2355 | p = find_task_by_pid(pid); | ||
| 2356 | error = -ESRCH; | ||
| 2357 | if (p) { | ||
| 2358 | error = check_kill_permission(sig, &info, p); | ||
| 2359 | /* | ||
| 2360 | * The null signal is a permissions and process existence | ||
| 2361 | * probe. No signal is actually delivered. | ||
| 2362 | */ | ||
| 2363 | if (!error && sig && p->sighand) { | ||
| 2364 | spin_lock_irq(&p->sighand->siglock); | ||
| 2365 | handle_stop_signal(sig, p); | ||
| 2366 | error = specific_send_sig_info(sig, &info, p); | ||
| 2367 | spin_unlock_irq(&p->sighand->siglock); | ||
| 2368 | } | ||
| 2369 | } | ||
| 2370 | read_unlock(&tasklist_lock); | ||
| 2371 | return error; | ||
| 2372 | } | 2326 | } |
| 2373 | 2327 | ||
| 2374 | asmlinkage long | 2328 | asmlinkage long |
