On Tue, Jan 31, 2017 at 03:36:21PM +0300, Soner Tari wrote: > >Synopsis: With large line numbers, tail(1) makes the system unusable. > >Category: system > >Environment: > System : OpenBSD 6.0 > Details : OpenBSD 6.0 (GENERIC) #2148: Tue Jul 26 12:55:20 > MDT 2016 > dera...@amd64.openbsd.org:/usr/src/sys/arch/am > d64/compile/GENERIC > > Architecture: OpenBSD.amd64 > Machine : amd64 > >Description: > When provided with a large line number, tail gives "Cannot allocate > memory" to a regular user, but when run as root tail gets stuck making > the system unusable. > > The same issue exists on 5.9 too. Note that I see a couple of changes > to tail on 5.9 Changelog. > > >How-To-Repeat: > Simply run the following command line as root: > > echo blah | /usr/bin/tail -99999999 > > Normally, it should print blah and exit, or give "Cannot allocate > memory" as it does to a regular user. (Note that tail on Linux prints > blah or gives "Numerical result out of range" for much larger numbers, > to both regular users and root.) > > >Fix: > Workaroud: Do not use such large numbers.
In your example tail allocates a huge amount of memory (99999999 * 24 bytes on amd64) and then keeps calling free(NULL) 99999998 times in a loop (the first of 99999999 iterations has a valid pointer to free). With this diff the issue as you presented it goes away. I am not sure if this is the best possible fix. With this diff the same amount of memory is still allocated but the program terminates quickly. Index: read.c =================================================================== RCS file: /cvs/src/usr.bin/tail/read.c,v retrieving revision 1.16 diff -u -p -r1.16 read.c --- read.c 26 Mar 2015 21:26:43 -0000 1.16 +++ read.c 31 Jan 2017 14:30:03 -0000 @@ -213,7 +213,7 @@ lines(FILE *fp, off_t off) WR(lines[cnt].l, lines[cnt].len); } done: - for (cnt = 0; cnt < off; cnt++) + for (cnt = 0; cnt < recno; cnt++) free(lines[cnt].l); free(sp); free(lines);