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

Reply via email to