diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | config.make.in | 1 | ||||
-rwxr-xr-x | configure | 25 | ||||
-rw-r--r-- | configure.ac | 9 | ||||
-rw-r--r-- | elf/endswith.h | 33 | ||||
-rw-r--r-- | elf/ldconfig.c | 12 | ||||
-rw-r--r-- | elf/readlib.c | 11 | ||||
-rw-r--r-- | libio/Makefile | 1 | ||||
-rw-r--r-- | libio/genops.c | 3 | ||||
-rw-r--r-- | libio/tst-closeall.c | 34 | ||||
-rw-r--r-- | manual/Makefile | 1 | ||||
-rw-r--r-- | manual/dynlink.texi | 558 | ||||
-rw-r--r-- | manual/intro.texi | 17 | ||||
-rw-r--r-- | manual/llio.texi | 34 | ||||
-rw-r--r-- | manual/macros.texi | 7 | ||||
-rw-r--r-- | manual/socket.texi | 52 | ||||
-rw-r--r-- | manual/startup.texi | 22 | ||||
-rw-r--r-- | manual/threads.texi | 8 | ||||
-rw-r--r-- | po/bg.po | 147 | ||||
-rw-r--r-- | socket/Makefile | 1 | ||||
-rw-r--r-- | socket/tst-shutdown.c | 257 | ||||
-rw-r--r-- | stdlib/arc4random.c | 2 | ||||
-rw-r--r-- | sysdeps/m68k/m680x0/fpu/libm-test-ulps | 451 | ||||
-rw-r--r-- | sysdeps/nptl/dl-tls_init_tp.c | 12 | ||||
-rw-r--r-- | sysdeps/riscv/nofpu/libm-test-ulps | 20 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/Makefile | 4 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/dl-rseq-symbols.S | 64 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/rseq-internal.h | 23 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/tst-rseq.c | 10 |
29 files changed, 1656 insertions, 166 deletions
diff --git a/NEWS b/NEWS index f626896aa0..3824815917 100644 --- a/NEWS +++ b/NEWS @@ -49,6 +49,9 @@ Deprecated and removed features, and other changes affecting compatibility: <utmpx.h> (except for login_tty) due to locking and session management problems. +* __rseq_size now denotes the size of the active rseq area (20 bytes + initially), not the size of struct rseq (32 bytes initially). + Changes to build and runtime requirements: [Add changes to build and runtime requirements here] diff --git a/config.make.in b/config.make.in index 55e8b7563b..36096881b7 100644 --- a/config.make.in +++ b/config.make.in @@ -91,6 +91,7 @@ use-nscd = @use_nscd@ build-hardcoded-path-in-tests= @hardcoded_path_in_tests@ build-pt-chown = @build_pt_chown@ pthread-in-libc = @pthread_in_libc@ +man-pages-version = @man_pages_version@ # Build tools. CC = @CC@ diff --git a/configure b/configure index 1bae55b45b..1d543548cd 100755 --- a/configure +++ b/configure @@ -699,6 +699,7 @@ force_install bindnow hardcoded_path_in_tests enable_timezone_tools +man_pages_version rtld_early_cflags extra_nonshared_cflags sysheaders @@ -782,6 +783,7 @@ with_headers with_nonshared_cflags with_rtld_early_cflags with_timeoutfactor +with_man_pages enable_sanity_checks enable_shared enable_profile @@ -1508,6 +1510,8 @@ Optional Packages: build early initialization with additional CFLAGS --with-timeoutfactor=NUM specify an integer to scale the timeout + --with-man-pages=VERSION + tie manual to a specific man-pages version --with-cpu=CPU select code for CPU variant Some influential environment variables: @@ -3868,8 +3872,9 @@ config_vars= if test ${enable_static_c___tests+y} then : enableval=$enable_static_c___tests; static_cxx_tests=$enableval -else $as_nop - static_cxx_tests=yes +else case e in #( + e) static_cxx_tests=yes ;; +esac fi config_vars="$config_vars @@ -3879,8 +3884,9 @@ static-cxx-tests = $static_cxx_tests" if test ${enable_static_c___link_check+y} then : enableval=$enable_static_c___link_check; static_cxx_link_check=$enableval -else $as_nop - static_cxx_link_check=yes +else case e in #( + e) static_cxx_link_check=yes ;; +esac fi @@ -4469,6 +4475,17 @@ fi printf "%s\n" "#define TIMEOUTFACTOR $timeoutfactor" >>confdefs.h +man_pages_version=6.9.1 + + +# Check whether --with-man-pages was given. +if test ${with_man_pages+y} +then : + withval=$with_man_pages; man_pages_version=$withval +fi + + + # Check whether --enable-sanity-checks was given. if test ${enable_sanity_checks+y} then : diff --git a/configure.ac b/configure.ac index e48957f318..9cbc0bf68f 100644 --- a/configure.ac +++ b/configure.ac @@ -183,6 +183,15 @@ AC_ARG_WITH([timeoutfactor], [timeoutfactor=1]) AC_DEFINE_UNQUOTED(TIMEOUTFACTOR, $timeoutfactor) +man_pages_version=6.9.1 + +AC_ARG_WITH([man-pages], + AS_HELP_STRING([--with-man-pages=VERSION], + [tie manual to a specific man-pages version]), + [man_pages_version=$withval], + []) +AC_SUBST(man_pages_version) + AC_ARG_ENABLE([sanity-checks], AS_HELP_STRING([--disable-sanity-checks], [really do not use threads (should not be used except in special situations) @<:@default=yes@:>@]), diff --git a/elf/endswith.h b/elf/endswith.h new file mode 100644 index 0000000000..c6430c48be --- /dev/null +++ b/elf/endswith.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2023-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; version 2 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#ifndef _ENDSWITH_H +#define _ENDSWITH_H + +#include <string.h> + +/* Return true if the N bytes at NAME end with with the characters in + the string SUFFIX. (NAME[N + 1] does not have to be a null byte.) + Expected to be called with a string literal for SUFFIX. */ +static inline bool +endswithn (const char *name, size_t n, const char *suffix) +{ + return (n >= strlen (suffix) + && memcmp (name + n - strlen (suffix), suffix, + strlen (suffix)) == 0); +} + +#endif /* _ENDSWITH_H */ diff --git a/elf/ldconfig.c b/elf/ldconfig.c index b64c54b53e..0f3ef707dd 100644 --- a/elf/ldconfig.c +++ b/elf/ldconfig.c @@ -40,6 +40,7 @@ #include <libgen.h> #include <ldconfig.h> +#include <endswith.h> #include <dl-cache.h> #include <dl-hwcaps.h> #include <dl-is_dso.h> @@ -661,17 +662,6 @@ struct dlib_entry struct dlib_entry *next; }; -/* Return true if the N bytes at NAME end with with the characters in - the string SUFFIX. (NAME[N + 1] does not have to be a null byte.) - Expected to be called with a string literal for SUFFIX. */ -static inline bool -endswithn (const char *name, size_t n, const char *suffix) -{ - return (n >= strlen (suffix) - && memcmp (name + n - strlen (suffix), suffix, - strlen (suffix)) == 0); -} - /* Skip some temporary DSO files. These files may be partially written and lead to ldconfig crashes when examined. */ static bool diff --git a/elf/readlib.c b/elf/readlib.c index 4d67c74136..f3129c4557 100644 --- a/elf/readlib.c +++ b/elf/readlib.c @@ -33,6 +33,7 @@ #include <gnu/lib-names.h> #include <ldconfig.h> +#include <endswith.h> #define Elf32_CLASS ELFCLASS32 #define Elf64_CLASS ELFCLASS64 @@ -43,12 +44,14 @@ struct known_names int flag; }; -/* Check if string corresponds to a GDB Python file. */ +/* Check if string corresponds to a GDB extension file. */ static bool -is_gdb_python_file (const char *name) +is_gdb_extension_file (const char *name) { size_t len = strlen (name); - return len > 7 && strcmp (name + len - 7, "-gdb.py") == 0; + return (endswithn (name, len, "-gdb.gdb") + || endswithn (name, len, "-gdb.py") + || endswithn (name, len, "-gdb.scm")); } /* Returns 0 if everything is ok, != 0 in case of error. */ @@ -145,7 +148,7 @@ process_file (const char *real_file_name, const char *file_name, size_t len = MIN (statbuf.st_size, 512); if (memmem (file_contents, len, "GROUP", 5) == NULL && memmem (file_contents, len, "GNU ld script", 13) == NULL - && !is_gdb_python_file (file_name)) + && !is_gdb_extension_file (file_name)) error (0, 0, _("%s is not an ELF file - it has the wrong magic bytes at the start.\n"), file_name); ret = 1; diff --git a/libio/Makefile b/libio/Makefile index 8720381fdc..6a507b67ea 100644 --- a/libio/Makefile +++ b/libio/Makefile @@ -91,6 +91,7 @@ tests = \ tst-bz24051 \ tst-bz24153 \ tst-bz28828 \ + tst-closeall \ tst-eof \ tst-ext \ tst-ext2 \ diff --git a/libio/genops.c b/libio/genops.c index 994ee9c0b1..99f5e80f20 100644 --- a/libio/genops.c +++ b/libio/genops.c @@ -119,7 +119,8 @@ _IO_link_in (struct _IO_FILE_plus *fp) if (_IO_vtable_offset ((FILE *) fp) == 0) { fp->file._prevchain = (FILE **) &_IO_list_all; - _IO_list_all->file._prevchain = &fp->file._chain; + if (_IO_list_all != NULL) + _IO_list_all->file._prevchain = &fp->file._chain; } _IO_list_all = fp; #ifdef _IO_MTSAFE_IO diff --git a/libio/tst-closeall.c b/libio/tst-closeall.c new file mode 100644 index 0000000000..34f5246490 --- /dev/null +++ b/libio/tst-closeall.c @@ -0,0 +1,34 @@ +/* Test that opening a file when all files are closed does not crash (bug 31963) + Copyright (C) 2024 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 <support/check.h> +#include <support/xstdio.h> + +static int +do_test (void) +{ + xfclose (stdin); + xfclose (stdout); + xfclose (stderr); + FILE *f = xfopen ("/dev/null", "w"); + fprintf (f, "final\n"); + xfclose (f); + return 0; +} + +#include <support/test-driver.c> diff --git a/manual/Makefile b/manual/Makefile index b5fda4a7ae..a6c05db540 100644 --- a/manual/Makefile +++ b/manual/Makefile @@ -117,6 +117,7 @@ $(objpfx)stamp-pkgvers: $(common-objpfx)config.make echo "@set PKGVERSION_DEFAULT" >> $(objpfx)pkgvers-tmp; \ fi echo "@set REPORT_BUGS_TO $(REPORT_BUGS_TEXI)" >> $(objpfx)pkgvers-tmp + echo "@set man_pages_version $(man-pages-version)" >> $(objpfx)pkgvers-tmp; \ echo "@end ifclear" >> $(objpfx)pkgvers-tmp $(move-if-change) $(objpfx)pkgvers-tmp $(objpfx)pkgvers.texi touch $@ diff --git a/manual/dynlink.texi b/manual/dynlink.texi index d71f7a30d6..03565d4fb0 100644 --- a/manual/dynlink.texi +++ b/manual/dynlink.texi @@ -15,6 +15,7 @@ Dynamic linkers are sometimes called @dfn{dynamic loaders}. @menu * Dynamic Linker Invocation:: Explicit invocation of the dynamic linker. * Dynamic Linker Introspection:: Interfaces for querying mapping information. +* Dynamic Linker Hardening:: Avoiding unexpected issues with dynamic linking. @end menu @node Dynamic Linker Invocation @@ -535,6 +536,563 @@ information is processed. This function is a GNU extension. @end deftypefun +@node Dynamic Linker Hardening +@section Avoiding Unexpected Issues With Dynamic Linking + +This section details recommendations for increasing application +robustness, by avoiding potential issues related to dynamic linking. +The recommendations have two main aims: reduce the involvement of the +dynamic linker in application execution after process startup, and +restrict the application to a dynamic linker feature set whose behavior +is more easily understood. + +Key aspects of limiting dynamic linker usage after startup are: no use +of the @code{dlopen} function, disabling lazy binding, and using the +static TLS model. More easily understood dynamic linker behavior +requires avoiding name conflicts (symbols and sonames) and highly +customizable features like the audit subsystem. + +Note that while these steps can be considered a form of application +hardening, they do not guard against potential harm from accidental or +deliberate loading of untrusted or malicious code. There is only +limited overlap with traditional security hardening for applications +running on GNU systems. + +@subsection Restricted Dynamic Linker Features + +Avoiding certain dynamic linker features can increase predictability of +applications and reduce the risk of running into dynamic linker defects. + +@itemize @bullet +@item +Do not use the functions @code{dlopen}, @code{dlmopen}, or +@code{dlclose}. Dynamic loading and unloading of shared objects +introduces substantial complications related to symbol and thread-local +storage (TLS) management. + +@item +Without the @code{dlopen} function, @code{dlsym} and @code{dlvsym} +cannot be used with shared object handles. Minimizing the use of both +functions is recommended. If they have to be used, only the +@code{RTLD_DEFAULT} pseudo-handle should be used. + +@item +Use the local-exec or initial-exec TLS models. If @code{dlopen} is not +used, there are no compatibility concerns for initial-exec TLS. This +TLS model avoids most of the complexity around TLS access. In +particular, there are no TLS-related run-time memory allocations after +process or thread start. + +If shared objects are expected to be used more generally, outside the +hardened, feature-restricted context, lack of compatibility between +@code{dlopen} and initial-exec TLS could be a concern. In that case, +the second-best alternative is to use global-dynamic TLS with GNU2 TLS +descriptors, for targets that fully implement them, including the fast +path for access to TLS variables defined in the initially loaded set of +objects. Like initial-exec TLS, this avoids memory allocations after +thread creation, but only if the @code{dlopen} function is not used. + +@item +Do not use lazy binding. Lazy binding may require run-time memory +allocation, is not async-signal-safe, and introduces considerable +complexity. + +@item +Make dependencies on shared objects explicit. Do not assume that +certain libraries (such as @code{libc.so.6}) are always loaded. +Specifically, if a main program or shared object references a symbol, +create an ELF @code{DT_NEEDED} dependency on that shared object, or on +another shared object that is documented (or otherwise guaranteed) to +have the required explicit dependency. Referencing a symbol without a +matching link dependency results in underlinking, and underlinked +objects cannot always be loaded correctly: Initialization of objects may +not happen in the required order. + +@item +Do not create dependency loops between shared objects (@code{libA.so.1} +depending on @code{libB.so.1} depending on @code{libC.so.1} depending on +@code{libA.so.1}). @Theglibc{} has to initialize one of the objects in +the cycle first, and the choice of that object is arbitrary and can +change over time. The object which is initialized first (and other +objects involved in the cycle) may not run correctly because not all of +its dependencies have been initialized. + +Underlinking (see above) can hide the presence of cycles. + +@item +Limit the creation of indirect function (IFUNC) resolvers. These +resolvers run during relocation processing, when @theglibc{} is not in +a fully consistent state. If you write your own IFUNC resolvers, do +not depend on external data or function references in those resolvers. + +@item +Do not use the audit functionality (@code{LD_AUDIT}, @code{DT_AUDIT}, +@code{DT_DEPAUDIT}). Its callback and hooking capabilities introduce a +lot of complexity and subtly alter dynamic linker behavior in corner +cases even if the audit module is inactive. + +@item +Do not use symbol interposition. Without symbol interposition, the +exact order in which shared objects are searched are less relevant. + +Exceptions to this rule are copy relocations (see the next item), and +vague linkage, as used by the C++ implementation (see below). + +@item +One potential source of symbol interposition is a combination of static +and dynamic linking, namely linking a static archive into multiple +dynamic shared objects. For such scenarios, the static library should +be converted into its own dynamic shared object. + +A different approach to this situation uses hidden visibility for +symbols in the static library, but this can cause problems if the +library does not expect that multiple copies of its code coexist within +the same process, with no or partial sharing of state. + +@item +If you use shared objects that are linked with @option{-Wl,-Bsymbolic} +(or equivalent) or use protected visibility, the code for the main +program must be built as @option{-fpic} or @option{-fPIC} to avoid +creating copy relocations (and the main program must not use copy +relocations for other reasons). Using @option{-fpie} or @option{-fPIE} +is not an alternative to PIC code in this context. + +@item +Be careful about explicit section annotations. Make sure that the +target section matches the properties of the declared entity (e.g., no +writable objects in @code{.text}). + +@item +Ensure that all assembler or object input files have the recommended +security markup, particularly for non-executable stack. + +@item +Avoid using non-default linker flags and features. In particular, do +not use the @code{DT_PREINIT_ARRAY} dynamic tag, and do not flag +objects as @code{DF_1_INITFIRST}. Do not change the default linker +script of BFD ld. Do not override ABI defaults, such as the dynamic +linker path (with @option{--dynamic-linker}). + +@item +Some features of @theglibc{} indirectly depend on run-time code loading +and @code{dlopen}. Use @code{iconv_open} with built-in converters only +(such as @code{UTF-8}). Do not use NSS functionality such as +@code{getaddrinfo} or @code{getpwuid_r} unless the system is configured +for built-in NSS service modules only (see below). +@end itemize + +Several considerations apply to ELF constructors and destructors. + +@itemize @bullet +@item +The dynamic linker does not take constructor and destructor priorities +into account when determining their execution order. Priorities are +only used by the link editor for ordering execution within a +completely linked object. If a dynamic shared object needs to be +initialized before another object, this can be expressed with a +@code{DT_NEEDED} dependency on the object that needs to be initialized +earlier. + +@item +The recommendations to avoid cyclic dependencies and symbol +interposition make it less likely that ELF objects are accessed before +their ELF constructors have run. However, using @code{dlsym} and +@code{dlvsym}, it is still possible to access uninitialized facilities +even with these restrictions in place. (Of course, access to +uninitialized functionality is also possible within a single shared +object or the main executable, without resorting to explicit symbol +lookup.) Consider using dynamic, on-demand initialization instead. To +deal with access after de-initialization, it may be necessary to +implement special cases for that scenario, potentially with degraded +functionality. + +@item +Be aware that when ELF destructors are executed, it is possible to +reference already-deconstructed shared objects. This can happen even in +the absence of @code{dlsym} and @code{dlvsym} function calls, for +example if client code using a shared object has registered callbacks or +objects with another shared object. The ELF destructor for the client +code is executed before the ELF destructor for the shared objects that +it uses, based on the expected dependency order. + +@item +If @code{dlopen} and @code{dlmopen} are not used, @code{DT_NEEDED} +dependency information is complete, and lazy binding is disabled, the +execution order of ELF destructors is expected to be the reverse of the +ELF constructor order. However, two separate dependency sort operations +still occur. Even though the listed preconditions should ensure that +both sorts produce the same ordering, it is recommended not to depend on +the destructor order being the reverse of the constructor order. +@end itemize + +The following items provide C++-specific guidance for preparing +applications. If another programming language is used and it uses these +toolchain features targeted at C++ to implement some language +constructs, these restrictions and recommendations still apply in +analogous ways. + +@itemize @bullet +@item +C++ inline functions, templates, and other constructs may need to be +duplicated into multiple shared objects using vague linkage, resulting +in symbol interposition. This type of symbol interposition is +unproblematic, as long as the C++ one definition rule (ODR) is followed, +and all definitions in different translation units are equivalent +according to the language C++ rules. + +@item +Be aware that under C++ language rules, it is unspecified whether +evaluating a string literal results in the same address for each +evaluation. This also applies to anonymous objects of static storage +duration that GCC creates, for example to implement the compound +literals C++ extension. As a result, comparing pointers to such +objects, or using them directly as hash table keys, may give unexpected +results. + +By default, variables of block scope of static storage have consistent +addresses across different translation units, even if defined in +functions that use vague linkage. + +@item +Special care is needed if a C++ project uses symbol visibility or +symbol version management (for example, the GCC @samp{visibility} +attribute, the GCC @option{-fvisibility} option, or a linker version +script with the linker option @option{--version-script}). It is +necessary to ensure that the symbol management remains consistent with +how the symbols are used. Some C++ constructs are implemented with +the help of ancillary symbols, which can make complicated to achieve +consistency. For example, an inline function that is always inlined +into its callers has no symbol footprint for the function itself, but +if the function contains a variable of static storage duration, this +variable may result in the creation of one or more global symbols. +For correctness, such symbols must be visible and bound to the same +object in all other places where the inline function may be called. +This requirement is not met if the symbol visibility is set to hidden, +or if symbols are assigned a textually different symbol version +(effectively creating two distinct symbols). + +Due to the complex interaction between ELF symbol management and C++ +symbol generation, it is recommended to use C++ language features for +symbol management, in particular inline namespaces. + +@item +The toolchain and dynamic linker have multiple mechanisms that bypass +the usual symbol binding procedures. This means that the C++ one +definition rule (ODR) still holds even if certain symbol-based isolation +mechanisms are used, and object addresses are not shared across +translation units with incompatible type definitions. + +This does not matter if the original (language-independent) advice +regarding symbol interposition is followed. However, as the advice may +be difficult to implement for C++ applications, it is recommended to +avoid ODR violations across the entire process image. Inline namespaces +can be helpful in this context because they can be used to create +distinct ELF symbols while maintaining source code compatibility at the +C++ level. + +@item +Be aware that as a special case of interposed symbols, symbols with the +@code{STB_GNU_UNIQUE} binding type do not follow the usual ELF symbol +namespace isolation rules: such symbols bind across @code{RTLD_LOCAL} +boundaries. Furthermore, symbol versioning is ignored for such symbols; +they are bound by symbol name only. All their definitions and uses must +therefore be compatible. Hidden visibility still prevents the creation +of @code{STB_GNU_UNIQUE} symbols and can achieve isolation of +incompatible definitions. + +@item +C++ constructor priorities only affect constructor ordering within one +shared object. Global constructor order across shared objects is +consistent with ELF dependency ordering if there are no ELF dependency +cycles. + +@item +C++ exception handling and run-time type information (RTTI), as +implemented in the GNU toolchain, is not address-significant, and +therefore is not affected by the symbol binding behaviour of the dynamic +linker. This means that types of the same fully-qualified name (in +non-anonymous namespaces) are always considered the same from an +exception-handling or RTTI perspective. This is true even if the type +information object or vtable has hidden symbol visibility, or the +corresponding symbols are versioned under different symbol versions, or +the symbols are not bound to the same objects due to the use of +@code{RTLD_LOCAL} or @code{dlmopen}. + +This can cause issues in applications that contain multiple incompatible +definitions of the same type. Inline namespaces can be used to create +distinct symbols at the ELF layer, avoiding this type of issue. + +@item +C++ exception handling across multiple @code{dlmopen} namespaces may +not work, particular with the unwinder in GCC versions before 12. +Current toolchain versions are able to process unwinding tables across +@code{dlmopen} boundaries. However, note that type comparison is +name-based, not address-based (see the previous item), so exception +types may still be matched in unexpected ways. An important special +case of exception handling, invoking destructors for variables of block +scope, is not impacted by this RTTI type-sharing. Likewise, regular +virtual member function dispatch for objects is unaffected (but still +requires that the type definitions match in all directly involved +translation units). + +Once more, inline namespaces can be used to create distinct ELF symbols +for different types. + +@item +Although the C++ standard requires that destructors for global objects +run in the opposite order of their constructors, the Itanium C++ ABI +requires a different destruction order in some cases. As a result, do +not depend on the precise destructor invocation order in applications +that use @code{dlclose}. + +@item +Registering destructors for later invocation allocates memory and may +silently fail if insufficient memory is available. As a result, the +destructor is never invoked. This applies to all forms of destructor +registration, with the exception of thread-local variables (see the next +item). To avoid this issue, ensure that such objects merely have +trivial destructors, avoiding the need for registration, and deallocate +resources using a different mechanism (for example, from an ELF +destructor). + +@item +A similar issue exists for @code{thread_local} variables with thread +storage duration of types that have non-trivial destructors. However, +in this case, memory allocation failure during registration leads to +process termination. If process termination is not acceptable, use +@code{thread_local} variables with trivial destructors only. +Functions for per-thread cleanup can be registered using +@code{pthread_key_create} (globally for all threads) and activated +using @code{pthread_setspecific} (on each thread). Note that a +@code{pthread_key_create} call may still fail (and +@code{pthread_create} keys are a limited resource in @theglibc{}), but +this failure can be handled without terminating the process. +@end itemize + +@subsection Producing Matching Binaries + +This subsection recommends tools and build flags for producing +applications that meet the recommendations of the previous subsection. + +@itemize @bullet +@item +Use BFD ld (@command{bfd.ld}) from GNU binutils to produce binaries, +invoked through a compiler driver such as @command{gcc}. The version +should be not too far ahead of what was current when the version of +@theglibc{} was first released. + +@item +Do not use a binutils release that is older than the one used to build +@theglibc{} itself. + +@item +Compile with @option{-ftls-model=initial-exec} to force the initial-exec +TLS model. + +@item +Link with @option{-Wl,-z,now} to disable lazy binding. + +@item +Link with @option{-Wl,-z,relro} to enable RELRO (which is the default on +most targets). + +@item +Specify all direct shared objects dependencies using @option{-l} options +to avoid underlinking. Rely on @code{.so} files (which can be linker +scripts) and searching with the @option{-l} option. Do not specify the +file names of shared objects on the linker command line. + +@item +Consider using @option{-Wl,-z,defs} to treat underlinking as an error +condition. + +@item +When creating a shared object (linked with @option{-shared}), use +@option{-Wl,-soname,lib@dots{}} to set a soname that matches the final +installed name of the file. + +@item +Do not use the @option{-rpath} linker option. (As explained below, all +required shared objects should be installed into the default search +path.) + +@item +Use @option{-Wl,--error-rwx-segments} and @option{-Wl,--error-execstack} to +instruct the link editor to fail the link if the resulting final object +would have read-write-execute segments or an executable stack. Such +issues usually indicate that the input files are not marked up +correctly. + +@item +Ensure that for each @code{LOAD} segment in the ELF program header, file +offsets, memory sizes, and load addresses are multiples of the largest +page size supported at run time. Similarly, the start address and size +of the @code{GNU_RELRO} range should be multiples of the page size. + +Avoid creating gaps between @code{LOAD} segments. The difference +between the load addresses of two subsequent @code{LOAD} segments should +be the size of the first @code{LOAD} segment. (This may require linking +with @option{-Wl,-z,noseparate-code}.) + +This may not be possible to achieve with the currently available link +editors. + +@item +If the multiple-of-page-size criterion for the @code{GNU_RELRO} region +cannot be achieved, ensure that the process memory image right before +the start of the region does not contain executable or writable memory. +@c https://sourceware.org/pipermail/libc-alpha/2022-May/138638.html +@end itemize + +@subsection Checking Binaries + +In some cases, if the previous recommendations are not followed, this +can be determined from the produced binaries. This section contains +suggestions for verifying aspects of these binaries. + +@itemize @bullet +@item +To detect underlinking, examine the dynamic symbol table, for example +using @samp{readelf -sDW}. If the symbol is defined in a shared object +that uses symbol versioning, it must carry a symbol version, as in +@samp{pthread_kill@@GLIBC_2.34}. + +@item +Examine the dynamic segment with @samp{readelf -dW} to check that all +the required @code{NEEDED} entries are present. (It is not necessary to +list indirect dependencies if these dependencies are guaranteed to +remain during the evolution of the explicitly listed direct +dependencies.) + +@item +The @code{NEEDED} entries should not contain full path names including +slashes, only @code{sonames}. + +@item +For a further consistency check, collect all shared objects referenced +via @code{NEEDED} entries in dynamic segments, transitively, starting at +the main program. Then determine their dynamic symbol tables (using +@samp{readelf -sDW}, for example). Ideally, every symbol should be +defined at most once, so that symbol interposition does not happen. + +If there are interposed data symbols, check if the single interposing +definition is in the main program. In this case, there must be a copy +relocation for it. (This only applies to targets with copy relocations.) + +Function symbols should only be interposed in C++ applications, to +implement vague linkage. (See the discussion in the C++ recommendations +above.) + +@item +Using the previously collected @code{NEEDED} entries, check that the +dependency graph does not contain any cycles. + +@item +The dynamic segment should also mention @code{BIND_NOW} on the +@code{FLAGS} line or @code{NOW} on the @code{FLAGS_1} line (one is +enough). + +@item +For shared objects (not main programs), if the program header has a +@code{PT_TLS} segment, the dynamic segment (as shown by @samp{readelf +-dW}) should contain the @code{STATIC_TLS} flag on the @code{FLAGS} +line. + +If @code{STATIC_TLS} is missing in shared objects, ensure that the +appropriate relocations for GNU2 TLS descriptors are used (for example, +@code{R_AARCH64_TLSDESC} or @code{R_X86_64_TLSDESC}). + +@item +There should not be a reference to the symbols @code{__tls_get_addr}, +@code{__tls_get_offset}, @code{__tls_get_addr_opt} in the dynamic symbol +table (in the @samp{readelf -sDW} output). Thread-local storage must be +accessed using the initial-exec (static) model, or using GNU2 TLS +descriptors. + +@item +Likewise, the functions @code{dlopen}, @code{dlmopen}, @code{dlclose} +should not be referenced from the dynamic symbol table. + +@item +For shared objects, there should be a @code{SONAME} entry that matches +the file name (the base name, i.e., the part after the slash). The +@code{SONAME} string must not contain a slash @samp{/}. + +@item +For all objects, the dynamic segment (as shown by @samp{readelf -dW}) +should not contain @code{RPATH} or @code{RUNPATH} entries. + +@item +Likewise, the dynamic segment should not show any @code{AUDIT}, +@code{DEPAUDIT}, @code{AUXILIARY}, @code{FILTER}, or +@code{PREINIT_ARRAY} tags. + +@item +If the dynamic segment contains a (deprecated) @code{HASH} tag, it +must also contain a @code{GNU_HASH} tag. + +@item +The @code{INITFIRST} flag (undeer @code{FLAGS_1}) should not be used. + +@item +The program header must not have @code{LOAD} segments that are writable +and executable at the same time. + +@item +All produced objects should have a @code{GNU_STACK} program header that +is not marked as executable. (However, on some newer targets, a +non-executable stack is the default, so the @code{GNU_STACK} program +header is not required.) +@end itemize + +@subsection Run-time Considerations + +In addition to preparing program binaries in a recommended fashion, the +run-time environment should be set up in such a way that problematic +dynamic linker features are not used. + +@itemize @bullet +@item +Install shared objects using their sonames in a default search path +directory (usually @file{/usr/lib64}). Do not use symbolic links. +@c This is currently not standard practice. + +@item +The default search path must not contain objects with duplicate file +names or sonames. + +@item +Do not use environment variables (@code{LD_@dots{}} variables such as +@code{LD_PRELOAD} or @code{LD_LIBRARY_PATH}, or @code{GLIBC_TUNABLES}) +to change default dynamic linker behavior. + +@item +Do not install shared objects in non-default locations. (Such locations +are listed explicitly in the configuration file for @command{ldconfig}, +usually @file{/etc/ld.so.conf}, or in files included from there.) + +@item +In relation to the previous item, do not install any objects it +@code{glibc-hwcaps} subdirectories. + +@item +Do not configure dynamically-loaded NSS service modules, to avoid +accidental internal use of the @code{dlopen} facility. The @code{files} +and @code{dns} modules are built in and do not rely on @code{dlopen}. + +@item +Do not truncate and overwrite files containing programs and shared +objects in place, while they are used. Instead, write the new version +to a different path and use @code{rename} to replace the +already-installed version. + +@item +Be aware that during a component update procedure that involves multiple +object files (shared objects and main programs), concurrently starting +processes may observe an inconsistent combination of object files (some +already updated, some still at the previous version). For example, +this can happen during an update of @theglibc{} itself. +@end itemize @c FIXME these are undocumented: @c dladdr diff --git a/manual/intro.texi b/manual/intro.texi index ff43c5a7fb..879c1b38d9 100644 --- a/manual/intro.texi +++ b/manual/intro.texi @@ -85,6 +85,7 @@ standards each function or symbol comes from. * Berkeley Unix:: BSD and SunOS. * SVID:: The System V Interface Description. * XPG:: The X/Open Portability Guide. +* Linux Kernel:: The Linux kernel. @end menu @node ISO C, POSIX, , Standards and Portability @@ -941,7 +942,7 @@ inter-process communication and shared memory, the @code{hsearch} and @code{drand48} families of functions, @code{fmtmsg} and several of the mathematical functions. -@node XPG, , SVID, Standards and Portability +@node XPG, Linux Kernel, SVID, Standards and Portability @subsection XPG (The X/Open Portability Guide) The X/Open Portability Guide, published by the X/Open Company, Ltd., is @@ -960,6 +961,20 @@ fulfilling the XPG standard with the Unix extensions is a precondition for getting the Unix brand chances are good that the functionality is available on commercial systems. +@node Linux Kernel, , XPG, Standards and Portability +@subsection Linux (The Linux Kernel) + +@Theglibc{} includes by reference the Linux man-pages +@value{man_pages_version} documentation to document the listed +syscalls for the Linux kernel. For reference purposes only the latest +@uref{https://www.kernel.org/doc/man-pages/,Linux man-pages Project} +documentation can be accessed from the +@uref{https://www.kernel.org,Linux kernel} website. Where the syscall +has more specific documentation in this manual that more specific +documentation is considered authoritative. + +Additional details on the Linux system call interface can be found in +@xref{System Calls}. @node Using the Library, Roadmap to the Manual, Standards and Portability, Introduction @section Using the Library diff --git a/manual/llio.texi b/manual/llio.texi index 78c7c79913..6f0a48609b 100644 --- a/manual/llio.texi +++ b/manual/llio.texi @@ -65,6 +65,7 @@ directly.) * Interrupt Input:: Getting an asynchronous signal when input arrives. * IOCTLs:: Generic I/O Control operations. +* Other Low-Level I/O APIs:: Other low-level-I/O-related functions. @end menu @@ -2324,6 +2325,8 @@ file descriptor, or until the timeout period expires. There is another example showing the use of @code{select} to multiplex input from multiple sockets in @ref{Server Example}. +For an alternate interface to this functionality, see @code{poll} +(@pxref{Other Low-Level I/O APIs}). @node Synchronizing I/O @section Synchronizing I/O operations @@ -3407,7 +3410,9 @@ require additional arguments to be supplied. These additional arguments and the return value and error conditions are given in the detailed descriptions of the individual commands. -Briefly, here is a list of what the various commands are. +Briefly, here is a list of what the various commands are. For an +exhaustive list of kernel-specific options, please see @xref{System +Calls}. @vtable @code @item F_DUPFD @@ -4743,5 +4748,28 @@ Most IOCTLs are OS-specific and/or only used in special system utilities, and are thus beyond the scope of this document. For an example of the use of an IOCTL, see @ref{Out-of-Band Data}. -@c FIXME this is undocumented: -@c dup3 +@node Other Low-Level I/O APIs +@section Other low-level-I/O-related functions + +@deftp {Data Type} {struct pollfd} +@standards{POSIX.1,poll.h} +@end deftp + +@deftp {Data Type} {struct epoll_event} +@standards{Linux,sys/epoll.h} +@end deftp + +@deftypefun int poll (struct pollfd *@var{fds}, nfds_t @var{nfds}, int @var{timeout}) + +@manpagefunctionstub{poll,2} +@end deftypefun + +@deftypefun int epoll_create(int @var{size}) + +@manpagefunctionstub{epoll_create,2} +@end deftypefun + +@deftypefun int epoll_wait(int @var{epfd}, struct epoll_event *@var{events}, int @var{maxevents}, int @var{timeout}) + +@manpagefunctionstub{epoll_wait,2} +@end deftypefun diff --git a/manual/macros.texi b/manual/macros.texi index 4a2e22f473..579da3fb81 100644 --- a/manual/macros.texi +++ b/manual/macros.texi @@ -282,4 +282,11 @@ cwd\comments\ @macro standardsx {element, standard, header} @end macro +@macro manpagefunctionstub {func,sec} +This documentation is a stub. For additional information on this +function, consult the manual page +@url{https://man7.org/linux/man-pages/man\sec\/\func\.\sec\.html}. +@xref{Linux Kernel}. +@end macro + @end ifclear diff --git a/manual/socket.texi b/manual/socket.texi index f0e35d9e13..8708cbb07c 100644 --- a/manual/socket.texi +++ b/manual/socket.texi @@ -41,6 +41,7 @@ aren't documented either so far. is to make it work with Inetd. * Socket Options:: Miscellaneous low-level socket options. * Networks Database:: Accessing the database of network names. +* Other Socket APIs:: Other socket-related functions. @end menu @node Socket Concepts @@ -3134,38 +3135,8 @@ You can use plain @code{recv} (@pxref{Receiving Data}) instead of treat all possible senders alike). Even @code{read} can be used if you don't want to specify @var{flags} (@pxref{I/O Primitives}). -@ignore -@c sendmsg and recvmsg are like readv and writev in that they -@c use a series of buffers. It's not clear this is worth -@c supporting or that we support them. -@c !!! they can do more; it is hairy - -@deftp {Data Type} {struct msghdr} -@standards{BSD, sys/socket.h} -@end deftp - -@deftypefun ssize_t sendmsg (int @var{socket}, const struct msghdr *@var{message}, int @var{flags}) -@standards{BSD, sys/socket.h} -@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} - -This function is defined as a cancellation point in multi-threaded -programs, so one has to be prepared for this and make sure that -allocated resources (like memory, files descriptors, semaphores or -whatever) are freed even if the thread is cancel. -@c @xref{pthread_cleanup_push}, for a method how to do this. -@end deftypefun - -@deftypefun ssize_t recvmsg (int @var{socket}, struct msghdr *@var{message}, int @var{flags}) -@standards{BSD, sys/socket.h} -@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} - -This function is defined as a cancellation point in multi-threaded -programs, so one has to be prepared for this and make sure that -allocated resources (like memory, files descriptors, semaphores or -whatever) are freed even if the thread is canceled. -@c @xref{pthread_cleanup_push}, for a method how to do this. -@end deftypefun -@end ignore +If you need more flexibility and/or control over sending and receiving +packets, see @code{sendmsg} and @code{recvmsg} (@pxref{Other Socket APIs}). @node Datagram Example @subsection Datagram Socket Example @@ -3664,3 +3635,20 @@ returns a null pointer if there are no more entries. @c libc_lock_unlock @aculock This function closes the networks database. @end deftypefun + +@node Other Socket APIs +@section Other Socket APIs + +@deftp {Data Type} {struct msghdr} +@standards{BSD, sys/socket.h} +@end deftp + +@deftypefun ssize_t sendmsg (int @var{socket}, const struct msghdr *@var{message}, int @var{flags}) + +@manpagefunctionstub{sendmsg,2} +@end deftypefun + +@deftypefun ssize_t recvmsg (int @var{socket}, struct msghdr *@var{message}, int @var{flags}) + +@manpagefunctionstub{recvmsg,2} +@end deftypefun diff --git a/manual/startup.texi b/manual/startup.texi index 224dd98c1e..747beed4d9 100644 --- a/manual/startup.texi +++ b/manual/startup.texi @@ -689,7 +689,25 @@ you don't need to know about it because you can just use @theglibc{}'s @code{chmod} function. @cindex kernel call -System calls are sometimes called kernel calls. +System calls are sometimes called syscalls or kernel calls, and this +interface is mostly a purely mechanical translation from the kernel's +ABI to the C ABI. For the set of syscalls where we do not guarantee +POSIX Thread cancellation the wrappers only organize the incoming +arguments from the C calling convention to the calling convention of +the target kernel. For the set of syscalls where we provided POSIX +Thread cancellation the wrappers set some internal state in the +library to support cancellation, but this does not impact the +behaviour of the syscall provided by the kernel. + +In some cases, if @theglibc{} detects that a system call has been +superseded by a more capable one, the wrapper may map the old call to +the new one. For example, @code{dup2} is implemented via @code{dup3} +by passing an additional empty flags argument, and @code{open} calls +@code{openat} passing the additional @code{AT_FDCWD}. Sometimes even +more is done, such as converting between 32-bit and 64-bit time +values. In general, though, such processing is only to make the +system call better match the C ABI, rather than change its +functionality. However, there are times when you want to make a system call explicitly, and for that, @theglibc{} provides the @code{syscall} function. @@ -711,6 +729,8 @@ we won't describe it here either because anyone who is coding library source code as a specification of the interface between them anyway. +@code{syscall} does not provide cancellation logic, even if the system +call you're calling is listed as cancellable above. @code{syscall} is declared in @file{unistd.h}. diff --git a/manual/threads.texi b/manual/threads.texi index e5544ff3da..25e99c9606 100644 --- a/manual/threads.texi +++ b/manual/threads.texi @@ -1007,8 +1007,12 @@ This variable is either zero (if restartable sequence registration failed or has been disabled) or the size of the restartable sequence registration. This can be different from the size of @code{struct rseq} if the kernel has extended the size of the registration. If -registration is successful, @code{__rseq_size} is at least 32 (the -initial size of @code{struct rseq}). +registration is successful, @code{__rseq_size} is at least 20 (the +initially active size of @code{struct rseq}). + +Previous versions of @theglibc{} set this to 32 even if the kernel only +supported the initial area of 20 bytes because the value included unused +padding at the end of the restartable sequence area. @end deftypevar @deftypevar {unsigned int} __rseq_flags diff --git a/po/bg.po b/po/bg.po index 875ea57eb6..c69a48331a 100644 --- a/po/bg.po +++ b/po/bg.po @@ -10,9 +10,9 @@ # msgid "" msgstr "" -"Project-Id-Version: libc 2.38.9000\n" +"Project-Id-Version: libc 2.39.9000\n" "POT-Creation-Date: 2024-06-19 22:30+0200\n" -"PO-Revision-Date: 2024-01-04 09:04+0300\n" +"PO-Revision-Date: 2024-07-01 08:04+0300\n" "Last-Translator: Roumen Petrov <transl@roumenpetrov.info>\n" "Language-Team: Bulgarian <dict@ludost.net>\n" "Language: bg\n" @@ -4689,7 +4689,7 @@ msgstr "" #: nss/makedb.c:229 #, c-format msgid "cannot open database file `%s'" -msgstr "не може да Ñе отвори файлът на базата данни: \"%s\"" +msgstr "не може да Ñе отвори файлът на базата данни: '%s'" #: nss/makedb.c:274 #, c-format @@ -6545,6 +6545,26 @@ msgstr "не може да Ñе забрани разрешенната подр msgid "can't disable SHSTK" msgstr "не може да Ñе забрани разрешенната подръжка на SHSTK" +#: timezone/zdump.c:131 +#, c-format +msgid "%s: size overflow\n" +msgstr "%s: препълване на ÑтойноÑтта за размер\n" + +#: timezone/zdump.c:170 +#, c-format +msgid "%s: Memory exhausted\n" +msgstr "%s: Изчерпана памет\n" + +#: timezone/zdump.c:257 +#, c-format +msgid "%s: setenv: %s\n" +msgstr "%s: уÑтановÑване на обкръжение: %s\n" + +#: timezone/zdump.c:337 timezone/zdump.c:604 +#, c-format +msgid "%s: unknown timezone '%s': %s\n" +msgstr "%s: неизвеÑтно времева зона '%s': %s\n" + #: timezone/zdump.c:402 msgid "has characters other than ASCII alphanumerics, '-' or '+'" msgstr "е Ñ Ð±ÑƒÐºÐ²Ð¸ извън ASCII букви или цифри, '-' или '+'" @@ -6599,6 +6619,16 @@ msgstr "%s: безумен -c аргумент %s\n" msgid "%s: wild -t argument %s\n" msgstr "%s: безумен -t аргумент %s\n" +#: timezone/zdump.c:857 +#, c-format +msgid " (gmtime failed)" +msgstr " (пропадна gmtime)" + +#: timezone/zdump.c:867 +#, c-format +msgid " (localtime failed)" +msgstr " (пропадна localtime)" + #: timezone/zic.c:463 #, c-format msgid "%s: Memory exhausted: %s\n" @@ -6635,11 +6665,50 @@ msgstr " (правило от \"%s\", ред %<PRIdMAX>)" msgid "warning: " msgstr "предупреждение: " +#: timezone/zic.c:669 +#, c-format +msgid "" +"%s: usage is %s [ --version ] [ --help ] [ -v ] \\\n" +"\t[ -b {slim|fat} ] [ -d directory ] [ -l localtime ] [ -L leapseconds ] \\\n" +"\t[ -p posixrules ] [ -r '[@lo][/@hi]' ] [ -R '@hi' ] \\\n" +"\t[ -t localtime-link ] \\\n" +"\t[ filename ... ]\n" +"\n" +"Report bugs to %s.\n" +msgstr "" +"%s: употребата е %s [ --version ] [ --help ] [ -v ] \\\n" +"\t[ -b {slim|fat} ] [ -d Ð´Ð¸Ñ€ÐµÐºÑ‚Ð¾Ñ€Ð¸Ñ ] [ -l меÑтновреме ] [ -L виÑокоÑниÑекунди ]\\\n" +"\t[ -p posix_правило ] [ -r '[@lo][/@hi]' ] [ -R '@hi' ] \\\n" +"\t[ -t връзка–към–меÑтновреме ] \\\n" +"\t[ именафайл ... ]\n" +"\n" +"Докладване на грешки към %s.\n" + #: timezone/zic.c:695 #, c-format msgid "%s: Can't chdir to %s: %s\n" msgstr "%s: Ðе може да Ñе Ñмени директориÑта на %s: %s\n" +#: timezone/zic.c:786 +#, c-format +msgid "\"Link %s %s\" is part of a link cycle" +msgstr "\"Връзката %s %s\" е чаÑÑ‚ от цикъл Ñ Ð²Ñ€ÑŠÐ·ÐºÐ¸" + +#: timezone/zic.c:797 +#, c-format +msgid "link %s targets itself" +msgstr "връзката %s е към Ñебе Ñи" + +#: timezone/zic.c:817 +#, c-format +msgid "link %s targeting link %s mishandled by pre-2023 zic" +msgstr "zic, преди 2023, не Ñе ÑÐ¿Ñ€Ð°Ð²Ñ Ð´Ð¾Ð±Ñ€Ðµ при връзка %s целÑща връзка %s" + +#: timezone/zic.c:821 +#, c-format +msgid "link %s targeting link %s" +msgstr "връка %s към връзка %s" + #: timezone/zic.c:992 msgid "wild compilation-time specification of zic_t" msgstr "при компилирането е зададен безумен тип за zic_t" @@ -6673,6 +6742,10 @@ msgstr "%s: Зададена е повече от една Ð¾Ð¿Ñ†Ð¸Ñ -p\n" msgid "%s: More than one -t option specified\n" msgstr "%s: Зададена е повече от една Ð¾Ð¿Ñ†Ð¸Ñ -t\n" +#: timezone/zic.c:1064 +msgid "-y ignored" +msgstr "-y пренебрегнат" + #: timezone/zic.c:1071 #, c-format msgid "%s: More than one -L option specified\n" @@ -6688,10 +6761,20 @@ msgstr "%s: Зададена е повече от една Ð¾Ð¿Ñ†Ð¸Ñ -r\n" msgid "%s: invalid time range: %s\n" msgstr "%s: неправилен времеви диапазон: %s\n" +#: timezone/zic.c:1098 +#, c-format +msgid "%s: invalid time: %s\n" +msgstr "%s: неправилно време: %s\n" + #: timezone/zic.c:1104 msgid "-s ignored" msgstr "-s пренебрегнат" +#: timezone/zic.c:1110 +#, c-format +msgid "%s: -R time exceeds -r cutoff\n" +msgstr "%s: -R 'време' превишава -r 'отрÑзък'\n" + #: timezone/zic.c:1171 msgid "empty file name" msgstr "празно име на файл" @@ -6731,11 +6814,21 @@ msgstr "името на файла '%s' Ñъдържа байт '\\%o'" msgid "%s: Can't create %s/%s: %s\n" msgstr "%s: Ðе може да Ñе Ñъздаде %s/%s: %s\n" +#: timezone/zic.c:1388 +#, c-format +msgid "%s: rename to %s/%s: %s\n" +msgstr "%s: преименуване на %s/%s: %s\n" + #: timezone/zic.c:1463 #, c-format msgid "%s: Can't remove %s/%s: %s\n" msgstr "%s: Ðе може да Ñе изтрие %s/%s: %s\n" +#: timezone/zic.c:1507 +#, c-format +msgid "%s: Can't link %s/%s to %s/%s: %s\n" +msgstr "%s: Ðе може да Ñе Ñвърже %s/%s към %s/%s: %s\n" + #: timezone/zic.c:1536 #, c-format msgid "symbolic link used because hard link failed: %s" @@ -6765,6 +6858,18 @@ msgstr "едно и Ñъщо име на правило в много файло msgid "%s in ruleless zone" msgstr "%s в зона без правила" +#: timezone/zic.c:1674 +msgid "input error" +msgstr "входна грешка" + +#: timezone/zic.c:1679 +msgid "unterminated line" +msgstr "незавършен ред" + +#: timezone/zic.c:1683 +msgid "NUL input byte" +msgstr "NUL входÑщ байт" + #: timezone/zic.c:1688 msgid "line too long" msgstr "Твърде дълъг ред" @@ -6899,6 +7004,15 @@ msgstr "многократни редове Expires" msgid "wrong number of fields on Link line" msgstr "неправилен брой полета на ред за Link" +#: timezone/zic.c:2129 +msgid "blank TARGET field on Link line" +msgstr "празно поле TARGET на ред за Link" + +#: timezone/zic.c:2192 +#, c-format +msgid "FROM year \"%s\" is obsolete; treated as %d" +msgstr "'от година' \"%s\" е отживелица, замеÑтено Ñ %d" + #: timezone/zic.c:2199 msgid "invalid starting year" msgstr "неправилна начална година" @@ -6911,6 +7025,11 @@ msgstr "неправилна крайна година" msgid "starting year greater than ending year" msgstr "началната година е по-голÑма от крайната" +#: timezone/zic.c:2222 +#, c-format +msgid "year type \"%s\" is unsupported; use \"-\" instead" +msgstr "тип на годината \"%s\" не Ñе поддържа, да Ñе използва \"-\"" + #: timezone/zic.c:2257 msgid "invalid weekday name" msgstr "неправилно име на ден от Ñедмицата" @@ -6924,6 +7043,16 @@ msgstr "нÑкой клиенти, Ñе ÑправÑÑ‚ зле при повечРmsgid "pre-2014 clients may mishandle more than 1200 transition times" msgstr "клиенти преди 2014, може да не Ñе ÑправÑÑ‚ правилно при повече от 1200 прехода" +#: timezone/zic.c:2480 +#, c-format +msgid "%s: pre-2021b clients may mishandle leap second expiry" +msgstr "%s: клиенти преди 2021b , може да не Ñе ÑправÑÑ‚ Ñ Ð¸Ð·Ñ‚Ð¸Ñ‡Ð°Ð½ÐµÑ‚Ð¾ на дългата Ñекунда" + +#: timezone/zic.c:2488 +#, c-format +msgid "%s: pre-2021b clients may mishandle leap second table truncation" +msgstr "%s: клиенти преди 2021b , може да не Ñе ÑправÑÑ‚ ÑÑŠÑ Ñъкращаването на таблицата Ñ Ð´ÑŠÐ»Ð³Ð¸ Ñекунди" + #: timezone/zic.c:2537 msgid "too many transition times" msgstr "твърде много типове за преход" @@ -6933,6 +7062,10 @@ msgstr "твърде много типове за преход" msgid "%%z UT offset magnitude exceeds 99:59:59" msgstr "%%z ОтмеÑтването ÑпрÑмо универÑалноте време превишава 99:59:59" +#: timezone/zic.c:3180 +msgid "no POSIX.1-2017 environment variable for zone" +msgstr "в обкръжението, липÑва POSIX.1-2017 променлива за зона" + #: timezone/zic.c:3187 #, c-format msgid "%s: pre-%d clients may mishandle distant timestamps" @@ -6958,6 +7091,10 @@ msgstr "твърде много типове за меÑтно време" msgid "too many leap seconds" msgstr "твърде много виÑокоÑни Ñекунди" +#: timezone/zic.c:3535 +msgid "Rolling leap seconds not supported with -r" +msgstr "Претълкалване на дълга Ñекунда не Ñе поддръжа Ñ -r" + #: timezone/zic.c:3562 msgid "Leap seconds too close together" msgstr "твърде близки виÑокоÑни Ñекунди" @@ -6980,6 +7117,10 @@ msgstr "\"%s\" е двуÑмиÑлен за zic от преди 2017c" msgid "Odd number of quotation marks" msgstr "Ðеочакван брой кавички" +#: timezone/zic.c:3750 +msgid "Too many input fields" +msgstr "Твърде много входÑщи полета" + #: timezone/zic.c:3839 msgid "use of 2/29 in non leap-year" msgstr "използване на 29.2 за невиÑокоÑна година" diff --git a/socket/Makefile b/socket/Makefile index fc1bd0a260..df732fa9b7 100644 --- a/socket/Makefile +++ b/socket/Makefile @@ -71,6 +71,7 @@ tests := \ tst-cmsg_cloexec \ tst-cmsghdr \ tst-connect \ + tst-shutdown \ tst-sockopt \ # tests diff --git a/socket/tst-shutdown.c b/socket/tst-shutdown.c new file mode 100644 index 0000000000..a305e5e494 --- /dev/null +++ b/socket/tst-shutdown.c @@ -0,0 +1,257 @@ +/* Test the shutdown function. + Copyright (C) 2024 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 <arpa/inet.h> +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> +#include <support/check.h> +#include <support/support.h> +#include <support/xsocket.h> +#include <support/xunistd.h> +#include <sys/socket.h> +#include <stdio.h> +#include <fcntl.h> +#include <string.h> + +struct connection +{ + int sockets[2]; +}; + +void +establish_connection (struct connection *conn) +{ + if (socketpair (AF_UNIX, SOCK_STREAM, 0, conn->sockets) != 0) + { + FAIL_EXIT1 ("socketpair (AF_UNIX, SOCK_STREAM, 0): %m\n"); + } +} + +void +close_connection (struct connection *conn) +{ + xclose (conn->sockets[0]); + xclose (conn->sockets[1]); +} + +/* Open a file and check that shutdown fails with the ENOTSOCK error code. */ +void +do_test_enotsock (void) +{ + /* Open file and check that shutdown will fail with ENOTSOCK. */ + int fd = xopen ("/dev/null", O_RDWR, 0); + + int result = shutdown (fd, SHUT_RD); + if (result == 0 || errno != ENOTSOCK) + { + FAIL_EXIT1 ("shutdown should fail with ENOTSOCK"); + } + xclose (fd); +} + +/* Test shutdown with SHUT_RD. */ +void +do_test_shut_rd (void) +{ + struct connection conn; + const char *str = "AAAAAAA"; + int len = 8; + int ret; + void *s_buf = xmalloc (len); + bzero (s_buf, len); + + establish_connection (&conn); + int server = conn.sockets[0]; + int client = conn.sockets[1]; + + /* Call shutdown with SHUT_RD on server socket. */ + if (shutdown (server, SHUT_RD) != 0) + { + FAIL_EXIT1 ("shutdown with SHUT_RD on socket %d failed", server); + } + + ret = send (server, str, len, 0); + if (ret <= 0) + { + FAIL_EXIT1 ("send (%d, data, %d): %m", server, len); + } + + ret = recv (client, s_buf, len, 0); + if (ret <= 0) + { + FAIL_EXIT1 ("recv (%d, data, %d): %m", client, len); + } + + TEST_COMPARE_BLOB (str, len, s_buf, len); + + /* Send data should be disallowed on shutdown socket. */ + errno = 0; + ret = send (client, str, len, MSG_NOSIGNAL); + if (ret >= 0 || errno != EPIPE) + { + FAIL_EXIT1 ("Send on SHUT_RD socket should be disallowed: %m"); + } + + /* Recv should return zero and no error. */ + errno = 0; + ret = recv (server, s_buf, len, 0); + if (ret != 0 || errno != 0) + { + FAIL_EXIT1 ("recv should return 0 without error: %m"); + } + + close_connection (&conn); +} + +/* Test shutdown with SHUT_WR. */ +void +do_test_shut_wr (void) +{ + struct connection conn; + const char *str1 = "CCCCCCC"; + const char *str2 = "DDDDDDD"; + const char *str3 = "EEEEEEE"; + int len = 8; + int ret; + void *c_buf = xmalloc (len); + void *s_buf = xmalloc (len); + + establish_connection (&conn); + int server = conn.sockets[0]; + int client = conn.sockets[1]; + + xwrite (client, str1, len); + + if (shutdown (client, SHUT_WR) != 0) + { + FAIL_EXIT1 ("shutdown with SHUT_WR on socket %d failed", client); + } + + ret = send (client, str2, len, MSG_NOSIGNAL); + if (ret >= 0) + { + FAIL_EXIT1 ("send on SHUT_WR socket should fail"); + } + + /* Read data written before shutdown and check if it's correct. */ + xread (server, s_buf, len); + TEST_COMPARE_BLOB (str1, len, s_buf, len); + + /* Second read should return zero without error. */ + errno = 0; + if (read (server, s_buf, len) != 0 || errno != 0) + { + FAIL_EXIT1 ("read after shutdown should return zero without error: %m"); + } + + /* Write some data to socket and check it still can be read on other side. */ + memcpy (s_buf, str3, len); + xwrite (server, s_buf, len); + + xread (client, c_buf, len); + TEST_COMPARE_BLOB (s_buf, len, c_buf, len); + + close_connection (&conn); +} + +/* Test shutdown with SHUT_RDWR. */ +void +do_test_shut_rdwr (void) +{ + struct connection conn; + struct sockaddr peer; + socklen_t peer_len = sizeof (peer); + + const char *str1 = "FFFFFFF"; + const char *str2 = "GGGGGGG"; + int len = 8; + int ret; + void *s_buf = xmalloc (len); + bzero (s_buf, len); + + establish_connection (&conn); + int server = conn.sockets[0]; + int client = conn.sockets[1]; + + /* Send some data to both sockets before shutdown. */ + xwrite (client, str1, len); + xwrite (server, str2, len); + + /* Call shutdown with SHUT_RDWR on client socket. */ + if (shutdown (client, SHUT_RDWR) != 0) + { + FAIL_EXIT1 ("shutdown with SHUT_RDWR on socket %d failed", client); + } + + /* Verify that socket is still connected. */ + xgetsockname (client, &peer, &peer_len); + + /* Read data written before shutdown. */ + xread (client, s_buf, len); + TEST_COMPARE_BLOB (s_buf, len, str2, len); + + /* Second read should return zero, but no error. */ + errno = 0; + if (read (client, s_buf, len) != 0 || errno != 0) + { + FAIL_EXIT1 ("read after shutdown should return zero without error: %m"); + } + + /* Send some data to shutdown socket and expect error. */ + errno = 0; + ret = send (server, str2, len, MSG_NOSIGNAL); + if (ret >= 0 || errno != EPIPE) + { + FAIL_EXIT1 ("send to RDWR shutdown socket should fail with EPIPE"); + } + + /* Read data written before shutdown. */ + xread (server, s_buf, len); + TEST_COMPARE_BLOB (s_buf, len, str1, len); + + /* Second read should return zero, but no error. */ + errno = 0; + if (read (server, s_buf, len) != 0 || errno != 0) + { + FAIL_EXIT1 ("read after shutdown should return zero without error: %m"); + } + + /* Send some data to shutdown socket and expect error. */ + errno = 0; + ret = send (client, str1, len, MSG_NOSIGNAL); + if (ret >= 0 || errno != EPIPE) + { + FAIL_EXIT1 ("send to RDWR shutdown socket should fail with EPIPE"); + } + + close_connection (&conn); +} + +static int +do_test (void) +{ + do_test_enotsock (); + do_test_shut_rd (); + do_test_shut_wr (); + do_test_shut_rdwr (); + + return 0; +} + +#include <support/test-driver.c> diff --git a/stdlib/arc4random.c b/stdlib/arc4random.c index 3ae8fc1302..7818cb9cf6 100644 --- a/stdlib/arc4random.c +++ b/stdlib/arc4random.c @@ -51,7 +51,7 @@ __arc4random_buf (void *p, size_t n) n -= l; continue; /* Interrupted by a signal; keep going. */ } - else if (l == -ENOSYS) + else if (l < 0 && errno == ENOSYS) break; /* No syscall, so fallback to /dev/urandom. */ arc4random_getrandom_failure (); } diff --git a/sysdeps/m68k/m680x0/fpu/libm-test-ulps b/sysdeps/m68k/m680x0/fpu/libm-test-ulps index b957e7b5d1..6eacfb6b6f 100644 --- a/sysdeps/m68k/m680x0/fpu/libm-test-ulps +++ b/sysdeps/m68k/m680x0/fpu/libm-test-ulps @@ -7,12 +7,12 @@ float: 1 ldouble: 1 Function: "acosh_downward": -double: 1 +double: 2 float: 1 ldouble: 1 Function: "acosh_towardzero": -double: 1 +double: 2 float: 1 ldouble: 1 @@ -21,6 +21,21 @@ double: 2 float: 1 ldouble: 1 +Function: "asin": +double: 1 + +Function: "asin_downward": +double: 1 +float: 1 + +Function: "asin_towardzero": +double: 1 +float: 1 + +Function: "asin_upward": +double: 1 +float: 1 + Function: "asinh": double: 1 float: 1 @@ -42,6 +57,7 @@ float: 2 ldouble: 3 Function: "atan2": +double: 1 float: 1 ldouble: 1 @@ -66,6 +82,7 @@ float: 1 ldouble: 1 Function: "atan_towardzero": +double: 1 float: 1 ldouble: 1 @@ -74,6 +91,17 @@ double: 1 float: 1 ldouble: 1 +Function: "atanh": +double: 1 + +Function: "atanh_downward": +double: 1 +float: 1 + +Function: "atanh_upward": +double: 1 +float: 1 + Function: "cabs": double: 1 ldouble: 1 @@ -147,7 +175,7 @@ ldouble: 4 Function: Imaginary part of "cacosh_downward": double: 2 -float: 2 +float: 3 ldouble: 2 Function: Real part of "cacosh_towardzero": @@ -166,7 +194,7 @@ float: 5 ldouble: 4 Function: Imaginary part of "cacosh_upward": -double: 2 +double: 3 float: 2 ldouble: 3 @@ -180,6 +208,7 @@ float: 1 ldouble: 1 Function: "carg_towardzero": +double: 1 float: 1 ldouble: 1 @@ -199,7 +228,7 @@ float: 1 ldouble: 2 Function: Real part of "casin_downward": -double: 2 +double: 3 float: 2 ldouble: 2 @@ -209,7 +238,7 @@ float: 3 ldouble: 4 Function: Real part of "casin_towardzero": -double: 1 +double: 3 float: 2 ldouble: 2 @@ -224,7 +253,7 @@ float: 2 ldouble: 2 Function: Imaginary part of "casin_upward": -double: 4 +double: 5 float: 5 ldouble: 4 @@ -244,7 +273,7 @@ float: 3 ldouble: 4 Function: Imaginary part of "casinh_downward": -double: 2 +double: 3 float: 2 ldouble: 2 @@ -254,7 +283,7 @@ float: 3 ldouble: 4 Function: Imaginary part of "casinh_towardzero": -double: 1 +double: 3 float: 2 ldouble: 2 @@ -269,6 +298,8 @@ float: 2 ldouble: 2 Function: Real part of "catan": +double: 1 +float: 1 ldouble: 1 Function: Imaginary part of "catan": @@ -283,7 +314,7 @@ ldouble: 1 Function: Imaginary part of "catan_downward": double: 2 -float: 1 +float: 2 ldouble: 3 Function: Real part of "catan_towardzero": @@ -312,11 +343,13 @@ float: 1 ldouble: 1 Function: Imaginary part of "catanh": +double: 1 +float: 1 ldouble: 1 Function: Real part of "catanh_downward": double: 2 -float: 1 +float: 2 ldouble: 3 Function: Imaginary part of "catanh_downward": @@ -365,60 +398,78 @@ float: 1 ldouble: 1 Function: Real part of "ccos": +float: 1 ldouble: 1 Function: Imaginary part of "ccos": +float: 1 ldouble: 1 Function: Real part of "ccos_downward": double: 1 +float: 1 ldouble: 2 Function: Imaginary part of "ccos_downward": double: 1 +float: 2 ldouble: 2 Function: Real part of "ccos_towardzero": double: 1 +float: 1 ldouble: 2 Function: Imaginary part of "ccos_towardzero": double: 1 +float: 2 ldouble: 2 Function: Real part of "ccos_upward": double: 1 +float: 1 ldouble: 2 Function: Imaginary part of "ccos_upward": double: 1 +float: 2 ldouble: 2 +Function: Real part of "ccosh": +float: 1 + Function: Imaginary part of "ccosh": +float: 1 ldouble: 1 Function: Real part of "ccosh_downward": double: 1 +float: 2 ldouble: 2 Function: Imaginary part of "ccosh_downward": double: 1 +float: 2 ldouble: 2 Function: Real part of "ccosh_towardzero": double: 1 +float: 2 ldouble: 2 Function: Imaginary part of "ccosh_towardzero": double: 1 +float: 2 ldouble: 2 Function: Real part of "ccosh_upward": double: 1 +float: 2 ldouble: 2 Function: Imaginary part of "ccosh_upward": double: 1 +float: 2 ldouble: 2 Function: Real part of "cexp": @@ -449,15 +500,17 @@ ldouble: 3 Function: Real part of "cexp_upward": double: 1 +float: 1 ldouble: 2 Function: Imaginary part of "cexp_upward": double: 1 +float: 1 ldouble: 2 Function: Real part of "clog": double: 3 -float: 2 +float: 3 ldouble: 3 Function: Imaginary part of "clog": @@ -467,12 +520,12 @@ ldouble: 1 Function: Real part of "clog10": double: 2 -float: 2 +float: 3 ldouble: 3 Function: Imaginary part of "clog10": double: 1 -float: 1 +float: 2 ldouble: 2 Function: Real part of "clog10_downward": @@ -482,17 +535,17 @@ ldouble: 7 Function: Imaginary part of "clog10_downward": double: 1 -float: 2 +float: 3 ldouble: 4 Function: Real part of "clog10_towardzero": double: 6 -float: 4 +float: 5 ldouble: 7 Function: Imaginary part of "clog10_towardzero": double: 1 -float: 2 +float: 3 ldouble: 4 Function: Real part of "clog10_upward": @@ -502,7 +555,7 @@ ldouble: 6 Function: Imaginary part of "clog10_upward": double: 1 -float: 2 +float: 3 ldouble: 3 Function: Real part of "clog_downward": @@ -537,6 +590,23 @@ ldouble: 2 Function: "cos": double: 1 +float: 6 + +Function: "cos_downward": +float: 5 + +Function: "cos_towardzero": +float: 5 + +Function: "cos_upward": +float: 5 + +Function: "cosh": +double: 1 + +Function: "cosh_upward": +double: 1 +float: 1 Function: Real part of "cpow": double: 1 @@ -578,11 +648,15 @@ float: 1 ldouble: 2 Function: Real part of "csin": +float: 1 ldouble: 1 +Function: Imaginary part of "csin": +float: 1 + Function: Real part of "csin_downward": double: 1 -float: 1 +float: 2 ldouble: 2 Function: Imaginary part of "csin_downward": @@ -592,7 +666,7 @@ ldouble: 1 Function: Real part of "csin_towardzero": double: 1 -float: 1 +float: 2 ldouble: 2 Function: Imaginary part of "csin_towardzero": @@ -602,7 +676,7 @@ ldouble: 1 Function: Real part of "csin_upward": double: 1 -float: 1 +float: 2 ldouble: 2 Function: Imaginary part of "csin_upward": @@ -611,8 +685,12 @@ float: 1 ldouble: 1 Function: Real part of "csinh": +float: 1 ldouble: 1 +Function: Imaginary part of "csinh": +float: 1 + Function: Real part of "csinh_downward": double: 1 float: 1 @@ -620,7 +698,7 @@ ldouble: 1 Function: Imaginary part of "csinh_downward": double: 1 -float: 1 +float: 2 ldouble: 2 Function: Real part of "csinh_towardzero": @@ -630,7 +708,7 @@ ldouble: 1 Function: Imaginary part of "csinh_towardzero": double: 1 -float: 1 +float: 2 ldouble: 2 Function: Real part of "csinh_upward": @@ -640,37 +718,37 @@ ldouble: 1 Function: Imaginary part of "csinh_upward": double: 1 -float: 1 +float: 2 ldouble: 2 Function: Real part of "csqrt": double: 1 -float: 1 +float: 2 ldouble: 2 Function: Imaginary part of "csqrt": double: 1 -float: 1 +float: 2 ldouble: 2 Function: Real part of "csqrt_downward": double: 1 -float: 2 +float: 4 ldouble: 4 Function: Imaginary part of "csqrt_downward": double: 1 -float: 2 +float: 3 ldouble: 3 Function: Real part of "csqrt_towardzero": double: 1 -float: 1 +float: 3 ldouble: 4 Function: Imaginary part of "csqrt_towardzero": double: 1 -float: 2 +float: 3 ldouble: 3 Function: Real part of "csqrt_upward": @@ -685,7 +763,7 @@ ldouble: 3 Function: Real part of "ctan": double: 1 -float: 1 +float: 2 ldouble: 2 Function: Imaginary part of "ctan": @@ -699,7 +777,7 @@ float: 2 ldouble: 2 Function: Imaginary part of "ctan_downward": -double: 3 +double: 9 float: 2 ldouble: 2 @@ -709,7 +787,7 @@ float: 2 ldouble: 2 Function: Imaginary part of "ctan_towardzero": -double: 3 +double: 9 float: 2 ldouble: 4 @@ -719,8 +797,8 @@ float: 3 ldouble: 5 Function: Imaginary part of "ctan_upward": -double: 1 -float: 1 +double: 9 +float: 2 ldouble: 7 Function: Real part of "ctanh": @@ -734,7 +812,7 @@ float: 2 ldouble: 2 Function: Real part of "ctanh_downward": -double: 3 +double: 9 float: 2 ldouble: 2 @@ -744,7 +822,7 @@ float: 2 ldouble: 2 Function: Real part of "ctanh_towardzero": -double: 3 +double: 9 float: 2 ldouble: 4 @@ -754,7 +832,7 @@ float: 1 ldouble: 2 Function: Real part of "ctanh_upward": -double: 1 +double: 9 float: 2 ldouble: 7 @@ -764,31 +842,37 @@ float: 3 ldouble: 5 Function: "erf": +double: 1 float: 1 ldouble: 1 Function: "erf_downward": +double: 1 float: 1 Function: "erf_towardzero": +double: 1 +float: 1 ldouble: 1 Function: "erf_upward": +double: 1 float: 1 ldouble: 1 Function: "erfc": -float: 1 +double: 1 +float: 2 ldouble: 2 Function: "erfc_downward": double: 1 -float: 3 +float: 4 ldouble: 4 Function: "erfc_towardzero": double: 1 -float: 1 +float: 4 ldouble: 4 Function: "erfc_upward": @@ -796,26 +880,83 @@ double: 1 float: 3 ldouble: 3 +Function: "exp10m1": +double: 1 +float: 1 + +Function: "exp10m1_downward": +double: 1 +float: 1 + +Function: "exp10m1_towardzero": +double: 1 +float: 1 + +Function: "exp10m1_upward": +double: 3 +float: 1 + Function: "exp2": double: 1 -Function: "gamma": +Function: "exp2_downward": +double: 1 + +Function: "exp2_towardzero": +double: 1 + +Function: "exp2m1": +double: 1 float: 1 -ldouble: 2 -Function: "gamma_downward": +Function: "exp2m1_downward": +double: 2 +float: 1 + +Function: "exp2m1_towardzero": +double: 2 +float: 1 + +Function: "exp2m1_upward": double: 1 float: 1 -ldouble: 3 -Function: "gamma_towardzero": +Function: "exp_upward": +double: 1 + +Function: "expm1": +double: 1 + +Function: "expm1_downward": double: 1 float: 1 -ldouble: 3 -Function: "gamma_upward": +Function: "expm1_towardzero": double: 1 float: 1 + +Function: "expm1_upward": +double: 1 +float: 1 + +Function: "gamma": +double: 3 +float: 7 +ldouble: 2 + +Function: "gamma_downward": +double: 3 +float: 7 +ldouble: 3 + +Function: "gamma_towardzero": +double: 4 +float: 6 +ldouble: 3 + +Function: "gamma_upward": +double: 4 +float: 6 ldouble: 2 Function: "hypot": @@ -835,82 +976,157 @@ double: 1 ldouble: 1 Function: "j0": -double: 1 -float: 2 +double: 8 +float: 8 ldouble: 2 Function: "j0_downward": -double: 4 -float: 3 +double: 7 +float: 8 ldouble: 4 Function: "j0_towardzero": double: 1 -float: 1 +float: 8 ldouble: 5 Function: "j0_upward": -double: 2 -float: 3 +double: 7 +float: 9 ldouble: 5 Function: "j1": -float: 2 +double: 3 +float: 7 ldouble: 1 Function: "j1_downward": -double: 1 -float: 4 +double: 3 +float: 7 ldouble: 5 Function: "j1_towardzero": -double: 1 -float: 2 +double: 9 +float: 7 ldouble: 4 Function: "j1_upward": -double: 1 -float: 3 +double: 9 +float: 6 ldouble: 3 Function: "jn": double: 2 -float: 2 +float: 5 ldouble: 4 Function: "jn_downward": double: 2 -float: 4 +float: 6 ldouble: 5 Function: "jn_towardzero": double: 2 -float: 3 +float: 6 ldouble: 5 Function: "jn_upward": double: 2 -float: 3 +float: 5 ldouble: 5 Function: "lgamma": -float: 1 +double: 3 +float: 7 ldouble: 2 Function: "lgamma_downward": -double: 1 -float: 1 +double: 3 +float: 7 ldouble: 3 Function: "lgamma_towardzero": -double: 1 -float: 1 +double: 4 +float: 6 ldouble: 3 Function: "lgamma_upward": +double: 4 +float: 6 +ldouble: 2 + +Function: "log10_downward": +double: 1 +float: 1 + +Function: "log10_towardzero": +double: 1 +float: 1 + +Function: "log10p1": +double: 1 +float: 2 + +Function: "log10p1_downward": +double: 1 +float: 1 + +Function: "log10p1_towardzero": +double: 1 +float: 1 + +Function: "log10p1_upward": +double: 1 +float: 1 + +Function: "log1p": +double: 1 + +Function: "log1p_downward": +double: 1 +float: 1 + +Function: "log1p_towardzero": +double: 1 +float: 1 + +Function: "log1p_upward": +double: 1 +float: 1 + +Function: "log2": +double: 1 + +Function: "log2p1": +double: 1 +float: 2 + +Function: "log2p1_downward": +double: 1 +float: 2 + +Function: "log2p1_towardzero": +double: 1 +float: 2 + +Function: "log2p1_upward": +double: 1 +float: 2 + +Function: "logp1": +double: 1 + +Function: "logp1_downward": +double: 1 +float: 1 + +Function: "logp1_towardzero": +double: 1 +float: 1 + +Function: "logp1_upward": double: 1 float: 1 -ldouble: 2 Function: "pow": double: 1 @@ -919,7 +1135,7 @@ ldouble: 9 Function: "pow_downward": double: 1 -float: 7 +float: 9 ldouble: 9 Function: "pow_towardzero": @@ -929,45 +1145,100 @@ ldouble: 4 Function: "pow_upward": double: 1 -float: 2 +float: 7 ldouble: 8 Function: "sin": double: 1 -Function: "tgamma": +Function: "sin_downward": double: 1 -float: 4 +float: 1 + +Function: "sin_towardzero": +double: 1 +float: 1 + +Function: "sin_upward": +double: 1 +float: 1 + +Function: "sincos_downward": +double: 1 +float: 1 + +Function: "sincos_towardzero": +double: 1 +float: 1 + +Function: "sincos_upward": +double: 1 +float: 1 + +Function: "sinh_downward": +double: 1 +float: 1 + +Function: "sinh_upward": +double: 1 +float: 1 + +Function: "tan_downward": +double: 1 +float: 1 + +Function: "tan_upward": +double: 1 +float: 1 + +Function: "tanh": +double: 1 + +Function: "tanh_downward": +double: 1 +float: 1 + +Function: "tanh_towardzero": +double: 1 +float: 1 + +Function: "tanh_upward": +double: 1 +float: 1 + +Function: "tgamma": +double: 3 +float: 9 ldouble: 9 Function: "tgamma_downward": -double: 2 -float: 3 +double: 3 +float: 9 ldouble: 9 Function: "tgamma_towardzero": -double: 2 -float: 4 +double: 3 +float: 9 ldouble: 9 Function: "tgamma_upward": -double: 1 -float: 4 +double: 2 +float: 9 ldouble: 9 Function: "y0": double: 1 -float: 1 +float: 4 ldouble: 1 Function: "y0_downward": double: 1 -float: 3 +float: 4 ldouble: 6 Function: "y0_towardzero": double: 1 -float: 2 +float: 4 ldouble: 5 Function: "y0_upward": @@ -977,12 +1248,12 @@ ldouble: 3 Function: "y1": double: 1 -float: 3 +float: 4 ldouble: 2 Function: "y1_downward": double: 4 -float: 3 +float: 6 ldouble: 6 Function: "y1_towardzero": @@ -992,7 +1263,7 @@ ldouble: 5 Function: "y1_upward": double: 2 -float: 2 +float: 4 ldouble: 7 Function: "yn": @@ -1007,12 +1278,12 @@ ldouble: 6 Function: "yn_towardzero": double: 3 -float: 3 +float: 4 ldouble: 5 Function: "yn_upward": double: 3 -float: 3 +float: 4 ldouble: 4 # end of automatic generation diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c index 092c274f36..7803e19fd1 100644 --- a/sysdeps/nptl/dl-tls_init_tp.c +++ b/sysdeps/nptl/dl-tls_init_tp.c @@ -45,8 +45,6 @@ rtld_mutex_dummy (pthread_mutex_t *lock) #endif const unsigned int __rseq_flags; -const unsigned int __rseq_size attribute_relro; -const ptrdiff_t __rseq_offset attribute_relro; void __tls_pre_init_tp (void) @@ -104,12 +102,7 @@ __tls_init_tp (void) bool do_rseq = true; do_rseq = TUNABLE_GET (rseq, int, NULL); if (rseq_register_current_thread (pd, do_rseq)) - { - /* We need a writable view of the variables. They are in - .data.relro and are not yet write-protected. */ - extern unsigned int size __asm__ ("__rseq_size"); - size = sizeof (pd->rseq_area); - } + _rseq_size = RSEQ_AREA_SIZE_INITIAL_USED; #ifdef RSEQ_SIG /* This should be a compile-time constant, but the current @@ -117,8 +110,7 @@ __tls_init_tp (void) all targets support __thread_pointer, so set __rseq_offset only if the rseq registration may have happened because RSEQ_SIG is defined. */ - extern ptrdiff_t offset __asm__ ("__rseq_offset"); - offset = (char *) &pd->rseq_area - (char *) __thread_pointer (); + _rseq_offset = (char *) &pd->rseq_area - (char *) __thread_pointer (); #endif } diff --git a/sysdeps/riscv/nofpu/libm-test-ulps b/sysdeps/riscv/nofpu/libm-test-ulps index d8cff3e077..9ad64d1d85 100644 --- a/sysdeps/riscv/nofpu/libm-test-ulps +++ b/sysdeps/riscv/nofpu/libm-test-ulps @@ -972,6 +972,11 @@ double: 2 float: 1 ldouble: 3 +Function: "exp10m1": +double: 2 +float: 1 +ldouble: 1 + Function: "exp2": double: 1 ldouble: 1 @@ -989,6 +994,11 @@ double: 1 float: 1 ldouble: 2 +Function: "exp2m1": +double: 1 +float: 1 +ldouble: 1 + Function: "exp_downward": double: 1 float: 1 @@ -1161,6 +1171,11 @@ double: 2 float: 2 ldouble: 1 +Function: "log10p1": +double: 1 +float: 1 +ldouble: 3 + Function: "log1p": double: 1 float: 1 @@ -1198,6 +1213,11 @@ Function: "log2_upward": double: 3 ldouble: 1 +Function: "log2p1": +double: 1 +float: 1 +ldouble: 3 + Function: "log_downward": ldouble: 1 diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index ae66590e91..097b5a26fc 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -616,6 +616,10 @@ tests += \ endif ifeq ($(subdir),elf) +dl-routines += \ + dl-rseq-symbols \ + # dl-routines + sysdep-rtld-routines += \ dl-brk \ dl-getcwd \ diff --git a/sysdeps/unix/sysv/linux/dl-rseq-symbols.S b/sysdeps/unix/sysv/linux/dl-rseq-symbols.S new file mode 100644 index 0000000000..b4bba06a99 --- /dev/null +++ b/sysdeps/unix/sysv/linux/dl-rseq-symbols.S @@ -0,0 +1,64 @@ +/* Define symbols used by rseq. + Copyright (C) 2024 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 <sysdep.h> + +#if __WORDSIZE == 64 +#define RSEQ_OFFSET_SIZE 8 +#else +#define RSEQ_OFFSET_SIZE 4 +#endif + +/* Some targets define a macro to denote the zero register. */ +#undef zero + +/* Define 2 symbols: '__rseq_size' is public const and '_rseq_size' (an + alias of '__rseq_size') is hidden and writable for internal use by the + dynamic linker which will initialize the value both symbols point to + before copy relocations take place. */ + + .globl __rseq_size + .type __rseq_size, %object + .size __rseq_size, 4 + .hidden _rseq_size + .globl _rseq_size + .type _rseq_size, %object + .size _rseq_size, 4 + .section .data.rel.ro + .balign 4 +__rseq_size: +_rseq_size: + .zero 4 + +/* Define 2 symbols: '__rseq_offset' is public const and '_rseq_offset' (an + alias of '__rseq_offset') is hidden and writable for internal use by the + dynamic linker which will initialize the value both symbols point to + before copy relocations take place. */ + + .globl __rseq_offset + .type __rseq_offset, %object + .size __rseq_offset, RSEQ_OFFSET_SIZE + .hidden _rseq_offset + .globl _rseq_offset + .type _rseq_offset, %object + .size _rseq_offset, RSEQ_OFFSET_SIZE + .section .data.rel.ro + .balign RSEQ_OFFSET_SIZE +__rseq_offset: +_rseq_offset: + .zero RSEQ_OFFSET_SIZE diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h index 48eebc1e16..7ea935b4ad 100644 --- a/sysdeps/unix/sysv/linux/rseq-internal.h +++ b/sysdeps/unix/sysv/linux/rseq-internal.h @@ -25,15 +25,34 @@ #include <stdio.h> #include <sys/rseq.h> +/* 32 is the initially required value for the area size. The + actually used rseq size may be less (20 bytes initially). */ +#define RSEQ_AREA_SIZE_INITIAL 32 +#define RSEQ_AREA_SIZE_INITIAL_USED 20 + +/* The variables are in .data.relro but are not yet write-protected. */ +extern unsigned int _rseq_size attribute_hidden; +extern ptrdiff_t _rseq_offset attribute_hidden; + #ifdef RSEQ_SIG static inline bool rseq_register_current_thread (struct pthread *self, bool do_rseq) { if (do_rseq) { + unsigned int size; +#if IS_IN (rtld) + /* Use the hidden symbol in ld.so. */ + size = _rseq_size; +#else + size = __rseq_size; +#endif + if (size < RSEQ_AREA_SIZE_INITIAL) + /* The initial implementation used only 20 bytes out of 32, + but still expected size 32. */ + size = RSEQ_AREA_SIZE_INITIAL; int ret = INTERNAL_SYSCALL_CALL (rseq, &self->rseq_area, - sizeof (self->rseq_area), - 0, RSEQ_SIG); + size, 0, RSEQ_SIG); if (!INTERNAL_SYSCALL_ERROR_P (ret)) return true; } diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c index 2c90409ba0..08a9533130 100644 --- a/sysdeps/unix/sysv/linux/tst-rseq.c +++ b/sysdeps/unix/sysv/linux/tst-rseq.c @@ -29,6 +29,7 @@ # include <stdlib.h> # include <string.h> # include <syscall.h> +# include <sys/auxv.h> # include <thread_pointer.h> # include <tls.h> # include "tst-rseq.h" @@ -42,7 +43,8 @@ do_rseq_main_test (void) TEST_COMPARE (__rseq_flags, 0); TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset == (char *) &pd->rseq_area); - TEST_COMPARE (__rseq_size, sizeof (pd->rseq_area)); + /* The current implementation only supports the initial size. */ + TEST_COMPARE (__rseq_size, 20); } static void @@ -52,6 +54,12 @@ do_rseq_test (void) { FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test"); } + printf ("info: __rseq_size: %u\n", __rseq_size); + printf ("info: __rseq_offset: %td\n", __rseq_offset); + printf ("info: __rseq_flags: %u\n", __rseq_flags); + printf ("info: getauxval (AT_RSEQ_FEATURE_SIZE): %ld\n", + getauxval (AT_RSEQ_FEATURE_SIZE)); + printf ("info: getauxval (AT_RSEQ_ALIGN): %ld\n", getauxval (AT_RSEQ_ALIGN)); do_rseq_main_test (); } #else /* RSEQ_SIG */ |