Subject: Re: Bug in mmap() for files with holes
To: Thor Lancelot Simon <tls@rek.tjls.com>
From: Bill Stouder-Studenmund <wrstuden@netbsd.org>
List: tech-kern
Date: 11/14/2007 14:21:45
--fKov5AqTsvseSZ0Z
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Wed, Nov 14, 2007 at 04:57:16PM -0500, Thor Lancelot Simon wrote:
> 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.
>=20
> 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.

Where do you explicitly grow the file? lseek() alone won't change the file=
=20
length. It is legal to lseek() past EOF.

I think what you want to throw in is an ftruncate().

Take care,

Bill

> #include <sys/types.h>
> #include <sys/mman.h>
>=20
> #include <unistd.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>=20
> int main (int argc, char **argv)
> {
> 	int dfd;
> 	char bu[32], copybuf[1024];
> 	void *ret;
>=20
>=20
> 	/* Get a temporary file to soak up writes for this stream */
> 	snprintf(bu, sizeof(bu), "/tmp/divo%d.XXXXXXXX", getpid());
> 	dfd =3D mkstemp(bu);
> 	if (dfd < 0) exit(1);
>=20
> 	/* Remove it from the filesystem: now it's private to us */
> 	if (unlink(bu)) exit(2);
>=20
> 	/* Extend temporary file to requested length */
> 	if (lseek(dfd, (off_t)1024, SEEK_SET) !=3D (off_t)1024) exit(3);
>=20
> 	(void)lseek(dfd, (off_t)0, SEEK_SET);
>=20
> 	/* Map it! */
> 	ret =3D mmap(NULL, 1024, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
> 		   dfd, (off_t)0);
>=20
> 	if (ret =3D=3D MAP_FAILED) exit(4);
>=20
> 	(void)memcpy(copybuf, ret, 1024);=20
>=20
> 	exit(0);
> }

--fKov5AqTsvseSZ0Z
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (NetBSD)

iD8DBQFHO3T5Wz+3JHUci9cRAvsYAKCYI1eXN7ShnY5Ar3pm9KBZob8EvACfa6L/
kdkXsMlvbx2FtavrKzbZW8U=
=ba0C
-----END PGP SIGNATURE-----

--fKov5AqTsvseSZ0Z--