aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 1814e68e4de3..934ae5e687b9 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -218,13 +218,13 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi
218 struct user_struct *user; 218 struct user_struct *user;
219 219
220 /* 220 /*
221 * We won't get problems with the target's UID changing under us 221 * Protect access to @t credentials. This can go away when all
222 * because changing it requires RCU be used, and if t != current, the 222 * callers hold rcu read lock.
223 * caller must be holding the RCU readlock (by way of a spinlock) and
224 * we use RCU protection here
225 */ 223 */
224 rcu_read_lock();
226 user = get_uid(__task_cred(t)->user); 225 user = get_uid(__task_cred(t)->user);
227 atomic_inc(&user->sigpending); 226 atomic_inc(&user->sigpending);
227 rcu_read_unlock();
228 228
229 if (override_rlimit || 229 if (override_rlimit ||
230 atomic_read(&user->sigpending) <= 230 atomic_read(&user->sigpending) <=
@@ -979,7 +979,8 @@ static void print_fatal_signal(struct pt_regs *regs, int signr)
979 for (i = 0; i < 16; i++) { 979 for (i = 0; i < 16; i++) {
980 unsigned char insn; 980 unsigned char insn;
981 981
982 __get_user(insn, (unsigned char *)(regs->ip + i)); 982 if (get_user(insn, (unsigned char *)(regs->ip + i)))
983 break;
983 printk("%02x ", insn); 984 printk("%02x ", insn);
984 } 985 }
985 } 986 }
@@ -1179,11 +1180,12 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
1179 int ret = -EINVAL; 1180 int ret = -EINVAL;
1180 struct task_struct *p; 1181 struct task_struct *p;
1181 const struct cred *pcred; 1182 const struct cred *pcred;
1183 unsigned long flags;
1182 1184
1183 if (!valid_signal(sig)) 1185 if (!valid_signal(sig))
1184 return ret; 1186 return ret;
1185 1187
1186 read_lock(&tasklist_lock); 1188 rcu_read_lock();
1187 p = pid_task(pid, PIDTYPE_PID); 1189 p = pid_task(pid, PIDTYPE_PID);
1188 if (!p) { 1190 if (!p) {
1189 ret = -ESRCH; 1191 ret = -ESRCH;
@@ -1199,14 +1201,16 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid,
1199 ret = security_task_kill(p, info, sig, secid); 1201 ret = security_task_kill(p, info, sig, secid);
1200 if (ret) 1202 if (ret)
1201 goto out_unlock; 1203 goto out_unlock;
1202 if (sig && p->sighand) { 1204
1203 unsigned long flags; 1205 if (sig) {
1204 spin_lock_irqsave(&p->sighand->siglock, flags); 1206 if (lock_task_sighand(p, &flags)) {
1205 ret = __send_signal(sig, info, p, 1, 0); 1207 ret = __send_signal(sig, info, p, 1, 0);
1206 spin_unlock_irqrestore(&p->sighand->siglock, flags); 1208 unlock_task_sighand(p, &flags);
1209 } else
1210 ret = -ESRCH;
1207 } 1211 }
1208out_unlock: 1212out_unlock:
1209 read_unlock(&tasklist_lock); 1213 rcu_read_unlock();
1210 return ret; 1214 return ret;
1211} 1215}
1212EXPORT_SYMBOL_GPL(kill_pid_info_as_uid); 1216EXPORT_SYMBOL_GPL(kill_pid_info_as_uid);