2.6.10-mm3: lseek broken on /proc/self/maps

From: Jeremy Fitzhardinge
Date: Fri Jan 14 2005 - 16:41:57 EST


lseek doesn't seem to have any effect on /proc/<pid>/maps. It should
either work as expected, or fail.

I've attached a test program which uses a doubling buffer policy to try
to read the whole buffer. If it runs out of buffer, it simply allocates
a new one, lseeks back to the beginning of the buffer, and tries again.
However, the lseek seems to have no effect, because the next read
continues from where the previous one (before the lseek) left off.

Re-opening the file between each attempt works as expected.

$ tm &
$ ./readmap $!
b7dea000-b7deb000 r-xp b7dea000 00:00 0
b7deb000-b7dec000 ---p b7deb000 00:00 0
b7dec000-b7ded000 r-xp b7dec000 00:00 0
b7ded000-b7dee000 ---p b7ded000 00:00 0
b7dee000-b7def000 r-xp b7dee000 00:00 0
b7def000-b7df0000 ---p b7def000 00:00 0
b7df0000-b7df1000 r-xp b7df0000 00:00 0
[...]
$ gcc -o readmap -DREOPEN readmap.c
$ ./readmap $!
08048000-08049000 r-xp 00000000 03:07 3868140 /home/jeremy/tm
08049000-0804a000 rwxp 00000000 03:07 3868140 /home/jeremy/tm
b7ae6000-b7ae7000 r-xp b7ae6000 00:00 0
b7ae7000-b7ae8000 ---p b7ae7000 00:00 0
b7ae8000-b7ae9000 r-xp b7ae8000 00:00 0
b7ae9000-b7aea000 ---p b7ae9000 00:00 0
b7aea000-b7aeb000 r-xp b7aea000 00:00 0
b7aeb000-b7aec000 ---p b7aeb000 00:00 0

J
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#ifndef REOPEN
#define REOPEN 0
#endif

int main(int argc, char **argv)
{
int bufsize = 1024;
char *buf = NULL;
int bufused;
int got;
int fd = -1;
char path[100];

if (argc <= 1)
strcpy(path, "/proc/self/maps");
else
sprintf(path, "/proc/%s/maps", argv[1]);

again:
if (fd == -1)
fd = open(path, O_RDONLY);

if (fd == -1) {
perror("open");
exit(1);
}

if (lseek(fd, 0, SEEK_SET) == -1) {
perror("lseek");
exit(1);
}
bufused = 0;
if (buf == NULL)
buf = malloc(bufsize);

do {
int want = bufsize - bufused;
got = read(fd, &buf[bufused],
want > 4000 ? 4000 : want); /* work around other bug */
if (got < 0) {
perror("read");
exit(1);
}
bufused += got;
} while(bufused < bufsize && got != 0);

if (bufused == bufsize) {
free(buf);
buf = NULL;
bufsize *= 2;
if (REOPEN) {
/* reopen */
close(fd);
fd = -1;
}
goto again;
}
close(fd);

write(1, buf, bufused);

return 0;
}
#include <sys/mman.h>
#include <unistd.h>
int main()
{
int i;
char *m = mmap(0, 1000*4096, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
char *p = m;

for(i = 0; i < 1000; i+=2) {
mprotect(p, 4096, PROT_READ);
p += 8192;
}

pause();

return 0;
}