]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] allow ptrace and /proc/PID/mem to read fixmap pages
authorRoland McGrath <roland@redhat.com>
Sat, 3 May 2003 11:50:19 +0000 (04:50 -0700)
committerLinus Torvalds <torvalds@home.transmeta.com>
Sat, 3 May 2003 11:50:19 +0000 (04:50 -0700)
This allows access to the globally shared FIXMAP mapping for ptrace
and frieds, so that debuggers can sanely trace through the vsyscall
sequence.

include/asm-i386/pgtable.h
mm/memory.c

index c2ef3a5479ecafb5c0078a729275f0beac99ff77..6d7508ca9b4e1e1c930ed02999e5df6ad83228de 100644 (file)
@@ -192,6 +192,7 @@ extern unsigned long pg0[1024];
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
  */
+static inline int pte_user(pte_t pte)          { return (pte).pte_low & _PAGE_USER; }
 static inline int pte_read(pte_t pte)          { return (pte).pte_low & _PAGE_USER; }
 static inline int pte_exec(pte_t pte)          { return (pte).pte_low & _PAGE_USER; }
 static inline int pte_dirty(pte_t pte)         { return (pte).pte_low & _PAGE_DIRTY; }
index d9b86809380f2376b975991db597a758008bc406..8397ea05445989ff7ce47de97ad179258459f07d 100644 (file)
@@ -51,6 +51,7 @@
 #include <asm/uaccess.h>
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
+#include <asm/pgtable.h>
 
 #include <linux/swapops.h>
 
@@ -688,6 +689,45 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 
                vma = find_extend_vma(mm, start);
 
+#ifdef FIXADDR_START
+               if (!vma && start >= FIXADDR_START && start < FIXADDR_TOP) {
+                       static struct vm_area_struct fixmap_vma = {
+                               /* Catch users - if there are any valid
+                                  ones, we can make this be "&init_mm" or
+                                  something.  */
+                               .vm_mm = NULL,
+                               .vm_start = FIXADDR_START,
+                               .vm_end = FIXADDR_TOP,
+                               .vm_page_prot = PAGE_READONLY,
+                               .vm_flags = VM_READ | VM_EXEC,
+                       };
+                       unsigned long pg = start & PAGE_MASK;
+                       pgd_t *pgd;
+                       pmd_t *pmd;
+                       pte_t *pte;
+                       pgd = pgd_offset_k(pg);
+                       if (!pgd)
+                               return i ? : -EFAULT;
+                       pmd = pmd_offset(pgd, pg);
+                       if (!pmd)
+                               return i ? : -EFAULT;
+                       pte = pte_offset_kernel(pmd, pg);
+                       if (!pte || !pte_present(*pte) || !pte_user(*pte) ||
+                           !(write ? pte_write(*pte) : pte_read(*pte)))
+                               return i ? : -EFAULT;
+                       if (pages) {
+                               pages[i] = pte_page(*pte);
+                               get_page(pages[i]);
+                       }
+                       if (vmas)
+                               vmas[i] = &fixmap_vma;
+                       i++;
+                       start += PAGE_SIZE;
+                       len--;
+                       continue;
+               }
+#endif
+
                if (!vma || (pages && (vma->vm_flags & VM_IO))
                                || !(flags & vma->vm_flags))
                        return i ? : -EFAULT;