diff mbox series

[1/2] coreutils: Backport a fix recommended by upstream

Message ID 20260802213000.457180-1-richard.purdie@linuxfoundation.org
State New
Headers show
Series [1/2] coreutils: Backport a fix recommended by upstream | expand

Commit Message

Richard Purdie Aug. 2, 2026, 9:29 p.m. UTC
Upstream suggested we may want this fix and other distros such
as SUSE are also adding it as it has caused problems for people.

Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
---
 ...cb99d691d920961938e61c43478566ef626e.patch | 221 ++++++++++++++++++
 meta/recipes-core/coreutils/coreutils_9.11.bb |   1 +
 2 files changed, 222 insertions(+)
 create mode 100644 meta/recipes-core/coreutils/coreutils/0d6fcb99d691d920961938e61c43478566ef626e.patch

Comments

patchtest@automation.yoctoproject.org Aug. 2, 2026, 9:47 p.m. UTC | #1
Thank you for your submission. Patchtest identified one
or more issues with the patch. Please see the log below for
more information:

---
Testing patch /home/patchtest/share/mboxes/1-2-coreutils-Backport-a-fix-recommended-by-upstream.patch

FAIL: test Upstream-Status presence: Upstream-Status is present only after the patch scissors. It must be placed in the patch header before the scissors line. (test_patch.TestPatch.test_upstream_status_presence_format)

PASS: test CVE check ignore (test_metadata.TestMetadata.test_cve_check_ignore)
PASS: test CVE tag format (test_patch.TestPatch.test_cve_tag_format)
PASS: test Signed-off-by presence (test_mbox.TestMbox.test_signed_off_by_presence)
PASS: test Signed-off-by presence (test_patch.TestPatch.test_signed_off_by_presence)
PASS: test author valid (test_mbox.TestMbox.test_author_valid)
PASS: test commit message presence (test_mbox.TestMbox.test_commit_message_presence)
PASS: test commit message user tags (test_mbox.TestMbox.test_commit_message_user_tags)
PASS: test lic files chksum modified not mentioned (test_metadata.TestMetadata.test_lic_files_chksum_modified_not_mentioned)
PASS: test max line length (test_metadata.TestMetadata.test_max_line_length)
PASS: test mbox format (test_mbox.TestMbox.test_mbox_format)
PASS: test non-AUH upgrade (test_mbox.TestMbox.test_non_auh_upgrade)
PASS: test shortlog format (test_mbox.TestMbox.test_shortlog_format)
PASS: test shortlog length (test_mbox.TestMbox.test_shortlog_length)
PASS: test target mailing list (test_mbox.TestMbox.test_target_mailing_list)

SKIP: pretest pylint: No python related patches, skipping test (test_python_pylint.PyLint.pretest_pylint)
SKIP: pretest src uri left files: Patch cannot be merged (test_metadata.TestMetadata.pretest_src_uri_left_files)
SKIP: test bugzilla entry format: No bug ID found (test_mbox.TestMbox.test_bugzilla_entry_format)
SKIP: test lic files chksum presence: No added recipes, skipping test (test_metadata.TestMetadata.test_lic_files_chksum_presence)
SKIP: test license presence: No added recipes, skipping test (test_metadata.TestMetadata.test_license_presence)
SKIP: test pylint: No python related patches, skipping test (test_python_pylint.PyLint.test_pylint)
SKIP: test series merge on head: Merge test is disabled for now (test_mbox.TestMbox.test_series_merge_on_head)
SKIP: test src uri left files: Patch cannot be merged (test_metadata.TestMetadata.test_src_uri_left_files)
SKIP: test summary presence: No added recipes, skipping test (test_metadata.TestMetadata.test_summary_presence)

---

Please address the issues identified and
submit a new revision of the patch, or alternatively, reply to this
email with an explanation of why the patch should be accepted. If you
believe these results are due to an error in patchtest, please submit a
bug at https://bugzilla.yoctoproject.org/ (use the 'Patchtest' category
under 'Yocto Project Subprojects'). For more information on specific
failures, see: https://wiki.yoctoproject.org/wiki/Patchtest. Thank
you!
diff mbox series

Patch

diff --git a/meta/recipes-core/coreutils/coreutils/0d6fcb99d691d920961938e61c43478566ef626e.patch b/meta/recipes-core/coreutils/coreutils/0d6fcb99d691d920961938e61c43478566ef626e.patch
new file mode 100644
index 00000000000..7d439f684ac
--- /dev/null
+++ b/meta/recipes-core/coreutils/coreutils/0d6fcb99d691d920961938e61c43478566ef626e.patch
@@ -0,0 +1,221 @@ 
+From 0d6fcb99d691d920961938e61c43478566ef626e 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
+
+* NEWS: Mention the bug fixes.
+* 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
+---
+ NEWS                      |  7 +++++
+ 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 ++++++++++++++++++++
+ 8 files changed, 111 insertions(+), 25 deletions(-)
+ create mode 100755 tests/tee/short-write.sh
+ create mode 100755 tests/tee/write-eagain.sh
+
+Upstream-Status: Backport [https://github.com/coreutils/coreutils/commit/0d6fcb99d691d920961938e61c43478566ef626e.patch]
+Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
+Index: coreutils-9.11/src/iopoll.c
+===================================================================
+--- coreutils-9.11.orig/src/iopoll.c
++++ coreutils-9.11/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,
+ {
+   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;
+ }
+Index: coreutils-9.11/src/iopoll.h
+===================================================================
+--- coreutils-9.11.orig/src/iopoll.h
++++ coreutils-9.11/src/iopoll.h
+@@ -5,5 +5,4 @@ int iopoll (int fdin, int fdout, bool bl
+ 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);
+Index: coreutils-9.11/src/tee.c
+===================================================================
+--- coreutils-9.11.orig/src/tee.c
++++ coreutils-9.11/src/tee.c
+@@ -329,7 +329,7 @@ tee_files (int nfiles, char **files, boo
+ 
+   /* 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;
+Index: coreutils-9.11/tests/local.mk
+===================================================================
+--- coreutils-9.11.orig/tests/local.mk
++++ coreutils-9.11/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			\
+Index: coreutils-9.11/tests/tee/short-write.sh
+===================================================================
+--- /dev/null
++++ coreutils-9.11/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
+Index: coreutils-9.11/tests/tee/write-eagain.sh
+===================================================================
+--- /dev/null
++++ coreutils-9.11/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
diff --git a/meta/recipes-core/coreutils/coreutils_9.11.bb b/meta/recipes-core/coreutils/coreutils_9.11.bb
index 63f7810e883..bbef3263994 100644
--- a/meta/recipes-core/coreutils/coreutils_9.11.bb
+++ b/meta/recipes-core/coreutils/coreutils_9.11.bb
@@ -18,6 +18,7 @@  SRC_URI = "${GNU_MIRROR}/coreutils/${BP}.tar.xz \
            file://run-ptest \
            file://CVE-2026-56391.patch \
            file://CVE-2026-56392.patch \
+           file://0d6fcb99d691d920961938e61c43478566ef626e.patch \
            "
 SRC_URI[sha256sum] = "394024eda0a5955217ceda9cd1201e65dc8fa3aa29c2951135a49521d57c3cc3"