This prevents an attacker from determining the robust_list or compat_robust_list userspace pointer of a process created by executing a setuid binary. Such an attack could be performed by racing get_robust_list() with a setuid execution. The impact of this issue is that an attacker could theoretically bypass ASLR when attacking setuid binaries. changed in v2: - only get_task_struct(p) if p!=NULL (Ben Hutchings) - move the -ESRCH return check Signed-off-by: Jann Horn <jann@xxxxxxxxx> --- kernel/futex.c | 30 +++++++++++++++++++++--------- kernel/futex_compat.c | 30 +++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 18 deletions(-) diff --git a/kernel/futex.c b/kernel/futex.c index 2c4be467fecd..f0697e0d55b8 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -3016,31 +3016,43 @@ SYSCALL_DEFINE3(get_robust_list, int, pid, if (!futex_cmpxchg_enabled) return -ENOSYS; - rcu_read_lock(); - - ret = -ESRCH; - if (!pid) + if (!pid) { p = current; - else { + get_task_struct(p); + } else { + rcu_read_lock(); p = find_task_by_vpid(pid); + /* pin the task to permit dropping the RCU read lock before + * acquiring the mutex + */ + if (p) + get_task_struct(p); + rcu_read_unlock(); if (!p) - goto err_unlock; + return -ESRCH; } + ret = mutex_lock_killable(&p->signal->cred_guard_light); + if (ret) + goto err_put; + ret = -EPERM; if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS)) goto err_unlock; head = p->robust_list; - rcu_read_unlock(); + + mutex_unlock(&p->signal->cred_guard_light); + put_task_struct(p); if (put_user(sizeof(*head), len_ptr)) return -EFAULT; return put_user(head, head_ptr); err_unlock: - rcu_read_unlock(); - + mutex_unlock(¤t->signal->cred_guard_light); +err_put: + put_task_struct(p); return ret; } diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c index 4ae3232e7a28..92c350f05ff8 100644 --- a/kernel/futex_compat.c +++ b/kernel/futex_compat.c @@ -143,31 +143,43 @@ COMPAT_SYSCALL_DEFINE3(get_robust_list, int, pid, if (!futex_cmpxchg_enabled) return -ENOSYS; - rcu_read_lock(); - - ret = -ESRCH; - if (!pid) + if (!pid) { p = current; - else { + get_task_struct(p); + } else { + rcu_read_lock(); p = find_task_by_vpid(pid); + /* pin the task to permit dropping the RCU read lock before + * acquiring the mutex + */ + if (p) + get_task_struct(p); + rcu_read_unlock(); if (!p) - goto err_unlock; + return -ESRCH; } + ret = mutex_lock_killable(&p->signal->cred_guard_light); + if (ret) + goto err_put; + ret = -EPERM; if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS)) goto err_unlock; head = p->compat_robust_list; - rcu_read_unlock(); + + mutex_unlock(&p->signal->cred_guard_light); + put_task_struct(p); if (put_user(sizeof(*head), len_ptr)) return -EFAULT; return put_user(ptr_to_compat(head), head_ptr); err_unlock: - rcu_read_unlock(); - + mutex_unlock(¤t->signal->cred_guard_light); +err_put: + put_task_struct(p); return ret; } -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html