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--