965c50
From 95f427178720d047316e95f44777cfdf2ecf2b46 Mon Sep 17 00:00:00 2001
965c50
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <P@draigBrady.com>
965c50
Date: Fri, 4 Jan 2019 09:29:13 -0800
965c50
Subject: [PATCH 1/4] tail: don't exit immediately with filters on AIX
965c50
965c50
* src/tail.c: Fix the check_output_available check on AIX.
965c50
Note we don't use poll for all systems as the overhead
965c50
of adding the gnulib poll module wouldn't be worth it
965c50
just for this single use.
965c50
* tests/tail-2/pipe-f.sh: Fix the test which always passed
965c50
due to only the exit code of sleep being checked.
965c50
* NEWS: Mention the bug fix and rearrange alphabetically.
965c50
Fixes http://bugs.gnu.org/33946
965c50
965c50
Upstream-commit: d5ab4cbe424e3e95140eec22ef828f50b2fb3067
965c50
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
965c50
---
965c50
 src/tail.c             | 13 +++++++++++++
965c50
 tests/tail-2/pipe-f.sh |  5 ++++-
965c50
 2 files changed, 17 insertions(+), 1 deletion(-)
965c50
965c50
diff --git a/src/tail.c b/src/tail.c
965c50
index ac001d7..d63aacc 100644
965c50
--- a/src/tail.c
965c50
+++ b/src/tail.c
965c50
@@ -30,6 +30,9 @@
965c50
 #include <getopt.h>
965c50
 #include <sys/types.h>
965c50
 #include <signal.h>
965c50
+#ifdef _AIX
965c50
+# include <poll.h>
965c50
+#endif
965c50
 
965c50
 #include "system.h"
965c50
 #include "argmatch.h"
965c50
@@ -335,6 +338,16 @@ named file in a way that accommodates renaming, removal and creation.\n\
965c50
 static void
965c50
 check_output_alive (void)
965c50
 {
965c50
+#ifdef _AIX
965c50
+  /* select on AIX was seen to give a readable event immediately.  */
965c50
+  struct pollfd pfd;
965c50
+  pfd.fd = STDOUT_FILENO;
965c50
+  pfd.events = POLLERR;
965c50
+
965c50
+  if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR))
965c50
+    raise (SIGPIPE);
965c50
+#endif
965c50
+
965c50
   if (! monitor_output)
965c50
     return;
965c50
 
965c50
diff --git a/tests/tail-2/pipe-f.sh b/tests/tail-2/pipe-f.sh
965c50
index 76b0d90..1126c93 100755
965c50
--- a/tests/tail-2/pipe-f.sh
965c50
+++ b/tests/tail-2/pipe-f.sh
965c50
@@ -37,7 +37,10 @@ compare exp out || fail=1
965c50
 
965c50
 # This would wait indefinitely before v8.28 due to no EPIPE being
965c50
 # generated due to no data written after the first small amount
965c50
-timeout 10 tail -f $mode $fastpoll out | sleep .1 || fail=1
965c50
+(returns_ 124 timeout 10 tail -n2 -f $mode $fastpoll out && touch timed_out) |
965c50
+ sed 2q > out2
965c50
+test -e timed_out && fail=1
965c50
+compare exp out2 || fail=1
965c50
 
965c50
 # This would wait indefinitely before v8.28 (until first write)
965c50
 (returns_ 1 timeout 10 tail -f $mode $fastpoll /dev/null >&-) || fail=1
965c50
-- 
965c50
2.31.1
965c50
965c50
965c50
From 125bb79d3e9f414533b1c29237ee3f647053d0d6 Mon Sep 17 00:00:00 2001
965c50
From: Ayappan <ayappap2@in.ibm.com>
965c50
Date: Sun, 20 Jan 2019 00:17:33 -0800
965c50
Subject: [PATCH 2/4] tail: fix recent ineffective AIX change
965c50
965c50
* src/tail.c: Fix commit v8.30-40-gd5ab4cb which was ineffective.
965c50
Fixes http://bugs.gnu.org/33946
965c50
965c50
Upstream-commit: 17983b2cb3bccbb4fa69691178caddd99269bda9
965c50
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
965c50
---
965c50
 src/tail.c | 10 +++++-----
965c50
 1 file changed, 5 insertions(+), 5 deletions(-)
