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
This commit is contained in:
Linus Torvalds 2012-03-30 18:07:13 -07:00
Родитель 623ff7739e ec0c4274e3
Коммит 3a0d184943
3 изменённых файлов: 42 добавлений и 48 удалений

Просмотреть файл

@ -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 @@
#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,
{ {
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;
if (!pid) WARN_ONCE(1, "deprecated: get_robust_list will be deleted in 2013.\n");
head = current->robust_list;
else {
struct task_struct *p;
ret = -ESRCH; rcu_read_lock();
rcu_read_lock();
ret = -ESRCH;
if (!pid)
p = current;
else {
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 @@
#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,
{ {
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;
if (!pid) WARN_ONCE(1, "deprecated: get_robust_list will be deleted in 2013.\n");
head = current->compat_robust_list;
else {
struct task_struct *p;
ret = -ESRCH; rcu_read_lock();
rcu_read_lock();
ret = -ESRCH;
if (!pid)
p = current;
else {
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);