From 753eb9378b5def16ed200173c249763d79f030dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Sandmann?= Date: Sat, 23 Apr 2005 21:53:16 +0000 Subject: [PATCH] New function to check if the page is readable before reading. Noop on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sat Apr 23 17:49:33 2005 Søren Sandmann * sysprof-module.c (page_readable): New function to check if the page is readable before reading. Noop on kernel <= 2.6.11 * sysprof-module.c (get_mm, put_mm): New functions to confine #ifdefs. --- ChangeLog | 13 +++++++++ Makefile | 2 +- sysprof-module.c | 75 ++++++++++++++++++++++++++++++++++++------------ 3 files changed, 71 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index 02720a6d..63577bf5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +Sat Apr 23 17:49:33 2005 Søren Sandmann + + * sysprof-module.c (page_readable): New function to check if the + page is readable before reading. Noop on kernel <= 2.6.11 + + * sysprof-module.c (get_mm, put_mm): New functions to confine + #ifdefs. + +Sat Apr 23 17:48:22 2005 Søren Sandmann + + * Makefile (MODCFLAGS): Disable optimization as I suspect + the oops is related to miscompilation. + Fri Apr 22 00:09:16 2005 Soeren Sandmann * sysprof-module.c (read_user_space): On >= 2.6.11 check that the diff --git a/Makefile b/Makefile index 5f7fc2df..d87da903 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ BINARY := sysprof MODULE := sysprof-module KDIR := /lib/modules/$(shell uname -r)/build INCLUDE := -isystem $(KDIR)/include -MODCFLAGS := -O2 -DMODULE -D__KERNEL__ -Wall ${INCLUDE} +MODCFLAGS := -DMODULE -D__KERNEL__ -Wall ${INCLUDE} MODULE := sysprof-module all: check $(BINARY) $(MODULE).o diff --git a/sysprof-module.c b/sysprof-module.c index bef47f40..e899fb38 100644 --- a/sysprof-module.c +++ b/sysprof-module.c @@ -72,29 +72,50 @@ struct userspace_reader * Source/target buffer must be kernel space, * Do not walk the page table directly, use get_user_pages */ - + +static struct mm_struct * +get_mm (struct task_struct *tsk) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) + struct mm_struct *mm; + + task_lock (tsk); + mm = tsk->mm; + task_unlock (tsk); + + return mm; +#else + return get_task_mm (tsk); +#endif +} + +static void +put_mm (struct mm_struct *mm) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) + mmput(mm); +#endif +} + static int -x_access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write) +x_access_process_vm (struct task_struct *tsk, + unsigned long addr, + void *buf, int len, int write) { struct mm_struct *mm; struct vm_area_struct *vma; struct page *page; void *old_buf = buf; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) - task_lock (tsk); - mm = tsk->mm; - task_unlock (tsk); -#else - mm = get_task_mm (tsk); -#endif + mm = get_mm (tsk); if (!mm) return 0; down_read(&mm->mmap_sem); /* ignore errors, just check how much was sucessfully transfered */ - while (len) { + while (len) + { int bytes, ret, offset; void *maddr; @@ -131,9 +152,7 @@ x_access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int } up_read(&mm->mmap_sem); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9) - mmput(mm); -#endif + put_mm (mm); return buf - old_buf; } @@ -150,6 +169,27 @@ init_userspace_reader (userspace_reader *reader, return 1; } +static int +page_readable (userspace_reader *reader, unsigned long address) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION (2,6,11) + struct mm_struct *mm; + int result = 1; + + mm = get_mm (reader->task); + + if (!mm) + return 0; + + if (!check_user_page_readable (reader->task->mm, address)) + result = 0; + + put_mm (mm); + + return result; +#endif +} + static int read_user_space (userspace_reader *reader, unsigned long address, @@ -158,11 +198,10 @@ read_user_space (userspace_reader *reader, unsigned long cache_address = reader->cache_address; int index, r; - if (!cache_address || cache_address != (address & PAGE_MASK)) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION (2,6,11) - if (!check_user_page_readable (reader->task->mm, address)) + if (!cache_address || cache_address != (address & PAGE_MASK)) + { + if (!page_readable (reader, address)) return 0; -#endif cache_address = address & PAGE_MASK; @@ -240,7 +279,7 @@ generate_stack_trace(struct task_struct *task, if (init_userspace_reader (&reader, task)) { while (i < SYSPROF_MAX_ADDRESSES && - read_frame (&reader, addr, &frame) && + read_frame (&reader, addr, &frame) && addr < START_OF_STACK && addr >= regs->esp) { trace->addresses[i++] = (void *)frame.return_address;