965c50
965c50
diff --git a/src/tail.c b/src/tail.c
965c50
index d63aacc..9ed6d48 100644
965c50
--- a/src/tail.c
965c50
+++ b/src/tail.c
965c50
@@ -338,6 +338,9 @@ named file in a way that accommodates renaming, removal and creation.\n\
965c50
 static void
965c50
 check_output_alive (void)
965c50
 {
965c50
+  if (! monitor_output)
965c50
+    return;
965c50
+
965c50
 #ifdef _AIX
965c50
   /* select on AIX was seen to give a readable event immediately.  */
965c50
   struct pollfd pfd;
965c50
@@ -346,11 +349,7 @@ check_output_alive (void)
965c50
 
965c50
   if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR))
965c50
     raise (SIGPIPE);
965c50
-#endif
965c50
-
965c50
-  if (! monitor_output)
965c50
-    return;
965c50
-
965c50
+#else
965c50
   struct timeval delay;
965c50
   delay.tv_sec = delay.tv_usec = 0;
965c50
 
965c50
@@ -362,6 +361,7 @@ check_output_alive (void)
965c50
      and implies an error condition on output like broken pipe.  */
965c50
   if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1)
965c50
     raise (SIGPIPE);
965c50
+#endif
965c50
 }
965c50
 
965c50
 static bool
965c50
-- 
965c50
2.31.1
965c50
965c50
965c50
From 7741989c3e633aa44f01d8f91332cb65a9280ba3 Mon Sep 17 00:00:00 2001
965c50
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <P@draigBrady.com>
965c50
Date: Sun, 20 Jan 2019 00:13:15 -0800
965c50
Subject: [PATCH 3/4] tail: fix handling of broken pipes with SIGPIPE ignored
965c50
965c50
* init.cfg (trap_sigpipe_or_skip_): A new function refactored from...
965c50
* tests/misc/printf-surprise.sh: ...here.
965c50
* tests/misc/seq-epipe.sh. Likewise.
965c50
* src/tail.c (die_pipe): Ensure we exit upon sending SIGPIPE.
965c50
* tests/tail-2/pipe-f.sh: Ensure we exit even if SIGPIPE is ignored.
965c50
* NEWS: Mention the bug fix.
965c50
965c50
Upstream-commit: fa50623394f491b975dbd7ad73193519dd721771
965c50
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
965c50
---
965c50
 init.cfg                      |  6 ++++++
965c50
 src/tail.c                    | 14 +++++++++++---
965c50
 tests/misc/printf-surprise.sh |  4 +---
965c50
 tests/misc/seq-epipe.sh       |  4 +---
965c50
 tests/tail-2/pipe-f.sh        | 19 ++++++++++++++-----
965c50
 5 files changed, 33 insertions(+), 14 deletions(-)
965c50
965c50
diff --git a/init.cfg b/init.cfg
965c50
index b6c81ab..985c8d3 100644
965c50
--- a/init.cfg
965c50
+++ b/init.cfg
965c50
@@ -613,6 +613,12 @@ mkfifo_or_skip_()
965c50
   fi
965c50
 }
965c50
 
965c50
+trap_sigpipe_or_skip_()
965c50
+{
965c50
+  (trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' ||
965c50
+    skip_ 'trapping SIGPIPE is not supported'
965c50
+}
965c50
+
965c50
 # Disable the current test if the working directory seems to have
965c50
 # the setgid bit set.
965c50
 skip_if_setgid_()
965c50
diff --git a/src/tail.c b/src/tail.c
965c50
index 9ed6d48..16e0d73 100644
965c50
--- a/src/tail.c
965c50
+++ b/src/tail.c
965c50
@@ -333,6 +333,14 @@ named file in a way that accommodates renaming, removal and creation.\n\
965c50
   exit (status);
965c50
 }
965c50
 
965c50
+/* Ensure exit, either with SIGPIPE or EXIT_FAILURE status.  */
965c50
+static void ATTRIBUTE_NORETURN
965c50
+die_pipe (void)
965c50
+{
965c50
+  raise (SIGPIPE);
965c50
+  exit (EXIT_FAILURE);
965c50
+}
965c50
+
965c50
 /* If the output has gone away, then terminate
965c50
    as we would if we had written to this output.  */
965c50
 static void
965c50
@@ -348,7 +356,7 @@ check_output_alive (void)
965c50
   pfd.events = POLLERR;
965c50
 
965c50
   if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR))
965c50
-    raise (SIGPIPE);
965c50
+    die_pipe ();
965c50
 #else
965c50
   struct timeval delay;
965c50
   delay.tv_sec = delay.tv_usec = 0;
965c50
@@ -360,7 +368,7 @@ check_output_alive (void)
965c50
   /* readable event on STDOUT is equivalent to POLLERR,
965c50
      and implies an error condition on output like broken pipe.  */
965c50
   if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1)
965c50
-    raise (SIGPIPE);
965c50
+    die_pipe ();
965c50
 #endif
965c50
 }
965c50
 
965c50
@@ -1658,7 +1666,7 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
965c50
              {
965c50
                /* readable event on STDOUT is equivalent to POLLERR,
965c50
                   and implies an error on output like broken pipe.  */
965c50
-               raise (SIGPIPE);
965c50
+               die_pipe ();
965c50
              }
965c50
            else
965c50
              break;
965c50
diff --git a/tests/misc/printf-surprise.sh b/tests/misc/printf-surprise.sh
965c50
index fd88133..acac0b1 100755
965c50
--- a/tests/misc/printf-surprise.sh
965c50
+++ b/tests/misc/printf-surprise.sh
965c50
@@ -49,9 +49,7 @@ vm=$(get_min_ulimit_v_ env $prog %20f 0) \
965c50
 # triggering the printf(3) misbehavior -- which, btw, is required by ISO C99.
965c50
 
965c50
 mkfifo_or_skip_ fifo
