[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