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 struct user_struct *user; 219 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 225 */ 226 user = get_uid(__task_cred(t)->user); 227 atomic_inc(&user->sigpending); 228 229 if (override_rlimit || 230 atomic_read(&user->sigpending) <= ··· 1179 int ret = -EINVAL; 1180 struct task_struct *p; 1181 const struct cred *pcred; 1182 1183 if (!valid_signal(sig)) 1184 return ret; 1185 1186 - read_lock(&tasklist_lock); 1187 p = pid_task(pid, PIDTYPE_PID); 1188 if (!p) { 1189 ret = -ESRCH; ··· 1200 ret = security_task_kill(p, info, sig, secid); 1201 if (ret) 1202 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); 1208 } 1209 out_unlock: 1210 - read_unlock(&tasklist_lock); 1211 return ret; 1212 } 1213 EXPORT_SYMBOL_GPL(kill_pid_info_as_uid);
··· 218 struct user_struct *user; 219 220 /* 221 + * Protect access to @t credentials. This can go away when all 222 + * callers hold rcu read lock. 223 */ 224 + rcu_read_lock(); 225 user = get_uid(__task_cred(t)->user); 226 atomic_inc(&user->sigpending); 227 + rcu_read_unlock(); 228 229 if (override_rlimit || 230 atomic_read(&user->sigpending) <= ··· 1179 int ret = -EINVAL; 1180 struct task_struct *p; 1181 const struct cred *pcred; 1182 + unsigned long flags; 1183 1184 if (!valid_signal(sig)) 1185 return ret; 1186 1187 + rcu_read_lock(); 1188 p = pid_task(pid, PIDTYPE_PID); 1189 if (!p) { 1190 ret = -ESRCH; ··· 1199 ret = security_task_kill(p, info, sig, secid); 1200 if (ret) 1201 goto out_unlock; 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; 1209 } 1210 out_unlock: 1211 + rcu_read_unlock(); 1212 return ret; 1213 } 1214 EXPORT_SYMBOL_GPL(kill_pid_info_as_uid);
+2
kernel/sys.c
··· 162 if (niceval > 19) 163 niceval = 19; 164 165 read_lock(&tasklist_lock); 166 switch (which) { 167 case PRIO_PROCESS: ··· 200 } 201 out_unlock: 202 read_unlock(&tasklist_lock); 203 out: 204 return error; 205 }
··· 162 if (niceval > 19) 163 niceval = 19; 164 165 + rcu_read_lock(); 166 read_lock(&tasklist_lock); 167 switch (which) { 168 case PRIO_PROCESS: ··· 199 } 200 out_unlock: 201 read_unlock(&tasklist_lock); 202 + rcu_read_unlock(); 203 out: 204 return error; 205 }