lkml.org 
[lkml]   [2008]   [Aug]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] /proc/self/maps doesn't display the real file offset
2.6.26 kernel on i386 platform.

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 show 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;
}

Signed-off-by: Clement Calmels <cboulte@gmail.com>
---
fs/proc/nommu.c | 4 ++--
fs/proc/task_mmu.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)

Index: linux-2.6.26/fs/proc/task_mmu.c
===================================================================
--- linux-2.6.26.orig/fs/proc/task_mmu.c
+++ linux-2.6.26/fs/proc/task_mmu.c
@@ -219,14 +219,14 @@ static int show_map(struct seq_file *m,
ino = inode->i_ino;
}

- seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n",
+ seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
vma->vm_start,
vma->vm_end,
flags & VM_READ ? 'r' : '-',
flags & VM_WRITE ? 'w' : '-',
flags & VM_EXEC ? 'x' : '-',
flags & VM_MAYSHARE ? 's' : 'p',
- vma->vm_pgoff << PAGE_SHIFT,
+ ((loff_t) vma->vm_pgoff) << PAGE_SHIFT,
MAJOR(dev), MINOR(dev), ino, &len);

/*
Index: linux-2.6.26/fs/proc/nommu.c
===================================================================
--- linux-2.6.26.orig/fs/proc/nommu.c
+++ linux-2.6.26/fs/proc/nommu.c
@@ -52,14 +52,14 @@ int nommu_vma_show(struct seq_file *m, s
}

seq_printf(m,
- "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n",
+ "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
vma->vm_start,
vma->vm_end,
flags & VM_READ ? 'r' : '-',
flags & VM_WRITE ? 'w' : '-',
flags & VM_EXEC ? 'x' : '-',
flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p',
- vma->vm_pgoff << PAGE_SHIFT,
+ ((loff_t)vma->vm_pgoff) << PAGE_SHIFT,
MAJOR(dev), MINOR(dev), ino, &len);

if (file) {

\
 
 \ /
  Last update: 2008-08-13 19:59    [W:0.030 / U:0.484 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site