GNU bug report logs - #49209
coreutils: stack out-of-bounds write in tail --follow

Previous Next

Package: coreutils;

Reported by: Kamil Dudka <kdudka <at> redhat.com>

Date: Thu, 24 Jun 2021 14:27:01 UTC

Severity: normal

Done: Paul Eggert <eggert <at> cs.ucla.edu>

Bug is archived. No further changes may be made.

Full log


Message #8 received at 49209 <at> debbugs.gnu.org (full text, mbox):

From: Pádraig Brady <P <at> draigBrady.com>
To: Kamil Dudka <kdudka <at> redhat.com>, 49209 <at> debbugs.gnu.org
Cc: sbroz <at> redhat.com
Subject: Re: bug#49209: coreutils: stack out-of-bounds write in tail --follow
Date: Thu, 24 Jun 2021 15:50:25 +0100
On 24/06/2021 15:26, Kamil Dudka wrote:
> Hello,
> 
> As originally reported by Stepan Broz (CC'd), tail --follow crashes when it
> is given too many files to follow, and ulimit -n is set to >1024.
> 
> FD_SET(wd, &rfd) in tail_forever_inotify() writes beyond the stack-allocated
> variable in case wd >= FD_SETSIZE.  Minimal example:
> 
> # mkdir dir
> # cd dir
> # touch {1..1021}
> # ulimit -n 1025
> # tail -f *
> 
> The out-of-bound write could be fixed like this:
> 
> --- a/src/tail.c
> +++ b/src/tail.c
> @@ -1647,28 +1647,32 @@ tail_forever_inotify (int wd, struct File_spec *f,
> size_t n_files,
>                 if (writer_is_dead)
>                   exit (EXIT_SUCCESS);
> 
>                 writer_is_dead = (kill (pid, 0) != 0 && errno != EPERM);
> 
>                 if (writer_is_dead)
>                   delay.tv_sec = delay.tv_usec = 0;
>                 else
>                   {
>                     delay.tv_sec = (time_t) sleep_interval;
>                     delay.tv_usec = 1000000 * (sleep_interval - delay.tv_sec);
>                   }
>               }
> 
> +           if (FD_SETSIZE <= wd)
> +             die (EXIT_FAILURE, 0,
> +                  _("too many open files to wait for inotify events"));
> +
>              fd_set rfd;
>              FD_ZERO (&rfd);
>              FD_SET (wd, &rfd);
>              if (monitor_output)
>                FD_SET (STDOUT_FILENO, &rfd);
> 
>              int file_change = select (MAX (wd, STDOUT_FILENO) + 1,
>                                        &rfd, NULL, NULL, pid ? &delay: NULL);
> 
>              if (file_change == 0)
>                continue;
>              else if (file_change == -1)
>                die (EXIT_FAILURE, errno,
>                     _("error waiting for inotify and output events"));
> 
> 
> Alternatively, we might rewrite the code to use poll() rather than select().

Note the number of descriptors select() is waiting on in independent of the number of files.
We should be able to inotify_init() earlier in the process to avoid this issue.
I'll have a look.

thanks!
Pádraig




This bug report was last modified 4 years and 19 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.