Subject: tail(1) seg faults on i/o error, with fix
To: None <netbsd-bugs@NetBSD.org>
From: Dieter <netbsd@sopwith.solgatos.com>
List: netbsd-bugs
Date: 02/16/2005 09:29:04
The tail(1) utility gets a segmentation fault core dump
if it gets an i/o error.  This happens on 1.6.2 and 2.0
(and probably other releases as well).

Repeat by: run tail on a file that gives an i/o error.

The problem is using mmap(2) and not insuring that the
data can be read.  I fixed it with mlock(2), which
allows a graceful handling of the i/o error without
a core dump.

The diff below (against 2.0) fixes the problem.  I make
no claim that this is the best fix, or the most efficient fix.
(It does an mlock() and munlock for each char.)
It probably isn't necessary to exit upon i/o error.

There are probably other programs lurking out there
using mmap unsafely.  :-(

===================================================================
RCS file: RCS/forward.c,v
retrieving revision 1.1
diff -c -r1.1 forward.c
*** forward.c	2005/02/10 18:34:56	1.1
--- forward.c	2005/02/16 17:11:40
***************
*** 312,321 ****
--- 312,334 ----
  		mmap_remaining = mmap_size;
  		/* Last char is special, ignore whether newline or not. */
  		for (p = start + mmap_remaining - 1 ; --mmap_remaining ; )
+ 		  {
+ 		      /* The mlock call is to prevent segmentation fault core dump
+ 		       * if it gets an i/o error.
+ 		       */
+ 		      if (mlock(p - 1, 1))
+ 		        {
+ 			  perror("mlock failed, exiting");
+ 			  exit(1);
+ 		        }
+ 
  			if (*--p == '\n' && !--off) {
  				++p;
+ 				if (munlock(p - 1, 1)) { perror("munlock failed"); }
  				break;
  			}
+ 			if (munlock(p - 1, 1)) { perror("munlock failed"); }
+ 		  }
  
  		file_remaining -= mmap_size - mmap_remaining;