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

Reply via email to