Commit 3a0d1849 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull core locking updates from Thomas Gleixner.

* 'core-locking-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  futex: Mark get_robust_list as deprecated
  futex: Do not leak robust list to unprivileged process
parents 623ff773 ec0c4274
...@@ -529,3 +529,13 @@ When: 3.5 ...@@ -529,3 +529,13 @@ When: 3.5
Why: The old kmap_atomic() with two arguments is deprecated, we only Why: The old kmap_atomic() with two arguments is deprecated, we only
keep it for backward compatibility for few cycles and then drop it. keep it for backward compatibility for few cycles and then drop it.
Who: Cong Wang <amwang@redhat.com> Who: Cong Wang <amwang@redhat.com>
----------------------------
What: get_robust_list syscall
When: 2013
Why: There appear to be no production users of the get_robust_list syscall,
and it runs the risk of leaking address locations, allowing the bypass
of ASLR. It was only ever intended for debugging, so it should be
removed.
Who: Kees Cook <keescook@chromium.org>
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
#include <linux/magic.h> #include <linux/magic.h>
#include <linux/pid.h> #include <linux/pid.h>
#include <linux/nsproxy.h> #include <linux/nsproxy.h>
#include <linux/ptrace.h>
#include <asm/futex.h> #include <asm/futex.h>
...@@ -2443,40 +2444,31 @@ SYSCALL_DEFINE3(get_robust_list, int, pid, ...@@ -2443,40 +2444,31 @@ SYSCALL_DEFINE3(get_robust_list, int, pid,
{ {
struct robust_list_head __user *head; struct robust_list_head __user *head;
unsigned long ret; unsigned long ret;
const struct cred *cred = current_cred(), *pcred; struct task_struct *p;
if (!futex_cmpxchg_enabled) if (!futex_cmpxchg_enabled)
return -ENOSYS; return -ENOSYS;
WARN_ONCE(1, "deprecated: get_robust_list will be deleted in 2013.\n");
rcu_read_lock();
ret = -ESRCH;
if (!pid) if (!pid)
head = current->robust_list; p = current;
else { else {
struct task_struct *p;
ret = -ESRCH;
rcu_read_lock();
p = find_task_by_vpid(pid); p = find_task_by_vpid(pid);
if (!p) if (!p)
goto err_unlock; goto err_unlock;
ret = -EPERM;
pcred = __task_cred(p);
/* If victim is in different user_ns, then uids are not
comparable, so we must have CAP_SYS_PTRACE */
if (cred->user->user_ns != pcred->user->user_ns) {
if (!ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
goto err_unlock;
goto ok;
}
/* If victim is in same user_ns, then uids are comparable */
if (cred->euid != pcred->euid &&
cred->euid != pcred->uid &&
!ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
goto err_unlock;
ok:
head = p->robust_list;
rcu_read_unlock();
} }
ret = -EPERM;
if (!ptrace_may_access(p, PTRACE_MODE_READ))
goto err_unlock;
head = p->robust_list;
rcu_read_unlock();
if (put_user(sizeof(*head), len_ptr)) if (put_user(sizeof(*head), len_ptr))
return -EFAULT; return -EFAULT;
return put_user(head, head_ptr); return put_user(head, head_ptr);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/nsproxy.h> #include <linux/nsproxy.h>
#include <linux/futex.h> #include <linux/futex.h>
#include <linux/ptrace.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -136,40 +137,31 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, ...@@ -136,40 +137,31 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
{ {
struct compat_robust_list_head __user *head; struct compat_robust_list_head __user *head;
unsigned long ret; unsigned long ret;
const struct cred *cred = current_cred(), *pcred; struct task_struct *p;
if (!futex_cmpxchg_enabled) if (!futex_cmpxchg_enabled)
return -ENOSYS; return -ENOSYS;
WARN_ONCE(1, "deprecated: get_robust_list will be deleted in 2013.\n");
rcu_read_lock();
ret = -ESRCH;
if (!pid) if (!pid)
head = current->compat_robust_list; p = current;
else { else {
struct task_struct *p;
ret = -ESRCH;
rcu_read_lock();
p = find_task_by_vpid(pid); p = find_task_by_vpid(pid);
if (!p) if (!p)
goto err_unlock; goto err_unlock;
ret = -EPERM;
pcred = __task_cred(p);
/* If victim is in different user_ns, then uids are not
comparable, so we must have CAP_SYS_PTRACE */
if (cred->user->user_ns != pcred->user->user_ns) {
if (!ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
goto err_unlock;
goto ok;
}
/* If victim is in same user_ns, then uids are comparable */
if (cred->euid != pcred->euid &&
cred->euid != pcred->uid &&
!ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
goto err_unlock;
ok:
head = p->compat_robust_list;
rcu_read_unlock();
} }
ret = -EPERM;
if (!ptrace_may_access(p, PTRACE_MODE_READ))
goto err_unlock;
head = p->compat_robust_list;
rcu_read_unlock();
if (put_user(sizeof(*head), len_ptr)) if (put_user(sizeof(*head), len_ptr))
return -EFAULT; return -EFAULT;
return put_user(ptr_to_compat(head), head_ptr); return put_user(ptr_to_compat(head), head_ptr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment