public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
* [rpms/coreutils] rawhide: fix CVE-2026-56391 and tee infinite loop
@ 2026-08-03  7:40 
  0 siblings, 0 replies; only message in thread
From:  @ 2026-08-03  7:40 UTC (permalink / raw)
  To: git-commits

            A new commit has been pushed.

            Repo   : rpms/coreutils
            Branch : rawhide
            Commit : 08a268447f66d6a0552cf6fd5056265bf82da808
            Author : Lukáš Zaoral <lzaoral@redhat.com>
            Date   : 2026-08-03T09:35:34+02:00
            Stats  : +312/-1 in 3 file(s)
            URL    : https://src.fedoraproject.org/rpms/coreutils/c/08a268447f66d6a0552cf6fd5056265bf82da808?branch=rawhide

            Log:
            fix CVE-2026-56391 and tee infinite loop

Resolves: rhbz#2507449

---
diff --git a/coreutils-9.11-CVE-2026-56391.patch b/coreutils-9.11-CVE-2026-56391.patch
new file mode 100644
index 0000000..7c4b862
--- /dev/null
+++ b/coreutils-9.11-CVE-2026-56391.patch
@@ -0,0 +1,63 @@
+From 3953e3d60edb0f23bdf367a3ccbc2282b9e00d1b Mon Sep 17 00:00:00 2001
+From: Paul Eggert <eggert@cs.ucla.edu>
+Date: Tue, 28 Apr 2026 11:25:00 -0700
+Subject: [PATCH] uniq: fix read overrun with -w
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Problem reported by Michał Majchrowicz.
+* src/uniq.c (find_field): Fix typo.
+* tests/uniq/uniq.pl (add_z_variants): Test for the bug.
+
+(cherry picked from commit d64e35a8a4c0e4608321433e0d84d917e4e36371)
+---
+ THANKS.in          | 1 +
+ src/uniq.c         | 4 ++--
+ tests/uniq/uniq.pl | 3 +++
+ 3 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/THANKS.in b/THANKS.in
+index 35fee75..5a2fd35 100644
+--- a/THANKS.in
++++ b/THANKS.in
+@@ -459,6 +459,7 @@ Michail Litvak                      mci@owl.openwall.com
+ Michal Politowski                   mpol@charybda.icm.edu.pl
+ Michal Svec                         msvec@suse.cz
+ Michal Trunecka                     mtruneck@redhat.com
++Michał Majchrowicz                  mmajchrowicz@afine.com
+ Michel Robitaille                   robitail@IRO.UMontreal.CA
+ Michiel Bacchiani                   bacchian@raven.bu.edu
+ Mike Castle                         dalgoda@ix.netcom.com
+diff --git a/src/uniq.c b/src/uniq.c
+index 3046359..5834596 100644
+--- a/src/uniq.c
++++ b/src/uniq.c
+@@ -285,8 +285,8 @@ find_field (struct linebuffer const *line, idx_t *plen)
+   else
+     {
+       char *ep = lp;
+-      for (idx_t i = check_chars; 0 < i && lp < lim; i--)
+-        ep += mcel_scan (lp, lim).len;
++      for (idx_t i = check_chars; 0 < i && ep < lim; i--)
++        ep += mcel_scan (ep, lim).len;
+       len = ep - lp;
+     }
+ 
+diff --git a/tests/uniq/uniq.pl b/tests/uniq/uniq.pl
+index b558fb3..0df7ec6 100755
+--- a/tests/uniq/uniq.pl
++++ b/tests/uniq/uniq.pl
+@@ -234,6 +234,9 @@ my @Tests =
+         "  - 'separate'\n" .
+         "  - 'both'\n" .
+         "Try '$prog --help' for more information.\n"}],
++ # Test for read buffer overrun.
++ do { my $longline = "\360\237\230\200" . "A" x 255 . "\n";
++      ['146', '-w256', {IN  => $longline x 2}, {OUT => $longline}] },
+ );
+ 
+ # Locale related tests
+-- 
+2.55.0
+

