git-updates
authorGNU Libc Maintainers <debian-glibc@lists.debian.org>
Wed, 31 Jan 2024 20:45:37 +0000 (21:45 +0100)
committerAurelien Jarno <aurel32@debian.org>
Wed, 31 Jan 2024 20:45:37 +0000 (21:45 +0100)
GIT update of https://sourceware.org/git/glibc.git/release/2.37/master from glibc-2.37

GIT update of https://sourceware.org/git/glibc.git/release/2.37/master from glibc-2.37

Gbp-Pq: Name git-updates.diff

90 files changed:
NEWS
elf/Makefile
elf/dl-audit.c
elf/dl-find_object.c
elf/dl-init.c
elf/dl-runtime.c
elf/dl-tls.c
elf/dl-tunables.c
elf/dl-tunables.list
elf/do-rel.h
elf/elf.h
elf/ldconfig.c
elf/readelflib.c
elf/readlib.c
elf/tst-auditmod28.c
elf/tst-env-setuid-tunables.c
elf/tst-ldconfig-p.sh [new file with mode: 0644]
elf/tst-ldconfig-soname-lib-with-soname.c [new file with mode: 0644]
elf/tst-ldconfig-soname-lib-without-soname.c [new file with mode: 0644]
elf/tst-ldconfig-soname.sh [new file with mode: 0644]
gmon/Makefile
gmon/gmon.c
gmon/mcount.c
gmon/sys/gmon.h
gmon/tst-mcleanup.c [new file with mode: 0644]
gmon/tst-mcount-overflow-check.sh [new file with mode: 0644]
gmon/tst-mcount-overflow.c [new file with mode: 0644]
gshadow/Makefile
gshadow/sgetsgent_r.c
gshadow/tst-sgetsgent.c [new file with mode: 0644]
hurd/catch-exc.c
hurd/hurd/signal.h
hurd/hurdfault.c
include/link.h
io/Makefile
io/tst-fcntl-lock-lfs.c [new file with mode: 0644]
io/tst-fcntl-lock.c [new file with mode: 0644]
io/tst-lockf.c
libio/wfileops.c
malloc/malloc.c
misc/Makefile
misc/sys/cdefs.h
misc/syslog.c
misc/tst-syslog-long-progname.c [new file with mode: 0644]
nss/Makefile
nss/nss_test_gai_hv2_canonname.c [new file with mode: 0644]
nss/tst-nss-gai-hv2-canonname.c [new file with mode: 0644]
nss/tst-nss-gai-hv2-canonname.h [new file with mode: 0644]
nss/tst-nss-gai-hv2-canonname.root/tst-nss-gai-hv2-canonname.script [new file with mode: 0644]
resolv/Makefile
resolv/nss_dns/dns-host.c
resolv/tst-resolv-noaaaa-vc.c [new file with mode: 0644]
stdio-common/Makefile
stdio-common/tst-grouping3.c [new file with mode: 0644]
stdio-common/vfprintf-process-arg.c
stdlib/Makefile
stdlib/exit.c
stdlib/test-atexit-recursive.c [new file with mode: 0644]
stdlib/tst-system.c
sunrpc/netname.c
support/Makefile
support/dtotimespec-time64.c [new file with mode: 0644]
support/dtotimespec.c [new file with mode: 0644]
support/shell-container.c
support/timespec.h
sysdeps/generic/dl-lookupcfg.h
sysdeps/generic/ldconfig.h
sysdeps/generic/ldsodefs.h
sysdeps/hppa/dl-lookupcfg.h
sysdeps/i386/i686/fpu/multiarch/libm-test-ulps
sysdeps/ia64/dl-lookupcfg.h
sysdeps/posix/getaddrinfo.c
sysdeps/posix/system.c
sysdeps/powerpc/dl-lookupcfg.h
sysdeps/pthread/tst-cancel30.c
sysdeps/sparc/dl-lookupcfg.h [new file with mode: 0644]
sysdeps/unix/sysv/linux/Makefile
sysdeps/unix/sysv/linux/bits/fcntl-linux.h
sysdeps/unix/sysv/linux/check_pf.c
sysdeps/unix/sysv/linux/hppa/Makefile
sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h
sysdeps/unix/sysv/linux/tst-mman-consts.py
sysdeps/x86/dl-cacheinfo.h
sysdeps/x86_64/dl-tlsdesc.S
sysdeps/x86_64/fpu/fraiseexcpt.c
time/Makefile
time/strftime_l.c
time/strptime_l.c
time/tst-strftime4-time64.c [new file with mode: 0644]
time/tst-strftime4.c [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index ad5196a5f1f3991624a9a6ebe7fa03f09fdfe5c5..c0d999337225ef1fe61f32d54e753de5da1fc580 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,60 @@ See the end for copying conditions.
 Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
 using `glibc' in the "product" field.
 \f
+Version 2.37.1
+
+Security related changes:
+
+  CVE-2023-25139: When the printf family of functions is called with a
+  format specifier that uses an <apostrophe> (enable grouping) and a
+  minimum width specifier, the resulting output could be larger than
+  reasonably expected by a caller that computed a tight bound on the
+  buffer size.  The resulting larger than expected output could result
+  in a buffer overflow in the printf family of functions.
+
+  CVE-2023-4527: If the system is configured in no-aaaa mode via
+  /etc/resolv.conf, getaddrinfo is called for the AF_UNSPEC address
+  family, and a DNS response is received over TCP that is larger than
+  2048 bytes, getaddrinfo may potentially disclose stack contents via
+  the returned address data, or crash.
+
+  CVE-2023-4806: When an NSS plugin only implements the
+  _gethostbyname2_r and _getcanonname_r callbacks, getaddrinfo could use
+  memory that was freed during buffer resizing, potentially causing a
+  crash or read or write to arbitrary memory.
+
+  CVE-2023-5156: The fix for CVE-2023-4806 introduced a memory leak when
+  an application calls getaddrinfo for AF_INET6 with AI_CANONNAME,
+  AI_ALL and AI_V4MAPPED flags set.
+
+  CVE-2023-4911: If a tunable of the form NAME=NAME=VAL is passed in the
+  environment of a setuid program and NAME is valid, it may result in a
+  buffer overflow, which could be exploited to achieve escalated
+  privileges.  This flaw was introduced in glibc 2.34.
+
+The following bugs are resolved with this release:
+
+  [20975] Deferred cancellation triggers in __check_pf and looses lock leading to deadlock
+  [27576] gmon: improve mcount overflow handling
+  [29039] Corrupt DTV after reuse of a TLS module ID following dlclose with unused TLS
+  [29444] gmon: Fix allocated buffer overflow (bug 29444)
+  [30053] time: strftime %s returns -1 after 2038 on 32 bits systems
+  [30101] gmon: fix memory corruption issues
+  [30125] dynamic-link: [regression, bisected] glibc-2.37 creates new
+    symlink for libraries without soname
+  [30151] gshadow: Matching sgetsgent, sgetsgent_r ERANGE handling
+  [30163] posix: Fix system blocks SIGCHLD erroneously
+  [30305] x86_64: Fix asm constraints in feraiseexcept
+  [30428] AMD cache size computation does not work for some CPUs, hypervisors
+  [30477] libc: [RISCV]: time64 does not work on riscv32
+  [30515] _dl_find_object incorrectly returns 1 during early startup
+  [30745] Slight bug in cache info codes for x86
+  [30842] Stack read overflow in getaddrinfo in no-aaaa mode (CVE-2023-4527)
+  [30843] potential use-after-free in getcanonname (CVE-2023-4806)
+  [31183] Wide stream buffer size reduced MB_LEN_MAX bytes after bug 17522 fix
+  [31184] FAIL: elf/tst-tlsgap
+  [31185] Incorrect thread point access in _dl_tlsdesc_undefweak and _dl_tlsdesc_dynamic
+\f
 Version 2.37
 
 Major new features:
@@ -105,6 +159,8 @@ The following bugs are resolved with this release:
     coincides with offset change
   [30039] stdio: __vsprintf_internal does not handle unspecified buffer
     length in fortify mode
+  [30804] F_GETLK, F_SETLK, and F_SETLKW value change for powerpc64 with
+    -D_FILE_OFFSET_BITS=64
 \f
 Version 2.36
 
index b509b3eada1fb77bf81e2a0ca5740b94ad185764..0d19964d428e0851c3b5a02009b5e5f8b3a8fb7b 100644 (file)
@@ -626,6 +626,8 @@ ifeq ($(run-built-tests),yes)
 tests-special += \
   $(objpfx)noload-mem.out \
   $(objpfx)tst-ldconfig-X.out \
+  $(objpfx)tst-ldconfig-p.out \
+  $(objpfx)tst-ldconfig-soname.out \
   $(objpfx)tst-leaks1-mem.out \
   $(objpfx)tst-rtld-help.out \
   # tests-special
@@ -858,6 +860,8 @@ modules-names += \
   tst-initorderb2 \
   tst-latepthreadmod \
   tst-ldconfig-ld-mod \
+  tst-ldconfig-soname-lib-with-soname \
+  tst-ldconfig-soname-lib-without-soname \
   tst-main1mod \
   tst-nodelete2mod \
   tst-nodelete-dlclose-dso \
@@ -2396,6 +2400,22 @@ $(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
                 '$(run-program-env)' > $@; \
        $(evaluate-test)
 
+$(objpfx)tst-ldconfig-p.out : tst-ldconfig-p.sh $(objpfx)ldconfig
+       $(SHELL) $< '$(common-objpfx)' '$(test-wrapper-env)' \
+                '$(run-program-env)' > $@; \
+       $(evaluate-test)
+
+LDFLAGS-tst-ldconfig-soname-lib-with-soname.so = \
+  -Wl,-soname,libtst-ldconfig-soname-lib-with-soname.so.1
+
+$(objpfx)tst-ldconfig-soname.out : tst-ldconfig-soname.sh \
+  $(objpfx)ldconfig \
+  $(objpfx)tst-ldconfig-soname-lib-with-soname.so \
+  $(objpfx)tst-ldconfig-soname-lib-without-soname.so
+       $(SHELL) $< '$(common-objpfx)' '$(test-wrapper-env)' \
+                '$(run-program-env)' > $@; \
+       $(evaluate-test)
+
 # Test static linking of all the libraries we can possibly link
 # together.  Note that in some configurations this may be less than the
 # complete list of libraries we build but we try to maxmimize this list.
index 00e794aa2689b87cd4bc78666a5cd9677b1bffa3..81543f85feb560b4616bd616dc18a2f2abfa5cb4 100644 (file)
@@ -176,8 +176,8 @@ rtld_hidden_def (_dl_audit_symbind_alt)
 
 void
 _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
-                  const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
-                  lookup_t result)
+                  const void *reloc, const ElfW(Sym) *defsym,
+                  DL_FIXUP_VALUE_TYPE *value, lookup_t result, bool lazy)
 {
   bool for_jmp_slot = reloc_result == NULL;
 
@@ -259,7 +259,7 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
     }
 
   if (flags & LA_SYMB_ALTVALUE)
-    DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value);
+    DL_FIXUP_BINDNOW_RELOC (l, reloc, value, new_value, sym.st_value, lazy);
 }
 
 void
index 2ced2f351028edb9e0cc355cd096610c167a70aa..934e77e11f2e50accbc70fbba57db398c1c2b302 100644 (file)
@@ -46,7 +46,7 @@ _dl_find_object_slow (void *pc, struct dl_find_object *result)
           struct dl_find_object_internal internal;
           _dl_find_object_from_map (l, &internal);
           _dl_find_object_to_external (&internal, result);
-          return 1;
+          return 0;
         }
 
   /* Object not found.  */
index 5b0732590fa12a04619d0fb0cc5537d7a1af2ec5..ba4d2fdc859c563ecbfa607d7ea6c1159ed4518f 100644 (file)
 static void
 call_init (struct link_map *l, int argc, char **argv, char **env)
 {
+  /* Do not run constructors for proxy objects.  */
+  if (l != l->l_real)
+    return;
+
   /* If the object has not been relocated, this is a bug.  The
      function pointers are invalid in this case.  (Executables do not
-     need relocation, and neither do proxy objects.)  */
-  assert (l->l_real->l_relocated || l->l_real->l_type == lt_executable);
+     need relocation.)  */
+  assert (l->l_relocated || l->l_type == lt_executable);
 
   if (l->l_init_called)
     /* This object is all done.  */
index d35a725415554337746f562c3f9b16ae8295613c..32a8bfcf7419394fb7bc80cd4c3489d0b42ab5ae 100644 (file)
@@ -139,7 +139,7 @@ _dl_fixup (
       unsigned int init = atomic_load_acquire (&reloc_result->init);
       if (init == 0)
        {
-         _dl_audit_symbind (l, reloc_result, sym, &value, result);
+         _dl_audit_symbind (l, reloc_result, reloc, sym, &value, result, true);
 
          /* Store the result for later runs.  */
          if (__glibc_likely (! GLRO(dl_bind_not)))
@@ -314,7 +314,8 @@ _dl_profile_fixup (
         auditing libraries the possibility to change the value and
         tell us whether further auditing is wanted.  */
       if (defsym != NULL && GLRO(dl_naudit) > 0)
-       _dl_audit_symbind (l, reloc_result, defsym, &value, result);
+       _dl_audit_symbind (l, reloc_result, reloc, defsym, &value, result,
+                          true);
 #endif
 
       /* Store the result for later runs.  */
index 8943a3b4ae29e8f14104dc492e26b0294b235d26..b1e85bde9d46b2adb62c6f27bd82c05cfbecb950 100644 (file)
@@ -160,6 +160,7 @@ _dl_assign_tls_modid (struct link_map *l)
              {
                /* Mark the entry as used, so any dependency see it.  */
                atomic_store_relaxed (&runp->slotinfo[result - disp].map, l);
+               atomic_store_relaxed (&runp->slotinfo[result - disp].gen, 0);
                break;
              }
 
index 327b9eb52f0942cc197c1c13e0d6c5dc9700eddb..985b69c180771f6358ba6c007aa4ade4ab35604d 100644 (file)
@@ -187,11 +187,7 @@ parse_tunables (char *tunestr, char *valstring)
       /* If we reach the end of the string before getting a valid name-value
         pair, bail out.  */
       if (p[len] == '\0')
-       {
-         if (__libc_enable_secure)
-           tunestr[off] = '\0';
-         return;
-       }
+       break;
 
       /* We did not find a valid name-value pair before encountering the
         colon.  */
@@ -251,9 +247,16 @@ parse_tunables (char *tunestr, char *valstring)
            }
        }
 
-      if (p[len] != '\0')
-       p += len + 1;
+      /* We reached the end while processing the tunable string.  */
+      if (p[len] == '\0')
+       break;
+
+      p += len + 1;
     }
+
+  /* Terminate tunestr before we leave.  */
+  if (__libc_enable_secure)
+    tunestr[off] = '\0';
 }
 #endif
 
index a685f5cdbc6abee7466fa928f0fc1664649fa1ae..695ba7192e5f3abeab41801fe5da8cc0f86822bc 100644 (file)
@@ -170,4 +170,17 @@ glibc {
       default: 2
     }
   }
+
+  gmon {
+    minarcs {
+      type: INT_32
+      minval: 50
+      default: 50
+    }
+    maxarcs {
+      type: INT_32
+      minval: 50
+      default: 1048576
+    }
+  }
 }
index 7e1cc4452aeb9d19de954e4411a57ece76802a3c..ea973b155a4e8fa8110f91a702bc29253326422d 100644 (file)
@@ -154,7 +154,8 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
                    = RESOLVE_MAP (map, scope, &sym, rversion,
                                   ELF_MACHINE_JMP_SLOT);
                  if (sym != NULL)
-                   _dl_audit_symbind (map, NULL, sym, r_addr_arg, sym_map);
+                   _dl_audit_symbind (map, NULL, r, sym, r_addr_arg, sym_map,
+                                      false);
                }
 #endif
            }
@@ -200,7 +201,8 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
                                   (struct r_found_version *) NULL,
                                   ELF_MACHINE_JMP_SLOT);
                  if (sym != NULL)
-                   _dl_audit_symbind (map, NULL , sym,r_addr_arg, sym_map);
+                   _dl_audit_symbind (map, NULL, r, sym,r_addr_arg, sym_map,
+                                      false);
                }
 # endif
            }
index b6a75c13a84bb04aff9c70fdfa63a1a681f29b33..4bc0e4299c3a4c8ffa5a4be077af273a16286ecf 100644 (file)
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -4159,6 +4159,46 @@ enum
 #define R_LARCH_GNU_VTINHERIT  57
 #define R_LARCH_GNU_VTENTRY  58
 
+/* reserved 59-63 */
+
+#define R_LARCH_B16 64
+#define R_LARCH_B21 65
+#define R_LARCH_B26 66
+#define R_LARCH_ABS_HI20 67
+#define R_LARCH_ABS_LO12 68
+#define R_LARCH_ABS64_LO20 69
+#define R_LARCH_ABS64_HI12 70
+#define R_LARCH_PCALA_HI20 71
+#define R_LARCH_PCALA_LO12 72
+#define R_LARCH_PCALA64_LO20 73
+#define R_LARCH_PCALA64_HI12 74
+#define R_LARCH_GOT_PC_HI20 75
+#define R_LARCH_GOT_PC_LO12 76
+#define R_LARCH_GOT64_PC_LO20 77
+#define R_LARCH_GOT64_PC_HI12 78
+#define R_LARCH_GOT_HI20 79
+#define R_LARCH_GOT_LO12 80
+#define R_LARCH_GOT64_LO20 81
+#define R_LARCH_GOT64_HI12 82
+#define R_LARCH_TLS_LE_HI20 83
+#define R_LARCH_TLS_LE_LO12 84
+#define R_LARCH_TLS_LE64_LO20 85
+#define R_LARCH_TLS_LE64_HI12 86
+#define R_LARCH_TLS_IE_PC_HI20 87
+#define R_LARCH_TLS_IE_PC_LO12 88
+#define R_LARCH_TLS_IE64_PC_LO20 89
+#define R_LARCH_TLS_IE64_PC_HI12 90
+#define R_LARCH_TLS_IE_HI20 91
+#define R_LARCH_TLS_IE_LO12 92
+#define R_LARCH_TLS_IE64_LO20 93
+#define R_LARCH_TLS_IE64_HI12 94
+#define R_LARCH_TLS_LD_PC_HI20 95
+#define R_LARCH_TLS_LD_HI20 96
+#define R_LARCH_TLS_GD_PC_HI20 97
+#define R_LARCH_TLS_GD_HI20 98
+#define R_LARCH_32_PCREL 99
+#define R_LARCH_RELAX 100
+
 /* ARC specific declarations.  */
 
 /* Processor specific flags for the Ehdr e_flags field.  */
index 166dccb5280cd8ef6bbcf98b4a77e24f7046bfe0..5b1c9139f6b14315a7ab278af00bebae69ce10e5 100644 (file)
@@ -616,7 +616,7 @@ manual_link (char *library)
       goto out;
     }
   if (soname == NULL)
-    soname = implicit_soname (libname, flag);
+    soname = xstrdup (libname);
   create_links (real_path, path, libname, soname);
   free (soname);
 out:
@@ -849,7 +849,7 @@ search_dir (const struct dir_entry *entry)
        }
 
       if (soname == NULL)
-       soname = implicit_soname (direntry->d_name, flag);
+       soname = xstrdup (direntry->d_name);
 
       /* A link may just point to itself.  */
       if (is_link)
index f5b8c80e385139ccf4096758c0daf136bb33888e..64f1d662a9a3fccfe4dafd6da2a2c912ddcef286 100644 (file)
@@ -107,6 +107,7 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
        case PT_INTERP:
          program_interpreter = (char *) (file_contents + segment->p_offset);
          check_ptr (program_interpreter);
+         break;
 
        case PT_GNU_PROPERTY:
          /* The NT_GNU_PROPERTY_TYPE_0 note must be aligned to 4 bytes
index c5c3591eef1e229c3d98aea3537626cc23ebe869..bc13d9acc64cf869473a24c2ba3a237d3f55381f 100644 (file)
@@ -166,24 +166,5 @@ process_file (const char *real_file_name, const char *file_name,
   return ret;
 }
 
-/* Returns made up soname if lib doesn't have explicit DT_SONAME.  */
-
-char *
-implicit_soname (const char *lib, int flag)
-{
-  char *soname = xstrdup (lib);
-
-  /* Aout files don't have a soname, just return the name
-     including the major number.  */
-  char *major = strstr (soname, ".so.");
-  if (major)
-    {
-      char *dot = strstr (major + 4, ".");
-      if (dot)
-       *dot = '\0';
-    }
-  return soname;
-}
-
 /* Get architecture specific version of process_elf_file.  */
 #include <readelflib.c>
index f6ab9913987ea1174bd0fc906b5a76ef58b4a2ce..f6dfbbe2028fa55e0ba06d1faedd19d3bc79154f 100644 (file)
@@ -71,6 +71,17 @@ la_version (unsigned int current)
   TEST_VERIFY (dladdr1 (&_exit, &info, &extra_info, RTLD_DL_LINKMAP) != 0);
   TEST_VERIFY (extra_info == handle);
 
+  /* Check _dl_find_object.  */
+  struct dl_find_object dlfo;
+  TEST_COMPARE (_dl_find_object (__builtin_return_address (0), &dlfo), 0);
+  /* "ld.so" is seen with --enable-hardcoded-path-in-tests.  */
+  if (strcmp (basename (dlfo.dlfo_link_map->l_name), "ld.so") != 0)
+    TEST_COMPARE_STRING (basename (dlfo.dlfo_link_map->l_name), LD_SO);
+  TEST_COMPARE (_dl_find_object (dlsym (handle, "environ"), &dlfo), 0);
+  TEST_COMPARE_STRING (basename (dlfo.dlfo_link_map->l_name), LIBC_SO);
+  TEST_COMPARE (_dl_find_object ((void *) 1, &dlfo), -1);
+  TEST_COMPARE (_dl_find_object ((void *) -1, &dlfo), -1);
+
   /* Verify that dlmopen creates a new namespace.  */
   void *dlmopen_handle = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
   TEST_VERIFY (dlmopen_handle != handle);
index 807b426012e9753a4ee3d7049b798dd668bd0ec5..1f5e7f4f064cf0aa8c23880eeccde050b4e08f43 100644 (file)
@@ -52,6 +52,8 @@ const char *teststrings[] =
   "glibc.malloc.perturb=0x800:not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
   "glibc.not_valid.check=2:glibc.malloc.mmap_threshold=4096",
   "not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
+  "glibc.malloc.mmap_threshold=glibc.malloc.mmap_threshold=4096",
+  "glibc.malloc.check=2",
   "glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096:glibc.malloc.check=2",
   "glibc.malloc.check=4:glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096",
   ":glibc.malloc.garbage=2:glibc.malloc.check=1",
@@ -70,6 +72,8 @@ const char *resultstrings[] =
   "glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096",
   "glibc.malloc.mmap_threshold=4096",
   "glibc.malloc.mmap_threshold=4096",
+  "glibc.malloc.mmap_threshold=glibc.malloc.mmap_threshold=4096",
+  "",
   "",
   "",
   "",
@@ -84,11 +88,18 @@ test_child (int off)
   const char *val = getenv ("GLIBC_TUNABLES");
 
 #if HAVE_TUNABLES
+  printf ("    [%d] GLIBC_TUNABLES is %s\n", off, val);
+  fflush (stdout);
   if (val != NULL && strcmp (val, resultstrings[off]) == 0)
     return 0;
 
   if (val != NULL)
-    printf ("[%d] Unexpected GLIBC_TUNABLES VALUE %s\n", off, val);
+    printf ("    [%d] Unexpected GLIBC_TUNABLES VALUE %s, expected %s\n",
+           off, val, resultstrings[off]);
+  else
+    printf ("    [%d] GLIBC_TUNABLES environment variable absent\n", off);
+
+  fflush (stdout);
 
   return 1;
 #else
@@ -117,21 +128,26 @@ do_test (int argc, char **argv)
       if (ret != 0)
        exit (1);
 
-      exit (EXIT_SUCCESS);
+      /* Special return code to make sure that the child executed all the way
+        through.  */
+      exit (42);
     }
   else
     {
-      int ret = 0;
-
       /* Spawn tests.  */
       for (int i = 0; i < array_length (teststrings); i++)
        {
          char buf[INT_BUFSIZE_BOUND (int)];
 
-         printf ("Spawned test for %s (%d)\n", teststrings[i], i);
+         printf ("[%d] Spawned test for %s\n", i, teststrings[i]);
          snprintf (buf, sizeof (buf), "%d\n", i);
+         fflush (stdout);
          if (setenv ("GLIBC_TUNABLES", teststrings[i], 1) != 0)
-           exit (1);
+           {
+             printf ("    [%d] Failed to set GLIBC_TUNABLES: %m", i);
+             support_record_failure ();
+             continue;
+           }
 
          int status = support_capture_subprogram_self_sgid (buf);
 
@@ -139,9 +155,14 @@ do_test (int argc, char **argv)
          if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
            return EXIT_UNSUPPORTED;
 
-         ret |= status;
+         if (WEXITSTATUS (status) != 42)
+           {
+             printf ("    [%d] child failed with status %d\n", i,
+                     WEXITSTATUS (status));
+             support_record_failure ();
+           }
        }
-      return ret;
+      return 0;
     }
 }
 
diff --git a/elf/tst-ldconfig-p.sh b/elf/tst-ldconfig-p.sh
new file mode 100644 (file)
index 0000000..ec937bf
--- /dev/null
@@ -0,0 +1,77 @@
+#!/bin/sh
+# Test that ldconfig -p prints something useful.
+# Copyright (C) 2023 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/>.
+
+# Check that the newly built ldconfig -p can dump the system
+# /etc/ld.so.cache file.  This should always work even if the ABIs are
+# not compatible, except in a cross-endian build (that presumably
+# involves emulation when running ldconfig).
+
+common_objpfx=$1
+test_wrapper_env=$2
+run_program_env=$3
+
+if ! test -r /etc/ld.so.cache; then
+    echo "warning: /etc/ld.so.cache does not exist, test skipped"
+    exit 77
+fi
+
+testout="${common_objpfx}elf/tst-ldconfig-p.out"
+# Truncate file.
+: > "$testout"
+
+${test_wrapper_env} \
+${run_program_env} \
+${common_objpfx}elf/ldconfig -p \
+  $testroot/lib >>"$testout" 2>>"$testout"
+status=$?
+echo "info: ldconfig exit status: $status" >>"$testout"
+
+errors=0
+case $status in
+    (0)
+       if head -n 1 "$testout" | \
+               grep -q "libs found in cache \`/etc/ld.so.cache'\$" ; then
+           echo "info: initial string found" >>"$testout"
+       else
+           echo "error: initial string not found" >>"$testout"
+           errors=1
+       fi
+       if grep -q "^   libc\.so\..* => " "$testout"; then
+           echo "info: libc.so.* string found" >>"$testout"
+       else
+           echo "error: libc.so.* string not found" >>"$testout"
+           errors=1
+       fi
+       ;;
+    (1)
+       if head -n 1 "$testout" | \
+               grep -q ": Cache file has wrong endianness\.$" ; then
+           echo "info: cache file has wrong endianess" >> "$testout"
+       else
+           echo "error: unexpected ldconfig error message" >> "$testout"
+           errors=1
+       fi
+       ;;
+    (*)
+       echo "error: unexpected exit status" >> "$testout"
+       errors=1
+       ;;
+esac
+
+exit $errors
diff --git a/elf/tst-ldconfig-soname-lib-with-soname.c b/elf/tst-ldconfig-soname-lib-with-soname.c
new file mode 100644 (file)
index 0000000..d1ab56a
--- /dev/null
@@ -0,0 +1 @@
+/* This file intentionally left blank */
diff --git a/elf/tst-ldconfig-soname-lib-without-soname.c b/elf/tst-ldconfig-soname-lib-without-soname.c
new file mode 100644 (file)
index 0000000..d1ab56a
--- /dev/null
@@ -0,0 +1 @@
+/* This file intentionally left blank */
diff --git a/elf/tst-ldconfig-soname.sh b/elf/tst-ldconfig-soname.sh
new file mode 100644 (file)
index 0000000..406f526
--- /dev/null
@@ -0,0 +1,49 @@
+#!/bin/sh
+# Test that ldconfig creates symlinks according to the library's soname
+# (and in particular, does not create symlinks for libraries without a soname)
+# Copyright (C) 2000-2023 Free Software Foundation, Inc.
+# Copyright The GNU Toolchain Authors.
+# 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/>.
+
+set -ex
+
+common_objpfx=$1
+test_wrapper_env=$2
+run_program_env=$3
+
+testroot="${common_objpfx}elf/bug30125-test-directory"
+cleanup () {
+    rm -rf "$testroot"
+}
+trap cleanup 0
+
+rm -rf "$testroot"
+mkdir -p $testroot/lib
+cp "${common_objpfx}elf/tst-ldconfig-soname-lib-with-soname.so" \
+    $testroot/lib/libtst-ldconfig-soname-lib-with-soname.so.1.2.3
+cp "${common_objpfx}elf/tst-ldconfig-soname-lib-without-soname.so" \
+    $testroot/lib/libtst-ldconfig-soname-lib-without-soname.so.1.2.3
+
+${test_wrapper_env} \
+${run_program_env} \
+${common_objpfx}elf/ldconfig -vn $testroot/lib
+
+LINKS=$(cd $testroot/lib && find . -type l)
+if [ "$LINKS" != "./libtst-ldconfig-soname-lib-with-soname.so.1" ]; then
+    echo "error: $0 - extra symlinks found"
+    exit 1
+fi
index 4dd5adb80b817fe5f14ff7777d2e097625eb4627..fbe2b0ba5c5787e9f90a1799477cd916da294481 100644 (file)
@@ -1,4 +1,5 @@
 # Copyright (C) 1995-2023 Free Software Foundation, Inc.
+# Copyright The GNU Toolchain Authors.
 # This file is part of the GNU C Library.
 
 # The GNU C Library is free software; you can redistribute it and/or
@@ -25,7 +26,7 @@ include ../Makeconfig
 headers        := sys/gmon.h sys/gmon_out.h sys/profil.h
 routines := gmon mcount profil sprofil prof-freq
 
-tests  = tst-sprofil tst-gmon
+tests  = tst-sprofil tst-gmon tst-mcleanup
 ifeq ($(build-profile),yes)
 tests  += tst-profile-static
 tests-static   += tst-profile-static
@@ -56,6 +57,14 @@ ifeq ($(run-built-tests),yes)
 tests-special += $(objpfx)tst-gmon-gprof.out
 endif
 
+CFLAGS-tst-mcleanup.c := -fno-omit-frame-pointer -pg
+tst-mcleanup-no-pie = yes
+CRT-tst-mcleanup := $(csu-objpfx)g$(start-installed-name)
+tst-mcleanup-ENV := GMON_OUT_PREFIX=$(objpfx)tst-mcleanup.data
+ifeq ($(run-built-tests),yes)
+tests-special += $(objpfx)tst-mcleanup.out
+endif
+
 CFLAGS-tst-gmon-static.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg
 CRT-tst-gmon-static := $(csu-objpfx)g$(static-start-installed-name)
 tst-gmon-static-no-pie = yes
@@ -103,6 +112,18 @@ $(objpfx)tst-gmon.out: clean-tst-gmon-data
 clean-tst-gmon-data:
        rm -f $(objpfx)tst-gmon.data.*
 
+$(objpfx)tst-mcount-overflow.o: clean-tst-mcount-overflow-data
+clean-tst-mcount-overflow-data:
+       rm -f $(objpfx)tst-mcount-overflow.data.*
+
+$(objpfx)tst-mcount-overflow-check.out: tst-mcount-overflow-check.sh $(objpfx)tst-mcount-overflow.out
+       $(SHELL) $< $(objpfx)tst-mcount-overflow > $@; \
+       $(evaluate-test)
+
+$(objpfx)tst-mcleanup.out: clean-tst-mcleanup-data
+clean-tst-mcleanup-data:
+       rm -f $(objpfx)tst-mcleanup.data.*
+
 $(objpfx)tst-gmon-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon.out
        $(SHELL) $< $(GPROF) $(objpfx)tst-gmon $(objpfx)tst-gmon.data.* > $@; \
        $(evaluate-test)
index dee64803ada583d79ca9adc281beffce4300255f..97be1f72caa163e10e8c0df39426f5870ff3fd92 100644 (file)
@@ -97,11 +97,8 @@ __moncontrol (int mode)
 {
   struct gmonparam *p = &_gmonparam;
 
-  /* Don't change the state if we ran into an error.  */
-  if (p->state == GMON_PROF_ERROR)
-    return;
-
-  if (mode)
+  /* Treat start request as stop if error or gmon not initialized. */
+  if (mode && p->state != GMON_PROF_ERROR && p->tos != NULL)
     {
       /* start */
       __profil((void *) p->kcount, p->kcountsize, p->lowpc, s_scale);
@@ -111,7 +108,9 @@ __moncontrol (int mode)
     {
       /* stop */
       __profil(NULL, 0, 0, 0);
-      p->state = GMON_PROF_OFF;
+      /* Don't change the state if we ran into an error. */
+      if (p->state != GMON_PROF_ERROR)
+        p->state = GMON_PROF_OFF;
     }
 }
 libc_hidden_def (__moncontrol)
@@ -124,6 +123,19 @@ __monstartup (u_long lowpc, u_long highpc)
   int o;
   char *cp;
   struct gmonparam *p = &_gmonparam;
+  long int minarcs, maxarcs;
+
+  /* No tunables, we use hardcoded defaults */
+  minarcs = MINARCS;
+  maxarcs = MAXARCS;
+
+  /*
+   * If we are incorrectly called twice in a row (without an
+   * intervening call to _mcleanup), ignore the second call to
+   * prevent leaking memory.
+   */
+  if (p->tos != NULL)
+      return;
 
   /*
    * round lowpc and highpc to multiples of the density we're using
@@ -132,6 +144,8 @@ __monstartup (u_long lowpc, u_long highpc)
   p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
   p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER));
   p->textsize = p->highpc - p->lowpc;
+  /* This looks like a typo, but it's here to align the p->froms
+     section.  */
   p->kcountsize = ROUNDUP(p->textsize / HISTFRACTION, sizeof(*p->froms));
   p->hashfraction = HASHFRACTION;
   p->log_hashfraction = -1;
@@ -142,12 +156,12 @@ __monstartup (u_long lowpc, u_long highpc)
         instead of integer division.  Precompute shift amount. */
       p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1;
   }
-  p->fromssize = p->textsize / HASHFRACTION;
+  p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms));
   p->tolimit = p->textsize * ARCDENSITY / 100;
-  if (p->tolimit < MINARCS)
-    p->tolimit = MINARCS;
-  else if (p->tolimit > MAXARCS)
-    p->tolimit = MAXARCS;
+  if (p->tolimit < minarcs)
+    p->tolimit = minarcs;
+  else if (p->tolimit > maxarcs)
+    p->tolimit = maxarcs;
   p->tossize = p->tolimit * sizeof(struct tostruct);
 
   cp = calloc (p->kcountsize + p->fromssize + p->tossize, 1);
@@ -440,9 +454,14 @@ _mcleanup (void)
 {
   __moncontrol (0);
 
-  if (_gmonparam.state != GMON_PROF_ERROR)
+  if (_gmonparam.state != GMON_PROF_ERROR && _gmonparam.tos != NULL)
     write_gmon ();
 
   /* free the memory. */
   free (_gmonparam.tos);
+
+  /* reset buffer to initial state for safety */
+  memset(&_gmonparam, 0, sizeof _gmonparam);
+  /* somewhat confusingly, ON=0, OFF=3 */
+  _gmonparam.state = GMON_PROF_OFF;
 }
index 9d4a1a50fa6ab21af97293c4ec59a199c06f0a5d..f7180fdb83399a1426b64fbe23b385d4f10255b9 100644 (file)
@@ -41,6 +41,10 @@ static char sccsid[] = "@(#)mcount.c 8.1 (Berkeley) 6/4/93";
 
 #include <atomic.h>
 
+#include <not-cancel.h>
+#include <unistd.h>
+#define ERR(s) __write_nocancel (STDERR_FILENO, s, sizeof (s) - 1)
+
 /*
  * mcount is called on entry to each function compiled with the profiling
  * switch set.  _mcount(), which is declared in a machine-dependent way
@@ -170,6 +174,7 @@ done:
        return;
 overflow:
        p->state = GMON_PROF_ERROR;
+       ERR("mcount: call graph buffer size limit exceeded, gmon.out will not be generated\n");
        return;
 }
 
index b4cc3b043a2aec77d55d4bb819cf24ae6c9a0ed0..af0582a3717085b531954ef1b94587f79acb3e66 100644 (file)
@@ -111,6 +111,8 @@ extern struct __bb *__bb_head;
  * Always allocate at least this many tostructs.  This
  * hides the inadequacy of the ARCDENSITY heuristic, at least
  * for small programs.
+ *
+ * Value can be overridden at runtime by glibc.gmon.minarcs tunable.
  */
 #define MINARCS                50
 
@@ -124,8 +126,8 @@ extern struct __bb *__bb_head;
  * Used to be max representable value of ARCINDEX minus 2, but now
  * that ARCINDEX is a long, that's too large; we don't really want
  * to allow a 48 gigabyte table.
- * The old value of 1<<16 wasn't high enough in practice for large C++
- * programs; will 1<<20 be adequate for long?  FIXME
+ *
+ * Value can be overridden at runtime by glibc.gmon.maxarcs tunable.
  */
 #define MAXARCS                (1 << 20)
 
diff --git a/gmon/tst-mcleanup.c b/gmon/tst-mcleanup.c
new file mode 100644 (file)
index 0000000..b259653
--- /dev/null
@@ -0,0 +1,31 @@
+/* Test program for repeated invocation of _mcleanup
+   Copyright The GNU Toolchain Authors.
+   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/>.  */
+
+/* Intentionally calls _mcleanup() twice: once manually, it will be
+   called again as an atexit handler. This is incorrect use of the API,
+   but the point of the test is to make sure we don't crash when the
+   API is misused in this way. */
+
+#include <sys/gmon.h>
+
+int
+main (void)
+{
+  _mcleanup();
+  return 0;
+}
diff --git a/gmon/tst-mcount-overflow-check.sh b/gmon/tst-mcount-overflow-check.sh
new file mode 100644 (file)
index 0000000..27eb553
--- /dev/null
@@ -0,0 +1,45 @@
+#!/bin/sh
+# Test expected messages generated when mcount overflows
+# Copyright (C) 2017-2023 Free Software Foundation, Inc.
+# Copyright The GNU Toolchain Authors.
+# 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/>.
+
+LC_ALL=C
+export LC_ALL
+set -e
+exec 2>&1
+
+program="$1"
+
+check_msg() {
+    if ! grep -q "$1" "$program.out"; then
+       echo "FAIL: expected message not in output: $1"
+       exit 1
+    fi
+}
+
+check_msg 'monstartup: maxarcs < minarcs, setting maxarcs = minarcs'
+check_msg 'mcount: call graph buffer size limit exceeded, gmon.out will not be generated'
+
+for data_file in $1.data.*; do
+  if [ -f "$data_file" ]; then
+    echo "FAIL: expected no data files, but found $data_file"
+    exit 1
+  fi
+done
+
+echo PASS
diff --git a/gmon/tst-mcount-overflow.c b/gmon/tst-mcount-overflow.c
new file mode 100644 (file)
index 0000000..06cc93e
--- /dev/null
@@ -0,0 +1,72 @@
+/* Test program to trigger mcount overflow in profiling collection.
+   Copyright (C) 2017-2023 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/>.  */
+
+/* Program with sufficiently complex, yet pointless, call graph
+   that it will trigger an mcount overflow, when you set the
+   minarcs/maxarcs tunables to very low values. */
+
+#define PREVENT_TAIL_CALL asm volatile ("")
+
+/* Calls REP(n) macro 16 times, for n=0..15.
+ * You need to define REP(n) before using this.
+ */
+#define REPS \
+  REP(0) REP(1) REP(2) REP(3) REP(4) REP(5) REP(6) REP(7) \
+  REP(8) REP(9) REP(10) REP(11) REP(12) REP(13) REP(14) REP(15)
+
+/* Defines 16 leaf functions named f1_0 to f1_15 */
+#define REP(n) \
+  __attribute__ ((noinline, noclone, weak)) void f1_##n (void) {};
+REPS
+#undef REP
+
+/* Calls all 16 leaf functions f1_* in succession */
+__attribute__ ((noinline, noclone, weak)) void
+f2 (void)
+{
+# define REP(n) f1_##n();
+  REPS
+# undef REP
+  PREVENT_TAIL_CALL;
+}
+
+/* Defines 16 functions named f2_0 to f2_15, which all just call f2 */
+#define REP(n) \
+  __attribute__ ((noinline, noclone, weak)) void \
+  f2_##n (void) { f2(); PREVENT_TAIL_CALL; };
+REPS
+#undef REP
+
+__attribute__ ((noinline, noclone, weak)) void
+f3 (int count)
+{
+  for (int i = 0; i < count; ++i)
+    {
+      /* Calls f1_0(), f2_0(), f1_1(), f2_1(), f3_0(), etc */
+#     define REP(n) f1_##n(); f2_##n();
+      REPS
+#     undef REP
+    }
+}
+
+int
+main (void)
+{
+  f3 (1000);
+  return 0;
+}
index 796fbbf4733ba9ac382306300b033ca764186f8e..a95524593a502ed1035f688b3c4ae3d007200034 100644 (file)
@@ -26,7 +26,7 @@ headers               = gshadow.h
 routines       = getsgent getsgnam sgetsgent fgetsgent putsgent \
                  getsgent_r getsgnam_r sgetsgent_r fgetsgent_r
 
-tests = tst-gshadow tst-putsgent tst-fgetsgent_r
+tests = tst-gshadow tst-putsgent tst-fgetsgent_r tst-sgetsgent
 
 CFLAGS-getsgent_r.c += -fexceptions
 CFLAGS-getsgent.c += -fexceptions
index ea085e91d7c2aa8cc501d14a6bf2865e32790a4e..c75624e1f75658aaf37c7fb572ef0e6a9fc496cb 100644 (file)
@@ -61,7 +61,10 @@ __sgetsgent_r (const char *string, struct sgrp *resbuf, char *buffer,
       buffer[buflen - 1] = '\0';
       sp = strncpy (buffer, string, buflen);
       if (buffer[buflen - 1] != '\0')
-       return ERANGE;
+       {
+         __set_errno (ERANGE);
+         return ERANGE;
+       }
     }
   else
     sp = (char *) string;
diff --git a/gshadow/tst-sgetsgent.c b/gshadow/tst-sgetsgent.c
new file mode 100644 (file)
index 0000000..0370c10
--- /dev/null
@@ -0,0 +1,69 @@
+/* Test large input for sgetsgent (bug 30151).
+   Copyright (C) 2023 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 <gshadow.h>
+#include <stddef.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+#include <stdlib.h>
+
+static int
+do_test (void)
+{
+  /* Create a shadow group with 1000 members.  */
+  struct xmemstream mem;
+  xopen_memstream (&mem);
+  const char *passwd = "k+zD0nucwfxAo3sw1NXUj6K5vt5M16+X0TVGdE1uFvq5R8V7efJ";
+  fprintf (mem.out, "group-name:%s::m0", passwd);
+  for (int i = 1; i < 1000; ++i)
+    fprintf (mem.out, ",m%d", i);
+  xfclose_memstream (&mem);
+
+  /* Call sgetsgent.  */
+  char *input = mem.buffer;
+  struct sgrp *e = sgetsgent (input);
+  TEST_VERIFY_EXIT (e != NULL);
+  TEST_COMPARE_STRING (e->sg_namp, "group-name");
+  TEST_COMPARE_STRING (e->sg_passwd, passwd);
+  /* No administrators.  */
+  TEST_COMPARE_STRING (e->sg_adm[0], NULL);
+  /* Check the members list.  */
+  for (int i = 0; i < 1000; ++i)
+    {
+      char *member = xasprintf ("m%d", i);
+      TEST_COMPARE_STRING (e->sg_mem[i], member);
+      free (member);
+    }
+  TEST_COMPARE_STRING (e->sg_mem[1000], NULL);
+
+  /* Check that putsgent brings back the input string.  */
+  xopen_memstream (&mem);
+  TEST_COMPARE (putsgent (e, mem.out), 0);
+  xfclose_memstream (&mem);
+  /* Compare without the trailing '\n' that putsgent added.  */
+  TEST_COMPARE (mem.buffer[mem.length - 1], '\n');
+  mem.buffer[mem.length - 1] = '\0';
+  TEST_COMPARE_STRING (mem.buffer, input);
+
+  free (mem.buffer);
+  free (input);
+  return 0;
+}
+
+#include <support/test-driver.c>
index e8a9c7981f51f083deb2dc9f65acfa8a0091927f..5ee2233aa9a2be2ae214160abc2838e6f9dd66e3 100644 (file)
@@ -31,7 +31,7 @@ _S_catch_exception_raise (mach_port_t port,
                          mach_msg_type_number_t codeCnt
 #else                          /* Vanilla Mach 3.0 interface.  */
                          integer_t exception,
-                         integer_t code, integer_t subcode
+                         integer_t code, long_integer_t subcode
 #endif
                          )
 {
index 4e9f79b19d0d9786251bc42e69ea1de4b8b9d741..c33f974b1bac1dc77909d93d9c1f667e8f97c1cd 100644 (file)
@@ -51,9 +51,10 @@ struct hurd_signal_preemptor;        /* <hurd/sigpreempt.h> */
 struct hurd_signal_detail
   {
     /* Codes from origination Mach exception_raise message.  */
-    integer_t exc, exc_code, exc_subcode;
+    integer_t exc, exc_code;
+    long_integer_t exc_subcode;
     /* Sigcode as passed or computed from exception codes.  */
-    integer_t code;
+    long_integer_t code;
     /* Error code as passed or extracted from exception codes.  */
     error_t error;
   };
index 069c1c262c9e982fa4cd02487dd9e69c763828f6..a81e72803f8d5bcd665c69457e531507d9f3b8e3 100644 (file)
@@ -45,7 +45,7 @@ _hurdsig_fault_catch_exception_raise (mach_port_t port,
                                      mach_msg_type_number_t codeCnt
 #else                          /* Vanilla Mach 3.0 interface.  */
                                      integer_t exception,
-                                     integer_t code, integer_t subcode
+                                     integer_t code, long_integer_t subcode
 #endif
                                      )
 {
index 1d74feb2bd6406d5f5a69c225b06c8b5cb8025a0..69bda3ed174a4e8ef4217cfa141d8281ac5fa5b6 100644 (file)
@@ -278,6 +278,10 @@ struct link_map
     /* List of object in order of the init and fini calls.  */
     struct link_map **l_initfini;
 
+    /* Linked list of objects in reverse ELF constructor execution
+       order.  Head of list is stored in _dl_init_called_list.  */
+    struct link_map *l_init_called_next;
+
     /* List of the dependencies introduced through symbol binding.  */
     struct link_map_reldeps
       {
index f72571cdaee7c16c127b9f4a67ebf278d649e9b7..069e6751886b6f43c00aa4c329c963edd339943a 100644 (file)
@@ -59,6 +59,7 @@ routines :=                                                           \
        ftw64-time64                                                    \
        closefrom close_range
 
+
 others         := pwd
 test-srcs      := ftwtest ftwtest-time64
 tests          := test-utime test-stat test-stat2 test-lfs tst-getcwd \
@@ -80,7 +81,9 @@ tests         := test-utime test-stat test-stat2 test-lfs tst-getcwd \
                   tst-utimensat \
                   tst-closefrom \
                   tst-close_range \
-                  tst-ftw-bz28126
+                  tst-ftw-bz28126 \
+                  tst-fcntl-lock \
+                  tst-fcntl-lock-lfs
 
 tests-time64 := \
   tst-fcntl-time64 \
diff --git a/io/tst-fcntl-lock-lfs.c b/io/tst-fcntl-lock-lfs.c
new file mode 100644 (file)
index 0000000..f2a909f
--- /dev/null
@@ -0,0 +1,2 @@
+#define _FILE_OFFSET_BITS 64
+#include <io/tst-fcntl-lock.c>
diff --git a/io/tst-fcntl-lock.c b/io/tst-fcntl-lock.c
new file mode 100644 (file)
index 0000000..357c4b7
--- /dev/null
@@ -0,0 +1,97 @@
+/* Test for advisory record locking.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+   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; either 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/>.
+*/
+
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+
+/* This is essentially the POSIX lockf.  */
+
+static int
+fcntl_lockf (int fd, int cmd, off_t len)
+{
+  struct flock fl = {
+    .l_type = F_WRLCK,
+    .l_whence = SEEK_CUR,
+    .l_len = len
+  };
+
+  switch (cmd)
+    {
+    case F_TEST:
+      fl.l_type = F_RDLCK;
+      if (fcntl (fd, F_GETLK, &fl) < 0)
+       return -1;
+      if (fl.l_type == F_UNLCK || fl.l_pid == getpid ())
+       return 0;
+      errno = EACCES;
+      return -1;
+
+    case F_ULOCK:
+      fl.l_type = F_UNLCK;
+      return fcntl (fd, F_SETLK, &fl);
+
+    case F_LOCK:
+      return fcntl (fd, F_SETLKW, &fl);
+
+    case F_TLOCK:
+      return fcntl (fd, F_SETLK, &fl);
+    }
+
+  errno = EINVAL;
+  return -1;
+}
+
+static int
+fcntl64_lockf (int fd, int cmd, off64_t len64)
+  {
+  struct flock64 fl64 = {
+    .l_type = F_WRLCK,
+    .l_whence = SEEK_CUR,
+    .l_len = len64
+  };
+
+  switch (cmd)
+    {
+    case F_TEST:
+      fl64.l_type = F_RDLCK;
+      if (fcntl64 (fd, F_GETLK64, &fl64) < 0)
+       return -1;
+      if (fl64.l_type == F_UNLCK || fl64.l_pid == getpid ())
+       return 0;
+      errno = EACCES;
+      return -1;
+
+    case F_ULOCK:
+      fl64.l_type = F_UNLCK;
+      return fcntl64 (fd, F_SETLK64, &fl64);
+
+    case F_LOCK:
+      return fcntl64 (fd, F_SETLKW64, &fl64);
+
+    case F_TLOCK:
+      return fcntl64 (fd, F_SETLK64, &fl64);
+    }
+
+  errno = EINVAL;
+  return -1;
+}
+
+#define TST_LOCKFD  "tst-fcntl-lock."
+#define LOCKF       fcntl_lockf
+#define LOCKF64     fcntl64_lockf
+#include "tst-lockf.c"
index eda04b5417d6d9603d8d139f4159acd746bbf8e0..cf8d3001c3f93eee5739adfd160a2209708ec9e8 100644 (file)
 #include <support/capture_subprocess.h>
 #include <support/check.h>
 
+#ifndef TST_LOCKFD
+# define TST_LOCKFD "tst-lockfd."
+#endif
+#ifndef LOCKF
+# define LOCKF lockf
+#endif
+#ifndef LOCKF64
+# define LOCKF64 lockf64
+#endif
+
 static char *temp_filename;
 static int temp_fd;
 
 static void
 do_prepare (int argc, char **argv)
 {
-  temp_fd = create_temp_file ("tst-lockfd.", &temp_filename);
+  temp_fd = create_temp_file (TST_LOCKFD, &temp_filename);
   TEST_VERIFY_EXIT (temp_fd != -1);
 }
 #define PREPARE do_prepare
@@ -40,22 +50,22 @@ do_test_child_lockf (void *closure)
 {
   /* Check if parent has [0, 1024) locked.  */
   TEST_COMPARE (lseek (temp_fd, 0, SEEK_SET), 0);
-  TEST_COMPARE (lockf (temp_fd, F_TLOCK, 1024), -1);
+  TEST_COMPARE (LOCKF (temp_fd, F_TLOCK, 1024), -1);
   TEST_COMPARE (errno, EAGAIN);
-  TEST_COMPARE (lockf (temp_fd, F_TEST, 1024), -1);
+  TEST_COMPARE (LOCKF (temp_fd, F_TEST, 1024), -1);
   TEST_COMPARE (errno, EACCES);
   /* Also Check if parent has last 1024 bytes locked.  */
   TEST_COMPARE (lseek (temp_fd, INT32_MAX-1024, SEEK_SET), INT32_MAX-1024);
-  TEST_COMPARE (lockf (temp_fd, F_TEST, 1024), -1);
+  TEST_COMPARE (LOCKF (temp_fd, F_TEST, 1024), -1);
 
   /* And try to lock [1024, 2048).  */
   TEST_COMPARE (lseek (temp_fd, 1024, SEEK_SET), 1024);
-  TEST_COMPARE (lockf (temp_fd, F_LOCK, 1024), 0);
+  TEST_COMPARE (LOCKF (temp_fd, F_LOCK, 1024), 0);
 
   /* Check if non-LFS interface cap access to 32-bif off_t.  */
   TEST_COMPARE (lseek64 (temp_fd, (off64_t)INT32_MAX, SEEK_SET),
                (off64_t)INT32_MAX);
-  TEST_COMPARE (lockf64 (temp_fd, F_TEST, 1024), 0);
+  TEST_COMPARE (LOCKF64 (temp_fd, F_TEST, 1024), 0);
 }
 
 static void
@@ -63,32 +73,32 @@ do_test_child_lockf64 (void *closure)
 {
   /* Check if parent has [0, 1024) locked.  */
   TEST_COMPARE (lseek64 (temp_fd, 0, SEEK_SET), 0);
-  TEST_COMPARE (lockf64 (temp_fd, F_TLOCK, 1024), -1);
+  TEST_COMPARE (LOCKF64 (temp_fd, F_TLOCK, 1024), -1);
   TEST_COMPARE (errno, EAGAIN);
-  TEST_COMPARE (lockf64 (temp_fd, F_TEST, 1024), -1);
+  TEST_COMPARE (LOCKF64 (temp_fd, F_TEST, 1024), -1);
   TEST_COMPARE (errno, EACCES);
   /* Also Check if parent has last 1024 bytes locked.  */
   TEST_COMPARE (lseek64 (temp_fd, INT32_MAX-1024, SEEK_SET), INT32_MAX-1024);
-  TEST_COMPARE (lockf64 (temp_fd, F_TEST, 1024), -1);
+  TEST_COMPARE (LOCKF64 (temp_fd, F_TEST, 1024), -1);
 
   /* And try to lock [1024, 2048).  */
   TEST_COMPARE (lseek64 (temp_fd, 1024, SEEK_SET), 1024);
-  TEST_COMPARE (lockf64 (temp_fd, F_LOCK, 1024), 0);
+  TEST_COMPARE (LOCKF64 (temp_fd, F_LOCK, 1024), 0);
 
   /* And also [INT32_MAX, INT32_MAX+1024).  */
   {
     off64_t off = (off64_t)INT32_MAX;
     TEST_COMPARE (lseek64 (temp_fd, off, SEEK_SET), off);
-    TEST_COMPARE (lockf64 (temp_fd, F_LOCK, 1024), 0);
+    TEST_COMPARE (LOCKF64 (temp_fd, F_LOCK, 1024), 0);
   }
 
   /* Check if [INT32_MAX+1024, INT64_MAX) is locked.  */
   {
     off64_t off = (off64_t)INT32_MAX+1024;
     TEST_COMPARE (lseek64 (temp_fd, off, SEEK_SET), off);
-    TEST_COMPARE (lockf64 (temp_fd, F_TLOCK, 1024), -1);
+    TEST_COMPARE (LOCKF64 (temp_fd, F_TLOCK, 1024), -1);
     TEST_COMPARE (errno, EAGAIN);
-    TEST_COMPARE (lockf64 (temp_fd, F_TEST, 1024), -1);
+    TEST_COMPARE (LOCKF64 (temp_fd, F_TEST, 1024), -1);
     TEST_COMPARE (errno, EACCES);
   }
 }
@@ -97,38 +107,38 @@ static int
 do_test (void)
 {
   /* Basic tests to check if a lock can be obtained and checked.  */
-  TEST_COMPARE (lockf (temp_fd, F_LOCK, 1024), 0);
-  TEST_COMPARE (lockf (temp_fd, F_LOCK, INT32_MAX), 0);
-  TEST_COMPARE (lockf (temp_fd, F_TLOCK, 1024), 0);
-  TEST_COMPARE (lockf (temp_fd, F_TEST, 1024), 0);
+  TEST_COMPARE (LOCKF (temp_fd, F_LOCK, 1024), 0);
+  TEST_COMPARE (LOCKF (temp_fd, F_LOCK, INT32_MAX), 0);
+  TEST_COMPARE (LOCKF (temp_fd, F_TLOCK, 1024), 0);
+  TEST_COMPARE (LOCKF (temp_fd, F_TEST, 1024), 0);
   TEST_COMPARE (lseek (temp_fd, 1024, SEEK_SET), 1024);
-  TEST_COMPARE (lockf (temp_fd, F_ULOCK, 1024), 0);
+  TEST_COMPARE (LOCKF (temp_fd, F_ULOCK, 1024), 0);
   /* Parent process should have ([0, 1024), [2048, INT32_MAX)) ranges locked.  */
 
   {
     struct support_capture_subprocess result;
     result = support_capture_subprocess (do_test_child_lockf, NULL);
-    support_capture_subprocess_check (&result, "lockf", 0, sc_allow_none);
+    support_capture_subprocess_check (&result, "LOCKF", 0, sc_allow_none);
   }
 
   if (sizeof (off_t) != sizeof (off64_t))
     {
       /* Check if previously locked regions with LFS symbol.  */
       TEST_COMPARE (lseek (temp_fd, 0, SEEK_SET), 0);
-      TEST_COMPARE (lockf64 (temp_fd, F_LOCK, 1024), 0);
-      TEST_COMPARE (lockf64 (temp_fd, F_TLOCK, 1024), 0);
-      TEST_COMPARE (lockf64 (temp_fd, F_TEST, 1024), 0);
+      TEST_COMPARE (LOCKF64 (temp_fd, F_LOCK, 1024), 0);
+      TEST_COMPARE (LOCKF64 (temp_fd, F_TLOCK, 1024), 0);
+      TEST_COMPARE (LOCKF64 (temp_fd, F_TEST, 1024), 0);
       /* Lock region [INT32_MAX+1024, INT64_MAX).  */
       off64_t off = (off64_t)INT32_MAX + 1024;
       TEST_COMPARE (lseek64 (temp_fd, off, SEEK_SET), off);
-      TEST_COMPARE (lockf64 (temp_fd, F_LOCK, 1024), 0);
+      TEST_COMPARE (LOCKF64 (temp_fd, F_LOCK, 1024), 0);
       /* Parent process should have ([0, 1024), [2048, INT32_MAX),
         [INT32_MAX+1024, INT64_MAX)) ranges locked.  */
 
       {
        struct support_capture_subprocess result;
        result = support_capture_subprocess (do_test_child_lockf64, NULL);
-       support_capture_subprocess_check (&result, "lockf", 0, sc_allow_none);
+       support_capture_subprocess_check (&result, "LOCKF", 0, sc_allow_none);
       }
     }
 
index cecea21c1c0e08aed3ddaefdfc2c6d2d30d3d683..e81924529e28578962566fa4492a9c8e9f2c2295 100644 (file)
@@ -55,7 +55,7 @@ _IO_wdo_write (FILE *fp, const wchar_t *data, size_t to_do)
          char mb_buf[MB_LEN_MAX];
          char *write_base, *write_ptr, *buf_end;
 
-         if (fp->_IO_write_ptr - fp->_IO_write_base < sizeof (mb_buf))
+         if (fp->_IO_buf_end - fp->_IO_write_ptr < sizeof (mb_buf))
            {
              /* Make sure we have room for at least one multibyte
                 character.  */
index fd8b52bfac00b1016669c91f0b56cbb4c4c419a1..67df9f8c5164541703e6fe9cab87c4740a7c51ff 100644 (file)
@@ -3398,16 +3398,23 @@ __libc_realloc (void *oldmem, size_t bytes)
   if (__glibc_unlikely (mtag_enabled))
     *(volatile char*) oldmem;
 
-  /* Return the chunk as is whenever possible, i.e. there's enough usable space
-     but not so much that we end up fragmenting the block.  We use the trim
-     threshold as the heuristic to decide the latter.  */
-  size_t usable = musable (oldmem);
-  if (bytes <= usable
-      && (unsigned long) (usable - bytes) <= mp_.trim_threshold)
-    return oldmem;
-
   /* chunk corresponding to oldmem */
   const mchunkptr oldp = mem2chunk (oldmem);
+
+  /* Return the chunk as is if the request grows within usable bytes, typically
+     into the alignment padding.  We want to avoid reusing the block for
+     shrinkages because it ends up unnecessarily fragmenting the address space.
+     This is also why the heuristic misses alignment padding for THP for
+     now.  */
+  size_t usable = musable (oldmem);
+  if (bytes <= usable)
+    {
+      size_t difference = usable - bytes;
+      if ((unsigned long) difference < 2 * sizeof (INTERNAL_SIZE_T)
+         || (chunk_is_mmapped (oldp) && difference <= GLRO (dl_pagesize)))
+       return oldmem;
+    }
+
   /* its size */
   const INTERNAL_SIZE_T oldsize = chunksize (oldp);
 
index 1a09f777fa37a6855b62e1063e3a78b0ea68d0d7..5db6f287194a3f2bda20e285ad7ab3766bd2a87a 100644 (file)
@@ -115,7 +115,10 @@ tests-special += $(objpfx)tst-error1-mem.out \
   $(objpfx)tst-allocate_once-mem.out
 endif
 
-tests-container := tst-syslog
+tests-container := \
+  tst-syslog \
+  tst-syslog-long-progname \
+  # tests-container
 
 CFLAGS-select.c += -fexceptions -fasynchronous-unwind-tables
 CFLAGS-tsearch.c += $(uses-callbacks)
@@ -177,6 +180,9 @@ $(objpfx)tst-allocate_once-mem.out: $(objpfx)tst-allocate_once.out
        $(common-objpfx)malloc/mtrace $(objpfx)tst-allocate_once.mtrace > $@; \
        $(evaluate-test)
 
+tst-syslog-long-progname-ENV = GLIBC_TUNABLES=glibc.malloc.check=3 \
+                              LD_PRELOAD=libc_malloc_debug.so.0
+
 $(objpfx)tst-select: $(librt)
 $(objpfx)tst-select-time64: $(librt)
 $(objpfx)tst-pselect: $(librt)
index 66d670212397c7185305ed38df5fbe6f08b2bec4..c37a3ff6373c3636779d1310a841d927f3b6baee 100644 (file)
 # define __glibc_objsize(__o) __bos (__o)
 #endif
 
+#if __USE_FORTIFY_LEVEL > 0
 /* Compile time conditions to choose between the regular, _chk and _chk_warn
    variants.  These conditions should get evaluated to constant and optimized
    away.  */
    ? __ ## f ## _alias (__VA_ARGS__)                                         \
    : (__glibc_unsafe_len (__l, __s, __osz)                                   \
       ? __ ## f ## _chk_warn (__VA_ARGS__, __osz)                            \
-      : __ ## f ## _chk (__VA_ARGS__, __osz)))                       \
+      : __ ## f ## _chk (__VA_ARGS__, __osz)))
 
 /* Fortify function f, where object size argument passed to f is the number of
    elements and not total size.  */
    ? __ ## f ## _alias (__VA_ARGS__)                                         \
    : (__glibc_unsafe_len (__l, __s, __osz)                                   \
       ? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s))                  \
-      : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s))))                     \
+      : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s))))
+#endif
 
 #if __GNUC_PREREQ (4,3)
 # define __warnattr(msg) __attribute__((__warning__ (msg)))
index f67d4b58a448cabdf63f629f72a9df6e009286cf..9336036666aada3d65b7fdca4e5b68b275e2f3b7 100644 (file)
@@ -41,6 +41,7 @@ static char sccsid[] = "@(#)syslog.c  8.4 (Berkeley) 3/18/94";
 #include <sys/uio.h>
 #include <sys/un.h>
 #include <syslog.h>
+#include <limits.h>
 
 static int LogType = SOCK_DGRAM;       /* type of socket connection */
 static int LogFile = -1;               /* fd for log */
@@ -122,8 +123,9 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
 {
   /* Try to use a static buffer as an optimization.  */
   char bufs[1024];
-  char *buf = NULL;
-  size_t bufsize = 0;
+  char *buf = bufs;
+  size_t bufsize;
+
   int msgoff;
   int saved_errno = errno;
 
@@ -175,29 +177,55 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
 #define SYSLOG_HEADER_WITHOUT_TS(__pri, __msgoff)        \
   "<%d>: %n", __pri, __msgoff
 
-  int l;
+  int l, vl;
   if (has_ts)
     l = __snprintf (bufs, sizeof bufs,
                    SYSLOG_HEADER (pri, timestamp, &msgoff, pid));
   else
     l = __snprintf (bufs, sizeof bufs,
                    SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
-  if (0 <= l && l < sizeof bufs)
+  if (l < 0)
+    goto out;
+
+  char *pos;
+  size_t len;
+
+  if (l < sizeof bufs)
     {
-      va_list apc;
-      va_copy (apc, ap);
+      /* At this point, there is still a chance that we can print the
+         remaining part of the log into bufs and use that.  */
+      pos = bufs + l;
+      len = sizeof (bufs) - l;
+    }
+  else
+    {
+      buf = NULL;
+      /* We already know that bufs is too small to use for this log message.
+         The next vsnprintf into bufs is used only to calculate the total
+         required buffer length.  We will discard bufs contents and allocate
+         an appropriately sized buffer later instead.  */
+      pos = bufs;
+      len = sizeof (bufs);
+    }
 
-      /* Restore errno for %m format.  */
-      __set_errno (saved_errno);
+  {
+    va_list apc;
+    va_copy (apc, ap);
 
-      int vl = __vsnprintf_internal (bufs + l, sizeof bufs - l, fmt, apc,
-                                     mode_flags);
-      if (0 <= vl && vl < sizeof bufs - l)
-        buf = bufs;
-      bufsize = l + vl;
+    /* Restore errno for %m format.  */
+    __set_errno (saved_errno);
 
-      va_end (apc);
-    }
+    vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags);
+    va_end (apc);
+
+    if (vl < 0 || vl >= INT_MAX - l)
+      goto out;
+
+    if (vl >= len)
+      buf = NULL;
+
+    bufsize = l + vl;
+  }
 
   if (buf == NULL)
     {
@@ -207,25 +235,37 @@ __vsyslog_internal (int pri, const char *fmt, va_list ap,
          /* Tell the cancellation handler to free this buffer.  */
          clarg.buf = buf;
 
+         int cl;
          if (has_ts)
-           __snprintf (buf, l + 1,
-                       SYSLOG_HEADER (pri, timestamp, &msgoff, pid));
+           cl = __snprintf (buf, l + 1,
+                            SYSLOG_HEADER (pri, timestamp, &msgoff, pid));
          else
-           __snprintf (buf, l + 1,
-                       SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
+           cl = __snprintf (buf, l + 1,
+                            SYSLOG_HEADER_WITHOUT_TS (pri, &msgoff));
+         if (cl != l)
+           goto out;
 
          va_list apc;
          va_copy (apc, ap);
-         __vsnprintf_internal (buf + l, bufsize - l + 1, fmt, apc,
-                               mode_flags);
+         cl = __vsnprintf_internal (buf + l, bufsize - l + 1, fmt, apc,
+                                    mode_flags);
          va_end (apc);
+
+         if (cl != vl)
+           goto out;
        }
       else
         {
+          int bl;
          /* Nothing much to do but emit an error message.  */
-          bufsize = __snprintf (bufs, sizeof bufs,
-                                "out of memory[%d]", __getpid ());
+          bl = __snprintf (bufs, sizeof bufs,
+                           "out of memory[%d]", __getpid ());
+          if (bl < 0 || bl >= sizeof bufs)
+            goto out;
+
+          bufsize = bl;
           buf = bufs;
+          msgoff = 0;
         }
     }
 
diff --git a/misc/tst-syslog-long-progname.c b/misc/tst-syslog-long-progname.c
new file mode 100644 (file)
index 0000000..88f37a8
--- /dev/null
@@ -0,0 +1,39 @@
+/* Test heap buffer overflow in syslog with long __progname (CVE-2023-6246)
+   Copyright (C) 2023 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 <syslog.h>
+#include <string.h>
+
+extern char * __progname;
+
+static int
+do_test (void)
+{
+  char long_progname[2048];
+
+  memset (long_progname, 'X', sizeof (long_progname) - 1);
+  long_progname[sizeof (long_progname) - 1] = '\0';
+
+  __progname = long_progname;
+
+  syslog (LOG_INFO, "Hello, World!");
+
+  return 0;
+}
+
+#include <support/test-driver.c>
index 3a9ea065acbd4793296f6f0522f2666e08cfd6b4..6ef5bf23b30cc66b3d539f5ae7dbb79c58c83f54 100644 (file)
@@ -81,6 +81,7 @@ tests-container := \
   tst-nss-test3 \
   tst-reload1 \
   tst-reload2 \
+  tst-nss-gai-hv2-canonname \
 # tests-container
 
 # Tests which need libdl
@@ -144,7 +145,17 @@ libnss_compat-inhibit-o    = $(filter-out .os,$(object-suffixes))
 ifeq ($(build-static-nss),yes)
 tests-static           += tst-nss-static
 endif
-extra-test-objs                += nss_test1.os nss_test2.os nss_test_errno.os
+extra-test-objs                += nss_test1.os nss_test2.os nss_test_errno.os \
+                          nss_test_gai_hv2_canonname.os
+
+ifeq ($(run-built-tests),yes)
+ifneq (no,$(PERL))
+tests-special += $(objpfx)mtrace-tst-nss-gai-hv2-canonname.out
+endif
+endif
+
+generated += mtrace-tst-nss-gai-hv2-canonname.out \
+               tst-nss-gai-hv2-canonname.mtrace
 
 include ../Rules
 
@@ -179,12 +190,16 @@ rtld-tests-LDFLAGS += -Wl,--dynamic-list=nss_test.ver
 libof-nss_test1 = extramodules
 libof-nss_test2 = extramodules
 libof-nss_test_errno = extramodules
+libof-nss_test_gai_hv2_canonname = extramodules
 $(objpfx)/libnss_test1.so: $(objpfx)nss_test1.os $(link-libc-deps)
        $(build-module)
 $(objpfx)/libnss_test2.so: $(objpfx)nss_test2.os $(link-libc-deps)
        $(build-module)
 $(objpfx)/libnss_test_errno.so: $(objpfx)nss_test_errno.os $(link-libc-deps)
        $(build-module)
+$(objpfx)/libnss_test_gai_hv2_canonname.so: \
+  $(objpfx)nss_test_gai_hv2_canonname.os $(link-libc-deps)
+       $(build-module)
 $(objpfx)nss_test2.os : nss_test1.c
 # Use the nss_files suffix for these objects as well.
 $(objpfx)/libnss_test1.so$(libnss_files.so-version): $(objpfx)/libnss_test1.so
@@ -194,10 +209,14 @@ $(objpfx)/libnss_test2.so$(libnss_files.so-version): $(objpfx)/libnss_test2.so
 $(objpfx)/libnss_test_errno.so$(libnss_files.so-version): \
   $(objpfx)/libnss_test_errno.so
        $(make-link)
+$(objpfx)/libnss_test_gai_hv2_canonname.so$(libnss_files.so-version): \
+  $(objpfx)/libnss_test_gai_hv2_canonname.so
+       $(make-link)
 $(patsubst %,$(objpfx)%.out,$(tests) $(tests-container)) : \
        $(objpfx)/libnss_test1.so$(libnss_files.so-version) \
        $(objpfx)/libnss_test2.so$(libnss_files.so-version) \
-       $(objpfx)/libnss_test_errno.so$(libnss_files.so-version)
+       $(objpfx)/libnss_test_errno.so$(libnss_files.so-version) \
+       $(objpfx)/libnss_test_gai_hv2_canonname.so$(libnss_files.so-version)
 
 ifeq (yes,$(have-thread-library))
 $(objpfx)tst-cancel-getpwuid_r: $(shared-thread-library)
@@ -206,6 +225,17 @@ endif
 $(objpfx)tst-nss-files-alias-leak.out: $(objpfx)/libnss_files.so
 $(objpfx)tst-nss-files-alias-truncated.out: $(objpfx)/libnss_files.so
 
+tst-nss-gai-hv2-canonname-ENV = \
+               MALLOC_TRACE=$(objpfx)tst-nss-gai-hv2-canonname.mtrace \
+               LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+$(objpfx)mtrace-tst-nss-gai-hv2-canonname.out: \
+  $(objpfx)tst-nss-gai-hv2-canonname.out
+       { test -r $(objpfx)tst-nss-gai-hv2-canonname.mtrace \
+       || ( echo "tst-nss-gai-hv2-canonname.mtrace does not exist"; exit 77; ) \
+       && $(common-objpfx)malloc/mtrace \
+       $(objpfx)tst-nss-gai-hv2-canonname.mtrace; } > $@; \
+       $(evaluate-test)
+
 # Disable DT_RUNPATH on NSS tests so that the glibc internal NSS
 # functions can load testing NSS modules via DT_RPATH.
 LDFLAGS-tst-nss-test1 = -Wl,--disable-new-dtags
@@ -214,3 +244,4 @@ LDFLAGS-tst-nss-test3 = -Wl,--disable-new-dtags
 LDFLAGS-tst-nss-test4 = -Wl,--disable-new-dtags
 LDFLAGS-tst-nss-test5 = -Wl,--disable-new-dtags
 LDFLAGS-tst-nss-test_errno = -Wl,--disable-new-dtags
+LDFLAGS-tst-nss-test_gai_hv2_canonname = -Wl,--disable-new-dtags
diff --git a/nss/nss_test_gai_hv2_canonname.c b/nss/nss_test_gai_hv2_canonname.c
new file mode 100644 (file)
index 0000000..4439c83
--- /dev/null
@@ -0,0 +1,56 @@
+/* NSS service provider that only provides gethostbyname2_r.
+   Copyright The GNU Toolchain Authors.
+   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 <nss.h>
+#include <stdlib.h>
+#include <string.h>
+#include "nss/tst-nss-gai-hv2-canonname.h"
+
+/* Catch misnamed and functions.  */
+#pragma GCC diagnostic error "-Wmissing-prototypes"
+NSS_DECLARE_MODULE_FUNCTIONS (test_gai_hv2_canonname)
+
+extern enum nss_status _nss_files_gethostbyname2_r (const char *, int,
+                                                   struct hostent *, char *,
+                                                   size_t, int *, int *);
+
+enum nss_status
+_nss_test_gai_hv2_canonname_gethostbyname2_r (const char *name, int af,
+                                             struct hostent *result,
+                                             char *buffer, size_t buflen,
+                                             int *errnop, int *herrnop)
+{
+  return _nss_files_gethostbyname2_r (name, af, result, buffer, buflen, errnop,
+                                     herrnop);
+}
+
+enum nss_status
+_nss_test_gai_hv2_canonname_getcanonname_r (const char *name, char *buffer,
+                                           size_t buflen, char **result,
+                                           int *errnop, int *h_errnop)
+{
+  /* We expect QUERYNAME, which is a small enough string that it shouldn't fail
+     the test.  */
+  if (memcmp (QUERYNAME, name, sizeof (QUERYNAME))
+      || buflen < sizeof (QUERYNAME))
+    abort ();
+
+  strncpy (buffer, name, buflen);
+  *result = buffer;
+  return NSS_STATUS_SUCCESS;
+}
diff --git a/nss/tst-nss-gai-hv2-canonname.c b/nss/tst-nss-gai-hv2-canonname.c
new file mode 100644 (file)
index 0000000..7db53cf
--- /dev/null
@@ -0,0 +1,66 @@
+/* Test NSS query path for plugins that only implement gethostbyname2
+   (#30843).
+   Copyright The GNU Toolchain Authors.
+   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 <nss.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mcheck.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#include "nss/tst-nss-gai-hv2-canonname.h"
+
+#define PREPARE do_prepare
+
+static void do_prepare (int a, char **av)
+{
+  FILE *hosts = xfopen ("/etc/hosts", "w");
+  for (unsigned i = 2; i < 255; i++)
+    {
+      fprintf (hosts, "ff01::ff02:ff03:%u:2\ttest.example.com\n", i);
+      fprintf (hosts, "192.168.0.%u\ttest.example.com\n", i);
+    }
+  xfclose (hosts);
+}
+
+static int
+do_test (void)
+{
+  mtrace ();
+
+  __nss_configure_lookup ("hosts", "test_gai_hv2_canonname");
+
+  struct addrinfo hints = {};
+  struct addrinfo *result = NULL;
+
+  hints.ai_family = AF_INET6;
+  hints.ai_flags = AI_ALL | AI_V4MAPPED | AI_CANONNAME;
+
+  int ret = getaddrinfo (QUERYNAME, NULL, &hints, &result);
+
+  if (ret != 0)
+    FAIL_EXIT1 ("getaddrinfo failed: %s\n", gai_strerror (ret));
+
+  TEST_COMPARE_STRING (result->ai_canonname, QUERYNAME);
+
+  freeaddrinfo(result);
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/nss/tst-nss-gai-hv2-canonname.h b/nss/tst-nss-gai-hv2-canonname.h
new file mode 100644 (file)
index 0000000..14f2a9c
--- /dev/null
@@ -0,0 +1 @@
+#define QUERYNAME "test.example.com"
diff --git a/nss/tst-nss-gai-hv2-canonname.root/tst-nss-gai-hv2-canonname.script b/nss/tst-nss-gai-hv2-canonname.root/tst-nss-gai-hv2-canonname.script
new file mode 100644 (file)
index 0000000..31848b4
--- /dev/null
@@ -0,0 +1,2 @@
+cp $B/nss/libnss_test_gai_hv2_canonname.so $L/libnss_test_gai_hv2_canonname.so.2
+su
index cc69b4e60b876555323f312b114bd3b3cc9aa673..60f5d468976e4d16adedf71ad274d0b666d29af5 100644 (file)
@@ -101,6 +101,7 @@ tests += \
   tst-resolv-invalid-cname \
   tst-resolv-network \
   tst-resolv-noaaaa \
+  tst-resolv-noaaaa-vc \
   tst-resolv-nondecimal \
   tst-resolv-res_init-multi \
   tst-resolv-search \
@@ -292,6 +293,7 @@ $(objpfx)tst-resolv-res_init-thread: $(objpfx)libresolv.so \
 $(objpfx)tst-resolv-invalid-cname: $(objpfx)libresolv.so \
   $(shared-thread-library)
 $(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-noaaaa-vc: $(objpfx)libresolv.so $(shared-thread-library)
 $(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library)
 $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
 $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library)
index ae1f8669d50f26dab78e2badef076b3c0bd152ed..e6aaef98d1793ffb60b8530ad86b76a1387110d6 100644 (file)
@@ -427,7 +427,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
     {
       n = __res_context_search (ctx, name, C_IN, T_A,
                                dns_packet_buffer, sizeof (dns_packet_buffer),
-                               NULL, NULL, NULL, NULL, NULL);
+                               &alt_dns_packet_buffer, NULL, NULL, NULL, NULL);
       if (n >= 0)
        status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n,
                                        &abuf, pat, errnop, herrnop, ttlp);
diff --git a/resolv/tst-resolv-noaaaa-vc.c b/resolv/tst-resolv-noaaaa-vc.c
new file mode 100644 (file)
index 0000000..9f5aebd
--- /dev/null
@@ -0,0 +1,129 @@
+/* Test the RES_NOAAAA resolver option with a large response.
+   Copyright (C) 2022-2023 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 <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+/* Used to keep track of the number of queries.  */
+static volatile unsigned int queries;
+
+/* If true, add a large TXT record at the start of the answer section.  */
+static volatile bool stuff_txt;
+
+static void
+response (const struct resolv_response_context *ctx,
+          struct resolv_response_builder *b,
+          const char *qname, uint16_t qclass, uint16_t qtype)
+{
+  /* If not using TCP, just force its use.  */
+  if (!ctx->tcp)
+    {
+      struct resolv_response_flags flags = {.tc = true};
+      resolv_response_init (b, flags);
+      resolv_response_add_question (b, qname, qclass, qtype);
+      return;
+    }
+
+  /* The test needs to send four queries, the first three are used to
+     grow the NSS buffer via the ERANGE handshake.  */
+  ++queries;
+  TEST_VERIFY (queries <= 4);
+
+  /* AAAA queries are supposed to be disabled.  */
+  TEST_COMPARE (qtype, T_A);
+  TEST_COMPARE (qclass, C_IN);
+  TEST_COMPARE_STRING (qname, "example.com");
+
+  struct resolv_response_flags flags = {};
+  resolv_response_init (b, flags);
+  resolv_response_add_question (b, qname, qclass, qtype);
+
+  resolv_response_section (b, ns_s_an);
+
+  if (stuff_txt)
+    {
+      resolv_response_open_record (b, qname, qclass, T_TXT, 60);
+      int zero = 0;
+      for (int i = 0; i <= 15000; ++i)
+        resolv_response_add_data (b, &zero, sizeof (zero));
+      resolv_response_close_record (b);
+    }
+
+  for (int i = 0; i < 200; ++i)
+    {
+      resolv_response_open_record (b, qname, qclass, qtype, 60);
+      char ipv4[4] = {192, 0, 2, i + 1};
+      resolv_response_add_data (b, &ipv4, sizeof (ipv4));
+      resolv_response_close_record (b);
+    }
+}
+
+static int
+do_test (void)
+{
+  struct resolv_test *obj = resolv_test_start
+    ((struct resolv_redirect_config)
+     {
+       .response_callback = response
+     });
+
+  _res.options |= RES_NOAAAA;
+
+  for (int do_stuff_txt = 0; do_stuff_txt < 2; ++do_stuff_txt)
+    {
+      queries = 0;
+      stuff_txt = do_stuff_txt;
+
+      struct addrinfo *ai = NULL;
+      int ret;
+      ret = getaddrinfo ("example.com", "80",
+                         &(struct addrinfo)
+                         {
+                           .ai_family = AF_UNSPEC,
+                           .ai_socktype = SOCK_STREAM,
+                         }, &ai);
+
+      char *expected_result;
+      {
+        struct xmemstream mem;
+        xopen_memstream (&mem);
+        for (int i = 0; i < 200; ++i)
+          fprintf (mem.out, "address: STREAM/TCP 192.0.2.%d 80\n", i + 1);
+        xfclose_memstream (&mem);
+        expected_result = mem.buffer;
+      }
+
+      check_addrinfo ("example.com", ai, ret, expected_result);
+
+      free (expected_result);
+      freeaddrinfo (ai);
+    }
+
+  resolv_test_end (obj);
+  return 0;
+}
+
+#include <support/test-driver.c>
index 34fdd6d1f890c2825d693ad593e84b6b35363d69..fdc49f32ea16d81e27ab3c974ca5d4c4bd371a3d 100644 (file)
@@ -196,6 +196,7 @@ tests := \
   tst-gets \
   tst-grouping \
   tst-grouping2 \
+  tst-grouping3 \
   tst-long-dbl-fphex \
   tst-memstream-string \
   tst-obprintf \
@@ -340,6 +341,7 @@ $(objpfx)tst-sscanf.out: $(gen-locales)
 $(objpfx)tst-swprintf.out: $(gen-locales)
 $(objpfx)tst-vfprintf-mbs-prec.out: $(gen-locales)
 $(objpfx)tst-vfprintf-width-i18n.out: $(gen-locales)
+$(objpfx)tst-grouping3.out: $(gen-locales)
 endif
 
 tst-printf-bz18872-ENV = MALLOC_TRACE=$(objpfx)tst-printf-bz18872.mtrace \
@@ -431,7 +433,7 @@ CFLAGS-tst-gets.c += -Wno-deprecated-declarations
 
 # BZ #11319 was first fixed for regular vdprintf, then reopened because
 # the fortified version had the same bug.
-CFLAGS-tst-bz11319-fortify2.c += -D_FORTIFY_SOURCE=2
+CFLAGS-tst-bz11319-fortify2.c += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2
 
 CFLAGS-tst-memstream-string.c += -fno-builtin-fprintf
 
diff --git a/stdio-common/tst-grouping3.c b/stdio-common/tst-grouping3.c
new file mode 100644 (file)
index 0000000..e9e3921
--- /dev/null
@@ -0,0 +1,54 @@
+/* Test printf with grouping and padding (bug 30068)
+   Copyright (C) 2023 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 <locale.h>
+#include <stdio.h>
+#include <support/check.h>
+#include <support/support.h>
+
+static int
+do_test (void)
+{
+  char buf[80];
+
+  xsetlocale (LC_NUMERIC, "de_DE.UTF-8");
+
+  /* The format string has the following conversion specifier:
+     '  - Use thousands grouping.
+     +  - The result of a signed conversion shall begin with a sign.
+     -  - Left justified.
+     13 - Minimum 13 bytes of width.
+     9  - Minimum 9 digits of precision.
+
+     In bug 30068 the grouping characters were not accounted for in
+     the width, and were added after the fact resulting in a 15-byte
+     output instead of a 13-byte output.  The two additional bytes
+     come from the locale-specific thousands separator.  This increase
+     in size could result in a buffer overflow if a reasonable caller
+     calculated the size of the expected buffer using nl_langinfo to
+     determine the sie of THOUSEP in bytes.
+
+     This bug is distinct from bug 23432 which has to do with the
+     minimum precision calculation (digit based).  */
+  sprintf (buf, "%+-'13.9d", 1234567);
+  TEST_COMPARE_STRING (buf, "+001.234.567 ");
+
+  return 0;
+}
+
+#include <support/test-driver.c>
index 24c9125f9fa930602953ad9569244d6e282e4d9d..8c0fcbcf785a947527b376d41b8cf1dc4e9ee029 100644 (file)
@@ -186,11 +186,17 @@ LABEL (unsigned_number):      /* Unsigned number of base BASE.  */
   bool octal_marker = (prec <= number_length && number.word != 0
                        && alt && base == 8);
 
-  prec = MAX (0, prec - (workend - string));
+  /* At this point prec_inc is the additional bytes required for the
+     specificed precision.  It is 0 if the precision would not have
+     required additional bytes i.e. the number of input digits is more
+     than the precision.  It is greater than zero if the precision is
+     more than the number of digits without grouping (precision only
+     considers digits).  */
+  unsigned int prec_inc = MAX (0, prec - (workend - string));
 
   if (!left)
     {
-      width -= number_length + prec;
+      width -= number_length + prec_inc;
 
       if (number.word != 0 && alt && (base == 16 || base == 2))
         /* Account for 0X, 0x, 0B or 0b hex or binary marker.  */
@@ -221,7 +227,7 @@ LABEL (unsigned_number):      /* Unsigned number of base BASE.  */
           Xprintf_buffer_putc (buf, spec);
         }
 
-      width += prec;
+      width += prec_inc;
       Xprintf_buffer_pad (buf, L_('0'), width);
 
       if (octal_marker)
@@ -237,6 +243,8 @@ LABEL (unsigned_number):      /* Unsigned number of base BASE.  */
     }
   else
     {
+      /* Perform left justification adjustments.  */
+
       if (is_negative)
         {
           Xprintf_buffer_putc (buf, L_('-'));
@@ -263,9 +271,13 @@ LABEL (unsigned_number):      /* Unsigned number of base BASE.  */
       if (octal_marker)
        --width;
 
-      width -= workend - string + prec;
+      /* Adjust the width by subtracting the number of bytes
+         required to represent the number with grouping characters
+        (NUMBER_LENGTH) and any additional bytes required for
+        precision.  */
+      width -= number_length + prec_inc;
 
-      Xprintf_buffer_pad (buf, L_('0'), prec);
+      Xprintf_buffer_pad (buf, L_('0'), prec_inc);
 
       if (octal_marker)
         Xprintf_buffer_putc (buf, L_('0'));
index e0fc82fc4d1530243360abd5408c34d9068933dd..005eede5d94b2205d3cd9faaee5ca4c0df9c87c8 100644 (file)
@@ -171,6 +171,7 @@ tests := \
   test-a64l \
   test-at_quick_exit-race \
   test-atexit-race \
+  test-atexit-recursive \
   test-bz22786 \
   test-canon \
   test-canon2 \
index 6b1eed644560bf4b45399fa60e1fb7c0dcde6615..1cd0bdfe948cd1a8d5f9ede23a84ba0d9b78632c 100644 (file)
@@ -51,7 +51,10 @@ __run_exit_handlers (int status, struct exit_function_list **listp,
      exit (). */
   while (true)
     {
-      struct exit_function_list *cur = *listp;
+      struct exit_function_list *cur;
+
+    restart:
+      cur = *listp;
 
       if (cur == NULL)
        {
@@ -113,7 +116,7 @@ __run_exit_handlers (int status, struct exit_function_list **listp,
          if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
            /* The last exit function, or another thread, has registered
               more exit functions.  Start the loop over.  */
-            continue;
+           goto restart;
        }
 
       *listp = cur->next;
diff --git a/stdlib/test-atexit-recursive.c b/stdlib/test-atexit-recursive.c
new file mode 100644 (file)
index 0000000..0596b97
--- /dev/null
@@ -0,0 +1,75 @@
+/* Support file for atexit/exit, etc. race tests (BZ #27749).
+   Copyright (C) 2023 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/>.  */
+
+/* Check that atexit handler registed from another handler still called. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/xunistd.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+static void
+atexit_cb (void)
+{
+}
+
+static void
+atexit_last (void)
+{
+  _exit (1);
+}
+
+static void
+atexit_recursive (void)
+{
+  atexit (&atexit_cb);
+  atexit (&atexit_last);
+}
+
+_Noreturn static void
+test_and_exit (int count)
+{
+  for (int i = 0; i < count; ++i)
+    atexit (&atexit_cb);
+  atexit (&atexit_recursive);
+  exit (0);
+}
+
+static int
+do_test (void)
+{
+  for (int i = 0; i < 100; ++i)
+    if (xfork () == 0)
+      test_and_exit (i);
+
+  for (int i = 0; i < 100; ++i)
+    {
+      int status;
+      xwaitpid (0, &status, 0);
+      if (!WIFEXITED (status))
+       FAIL_EXIT1 ("Failed iterations %d", i);
+      TEST_COMPARE (WEXITSTATUS (status), 1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test
+#include <support/test-driver.c>
index 634acfe264136c72ecc2b6cf1d064295834940a8..47a0afe6bf2b118bf52c535f68d8eecc814e0ae5 100644 (file)
@@ -25,6 +25,7 @@
 #include <support/check.h>
 #include <support/temp_file.h>
 #include <support/support.h>
+#include <support/xthread.h>
 #include <support/xunistd.h>
 
 static char *tmpdir;
@@ -71,6 +72,20 @@ call_system (void *closure)
     }
 }
 
+static void *
+sleep_and_check_sigchld (void *closure)
+{
+  double *seconds = (double *) closure;
+  char cmd[namemax];
+  sprintf (cmd, "sleep %lf" , *seconds);
+  TEST_COMPARE (system (cmd), 0);
+
+  sigset_t blocked = {0};
+  TEST_COMPARE (sigprocmask (SIG_BLOCK, NULL, &blocked), 0);
+  TEST_COMPARE (sigismember (&blocked, SIGCHLD), 0);
+  return NULL;
+}
+
 static int
 do_test (void)
 {
@@ -154,6 +169,17 @@ do_test (void)
     xchmod (_PATH_BSHELL, st.st_mode);
   }
 
+  {
+    pthread_t long_sleep_thread = xpthread_create (NULL,
+                                                   sleep_and_check_sigchld,
+                                                   &(double) { 0.2 });
+    pthread_t short_sleep_thread = xpthread_create (NULL,
+                                                    sleep_and_check_sigchld,
+                                                    &(double) { 0.1 });
+    xpthread_join (short_sleep_thread);
+    xpthread_join (long_sleep_thread);
+  }
+
   TEST_COMPARE (system (""), 0);
 
   return 0;
index dd2cb1b441cc6c344a458e242e2a2a1dbc97c07e..6641d256253889a8699b41aecf50dc69be1f8697 100644 (file)
@@ -52,10 +52,14 @@ user2netname (char netname[MAXNETNAMELEN + 1], const uid_t uid,
   /* GCC with -Os or -O1 warns that sprint might overflow while handling
      dfltdom, however the above test does check if an overflow would
      happen.  */
+#if __GNUC_PREREQ (8, 0)
   DIAG_PUSH_NEEDS_COMMENT;
   DIAG_IGNORE_NEEDS_COMMENT (8, "-Wformat-overflow");
+#endif
   sprintf (netname, "%s.%d@%s", OPSYS, uid, dfltdom);
+#if __GNUC_PREREQ (8, 0)
   DIAG_POP_NEEDS_COMMENT;
+#endif
   i = strlen (netname);
   if (netname[i - 1] == '.')
     netname[i - 1] = '\0';
index b29b7eb50578de1f93557fc6ad29471b54053586..48cd74581d548b8a0fefdbf445c8c9f3fbdcb8d7 100644 (file)
@@ -32,6 +32,8 @@ libsupport-routines = \
   check_hostent \
   check_netent \
   delayed_exit \
+  dtotimespec \
+  dtotimespec-time64 \
   ignore_stderr \
   next_to_fault \
   oom_error \
diff --git a/support/dtotimespec-time64.c b/support/dtotimespec-time64.c
new file mode 100644 (file)
index 0000000..b3d5e35
--- /dev/null
@@ -0,0 +1,27 @@
+/* Convert double to timespec.  64-bit time support.
+   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library and is also part of gnulib.
+   Patches to this file should be submitted to both projects.
+
+   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 <time.h>
+
+#if __TIMESIZE != 64
+# define timespec      __timespec64
+# define time_t        __time64_t
+# define dtotimespec   dtotimespec_time64
+# include "dtotimespec.c"
+#endif
diff --git a/support/dtotimespec.c b/support/dtotimespec.c
new file mode 100644 (file)
index 0000000..cde5b4d
--- /dev/null
@@ -0,0 +1,50 @@
+/* Convert double to timespec.
+   Copyright (C) 2011-2023 Free Software Foundation, Inc.
+   This file is part of the GNU C Library and is also part of gnulib.
+   Patches to this file should be submitted to both projects.
+
+   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/>.  */
+
+/* Convert the double value SEC to a struct timespec.  Round toward
+   positive infinity.  On overflow, return an extremal value.  */
+
+#include <support/timespec.h>
+#include <intprops.h>
+
+struct timespec
+dtotimespec (double sec)
+{
+  if (sec <= TYPE_MINIMUM (time_t))
+    return make_timespec (TYPE_MINIMUM (time_t), 0);
+  else if (sec >= 1.0 + TYPE_MAXIMUM (time_t))
+    return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_HZ - 1);
+  else
+    {
+      time_t s = sec;
+      double frac = TIMESPEC_HZ * (sec - s);
+      long ns = frac;
+      ns += ns < frac;
+      s += ns / TIMESPEC_HZ;
+      ns %= TIMESPEC_HZ;
+
+      if (ns < 0)
+        {
+          s--;
+          ns += TIMESPEC_HZ;
+        }
+
+      return make_timespec (s, ns);
+    }
+}
index e9ac9b6d041b7a6e86376fce1c90d73c83fe9f65..66cf0c8b1f9274e36012e0ef2933a01316a5b745 100644 (file)
@@ -39,6 +39,7 @@
 #include <error.h>
 
 #include <support/support.h>
+#include <support/timespec.h>
 
 /* Design considerations
 
@@ -171,6 +172,32 @@ kill_func (char **argv)
   return 0;
 }
 
+/* Emulate the "/bin/sleep" command.  No suffix support.  Options are
+   ignored.  */
+static int
+sleep_func (char **argv)
+{
+  if (argv[0] == NULL)
+    {
+      fprintf (stderr, "sleep: missing operand\n");
+      return 1;
+    }
+  char *endptr = NULL;
+  double sec = strtod (argv[0], &endptr);
+  if (endptr == argv[0] || errno == ERANGE || sec < 0)
+    {
+      fprintf (stderr, "sleep: invalid time interval '%s'\n", argv[0]);
+      return 1;
+    }
+  struct timespec ts = dtotimespec (sec);
+  if (nanosleep (&ts, NULL) < 0)
+    {
+      fprintf (stderr, "sleep: failed to nanosleep: %s\n", strerror (errno));
+      return 1;
+    }
+  return 0;
+}
+
 /* This is a list of all the built-in commands we understand.  */
 static struct {
   const char *name;
@@ -181,6 +208,7 @@ static struct {
   { "cp", copy_func },
   { "exit", exit_func },
   { "kill", kill_func },
+  { "sleep", sleep_func },
   { NULL, NULL }
 };
 
index 77b1e4e8d676d466dda1dddcc99d707ea3ac35b6..9559836d4c7f7c3dc661c53b5218357c30c4a160 100644 (file)
@@ -57,6 +57,8 @@ int support_timespec_check_in_range (struct timespec expected,
                                     struct timespec observed,
                                     double lower_bound, double upper_bound);
 
+struct timespec dtotimespec (double sec) __attribute__((const));
+
 #else
 struct timespec __REDIRECT (timespec_add, (struct timespec, struct timespec),
                            timespec_add_time64);
@@ -82,6 +84,8 @@ int __REDIRECT (support_timespec_check_in_range, (struct timespec expected,
                                                  double lower_bound,
                                                  double upper_bound),
                support_timespec_check_in_range_time64);
+
+struct timespec __REDIRECT (dtotimespec, (double sec), dtotimespec_time64);
 #endif
 
 /* Check that the timespec on the left represents a time before the
index cc5e9d619b309b234bab570f94486d5be3ae0006..e4f6358f883ee2dd9b6d2f504dd069c4edba1c7e 100644 (file)
@@ -27,5 +27,5 @@
 #define DL_FIXUP_VALUE_ADDR(value) (value)
 #define DL_FIXUP_ADDR_VALUE(addr) (addr)
 #define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
-#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
+#define DL_FIXUP_BINDNOW_RELOC(l, reloc, value, new_value, st_value, lazy) \
   (*value) = st_value;
index 0e1a9a9515ddcb922bd1d2b1447d0a747a4649d5..e9e9e19d0f6faf04dd42138684d26d272883d217 100644 (file)
@@ -90,8 +90,6 @@ extern int process_file (const char *real_file_name, const char *file_name,
                         const char *lib, int *flag, unsigned int *isa_level,
                         char **soname, int is_link, struct stat *stat_buf);
 
-extern char *implicit_soname (const char *lib, int flag);
-
 /* Declared in readelflib.c.  */
 extern int process_elf_file (const char *file_name, const char *lib,
                             int *flag, unsigned int *isa_level, char **soname,
index c99dad77ccb90d38a9aef00fb406e21556a06059..877c60ba892af3dd8100d3808b82f12cf0f2d0bd 100644 (file)
@@ -1377,8 +1377,8 @@ void _dl_audit_preinit (struct link_map *l);
    the flags with LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT prior calling
    la_symbind{32,64}.  */
 void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
-                       const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
-                       lookup_t result)
+                       const void *reloc, const ElfW(Sym) *defsym,
+                       DL_FIXUP_VALUE_TYPE *value, lookup_t result, bool lazy)
   attribute_hidden;
 /* Same as _dl_audit_symbind, but also sets LA_SYMB_DLSYM flag.  */
 void _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref,
index 66b3ff97633c316364a6a7e4eb674b1f3ab42ed2..28daf3f89b85fb83f3b271e213e2e6bf870196a9 100644 (file)
@@ -84,5 +84,5 @@ void attribute_hidden _dl_unmap (struct link_map *map);
 #define DL_FIXUP_ADDR_VALUE(addr) \
   (*(DL_FIXUP_VALUE_TYPE *) ((uintptr_t) (addr) & ~2))
 #define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
-#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value)     \
+#define DL_FIXUP_BINDNOW_RELOC(l, reloc, value, new_value, st_value, lazy) \
   *(value) = *(DL_FIXUP_VALUE_TYPE *) ((uintptr_t) (new_value) & ~2)
index 8705a7822c62428103f9e56b818b8234a1ba2742..6f50cec7619dd6ec025bbbfc095696ceebae0274 100644 (file)
@@ -1617,7 +1617,7 @@ ldouble: 5
 
 Function: "y0_towardzero":
 double: 4
-float: 8
+float: 9
 float128: 3
 ldouble: 8
 
index 0e47e529fe16818bcb1c2f466e9d546c666f5a6c..64218fa7bbb8c7187f2023aa1a67c79a2945efeb 100644 (file)
@@ -75,5 +75,5 @@ extern void attribute_hidden _dl_unmap (struct link_map *map);
 #define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value))
 #define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr))
 #define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
-#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
+#define DL_FIXUP_BINDNOW_RELOC(l, reloc, value, new_value, st_value, lazy) \
   (*value) = *(struct fdesc *) (st_value)
index fd22dc4fcbc1dcd773f94e8b3202c10ab3be99fb..8607486798fea26783d8abc3a4f2ea4a6983f74e 100644 (file)
@@ -120,6 +120,7 @@ struct gaih_result
 {
   struct gaih_addrtuple *at;
   char *canon;
+  char *h_name;
   bool free_at;
   bool got_ipv6;
 };
@@ -165,6 +166,7 @@ gaih_result_reset (struct gaih_result *res)
   if (res->free_at)
     free (res->at);
   free (res->canon);
+  free (res->h_name);
   memset (res, 0, sizeof (*res));
 }
 
@@ -203,9 +205,8 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
   return 0;
 }
 
-/* Convert struct hostent to a list of struct gaih_addrtuple objects.  h_name
-   is not copied, and the struct hostent object must not be deallocated
-   prematurely.  The new addresses are appended to the tuple array in RES.  */
+/* Convert struct hostent to a list of struct gaih_addrtuple objects.  The new
+   addresses are appended to the tuple array in RES.  */
 static bool
 convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family,
                                   struct hostent *h, struct gaih_result *res)
@@ -238,6 +239,15 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family,
   res->at = array;
   res->free_at = true;
 
+  /* Duplicate h_name because it may get reclaimed when the underlying storage
+     is freed.  */
+  if (res->h_name == NULL)
+    {
+      res->h_name = __strdup (h->h_name);
+      if (res->h_name == NULL)
+       return false;
+    }
+
   /* Update the next pointers on reallocation.  */
   for (size_t i = 0; i < old; i++)
     array[i].next = array + i + 1;
@@ -262,7 +272,6 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, int family,
        }
       array[i].next = array + i + 1;
     }
-  array[0].name = h->h_name;
   array[count - 1].next = NULL;
 
   return true;
@@ -324,15 +333,15 @@ gethosts (nss_gethostbyname3_r fct, int family, const char *name,
    memory allocation failure.  The returned string is allocated on the
    heap; the caller has to free it.  */
 static char *
-getcanonname (nss_action_list nip, struct gaih_addrtuple *at, const char *name)
+getcanonname (nss_action_list nip, const char *hname, const char *name)
 {
   nss_getcanonname_r *cfct = __nss_lookup_function (nip, "getcanonname_r");
   char *s = (char *) name;
   if (cfct != NULL)
     {
       char buf[256];
-      if (DL_CALL_FCT (cfct, (at->name ?: name, buf, sizeof (buf),
-                             &s, &errno, &h_errno)) != NSS_STATUS_SUCCESS)
+      if (DL_CALL_FCT (cfct, (hname ?: name, buf, sizeof (buf), &s, &errno,
+                             &h_errno)) != NSS_STATUS_SUCCESS)
        /* If the canonical name cannot be determined, use the passed
           string.  */
        s = (char *) name;
@@ -607,7 +616,14 @@ get_nss_addresses (const char *name, const struct addrinfo *req,
      function variant.  */
   res_ctx = __resolv_context_get ();
   if (res_ctx == NULL)
-    no_more = 1;
+    {
+      if (errno == ENOMEM)
+       {
+         result = -EAI_MEMORY;
+         goto out;
+       }
+      no_more = 1;
+    }
 
   while (!no_more)
     {
@@ -771,7 +787,7 @@ get_nss_addresses (const char *name, const struct addrinfo *req,
                  if ((req->ai_flags & AI_CANONNAME) != 0
                      && res->canon == NULL)
                    {
-                     char *canonbuf = getcanonname (nip, res->at, name);
+                     char *canonbuf = getcanonname (nip, res->h_name, name);
                      if (canonbuf == NULL)
                        {
                          __resolv_context_put (res_ctx);
@@ -1187,9 +1203,7 @@ free_and_return:
   if (malloc_name)
     free ((char *) name);
   free (addrmem);
-  if (res.free_at)
-    free (res.at);
-  free (res.canon);
+  gaih_result_reset (&res);
 
   return result;
 }
index 2335a99184a2fc2f0d2975a145cf4dfd7dcfda2d..d77720a625e0d42a5cdca13961aae9db9c95ea78 100644 (file)
@@ -179,16 +179,16 @@ do_system (const char *line)
       as if the shell had terminated using _exit(127).  */
    status = W_EXITCODE (127, 0);
 
+  /* sigaction can not fail with SIGINT/SIGQUIT used with old
+     disposition.  Same applies for sigprocmask.  */
   DO_LOCK ();
   if (SUB_REF () == 0)
     {
-      /* sigaction can not fail with SIGINT/SIGQUIT used with old
-        disposition.  Same applies for sigprocmask.  */
       __sigaction (SIGINT, &intr, NULL);
       __sigaction (SIGQUIT, &quit, NULL);
-      __sigprocmask (SIG_SETMASK, &omask, NULL);
     }
   DO_UNLOCK ();
+  __sigprocmask (SIG_SETMASK, &omask, NULL);
 
   if (ret != 0)
     __set_errno (ret);
index db0869bd33fab9f56ab25939497697d1b3b77b1b..0d6dcb8e2549345da027c46705373935ad522457 100644 (file)
@@ -25,7 +25,7 @@
 /* We need to correctly set the audit modules value for bind-now.  */
 # define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) \
  (((Elf64_FuncDesc *)(addr))->fd_func)
-# define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value)    \
+# define DL_FIXUP_BINDNOW_RELOC(l, reloc, value, new_value, st_value, lazy) \
  ({                                                            \
     Elf64_FuncDesc *opd = (Elf64_FuncDesc *) (value);          \
     opd->fd_func = (st_value);                                 \
@@ -34,6 +34,6 @@
   })
 #else
 # define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
-# define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value)    \
+# define DL_FIXUP_BINDNOW_RELOC(l, reloc, value, new_value, st_value, lazy) \
   (*value) = st_value;
 #endif
index 6eb4eb5b42bb8922c5a1322248ec45e998bbeec4..ff803386be43ded13ab3c65c47e7cca6649c6029 100644 (file)
@@ -46,9 +46,7 @@ tf (void *arg)
 
   /* Wait indefinitely for cancellation, which only works if asynchronous
      cancellation is enabled.  */
-#ifdef SYS_pause
-  syscall (SYS_pause);
-#elif defined SYS_ppoll || defined SYS_ppoll_time64
+#if defined SYS_ppoll || defined SYS_ppoll_time64
 # ifndef SYS_ppoll_time64
 #  define SYS_ppoll_time64 SYS_ppoll
 # endif
diff --git a/sysdeps/sparc/dl-lookupcfg.h b/sysdeps/sparc/dl-lookupcfg.h
new file mode 100644 (file)
index 0000000..3a5a5c1
--- /dev/null
@@ -0,0 +1,49 @@
+/* Configuration of lookup functions.  SPARC64 version.
+   Copyright (C) 2023 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/>.  */
+
+/* The type of the return value of fixup/profile_fixup.  */
+#define DL_FIXUP_VALUE_TYPE ElfW(Addr)
+/* Construct a value of type DL_FIXUP_VALUE_TYPE from a code address
+   and a link map.  */
+#define DL_FIXUP_MAKE_VALUE(map, addr) (addr)
+/* Extract the code address from a value of type DL_FIXUP_MAKE_VALUE.
+ */
+#define DL_FIXUP_VALUE_CODE_ADDR(value) (value)
+#define DL_FIXUP_VALUE_ADDR(value) (value)
+#define DL_FIXUP_ADDR_VALUE(addr) (addr)
+#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
+/* For bindnow, _dl_audit_symbind will be responsible to setup the final value
+   while for lazy binding _dl_fixup/_dl_profile_fixup will call the audit
+   callbacks and tail cail elf_machine_fixup_plt.  */
+#ifdef __arch64__
+# define DL_SPARC_FIXUP(l, r, value, new_value)                              \
+  sparc64_fixup_plt (l, r, value, new_value, (r)->r_addend, 0)
+#else
+# define DL_SPARC_FIXUP(l, r, value, new_value)                              \
+  sparc_fixup_plt (r, value, new_value, 0, 1)
+#endif
+#define DL_FIXUP_BINDNOW_RELOC(l, reloc, value, new_value, st_value, lazy)   \
+  ({                                                                         \
+     if (lazy)                                                               \
+       (*value) = st_value;                                                  \
+     else                                                                    \
+       {                                                                     \
+         const PLTREL *__r = (reloc);                                        \
+         DL_SPARC_FIXUP (l, __r, value, new_value);                          \
+       }                                                                     \
+  })
index f298878e8f87ddad8ee6f980a88d4f8b2b32a62b..94747b37a6a49b1525df01c70b1f28611c5b1a67 100644 (file)
@@ -456,6 +456,8 @@ sysdep_headers += netinet/if_fddi.h netinet/if_tr.h \
                  netrom/netrom.h netpacket/packet.h netrose/rose.h \
                  neteconet/ec.h netiucv/iucv.h
 sysdep_routines += netlink_assert_response
+
+CFLAGS-check_pf.c += -fexceptions
 endif
 
 # Don't compile the ctype glue code, since there is no old non-GNU C library.
index ca6a0d75168d28a5b1aed10ea7d0619cb708bef8..1babbdc84efd377450bca15c8e040e7ab9260f69 100644 (file)
 #endif
 
 #ifndef F_GETLK
-# ifndef __USE_FILE_OFFSET64
+# if !defined __USE_FILE_OFFSET64 && __TIMESIZE != 64
 #  define F_GETLK      5       /* Get record locking info.  */
 #  define F_SETLK      6       /* Set record locking info (non-blocking).  */
 #  define F_SETLKW     7       /* Set record locking info (blocking).  */
index de207122b07b485ab8e5a378576ce9527d936e49..50654cb28def15ecf48fce1b36dc8475b911a6cc 100644 (file)
@@ -292,6 +292,14 @@ make_request (int fd, pid_t pid)
   return NULL;
 }
 
+#ifdef __EXCEPTIONS
+static void
+cancel_handler (void *arg __attribute__((unused)))
+{
+  /* Release the lock.  */
+  __libc_lock_unlock (lock);
+}
+#endif
 
 void
 attribute_hidden
@@ -304,6 +312,10 @@ __check_pf (bool *seen_ipv4, bool *seen_ipv6,
   struct cached_data *olddata = NULL;
   struct cached_data *data = NULL;
 
+#ifdef __EXCEPTIONS
+  /* Make sure that lock is released when the thread is cancelled.  */
+  __libc_cleanup_push (cancel_handler, NULL);
+#endif
   __libc_lock_lock (lock);
 
   if (cache_valid_p ())
@@ -338,6 +350,9 @@ __check_pf (bool *seen_ipv4, bool *seen_ipv6,
        }
     }
 
+#ifdef __EXCEPTIONS
+  __libc_cleanup_pop (0);
+#endif
   __libc_lock_unlock (lock);
 
   if (data != NULL)
index c89ec8318208205da9761bae2fa0da9f280219f3..2e031e2f8a951cf6ca55b496ee85381439cb38bd 100644 (file)
@@ -14,3 +14,7 @@ test-xfail-check-execstack = yes
 test-xfail-check-wx-segment = *
 
 endif # $(subdir) == elf
+
+ifeq ($(subdir),debug)
+test-xfail-tst-ssp-1 = $(have-ssp)
+endif # $(subdir) == debug
index 0905cd833c746d971876d041ae5d79a9c07d6283..d8a291a33197561790a4e99f9db9693b19ffd98b 100644 (file)
 # define __O_LARGEFILE 0200000
 #endif
 
+#if __WORDSIZE == 64 && !defined __USE_FILE_OFFSET64
+# define F_GETLK       5
+# define F_SETLK       6
+# define F_SETLKW      7
+#endif
+
 struct flock
   {
     short int l_type;  /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.  */
index 0bba8930645f72ff4575a382ca105fb398e7fedc..92b78a877c9a0b2e2ad38510239dcfef8f3607da 100644 (file)
@@ -47,9 +47,12 @@ def main():
         # MAP_ANON alias for MAP_ANONYMOUS.  MAP_RENAME, MAP_AUTOGROW,
         # MAP_LOCAL and MAP_AUTORSRV are in the kernel header for
         # MIPS, marked as "not used by linux"; SPARC has MAP_INHERIT
-        # in the kernel header, but does not use it.
+        # in the kernel header, but does not use it.  The kernel
+        # header for HPPA removed a define of MAP_VARIABLE to 0 in
+        # Linux 6.2.
         'MAP_HUGE_[0-9].*|MAP_UNINITIALIZED|MAP_FAILED|MAP_ANON'
-        '|MAP_RENAME|MAP_AUTOGROW|MAP_LOCAL|MAP_AUTORSRV|MAP_INHERIT',
+        '|MAP_RENAME|MAP_AUTOGROW|MAP_LOCAL|MAP_AUTORSRV|MAP_INHERIT'
+        '|MAP_VARIABLE',
         linux_version_glibc > linux_version_headers,
         linux_version_headers > linux_version_glibc))
 
index a0474af8d1fb7dd01da190b94fb0f68b64d64a88..4383eb568ba404389f20ce1a904dbc5de6c9ea78 100644 (file)
@@ -311,47 +311,212 @@ handle_intel (int name, const struct cpu_features *cpu_features)
 
 
 static long int __attribute__ ((noinline))
-handle_amd (int name, const struct cpu_features *cpu_features)
+handle_amd (int name)
 {
   unsigned int eax;
   unsigned int ebx;
-  unsigned int ecx;
+  unsigned int ecx = 0;
   unsigned int edx;
-  unsigned int count = 0x1;
+  unsigned int max_cpuid = 0;
+  unsigned int fn = 0;
 
   /* No level 4 cache (yet).  */
   if (name > _SC_LEVEL3_CACHE_LINESIZE)
     return 0;
 
-  if (name >= _SC_LEVEL3_CACHE_SIZE)
-    count = 0x3;
-  else if (name >= _SC_LEVEL2_CACHE_SIZE)
-    count = 0x2;
-  else if (name >= _SC_LEVEL1_DCACHE_SIZE)
-    count = 0x0;
+  __cpuid (0x80000000, max_cpuid, ebx, ecx, edx);
+
+  if (max_cpuid >= 0x8000001D)
+    /* Use __cpuid__ '0x8000_001D' to compute cache details.  */
+    {
+      unsigned int count = 0x1;
+
+      if (name >= _SC_LEVEL3_CACHE_SIZE)
+        count = 0x3;
+      else if (name >= _SC_LEVEL2_CACHE_SIZE)
+        count = 0x2;
+      else if (name >= _SC_LEVEL1_DCACHE_SIZE)
+        count = 0x0;
+
+      __cpuid_count (0x8000001D, count, eax, ebx, ecx, edx);
+
+      if (ecx != 0)
+        {
+          switch (name)
+            {
+            case _SC_LEVEL1_ICACHE_ASSOC:
+            case _SC_LEVEL1_DCACHE_ASSOC:
+            case _SC_LEVEL2_CACHE_ASSOC:
+            case _SC_LEVEL3_CACHE_ASSOC:
+              return ((ebx >> 22) & 0x3ff) + 1;
+            case _SC_LEVEL1_ICACHE_LINESIZE:
+            case _SC_LEVEL1_DCACHE_LINESIZE:
+            case _SC_LEVEL2_CACHE_LINESIZE:
+            case _SC_LEVEL3_CACHE_LINESIZE:
+              return (ebx & 0xfff) + 1;
+            case _SC_LEVEL1_ICACHE_SIZE:
+            case _SC_LEVEL1_DCACHE_SIZE:
+            case _SC_LEVEL2_CACHE_SIZE:
+            case _SC_LEVEL3_CACHE_SIZE:
+              return (((ebx >> 22) & 0x3ff) + 1) * ((ebx & 0xfff) + 1) * (ecx + 1);
+            default:
+              __builtin_unreachable ();
+            }
+          return -1;
+        }
+    }
+
+  /* Legacy cache computation for CPUs prior to Bulldozer family.
+     This is also a fail-safe mechanism for some hypervisors that
+     accidentally configure __cpuid__ '0x8000_001D' to Zero.  */
+
+  fn = 0x80000005 + (name >= _SC_LEVEL2_CACHE_SIZE);
+
+  if (max_cpuid < fn)
+    return 0;
+
+  __cpuid (fn, eax, ebx, ecx, edx);
 
-  __cpuid_count (0x8000001D, count, eax, ebx, ecx, edx);
+  if (name < _SC_LEVEL1_DCACHE_SIZE)
+    {
+      name += _SC_LEVEL1_DCACHE_SIZE - _SC_LEVEL1_ICACHE_SIZE;
+      ecx = edx;
+    }
 
   switch (name)
     {
-       case _SC_LEVEL1_ICACHE_ASSOC:
-       case _SC_LEVEL1_DCACHE_ASSOC:
-       case _SC_LEVEL2_CACHE_ASSOC:
-       case _SC_LEVEL3_CACHE_ASSOC:
-         return ecx?((ebx >> 22) & 0x3ff) + 1 : 0;
-       case _SC_LEVEL1_ICACHE_LINESIZE:
-       case _SC_LEVEL1_DCACHE_LINESIZE:
-       case _SC_LEVEL2_CACHE_LINESIZE:
-       case _SC_LEVEL3_CACHE_LINESIZE:
-         return ecx?(ebx & 0xfff) + 1 : 0;
-       case _SC_LEVEL1_ICACHE_SIZE:
-       case _SC_LEVEL1_DCACHE_SIZE:
-       case _SC_LEVEL2_CACHE_SIZE:
-       case _SC_LEVEL3_CACHE_SIZE:
-         return ecx?(((ebx >> 22) & 0x3ff) + 1)*((ebx & 0xfff) + 1)\
-                                                    *(ecx + 1):0;
-       default:
-         assert (! "cannot happen");
+      case _SC_LEVEL1_DCACHE_SIZE:
+        return (ecx >> 14) & 0x3fc00;
+
+      case _SC_LEVEL1_DCACHE_ASSOC:
+        ecx >>= 16;
+        if ((ecx & 0xff) == 0xff)
+        {
+          /* Fully associative.  */
+          return (ecx << 2) & 0x3fc00;
+        }
+        return ecx & 0xff;
+
+      case _SC_LEVEL1_DCACHE_LINESIZE:
+        return ecx & 0xff;
+
+      case _SC_LEVEL2_CACHE_SIZE:
+        return (ecx & 0xf000) == 0 ? 0 : (ecx >> 6) & 0x3fffc00;
+
+      case _SC_LEVEL2_CACHE_ASSOC:
+        switch ((ecx >> 12) & 0xf)
+          {
+            case 0:
+            case 1:
+            case 2:
+            case 4:
+              return (ecx >> 12) & 0xf;
+            case 6:
+              return 8;
+            case 8:
+              return 16;
+            case 10:
+              return 32;
+            case 11:
+              return 48;
+            case 12:
+              return 64;
+            case 13:
+              return 96;
+            case 14:
+              return 128;
+            case 15:
+              return ((ecx >> 6) & 0x3fffc00) / (ecx & 0xff);
+            default:
+              return 0;
+          }
+
+      case _SC_LEVEL2_CACHE_LINESIZE:
+        return (ecx & 0xf000) == 0 ? 0 : ecx & 0xff;
+
+      case _SC_LEVEL3_CACHE_SIZE:
+        {
+        long int total_l3_cache = 0, l3_cache_per_thread = 0;
+        unsigned int threads = 0;
+        const struct cpu_features *cpu_features;
+
+        if ((edx & 0xf000) == 0)
+          return 0;
+
+        total_l3_cache = (edx & 0x3ffc0000) << 1;
+        cpu_features = __get_cpu_features ();
+
+        /* Figure out the number of logical threads that share L3.  */
+        if (max_cpuid >= 0x80000008)
+          {
+            /* Get width of APIC ID.  */
+            __cpuid (0x80000008, eax, ebx, ecx, edx);
+            threads = (ecx & 0xff) + 1;
+          }
+
+        if (threads == 0)
+          {
+            /* If APIC ID width is not available, use logical
+            processor count.  */
+            __cpuid (0x00000001, eax, ebx, ecx, edx);
+            if ((edx & (1 << 28)) != 0)
+              threads = (ebx >> 16) & 0xff;
+          }
+
+        /* Cap usage of highest cache level to the number of
+           supported threads.  */
+        if (threads > 0)
+          l3_cache_per_thread = total_l3_cache/threads;
+
+        /* Get shared cache per ccx for Zen architectures.  */
+        if (cpu_features->basic.family >= 0x17)
+          {
+            long int l3_cache_per_ccx = 0;
+            /* Get number of threads share the L3 cache in CCX.  */
+            __cpuid_count (0x8000001D, 0x3, eax, ebx, ecx, edx);
+            unsigned int threads_per_ccx = ((eax >> 14) & 0xfff) + 1;
+            l3_cache_per_ccx = l3_cache_per_thread * threads_per_ccx;
+            return l3_cache_per_ccx;
+          }
+        else
+          {
+            return l3_cache_per_thread;
+          }
+      }
+
+    case _SC_LEVEL3_CACHE_ASSOC:
+      switch ((edx >> 12) & 0xf)
+      {
+        case 0:
+        case 1:
+        case 2:
+        case 4:
+          return (edx >> 12) & 0xf;
+        case 6:
+          return 8;
+        case 8:
+          return 16;
+        case 10:
+          return 32;
+        case 11:
+          return 48;
+        case 12:
+          return 64;
+        case 13:
+          return 96;
+        case 14:
+          return 128;
+        case 15:
+          return ((edx & 0x3ffc0000) << 1) / (edx & 0xff);
+        default:
+          return 0;
+      }
+
+    case _SC_LEVEL3_CACHE_LINESIZE:
+      return (edx & 0xf000) == 0 ? 0 : edx & 0xff;
+
+    default:
+      __builtin_unreachable ();
     }
   return -1;
 }
@@ -408,7 +573,7 @@ handle_zhaoxin (int name)
 }
 
 static void
-get_common_cache_info (long int *shared_ptr, unsigned int *threads_ptr,
+get_common_cache_info (long int *shared_ptr, long int * shared_per_thread_ptr, unsigned int *threads_ptr,
                 long int core)
 {
   unsigned int eax;
@@ -427,6 +592,7 @@ get_common_cache_info (long int *shared_ptr, unsigned int *threads_ptr,
   unsigned int family = cpu_features->basic.family;
   unsigned int model = cpu_features->basic.model;
   long int shared = *shared_ptr;
+  long int shared_per_thread = *shared_per_thread_ptr;
   unsigned int threads = *threads_ptr;
   bool inclusive_cache = true;
   bool support_count_mask = true;
@@ -442,6 +608,7 @@ get_common_cache_info (long int *shared_ptr, unsigned int *threads_ptr,
       /* Try L2 otherwise.  */
       level  = 2;
       shared = core;
+      shared_per_thread = core;
       threads_l2 = 0;
       threads_l3 = -1;
     }
@@ -598,29 +765,27 @@ get_common_cache_info (long int *shared_ptr, unsigned int *threads_ptr,
         }
       else
         {
-intel_bug_no_cache_info:
-          /* Assume that all logical threads share the highest cache
-             level.  */
-          threads
-            = ((cpu_features->features[CPUID_INDEX_1].cpuid.ebx >> 16)
-              & 0xff);
-        }
-
-        /* Cap usage of highest cache level to the number of supported
-           threads.  */
-        if (shared > 0 && threads > 0)
-          shared /= threads;
+       intel_bug_no_cache_info:
+         /* Assume that all logical threads share the highest cache
+            level.  */
+         threads = ((cpu_features->features[CPUID_INDEX_1].cpuid.ebx >> 16)
+                    & 0xff);
+       }
+      /* Get per-thread size of highest level cache.  */
+      if (shared_per_thread > 0 && threads > 0)
+       shared_per_thread /= threads;
     }
 
   /* Account for non-inclusive L2 and L3 caches.  */
   if (!inclusive_cache)
     {
-      if (threads_l2 > 0)
-        core /= threads_l2;
+      long int core_per_thread = threads_l2 > 0 ? (core / threads_l2) : core;
+      shared_per_thread += core_per_thread;
       shared += core;
     }
 
   *shared_ptr = shared;
+  *shared_per_thread_ptr = shared_per_thread;
   *threads_ptr = threads;
 }
 
@@ -630,6 +795,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
   /* Find out what brand of processor.  */
   long int data = -1;
   long int shared = -1;
+  long int shared_per_thread = -1;
   long int core = -1;
   unsigned int threads = 0;
   unsigned long int level1_icache_size = -1;
@@ -650,6 +816,7 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
       data = handle_intel (_SC_LEVEL1_DCACHE_SIZE, cpu_features);
       core = handle_intel (_SC_LEVEL2_CACHE_SIZE, cpu_features);
       shared = handle_intel (_SC_LEVEL3_CACHE_SIZE, cpu_features);
+      shared_per_thread = shared;
 
       level1_icache_size
        = handle_intel (_SC_LEVEL1_ICACHE_SIZE, cpu_features);
@@ -673,13 +840,14 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
       level4_cache_size
        = handle_intel (_SC_LEVEL4_CACHE_SIZE, cpu_features);
 
-      get_common_cache_info (&shared, &threads, core);
+      get_common_cache_info (&shared, &shared_per_thread, &threads, core);
     }
   else if (cpu_features->basic.kind == arch_kind_zhaoxin)
     {
       data = handle_zhaoxin (_SC_LEVEL1_DCACHE_SIZE);
       core = handle_zhaoxin (_SC_LEVEL2_CACHE_SIZE);
       shared = handle_zhaoxin (_SC_LEVEL3_CACHE_SIZE);
+      shared_per_thread = shared;
 
       level1_icache_size = handle_zhaoxin (_SC_LEVEL1_ICACHE_SIZE);
       level1_icache_linesize = handle_zhaoxin (_SC_LEVEL1_ICACHE_LINESIZE);
@@ -693,34 +861,39 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
       level3_cache_assoc = handle_zhaoxin (_SC_LEVEL3_CACHE_ASSOC);
       level3_cache_linesize = handle_zhaoxin (_SC_LEVEL3_CACHE_LINESIZE);
 
-      get_common_cache_info (&shared, &threads, core);
+      get_common_cache_info (&shared, &shared_per_thread, &threads, core);
     }
   else if (cpu_features->basic.kind == arch_kind_amd)
     {
-      data  = handle_amd (_SC_LEVEL1_DCACHE_SIZE, cpu_features);
-      core = handle_amd (_SC_LEVEL2_CACHE_SIZE, cpu_features);
-      shared = handle_amd (_SC_LEVEL3_CACHE_SIZE, cpu_features);
+      data = handle_amd (_SC_LEVEL1_DCACHE_SIZE);
+      core = handle_amd (_SC_LEVEL2_CACHE_SIZE);
+      shared = handle_amd (_SC_LEVEL3_CACHE_SIZE);
 
-      level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE, cpu_features);
-      level1_icache_linesize
-       = handle_amd (_SC_LEVEL1_ICACHE_LINESIZE, cpu_features);
+      level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE);
+      level1_icache_linesize = handle_amd (_SC_LEVEL1_ICACHE_LINESIZE);
       level1_dcache_size = data;
-      level1_dcache_assoc
-       = handle_amd (_SC_LEVEL1_DCACHE_ASSOC, cpu_features);
-      level1_dcache_linesize
-       = handle_amd (_SC_LEVEL1_DCACHE_LINESIZE, cpu_features);
+      level1_dcache_assoc = handle_amd (_SC_LEVEL1_DCACHE_ASSOC);
+      level1_dcache_linesize = handle_amd (_SC_LEVEL1_DCACHE_LINESIZE);
       level2_cache_size = core;
-      level2_cache_assoc = handle_amd (_SC_LEVEL2_CACHE_ASSOC, cpu_features);
-      level2_cache_linesize
-       = handle_amd (_SC_LEVEL2_CACHE_LINESIZE, cpu_features);
+      level2_cache_assoc = handle_amd (_SC_LEVEL2_CACHE_ASSOC);
+      level2_cache_linesize = handle_amd (_SC_LEVEL2_CACHE_LINESIZE);
       level3_cache_size = shared;
-      level3_cache_assoc = handle_amd (_SC_LEVEL3_CACHE_ASSOC, cpu_features);
-      level3_cache_linesize
-       = handle_amd (_SC_LEVEL3_CACHE_LINESIZE, cpu_features);
+      level3_cache_assoc = handle_amd (_SC_LEVEL3_CACHE_ASSOC);
+      level3_cache_linesize = handle_amd (_SC_LEVEL3_CACHE_LINESIZE);
+      level4_cache_size = handle_amd (_SC_LEVEL4_CACHE_SIZE);
 
       if (shared <= 0)
-        /* No shared L3 cache.  All we have is the L2 cache.  */
-         shared = core;
+        {
+           /* No shared L3 cache.  All we have is the L2 cache.  */
+           shared = core;
+        }
+      else if (cpu_features->basic.family < 0x17)
+        {
+           /* Account for exclusive L2 and L3 caches.  */
+           shared += core;
+        }
+
+      shared_per_thread = shared;
     }
 
   cpu_features->level1_icache_size = level1_icache_size;
@@ -736,17 +909,34 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
   cpu_features->level3_cache_linesize = level3_cache_linesize;
   cpu_features->level4_cache_size = level4_cache_size;
 
-  /* The default setting for the non_temporal threshold is 3/4 of one
-     thread's share of the chip's cache. For most Intel and AMD processors
-     with an initial release date between 2017 and 2020, a thread's typical
-     share of the cache is from 500 KBytes to 2 MBytes. Using the 3/4
-     threshold leaves 125 KBytes to 500 KBytes of the thread's data
-     in cache after a maximum temporal copy, which will maintain
-     in cache a reasonable portion of the thread's stack and other
-     active data. If the threshold is set higher than one thread's
-     share of the cache, it has a substantial risk of negatively
-     impacting the performance of other threads running on the chip. */
-  unsigned long int non_temporal_threshold = shared * 3 / 4;
+  /* The default setting for the non_temporal threshold is 1/4 of size
+     of the chip's cache. For most Intel and AMD processors with an
+     initial release date between 2017 and 2023, a thread's typical
+     share of the cache is from 18-64MB. Using the 1/4 L3 is meant to
+     estimate the point where non-temporal stores begin out-competing
+     REP MOVSB. As well the point where the fact that non-temporal
+     stores are forced back to main memory would already occurred to the
+     majority of the lines in the copy. Note, concerns about the
+     entire L3 cache being evicted by the copy are mostly alleviated
+     by the fact that modern HW detects streaming patterns and
+     provides proper LRU hints so that the maximum thrashing
+     capped at 1/associativity. */
+  unsigned long int non_temporal_threshold = shared / 4;
+
+  /* If the computed non_temporal_threshold <= 3/4 * per-thread L3, we most
+     likely have incorrect/incomplete cache info in which case, default to
+     3/4 * per-thread L3 to avoid regressions.  */
+  unsigned long int non_temporal_threshold_lowbound
+      = shared_per_thread * 3 / 4;
+  if (non_temporal_threshold < non_temporal_threshold_lowbound)
+    non_temporal_threshold = non_temporal_threshold_lowbound;
+
+  /* If no ERMS, we use the per-thread L3 chunking. Normal cacheable stores run
+     a higher risk of actually thrashing the cache as they don't have a HW LRU
+     hint. As well, their performance in highly parallel situations is
+     noticeably worse.  */
+  if (!CPU_FEATURE_USABLE_P (cpu_features, ERMS))
+    non_temporal_threshold = non_temporal_threshold_lowbound;
   /* SIZE_MAX >> 4 because memmove-vec-unaligned-erms right-shifts the value of
      'x86_non_temporal_threshold' by `LOG_4X_MEMCPY_THRESH` (4) and it is best
      if that operation cannot overflow. Minimum of 0x4040 (16448) because the
index 5593897e29bd82ff465b650ed5592397e6196138..4579424bf7e98d0a4e15df4ae5aab8b610875a70 100644 (file)
@@ -61,7 +61,7 @@ _dl_tlsdesc_return:
 _dl_tlsdesc_undefweak:
        _CET_ENDBR
        movq    8(%rax), %rax
-       subq    %fs:0, %rax
+       sub     %fs:0, %RAX_LP
        ret
        cfi_endproc
        .size   _dl_tlsdesc_undefweak, .-_dl_tlsdesc_undefweak
@@ -102,7 +102,7 @@ _dl_tlsdesc_dynamic:
        /* Preserve call-clobbered registers that we modify.
           We need two scratch regs anyway.  */
        movq    %rsi, -16(%rsp)
-       movq    %fs:DTV_OFFSET, %rsi
+       mov     %fs:DTV_OFFSET, %RSI_LP
        movq    %rdi, -8(%rsp)
        movq    TLSDESC_ARG(%rax), %rdi
        movq    (%rsi), %rax
@@ -116,7 +116,7 @@ _dl_tlsdesc_dynamic:
        addq    TLSDESC_MODOFF(%rdi), %rax
 .Lret:
        movq    -16(%rsp), %rsi
-       subq    %fs:0, %rax
+       sub     %fs:0, %RAX_LP
        movq    -8(%rsp), %rdi
        ret
 .Lslow:
index 924eed96a90de26f6cddb415a83c9ce29ffc7dd6..e7430a4158fb1b9302a8fb6cf503017034a61f8c 100644 (file)
@@ -33,7 +33,7 @@ __feraiseexcept (int excepts)
       /* One example of an invalid operation is 0.0 / 0.0.  */
       float f = 0.0;
 
-      __asm__ __volatile__ ("divss %0, %0 " : : "x" (f));
+      __asm__ __volatile__ ("divss %0, %0 " : "+x" (f));
       (void) &f;
     }
 
@@ -43,7 +43,7 @@ __feraiseexcept (int excepts)
       float f = 1.0;
       float g = 0.0;
 
-      __asm__ __volatile__ ("divss %1, %0" : : "x" (f), "x" (g));
+      __asm__ __volatile__ ("divss %1, %0" : "+x" (f) : "x" (g));
       (void) &f;
     }
 
index d86f2105c5df9e7b6e801a847c2d8a3258cdfaa2..92bc3db315bc6465aeaa3c0b73903b804c755519 100644 (file)
@@ -50,7 +50,7 @@ tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
           tst-clock tst-clock2 tst-clock_nanosleep tst-cpuclock1 \
           tst-adjtime tst-ctime tst-difftime tst-mktime4 tst-clock_settime \
           tst-settimeofday tst-itimer tst-gmtime tst-timegm \
-          tst-timespec_get tst-timespec_getres
+          tst-timespec_get tst-timespec_getres tst-strftime4
 
 tests-time64 := \
   tst-adjtime-time64 \
@@ -65,6 +65,7 @@ tests-time64 := \
   tst-itimer-time64 \
   tst-mktime4-time64 \
   tst-settimeofday-time64 \
+  tst-strftime4-time64 \
   tst-timegm-time64 \
   tst-timespec_get-time64 \
   tst-timespec_getres-time64 \
index e09561c39ccf65c2e71c0cc0d46306b9f42dee81..402c6c411140a87fac35fdc8c7c89be206bc85ec 100644 (file)
@@ -159,6 +159,10 @@ extern char *tzname[];
 #ifdef _LIBC
 # define tzname __tzname
 # define tzset __tzset
+
+# define time_t __time64_t
+# define __gmtime_r(t, tp) __gmtime64_r (t, tp)
+# define mktime(tp) __mktime64 (tp)
 #endif
 
 #if !HAVE_TM_GMTOFF
index 80fd705b8dfc6e79c47c09840b1be12f1e5b5ac9..85c3249fcc256533b08186c5c18a8c369698b96e 100644 (file)
 #ifdef _LIBC
 # define HAVE_LOCALTIME_R 0
 # include "../locale/localeinfo.h"
-#endif
 
+# define time_t __time64_t
+# define __localtime_r(t, tp) __localtime64_r (t, tp)
+#endif
 
 #if ! HAVE_LOCALTIME_R && ! defined localtime_r
 # ifdef _LIBC
diff --git a/time/tst-strftime4-time64.c b/time/tst-strftime4-time64.c
new file mode 100644 (file)
index 0000000..4d47ee7
--- /dev/null
@@ -0,0 +1 @@
+#include "tst-strftime4.c"
diff --git a/time/tst-strftime4.c b/time/tst-strftime4.c
new file mode 100644 (file)
index 0000000..659716d
--- /dev/null
@@ -0,0 +1,52 @@
+/* Test strftime and strptime after 2038-01-19 03:14:07 UTC (bug 30053).
+   Copyright (C) 2023 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 <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <support/check.h>
+
+static int
+do_test (void)
+{
+  TEST_VERIFY_EXIT (setenv ("TZ", "UTC0", 1) == 0);
+  tzset ();
+  if (sizeof (time_t) > 4)
+    {
+      time_t wrap = (time_t) 2147483648LL;
+      char buf[80];
+      struct tm *tm = gmtime (&wrap);
+      TEST_VERIFY_EXIT (tm != NULL);
+      TEST_VERIFY_EXIT (strftime (buf, sizeof buf, "%s", tm) > 0);
+      puts (buf);
+      TEST_VERIFY (strcmp (buf, "2147483648") == 0);
+
+      struct tm tm2;
+      char *p = strptime (buf, "%s", &tm2);
+      TEST_VERIFY_EXIT (p != NULL && *p == '\0');
+      time_t t = mktime (&tm2);
+      printf ("%lld\n", (long long) t);
+      TEST_VERIFY (t == wrap);
+    }
+  else
+    FAIL_UNSUPPORTED ("32-bit time_t");
+  return 0;
+}
+
+#include <support/test-driver.c>