diff options
| -rw-r--r-- | include/asm-i386/pgtable.h | 1 | ||||
| -rw-r--r-- | mm/memory.c | 40 |
2 files changed, 41 insertions, 0 deletions
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index c2ef3a5479ec..6d7508ca9b4e 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -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; } diff --git a/mm/memory.c b/mm/memory.c index d9b86809380f..8397ea054459 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -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; |
