Message ID | 20180318015332.9759-1-samuel.thibault@ens-lyon.org |
---|---|
State | New |
Headers | show |
Series | hurd: Fix early rtld access to errno | expand |
Samuel Thibault, on dim. 18 mars 2018 02:53:32 +0100, wrote: > * sysdeps/generic/dl-sysdep.h (RTLD_EXTERN_ERRNO): Define macro to 0. > * sysdeps/mach/hurd/i386/dl-sysdep.h: Include <dl-sysdep.h>. > [IS_IN(rtld)] (RTLD_EXTERN_ERRNO): Define macro to 1. > [!IS_IN(rtld)] (RTLD_EXTERN_ERRNO): Define macro to 0. > * include/errno.h [IS_IN(rtld) && !defined RTLD_EXTERN_ERRNO]: Error > out. > [!IS_IN(rtld)] (RTLD_EXTERN_ERRNO): Define to 0. > [RTLD_EXTERN_ERRNO]: Do not use TLS access to errno. All that being said, I'm surprised: AIUI this problem would be the same on all platforms as soon as one would set RTLD_PRIVATE_ERRNO to 0. Trying to set RTLD_PRIVATE_ERRNO to 0 on Linux x86_64 for instance, ld.so crashes in assert (info[DT_FLAGS] == NULL || (info[DT_FLAGS]->d_un.d_val & ~DF_BIND_NOW) == 0); since __thread access produces DF_STATIC_TLS. Ignoring that check just pushes the crash to open_verify()'s __set_errno call, on fs:(%eax) or fs:0 access (depending whether initial-exec TLS model is enabled or not). I guess that at that point Linux x86_64 hasn't initialized %fs yet. I tried to just disable the use of __thread access to errno in rtld with > @@ -20,7 +24,7 @@ > # define errno rtld_errno > extern int rtld_errno attribute_hidden; > > -# elif IS_IN_LIB > +# elif IS_IN_LIB && !IS_IN(rtld) > > # include <tls.h> > But that's only pushing the issue to the __errno_location() function. In sysdeps/mach/hurd/errno-loc.c I made the rtld version of __errno_location() a weak function which avoids accessing TLS by using a static variable, that function being overriden by libc as soon as it gets loaded. I'm actually wondering why not all archs would need this when RTLD_PRIVATE_ERRNO is 0. Samuel
On 03/18/2018 03:07 AM, Samuel Thibault wrote: > All that being said, I'm surprised: AIUI this problem would be the > same on all platforms as soon as one would set RTLD_PRIVATE_ERRNO to > 0. I think this is presently a knob for Hurd only. It might have been different in the LinuxThreads days, though. Thanks, Florian
diff --git a/include/errno.h b/include/errno.h index 3c3d2288c8..792f974518 100644 --- a/include/errno.h +++ b/include/errno.h @@ -7,8 +7,12 @@ # ifndef RTLD_PRIVATE_ERRNO # error "dl-sysdep.h must define RTLD_PRIVATE_ERRNO!" # endif +# ifndef RTLD_EXTERN_ERRNO +# error "dl-sysdep.h must define RTLD_EXTERN_ERRNO!" +# endif # else # define RTLD_PRIVATE_ERRNO 0 +# define RTLD_EXTERN_ERRNO 0 # endif # if RTLD_PRIVATE_ERRNO @@ -20,7 +24,7 @@ # define errno rtld_errno extern int rtld_errno attribute_hidden; -# elif IS_IN_LIB +# elif IS_IN_LIB && !RTLD_EXTERN_ERRNO # include <tls.h> diff --git a/sysdeps/generic/dl-sysdep.h b/sysdeps/generic/dl-sysdep.h index 2cb8565b5b..d787f142e9 100644 --- a/sysdeps/generic/dl-sysdep.h +++ b/sysdeps/generic/dl-sysdep.h @@ -32,3 +32,11 @@ #else # define RTLD_PRIVATE_ERRNO 0 #endif + +/* This macro must be defined to either 0 or 1. + + If 1, then ld.so will use the external errno access through + __errno_location(). This may be needed if early TLS access to + errno can not work. */ + +#define RTLD_EXTERN_ERRNO 0 diff --git a/sysdeps/mach/hurd/i386/dl-sysdep.h b/sysdeps/mach/hurd/i386/dl-sysdep.h new file mode 100644 index 0000000000..1533753a49 --- /dev/null +++ b/sysdeps/mach/hurd/i386/dl-sysdep.h @@ -0,0 +1,27 @@ +/* System-specific settings for dynamic linker code. Hurd version. + Copyright (C) 2002-2018 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 + <http://www.gnu.org/licenses/>. */ + +#include_next <dl-sysdep.h> + +/* TLS access can not work early in ld.so. */ + +#if IS_IN (rtld) +# define RTLD_EXTERN_ERRNO 1 +#else +# define RTLD_EXTERN_ERRNO 0 +#endif