965c50
-
965c50
-(trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' ||
965c50
-    skip_ 'trapping SIGPIPE is not supported'
965c50
+trap_sigpipe_or_skip_
965c50
 
965c50
 # Disable MALLOC_PERTURB_, to avoid triggering this bug
965c50
 # https://bugs.debian.org/481543#77
965c50
diff --git a/tests/misc/seq-epipe.sh b/tests/misc/seq-epipe.sh
965c50
index 3e89158..127d61c 100755
965c50
--- a/tests/misc/seq-epipe.sh
965c50
+++ b/tests/misc/seq-epipe.sh
965c50
@@ -18,9 +18,7 @@
965c50
 
965c50
 . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
965c50
 print_ver_ seq
965c50
-
965c50
-(trap '' PIPE && yes | :) 2>&1 | grep -qF 'Broken pipe' ||
965c50
-    skip_ 'trapping SIGPIPE is not supported'
965c50
+trap_sigpipe_or_skip_
965c50
 
965c50
 # upon EPIPE with signals ignored, 'seq' should exit with an error.
965c50
 timeout 10 sh -c \
965c50
diff --git a/tests/tail-2/pipe-f.sh b/tests/tail-2/pipe-f.sh
965c50
index 1126c93..f734a61 100755
965c50
--- a/tests/tail-2/pipe-f.sh
965c50
+++ b/tests/tail-2/pipe-f.sh
965c50
@@ -18,6 +18,7 @@
965c50
 
965c50
 . "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
965c50
 print_ver_ tail
965c50
+trap_sigpipe_or_skip_
965c50
 
965c50
 # Speedup the non inotify case
965c50
 fastpoll='-s.1 --max-unchanged-stats=1'
965c50
@@ -36,11 +37,19 @@ echo bar | returns_ 1 \
965c50
 compare exp out || fail=1
965c50
 
965c50
 # This would wait indefinitely before v8.28 due to no EPIPE being
965c50
-# generated due to no data written after the first small amount
965c50
-(returns_ 124 timeout 10 tail -n2 -f $mode $fastpoll out && touch timed_out) |
965c50
- sed 2q > out2
965c50
-test -e timed_out && fail=1
965c50
-compare exp out2 || fail=1
965c50
+# generated due to no data written after the first small amount.
965c50
+# Also check tail exits if SIGPIPE is being ignored.
965c50
+# Note 'trap - SIGPIPE' is ineffective if the initiating shell
965c50
+# has ignored SIGPIPE, but that's not the normal case.
965c50
+for disposition in '' '-'; do
965c50
+  (trap "$disposition" PIPE;
965c50
+   returns_ 124 timeout 10 \
965c50
+    tail -n2 -f $mode $fastpoll out && touch timed_out) |
965c50
+  sed 2q > out2
965c50
+  test -e timed_out && fail=1
965c50
+  compare exp out2 || fail=1
965c50
+  rm -f timed_out
965c50
+done
965c50
 
965c50
 # This would wait indefinitely before v8.28 (until first write)
965c50
 (returns_ 1 timeout 10 tail -f $mode $fastpoll /dev/null >&-) || fail=1
965c50
-- 
965c50
2.31.1
965c50
965c50
965c50
From 0f5760466d167e955d28a1250ffd0af347d48dc9 Mon Sep 17 00:00:00 2001
965c50
From: Paul Eggert <eggert@cs.ucla.edu>
965c50
Date: Sat, 26 Jun 2021 18:23:52 -0700
965c50
Subject: [PATCH 4/4] tail: use poll, not select
965c50
MIME-Version: 1.0
965c50
Content-Type: text/plain; charset=UTF-8
965c50
Content-Transfer-Encoding: 8bit
965c50
965c50
This fixes an unlikely stack out-of-bounds write reported by
965c50
Stepan Broz via Kamil Dudka (Bug#49209).
965c50
* src/tail.c: Do not include <sys/select.h>.
965c50
[!_AIX]: Include poll.h.
965c50
(check_output_alive) [!_AIX]: Use poll instead of select.
965c50
(tail_forever_inotify): Likewise.  Simplify logic, as there is no
965c50
need for a ‘while (len <= evbuf_off)’ loop.
965c50
965c50
Upstream-commit: da0d448bca62c6305fc432f67e2c5ccc2da75346
965c50
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
965c50
---
965c50
 src/tail.c | 101 +++++++++++++++++++++--------------------------------
965c50
 1 file changed, 39 insertions(+), 62 deletions(-)
965c50
965c50
diff --git a/src/tail.c b/src/tail.c
965c50
index 16e0d73..d77c660 100644
965c50
--- a/src/tail.c
965c50
+++ b/src/tail.c
965c50
@@ -29,10 +29,8 @@
965c50
 #include <assert.h>
965c50
 #include <getopt.h>
965c50
 #include <sys/types.h>
965c50
+#include <poll.h>
965c50
 #include <signal.h>
965c50
-#ifdef _AIX
965c50
-# include <poll.h>
965c50
-#endif
965c50
 
965c50
 #include "system.h"
965c50
 #include "argmatch.h"
965c50
@@ -55,8 +53,6 @@
965c50
 #if HAVE_INOTIFY
965c50
 # include "hash.h"
965c50
 # include <sys/inotify.h>
965c50
-/* 'select' is used by tail_forever_inotify.  */
965c50
-# include <sys/select.h>
965c50
 
965c50
 /* inotify needs to know if a file is local.  */
965c50
 # include "fs.h"
965c50
@@ -349,27 +345,12 @@ check_output_alive (void)
965c50
   if (! monitor_output)
965c50
     return;
965c50
 
965c50
-#ifdef _AIX
965c50
-  /* select on AIX was seen to give a readable event immediately.  */
965c50
   struct pollfd pfd;
965c50
   pfd.fd = STDOUT_FILENO;
965c50
   pfd.events = POLLERR;
965c50
 
965c50
   if (poll (&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR))
965c50
     die_pipe ();
965c50
-#else
965c50
-  struct timeval delay;
965c50
-  delay.tv_sec = delay.tv_usec = 0;
965c50
-
965c50
-  fd_set rfd;
965c50
-  FD_ZERO (&rfd;;
965c50
-  FD_SET (STDOUT_FILENO, &rfd;;
965c50
-
965c50
-  /* readable event on STDOUT is equivalent to POLLERR,
965c50
-     and implies an error condition on output like broken pipe.  */
965c50
-  if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1)
965c50
-    die_pipe ();
965c50
-#endif
965c50
 }
965c50
 
965c50
 static bool
965c50
@@ -1609,7 +1590,7 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
965c50
   /* Wait for inotify events and handle them.  Events on directories
965c50
      ensure that watched files can be re-added when following by name.
965c50
      This loop blocks on the 'safe_read' call until a new event is notified.
965c50
-     But when --pid=P is specified, tail usually waits via the select.  */
965c50
+     But when --pid=P is specified, tail usually waits via poll.  */
965c50
   while (1)
965c50
     {
965c50
       struct File_spec *fspec;
965c50
@@ -1626,54 +1607,51 @@ tail_forever_inotify (int wd, struct File_spec *f, size_t n_files,
965c50
           return false;
965c50
         }
965c50
 
965c50
-      /* When watching a PID, ensure that a read from WD will not block
965c50
-         indefinitely.  */
965c50
-      while (len <= evbuf_off)
965c50
+      if (len <= evbuf_off)
965c50
         {
965c50
-          struct timeval delay; /* how long to wait for file changes.  */
965c50
+          /* Poll for inotify events.  When watching a PID, ensure
965c50
+             that a read from WD will not block indefinitely.
965c50
+             If MONITOR_OUTPUT, also poll for a broken output pipe.  */
965c50
 
965c50
-          if (pid)
965c50
+          int file_change;
965c50
+          struct pollfd pfd[2];
965c50
+          do
965c50
             {
965c50
-              if (writer_is_dead)
965c50
-                exit (EXIT_SUCCESS);
965c50
+              /* How many ms to wait for changes.  -1 means wait forever.  */
965c50
+              int delay = -1;
965c50
 
965c50
-              writer_is_dead = (kill (pid, 0) != 0 && errno != EPERM);
965c50
-
965c50
-              if (writer_is_dead)
965c50
-                delay.tv_sec = delay.tv_usec = 0;
965c50
-              else
965c50
+              if (pid)
965c50
                 {
965c50
-                  delay.tv_sec = (time_t) sleep_interval;
965c50
-                  delay.tv_usec = 1000000 * (sleep_interval - delay.tv_sec);
965c50
+                  if (writer_is_dead)
965c50
+                    exit (EXIT_SUCCESS);
965c50
+
965c50
+                  writer_is_dead = (kill (pid, 0) != 0 && errno != EPERM);
965c50
+
965c50
+                  if (writer_is_dead || sleep_interval <= 0)
965c50
+                    delay = 0;
965c50
+                  else if (sleep_interval < INT_MAX / 1000 - 1)
965c50
+                    {
965c50
+                      /* delay = ceil (sleep_interval * 1000), sans libm.  */
965c50
+                      double ddelay = sleep_interval * 1000;
965c50
+                      delay = ddelay;
965c50
+                      delay += delay < ddelay;
965c50
+                    }
965c50
                 }
965c50
+
965c50
+              pfd[0].fd = wd;
965c50
+              pfd[0].events = POLLIN;
965c50
+              pfd[1].fd = STDOUT_FILENO;
965c50
+              pfd[1].events = pfd[1].revents = 0;
965c50
+              file_change = poll (pfd, monitor_output + 1, delay);
965c50
             }
965c50
+          while (file_change == 0);
965c50
 
965c50
-           fd_set rfd;
965c50
-           FD_ZERO (&rfd;;
965c50
-           FD_SET (wd, &rfd;;
965c50
-           if (monitor_output)
965c50
-             FD_SET (STDOUT_FILENO, &rfd;;
965c50
-
965c50
-           int file_change = select (MAX (wd, STDOUT_FILENO) + 1,
965c50
-                                     &rfd, NULL, NULL, pid ? &delay: NULL);
965c50
-
965c50
-           if (file_change == 0)
965c50
-             continue;
965c50
-           else if (file_change == -1)
965c50
-             die (EXIT_FAILURE, errno,
965c50
-                  _("error waiting for inotify and output events"));
965c50
-           else if (FD_ISSET (STDOUT_FILENO, &rfd))
965c50
-             {
965c50
-               /* readable event on STDOUT is equivalent to POLLERR,
965c50
-                  and implies an error on output like broken pipe.  */
965c50
-               die_pipe ();
965c50
-             }
965c50
-           else
965c50
-             break;
965c50
-        }
965c50
+          if (file_change < 0)
965c50
+            die (EXIT_FAILURE, errno,
965c50
+                 _("error waiting for inotify and output events"));
965c50
+          if (pfd[1].revents)
965c50
+            die_pipe ();
965c50
 
965c50
-      if (len <= evbuf_off)
965c50
-        {
965c50
           len = safe_read (wd, evbuf, evlen);
965c50
           evbuf_off = 0;
965c50
 
965c50
@@ -2434,8 +2412,7 @@ main (int argc, char **argv)
965c50
   if (forever && ignore_fifo_and_pipe (F, n_files))
965c50
     {
965c50
       /* If stdout is a fifo or pipe, then monitor it
965c50
-         so that we exit if the reader goes away.
965c50
-         Note select() on a regular file is always readable.  */
965c50
+         so that we exit if the reader goes away.  */
965c50
       struct stat out_stat;
965c50
       if (fstat (STDOUT_FILENO, &out_stat) < 0)
965c50
         die (EXIT_FAILURE, errno, _("standard output"));
965c50
-- 
965c50
2.31.1
965c50