Subject: bin/11247: mmap maps only part of file
To: None <gnats-bugs@gnats.netbsd.org>
From: Havard Eidnes <he@runit.no>
List: netbsd-bugs
Date: 10/17/2000 04:33:19
>Number:         11247
>Category:       bin
>Synopsis:       mmap maps only part of file
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Oct 17 04:33:00 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Havard Eidnes
>Release:        NetBSD-current Oct 14 2000
>Organization:
	RUNIT AS
>Environment:
	NetBSD pt.runit.no 1.5H NetBSD 1.5H (PT) #5: Mon Oct 16 22:13:39 CEST 2000     he@pt.runit.no:/usr/src/sys/arch/i386/compile/PT i386
System: NetBSD pt.runit.no 1.5H NetBSD 1.5H (PT) #5: Mon Oct 16 22:13:39 CEST 2000     he@pt.runit.no:/usr/src/sys/arch/i386/compile/PT i386

>Description:

I'm currently in the middle of a source-based update of a machine from
1.5_ALPHA2 to NetBSD-current (1.5H) as of a couple of days ago.
However, both the old installed tail and the newly compiled one (after
"make includes" and the new libraries have been installed) both
exhibit the problem.

Running "tail -f" or simply "tail" on a moderately large file causes a
segmentation fault.  The reason appears to be that the mmap() call of
the file in rlines() only maps *parts* of the file, contrary to what
is being asked for.

The following GDB session demonstrates the problem, and why I don't
see this as a simple user-land bug:


pt# gdb obj/tail
GNU gdb 4.17
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386--netbsd"...
(gdb) run -f /usr/src/list.1
Starting program: /usr/src/usr.bin/tail/obj/tail -f /usr/src/list.1

Program received signal SIGSEGV, Segmentation fault.
0x804949a in rlines (fp=0x480f3200, off=10, sbp=0xbfbfd69c)
    at /usr/src/usr.bin/tail/forward.c:272
