Skip to content
  • Clement Calmels's avatar
    /proc/self/maps doesn't display the real file offset · 1804dc6e
    Clement Calmels authored
    This addresses
    
    	http://bugzilla.kernel.org/show_bug.cgi?id=11318
    
    
    
    In function show_map (file: fs/proc/task_mmu.c), if vma->vm_pgoff > 2^20
    than (vma->vm_pgoff << PAGE_SIZE) is greater than 2^32 (with PAGE_SIZE
    equal to 4096 (i.e.  2^12).  The next seq_printf use an unsigned long for
    the conversion of (vma->vm_pgoff << PAGE_SIZE), as a result the offset
    value displayed in /proc/self/maps is truncated if the page offset is
    greater than 2^20.
    
    A test that shows this issue:
    
    #define _GNU_SOURCE
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/mman.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <string.h>
    
    #define PAGE_SIZE (getpagesize())
    
    #if __i386__
    #   define U64_STR "%llx"
    #elif __x86_64
    #   define U64_STR "%lx"
    #else
    #   error "Architecture Unsupported"
    #endif
    
    int main(int argc, char *argv[])
    {
    	int fd;
    	char *addr;
    	off64_t offset = 0x10000000;
    	char *filename = "/dev/zero";
    
    	fd = open(filename, O_RDONLY);
    	if (fd < 0) {
    		perror("open");
    		return 1;
    	}
    
    	offset *= 0x10;
    	printf("offset = " U64_STR "\n", offset);
    
    	addr = (char*)mmap64(NULL, PAGE_SIZE, PROT_READ, MAP_PRIVATE, fd,
    			     offset);
    	if ((void*)addr == MAP_FAILED) {
    		perror("mmap64");
    		return 1;
    	}
    
    	{
    		FILE *fmaps;
    		char *line = NULL;
    		size_t len = 0;
    		ssize_t read;
    		size_t filename_len = strlen(filename);
    
    		fmaps = fopen("/proc/self/maps", "r");
    		if (!fmaps) {
    			perror("fopen");
    			return 1;
    		}
    		while ((read = getline(&line, &len, fmaps)) != -1) {
    			if ((read > filename_len + 1)
    			    && (strncmp(&line[read - filename_len - 1], filename, filename_len) == 0))
    				printf("%s", line);
    		}
    
    		if (line)
    			free(line);
    
    		fclose(fmaps);
    	}
    
    	close(fd);
    	return 0;
    }
    
    [akpm@linux-foundation.org: coding-style fixes]
    Signed-off-by: default avatarClement Calmels <cboulte@gmail.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    1804dc6e