[PATCH] Linux: Fix '__close_nocancel_nostatus' clobbering 'errno' [BZ #33035]
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Fri May 30 15:38:34 GMT 2025
On 30/05/25 12:30, Maciej W. Rozycki wrote:
> 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?
It is not clear neither from the bug report nor from commit message why
cloberring errno in this case causes the regression.
>
> 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);
Why not use INTERNAL_SYSCALL_CALL here? This avoid all the machinery required
to export the symbol.
> -}
> -
> /* 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