Subject: Bug in mmap() for files with holes
To: None <tech-kern@netbsd.org>
From: Thor Lancelot Simon <tls@rek.tjls.com>
List: tech-kern
Date: 11/14/2007 16:57:16
Lots of operating systems, over the years, have had bugs in mmap() such
that, for example, writing a byte into a page notionally backed by a
file that has a hole in it causes a segfault or bus error.

We appear to have such a bug for _reading_ files consisting only of holes;
see the program below.  Modifying the program to write one byte to the
file before the lseek() that extends it causes the segfault to go away.

#include <sys/types.h>
#include <sys/mman.h>

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

int main (int argc, char **argv)
{
	int dfd;
	char bu[32], copybuf[1024];
	void *ret;


	/* Get a temporary file to soak up writes for this stream */
	snprintf(bu, sizeof(bu), "/tmp/divo%d.XXXXXXXX", getpid());
	dfd = mkstemp(bu);
	if (dfd < 0) exit(1);

	/* Remove it from the filesystem: now it's private to us */
	if (unlink(bu)) exit(2);

	/* Extend temporary file to requested length */
	if (lseek(dfd, (off_t)1024, SEEK_SET) != (off_t)1024) exit(3);

	(void)lseek(dfd, (off_t)0, SEEK_SET);

	/* Map it! */
	ret = mmap(NULL, 1024, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
		   dfd, (off_t)0);

	if (ret == MAP_FAILED) exit(4);

	(void)memcpy(copybuf, ret, 1024); 

	exit(0);
}