aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorGreg Banks <gnb@melbourne.sgi.com>2005-01-04 05:41:31 -0800
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-01-04 05:41:31 -0800
commit9a3ed4ef5e77e28427c33745d6317348123714c0 (patch)
treee7592ad02be1112e078038b78167a3c61da5d13e /mm
parent066752a33fe75667a5e0e65b0e1fac8653ba4535 (diff)
downloadhistory-9a3ed4ef5e77e28427c33745d6317348123714c0.tar.gz
[PATCH] oprofile: add check_user_page_readable()
Add check_user_page_readable() for kernel modules which need to follow user space addresses but can't use get_user(). Signed-off-by: John Levon <levon@movementarian.org> Signed-off-by: Greg Banks <gnb@melbourne.sgi.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/memory.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/mm/memory.c b/mm/memory.c
index 58ba5fe6660420..b0c61dac23e6a5 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -747,8 +747,8 @@ void zap_page_range(struct vm_area_struct *vma, unsigned long address,
* Do a quick page-table lookup for a single page.
* mm->page_table_lock must be held.
*/
-struct page *
-follow_page(struct mm_struct *mm, unsigned long address, int write)
+static struct page *
+__follow_page(struct mm_struct *mm, unsigned long address, int read, int write)
{
pgd_t *pgd;
pud_t *pud;
@@ -784,6 +784,8 @@ follow_page(struct mm_struct *mm, unsigned long address, int write)
if (pte_present(pte)) {
if (write && !pte_write(pte))
goto out;
+ if (read && !pte_read(pte))
+ goto out;
pfn = pte_pfn(pte);
if (pfn_valid(pfn)) {
page = pfn_to_page(pfn);
@@ -798,6 +800,20 @@ out:
return NULL;
}
+struct page *
+follow_page(struct mm_struct *mm, unsigned long address, int write)
+{
+ return __follow_page(mm, address, /*read*/0, write);
+}
+
+int
+check_user_page_readable(struct mm_struct *mm, unsigned long address)
+{
+ return __follow_page(mm, address, /*read*/1, /*write*/0) != NULL;
+}
+
+EXPORT_SYMBOL(check_user_page_readable);
+
/*
* Given a physical address, is there a useful struct page pointing to
* it? This may become more complex in the future if we start dealing