[PATCH] Linux: Fix '__close_nocancel_nostatus' clobbering 'errno' [BZ #33035]

Maciej W. Rozycki macro@redhat.com
Fri May 30 15:30:56 GMT 2025


Fix fallout from commit c181840c93d3 ("Consolidate non cancellable close 
call") that caused '__close_nocancel_nostatus' to clobber 'errno' on a 
close(2) failure, a 2.27 regression.

The problem came from a rewrite from 'close_not_cancel_no_status' to 
'__close_nocancel_nostatus' switching from an inline implementation that 
used INTERNAL_SYSCALL macro (which stays away from 'errno') to a call to 
'__close_nocancel' function that uses INLINE_SYSCALL_CALL macro (which 
does poke at 'errno').

Implement '__close_nocancel_nostatus' then as a standalone function in 
terms of INTERNAL_SYSCALL_CALL, which leaves 'errno' intact.  This is a 
generic Linux version analogous to '__close_nocancel'.  Platforms may 
choose to implement an inline variant where the syscall invocation code 
sequence is short enough to be beneficial over a function call.
---
Hi,

 Spotted while proofreading an upcoming change for `if_nameindex' and 
`if_nametoindex' to remove support for obsolete pre-2.1.x Linux versions. 

 The offending commit was pushed as obvious without a review, which I 
suppose contributed to the overlooking of the change to semantics caused.  
Then close(2) failures are exceedingly rare where the syscall is made for 
a valid file descriptor, so nobody has reported an issue in the field.

 Verified with a `powerpc64le-linux-gnu' native configuration and by 
inspecting the object code produced for io/close_nocancel_nostatus.o vs 
io/close_nocancel.o.

 OK to apply?

  Maciej
---
 sysdeps/unix/sysv/linux/Makefile                  |    1 
 sysdeps/unix/sysv/linux/Versions                  |    1 
 sysdeps/unix/sysv/linux/close_nocancel_nostatus.c |   28 ++++++++++++++++++++++
 sysdeps/unix/sysv/linux/not-cancel.h              |   12 +++------
 4 files changed, 34 insertions(+), 8 deletions(-)

glibc-linux-close-nocancel-nostatus.diff
Index: glibc/sysdeps/unix/sysv/linux/Makefile
===================================================================
--- glibc.orig/sysdeps/unix/sysv/linux/Makefile
+++ glibc/sysdeps/unix/sysv/linux/Makefile
@@ -603,6 +603,7 @@ endif
 ifeq ($(subdir),io)
 sysdep_routines += \
   close_nocancel \
+  close_nocancel_nostatus \
   fallocate \
   fallocate64 \
   fcntl_nocancel \
Index: glibc/sysdeps/unix/sysv/linux/Versions
===================================================================
--- glibc.orig/sysdeps/unix/sysv/linux/Versions
+++ glibc/sysdeps/unix/sysv/linux/Versions
@@ -339,6 +339,7 @@ libc {
     __read_nocancel;
     __pread64_nocancel;
     __close_nocancel;
+    __close_nocancel_nostatus;
     __sigtimedwait;
     # functions used by nscd
     __netlink_assert_response;
Index: glibc/sysdeps/unix/sysv/linux/close_nocancel_nostatus.c
===================================================================
--- /dev/null
+++ glibc/sysdeps/unix/sysv/linux/close_nocancel_nostatus.c
@@ -0,0 +1,28 @@
+/* Linux close syscall implementation -- non-cancellable, no errno update.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <sysdep-cancel.h>
+#include <not-cancel.h>
+
+int
+__close_nocancel_nostatus (int fd)
+{
+  return INTERNAL_SYSCALL_CALL (close, fd);
+}
+libc_hidden_def (__close_nocancel_nostatus)
Index: glibc/sysdeps/unix/sysv/linux/not-cancel.h
===================================================================
--- glibc.orig/sysdeps/unix/sysv/linux/not-cancel.h
+++ glibc/sysdeps/unix/sysv/linux/not-cancel.h
@@ -53,6 +53,9 @@ __typeof (__write) __write_nocancel;
 /* Uncancelable close.  */
 __typeof (__close) __close_nocancel;
 
+/* Uncancellable close that does not also set errno in case of failure.  */
+__typeof (__close) __close_nocancel_nostatus;
+
 /* Uncancelable fcntl.  */
 int __fcntl64_nocancel (int, int, ...);
 
@@ -65,17 +68,10 @@ hidden_proto (__read_nocancel)
 hidden_proto (__pread64_nocancel)
 hidden_proto (__write_nocancel)
 hidden_proto (__close_nocancel)
+hidden_proto (__close_nocancel_nostatus)
 hidden_proto (__fcntl64_nocancel)
 #endif
 
-/* Non cancellable close syscall that does not also set errno in case of
-   failure.  */
-static inline void
-__close_nocancel_nostatus (int fd)
-{
-  __close_nocancel (fd);
-}
-
 /* Non cancellable writev syscall that does not also set errno in case of
    failure.  */
 static inline void



More information about the Libc-alpha mailing list