diff --git a/coreutils-9.11-tee-infinite-loop.patch b/coreutils-9.11-tee-infinite-loop.patch
new file mode 100644
index 0000000..2a2d5ba
--- /dev/null
+++ b/coreutils-9.11-tee-infinite-loop.patch
@@ -0,0 +1,236 @@
+From c6b1d7c08d802accd0075c3dc29ba46d42fca8d7 Mon Sep 17 00:00:00 2001
+From: Collin Funk <collin.funk1@gmail.com>
+Date: Mon, 18 May 2026 20:40:28 -0700
+Subject: [PATCH] tee: fix infinite loop when write returns EAGAIN and short
+ write errors
+
+* THANKS.in: Add Bernhard M. Wiedemann for reporting the bugs.
+* src/iopoll.c (close_wait): Remove function.
+(write_wait): Don't call wait_for_nonblocking_write if write is
+successful. Handle errors more robustly.
+* src/iopoll.h (close_wait): Remove declaration.
+* src/tee.c (tee_files): Use close instead of close_wait.
+* tests/tee/short-write.sh: New test for the bug.
+* tests/tee/write-eagain.sh: Likewise.
+* tests/local.mk (all_tests): Add the new tests.
+Fixes https://bugs.gnu.org/81060
+
+(cherry picked from commit 0d6fcb99d691d920961938e61c43478566ef626e)
+---
+ THANKS.in                 |  1 +
+ src/iopoll.c              | 59 ++++++++++++++++++++++++---------------
+ src/iopoll.h              |  1 -
+ src/tee.c                 |  2 +-
+ tests/local.mk            |  2 ++
+ tests/tee/short-write.sh  | 33 ++++++++++++++++++++++
+ tests/tee/write-eagain.sh | 31 ++++++++++++++++++++
+ 7 files changed, 104 insertions(+), 25 deletions(-)
+ create mode 100755 tests/tee/short-write.sh
+ create mode 100755 tests/tee/write-eagain.sh
+
+diff --git a/THANKS.in b/THANKS.in
+index 5a2fd35..b1453be 100644
+--- a/THANKS.in
++++ b/THANKS.in
+@@ -86,6 +86,7 @@ Bernd Leibing                       bernd.leibing@rz.uni-ulm.de
+ Bernd Melchers                      melchers@cis.fu-berlin.de
+ Bernhard Baehr                      bernhard.baehr@gmx.de
+ Bernhard Gabler                     bernhard@uni-koblenz.de
++Bernhard M. Wiedemann               bwiedemann@suse.de
+ Bernhard Rosenkraenzer              bero@redhat.de
+ Bert Deknuydt                       Bert.Deknuydt@esat.kuleuven.ac.be
+ Bert Wesarg                         bert.wesarg@googlemail.com
+diff --git a/src/iopoll.c b/src/iopoll.c
+index de20bc8..0bd2d6b 100644
+--- a/src/iopoll.c
++++ b/src/iopoll.c
+@@ -194,17 +194,6 @@ wait_for_nonblocking_write (int fd)
+   return true;
+ }
+ 
+-/* wrapper for close() that also waits for FD if non blocking.  */
+-
+-extern bool
+-close_wait (int fd)
+-{
+-  while (wait_for_nonblocking_write (fd))
+-    ;
+-  return close (fd) == 0;
+-}
+-
+-
+ /* wrapper for write() that also waits for FD if non blocking.  */
+ 
+ extern bool
+@@ -212,19 +201,43 @@ write_wait (int fd, void const *buffer, size_t size)
+ {
+   unsigned char const *buf = buffer;
+ 
+-  while (true)
++  do
+     {
+-      ssize_t written = write (fd, buf, size);
+-      if (written < 0)
+-        written = 0;
+-
+-      size -= written;
+-      if (size <= 0)  /* everything written */
+-        return true;
+-
+-      if (! wait_for_nonblocking_write (fd))
+-        return false;
++      const ssize_t written = write (fd, buf, size);
++      /* POSIX says that calling write with SIZE of zero may detect and
++         return errors.  If no error occurs, or write makes no attempt
++         to detect errors, then write returns zero with no other
++         results.  write_fail will return successfully in this case.  */
++      if (written == 0)
++        {
++          if (size == 0)
++            return true;
++          else
++            {
++              /* If SIZE is greater than zero and write returns zero,
++                 treat it as an error.  Some buggy drivers behave this
++                 way.  See src/dd.c and Gnulib's lib/full-write.c for
++                 more details.  */
++              errno = ENOSPC;
++              return false;
++            }
++        }
+ 
+-      buf += written;
++      if (written < 0)
++        {
++          /* Return an error if write detected one with a SIZE of zero.
++             Otherwise, if SIZE is greater than zero, fail if it does
++             not become writable.  */
++          if (size == 0 || ! wait_for_nonblocking_write (fd))
++            return false;
++        }
++      else
++        {
++          buf += written;
++          size -= written;
++        }
+     }
++  while (0 < size);
++
++  return true;
+ }
+diff --git a/src/iopoll.h b/src/iopoll.h
+index 1711fda..a1561b9 100644
+--- a/src/iopoll.h
++++ b/src/iopoll.h
+@@ -5,5 +5,4 @@ int iopoll (int fdin, int fdout, bool block);
+ bool iopoll_input_ok (int fdin);
+ bool iopoll_output_ok (int fdout);
+ 
+-bool close_wait (int fd);
+ bool write_wait (int fd, void const *buffer, size_t size);
+diff --git a/src/tee.c b/src/tee.c
+index 32a18e3..fba6ae0 100644
+--- a/src/tee.c
++++ b/src/tee.c
+@@ -329,7 +329,7 @@ tee_files (int nfiles, char **files, bool pipe_check)
+ 
+   /* Close the files, but not standard output.  */
+   for (int i = 1; i <= nfiles; i++)
+-    if (0 <= descriptors[i] && ! close_wait (descriptors[i]))
++    if (0 <= descriptors[i] && close (descriptors[i]) < 0)
+       {
+         error (0, errno, "%s", quotef (files[i]));
+         ok = false;
+diff --git a/tests/local.mk b/tests/local.mk
+index e2c07a8..ea5ef7c 100644
+--- a/tests/local.mk
++++ b/tests/local.mk
+@@ -485,7 +485,9 @@ all_tests =					\
+   tests/tac/tac-2-nonseekable.sh		\
+   tests/tail/tail.pl				\
+   tests/tee/append.sh				\
++  tests/tee/short-write.sh			\
+   tests/tee/tee.sh				\
++  tests/tee/write-eagain.sh			\
+   tests/test/test-N.sh				\
+   tests/test/test-diag.pl			\
+   tests/test/test-file.sh			\
+diff --git a/tests/tee/short-write.sh b/tests/tee/short-write.sh
+new file mode 100755
+index 0000000..4270926
+--- /dev/null
++++ b/tests/tee/short-write.sh
+@@ -0,0 +1,33 @@
++#!/bin/sh
++# Test 'tee' when a write is short.
++
++# Copyright (C) 2026 Free Software Foundation, Inc.
++
++# This program is free software: you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation, either version 3 of the License, or
++# (at your option) any later version.
++
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <https://www.gnu.org/licenses/>.
++
++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
++print_ver_ tee
++require_strace_ write
++
++printf 'abcdef' >file1-exp || framework_failure_
++printf 'f' >out-exp || framework_failure_
++
++# In coreutils-9.11, a short write would be treated as an error.
++strace -qqq -o /dev/null --trace-fds=1 -e trace=write \
++  -e inject=write:retval=1:when=1..5 tee file1 >out 2>err <file1-exp || fail=1
++compare file1-exp file1 || fail=1
++compare out-exp out || fail=1
++compare /dev/null err || fail=1
++
++Exit $fail
+diff --git a/tests/tee/write-eagain.sh b/tests/tee/write-eagain.sh
+new file mode 100755
+index 0000000..f434ee6
+--- /dev/null
++++ b/tests/tee/write-eagain.sh
+@@ -0,0 +1,31 @@
++#!/bin/sh
++# Test 'tee' when a write fails with errno set to EAGAIN.
++
++# Copyright (C) 2026 Free Software Foundation, Inc.
++
++# This program is free software: you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation, either version 3 of the License, or
++# (at your option) any later version.
++
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <https://www.gnu.org/licenses/>.
++
++. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
++print_ver_ tee
++require_strace_ write
++
++# In coreutils-9.11 the following test would infinite loop.
++echo a >exp || framework_failure_
++timeout 10 strace -qqq -o /dev/null -e trace-fds=3 \
++  -e inject=write:error=EAGAIN:when=1 tee file1 <exp >out 2>err || fail=1
++compare exp file1 || fail=1
++compare exp out || fail=1
++compare /dev/null err || fail=1
++
++Exit $fail
+-- 
+2.55.0
+

diff --git a/coreutils.spec b/coreutils.spec
index 7112f8e..caca7d2 100644
--- a/coreutils.spec
+++ b/coreutils.spec
@@ -1,7 +1,7 @@
 Summary: A set of basic GNU tools commonly used in shell scripts
 Name:    coreutils
 Version: 9.11
-Release: 5%{?dist}
+Release: 6%{?dist}
 # some used parts of gnulib are under various variants of LGPL
 License: GPL-3.0-or-later AND GFDL-1.3-no-invariants-or-later AND LGPL-2.1-or-later AND LGPL-3.0-or-later
 Url:     https://www.gnu.org/software/coreutils/
@@ -39,6 +39,14 @@ Patch104: coreutils-df-direct.patch
 # https://cgit.git.savannah.gnu.org/cgit/coreutils.git/commit/?id=4ade9cf77f6c7b39e3fdc5ce97a778f8e294694c
 Patch200: coreutils-9.11-unexpand-heap-overflows.patch
 
+# CVE-2026-56391 - uniq: fix read overrun with -w
+# https://cgit.git.savannah.gnu.org/cgit/coreutils.git/commit/?id=d64e35a8a4c0e4608321433e0d84d917e4e36371
+Patch201: coreutils-9.11-CVE-2026-56391.patch
+
+# tee: fix infinite loop when write returns EAGAIN and short write errors
+# https://cgit.git.savannah.gnu.org/cgit/coreutils.git/commit/?id=0d6fcb99d691d920961938e61c43478566ef626e
+Patch202: coreutils-9.11-tee-infinite-loop.patch
+
 # (sb) lin18nux/lsb compliance - multibyte functionality patch
 Patch800: coreutils-i18n.patch
 
@@ -290,6 +298,10 @@ rm -f $RPM_BUILD_ROOT%{_infodir}/dir
 %license COPYING
 
 %changelog
+* Mon Aug 03 2026 Lukáš Zaoral <lzaoral@redhat.com> - 9.11-6
+- CVE-2026-56391 - uniq: fix read overrun with -w (rhbz#2507449)
+- tee: fix infinite loop when write returns EAGAIN and short write errors
+
 * Wed Jul 15 2026 Fedora Release Engineering <releng@fedoraproject.org> - 9.11-5
 - Rebuilt for https://fedoraproject.org/wiki/Fedora_45_Mass_Rebuild
 

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-08-03  7:40 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-03  7:40 [rpms/coreutils] rawhide: fix CVE-2026-56391 and tee infinite loop 

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox