Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
sys: Fix missing rcu protection for __task_cred() access
signals: Fix more rcu assumptions
signal: Fix racy access to __task_cred in kill_pid_info_as_uid()

+16 -11
+14 -11
kernel/signal.c
··· 218 218 struct user_struct *user; 219 219 220 220 /* 221 - * We won't get problems with the target's UID changing under us 222 - * because changing it requires RCU be used, and if t != current, the 223 - * caller must be holding the RCU readlock (by way of a spinlock) and 224 - * we use RCU protection here 221 + * Protect access to @t credentials. This can go away when all 222 + * callers hold rcu read lock. 225 223 */ 224 + rcu_read_lock(); 226 225 user = get_uid(__task_cred(t)->user); 227 226 atomic_inc(&user->sigpending); 227 + rcu_read_unlock(); 228 228 229 229 if (override_rlimit || 230 230 atomic_read(&user->sigpending) <= ··· 1179 1179 int ret = -EINVAL; 1180 1180 struct task_struct *p; 1181 1181 const struct cred *pcred; 1182 + unsigned long flags; 1182 1183 1183 1184 if (!valid_signal(sig)) 1184 1185 return ret; 1185 1186 1186 - read_lock(&tasklist_lock); 1187 + rcu_read_lock(); 1187 1188 p = pid_task(pid, PIDTYPE_PID); 1188 1189 if (!p) { 1189 1190 ret = -ESRCH; ··· 1200 1199 ret = security_task_kill(p, info, sig, secid); 1201 1200 if (ret) 1202 1201 goto out_unlock; 1203 - if (sig && p->sighand) { 1204 - unsigned long flags; 1205 - spin_lock_irqsave(&p->sighand->siglock, flags); 1206 - ret = __send_signal(sig, info, p, 1, 0); 1207 - spin_unlock_irqrestore(&p->sighand->siglock, flags); 1202 + 1203 + if (sig) { 1204 + if (lock_task_sighand(p, &flags)) { 1205 + ret = __send_signal(sig, info, p, 1, 0); 1206 + unlock_task_sighand(p, &flags); 1207 + } else 1208 + ret = -ESRCH; 1208 1209 } 1209 1210 out_unlock: 1210 - read_unlock(&tasklist_lock); 1211 + rcu_read_unlock(); 1211 1212 return ret; 1212 1213 } 1213 1214 EXPORT_SYMBOL_GPL(kill_pid_info_as_uid);
+2
kernel/sys.c
··· 162 162 if (niceval > 19) 163 163 niceval = 19; 164 164 165 + rcu_read_lock(); 165 166 read_lock(&tasklist_lock); 166 167 switch (which) { 167 168 case PRIO_PROCESS: ··· 200 199 } 201 200 out_unlock: 202 201 read_unlock(&tasklist_lock); 202 + rcu_read_unlock(); 203 203 out: 204 204 return error; 205 205 }