diff options
Diffstat (limited to 'kernel/signal.c')
| -rw-r--r-- | kernel/signal.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 906ae5a1779c..4e3cff10fdce 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -637,7 +637,7 @@ static inline bool si_fromuser(const struct siginfo *info) | |||
| 637 | 637 | ||
| 638 | /* | 638 | /* |
| 639 | * Bad permissions for sending the signal | 639 | * Bad permissions for sending the signal |
| 640 | * - the caller must hold at least the RCU read lock | 640 | * - the caller must hold the RCU read lock |
| 641 | */ | 641 | */ |
| 642 | static int check_kill_permission(int sig, struct siginfo *info, | 642 | static int check_kill_permission(int sig, struct siginfo *info, |
| 643 | struct task_struct *t) | 643 | struct task_struct *t) |
| @@ -1105,7 +1105,8 @@ int zap_other_threads(struct task_struct *p) | |||
| 1105 | return count; | 1105 | return count; |
| 1106 | } | 1106 | } |
| 1107 | 1107 | ||
| 1108 | struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long *flags) | 1108 | struct sighand_struct *__lock_task_sighand(struct task_struct *tsk, |
| 1109 | unsigned long *flags) | ||
| 1109 | { | 1110 | { |
| 1110 | struct sighand_struct *sighand; | 1111 | struct sighand_struct *sighand; |
| 1111 | 1112 | ||
| @@ -1127,11 +1128,14 @@ struct sighand_struct *lock_task_sighand(struct task_struct *tsk, unsigned long | |||
| 1127 | 1128 | ||
| 1128 | /* | 1129 | /* |
| 1129 | * send signal info to all the members of a group | 1130 | * send signal info to all the members of a group |
| 1130 | * - the caller must hold the RCU read lock at least | ||
| 1131 | */ | 1131 | */ |
| 1132 | int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) | 1132 | int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p) |
| 1133 | { | 1133 | { |
| 1134 | int ret = check_kill_permission(sig, info, p); | 1134 | int ret; |
| 1135 | |||
| 1136 | rcu_read_lock(); | ||
| 1137 | ret = check_kill_permission(sig, info, p); | ||
| 1138 | rcu_read_unlock(); | ||
| 1135 | 1139 | ||
| 1136 | if (!ret && sig) | 1140 | if (!ret && sig) |
| 1137 | ret = do_send_sig_info(sig, info, p, true); | 1141 | ret = do_send_sig_info(sig, info, p, true); |
| @@ -1614,6 +1618,8 @@ static int sigkill_pending(struct task_struct *tsk) | |||
| 1614 | * is gone, we keep current->exit_code unless clear_code. | 1618 | * is gone, we keep current->exit_code unless clear_code. |
| 1615 | */ | 1619 | */ |
| 1616 | static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) | 1620 | static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) |
| 1621 | __releases(¤t->sighand->siglock) | ||
| 1622 | __acquires(¤t->sighand->siglock) | ||
| 1617 | { | 1623 | { |
| 1618 | if (arch_ptrace_stop_needed(exit_code, info)) { | 1624 | if (arch_ptrace_stop_needed(exit_code, info)) { |
| 1619 | /* | 1625 | /* |
| @@ -2212,6 +2218,14 @@ int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from) | |||
| 2212 | #ifdef __ARCH_SI_TRAPNO | 2218 | #ifdef __ARCH_SI_TRAPNO |
| 2213 | err |= __put_user(from->si_trapno, &to->si_trapno); | 2219 | err |= __put_user(from->si_trapno, &to->si_trapno); |
| 2214 | #endif | 2220 | #endif |
| 2221 | #ifdef BUS_MCEERR_AO | ||
| 2222 | /* | ||
| 2223 | * Other callers might not initialize the si_lsb field, | ||
| 2224 | * so check explicitely for the right codes here. | ||
| 2225 | */ | ||
| 2226 | if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO) | ||
| 2227 | err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb); | ||
| 2228 | #endif | ||
| 2215 | break; | 2229 | break; |
| 2216 | case __SI_CHLD: | 2230 | case __SI_CHLD: |
| 2217 | err |= __put_user(from->si_pid, &to->si_pid); | 2231 | err |= __put_user(from->si_pid, &to->si_pid); |
