Skip to content
  • David Howells's avatar
    nommu: fix shared mmap after truncate shrinkage problems · 7e660872
    David Howells authored
    
    
    Fix a problem in NOMMU mmap with ramfs whereby a shared mmap can happen
    over the end of a truncation.  The problem is that
    ramfs_nommu_check_mappings() checks that the reduced file size against the
    VMA tree, but not the vm_region tree.
    
    The following sequence of events can cause the problem:
    
    	fd = open("/tmp/x", O_RDWR|O_TRUNC|O_CREAT, 0600);
    	ftruncate(fd, 32 * 1024);
    	a = mmap(NULL, 32 * 1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    	b = mmap(NULL, 16 * 1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    	munmap(a, 32 * 1024);
    	ftruncate(fd, 16 * 1024);
    	c = mmap(NULL, 32 * 1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    
    Mapping 'a' creates a vm_region covering 32KB of the file.  Mapping 'b'
    sees that the vm_region from 'a' is covering the region it wants and so
    shares it, pinning it in memory.
    
    Mapping 'a' then goes away and the file is truncated to the end of VMA
    'b'.  However, the region allocated by 'a' is still in effect, and has
    _not_ been reduced.
    
    Mapping 'c' is then created, and because there's a vm_region covering the
    desired region, get_unmapped_area() is _not_ called to repeat the check,
    and the mapping is granted, even though the pages from the latter half of
    the mapping have been discarded.
    
    However:
    
    	d = mmap(NULL, 16 * 1024, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    
    Mapping 'd' should work, and should end up sharing the region allocated by
    'a'.
    
    To deal with this, we shrink the vm_region struct during the truncation,
    lest do_mmap_pgoff() take it as licence to share the full region
    automatically without calling the get_unmapped_area() file op again.
    
    Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
    Acked-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
    Cc: Greg Ungerer <gerg@snapgear.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    7e660872