Messages in this thread Patch in this message | | | Subject | [PATCH 1/11] oprofile: add check_user_page_readable() | From | Greg Banks <> | Date | Tue, 09 Nov 2004 21:37:16 +1100 |
| |
-- Greg Banks, R&D Software Engineer, SGI Australian Software Group. I don't speak for SGI.
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> ---
include/linux/mm.h | 1 + mm/memory.c | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-)
Index: linux/include/linux/mm.h =================================================================== --- linux.orig/include/linux/mm.h 2004-11-06 01:12:07.%N +1100 +++ linux/include/linux/mm.h 2004-11-07 17:59:40.%N +1100 @@ -789,6 +789,7 @@ extern struct page * vmalloc_to_page(voi extern unsigned long vmalloc_to_pfn(void *addr); extern struct page * follow_page(struct mm_struct *mm, unsigned long address, int write); +extern int check_user_page_readable(struct mm_struct *mm, unsigned long address); int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long, unsigned long, pgprot_t); Index: linux/mm/memory.c =================================================================== --- linux.orig/mm/memory.c 2004-11-06 01:11:57.%N +1100 +++ linux/mm/memory.c 2004-11-07 17:59:40.%N +1100 @@ -746,8 +746,8 @@ void zap_page_range(struct vm_area_struc * 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) { pml4_t *pml4; pgd_t *pgd; @@ -790,6 +790,8 @@ follow_page(struct mm_struct *mm, unsign 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); @@ -804,6 +806,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
| |