272                     if (*--p == '\n' && !--off) {
(gdb) where
#0  0x804949a in rlines (fp=0x480f3200, off=10, sbp=0xbfbfd69c)
    at /usr/src/usr.bin/tail/forward.c:272
#1  0x8049105 in forward (fp=0x480f3200, style=RLINES, off=10, sbp=0xbfbfd69c)
    at /usr/src/usr.bin/tail/forward.c:165
#2  0x804a981 in main (argc=1, argv=0xbfbfd750)
    at /usr/src/usr.bin/tail/tail.c:187
#3  0x8048ba5 in ___start ()
(gdb) l rlines
246     static int
247     rlines(fp, off, sbp)
248             FILE *fp;
249             long off;
250             struct stat *sbp;
251     {
252             off_t size;
253             char *p;
254             char *start;
255
256             if (!(size = sbp->st_size))
257                     return (0);
258
(gdb) l
259             if (size > SIZE_T_MAX) {
260                     err(0, "%s: %s", fname, strerror(EFBIG));
261                     return (1);
262             }
263
264             if ((start = mmap(NULL, (size_t)size, PROT_READ,
265                 MAP_FILE|MAP_SHARED, fileno(fp), (off_t)0)) == (caddr_t)-1) {
266                     err(0, "%s: %s", fname, strerror(EFBIG));
267                     return (1);
268             }
(gdb) l
269
270             /* Last char is special, ignore whether newline or not. */
271             for (p = start + size - 1; --size;)
272                     if (*--p == '\n' && !--off) {
273                             ++p;
274                             break;
275                     }
276
277             /* Set the file pointer to reflect the length displayed. */
278             size = sbp->st_size - size;
(gdb) p start
$1 = 0x480f4000 "Build started at: Mon Oct 16 22:50:46 CEST 2000\n(cd /usr/src/etc && make -m /usr/src/share/mk DESTDIR=/ distrib-dirs)\ninstall  -d -o root -g wheel -m 755 /\nmtree -def mtree/NetBSD.dist -p // -u\nmissin"...
(gdb) p size
$2 = 8110783
(gdb) p p
$3 = 0x488b02be <Error reading address 0x488b02be: Bad address>
(gdb) p start+size
$4 = 0x488b02bf <Error reading address 0x488b02bf: Bad address>
(gdb) p fp
$5 = (FILE *) 0x480f3200
(gdb) p *$
$6 = {_p = 0x0, _r = 0, _w = 0, _flags = 4, _file = 6, _bf = {_base = 0x0, 
    _size = 0}, _lbfsize = 0, _cookie = 0x480f3200, 
  _close = 0x480dc4dc <__sclose>, _read = 0x480dc3ec <__sread>, 
  _seek = 0x480dc488 <__sseek>, _write = 0x480dc43c <__swrite>, _ub = {
    _base = 0x0, _size = 0}, _up = 0x0, _ur = 0, _ubuf = "\000\000", 
  _nbuf = "", _lb = {_base = 0x0, _size = 0}, _blksize = 0, _offset = 0}
(gdb)  
(gdb) p start+64536
$7 = 0x48103c18 "c.o p7_evp.o p7_dgst.o p7_s_e.o p7_enc.o p7_lib.o f_int.o f_string.o i2d_dhp.o i2d_dsap.o d2i_dhp.o d2i_dsap.o n_pkey.o f_enum.o a_hdr.o x_pkey.o a_bool.o x_exten.o asn1_par.o asn1_lib.o asn1_err.o a_"...
(gdb) p start+128000
$8 = 0x48113400 "depend /usr/src/sbin/sysctl/tags \ncleandir ===> sbin/ttyflags\nrm -f a.out [Ee]rrs mklog core *.core  ttyflags ttyflags.o  ttyflags.ln  \nrm -f ttyflags.cat8\nrm -f .depend /usr/src/sbin/ttyflags/tags \nc"...
(gdb) p start+256000
$9 = 0x48132800 "wap_2.o byte_swap_4.o bswap64.o bcmp.o bzero.o ffs.o memchr.o memcmp.o memcpy.o memmove.o memset.o strcat.o strchr.o strcmp.o strcpy.o strlen.o strncasecmp.o strncmp.o strncpy.o strrchr.o scanc.o skpc"...
(gdb) p start+512000
$10 = 0x48171000 <Error reading address 0x48171000: Bad address>
(gdb) p size
$11 = 8142006
(gdb) p start+400000
$12 = 0x48155a80 <Error reading address 0x48155a80: Bad address>
(gdb) p start+300000
$13 = 0x4813d3e0 "nake/snscore\nrm -f a.out [Ee]rrs mklog core *.core  snscore snscore.o  snscore.ln  \nrm -f snscore.cat1\nrm -f .depend /usr/src/games/snake/snscore/tags \ncleandir ===> games/tetris\nrm -f a.out [Ee]rrs m"...
(gdb) p start+350000
$14 = 0x48149730 ""
(gdb) p start+355000
$15 = 0x4814aab8 <Error reading address 0x4814aab8: Bad address>
(gdb) p start+352000
$16 = 0x48149f00 ""
(gdb) p start+351000
$17 = 0x48149b18 ""
(gdb) p start+340000
$18 = 0x48147020 "ln tc-i386.ln obj-elf.ln atof-ieee.ln  \nrm -f as.cat1\nrm -f .depend /usr/src/gnu/usr.bin/gas.new/tags \ncleandir ===> gnu/usr.bin/gawk\nrm -f awk.info\nrm -f a.out [Ee]rrs mklog core *.core  awk alloca.o"...
(gdb) p start+345000
$19 = 0x481483a8 "f/libdriver/tags \ncleandir ===> gnu/usr.bin/groff/libbib\nrm -f a.out [Ee]rrs mklog core *.core  \nrm -f libbib.a common.o index.o linear.o search.o map.o\nrm -f libbib_p.a \nrm -f libbib_pic.a libbib.so."...
(gdb) p start+348000
$20 = 0x48148f60 "usr.bin/groff/lkbib/tags \ncleandir ===> gnu/usr.bin/groff/hpftodit\nrm -f a.out [Ee]rrs mklog core *.core  hpftodit hpftodit.o    \nrm -f hpftodit.cat1\nrm -f .depend /usr/src/gnu/usr.bin/groff/hpftodit/"...
(gdb) p start+349000
$21 = 0x48149348 "ff/devices/devascii\nrm -f a.out [Ee]rrs mklog core *.core     \nrm -f R I B BI DESC\ncleandir ===> gnu/usr.bin/groff/devices/devlatin1\nrm -f a.out [Ee]rrs mklog core *.core     \nrm -f R I B BI DESC\nclea"...
(gdb) p start+349500
$22 = 0x4814953c "ices/devX100\nrm -f a.out [Ee]rrs mklog core *.core     \ncleandir ===> gnu/usr.bin/groff/devices/devX100-12\nrm -f a.out [Ee]rrs mklog core *.core     \ncleandir ===> gnu/usr.bin/groff/devices/devX75\nrm "...
(gdb) p start+349800
$23 = 0x48149668 "t [Ee]rrs mklog core *.core     \ncleandir ===> gnu/usr.bin/groff/tmac\n"
(gdb) p start+350000
$24 = 0x48149730 ""
(gdb) p start+349999
$25 = 0x4814972f ""
(gdb) p start+349900
$26 = 0x481496cc ""
(gdb) p start+349800
$27 = 0x48149668 "t [Ee]rrs mklog core *.core     \ncleandir ===> gnu/usr.bin/groff/tmac\n"
(gdb) p start+349850
$28 = 0x4814969a "/usr.bin/groff/tmac\n"
(gdb)  

???

pt# limit
cputime         unlimited
filesize        unlimited
datasize        131072 kbytes
stacksize       2048 kbytes
coredumpsize    unlimited
memoryuse       14156 kbytes
memorylocked    4718 kbytes
maxproc         80 
openfiles       64 
pt#


>How-To-Repeat:
	See above.

>Fix:
	Don't know.
>Release-Note:
>Audit-Trail:
>Unformatted: