[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