From: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> To: linux-mm@kvack.org, Andrew Morton <akpm@linux-foundation.org>, Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Cc: "Kirill A. Shutemov" <kirill@shutemov.name>, Mark Williamson <mwilliamson@undo-software.com>, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v4 1/5] pagemap: check permissions and capabilities at open time Date: Tue, 14 Jul 2015 18:37:35 +0300 [thread overview] Message-ID: <20150714153735.29844.38428.stgit@buzz> (raw) In-Reply-To: <20150714152516.29844.69929.stgit@buzz> This patch moves permission checks from pagemap_read() into pagemap_open(). Pointer to mm is saved in file->private_data. This reference pins only mm_struct itself. /proc/*/mem, maps, smaps already work in the same way. Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> Link: http://lkml.kernel.org/r/CA+55aFyKpWrt_Ajzh1rzp_GcwZ4=6Y=kOv8hBz172CFJp6L8Tg@mail.gmail.com --- fs/proc/task_mmu.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index ca1e091881d4..270bf7cbc8a5 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -1227,40 +1227,33 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask, static ssize_t pagemap_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct task_struct *task = get_proc_task(file_inode(file)); - struct mm_struct *mm; + struct mm_struct *mm = file->private_data; struct pagemapread pm; - int ret = -ESRCH; struct mm_walk pagemap_walk = {}; unsigned long src; unsigned long svpfn; unsigned long start_vaddr; unsigned long end_vaddr; - int copied = 0; + int ret = 0, copied = 0; - if (!task) + if (!mm || !atomic_inc_not_zero(&mm->mm_users)) goto out; ret = -EINVAL; /* file position must be aligned */ if ((*ppos % PM_ENTRY_BYTES) || (count % PM_ENTRY_BYTES)) - goto out_task; + goto out_mm; ret = 0; if (!count) - goto out_task; + goto out_mm; pm.v2 = soft_dirty_cleared; pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_TEMPORARY); ret = -ENOMEM; if (!pm.buffer) - goto out_task; - - mm = mm_access(task, PTRACE_MODE_READ); - ret = PTR_ERR(mm); - if (!mm || IS_ERR(mm)) - goto out_free; + goto out_mm; pagemap_walk.pmd_entry = pagemap_pte_range; pagemap_walk.pte_hole = pagemap_pte_hole; @@ -1273,10 +1266,10 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, src = *ppos; svpfn = src / PM_ENTRY_BYTES; start_vaddr = svpfn << PAGE_SHIFT; - end_vaddr = TASK_SIZE_OF(task); + end_vaddr = mm->task_size; /* watch out for wraparound */ - if (svpfn > TASK_SIZE_OF(task) >> PAGE_SHIFT) + if (svpfn > mm->task_size >> PAGE_SHIFT) start_vaddr = end_vaddr; /* @@ -1303,7 +1296,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, len = min(count, PM_ENTRY_BYTES * pm.pos); if (copy_to_user(buf, pm.buffer, len)) { ret = -EFAULT; - goto out_mm; + goto out_free; } copied += len; buf += len; @@ -1313,24 +1306,38 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, if (!ret || ret == PM_END_OF_BUFFER) ret = copied; -out_mm: - mmput(mm); out_free: kfree(pm.buffer); -out_task: - put_task_struct(task); +out_mm: + mmput(mm); out: return ret; } static int pagemap_open(struct inode *inode, struct file *file) { + struct mm_struct *mm; + /* do not disclose physical addresses: attack vector */ if (!capable(CAP_SYS_ADMIN)) return -EPERM; pr_warn_once("Bits 55-60 of /proc/PID/pagemap entries are about " "to stop being page-shift some time soon. See the " "linux/Documentation/vm/pagemap.txt for details.\n"); + + mm = proc_mem_open(inode, PTRACE_MODE_READ); + if (IS_ERR(mm)) + return PTR_ERR(mm); + file->private_data = mm; + return 0; +} + +static int pagemap_release(struct inode *inode, struct file *file) +{ + struct mm_struct *mm = file->private_data; + + if (mm) + mmdrop(mm); return 0; } @@ -1338,6 +1345,7 @@ const struct file_operations proc_pagemap_operations = { .llseek = mem_lseek, /* borrow this */ .read = pagemap_read, .open = pagemap_open, + .release = pagemap_release, }; #endif /* CONFIG_PROC_PAGE_MONITOR */
WARNING: multiple messages have this Message-ID (diff)
From: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> To: linux-mm@kvack.org, Andrew Morton <akpm@linux-foundation.org>, Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Cc: "Kirill A. Shutemov" <kirill@shutemov.name>, Mark Williamson <mwilliamson@undo-software.com>, linux-kernel@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v4 1/5] pagemap: check permissions and capabilities at open time Date: Tue, 14 Jul 2015 18:37:35 +0300 [thread overview] Message-ID: <20150714153735.29844.38428.stgit@buzz> (raw) In-Reply-To: <20150714152516.29844.69929.stgit@buzz> This patch moves permission checks from pagemap_read() into pagemap_open(). Pointer to mm is saved in file->private_data. This reference pins only mm_struct itself. /proc/*/mem, maps, smaps already work in the same way. Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> Link: http://lkml.kernel.org/r/CA+55aFyKpWrt_Ajzh1rzp_GcwZ4=6Y=kOv8hBz172CFJp6L8Tg@mail.gmail.com --- fs/proc/task_mmu.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index ca1e091881d4..270bf7cbc8a5 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -1227,40 +1227,33 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask, static ssize_t pagemap_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - struct task_struct *task = get_proc_task(file_inode(file)); - struct mm_struct *mm; + struct mm_struct *mm = file->private_data; struct pagemapread pm; - int ret = -ESRCH; struct mm_walk pagemap_walk = {}; unsigned long src; unsigned long svpfn; unsigned long start_vaddr; unsigned long end_vaddr; - int copied = 0; + int ret = 0, copied = 0; - if (!task) + if (!mm || !atomic_inc_not_zero(&mm->mm_users)) goto out; ret = -EINVAL; /* file position must be aligned */ if ((*ppos % PM_ENTRY_BYTES) || (count % PM_ENTRY_BYTES)) - goto out_task; + goto out_mm; ret = 0; if (!count) - goto out_task; + goto out_mm; pm.v2 = soft_dirty_cleared; pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_TEMPORARY); ret = -ENOMEM; if (!pm.buffer) - goto out_task; - - mm = mm_access(task, PTRACE_MODE_READ); - ret = PTR_ERR(mm); - if (!mm || IS_ERR(mm)) - goto out_free; + goto out_mm; pagemap_walk.pmd_entry = pagemap_pte_range; pagemap_walk.pte_hole = pagemap_pte_hole; @@ -1273,10 +1266,10 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, src = *ppos; svpfn = src / PM_ENTRY_BYTES; start_vaddr = svpfn << PAGE_SHIFT; - end_vaddr = TASK_SIZE_OF(task); + end_vaddr = mm->task_size; /* watch out for wraparound */ - if (svpfn > TASK_SIZE_OF(task) >> PAGE_SHIFT) + if (svpfn > mm->task_size >> PAGE_SHIFT) start_vaddr = end_vaddr; /* @@ -1303,7 +1296,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, len = min(count, PM_ENTRY_BYTES * pm.pos); if (copy_to_user(buf, pm.buffer, len)) { ret = -EFAULT; - goto out_mm; + goto out_free; } copied += len; buf += len; @@ -1313,24 +1306,38 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, if (!ret || ret == PM_END_OF_BUFFER) ret = copied; -out_mm: - mmput(mm); out_free: kfree(pm.buffer); -out_task: - put_task_struct(task); +out_mm: + mmput(mm); out: return ret; } static int pagemap_open(struct inode *inode, struct file *file) { + struct mm_struct *mm; + /* do not disclose physical addresses: attack vector */ if (!capable(CAP_SYS_ADMIN)) return -EPERM; pr_warn_once("Bits 55-60 of /proc/PID/pagemap entries are about " "to stop being page-shift some time soon. See the " "linux/Documentation/vm/pagemap.txt for details.\n"); + + mm = proc_mem_open(inode, PTRACE_MODE_READ); + if (IS_ERR(mm)) + return PTR_ERR(mm); + file->private_data = mm; + return 0; +} + +static int pagemap_release(struct inode *inode, struct file *file) +{ + struct mm_struct *mm = file->private_data; + + if (mm) + mmdrop(mm); return 0; } @@ -1338,6 +1345,7 @@ const struct file_operations proc_pagemap_operations = { .llseek = mem_lseek, /* borrow this */ .read = pagemap_read, .open = pagemap_open, + .release = pagemap_release, }; #endif /* CONFIG_PROC_PAGE_MONITOR */ -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
next prev parent reply other threads:[~2015-07-14 15:39 UTC|newest] Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top 2015-07-14 15:37 [PATCHSET v4 0/5] pagemap: make useable for non-privilege users Konstantin Khlebnikov 2015-07-14 15:37 ` Konstantin Khlebnikov 2015-07-14 15:37 ` Konstantin Khlebnikov [this message] 2015-07-14 15:37 ` [PATCH v4 1/5] pagemap: check permissions and capabilities at open time Konstantin Khlebnikov 2015-07-21 8:06 ` Naoya Horiguchi 2015-07-21 8:06 ` Naoya Horiguchi 2015-07-24 18:16 ` Mark Williamson 2015-07-24 18:16 ` Mark Williamson 2015-07-24 18:16 ` Mark Williamson 2015-07-14 15:37 ` [PATCH v4 2/5] pagemap: switch to the new format and do some cleanup Konstantin Khlebnikov 2015-07-14 15:37 ` Konstantin Khlebnikov 2015-07-21 7:44 ` Naoya Horiguchi 2015-07-21 7:44 ` Naoya Horiguchi 2015-07-14 15:37 ` [PATCH v4 3/5] pagemap: rework hugetlb and thp report Konstantin Khlebnikov 2015-07-14 15:37 ` Konstantin Khlebnikov 2015-07-19 11:10 ` Kirill A. Shutemov 2015-07-19 11:10 ` Kirill A. Shutemov 2015-07-21 8:00 ` Naoya Horiguchi 2015-07-21 8:00 ` Naoya Horiguchi 2015-07-21 8:43 ` Konstantin Khlebnikov 2015-07-21 8:43 ` Konstantin Khlebnikov 2015-07-24 18:17 ` Mark Williamson 2015-07-24 18:17 ` Mark Williamson 2015-07-24 18:17 ` Mark Williamson 2015-07-24 18:19 ` Mark Williamson 2015-07-24 18:19 ` Mark Williamson 2015-07-14 15:37 ` [PATCH v4 4/5] pagemap: hide physical addresses from non-privileged users Konstantin Khlebnikov 2015-07-14 15:37 ` Konstantin Khlebnikov 2015-07-21 8:11 ` Naoya Horiguchi 2015-07-21 8:11 ` Naoya Horiguchi 2015-07-21 8:39 ` Konstantin Khlebnikov 2015-07-21 8:39 ` Konstantin Khlebnikov 2015-07-24 18:18 ` Mark Williamson 2015-07-24 18:18 ` Mark Williamson 2015-07-14 15:37 ` [PATCH v4 5/5] pagemap: add mmap-exclusive bit for marking pages mapped only here Konstantin Khlebnikov 2015-07-14 15:37 ` Konstantin Khlebnikov 2015-07-21 8:17 ` Naoya Horiguchi 2015-07-21 8:17 ` Naoya Horiguchi 2015-07-21 8:17 ` Naoya Horiguchi 2015-07-24 18:18 ` Mark Williamson 2015-07-24 18:18 ` Mark Williamson 2015-07-14 18:52 ` [PATCHSET v4 0/5] pagemap: make useable for non-privilege users Andrew Morton 2015-07-14 18:52 ` Andrew Morton 2015-07-14 18:52 ` Andrew Morton 2015-07-14 20:15 ` Konstantin Khlebnikov 2015-07-14 20:15 ` Konstantin Khlebnikov 2015-07-14 20:15 ` Konstantin Khlebnikov 2015-07-16 18:47 ` [PATCH] pagemap: update documentation Konstantin Khlebnikov 2015-07-16 18:47 ` Konstantin Khlebnikov 2015-07-16 18:47 ` Konstantin Khlebnikov 2015-07-21 8:35 ` Naoya Horiguchi 2015-07-21 8:35 ` Naoya Horiguchi 2015-07-24 17:34 ` [PATCHSET v4 0/5] pagemap: make useable for non-privilege users Mark Williamson 2015-07-24 17:34 ` Mark Williamson 2015-07-24 17:34 ` Mark Williamson
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20150714153735.29844.38428.stgit@buzz \ --to=khlebnikov@yandex-team.ru \ --cc=akpm@linux-foundation.org \ --cc=kirill@shutemov.name \ --cc=linux-api@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-mm@kvack.org \ --cc=mwilliamson@undo-software.com \ --cc=n-horiguchi@ah.jp.nec.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.