On 01/31/17 15:34, Stefan Sperling wrote: > 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 >> [email protected]:/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.
This is wrong, If a file wraps recno can become 0 again and a lot of memory won't be freed. martijn@ > > 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); >
