

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.


 25-akpm/include/asm-i386/pgtable-2level.h |    2 ++
 25-akpm/mm/fremap.c                       |    8 ++++++++
 2 files changed, 10 insertions(+)

diff -puN mm/fremap.c~fremap-limit-offsets mm/fremap.c
--- 25/mm/fremap.c~fremap-limit-offsets	Wed Mar 12 15:10:22 2003
+++ 25-akpm/mm/fremap.c	Wed Mar 12 15:59:12 2003
@@ -129,6 +129,14 @@ 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 (pgoff + (size >> PAGE_SHIFT) >= (1UL << PTE_FILE_MAX_BITS))
+		return err;
+
 	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	Wed Mar 12 15:39:41 2003
+++ 25-akpm/include/asm-i386/pgtable-2level.h	Wed Mar 12 15:39:58 2003
@@ -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 ))
 

_
