When a nonlinear mapping's page is unmapped, its file offset is placed into the user's pte. As this can only hold (say) 29 bits, this places a per-arch upper bound on the file offsets which can be nonlinearly mapped. The patch enforces those offsets at remap_file_pages() time. It also adds additional checking on the remap_file_pages() incoming address range. Last time I looked, these checks aren't actually necessary, but it's clearer to do this up-front. include/asm-i386/pgtable-2level.h | 2 ++ include/asm-i386/pgtable-3level.h | 1 + mm/fremap.c | 10 ++++++++++ 3 files changed, 13 insertions(+) diff -puN mm/fremap.c~fremap-limit-offsets mm/fremap.c --- 25/mm/fremap.c~fremap-limit-offsets 2003-03-13 20:17:53.000000000 -0800 +++ 25-akpm/mm/fremap.c 2003-03-13 20:46:51.000000000 -0800 @@ -129,6 +129,16 @@ int sys_remap_file_pages(unsigned long s start = start & PAGE_MASK; size = size & PAGE_MASK; + /* Does the address range wrap, or is the span zero-sized? */ + if (start + size <= start) + return err; + + /* Can we represent this offset inside this architecture's pte's? */ +#if PTE_FILE_MAX_BITS < BITS_PER_LONG + if (pgoff + (size >> PAGE_SHIFT) >= (1UL << PTE_FILE_MAX_BITS)) + return err; +#endif + down_read(&mm->mmap_sem); vma = find_vma(mm, start); diff -puN include/asm-i386/pgtable-2level.h~fremap-limit-offsets include/asm-i386/pgtable-2level.h --- 25/include/asm-i386/pgtable-2level.h~fremap-limit-offsets 2003-03-13 20:17:53.000000000 -0800 +++ 25-akpm/include/asm-i386/pgtable-2level.h 2003-03-13 20:17:53.000000000 -0800 @@ -67,6 +67,8 @@ static inline pmd_t * pmd_offset(pgd_t * * Bits 0, 6 and 7 are taken, split up the 29 bits of offset * into this range: */ +#define PTE_FILE_MAX_BITS 29 + #define pte_to_pgoff(pte) \ ((((pte).pte_low >> 1) & 0x1f ) + (((pte).pte_low >> 8) << 5 )) diff -puN include/asm-i386/pgtable-3level.h~fremap-limit-offsets include/asm-i386/pgtable-3level.h --- 25/include/asm-i386/pgtable-3level.h~fremap-limit-offsets 2003-03-13 20:18:38.000000000 -0800 +++ 25-akpm/include/asm-i386/pgtable-3level.h 2003-03-13 20:19:02.000000000 -0800 @@ -121,5 +121,6 @@ static inline pmd_t pfn_pmd(unsigned lon */ #define pte_to_pgoff(pte) ((pte).pte_high) #define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) }) +#define PTE_FILE_MAX_BITS 32 #endif /* _I386_PGTABLE_3LEVEL_H */ _