aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds2017-08-20 15:26:27 -0500
committerGreg Kroah-Hartman2017-08-24 19:02:36 -0500
commit46d51a26efbc7cbaa2bc1f01628a00a604193856 (patch)
tree163d4816a41b4fea4752d667b1c08c0e43df1239
parentb27e9ff9a5f457e85c47733387426bf522cef2aa (diff)
downloadkernel-omap-46d51a26efbc7cbaa2bc1f01628a00a604193856.tar.gz
kernel-omap-46d51a26efbc7cbaa2bc1f01628a00a604193856.tar.xz
kernel-omap-46d51a26efbc7cbaa2bc1f01628a00a604193856.zip
Sanitize 'move_pages()' permission checks
commit 197e7e521384a23b9e585178f3f11c9fa08274b9 upstream. The 'move_paghes()' system call was introduced long long ago with the same permission checks as for sending a signal (except using CAP_SYS_NICE instead of CAP_SYS_KILL for the overriding capability). That turns out to not be a great choice - while the system call really only moves physical page allocations around (and you need other capabilities to do a lot of it), you can check the return value to map out some the virtual address choices and defeat ASLR of a binary that still shares your uid. So change the access checks to the more common 'ptrace_may_access()' model instead. This tightens the access checks for the uid, and also effectively changes the CAP_SYS_NICE check to CAP_SYS_PTRACE, but it's unlikely that anybody really _uses_ this legacy system call any more (we hav ebetter NUMA placement models these days), so I expect nobody to notice. Famous last words. Reported-by: Otto Ebeling <otto.ebeling@iki.fi> Acked-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Willy Tarreau <w@1wt.eu> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--mm/migrate.c11
1 files changed, 3 insertions, 8 deletions
diff --git a/mm/migrate.c b/mm/migrate.c
index 72c09dea6526..afedcfab60e2 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -38,6 +38,7 @@
38#include <linux/balloon_compaction.h> 38#include <linux/balloon_compaction.h>
39#include <linux/mmu_notifier.h> 39#include <linux/mmu_notifier.h>
40#include <linux/page_idle.h> 40#include <linux/page_idle.h>
41#include <linux/ptrace.h>
41 42
42#include <asm/tlbflush.h> 43#include <asm/tlbflush.h>
43 44
@@ -1483,7 +1484,6 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages,
1483 const int __user *, nodes, 1484 const int __user *, nodes,
1484 int __user *, status, int, flags) 1485 int __user *, status, int, flags)
1485{ 1486{
1486 const struct cred *cred = current_cred(), *tcred;
1487 struct task_struct *task; 1487 struct task_struct *task;
1488 struct mm_struct *mm; 1488 struct mm_struct *mm;
1489 int err; 1489 int err;
@@ -1507,14 +1507,9 @@ SYSCALL_DEFINE6(move_pages, pid_t, pid, unsigned long, nr_pages,
1507 1507
1508 /* 1508 /*
1509 * Check if this process has the right to modify the specified 1509 * Check if this process has the right to modify the specified
1510 * process. The right exists if the process has administrative 1510 * process. Use the regular "ptrace_may_access()" checks.
1511 * capabilities, superuser privileges or the same
1512 * userid as the target process.
1513 */ 1511 */
1514 tcred = __task_cred(task); 1512 if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS)) {
1515 if (!uid_eq(cred->euid, tcred->suid) && !uid_eq(cred->euid, tcred->uid) &&
1516 !uid_eq(cred->uid, tcred->suid) && !uid_eq(cred->uid, tcred->uid) &&
1517 !capable(CAP_SYS_NICE)) {
1518 rcu_read_unlock(); 1513 rcu_read_unlock();
1519 err = -EPERM; 1514 err = -EPERM;
1520 goto out; 1515 goto out;