git-updates
authorGNU Libc Maintainers <debian-glibc@lists.debian.org>
Sat, 1 Jun 2024 21:16:35 +0000 (23:16 +0200)
committerAurelien Jarno <aurel32@debian.org>
Sat, 1 Jun 2024 21:16:35 +0000 (23:16 +0200)
GIT update of https://sourceware.org/git/glibc.git/release/2.38/master from glibc-2.38

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

Gbp-Pq: Name git-updates.diff

155 files changed:
Makeconfig
NEWS
bits/wordsize.h
elf/Makefile
elf/dl-init.c
elf/dl-tls.c
elf/dl-tunables.c
elf/readelflib.c
elf/tst-env-setuid-tunables.c
elf/tst-tlsgap-mod0.c [new file with mode: 0644]
elf/tst-tlsgap-mod1.c [new file with mode: 0644]
elf/tst-tlsgap-mod2.c [new file with mode: 0644]
elf/tst-tlsgap.c [new file with mode: 0644]
iconv/iconv_prog.c
iconvdata/Makefile
iconvdata/iso-2022-cn-ext.c
iconvdata/tst-iconv-iso-2022-cn-ext.c [new file with mode: 0644]
include/ifaddrs.h
include/link.h
include/sys/sysinfo.h
inet/check_pf.c
io/Makefile
io/tst-fcntl-lock-lfs.c [new file with mode: 0644]
libio/vtables.c
libio/wfileops.c
login/Makefile
login/tst-utmp-size-64.c [new file with mode: 0644]
login/tst-utmp-size.c [new file with mode: 0644]
malloc/arena.c
malloc/malloc.c
malloc/tst-memalign-2.c
misc/Makefile
misc/getsysstats.c
misc/syslog.c
misc/tst-preadvwritev2-common.c
misc/tst-syslog-long-progname.c [new file with mode: 0644]
nscd/Makefile
nscd/connections.c
nscd/gai.c [deleted file]
nscd/netgroupcache.c
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/res_nameinquery.c
resolv/res_queriesmatch.c
resolv/tst-resolv-noaaaa-vc.c [new file with mode: 0644]
stdlib/tst-realpath.c
string/tester.c
sysdeps/aarch64/configure [changed mode: 0644->0755]
sysdeps/aarch64/configure.ac
sysdeps/aarch64/memset.S
sysdeps/aarch64/multiarch/Makefile
sysdeps/aarch64/multiarch/ifunc-impl-list.c
sysdeps/aarch64/multiarch/init-arch.h
sysdeps/aarch64/multiarch/memchr_nosimd.S
sysdeps/aarch64/multiarch/memcpy.c
sysdeps/aarch64/multiarch/memcpy_a64fx.S
sysdeps/aarch64/multiarch/memcpy_falkor.S [deleted file]
sysdeps/aarch64/multiarch/memcpy_mops.S [new file with mode: 0644]
sysdeps/aarch64/multiarch/memcpy_sve.S
sysdeps/aarch64/multiarch/memcpy_thunderx.S
sysdeps/aarch64/multiarch/memcpy_thunderx2.S
sysdeps/aarch64/multiarch/memmove.c
sysdeps/aarch64/multiarch/memmove_mops.S [new file with mode: 0644]
sysdeps/aarch64/multiarch/memset.c
sysdeps/aarch64/multiarch/memset_a64fx.S
sysdeps/aarch64/multiarch/memset_base64.S [deleted file]
sysdeps/aarch64/multiarch/memset_emag.S
sysdeps/aarch64/multiarch/memset_falkor.S [deleted file]
sysdeps/aarch64/multiarch/memset_generic.S
sysdeps/aarch64/multiarch/memset_kunpeng.S
sysdeps/aarch64/multiarch/memset_mops.S [new file with mode: 0644]
sysdeps/aarch64/multiarch/memset_zva64.S [new file with mode: 0644]
sysdeps/aarch64/multiarch/rtld-memset.S [deleted file]
sysdeps/aarch64/multiarch/strlen.c
sysdeps/aarch64/multiarch/strlen_asimd.S
sysdeps/aarch64/multiarch/strlen_generic.S [new file with mode: 0644]
sysdeps/aarch64/multiarch/strlen_mte.S [deleted file]
sysdeps/aarch64/rawmemchr.S
sysdeps/arc/utmp-size.h [new file with mode: 0644]
sysdeps/arm/bits/wordsize.h [new file with mode: 0644]
sysdeps/arm/dl-machine.h
sysdeps/arm/utmp-size.h [new file with mode: 0644]
sysdeps/csky/bits/wordsize.h [new file with mode: 0644]
sysdeps/csky/utmp-size.h [new file with mode: 0644]
sysdeps/generic/unsecvars.h
sysdeps/generic/utmp-size.h [new file with mode: 0644]
sysdeps/hppa/utmp-size.h [new file with mode: 0644]
sysdeps/i386/fpu/libm-test-ulps
sysdeps/i386/i686/memcpy.S
sysdeps/i386/i686/mempcpy.S
sysdeps/i386/i686/multiarch/memcpy_chk.c
sysdeps/i386/i686/multiarch/memmove_chk.c
sysdeps/i386/i686/multiarch/mempcpy_chk.c
sysdeps/i386/i686/multiarch/memset_chk.c
sysdeps/loongarch/dl-trampoline.h
sysdeps/loongarch/fpu/e_scalbf.c
sysdeps/m68k/bits/wordsize.h [new file with mode: 0644]
sysdeps/m68k/utmp-size.h [new file with mode: 0644]
sysdeps/mach/getsysstats.c
sysdeps/microblaze/bits/wordsize.h [new file with mode: 0644]
sysdeps/microblaze/utmp-size.h [new file with mode: 0644]
sysdeps/mips/bits/wordsize.h
sysdeps/mips/utmp-size.h [new file with mode: 0644]
sysdeps/nios2/bits/wordsize.h [new file with mode: 0644]
sysdeps/nios2/utmp-size.h [new file with mode: 0644]
sysdeps/or1k/utmp-size.h [new file with mode: 0644]
sysdeps/posix/getaddrinfo.c
sysdeps/powerpc/powerpc32/bits/wordsize.h
sysdeps/powerpc/powerpc64/bits/wordsize.h
sysdeps/powerpc/powerpc64/dl-machine.h
sysdeps/powerpc/utmp-size.h [new file with mode: 0644]
sysdeps/pthread/sem_open.c
sysdeps/pthread/tst-cancel30.c
sysdeps/riscv/utmp-size.h [new file with mode: 0644]
sysdeps/s390/memrchr-c.c
sysdeps/s390/strchrnul-c.c
sysdeps/sh/bits/wordsize.h [new file with mode: 0644]
sysdeps/sh/utmp-size.h [new file with mode: 0644]
sysdeps/sparc/sparc32/bits/wordsize.h
sysdeps/sparc/sparc32/memset.S
sysdeps/sparc/sparc64/bits/wordsize.h
sysdeps/sparc/sparc64/memmove.S
sysdeps/sparc/sysdep.h
sysdeps/sparc/utmp-size.h [new file with mode: 0644]
sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h
sysdeps/unix/sysv/linux/aarch64/cpu-features.c
sysdeps/unix/sysv/linux/aarch64/cpu-features.h
sysdeps/unix/sysv/linux/bits/uio-ext.h
sysdeps/unix/sysv/linux/check_pf.c
sysdeps/unix/sysv/linux/getsysstats.c
sysdeps/unix/sysv/linux/hppa/bits/wordsize.h [new file with mode: 0644]
sysdeps/unix/sysv/linux/i386/tst-bz21269.c
sysdeps/unix/sysv/linux/powerpc/bits/fcntl.h
sysdeps/unix/sysv/linux/powerpc/bits/wordsize.h
sysdeps/unix/sysv/linux/s390/s390-32/clone.S
sysdeps/unix/sysv/linux/s390/s390-64/clone.S
sysdeps/unix/sysv/linux/sched_getcpu.c
sysdeps/unix/sysv/linux/sparc/bits/wordsize.h
sysdeps/unix/sysv/linux/sparc/sparc32/sigreturn_stub.S
sysdeps/unix/sysv/linux/sparc/sparc64/sigreturn_stub.S
sysdeps/unix/sysv/linux/tst-clone.c
sysdeps/x86/bits/wordsize.h
sysdeps/x86/dl-cacheinfo.h
sysdeps/x86/tst-cpu-features-supports.c
sysdeps/x86/utmp-size.h [new file with mode: 0644]
sysdeps/x86_64/dl-tlsdesc.S
sysdeps/x86_64/ffsll.c
sysdeps/x86_64/memcpy.S
sysdeps/x86_64/memmove.S
sysdeps/x86_64/memset.S

index 77d7fd14df1a6cd22ecc00d3139d2db3de28b780..3f8acff459dd7fcd13ab6315c55f238dbc312fd8 100644 (file)
@@ -586,10 +586,13 @@ link-libc-rpath-link = -Wl,-rpath-link=$(rpath-link)
 # before the expansion of LDLIBS-* variables).
 
 # Tests use -Wl,-rpath instead of -Wl,-rpath-link for
-# build-hardcoded-path-in-tests.
+# build-hardcoded-path-in-tests.  Add -Wl,--disable-new-dtags to force
+# DT_RPATH instead of DT_RUNPATH which only applies to DT_NEEDED entries
+# in the executable and doesn't applies to DT_NEEDED entries in shared
+# libraries which are loaded via DT_NEEDED entries in the executable.
 ifeq (yes,$(build-hardcoded-path-in-tests))
-link-libc-tests-rpath-link = $(link-libc-rpath)
-link-test-modules-rpath-link = $(link-libc-rpath)
+link-libc-tests-rpath-link = $(link-libc-rpath) -Wl,--disable-new-dtags
+link-test-modules-rpath-link = $(link-libc-rpath) -Wl,--disable-new-dtags
 else
 link-libc-tests-rpath-link = $(link-libc-rpath-link)
 link-test-modules-rpath-link =
diff --git a/NEWS b/NEWS
index 872bc8907bc01a93c6633b75381cd19c7a07ab3e..6768c2da6f0a719f3c62701bece0d9bb9ccef73d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,49 @@ 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.38.1
+
+Security related changes:
+
+  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:
+
+  [29039] Corrupt DTV after reuse of a TLS module ID following dlclose with unused TLS
+  [30694] The iconv program no longer tells the user which given encoding name was wrong
+  [30709] nscd fails to build with cleanup handler if built with -fexceptions
+  [30721] x86_64: Fix build with --disable-multiarch
+  [30723] posix_memalign repeatedly scans long bin lists
+  [30745] Slight bug in cache info codes for x86
+  [30789] sem_open will fail on multithreaded scenarios when semaphore
+    file doesn't exist (O_CREAT)
+  [30804] F_GETLK, F_SETLK, and F_SETLKW value change for powerpc64 with
+    -D_FILE_OFFSET_BITS=64
+  [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.38
 
index 14edae3a11d01c9714172d9dd6b78b38b086c36c..53013a9275c7c81eccb0356ab956eb2688bcf512 100644 (file)
@@ -21,7 +21,9 @@
 #define __WORDSIZE32_PTRDIFF_LONG
 
 /* Set to 1 in order to force time types to be 32 bits instead of 64 bits in
-   struct lastlog and struct utmp{,x} on 64-bit ports.  This may be done in
+   struct lastlog and struct utmp{,x}.  This may be done in
    order to make 64-bit ports compatible with 32-bit ports.  Set to 0 for
-   64-bit ports where the time types are 64-bits or for any 32-bit ports.  */
+   64-bit ports where the time types are 64-bits and new 32-bit ports
+   where time_t is 64 bits, and there is no companion architecture with
+   32-bit time_t.  */
 #define __WORDSIZE_TIME64_COMPAT32
index c00e2ccfc55a004d9ef069e3e60e50a89b3284ae..c2af11b92c9d1cf1e48210eab6fbae47b985200c 100644 (file)
@@ -166,6 +166,7 @@ CFLAGS-.op += $(call elide-stack-protector,.op,$(elide-routines.os))
 CFLAGS-.os += $(call elide-stack-protector,.os,$(all-rtld-routines))
 
 # Add the requested compiler flags to the early startup code.
+CFLAGS-dl-misc.os += $(rtld-early-cflags)
 CFLAGS-dl-printf.os += $(rtld-early-cflags)
 CFLAGS-dl-setup_hash.os += $(rtld-early-cflags)
 CFLAGS-dl-sysdep.os += $(rtld-early-cflags)
@@ -459,6 +460,7 @@ tests += \
   tst-tls21 \
   tst-tlsalign \
   tst-tlsalign-extern \
+  tst-tlsgap \
   tst-unique1 \
   tst-unique2 \
   tst-unwind-ctor \
@@ -883,6 +885,9 @@ modules-names += \
   tst-tls20mod-bad \
   tst-tls21mod \
   tst-tlsalign-lib \
+  tst-tlsgap-mod0 \
+  tst-tlsgap-mod1 \
+  tst-tlsgap-mod2 \
   tst-tlsmod1 \
   tst-tlsmod10 \
   tst-tlsmod11 \
@@ -3009,3 +3014,14 @@ LDFLAGS-tst-dlclose-lazy-mod1.so = -Wl,-z,lazy,--no-as-needed
 $(objpfx)tst-dlclose-lazy-mod1.so: $(objpfx)tst-dlclose-lazy-mod2.so
 $(objpfx)tst-dlclose-lazy.out: \
   $(objpfx)tst-dlclose-lazy-mod1.so $(objpfx)tst-dlclose-lazy-mod2.so
+
+$(objpfx)tst-tlsgap: $(shared-thread-library)
+$(objpfx)tst-tlsgap.out: \
+  $(objpfx)tst-tlsgap-mod0.so \
+  $(objpfx)tst-tlsgap-mod1.so \
+  $(objpfx)tst-tlsgap-mod2.so
+ifeq (yes,$(have-mtls-dialect-gnu2))
+CFLAGS-tst-tlsgap-mod0.c += -mtls-dialect=gnu2
+CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=gnu2
+CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=gnu2
+endif
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 99b83ca6962cf8464c57195ee5ef7fd6723ebc21..1f6f820819d847d6e2b3aa43646821df4d266cfa 100644 (file)
@@ -154,6 +154,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 62b7332d95b61ce3428040522271f6e93e9d53ed..cae67efa0aacb9984c49874dcb95f170ecd1d86d 100644 (file)
@@ -180,11 +180,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.  */
@@ -244,9 +240,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';
 }
 
 /* Enable the glibc.malloc.check tunable in SETUID/SETGID programs only when
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 7dfb0e073ae1a9c63f6790a8b80433e237010e22..f0b92c97e7670a93ff7300a8d97d0329fd184452 100644 (file)
@@ -50,6 +50,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",
@@ -68,6 +70,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",
+  "",
   "",
   "",
   "",
@@ -81,11 +85,18 @@ test_child (int off)
 {
   const char *val = getenv ("GLIBC_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;
 }
@@ -106,21 +117,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);
 
@@ -128,9 +144,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-tlsgap-mod0.c b/elf/tst-tlsgap-mod0.c
new file mode 100644 (file)
index 0000000..1478b0b
--- /dev/null
@@ -0,0 +1,2 @@
+int __thread tls0;
+int *f0(void) { return &tls0; }
diff --git a/elf/tst-tlsgap-mod1.c b/elf/tst-tlsgap-mod1.c
new file mode 100644 (file)
index 0000000..b10fc37
--- /dev/null
@@ -0,0 +1,2 @@
+int __thread tls1[100]; /* Size > glibc.rtld.optional_static_tls / 2.  */
+int *f1(void) { return tls1; }
diff --git a/elf/tst-tlsgap-mod2.c b/elf/tst-tlsgap-mod2.c
new file mode 100644 (file)
index 0000000..166c27d
--- /dev/null
@@ -0,0 +1,2 @@
+int __thread tls2;
+int *f2(void) { return &tls2; }
diff --git a/elf/tst-tlsgap.c b/elf/tst-tlsgap.c
new file mode 100644 (file)
index 0000000..4932885
--- /dev/null
@@ -0,0 +1,92 @@
+/* TLS modid gap reuse regression test for bug 29039.
+   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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <dlfcn.h>
+#include <pthread.h>
+#include <support/xdlfcn.h>
+#include <support/xthread.h>
+#include <support/check.h>
+
+static void *mod[3];
+#define MOD(i) "tst-tlsgap-mod" #i ".so"
+static const char *modname[3] = { MOD(0), MOD(1), MOD(2) };
+#undef MOD
+
+static void
+open_mod (int i)
+{
+  mod[i] = xdlopen (modname[i], RTLD_LAZY);
+  printf ("open %s\n", modname[i]);
+}
+
+static void
+close_mod (int i)
+{
+  xdlclose (mod[i]);
+  mod[i] = NULL;
+  printf ("close %s\n", modname[i]);
+}
+
+static void
+access_mod (int i, const char *sym)
+{
+  int *(*f) (void) = xdlsym (mod[i], sym);
+  int *p = f ();
+  printf ("access %s: %s() = %p\n", modname[i], sym, p);
+  TEST_VERIFY_EXIT (p != NULL);
+  ++*p;
+}
+
+static void *
+start (void *arg)
+{
+  /* The DTV generation is at the last dlopen of mod0 and the
+     entry for mod1 is NULL.  */
+
+  open_mod (1); /* Reuse modid of mod1. Uses dynamic TLS.  */
+
+  /* DTV is unchanged: dlopen only updates the DTV to the latest
+     generation if static TLS is allocated for a loaded module.
+
+     With bug 29039, the TLSDESC relocation in mod1 uses the old
+     dlclose generation of mod1 instead of the new dlopen one so
+     DTV is not updated on TLS access.  */
+
+  access_mod (1, "f1");
+
+  return arg;
+}
+
+static int
+do_test (void)
+{
+  open_mod (0);
+  open_mod (1);
+  open_mod (2);
+  close_mod (0);
+  close_mod (1); /* Create modid gap at mod1.  */
+  open_mod (0); /* Reuse modid of mod0, bump generation count.  */
+
+  /* Create a thread where DTV of mod1 is NULL.  */
+  pthread_t t = xpthread_create (NULL, start, NULL);
+  xpthread_join (t);
+  return 0;
+}
+
+#include <support/test-driver.c>
index bee898c63c603da6132a50f30e34b87a32e1fc29..cf32cf9b44b208e2df0bec30bf0edd4941dfa657 100644 (file)
@@ -187,7 +187,7 @@ main (int argc, char *argv[])
 
       if (res != __GCONV_OK)
        {
-         if (errno == EINVAL)
+         if (res == __GCONV_NOCONV || res == __GCONV_NODB)
            {
              /* Try to be nice with the user and tell her which of the
                 two encoding names is wrong.  This is possible because
index dd5cafab21d5879a0f5abb437fec022d567fc081..075098dce8145fad22e50f22d542ead1f7164abd 100644 (file)
@@ -75,7 +75,8 @@ ifeq (yes,$(build-shared))
 tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
        tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
        bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \
-       bug-iconv13 bug-iconv14 bug-iconv15
+       bug-iconv13 bug-iconv14 bug-iconv15 \
+       tst-iconv-iso-2022-cn-ext
 ifeq ($(have-thread-library),yes)
 tests += bug-iconv3
 endif
@@ -330,6 +331,8 @@ $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \
                          $(addprefix $(objpfx),$(modules.so))
 $(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
                          $(addprefix $(objpfx),$(modules.so))
+$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \
+                                       $(addprefix $(objpfx),$(modules.so))
 
 $(objpfx)iconv-test.out: run-iconv-test.sh \
                         $(addprefix $(objpfx), $(gconv-modules)) \
index 36727f0865da11acd6748e3a3722cc5d16735275..9bb02238a3cc810de8b992eb95435938f77cc174 100644 (file)
@@ -574,6 +574,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
              {                                                               \
                const char *escseq;                                           \
                                                                              \
+               if (outptr + 4 > outend)                                      \
+                 {                                                           \
+                   result = __GCONV_FULL_OUTPUT;                             \
+                   break;                                                    \
+                 }                                                           \
+                                                                             \
                assert (used == CNS11643_2_set); /* XXX */                    \
                escseq = "*H";                                                \
                *outptr++ = ESC;                                              \
@@ -587,6 +593,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
              {                                                               \
                const char *escseq;                                           \
                                                                              \
+               if (outptr + 4 > outend)                                      \
+                 {                                                           \
+                   result = __GCONV_FULL_OUTPUT;                             \
+                   break;                                                    \
+                 }                                                           \
+                                                                             \
                assert ((used >> 5) >= 3 && (used >> 5) <= 7);                \
                escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2;                \
                *outptr++ = ESC;                                              \
diff --git a/iconvdata/tst-iconv-iso-2022-cn-ext.c b/iconvdata/tst-iconv-iso-2022-cn-ext.c
new file mode 100644 (file)
index 0000000..96a8765
--- /dev/null
@@ -0,0 +1,128 @@
+/* Verify ISO-2022-CN-EXT does not write out of the bounds.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <errno.h>
+#include <iconv.h>
+#include <sys/mman.h>
+
+#include <support/xunistd.h>
+#include <support/check.h>
+#include <support/support.h>
+
+/* The test sets up a two memory page buffer with the second page marked
+   PROT_NONE to trigger a fault if the conversion writes beyond the exact
+   expected amount.  Then we carry out various conversions and precisely
+   place the start of the output buffer in order to trigger a SIGSEGV if the
+   process writes anywhere between 1 and page sized bytes more (only one
+   PROT_NONE page is setup as a canary) than expected.  These tests exercise
+   all three of the cases in ISO-2022-CN-EXT where the converter must switch
+   character sets and may run out of buffer space while doing the
+   operation.  */
+
+static int
+do_test (void)
+{
+  iconv_t cd = iconv_open ("ISO-2022-CN-EXT", "UTF-8");
+  TEST_VERIFY_EXIT (cd != (iconv_t) -1);
+
+  char *ntf;
+  size_t ntfsize;
+  char *outbufbase;
+  {
+    int pgz = getpagesize ();
+    TEST_VERIFY_EXIT (pgz > 0);
+    ntfsize = 2 * pgz;
+
+    ntf = xmmap (NULL, ntfsize, PROT_READ | PROT_WRITE, MAP_PRIVATE
+                | MAP_ANONYMOUS, -1);
+    xmprotect (ntf + pgz, pgz, PROT_NONE);
+
+    outbufbase = ntf + pgz;
+  }
+
+  /* Check if SOdesignation escape sequence does not trigger an OOB write.  */
+  {
+    char inbuf[] = "\xe4\xba\xa4\xe6\x8d\xa2";
+
+    for (int i = 0; i < 9; i++)
+      {
+       char *inp = inbuf;
+       size_t inleft = sizeof (inbuf) - 1;
+
+       char *outp = outbufbase - i;
+       size_t outleft = i;
+
+       TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+                         == (size_t) -1);
+       TEST_COMPARE (errno, E2BIG);
+
+       TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+      }
+  }
+
+  /* Same as before for SS2designation.  */
+  {
+    char inbuf[] = "ã´½ \xe3\xb4\xbd";
+
+    for (int i = 0; i < 14; i++)
+      {
+       char *inp = inbuf;
+       size_t inleft = sizeof (inbuf) - 1;
+
+       char *outp = outbufbase - i;
+       size_t outleft = i;
+
+       TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+                         == (size_t) -1);
+       TEST_COMPARE (errno, E2BIG);
+
+       TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+      }
+  }
+
+  /* Same as before for SS3designation.  */
+  {
+    char inbuf[] = "劄 \xe5\x8a\x84";
+
+    for (int i = 0; i < 14; i++)
+      {
+       char *inp = inbuf;
+       size_t inleft = sizeof (inbuf) - 1;
+
+       char *outp = outbufbase - i;
+       size_t outleft = i;
+
+       TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+                         == (size_t) -1);
+       TEST_COMPARE (errno, E2BIG);
+
+       TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+      }
+  }
+
+  TEST_VERIFY_EXIT (iconv_close (cd) != -1);
+
+  xmunmap (ntf, ntfsize);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
index 416118f1b38cb580b2d45966d5e29d531f4c81d5..19a3afb19f9e893c08e66d2ac6bc6703afed3302 100644 (file)
@@ -34,9 +34,5 @@ extern void __check_native (uint32_t a1_index, int *a1_native,
                            uint32_t a2_index, int *a2_native)
   attribute_hidden;
 
-#if IS_IN (nscd)
-extern uint32_t __bump_nl_timestamp (void) attribute_hidden;
-#endif
-
 # endif /* !_ISOMAC */
 #endif /* ifaddrs.h */
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 c490561581733038fa4ac0377143125bb133a8be..65742b10366590f053a97b77310316012d54d588 100644 (file)
@@ -14,10 +14,6 @@ libc_hidden_proto (__get_nprocs_conf)
 extern int __get_nprocs (void);
 libc_hidden_proto (__get_nprocs)
 
-/* Return the number of available processors which the process can
-   be scheduled.  */
-extern int __get_nprocs_sched (void) attribute_hidden;
-
 /* Return number of physical pages of memory in the system.  */
 extern long int __get_phys_pages (void);
 libc_hidden_proto (__get_phys_pages)
index 5310c99121aa5a6466ee86f39783f22970fbc90d..6d1475920fc137d140903c4275f0b0a66a667154 100644 (file)
@@ -60,12 +60,3 @@ __free_in6ai (struct in6addrinfo *in6ai)
 {
   /* Nothing to do.  */
 }
-
-
-#if IS_IN (nscd)
-uint32_t
-__bump_nl_timestamp (void)
-{
-  return 0;
-}
-#endif
index 6ccc0e8691568546885d606d21b8b19dfb313949..8a3c83a3bbd5487a712792f69aa12a8201a11d88 100644 (file)
@@ -192,6 +192,7 @@ tests := \
   tst-fchownat \
   tst-fcntl \
   tst-fcntl-lock \
+  tst-fcntl-lock-lfs \
   tst-fstatat \
   tst-fts \
   tst-fts-lfs \
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>
index 1d8ad612e94ecf81c6320779f5d9bc44cf7cc9ea..34f7e15f1c25d6007b59019d184c25751bc4ae3b 100644 (file)
@@ -20,6 +20,7 @@
 #include <libioP.h>
 #include <stdio.h>
 #include <ldsodefs.h>
+#include <array_length.h>
 #include <pointer_guard.h>
 #include <libio-macros.h>
 
@@ -88,7 +89,7 @@
 # pragma weak __wprintf_buffer_as_file_xsputn
 #endif
 
-const struct _IO_jump_t __io_vtables[IO_VTABLES_LEN] attribute_relro =
+const struct _IO_jump_t __io_vtables[] attribute_relro =
 {
   /* _IO_str_jumps  */
   [IO_STR_JUMPS] =
@@ -485,6 +486,8 @@ const struct _IO_jump_t __io_vtables[IO_VTABLES_LEN] attribute_relro =
   },
 #endif
 };
+_Static_assert (array_length (__io_vtables) == IO_VTABLES_NUM,
+                "initializer count");
 
 #ifdef SHARED
 
index f16f6db1c3e384eea7a59e6bd4fa72ec65369b87..9ab8f2e7f3b5e2d2cc6cccbb04bea72cbcdd2e09 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 74216cbcb24cf2d66e3ae7c3001181683882ebca..7dd6cab9c96220501ac63a1b560d98065e858f02 100644 (file)
@@ -44,7 +44,9 @@ subdir-dirs = programs
 vpath %.c programs
 
 tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx \
-  tst-pututxline-lockfail tst-pututxline-cache
+  tst-pututxline-lockfail tst-pututxline-cache tst-utmp-size tst-utmp-size-64
+
+CFLAGS-tst-utmp-size-64.c += -D_FILE_OFFSET_BITS=64 -D_TIME_BITS=64
 
 # Empty compatibility library for old binaries.
 extra-libs      := libutil
diff --git a/login/tst-utmp-size-64.c b/login/tst-utmp-size-64.c
new file mode 100644 (file)
index 0000000..7a581a4
--- /dev/null
@@ -0,0 +1,2 @@
+/* The on-disk layout must not change in time64 mode.  */
+#include "tst-utmp-size.c"
diff --git a/login/tst-utmp-size.c b/login/tst-utmp-size.c
new file mode 100644 (file)
index 0000000..1b7f7ff
--- /dev/null
@@ -0,0 +1,33 @@
+/* Check expected sizes of struct utmp, struct utmpx, struct lastlog.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <utmp.h>
+#include <utmpx.h>
+#include <utmp-size.h>
+
+static int
+do_test (void)
+{
+  _Static_assert (sizeof (struct utmp) == UTMP_SIZE, "struct utmp size");
+  _Static_assert (sizeof (struct utmpx) == UTMP_SIZE, "struct utmpx size");
+  _Static_assert (sizeof (struct lastlog) == LASTLOG_SIZE,
+                  "struct lastlog size");
+  return 0;
+}
+
+#include <support/test-driver.c>
index 6f03955ff24e1bb3df0ee71c96606ecea2ce744a..82b09adb47ba0acdfee69d937562497ea090e5fb 100644 (file)
@@ -820,7 +820,7 @@ arena_get2 (size_t size, mstate avoid_arena)
             narenas_limit = mp_.arena_max;
           else if (narenas > mp_.arena_test)
             {
-              int n = __get_nprocs_sched ();
+              int n = __get_nprocs ();
 
               if (n >= 1)
                 narenas_limit = NARENAS_FROM_NCORES (n);
index e2f1a615a4fc7b036e188a28de9cfb132b2351df..d0bbbf371048ee8aa8a30c03b189cb268b8ad9e4 100644 (file)
@@ -1086,6 +1086,11 @@ typedef struct malloc_chunk* mchunkptr;
 
 static void*  _int_malloc(mstate, size_t);
 static void     _int_free(mstate, mchunkptr, int);
+static void _int_free_merge_chunk (mstate, mchunkptr, INTERNAL_SIZE_T);
+static INTERNAL_SIZE_T _int_free_create_chunk (mstate,
+                                              mchunkptr, INTERNAL_SIZE_T,
+                                              mchunkptr, INTERNAL_SIZE_T);
+static void _int_free_maybe_consolidate (mstate, INTERNAL_SIZE_T);
 static void*  _int_realloc(mstate, mchunkptr, INTERNAL_SIZE_T,
                           INTERNAL_SIZE_T);
 static void*  _int_memalign(mstate, size_t, size_t);
@@ -4483,12 +4488,6 @@ _int_free (mstate av, mchunkptr p, int have_lock)
 {
   INTERNAL_SIZE_T size;        /* its size */
   mfastbinptr *fb;             /* associated fastbin */
-  mchunkptr nextchunk;         /* next contiguous chunk */
-  INTERNAL_SIZE_T nextsize;    /* its size */
-  int nextinuse;               /* true if nextchunk is used */
-  INTERNAL_SIZE_T prevsize;    /* size of previous contiguous chunk */
-  mchunkptr bck;               /* misc temp for linking */
-  mchunkptr fwd;               /* misc temp for linking */
 
   size = chunksize (p);
 
@@ -4637,31 +4636,52 @@ _int_free (mstate av, mchunkptr p, int have_lock)
     if (!have_lock)
       __libc_lock_lock (av->mutex);
 
-    nextchunk = chunk_at_offset(p, size);
-
-    /* Lightweight tests: check whether the block is already the
-       top block.  */
-    if (__glibc_unlikely (p == av->top))
-      malloc_printerr ("double free or corruption (top)");
-    /* Or whether the next chunk is beyond the boundaries of the arena.  */
-    if (__builtin_expect (contiguous (av)
-                         && (char *) nextchunk
-                         >= ((char *) av->top + chunksize(av->top)), 0))
-       malloc_printerr ("double free or corruption (out)");
-    /* Or whether the block is actually not marked used.  */
-    if (__glibc_unlikely (!prev_inuse(nextchunk)))
-      malloc_printerr ("double free or corruption (!prev)");
-
-    nextsize = chunksize(nextchunk);
-    if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
-       || __builtin_expect (nextsize >= av->system_mem, 0))
-      malloc_printerr ("free(): invalid next size (normal)");
+    _int_free_merge_chunk (av, p, size);
 
-    free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
+    if (!have_lock)
+      __libc_lock_unlock (av->mutex);
+  }
+  /*
+    If the chunk was allocated via mmap, release via munmap().
+  */
 
-    /* consolidate backward */
-    if (!prev_inuse(p)) {
-      prevsize = prev_size (p);
+  else {
+    munmap_chunk (p);
+  }
+}
+
+/* Try to merge chunk P of SIZE bytes with its neighbors.  Put the
+   resulting chunk on the appropriate bin list.  P must not be on a
+   bin list yet, and it can be in use.  */
+static void
+_int_free_merge_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size)
+{
+  mchunkptr nextchunk = chunk_at_offset(p, size);
+
+  /* Lightweight tests: check whether the block is already the
+     top block.  */
+  if (__glibc_unlikely (p == av->top))
+    malloc_printerr ("double free or corruption (top)");
+  /* Or whether the next chunk is beyond the boundaries of the arena.  */
+  if (__builtin_expect (contiguous (av)
+                       && (char *) nextchunk
+                       >= ((char *) av->top + chunksize(av->top)), 0))
+    malloc_printerr ("double free or corruption (out)");
+  /* Or whether the block is actually not marked used.  */
+  if (__glibc_unlikely (!prev_inuse(nextchunk)))
+    malloc_printerr ("double free or corruption (!prev)");
+
+  INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
+  if (__builtin_expect (chunksize_nomask (nextchunk) <= CHUNK_HDR_SZ, 0)
+      || __builtin_expect (nextsize >= av->system_mem, 0))
+    malloc_printerr ("free(): invalid next size (normal)");
+
+  free_perturb (chunk2mem(p), size - CHUNK_HDR_SZ);
+
+  /* Consolidate backward.  */
+  if (!prev_inuse(p))
+    {
+      INTERNAL_SIZE_T prevsize = prev_size (p);
       size += prevsize;
       p = chunk_at_offset(p, -((long) prevsize));
       if (__glibc_unlikely (chunksize(p) != prevsize))
@@ -4669,9 +4689,25 @@ _int_free (mstate av, mchunkptr p, int have_lock)
       unlink_chunk (av, p);
     }
 
-    if (nextchunk != av->top) {
+  /* Write the chunk header, maybe after merging with the following chunk.  */
+  size = _int_free_create_chunk (av, p, size, nextchunk, nextsize);
+  _int_free_maybe_consolidate (av, size);
+}
+
+/* Create a chunk at P of SIZE bytes, with SIZE potentially increased
+   to cover the immediately following chunk NEXTCHUNK of NEXTSIZE
+   bytes (if NEXTCHUNK is unused).  The chunk at P is not actually
+   read and does not have to be initialized.  After creation, it is
+   placed on the appropriate bin list.  The function returns the size
+   of the new chunk.  */
+static INTERNAL_SIZE_T
+_int_free_create_chunk (mstate av, mchunkptr p, INTERNAL_SIZE_T size,
+                       mchunkptr nextchunk, INTERNAL_SIZE_T nextsize)
+{
+  if (nextchunk != av->top)
+    {
       /* get and clear inuse bit */
-      nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
+      bool nextinuse = inuse_bit_at_offset (nextchunk, nextsize);
 
       /* consolidate forward */
       if (!nextinuse) {
@@ -4686,8 +4722,8 @@ _int_free (mstate av, mchunkptr p, int have_lock)
        been given one chance to be used in malloc.
       */
 
-      bck = unsorted_chunks(av);
-      fwd = bck->fd;
+      mchunkptr bck = unsorted_chunks (av);
+      mchunkptr fwd = bck->fd;
       if (__glibc_unlikely (fwd->bk != bck))
        malloc_printerr ("free(): corrupted unsorted chunks");
       p->fd = fwd;
@@ -4706,61 +4742,52 @@ _int_free (mstate av, mchunkptr p, int have_lock)
       check_free_chunk(av, p);
     }
 
-    /*
-      If the chunk borders the current high end of memory,
-      consolidate into top
-    */
-
-    else {
+  else
+    {
+      /* If the chunk borders the current high end of memory,
+        consolidate into top.  */
       size += nextsize;
       set_head(p, size | PREV_INUSE);
       av->top = p;
       check_chunk(av, p);
     }
 
-    /*
-      If freeing a large space, consolidate possibly-surrounding
-      chunks. Then, if the total unused topmost memory exceeds trim
-      threshold, ask malloc_trim to reduce top.
-
-      Unless max_fast is 0, we don't know if there are fastbins
-      bordering top, so we cannot tell for sure whether threshold
-      has been reached unless fastbins are consolidated.  But we
-      don't want to consolidate on each free.  As a compromise,
-      consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD
-      is reached.
-    */
+  return size;
+}
 
-    if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) {
+/* If freeing a large space, consolidate possibly-surrounding
+   chunks.  Then, if the total unused topmost memory exceeds trim
+   threshold, ask malloc_trim to reduce top.  */
+static void
+_int_free_maybe_consolidate (mstate av, INTERNAL_SIZE_T size)
+{
+  /* Unless max_fast is 0, we don't know if there are fastbins
+     bordering top, so we cannot tell for sure whether threshold has
+     been reached unless fastbins are consolidated.  But we don't want
+     to consolidate on each free.  As a compromise, consolidation is
+     performed if FASTBIN_CONSOLIDATION_THRESHOLD is reached.  */
+  if (size >= FASTBIN_CONSOLIDATION_THRESHOLD)
+    {
       if (atomic_load_relaxed (&av->have_fastchunks))
        malloc_consolidate(av);
 
-      if (av == &main_arena) {
+      if (av == &main_arena)
+       {
 #ifndef MORECORE_CANNOT_TRIM
-       if ((unsigned long)(chunksize(av->top)) >=
-           (unsigned long)(mp_.trim_threshold))
-         systrim(mp_.top_pad, av);
+         if (chunksize (av->top) >= mp_.trim_threshold)
+           systrim (mp_.top_pad, av);
 #endif
-      } else {
-       /* Always try heap_trim(), even if the top chunk is not
-          large, because the corresponding heap might go away.  */
-       heap_info *heap = heap_for_ptr(top(av));
+       }
+      else
+       {
+         /* Always try heap_trim, even if the top chunk is not large,
+            because the corresponding heap might go away.  */
+         heap_info *heap = heap_for_ptr (top (av));
 
-       assert(heap->ar_ptr == av);
-       heap_trim(heap, mp_.top_pad);
-      }
+         assert (heap->ar_ptr == av);
+         heap_trim (heap, mp_.top_pad);
+       }
     }
-
-    if (!have_lock)
-      __libc_lock_unlock (av->mutex);
-  }
-  /*
-    If the chunk was allocated via mmap, release via munmap().
-  */
-
-  else {
-    munmap_chunk (p);
-  }
 }
 
 /*
@@ -4999,42 +5026,6 @@ _int_realloc (mstate av, mchunkptr oldp, INTERNAL_SIZE_T oldsize,
    ------------------------------ memalign ------------------------------
  */
 
-/* Returns 0 if the chunk is not and does not contain the requested
-   aligned sub-chunk, else returns the amount of "waste" from
-   trimming.  NB is the *chunk* byte size, not the user byte
-   size.  */
-static size_t
-chunk_ok_for_memalign (mchunkptr p, size_t alignment, size_t nb)
-{
-  void *m = chunk2mem (p);
-  INTERNAL_SIZE_T size = chunksize (p);
-  void *aligned_m = m;
-
-  if (__glibc_unlikely (misaligned_chunk (p)))
-    malloc_printerr ("_int_memalign(): unaligned chunk detected");
-
-  aligned_m = PTR_ALIGN_UP (m, alignment);
-
-  INTERNAL_SIZE_T front_extra = (intptr_t) aligned_m - (intptr_t) m;
-
-  /* We can't trim off the front as it's too small.  */
-  if (front_extra > 0 && front_extra < MINSIZE)
-    return 0;
-
-  /* If it's a perfect fit, it's an exception to the return value rule
-     (we would return zero waste, which looks like "not usable"), so
-     handle it here by returning a small non-zero value instead.  */
-  if (size == nb && front_extra == 0)
-    return 1;
-
-  /* If the block we need fits in the chunk, calculate total waste.  */
-  if (size > nb + front_extra)
-    return size - nb;
-
-  /* Can't use this chunk.  */
-  return 0;
-}
-
 /* BYTES is user requested bytes, not requested chunksize bytes.  */
 static void *
 _int_memalign (mstate av, size_t alignment, size_t bytes)
@@ -5049,7 +5040,6 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
   mchunkptr remainder;            /* spare room at end to split off */
   unsigned long remainder_size;   /* its size */
   INTERNAL_SIZE_T size;
-  mchunkptr victim;
 
   nb = checked_request2size (bytes);
   if (nb == 0)
@@ -5068,129 +5058,13 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
      we don't find anything in those bins, the common malloc code will
      scan starting at 2x.  */
 
-  /* This will be set if we found a candidate chunk.  */
-  victim = NULL;
+  /* Call malloc with worst case padding to hit alignment. */
+  m = (char *) (_int_malloc (av, nb + alignment + MINSIZE));
 
-  /* Fast bins are singly-linked, hard to remove a chunk from the middle
-     and unlikely to meet our alignment requirements.  We have not done
-     any experimentation with searching for aligned fastbins.  */
-
-  if (av != NULL)
-    {
-      int first_bin_index;
-      int first_largebin_index;
-      int last_bin_index;
-
-      if (in_smallbin_range (nb))
-       first_bin_index = smallbin_index (nb);
-      else
-       first_bin_index = largebin_index (nb);
+  if (m == 0)
+    return 0;           /* propagate failure */
 
-      if (in_smallbin_range (nb * 2))
-       last_bin_index = smallbin_index (nb * 2);
-      else
-       last_bin_index = largebin_index (nb * 2);
-
-      first_largebin_index = largebin_index (MIN_LARGE_SIZE);
-
-      int victim_index;                 /* its bin index */
-
-      for (victim_index = first_bin_index;
-          victim_index < last_bin_index;
-          victim_index ++)
-       {
-         victim = NULL;
-
-         if (victim_index < first_largebin_index)
-           {
-             /* Check small bins.  Small bin chunks are doubly-linked despite
-                being the same size.  */
-
-             mchunkptr fwd;                    /* misc temp for linking */
-             mchunkptr bck;                    /* misc temp for linking */
-
-             bck = bin_at (av, victim_index);
-             fwd = bck->fd;
-             while (fwd != bck)
-               {
-                 if (chunk_ok_for_memalign (fwd, alignment, nb) > 0)
-                   {
-                     victim = fwd;
-
-                     /* Unlink it */
-                     victim->fd->bk = victim->bk;
-                     victim->bk->fd = victim->fd;
-                     break;
-                   }
-
-                 fwd = fwd->fd;
-               }
-           }
-         else
-           {
-             /* Check large bins.  */
-             mchunkptr fwd;                    /* misc temp for linking */
-             mchunkptr bck;                    /* misc temp for linking */
-             mchunkptr best = NULL;
-             size_t best_size = 0;
-
-             bck = bin_at (av, victim_index);
-             fwd = bck->fd;
-
-             while (fwd != bck)
-               {
-                 int extra;
-
-                 if (chunksize (fwd) < nb)
-                   break;
-                 extra = chunk_ok_for_memalign (fwd, alignment, nb);
-                 if (extra > 0
-                     && (extra <= best_size || best == NULL))
-                   {
-                     best = fwd;
-                     best_size = extra;
-                   }
-
-                 fwd = fwd->fd;
-               }
-             victim = best;
-
-             if (victim != NULL)
-               {
-                 unlink_chunk (av, victim);
-                 break;
-               }
-           }
-
-         if (victim != NULL)
-           break;
-       }
-    }
-
-  /* Strategy: find a spot within that chunk that meets the alignment
-     request, and then possibly free the leading and trailing space.
-     This strategy is incredibly costly and can lead to external
-     fragmentation if header and footer chunks are unused.  */
-
-  if (victim != NULL)
-    {
-      p = victim;
-      m = chunk2mem (p);
-      set_inuse (p);
-      if (av != &main_arena)
-       set_non_main_arena (p);
-    }
-  else
-    {
-      /* Call malloc with worst case padding to hit alignment. */
-
-      m = (char *) (_int_malloc (av, nb + alignment + MINSIZE));
-
-      if (m == 0)
-       return 0;           /* propagate failure */
-
-      p = mem2chunk (m);
-    }
+  p = mem2chunk (m);
 
   if ((((unsigned long) (m)) % alignment) != 0)   /* misaligned */
     {
@@ -5221,7 +5095,7 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
                 (av != &main_arena ? NON_MAIN_ARENA : 0));
       set_inuse_bit_at_offset (newp, newsize);
       set_head_size (p, leadsize | (av != &main_arena ? NON_MAIN_ARENA : 0));
-      _int_free (av, p, 1);
+      _int_free_merge_chunk (av, p, leadsize);
       p = newp;
 
       assert (newsize >= nb &&
@@ -5232,15 +5106,27 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
   if (!chunk_is_mmapped (p))
     {
       size = chunksize (p);
-      if ((unsigned long) (size) > (unsigned long) (nb + MINSIZE))
+      mchunkptr nextchunk = chunk_at_offset(p, size);
+      INTERNAL_SIZE_T nextsize = chunksize(nextchunk);
+      if (size > nb)
         {
           remainder_size = size - nb;
-          remainder = chunk_at_offset (p, nb);
-          set_head (remainder, remainder_size | PREV_INUSE |
-                    (av != &main_arena ? NON_MAIN_ARENA : 0));
-          set_head_size (p, nb);
-          _int_free (av, remainder, 1);
-        }
+         if (remainder_size >= MINSIZE
+             || nextchunk == av->top
+             || !inuse_bit_at_offset (nextchunk, nextsize))
+           {
+             /* We can only give back the tail if it is larger than
+                MINSIZE, or if the following chunk is unused (top
+                chunk or unused in-heap chunk).  Otherwise we would
+                create a chunk that is smaller than MINSIZE.  */
+             remainder = chunk_at_offset (p, nb);
+             set_head_size (p, nb);
+             remainder_size = _int_free_create_chunk (av, remainder,
+                                                      remainder_size,
+                                                      nextchunk, nextsize);
+             _int_free_maybe_consolidate (av, remainder_size);
+           }
+       }
     }
 
   check_inuse_chunk (av, p);
index f229283dbf73d4ab7e4fe41c5b193e76444fe312..ecd6fa249eb38df7f8f741de67b8291f014020fb 100644 (file)
@@ -86,7 +86,8 @@ do_test (void)
       TEST_VERIFY (tcache_allocs[i].ptr1 == tcache_allocs[i].ptr2);
     }
 
-  /* Test for non-head tcache hits.  */
+  /* Test for non-head tcache hits.  This exercises the memalign
+     scanning code to find matching allocations.  */
   for (i = 0; i < array_length (ptr); ++ i)
     {
       if (i == 4)
@@ -113,7 +114,9 @@ do_test (void)
   free (p);
   TEST_VERIFY (count > 0);
 
-  /* Large bins test.  */
+  /* Large bins test.  This verifies that the over-allocated parts
+     that memalign releases for future allocations can be reused by
+     memalign itself at least in some cases.  */
 
   for (i = 0; i < LN; ++ i)
     {
index fe0d49c1de5c8a0cf51d84ce4455bd87587b8046..90b31952c59e5d0c7a94f60e3843caec34370e22 100644 (file)
@@ -289,7 +289,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)
@@ -351,6 +354,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 5f36adc0e8f12588ce07b42af8301a0ec518c4e9..23cc11207480732a6507891557e219f60769b66f 100644 (file)
@@ -44,12 +44,6 @@ weak_alias (__get_nprocs, get_nprocs)
 link_warning (get_nprocs, "warning: get_nprocs will always return 1")
 
 
-int
-__get_nprocs_sched (void)
-{
-  return 1;
-}
-
 long int
 __get_phys_pages (void)
 {
index 1b8cb722c51981a88b5964a4ce51843ae7ac62ca..4af87f54fdbe49bec65c637cab3a6e2397fe33ba 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 */
@@ -124,8 +125,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;
 
@@ -177,29 +179,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)
     {
@@ -209,25 +237,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;
         }
     }
 
index 355dbea05c78a9dfa0b65f507a8a5789bde659a6..0d3729eac076b86db02e267761876cf2001ae43d 100644 (file)
 #ifndef RWF_APPEND
 # define RWF_APPEND 0
 #endif
+#ifndef RWF_NOAPPEND
+# define RWF_NOAPPEND 0
+#endif
 #define RWF_SUPPORTED  (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT \
-                        | RWF_APPEND)
+                        | RWF_APPEND | RWF_NOAPPEND)
 
 /* Generic uio_lim.h does not define IOV_MAX.  */
 #ifndef IOV_MAX
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 2a0489f4cfd4437c7278d371922132b29a1c71c4..16b6460ee9c81546966d0eb2625ad79039327d07 100644 (file)
@@ -35,7 +35,7 @@ nscd-modules := nscd connections pwdcache getpwnam_r getpwuid_r grpcache \
                getgrnam_r getgrgid_r hstcache gethstbyad_r gethstbynm3_r \
                getsrvbynm_r getsrvbypt_r servicescache \
                dbg_log nscd_conf nscd_stat cache mem nscd_setup_thread \
-               xmalloc xstrdup aicache initgrcache gai res_hconf \
+               xmalloc xstrdup aicache initgrcache res_hconf \
                netgroupcache cachedumper
 
 ifeq ($(build-nscd)$(have-thread-library),yesyes)
index a405a44a9bd766af71a41301e23d213dc6b8cb88..15693e5090a8040d2b31a91b8c70278c390e282d 100644 (file)
@@ -256,6 +256,17 @@ int inotify_fd = -1;
 #ifdef HAVE_NETLINK
 /* Descriptor for netlink status updates.  */
 static int nl_status_fd = -1;
+
+static uint32_t
+__bump_nl_timestamp (void)
+{
+  static uint32_t nl_timestamp;
+
+  if (atomic_fetch_add_relaxed (&nl_timestamp, 1) + 1 == 0)
+    atomic_fetch_add_relaxed (&nl_timestamp, 1);
+
+  return nl_timestamp;
+}
 #endif
 
 /* Number of times clients had to wait.  */
diff --git a/nscd/gai.c b/nscd/gai.c
deleted file mode 100644 (file)
index e29f3fe..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright (C) 2004-2023 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published
-   by the Free Software Foundation; version 2 of the License, or
-   (at your option) any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
-
-#include <alloca.h>
-#include <sys/stat.h>
-
-/* This file uses the getaddrinfo code but it compiles it without NSCD
-   support.  We just need a few symbol renames.  */
-#define __ioctl ioctl
-#define __getsockname getsockname
-#define __socket socket
-#define __recvmsg recvmsg
-#define __bind bind
-#define __sendto sendto
-#define __strchrnul strchrnul
-#define __getline getline
-#define __qsort_r qsort_r
-/* nscd uses 1MB or 2MB thread stacks.  */
-#define __libc_use_alloca(size) (size <= __MAX_ALLOCA_CUTOFF)
-#define __getifaddrs getifaddrs
-#define __freeifaddrs freeifaddrs
-#undef __fstat64
-#define __fstat64 fstat64
-#undef __stat64
-#define __stat64 stat64
-
-/* We are nscd, so we don't want to be talking to ourselves.  */
-#undef  USE_NSCD
-
-#include <getaddrinfo.c>
-
-/* Support code.  */
-#include <check_pf.c>
-#include <check_native.c>
-
-/* Some variables normally defined in libc.  */
-nss_action_list __nss_hosts_database attribute_hidden;
index 06b7d7b6ca86453ba22fc28ff127ca92ae4b9c95..a63b260fdb1a988738e1c6335bcb2d597be065a7 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/mman.h>
+#include <scratch_buffer.h>
 
 #include "../inet/netgroup.h"
 #include "nscd.h"
@@ -65,6 +66,16 @@ struct dataset
   char strdata[0];
 };
 
+/* Send a notfound response to FD.  Always returns -1 to indicate an
+   ephemeral error.  */
+static time_t
+send_notfound (int fd)
+{
+  if (fd != -1)
+    TEMP_FAILURE_RETRY (send (fd, &notfound, sizeof (notfound), MSG_NOSIGNAL));
+  return -1;
+}
+
 /* Sends a notfound message and prepares a notfound dataset to write to the
    cache.  Returns true if there was enough memory to allocate the dataset and
    returns the dataset in DATASETP, total bytes to write in TOTALP and the
@@ -83,8 +94,7 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
   total = sizeof (notfound);
   timeout = time (NULL) + db->negtimeout;
 
-  if (fd != -1)
-    TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
+  send_notfound (fd);
 
   dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
   /* If we cannot permanently store the result, so be it.  */
@@ -109,11 +119,78 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
   return cacheable;
 }
 
+struct addgetnetgrentX_scratch
+{
+  /* This is the result that the caller should use.  It can be NULL,
+     point into buffer, or it can be in the cache.  */
+  struct dataset *dataset;
+
+  struct scratch_buffer buffer;
+
+  /* Used internally in addgetnetgrentX as a staging area.  */
+  struct scratch_buffer tmp;
+
+  /* Number of bytes in buffer that are actually used.  */
+  size_t buffer_used;
+};
+
+static void
+addgetnetgrentX_scratch_init (struct addgetnetgrentX_scratch *scratch)
+{
+  scratch->dataset = NULL;
+  scratch_buffer_init (&scratch->buffer);
+  scratch_buffer_init (&scratch->tmp);
+
+  /* Reserve space for the header.  */
+  scratch->buffer_used = sizeof (struct dataset);
+  static_assert (sizeof (struct dataset) < sizeof (scratch->tmp.__space),
+                "initial buffer space");
+  memset (scratch->tmp.data, 0, sizeof (struct dataset));
+}
+
+static void
+addgetnetgrentX_scratch_free (struct addgetnetgrentX_scratch *scratch)
+{
+  scratch_buffer_free (&scratch->buffer);
+  scratch_buffer_free (&scratch->tmp);
+}
+
+/* Copy LENGTH bytes from S into SCRATCH.  Returns NULL if SCRATCH
+   could not be resized, otherwise a pointer to the copy.  */
+static char *
+addgetnetgrentX_append_n (struct addgetnetgrentX_scratch *scratch,
+                         const char *s, size_t length)
+{
+  while (true)
+    {
+      size_t remaining = scratch->buffer.length - scratch->buffer_used;
+      if (remaining >= length)
+       break;
+      if (!scratch_buffer_grow_preserve (&scratch->buffer))
+       return NULL;
+    }
+  char *copy = scratch->buffer.data + scratch->buffer_used;
+  memcpy (copy, s, length);
+  scratch->buffer_used += length;
+  return copy;
+}
+
+/* Copy S into SCRATCH, including its null terminator.  Returns false
+   if SCRATCH could not be resized.  */
+static bool
+addgetnetgrentX_append (struct addgetnetgrentX_scratch *scratch, const char *s)
+{
+  if (s == NULL)
+    s = "";
+  return addgetnetgrentX_append_n (scratch, s, strlen (s) + 1) != NULL;
+}
+
+/* Caller must initialize and free *SCRATCH.  If the return value is
+   negative, this function has sent a notfound response.  */
 static time_t
 addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
                 const char *key, uid_t uid, struct hashentry *he,
-                struct datahead *dh, struct dataset **resultp,
-                void **tofreep)
+                struct datahead *dh, struct addgetnetgrentX_scratch *scratch)
 {
   if (__glibc_unlikely (debug_level > 0))
     {
@@ -132,14 +209,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
 
   char *key_copy = NULL;
   struct __netgrent data;
-  size_t buflen = MAX (1024, sizeof (*dataset) + req->key_len);
-  size_t buffilled = sizeof (*dataset);
-  char *buffer = NULL;
   size_t nentries = 0;
   size_t group_len = strlen (key) + 1;
   struct name_list *first_needed
     = alloca (sizeof (struct name_list) + group_len);
-  *tofreep = NULL;
 
   if (netgroup_database == NULL
       && !__nss_database_get (nss_database_netgroup, &netgroup_database))
@@ -147,12 +220,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
       /* No such service.  */
       cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
                               &key_copy);
-      goto writeout;
+      goto maybe_cache_add;
     }
 
   memset (&data, '\0', sizeof (data));
-  buffer = xmalloc (buflen);
-  *tofreep = buffer;
   first_needed->next = first_needed;
   memcpy (first_needed->name, key, group_len);
   data.needed_groups = first_needed;
@@ -195,8 +266,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
                while (1)
                  {
                    int e;
-                   status = getfct.f (&data, buffer + buffilled,
-                                      buflen - buffilled - req->key_len, &e);
+                   status = getfct.f (&data, scratch->tmp.data,
+                                      scratch->tmp.length, &e);
                    if (status == NSS_STATUS_SUCCESS)
                      {
                        if (data.type == triple_val)
@@ -204,68 +275,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
                            const char *nhost = data.val.triple.host;
                            const char *nuser = data.val.triple.user;
                            const char *ndomain = data.val.triple.domain;
-
-                           size_t hostlen = strlen (nhost ?: "") + 1;
-                           size_t userlen = strlen (nuser ?: "") + 1;
-                           size_t domainlen = strlen (ndomain ?: "") + 1;
-
-                           if (nhost == NULL || nuser == NULL || ndomain == NULL
-                               || nhost > nuser || nuser > ndomain)
-                             {
-                               const char *last = nhost;
-                               if (last == NULL
-                                   || (nuser != NULL && nuser > last))
-                                 last = nuser;
-                               if (last == NULL
-                                   || (ndomain != NULL && ndomain > last))
-                                 last = ndomain;
-
-                               size_t bufused
-                                 = (last == NULL
-                                    ? buffilled
-                                    : last + strlen (last) + 1 - buffer);
-
-                               /* We have to make temporary copies.  */
-                               size_t needed = hostlen + userlen + domainlen;
-
-                               if (buflen - req->key_len - bufused < needed)
-                                 {
-                                   buflen += MAX (buflen, 2 * needed);
-                                   /* Save offset in the old buffer.  We don't
-                                      bother with the NULL check here since
-                                      we'll do that later anyway.  */
-                                   size_t nhostdiff = nhost - buffer;
-                                   size_t nuserdiff = nuser - buffer;
-                                   size_t ndomaindiff = ndomain - buffer;
-
-                                   char *newbuf = xrealloc (buffer, buflen);
-                                   /* Fix up the triplet pointers into the new
-                                      buffer.  */
-                                   nhost = (nhost ? newbuf + nhostdiff
-                                            : NULL);
-                                   nuser = (nuser ? newbuf + nuserdiff
-                                            : NULL);
-                                   ndomain = (ndomain ? newbuf + ndomaindiff
-                                              : NULL);
-                                   *tofreep = buffer = newbuf;
-                                 }
-
-                               nhost = memcpy (buffer + bufused,
-                                               nhost ?: "", hostlen);
-                               nuser = memcpy ((char *) nhost + hostlen,
-                                               nuser ?: "", userlen);
-                               ndomain = memcpy ((char *) nuser + userlen,
-                                                 ndomain ?: "", domainlen);
-                             }
-
-                           char *wp = buffer + buffilled;
-                           wp = memmove (wp, nhost ?: "", hostlen);
-                           wp += hostlen;
-                           wp = memmove (wp, nuser ?: "", userlen);
-                           wp += userlen;
-                           wp = memmove (wp, ndomain ?: "", domainlen);
-                           wp += domainlen;
-                           buffilled = wp - buffer;
+                           if (!(addgetnetgrentX_append (scratch, nhost)
+                                 && addgetnetgrentX_append (scratch, nuser)
+                                 && addgetnetgrentX_append (scratch, ndomain)))
+                             return send_notfound (fd);
                            ++nentries;
                          }
                        else
@@ -317,8 +330,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
                      }
                    else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE)
                      {
-                       buflen *= 2;
-                       *tofreep = buffer = xrealloc (buffer, buflen);
+                       if (!scratch_buffer_grow (&scratch->tmp))
+                         return send_notfound (fd);
                      }
                    else if (status == NSS_STATUS_RETURN
                             || status == NSS_STATUS_NOTFOUND
@@ -348,13 +361,20 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
     {
       cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
                               &key_copy);
-      goto writeout;
+      goto maybe_cache_add;
     }
 
-  total = buffilled;
+  /* Capture the result size without the key appended.   */
+  total = scratch->buffer_used;
+
+  /* Make a copy of the key.  The scratch buffer must not move after
+     this point.  */
+  key_copy = addgetnetgrentX_append_n (scratch, key, req->key_len);
+  if (key_copy == NULL)
+    return send_notfound (fd);
 
   /* Fill in the dataset.  */
-  dataset = (struct dataset *) buffer;
+  dataset = scratch->buffer.data;
   timeout = datahead_init_pos (&dataset->head, total + req->key_len,
                               total - offsetof (struct dataset, resp),
                               he == NULL ? 0 : dh->nreloads + 1,
@@ -363,11 +383,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
   dataset->resp.version = NSCD_VERSION;
   dataset->resp.found = 1;
   dataset->resp.nresults = nentries;
-  dataset->resp.result_len = buffilled - sizeof (*dataset);
-
-  assert (buflen - buffilled >= req->key_len);
-  key_copy = memcpy (buffer + buffilled, key, req->key_len);
-  buffilled += req->key_len;
+  dataset->resp.result_len = total - sizeof (*dataset);
 
   /* Now we can determine whether on refill we have to create a new
      record or not.  */
@@ -398,7 +414,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
     if (__glibc_likely (newp != NULL))
       {
        /* Adjust pointer into the memory block.  */
-       key_copy = (char *) newp + (key_copy - buffer);
+       key_copy = (char *) newp + (key_copy - (char *) dataset);
 
        dataset = memcpy (newp, dataset, total + req->key_len);
        cacheable = true;
@@ -410,14 +426,12 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
   }
 
   if (he == NULL && fd != -1)
-    {
-      /* We write the dataset before inserting it to the database
-        since while inserting this thread might block and so would
-        unnecessarily let the receiver wait.  */
-    writeout:
+    /* We write the dataset before inserting it to the database since
+       while inserting this thread might block and so would
+       unnecessarily let the receiver wait.  */
       writeall (fd, &dataset->resp, dataset->head.recsize);
-    }
 
+ maybe_cache_add:
   if (cacheable)
     {
       /* If necessary, we also propagate the data to disk.  */
@@ -441,7 +455,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
     }
 
  out:
-  *resultp = dataset;
+  scratch->dataset = dataset;
 
   return timeout;
 }
@@ -462,6 +476,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
   if (user != NULL)
     key = strchr (key, '\0') + 1;
   const char *domain = *key++ ? key : NULL;
+  struct addgetnetgrentX_scratch scratch;
+
+  addgetnetgrentX_scratch_init (&scratch);
 
   if (__glibc_unlikely (debug_level > 0))
     {
@@ -477,12 +494,8 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
                                                            group, group_len,
                                                            db, uid);
   time_t timeout;
-  void *tofree;
   if (result != NULL)
-    {
-      timeout = result->head.timeout;
-      tofree = NULL;
-    }
+    timeout = result->head.timeout;
   else
     {
       request_header req_get =
@@ -491,7 +504,10 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
          .key_len = group_len
        };
       timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL,
-                                &result, &tofree);
+                                &scratch);
+      result = scratch.dataset;
+      if (timeout < 0)
+       goto out;
     }
 
   struct indataset
@@ -502,24 +518,26 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
       = (struct indataset *) mempool_alloc (db,
                                            sizeof (*dataset) + req->key_len,
                                            1);
-  struct indataset dataset_mem;
   bool cacheable = true;
   if (__glibc_unlikely (dataset == NULL))
     {
       cacheable = false;
-      dataset = &dataset_mem;
+      /* The alloca is safe because nscd_run_worker verfies that
+        key_len is not larger than MAXKEYLEN.  */
+      dataset = alloca (sizeof (*dataset) + req->key_len);
     }
 
   datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len,
                     sizeof (innetgroup_response_header),
-                    he == NULL ? 0 : dh->nreloads + 1, result->head.ttl);
+                    he == NULL ? 0 : dh->nreloads + 1,
+                    result == NULL ? db->negtimeout : result->head.ttl);
   /* Set the notfound status and timeout based on the result from
      getnetgrent.  */
-  dataset->head.notfound = result->head.notfound;
+  dataset->head.notfound = result == NULL || result->head.notfound;
   dataset->head.timeout = timeout;
 
   dataset->resp.version = NSCD_VERSION;
-  dataset->resp.found = result->resp.found;
+  dataset->resp.found = result != NULL && result->resp.found;
   /* Until we find a matching entry the result is 0.  */
   dataset->resp.result = 0;
 
@@ -567,7 +585,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
       goto out;
     }
 
-  if (he == NULL)
+  /* addgetnetgrentX may have already sent a notfound response.  Do
+     not send another one.  */
+  if (he == NULL && dataset->resp.found)
     {
       /* We write the dataset before inserting it to the database
         since while inserting this thread might block and so would
@@ -601,7 +621,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
     }
 
  out:
-  free (tofree);
+  addgetnetgrentX_scratch_free (&scratch);
   return timeout;
 }
 
@@ -611,11 +631,12 @@ addgetnetgrentX_ignore (struct database_dyn *db, int fd, request_header *req,
                        const char *key, uid_t uid, struct hashentry *he,
                        struct datahead *dh)
 {
-  struct dataset *ignore;
-  void *tofree;
-  time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh,
-                                   &ignore, &tofree);
-  free (tofree);
+  struct addgetnetgrentX_scratch scratch;
+  addgetnetgrentX_scratch_init (&scratch);
+  time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, &scratch);
+  addgetnetgrentX_scratch_free (&scratch);
+  if (timeout < 0)
+    timeout = 0;
   return timeout;
 }
 
@@ -659,5 +680,9 @@ readdinnetgr (struct database_dyn *db, struct hashentry *he,
       .key_len = he->len
     };
 
-  return addinnetgrX (db, -1, &req, db->data + he->key, he->owner, he, dh);
+  time_t timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
+                               he, dh);
+  if (timeout < 0)
+    timeout = 0;
+  return timeout;
 }
index 06fcdc450f1c889887409a0d6a3e87fb8ca0ba58..668ba34b187b5d69db9310dcfc226289a7d146c0 100644 (file)
@@ -82,6 +82,7 @@ tests-container := \
   tst-nss-test3 \
   tst-reload1 \
   tst-reload2 \
+  tst-nss-gai-hv2-canonname \
 # tests-container
 
 # Tests which need libdl
@@ -145,7 +146,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
 
@@ -180,12 +191,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
@@ -195,10 +210,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)
@@ -207,6 +226,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
@@ -215,3 +245,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 054b1fa36ca5b68acb007ecc6307b7a0c5e362b2..2f99eb38625fecc1343c10e1c6669fa747870300 100644 (file)
@@ -102,6 +102,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 \
@@ -293,6 +294,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 1d60c51f5e0ec1aa146872e3af5a4909a7660f57..5d0ab30de6e9da6b1d08b8e7d85bdbfc0e8fa567 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);
index 24172700e19570c23da8df9e7c3763c53d2c7ffe..ca56bc9283e4fb1a440c888cb76de74948fa137a 100644 (file)
@@ -84,6 +84,7 @@
 
 #include <arpa/nameser.h>
 #include <resolv.h>
+#include <resolv/resolv-internal.h>
 
 /* Author: paul vixie, 29may94.  */
 int
@@ -91,7 +92,7 @@ __libc_res_nameinquery (const char *name, int type, int class,
                         const unsigned char *buf, const unsigned char *eom)
 {
   const unsigned char *cp = buf + HFIXEDSZ;
-  int qdcount = ntohs (((HEADER *) buf)->qdcount);
+  int qdcount = ntohs (((UHEADER *) buf)->qdcount);
 
   while (qdcount-- > 0)
     {
index 13a6936c472806c86eeead618facc110aa7106a2..ba1c1d0c0cf6cbf66599e45849b99b8890919fe1 100644 (file)
@@ -83,6 +83,7 @@
  */
 
 #include <resolv.h>
+#include <resolv/resolv-internal.h>
 
 /* Author: paul vixie, 29may94.  */
 int
@@ -102,7 +103,7 @@ __libc_res_queriesmatch (const unsigned char *buf1, const unsigned char *eom1,
      order.  We can compare it with the second buffer's QDCOUNT
      value without doing this.  */
   int qdcount = ((HEADER *) buf1)->qdcount;
-  if (qdcount != ((HEADER *) buf2)->qdcount)
+  if (qdcount != ((UHEADER *) buf2)->qdcount)
     return 0;
 
   qdcount = htons (qdcount);
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 f325c95a44896f524188c2b293f776ed75c2b15a..3694ecd8af32687cbc6172e7bef6af95bbf671ee 100644 (file)
@@ -24,6 +24,7 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
+#include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <malloc.h>
@@ -50,7 +51,11 @@ void dealloc (void *p)
 
 char* alloc (void)
 {
-  return (char *)malloc (8);
+#ifdef PATH_MAX
+  return (char *)malloc (PATH_MAX);
+#else
+  return (char *)malloc (4096);
+#endif
 }
 
 static int
index f7d4bac5a8a906aa7685cfd72422e1f8cdd42149..824cf315ffc3cd1d598b61f5594471ff59dbd8b7 100644 (file)
 DIAG_IGNORE_NEEDS_COMMENT (8, "-Wstringop-truncation");
 #endif
 
+/* When building with fortify enabled, GCC < 12 issues a warning on the
+   fortify strncat wrapper might overflow the destination buffer (the
+   failure is tied to -Werror).
+   Triggered by strncat fortify wrapper when it is enabled.  */
+#if __GNUC_PREREQ (11, 0)
+DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overread");
+#endif
+
 #include <errno.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -52,9 +60,6 @@ DIAG_IGNORE_NEEDS_COMMENT (5.0, "-Wmemset-transposed-args");
 DIAG_IGNORE_NEEDS_COMMENT (9, "-Wrestrict");
 DIAG_IGNORE_NEEDS_COMMENT (7, "-Wstringop-overflow=");
 #endif
-#if __GNUC_PREREQ (11, 0)
-DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overread");
-#endif
 
 
 #define        STREQ(a, b)     (strcmp((a), (b)) == 0)
old mode 100644 (file)
new mode 100755 (executable)
index ca57edc..9606137
@@ -325,9 +325,10 @@ then :
   printf %s "(cached) " >&6
 else $as_nop
   cat > conftest.s <<\EOF
-        ptrue p0.b
+       .arch armv8.2-a+sve
+       ptrue p0.b
 EOF
-if { ac_try='${CC-cc} -c -march=armv8.2-a+sve conftest.s 1>&5'
+if { ac_try='${CC-cc} -c conftest.s 1>&5'
   { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
   (eval $ac_try) 2>&5
   ac_status=$?
index 27874eceb44911e4f5751ca870d37198f37a9869..56d12d661d72689285a23dce5d84bf0182f5b13d 100644 (file)
@@ -90,9 +90,10 @@ LIBC_CONFIG_VAR([aarch64-variant-pcs], [$libc_cv_aarch64_variant_pcs])
 # Check if asm support armv8.2-a+sve
 AC_CACHE_CHECK([for SVE support in assembler], [libc_cv_aarch64_sve_asm], [dnl
 cat > conftest.s <<\EOF
-        ptrue p0.b
+       .arch armv8.2-a+sve
+       ptrue p0.b
 EOF
-if AC_TRY_COMMAND(${CC-cc} -c -march=armv8.2-a+sve conftest.s 1>&AS_MESSAGE_LOG_FD); then
+if AC_TRY_COMMAND(${CC-cc} -c conftest.s 1>&AS_MESSAGE_LOG_FD); then
   libc_cv_aarch64_sve_asm=yes
 else
   libc_cv_aarch64_sve_asm=no
index 50e5da3e7aec3a7b4ef23676c35c34896e8078e6..bbfb7184c3e4277f59178ccf4f9b92814dd7a48d 100644 (file)
@@ -29,7 +29,7 @@
  *
  */
 
-ENTRY_ALIGN (MEMSET, 6)
+ENTRY (MEMSET)
 
        PTR_ARG (0)
        SIZE_ARG (2)
@@ -101,19 +101,19 @@ L(tail64):
        ret
 
 L(try_zva):
-#ifdef ZVA_MACRO
-       zva_macro
-#else
+#ifndef ZVA64_ONLY
        .p2align 3
        mrs     tmp1, dczid_el0
        tbnz    tmp1w, 4, L(no_zva)
        and     tmp1w, tmp1w, 15
        cmp     tmp1w, 4        /* ZVA size is 64 bytes.  */
        b.ne     L(zva_128)
-
+       nop
+#endif
        /* Write the first and last 64 byte aligned block using stp rather
           than using DC ZVA.  This is faster on some cores.
         */
+       .p2align 4
 L(zva_64):
        str     q0, [dst, 16]
        stp     q0, q0, [dst, 32]
@@ -123,7 +123,6 @@ L(zva_64):
        sub     count, dstend, dst      /* Count is now 128 too large.  */
        sub     count, count, 128+64+64 /* Adjust count and bias for loop.  */
        add     dst, dst, 128
-       nop
 1:     dc      zva, dst
        add     dst, dst, 64
        subs    count, count, 64
@@ -134,6 +133,7 @@ L(zva_64):
        stp     q0, q0, [dstend, -32]
        ret
 
+#ifndef ZVA64_ONLY
        .p2align 3
 L(zva_128):
        cmp     tmp1w, 5        /* ZVA size is 128 bytes.  */
index 223777d94e350fdfd1bb82a4b38eea4653d63057..e4720b746859f51502e070ba0c2f308072a49740 100644 (file)
@@ -3,17 +3,19 @@ sysdep_routines += \
   memchr_generic \
   memchr_nosimd \
   memcpy_a64fx \
-  memcpy_falkor \
   memcpy_generic \
+  memcpy_mops \
   memcpy_sve \
   memcpy_thunderx \
   memcpy_thunderx2 \
+  memmove_mops \
   memset_a64fx \
   memset_emag \
-  memset_falkor \
   memset_generic \
   memset_kunpeng \
+  memset_mops \
+  memset_zva64 \
   strlen_asimd \
-  strlen_mte \
+  strlen_generic \
 # sysdep_routines
 endif
index d274f01fdbd1c99d7f872bbdcdc7b2a1cbc7b042..73038ac8102b1ef8a58a51ca19638720f26e6a66 100644 (file)
@@ -36,30 +36,29 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
   IFUNC_IMPL (i, name, memcpy,
              IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_thunderx)
              IFUNC_IMPL_ADD (array, i, memcpy, !bti, __memcpy_thunderx2)
-             IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_falkor)
 #if HAVE_AARCH64_SVE_ASM
              IFUNC_IMPL_ADD (array, i, memcpy, sve, __memcpy_a64fx)
              IFUNC_IMPL_ADD (array, i, memcpy, sve, __memcpy_sve)
 #endif
+             IFUNC_IMPL_ADD (array, i, memcpy, mops, __memcpy_mops)
              IFUNC_IMPL_ADD (array, i, memcpy, 1, __memcpy_generic))
   IFUNC_IMPL (i, name, memmove,
              IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_thunderx)
              IFUNC_IMPL_ADD (array, i, memmove, !bti, __memmove_thunderx2)
-             IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_falkor)
 #if HAVE_AARCH64_SVE_ASM
              IFUNC_IMPL_ADD (array, i, memmove, sve, __memmove_a64fx)
              IFUNC_IMPL_ADD (array, i, memmove, sve, __memmove_sve)
 #endif
+             IFUNC_IMPL_ADD (array, i, memmove, mops, __memmove_mops)
              IFUNC_IMPL_ADD (array, i, memmove, 1, __memmove_generic))
   IFUNC_IMPL (i, name, memset,
-             /* Enable this on non-falkor processors too so that other cores
-                can do a comparative analysis with __memset_generic.  */
-             IFUNC_IMPL_ADD (array, i, memset, (zva_size == 64), __memset_falkor)
-             IFUNC_IMPL_ADD (array, i, memset, (zva_size == 64), __memset_emag)
+             IFUNC_IMPL_ADD (array, i, memset, (zva_size == 64), __memset_zva64)
+             IFUNC_IMPL_ADD (array, i, memset, 1, __memset_emag)
              IFUNC_IMPL_ADD (array, i, memset, 1, __memset_kunpeng)
 #if HAVE_AARCH64_SVE_ASM
              IFUNC_IMPL_ADD (array, i, memset, sve && zva_size == 256, __memset_a64fx)
 #endif
+             IFUNC_IMPL_ADD (array, i, memset, mops, __memset_mops)
              IFUNC_IMPL_ADD (array, i, memset, 1, __memset_generic))
   IFUNC_IMPL (i, name, memchr,
              IFUNC_IMPL_ADD (array, i, memchr, !mte, __memchr_nosimd)
@@ -67,7 +66,7 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
 
   IFUNC_IMPL (i, name, strlen,
              IFUNC_IMPL_ADD (array, i, strlen, !mte, __strlen_asimd)
-             IFUNC_IMPL_ADD (array, i, strlen, 1, __strlen_mte))
+             IFUNC_IMPL_ADD (array, i, strlen, 1, __strlen_generic))
 
   return 0;
 }
index 6de081e3814d55812572c889fb8749e0e4e6222a..daef631e04bb687261b259cf576599edac65955f 100644 (file)
@@ -35,4 +35,8 @@
   bool __attribute__((unused)) mte =                                         \
     MTE_ENABLED ();                                                          \
   bool __attribute__((unused)) sve =                                         \
-    GLRO(dl_aarch64_cpu_features).sve;
+    GLRO(dl_aarch64_cpu_features).sve;                                       \
+  bool __attribute__((unused)) prefer_sve_ifuncs =                           \
+    GLRO(dl_aarch64_cpu_features).prefer_sve_ifuncs;                         \
+  bool __attribute__((unused)) mops =                                        \
+    GLRO(dl_aarch64_cpu_features).mops;
index 57e48375e91edd74ee0a69e747e09d995ae8fd4f..780075189902919345c5eb15cba7ea0929043d6a 100644 (file)
  * Use base integer registers.
  */
 
-#ifndef MEMCHR
-# define MEMCHR __memchr_nosimd
-#endif
-
 /* Arguments and results.  */
 #define srcin          x0
 #define chrin          x1
@@ -62,7 +58,7 @@
 #define REP8_7f                0x7f7f7f7f7f7f7f7f
 
 
-ENTRY_ALIGN (MEMCHR, 6)
+ENTRY (__memchr_nosimd)
 
        PTR_ARG (0)
        SIZE_ARG (2)
@@ -219,5 +215,4 @@ L(none_chr):
        mov     result, 0
        ret
 
-END (MEMCHR)
-libc_hidden_builtin_def (MEMCHR)
+END (__memchr_nosimd)
index 3aae915c5f479fe5426399fbaa2f951d5771a997..e7c7795db68e0a5d89c643d4639e0a2183ca6c6c 100644 (file)
@@ -31,20 +31,23 @@ extern __typeof (__redirect_memcpy) __libc_memcpy;
 extern __typeof (__redirect_memcpy) __memcpy_generic attribute_hidden;
 extern __typeof (__redirect_memcpy) __memcpy_thunderx attribute_hidden;
 extern __typeof (__redirect_memcpy) __memcpy_thunderx2 attribute_hidden;
-extern __typeof (__redirect_memcpy) __memcpy_falkor attribute_hidden;
 extern __typeof (__redirect_memcpy) __memcpy_a64fx attribute_hidden;
 extern __typeof (__redirect_memcpy) __memcpy_sve attribute_hidden;
+extern __typeof (__redirect_memcpy) __memcpy_mops attribute_hidden;
 
 static inline __typeof (__redirect_memcpy) *
 select_memcpy_ifunc (void)
 {
   INIT_ARCH ();
 
+  if (mops)
+    return __memcpy_mops;
+
   if (sve && HAVE_AARCH64_SVE_ASM)
     {
       if (IS_A64FX (midr))
        return __memcpy_a64fx;
-      return __memcpy_sve;
+      return prefer_sve_ifuncs ? __memcpy_sve : __memcpy_generic;
     }
 
   if (IS_THUNDERX (midr))
@@ -53,9 +56,6 @@ select_memcpy_ifunc (void)
   if (IS_THUNDERX2 (midr) || IS_THUNDERX2PA (midr))
     return __memcpy_thunderx2;
 
-  if (IS_FALKOR (midr) || IS_PHECDA (midr))
-    return __memcpy_falkor;
-
   return __memcpy_generic;
 }
 
index f89b5b670a16ceb944eb816d318e02628a239df8..baff7e96d0045dac5a6a7a8d555e997998c978dd 100644 (file)
@@ -39,9 +39,6 @@
 #define vlen8  x8
 
 #if HAVE_AARCH64_SVE_ASM
-# if IS_IN (libc)
-#  define MEMCPY __memcpy_a64fx
-#  define MEMMOVE __memmove_a64fx
 
        .arch armv8.2-a+sve
 
@@ -97,7 +94,7 @@
 #undef BTI_C
 #define BTI_C
 
-ENTRY (MEMCPY)
+ENTRY (__memcpy_a64fx)
 
        PTR_ARG (0)
        PTR_ARG (1)
@@ -234,11 +231,10 @@ L(last_bytes):
        st1b    z3.b, p0, [dstend, -1, mul vl]
        ret
 
-END (MEMCPY)
-libc_hidden_builtin_def (MEMCPY)
+END (__memcpy_a64fx)
 
 
-ENTRY_ALIGN (MEMMOVE, 4)
+ENTRY_ALIGN (__memmove_a64fx, 4)
 
        PTR_ARG (0)
        PTR_ARG (1)
@@ -307,7 +303,5 @@ L(full_overlap):
        mov     dst, dstin
        b       L(last_bytes)
 
-END (MEMMOVE)
-libc_hidden_builtin_def (MEMMOVE)
-# endif /* IS_IN (libc) */
+END (__memmove_a64fx)
 #endif /* HAVE_AARCH64_SVE_ASM */
diff --git a/sysdeps/aarch64/multiarch/memcpy_falkor.S b/sysdeps/aarch64/multiarch/memcpy_falkor.S
deleted file mode 100644 (file)
index ec0e4ad..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-/* Optimized memcpy for Qualcomm Falkor processor.
-   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/>.  */
-
-#include <sysdep.h>
-
-/* Assumptions:
-
-   ARMv8-a, AArch64, falkor, unaligned accesses.  */
-
-#define dstin  x0
-#define src    x1
-#define count  x2
-#define dst    x3
-#define srcend x4
-#define dstend x5
-#define tmp1   x14
-#define A_x    x6
-#define B_x    x7
-#define A_w    w6
-#define B_w    w7
-
-#define A_q    q0
-#define B_q    q1
-#define C_q    q2
-#define D_q    q3
-#define E_q    q4
-#define F_q    q5
-#define G_q    q6
-#define H_q    q7
-#define Q_q    q6
-#define S_q    q22
-
-/* Copies are split into 3 main cases:
-
-   1. Small copies of up to 32 bytes
-   2. Medium copies of 33..128 bytes which are fully unrolled
-   3. Large copies of more than 128 bytes.
-
-   Large copies align the source to a quad word and use an unrolled loop
-   processing 64 bytes per iteration.
-
-   FALKOR-SPECIFIC DESIGN:
-
-   The smallest copies (32 bytes or less) focus on optimal pipeline usage,
-   which is why the redundant copies of 0-3 bytes have been replaced with
-   conditionals, since the former would unnecessarily break across multiple
-   issue groups.  The medium copy group has been enlarged to 128 bytes since
-   bumping up the small copies up to 32 bytes allows us to do that without
-   cost and also allows us to reduce the size of the prep code before loop64.
-
-   The copy loop uses only one register q0.  This is to ensure that all loads
-   hit a single hardware prefetcher which can get correctly trained to prefetch
-   a single stream.
-
-   The non-temporal stores help optimize cache utilization.  */
-
-#if IS_IN (libc)
-ENTRY_ALIGN (__memcpy_falkor, 6)
-
-       PTR_ARG (0)
-       PTR_ARG (1)
-       SIZE_ARG (2)
-
-       cmp     count, 32
-       add     srcend, src, count
-       add     dstend, dstin, count
-       b.ls    L(copy32)
-       cmp     count, 128
-       b.hi    L(copy_long)
-
-       /* Medium copies: 33..128 bytes.  */
-L(copy128):
-       sub     tmp1, count, 1
-       ldr     A_q, [src]
-       ldr     B_q, [src, 16]
-       ldr     C_q, [srcend, -32]
-       ldr     D_q, [srcend, -16]
-       tbz     tmp1, 6, 1f
-       ldr     E_q, [src, 32]
-       ldr     F_q, [src, 48]
-       ldr     G_q, [srcend, -64]
-       ldr     H_q, [srcend, -48]
-       str     G_q, [dstend, -64]
-       str     H_q, [dstend, -48]
-       str     E_q, [dstin, 32]
-       str     F_q, [dstin, 48]
-1:
-       str     A_q, [dstin]
-       str     B_q, [dstin, 16]
-       str     C_q, [dstend, -32]
-       str     D_q, [dstend, -16]
-       ret
-
-       .p2align 4
-       /* Small copies: 0..32 bytes.  */
-L(copy32):
-       /* 16-32 */
-       cmp     count, 16
-       b.lo    1f
-       ldr     A_q, [src]
-       ldr     B_q, [srcend, -16]
-       str     A_q, [dstin]
-       str     B_q, [dstend, -16]
-       ret
-       .p2align 4
-1:
-       /* 8-15 */
-       tbz     count, 3, 1f
-       ldr     A_x, [src]
-       ldr     B_x, [srcend, -8]
-       str     A_x, [dstin]
-       str     B_x, [dstend, -8]
-       ret
-       .p2align 4
-1:
-       /* 4-7 */
-       tbz     count, 2, 1f
-       ldr     A_w, [src]
-       ldr     B_w, [srcend, -4]
-       str     A_w, [dstin]
-       str     B_w, [dstend, -4]
-       ret
-       .p2align 4
-1:
-       /* 2-3 */
-       tbz     count, 1, 1f
-       ldrh    A_w, [src]
-       ldrh    B_w, [srcend, -2]
-       strh    A_w, [dstin]
-       strh    B_w, [dstend, -2]
-       ret
-       .p2align 4
-1:
-       /* 0-1 */
-       tbz     count, 0, 1f
-       ldrb    A_w, [src]
-       strb    A_w, [dstin]
-1:
-       ret
-
-       /* Align SRC to 16 bytes and copy; that way at least one of the
-          accesses is aligned throughout the copy sequence.
-
-          The count is off by 0 to 15 bytes, but this is OK because we trim
-          off the last 64 bytes to copy off from the end.  Due to this the
-          loop never runs out of bounds.  */
-
-       .p2align 4
-       nop             /* Align loop64 below.  */
-L(copy_long):
-       ldr     A_q, [src]
-       sub     count, count, 64 + 16
-       and     tmp1, src, 15
-       str     A_q, [dstin]
-       bic     src, src, 15
-       sub     dst, dstin, tmp1
-       add     count, count, tmp1
-
-L(loop64):
-       ldr     A_q, [src, 16]!
-       str     A_q, [dst, 16]
-       ldr     A_q, [src, 16]!
-       subs    count, count, 64
-       str     A_q, [dst, 32]
-       ldr     A_q, [src, 16]!
-       str     A_q, [dst, 48]
-       ldr     A_q, [src, 16]!
-       str     A_q, [dst, 64]!
-       b.hi    L(loop64)
-
-       /* Write the last full set of 64 bytes.  The remainder is at most 64
-          bytes, so it is safe to always copy 64 bytes from the end even if
-          there is just 1 byte left.  */
-       ldr     E_q, [srcend, -64]
-       str     E_q, [dstend, -64]
-       ldr     D_q, [srcend, -48]
-       str     D_q, [dstend, -48]
-       ldr     C_q, [srcend, -32]
-       str     C_q, [dstend, -32]
-       ldr     B_q, [srcend, -16]
-       str     B_q, [dstend, -16]
-       ret
-
-END (__memcpy_falkor)
-libc_hidden_builtin_def (__memcpy_falkor)
-
-
-/* RATIONALE:
-
-   The move has 4 distinct parts:
-   * Small moves of 32 bytes and under.
-   * Medium sized moves of 33-128 bytes (fully unrolled).
-   * Large moves where the source address is higher than the destination
-     (forward copies)
-   * Large moves where the destination address is higher than the source
-     (copy backward, or move).
-
-   We use only two registers q6 and q22 for the moves and move 32 bytes at a
-   time to correctly train the hardware prefetcher for better throughput.
-
-   For small and medium cases memcpy is used.  */
-
-ENTRY_ALIGN (__memmove_falkor, 6)
-
-       PTR_ARG (0)
-       PTR_ARG (1)
-       SIZE_ARG (2)
-
-       cmp     count, 32
-       add     srcend, src, count
-       add     dstend, dstin, count
-       b.ls    L(copy32)
-       cmp     count, 128
-       b.ls    L(copy128)
-       sub     tmp1, dstin, src
-       ccmp    tmp1, count, 2, hi
-       b.lo    L(move_long)
-
-       /* CASE: Copy Forwards
-
-          Align src to 16 byte alignment so that we don't cross cache line
-          boundaries on both loads and stores.  There are at least 128 bytes
-          to copy, so copy 16 bytes unaligned and then align.  The loop
-          copies 32 bytes per iteration and prefetches one iteration ahead.  */
-
-       ldr     S_q, [src]
-       and     tmp1, src, 15
-       bic     src, src, 15
-       sub     dst, dstin, tmp1
-       add     count, count, tmp1      /* Count is now 16 too large.  */
-       ldr     Q_q, [src, 16]!
-       str     S_q, [dstin]
-       ldr     S_q, [src, 16]!
-       sub     count, count, 32 + 32 + 16      /* Test and readjust count.  */
-
-       .p2align 4
-1:
-       subs    count, count, 32
-       str     Q_q, [dst, 16]
-       ldr     Q_q, [src, 16]!
-       str     S_q, [dst, 32]!
-       ldr     S_q, [src, 16]!
-       b.hi    1b
-
-       /* Copy 32 bytes from the end before writing the data prefetched in the
-          last loop iteration.  */
-2:
-       ldr     B_q, [srcend, -32]
-       ldr     C_q, [srcend, -16]
-       str     Q_q, [dst, 16]
-       str     S_q, [dst, 32]
-       str     B_q, [dstend, -32]
-       str     C_q, [dstend, -16]
-       ret
-
-       /* CASE: Copy Backwards
-
-          Align srcend to 16 byte alignment so that we don't cross cache line
-          boundaries on both loads and stores.  There are at least 128 bytes
-          to copy, so copy 16 bytes unaligned and then align.  The loop
-          copies 32 bytes per iteration and prefetches one iteration ahead.  */
-
-       .p2align 4
-       nop
-       nop
-L(move_long):
-       cbz     tmp1, 3f  /* Return early if src == dstin */
-       ldr     S_q, [srcend, -16]
-       and     tmp1, srcend, 15
-       sub     srcend, srcend, tmp1
-       ldr     Q_q, [srcend, -16]!
-       str     S_q, [dstend, -16]
-       sub     count, count, tmp1
-       ldr     S_q, [srcend, -16]!
-       sub     dstend, dstend, tmp1
-       sub     count, count, 32 + 32
-
-1:
-       subs    count, count, 32
-       str     Q_q, [dstend, -16]
-       ldr     Q_q, [srcend, -16]!
-       str     S_q, [dstend, -32]!
-       ldr     S_q, [srcend, -16]!
-       b.hi    1b
-
-       /* Copy 32 bytes from the start before writing the data prefetched in the
-          last loop iteration.  */
-
-       ldr     B_q, [src, 16]
-       ldr     C_q, [src]
-       str     Q_q, [dstend, -16]
-       str     S_q, [dstend, -32]
-       str     B_q, [dstin, 16]
-       str     C_q, [dstin]
-3:     ret
-
-END (__memmove_falkor)
-libc_hidden_builtin_def (__memmove_falkor)
-#endif
diff --git a/sysdeps/aarch64/multiarch/memcpy_mops.S b/sysdeps/aarch64/multiarch/memcpy_mops.S
new file mode 100644 (file)
index 0000000..4685629
--- /dev/null
@@ -0,0 +1,39 @@
+/* Optimized memcpy for MOPS.
+   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 <sysdep.h>
+
+/* Assumptions:
+ *
+ * AArch64, MOPS.
+ *
+ */
+
+ENTRY (__memcpy_mops)
+       PTR_ARG (0)
+       PTR_ARG (1)
+       SIZE_ARG (2)
+
+       mov     x3, x0
+       .inst   0x19010443      /* cpyfp   [x3]!, [x1]!, x2!  */
+       .inst   0x19410443      /* cpyfm   [x3]!, [x1]!, x2!  */
+       .inst   0x19810443      /* cpyfe   [x3]!, [x1]!, x2!  */
+       ret
+
+END (__memcpy_mops)
index d11be6a44301af4bfd7fa4900555b769dc58d34d..2f14f9136698c5b3130482e2c15c5d4ceb198bda 100644 (file)
@@ -141,7 +141,6 @@ L(copy64_from_end):
        ret
 
 END (__memcpy_sve)
-libc_hidden_builtin_def (__memcpy_sve)
 
 
 ENTRY (__memmove_sve)
@@ -208,5 +207,4 @@ L(return):
        ret
 
 END (__memmove_sve)
-libc_hidden_builtin_def (__memmove_sve)
 #endif
index 366287587f4aec5c00c35320fd1f862e45400d08..14269b1a47137f178e289e31026ab2874ccc3173 100644 (file)
    Overlapping large forward memmoves use a loop that copies backwards.
 */
 
-#ifndef MEMMOVE
-# define MEMMOVE memmove
-#endif
-#ifndef MEMCPY
-# define MEMCPY memcpy
-#endif
-
-#if IS_IN (libc)
-
-#  undef MEMCPY
-#  define MEMCPY __memcpy_thunderx
-#  undef MEMMOVE
-#  define MEMMOVE __memmove_thunderx
-
-ENTRY_ALIGN (MEMMOVE, 6)
+ENTRY (__memmove_thunderx)
 
        PTR_ARG (0)
        PTR_ARG (1)
@@ -91,9 +77,9 @@ ENTRY_ALIGN (MEMMOVE, 6)
        b.lo    L(move_long)
 
        /* Common case falls through into memcpy.  */
-END (MEMMOVE)
-libc_hidden_builtin_def (MEMMOVE)
-ENTRY (MEMCPY)
+END (__memmove_thunderx)
+
+ENTRY (__memcpy_thunderx)
 
        PTR_ARG (0)
        PTR_ARG (1)
@@ -316,7 +302,4 @@ L(move_long):
        stp     C_l, C_h, [dstin]
 3:     ret
 
-END (MEMCPY)
-libc_hidden_builtin_def (MEMCPY)
-
-#endif
+END (__memcpy_thunderx)
index d3d6f1debcc936b81aa62b170969b149faa9913d..93993b9e03b95075dbc9aef13f44c2b9a2b7800f 100644 (file)
 #define I_v    v16
 #define J_v    v17
 
-#ifndef MEMMOVE
-# define MEMMOVE memmove
-#endif
-#ifndef MEMCPY
-# define MEMCPY memcpy
-#endif
-
-#if IS_IN (libc)
-
-#undef MEMCPY
-#define MEMCPY __memcpy_thunderx2
-#undef MEMMOVE
-#define MEMMOVE __memmove_thunderx2
-
-
 /* Overlapping large forward memmoves use a loop that copies backwards.
    Otherwise memcpy is used. Small moves branch to memcopy16 directly.
    The longer memcpy cases fall through to the memcpy head.
 */
 
-ENTRY_ALIGN (MEMMOVE, 6)
+ENTRY (__memmove_thunderx2)
 
        PTR_ARG (0)
        PTR_ARG (1)
@@ -109,8 +94,7 @@ ENTRY_ALIGN (MEMMOVE, 6)
        ccmp    tmp1, count, 2, hi
        b.lo    L(move_long)
 
-END (MEMMOVE)
-libc_hidden_builtin_def (MEMMOVE)
+END (__memmove_thunderx2)
 
 
 /* Copies are split into 3 main cases: small copies of up to 16 bytes,
@@ -124,8 +108,7 @@ libc_hidden_builtin_def (MEMMOVE)
 
 #define MEMCPY_PREFETCH_LDR 640
 
-       .p2align 4
-ENTRY (MEMCPY)
+ENTRY (__memcpy_thunderx2)
 
        PTR_ARG (0)
        PTR_ARG (1)
@@ -449,7 +432,7 @@ L(move_long):
 3:     ret
 
 
-END (MEMCPY)
+END (__memcpy_thunderx2)
        .section        .rodata
        .p2align        4
 
@@ -472,6 +455,3 @@ L(ext_table):
        .word   L(ext_size_13) -.
        .word   L(ext_size_14) -.
        .word   L(ext_size_15) -.
-
-libc_hidden_builtin_def (MEMCPY)
-#endif
index 312f90f111868c71dd1f32f4a175a28e93c948ee..6b7716685148358a31dfc7969825db8e1e30500a 100644 (file)
@@ -31,20 +31,23 @@ extern __typeof (__redirect_memmove) __libc_memmove;
 extern __typeof (__redirect_memmove) __memmove_generic attribute_hidden;
 extern __typeof (__redirect_memmove) __memmove_thunderx attribute_hidden;
 extern __typeof (__redirect_memmove) __memmove_thunderx2 attribute_hidden;
-extern __typeof (__redirect_memmove) __memmove_falkor attribute_hidden;
 extern __typeof (__redirect_memmove) __memmove_a64fx attribute_hidden;
 extern __typeof (__redirect_memmove) __memmove_sve attribute_hidden;
+extern __typeof (__redirect_memmove) __memmove_mops attribute_hidden;
 
 static inline __typeof (__redirect_memmove) *
 select_memmove_ifunc (void)
 {
   INIT_ARCH ();
 
+  if (mops)
+    return __memmove_mops;
+
   if (sve && HAVE_AARCH64_SVE_ASM)
     {
       if (IS_A64FX (midr))
        return __memmove_a64fx;
-      return __memmove_sve;
+      return prefer_sve_ifuncs ? __memmove_sve : __memmove_generic;
     }
 
   if (IS_THUNDERX (midr))
@@ -53,9 +56,6 @@ select_memmove_ifunc (void)
   if (IS_THUNDERX2 (midr) || IS_THUNDERX2PA (midr))
     return __memmove_thunderx2;
 
-  if (IS_FALKOR (midr) || IS_PHECDA (midr))
-    return __memmove_falkor;
-
   return __memmove_generic;
 }
 
diff --git a/sysdeps/aarch64/multiarch/memmove_mops.S b/sysdeps/aarch64/multiarch/memmove_mops.S
new file mode 100644 (file)
index 0000000..c5ea66b
--- /dev/null
@@ -0,0 +1,39 @@
+/* Optimized memmove for MOPS.
+   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 <sysdep.h>
+
+/* Assumptions:
+ *
+ * AArch64, MOPS.
+ *
+ */
+
+ENTRY (__memmove_mops)
+       PTR_ARG (0)
+       PTR_ARG (1)
+       SIZE_ARG (2)
+
+       mov     x3, x0
+       .inst   0x1d010443      /* cpyp    [x3]!, [x1]!, x2!  */
+       .inst   0x1d410443      /* cpym    [x3]!, [x1]!, x2!  */
+       .inst   0x1d810443      /* cpye    [x3]!, [x1]!, x2!  */
+       ret
+
+END (__memmove_mops)
index f9c81d3d8e46ec86d9f100835e1c43210899770a..6deb6865e5154f129922dca673cf069f72f46d79 100644 (file)
 
 extern __typeof (__redirect_memset) __libc_memset;
 
-extern __typeof (__redirect_memset) __memset_falkor attribute_hidden;
+extern __typeof (__redirect_memset) __memset_zva64 attribute_hidden;
 extern __typeof (__redirect_memset) __memset_emag attribute_hidden;
 extern __typeof (__redirect_memset) __memset_kunpeng attribute_hidden;
 extern __typeof (__redirect_memset) __memset_a64fx attribute_hidden;
 extern __typeof (__redirect_memset) __memset_generic attribute_hidden;
+extern __typeof (__redirect_memset) __memset_mops attribute_hidden;
 
 static inline __typeof (__redirect_memset) *
 select_memset_ifunc (void)
 {
   INIT_ARCH ();
 
+  if (mops)
+    return __memset_mops;
+
   if (sve && HAVE_AARCH64_SVE_ASM)
     {
       if (IS_A64FX (midr) && zva_size == 256)
        return __memset_a64fx;
-      return __memset_generic;
     }
 
   if (IS_KUNPENG920 (midr))
     return __memset_kunpeng;
 
-  if ((IS_FALKOR (midr) || IS_PHECDA (midr)) && zva_size == 64)
-    return __memset_falkor;
-
-  if (IS_EMAG (midr) && zva_size == 64)
+  if (IS_EMAG (midr))
     return __memset_emag;
 
+  if (zva_size == 64)
+    return __memset_zva64;
+
   return __memset_generic;
 }
 
index d520355143ead2acdaf6a7e1652d2417df8087e8..7176f3d284ab12f7a354781db668c0520f47702d 100644 (file)
@@ -33,8 +33,6 @@
 #define vector_length  x9
 
 #if HAVE_AARCH64_SVE_ASM
-# if IS_IN (libc)
-#  define MEMSET __memset_a64fx
 
        .arch armv8.2-a+sve
 
@@ -49,7 +47,7 @@
 #undef BTI_C
 #define BTI_C
 
-ENTRY (MEMSET)
+ENTRY (__memset_a64fx)
        PTR_ARG (0)
        SIZE_ARG (2)
 
@@ -166,8 +164,6 @@ L(L2):
        add     count, count, CACHE_LINE_SIZE
        b       L(last)
 
-END (MEMSET)
-libc_hidden_builtin_def (MEMSET)
+END (__memset_a64fx)
 
-#endif /* IS_IN (libc) */
 #endif /* HAVE_AARCH64_SVE_ASM */
diff --git a/sysdeps/aarch64/multiarch/memset_base64.S b/sysdeps/aarch64/multiarch/memset_base64.S
deleted file mode 100644 (file)
index 35296a6..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/* Copyright (C) 2018-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 <sysdep.h>
-#include "memset-reg.h"
-
-#ifndef MEMSET
-# define MEMSET __memset_base64
-#endif
-
-/* To disable DC ZVA, set this threshold to 0. */
-#ifndef DC_ZVA_THRESHOLD
-# define DC_ZVA_THRESHOLD 512
-#endif
-
-/* Assumptions:
- *
- * ARMv8-a, AArch64, unaligned accesses
- *
- */
-
-ENTRY_ALIGN (MEMSET, 6)
-
-       PTR_ARG (0)
-       SIZE_ARG (2)
-
-       bfi     valw, valw, 8, 8
-       bfi     valw, valw, 16, 16
-       bfi     val, val, 32, 32
-
-       add     dstend, dstin, count
-
-       cmp     count, 96
-       b.hi    L(set_long)
-       cmp     count, 16
-       b.hs    L(set_medium)
-
-       /* Set 0..15 bytes.  */
-       tbz     count, 3, 1f
-       str     val, [dstin]
-       str     val, [dstend, -8]
-       ret
-
-       .p2align 3
-1:     tbz     count, 2, 2f
-       str     valw, [dstin]
-       str     valw, [dstend, -4]
-       ret
-2:     cbz     count, 3f
-       strb    valw, [dstin]
-       tbz     count, 1, 3f
-       strh    valw, [dstend, -2]
-3:     ret
-
-       .p2align 3
-       /* Set 16..96 bytes.  */
-L(set_medium):
-       stp     val, val, [dstin]
-       tbnz    count, 6, L(set96)
-       stp     val, val, [dstend, -16]
-       tbz     count, 5, 1f
-       stp     val, val, [dstin, 16]
-       stp     val, val, [dstend, -32]
-1:     ret
-
-       .p2align 4
-       /* Set 64..96 bytes.  Write 64 bytes from the start and
-          32 bytes from the end.  */
-L(set96):
-       stp     val, val, [dstin, 16]
-       stp     val, val, [dstin, 32]
-       stp     val, val, [dstin, 48]
-       stp     val, val, [dstend, -32]
-       stp     val, val, [dstend, -16]
-       ret
-
-       .p2align 4
-L(set_long):
-       stp     val, val, [dstin]
-       bic     dst, dstin, 15
-#if DC_ZVA_THRESHOLD
-       cmp     count, DC_ZVA_THRESHOLD
-       ccmp    val, 0, 0, cs
-       b.eq    L(zva_64)
-#endif
-       /* Small-size or non-zero memset does not use DC ZVA. */
-       sub     count, dstend, dst
-
-       /*
-        * Adjust count and bias for loop. By subtracting extra 1 from count,
-        * it is easy to use tbz instruction to check whether loop tailing
-        * count is less than 33 bytes, so as to bypass 2 unnecessary stps.
-        */
-       sub     count, count, 64+16+1
-
-#if DC_ZVA_THRESHOLD
-       /* Align loop on 16-byte boundary, this might be friendly to i-cache. */
-       nop
-#endif
-
-1:     stp     val, val, [dst, 16]
-       stp     val, val, [dst, 32]
-       stp     val, val, [dst, 48]
-       stp     val, val, [dst, 64]!
-       subs    count, count, 64
-       b.hs    1b
-
-       tbz     count, 5, 1f    /* Remaining count is less than 33 bytes? */
-       stp     val, val, [dst, 16]
-       stp     val, val, [dst, 32]
-1:     stp     val, val, [dstend, -32]
-       stp     val, val, [dstend, -16]
-       ret
-
-#if DC_ZVA_THRESHOLD
-       .p2align 3
-L(zva_64):
-       stp     val, val, [dst, 16]
-       stp     val, val, [dst, 32]
-       stp     val, val, [dst, 48]
-       bic     dst, dst, 63
-
-       /*
-        * Previous memory writes might cross cache line boundary, and cause
-        * cache line partially dirty. Zeroing this kind of cache line using
-        * DC ZVA will incur extra cost, for it requires loading untouched
-        * part of the line from memory before zeoring.
-        *
-        * So, write the first 64 byte aligned block using stp to force
-        * fully dirty cache line.
-        */
-       stp     val, val, [dst, 64]
-       stp     val, val, [dst, 80]
-       stp     val, val, [dst, 96]
-       stp     val, val, [dst, 112]
-
-       sub     count, dstend, dst
-       /*
-        * Adjust count and bias for loop. By subtracting extra 1 from count,
-        * it is easy to use tbz instruction to check whether loop tailing
-        * count is less than 33 bytes, so as to bypass 2 unnecessary stps.
-        */
-       sub     count, count, 128+64+64+1
-       add     dst, dst, 128
-       nop
-
-       /* DC ZVA sets 64 bytes each time. */
-1:     dc      zva, dst
-       add     dst, dst, 64
-       subs    count, count, 64
-       b.hs    1b
-
-       /*
-        * Write the last 64 byte aligned block using stp to force fully
-        * dirty cache line.
-        */
-       stp     val, val, [dst, 0]
-       stp     val, val, [dst, 16]
-       stp     val, val, [dst, 32]
-       stp     val, val, [dst, 48]
-
-       tbz     count, 5, 1f    /* Remaining count is less than 33 bytes? */
-       stp     val, val, [dst, 64]
-       stp     val, val, [dst, 80]
-1:     stp     val, val, [dstend, -32]
-       stp     val, val, [dstend, -16]
-       ret
-#endif
-
-END (MEMSET)
-libc_hidden_builtin_def (MEMSET)
index 17d609cead96030fbd42f2997d081c6740396af3..bbfa815925899149e2313a9317380fa9fd089abd 100644 (file)
    <https://www.gnu.org/licenses/>.  */
 
 #include <sysdep.h>
+#include "memset-reg.h"
 
-#if IS_IN (libc)
-# define MEMSET __memset_emag
-
-/*
- * Using DC ZVA to zero memory does not produce better performance if
- * memory size is not very large, especially when there are multiple
- * processes/threads contending memory/cache. Here we set threshold to
- * zero to disable using DC ZVA, which is good for multi-process/thread
- * workloads.
+/* Assumptions:
+ *
+ * ARMv8-a, AArch64, unaligned accesses
+ *
  */
 
-# define DC_ZVA_THRESHOLD 0
+ENTRY (__memset_emag)
+
+       PTR_ARG (0)
+       SIZE_ARG (2)
+
+       bfi     valw, valw, 8, 8
+       bfi     valw, valw, 16, 16
+       bfi     val, val, 32, 32
+
+       add     dstend, dstin, count
+
+       cmp     count, 96
+       b.hi    L(set_long)
+       cmp     count, 16
+       b.hs    L(set_medium)
+
+       /* Set 0..15 bytes.  */
+       tbz     count, 3, 1f
+       str     val, [dstin]
+       str     val, [dstend, -8]
+       ret
+
+       .p2align 3
+1:     tbz     count, 2, 2f
+       str     valw, [dstin]
+       str     valw, [dstend, -4]
+       ret
+2:     cbz     count, 3f
+       strb    valw, [dstin]
+       tbz     count, 1, 3f
+       strh    valw, [dstend, -2]
+3:     ret
+
+       .p2align 3
+       /* Set 16..96 bytes.  */
+L(set_medium):
+       stp     val, val, [dstin]
+       tbnz    count, 6, L(set96)
+       stp     val, val, [dstend, -16]
+       tbz     count, 5, 1f
+       stp     val, val, [dstin, 16]
+       stp     val, val, [dstend, -32]
+1:     ret
+
+       .p2align 4
+       /* Set 64..96 bytes.  Write 64 bytes from the start and
+          32 bytes from the end.  */
+L(set96):
+       stp     val, val, [dstin, 16]
+       stp     val, val, [dstin, 32]
+       stp     val, val, [dstin, 48]
+       stp     val, val, [dstend, -32]
+       stp     val, val, [dstend, -16]
+       ret
+
+       .p2align 4
+L(set_long):
+       stp     val, val, [dstin]
+       bic     dst, dstin, 15
+       /* Small-size or non-zero memset does not use DC ZVA. */
+       sub     count, dstend, dst
+
+       /*
+        * Adjust count and bias for loop. By subtracting extra 1 from count,
+        * it is easy to use tbz instruction to check whether loop tailing
+        * count is less than 33 bytes, so as to bypass 2 unnecessary stps.
+        */
+       sub     count, count, 64+16+1
+
+1:     stp     val, val, [dst, 16]
+       stp     val, val, [dst, 32]
+       stp     val, val, [dst, 48]
+       stp     val, val, [dst, 64]!
+       subs    count, count, 64
+       b.hs    1b
+
+       tbz     count, 5, 1f    /* Remaining count is less than 33 bytes? */
+       stp     val, val, [dst, 16]
+       stp     val, val, [dst, 32]
+1:     stp     val, val, [dstend, -32]
+       stp     val, val, [dstend, -16]
+       ret
 
-# include "./memset_base64.S"
-#endif
+END (__memset_emag)
diff --git a/sysdeps/aarch64/multiarch/memset_falkor.S b/sysdeps/aarch64/multiarch/memset_falkor.S
deleted file mode 100644 (file)
index c6946a8..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Memset for falkor.
-   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/>.  */
-
-#include <sysdep.h>
-#include <memset-reg.h>
-
-/* Reading dczid_el0 is expensive on falkor so move it into the ifunc
-   resolver and assume ZVA size of 64 bytes.  The IFUNC resolver takes care to
-   use this function only when ZVA is enabled.  */
-
-#if IS_IN (libc)
-.macro zva_macro
-       .p2align 4
-       /* Write the first and last 64 byte aligned block using stp rather
-          than using DC ZVA.  This is faster on some cores.  */
-       str     q0, [dst, 16]
-       stp     q0, q0, [dst, 32]
-       bic     dst, dst, 63
-       stp     q0, q0, [dst, 64]
-       stp     q0, q0, [dst, 96]
-       sub     count, dstend, dst      /* Count is now 128 too large.  */
-       sub     count, count, 128+64+64 /* Adjust count and bias for loop.  */
-       add     dst, dst, 128
-1:     dc      zva, dst
-       add     dst, dst, 64
-       subs    count, count, 64
-       b.hi    1b
-       stp     q0, q0, [dst, 0]
-       stp     q0, q0, [dst, 32]
-       stp     q0, q0, [dstend, -64]
-       stp     q0, q0, [dstend, -32]
-       ret
-.endm
-
-# define ZVA_MACRO zva_macro
-# define MEMSET __memset_falkor
-# include <sysdeps/aarch64/memset.S>
-#endif
index 9c23e482bf90d8b466d3e3d1e2d2d4a053b434bb..6c1f0daac8615c3e83e067db9b61e77c1c2c2fdd 100644 (file)
 
 #if IS_IN (libc)
 # define MEMSET __memset_generic
+
+/* Do not hide the generic version of memset, we use it internally.  */
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(name)
+
 /* Add a hidden definition for use within libc.so.  */
 # ifdef SHARED
        .globl __GI_memset; __GI_memset = __memset_generic
 # endif
-# include <sysdeps/aarch64/memset.S>
 #endif
+
+#include <../memset.S>
index 86c46434fdd30460d0655850d25f69d75b193b2e..4a54373398ff14151c49490c06749277de664cd9 100644 (file)
 #include <sysdep.h>
 #include <sysdeps/aarch64/memset-reg.h>
 
-#if IS_IN (libc)
-# define MEMSET __memset_kunpeng
-
 /* Assumptions:
  *
  * ARMv8-a, AArch64, unaligned accesses
  *
  */
 
-ENTRY_ALIGN (MEMSET, 6)
+ENTRY (__memset_kunpeng)
 
        PTR_ARG (0)
        SIZE_ARG (2)
@@ -108,6 +105,4 @@ L(set_long):
        stp     q0, q0, [dstend, -32]
        ret
 
-END (MEMSET)
-libc_hidden_builtin_def (MEMSET)
-#endif
+END (__memset_kunpeng)
diff --git a/sysdeps/aarch64/multiarch/memset_mops.S b/sysdeps/aarch64/multiarch/memset_mops.S
new file mode 100644 (file)
index 0000000..ca820b8
--- /dev/null
@@ -0,0 +1,38 @@
+/* Optimized memset for MOPS.
+   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 <sysdep.h>
+
+/* Assumptions:
+ *
+ * AArch64, MOPS.
+ *
+ */
+
+ENTRY (__memset_mops)
+       PTR_ARG (0)
+       SIZE_ARG (2)
+
+       mov     x3, x0
+       .inst   0x19c10443      /* setp    [x3]!, x2!, x1  */
+       .inst   0x19c14443      /* setm    [x3]!, x2!, x1  */
+       .inst   0x19c18443      /* sete    [x3]!, x2!, x1  */
+       ret
+
+END (__memset_mops)
diff --git a/sysdeps/aarch64/multiarch/memset_zva64.S b/sysdeps/aarch64/multiarch/memset_zva64.S
new file mode 100644 (file)
index 0000000..13f45fd
--- /dev/null
@@ -0,0 +1,27 @@
+/* Optimized memset for zva size = 64.
+   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 <sysdep.h>
+
+#define ZVA64_ONLY 1
+#define MEMSET __memset_zva64
+#undef libc_hidden_builtin_def
+#define libc_hidden_builtin_def(X)
+
+#include "../memset.S"
diff --git a/sysdeps/aarch64/multiarch/rtld-memset.S b/sysdeps/aarch64/multiarch/rtld-memset.S
deleted file mode 100644 (file)
index 4b035ed..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Memset for aarch64, for the dynamic linker.
-   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/>.  */
-
-#include <sysdep.h>
-
-#if IS_IN (rtld)
-# define MEMSET memset
-# include <sysdeps/aarch64/memset.S>
-#endif
index bbdd3de8c4a8dca2e86f6fcfbe810be2fb1867b1..728bd1936a218c77f931c7327d402bcc873c50f9 100644 (file)
 
 extern __typeof (__redirect_strlen) __strlen;
 
-extern __typeof (__redirect_strlen) __strlen_mte attribute_hidden;
+extern __typeof (__redirect_strlen) __strlen_generic attribute_hidden;
 extern __typeof (__redirect_strlen) __strlen_asimd attribute_hidden;
 
-libc_ifunc (__strlen, (mte ? __strlen_mte : __strlen_asimd));
+libc_ifunc (__strlen, (mte ? __strlen_generic : __strlen_asimd));
 
 # undef strlen
 strong_alias (__strlen, strlen);
index 490439491d19c3f14b0228f42248bc8aa6e9e8bd..aee5ef9f78adb1f769dbc48ef9aae8966f120c24 100644 (file)
@@ -203,4 +203,3 @@ L(page_cross):
        ret
 
 END (__strlen_asimd)
-libc_hidden_builtin_def (__strlen_asimd)
diff --git a/sysdeps/aarch64/multiarch/strlen_generic.S b/sysdeps/aarch64/multiarch/strlen_generic.S
new file mode 100644 (file)
index 0000000..2346296
--- /dev/null
@@ -0,0 +1,39 @@
+/* A Generic Optimized strlen implementation for AARCH64.
+   Copyright (C) 2018-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 actual strlen code is in ../strlen.S.  If we are building libc this file
+   defines __strlen_generic.  Otherwise the include of ../strlen.S will define
+   the normal __strlen entry points.  */
+
+#include <sysdep.h>
+
+#if IS_IN (libc)
+
+# define STRLEN __strlen_generic
+
+/* Do not hide the generic version of strlen, we use it internally.  */
+# undef libc_hidden_builtin_def
+# define libc_hidden_builtin_def(name)
+
+# ifdef SHARED
+/* It doesn't make sense to send libc-internal strlen calls through a PLT. */
+       .globl __GI_strlen; __GI_strlen = __strlen_generic
+# endif
+#endif
+
+#include "../strlen.S"
diff --git a/sysdeps/aarch64/multiarch/strlen_mte.S b/sysdeps/aarch64/multiarch/strlen_mte.S
deleted file mode 100644 (file)
index 1c1220b..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* A Generic Optimized strlen implementation for AARCH64.
-   Copyright (C) 2018-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 actual strlen code is in ../strlen.S.  If we are building libc this file
-   defines __strlen_mte.  Otherwise the include of ../strlen.S will define
-   the normal __strlen  entry points.  */
-
-#include <sysdep.h>
-
-#if IS_IN (libc)
-
-# define STRLEN __strlen_mte
-
-/* Do not hide the generic version of strlen, we use it internally.  */
-# undef libc_hidden_builtin_def
-# define libc_hidden_builtin_def(name)
-
-# ifdef SHARED
-/* It doesn't make sense to send libc-internal strlen calls through a PLT. */
-       .globl __GI_strlen; __GI_strlen = __strlen_mte
-# endif
-#endif
-
-#include "../strlen.S"
index efc4b7007b2730d3ebe92dc39bb0d23195c7cc62..1fff094215296d6943a0187d09e14f22d7a9ed55 100644 (file)
@@ -31,7 +31,7 @@ ENTRY (__rawmemchr)
 
 L(do_strlen):
        mov     x15, x30
-       cfi_return_column (x15)
+       cfi_register (x30, x15)
        mov     x14, x0
        bl      __strlen
        add     x0, x14, x0
diff --git a/sysdeps/arc/utmp-size.h b/sysdeps/arc/utmp-size.h
new file mode 100644 (file)
index 0000000..a247fcd
--- /dev/null
@@ -0,0 +1,3 @@
+/* arc has less padding than other architectures with 64-bit time_t.  */
+#define UTMP_SIZE 392
+#define LASTLOG_SIZE 296
diff --git a/sysdeps/arm/bits/wordsize.h b/sysdeps/arm/bits/wordsize.h
new file mode 100644 (file)
index 0000000..6ecbfe7
--- /dev/null
@@ -0,0 +1,21 @@
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define __WORDSIZE                     32
+#define __WORDSIZE_TIME64_COMPAT32     1
+#define __WORDSIZE32_SIZE_ULONG                0
+#define __WORDSIZE32_PTRDIFF_LONG      0
index d720c02c96b8f51c3464c2e5656f70fcf03e9cc2..77dc7415e906c8ca3afea2aab64ceed9989cbbc6 100644 (file)
@@ -137,7 +137,6 @@ _start:\n\
 _dl_start_user:\n\
        adr     r6, .L_GET_GOT\n\
        add     sl, sl, r6\n\
-       ldr     r4, [sl, r4]\n\
        @ save the entry point in another register\n\
        mov     r6, r0\n\
        @ get the original arg count\n\
diff --git a/sysdeps/arm/utmp-size.h b/sysdeps/arm/utmp-size.h
new file mode 100644 (file)
index 0000000..8f21ebe
--- /dev/null
@@ -0,0 +1,2 @@
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
diff --git a/sysdeps/csky/bits/wordsize.h b/sysdeps/csky/bits/wordsize.h
new file mode 100644 (file)
index 0000000..6ecbfe7
--- /dev/null
@@ -0,0 +1,21 @@
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define __WORDSIZE                     32
+#define __WORDSIZE_TIME64_COMPAT32     1
+#define __WORDSIZE32_SIZE_ULONG                0
+#define __WORDSIZE32_PTRDIFF_LONG      0
diff --git a/sysdeps/csky/utmp-size.h b/sysdeps/csky/utmp-size.h
new file mode 100644 (file)
index 0000000..8f21ebe
--- /dev/null
@@ -0,0 +1,2 @@
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
index 81397fb90ba48d7e0e4c2ba99c8efb5daf1d6c5b..8278c50a84ffda18e28c178d390f1899d8306e26 100644 (file)
@@ -4,7 +4,6 @@
 #define UNSECURE_ENVVARS \
   "GCONV_PATH\0"                                                             \
   "GETCONF_DIR\0"                                                            \
-  "GLIBC_TUNABLES\0"                                                         \
   "HOSTALIASES\0"                                                            \
   "LD_AUDIT\0"                                                               \
   "LD_DEBUG\0"                                                               \
diff --git a/sysdeps/generic/utmp-size.h b/sysdeps/generic/utmp-size.h
new file mode 100644 (file)
index 0000000..89dbe87
--- /dev/null
@@ -0,0 +1,23 @@
+/* Expected sizes of utmp-related structures stored in files.  64-bit version.
+   Copyright (C) 2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* Expected size, in bytes, of struct utmp and struct utmpx.  */
+#define UTMP_SIZE 400
+
+/* Expected size, in bytes, of struct lastlog.  */
+#define LASTLOG_SIZE 296
diff --git a/sysdeps/hppa/utmp-size.h b/sysdeps/hppa/utmp-size.h
new file mode 100644 (file)
index 0000000..8f21ebe
--- /dev/null
@@ -0,0 +1,2 @@
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
index 84e6686eba5fe79aee4b6317f21809a4fd6a84d6..f2139fc172ceef7b74931c8572ced5e48fa89d1b 100644 (file)
@@ -1232,6 +1232,7 @@ ldouble: 6
 
 Function: "hypot":
 double: 1
+float: 1
 float128: 1
 ldouble: 1
 
index 9b48ec0ea15585d828abe97e5bf39219e3e2e8c8..b86af4aac9995d7f8220690717f5b2661f631212 100644 (file)
@@ -27,7 +27,7 @@
 #define LEN    SRC+4
 
        .text
-#if defined PIC && IS_IN (libc)
+#if defined SHARED && IS_IN (libc)
 ENTRY_CHK (__memcpy_chk)
        movl    12(%esp), %eax
        cmpl    %eax, 16(%esp)
index 26f8501e7dcde6cad5435e32b27a861270376fc9..14d9dd681a0e88dd60679474a3a7c85f0002daa3 100644 (file)
@@ -27,7 +27,7 @@
 #define LEN    SRC+4
 
        .text
-#if defined PIC && IS_IN (libc)
+#if defined SHARED && IS_IN (libc)
 ENTRY_CHK (__mempcpy_chk)
        movl    12(%esp), %eax
        cmpl    %eax, 16(%esp)
index ec945dc91f3e38255b3592af5ff6154d39bdeae1..c3a8aeaf184bb8efa5b050caf4921c3ecc69b1ce 100644 (file)
@@ -32,4 +32,6 @@ libc_ifunc_redirected (__redirect_memcpy_chk, __memcpy_chk,
 __hidden_ver1 (__memcpy_chk, __GI___memcpy_chk, __redirect_memcpy_chk)
   __attribute__ ((visibility ("hidden"))) __attribute_copy__ (__memcpy_chk);
 # endif
+#else
+# include <debug/memcpy_chk.c>
 #endif
index 55c7601d5d5baa070fba64f2e5d6c20013b79134..070dde083a563564db998e8b005946565cbf9685 100644 (file)
@@ -32,4 +32,6 @@ libc_ifunc_redirected (__redirect_memmove_chk, __memmove_chk,
 __hidden_ver1 (__memmove_chk, __GI___memmove_chk, __redirect_memmove_chk)
   __attribute__ ((visibility ("hidden"))) __attribute_copy__ (__memmove_chk);
 # endif
+#else
+# include <debug/memmove_chk.c>
 #endif
index 83569cf9d9c6471310e2528c06170d4ba4c6c9a3..14360f1828406eb86d1ca8f7cbff0ef3eb1c2bb4 100644 (file)
@@ -32,4 +32,6 @@ libc_ifunc_redirected (__redirect_mempcpy_chk, __mempcpy_chk,
 __hidden_ver1 (__mempcpy_chk, __GI___mempcpy_chk, __redirect_mempcpy_chk)
   __attribute__ ((visibility ("hidden"))) __attribute_copy__ (__mempcpy_chk);
 # endif
+#else
+# include <debug/mempcpy_chk.c>
 #endif
index 1a7503858d9394cfa7649ef063689433bd38faad..8179ef7c0bf7524b4a005ac5f1627834c23f9846 100644 (file)
@@ -32,4 +32,6 @@ libc_ifunc_redirected (__redirect_memset_chk, __memset_chk,
 __hidden_ver1 (__memset_chk, __GI___memset_chk, __redirect_memset_chk)
   __attribute__ ((visibility ("hidden"))) __attribute_copy__ (__memset_chk);
 # endif
+#else
+# include <debug/memset_chk.c>
 #endif
index 02375286f8da6f1a9511059ebda73da57df1d25d..99fcacab76b057b58c35de899ab210f6aa1c82c0 100644 (file)
@@ -19,9 +19,9 @@
 /* Assembler veneer called from the PLT header code for lazy loading.
    The PLT header passes its own args in t0-t2.  */
 #ifdef USE_LASX
-# define FRAME_SIZE (-((-9 * SZREG - 8 * SZFREG - 8 * SZXREG) & ALMASK))
+# define FRAME_SIZE (-((-9 * SZREG - 8 * SZXREG) & ALMASK))
 #elif defined USE_LSX
-# define FRAME_SIZE (-((-9 * SZREG - 8 * SZFREG - 8 * SZVREG) & ALMASK))
+# define FRAME_SIZE (-((-9 * SZREG - 8 * SZVREG) & ALMASK))
 #elif !defined __loongarch_soft_float
 # define FRAME_SIZE (-((-9 * SZREG - 8 * SZFREG) & ALMASK))
 #else
@@ -44,23 +44,23 @@ ENTRY (_dl_runtime_resolve)
        REG_S   a7, sp, 8*SZREG
 
 #ifdef USE_LASX
-       xvst    xr0, sp, 9*SZREG + 8*SZFREG + 0*SZXREG
-       xvst    xr1, sp, 9*SZREG + 8*SZFREG + 1*SZXREG
-       xvst    xr2, sp, 9*SZREG + 8*SZFREG + 2*SZXREG
-       xvst    xr3, sp, 9*SZREG + 8*SZFREG + 3*SZXREG
-       xvst    xr4, sp, 9*SZREG + 8*SZFREG + 4*SZXREG
-       xvst    xr5, sp, 9*SZREG + 8*SZFREG + 5*SZXREG
-       xvst    xr6, sp, 9*SZREG + 8*SZFREG + 6*SZXREG
-       xvst    xr7, sp, 9*SZREG + 8*SZFREG + 7*SZXREG
+       xvst    xr0, sp, 9*SZREG + 0*SZXREG
+       xvst    xr1, sp, 9*SZREG + 1*SZXREG
+       xvst    xr2, sp, 9*SZREG + 2*SZXREG
+       xvst    xr3, sp, 9*SZREG + 3*SZXREG
+       xvst    xr4, sp, 9*SZREG + 4*SZXREG
+       xvst    xr5, sp, 9*SZREG + 5*SZXREG
+       xvst    xr6, sp, 9*SZREG + 6*SZXREG
+       xvst    xr7, sp, 9*SZREG + 7*SZXREG
 #elif defined USE_LSX
-       vst     vr0, sp, 9*SZREG + 8*SZFREG + 0*SZVREG
-       vst     vr1, sp, 9*SZREG + 8*SZFREG + 1*SZVREG
-       vst     vr2, sp, 9*SZREG + 8*SZFREG + 2*SZVREG
-       vst     vr3, sp, 9*SZREG + 8*SZFREG + 3*SZVREG
-       vst     vr4, sp, 9*SZREG + 8*SZFREG + 4*SZVREG
-       vst     vr5, sp, 9*SZREG + 8*SZFREG + 5*SZVREG
-       vst     vr6, sp, 9*SZREG + 8*SZFREG + 6*SZVREG
-       vst     vr7, sp, 9*SZREG + 8*SZFREG + 7*SZVREG
+       vst     vr0, sp, 9*SZREG + 0*SZVREG
+       vst     vr1, sp, 9*SZREG + 1*SZVREG
+       vst     vr2, sp, 9*SZREG + 2*SZVREG
+       vst     vr3, sp, 9*SZREG + 3*SZVREG
+       vst     vr4, sp, 9*SZREG + 4*SZVREG
+       vst     vr5, sp, 9*SZREG + 5*SZVREG
+       vst     vr6, sp, 9*SZREG + 6*SZVREG
+       vst     vr7, sp, 9*SZREG + 7*SZVREG
 #elif !defined __loongarch_soft_float
        FREG_S  fa0, sp, 9*SZREG + 0*SZFREG
        FREG_S  fa1, sp, 9*SZREG + 1*SZFREG
@@ -92,23 +92,23 @@ ENTRY (_dl_runtime_resolve)
        REG_L   a7, sp, 8*SZREG
 
 #ifdef USE_LASX
-       xvld    xr0, sp, 9*SZREG + 8*SZFREG + 0*SZXREG
-       xvld    xr1, sp, 9*SZREG + 8*SZFREG + 1*SZXREG
-       xvld    xr2, sp, 9*SZREG + 8*SZFREG + 2*SZXREG
-       xvld    xr3, sp, 9*SZREG + 8*SZFREG + 3*SZXREG
-       xvld    xr4, sp, 9*SZREG + 8*SZFREG + 4*SZXREG
-       xvld    xr5, sp, 9*SZREG + 8*SZFREG + 5*SZXREG
-       xvld    xr6, sp, 9*SZREG + 8*SZFREG + 6*SZXREG
-       xvld    xr7, sp, 9*SZREG + 8*SZFREG + 7*SZXREG
+       xvld    xr0, sp, 9*SZREG + 0*SZXREG
+       xvld    xr1, sp, 9*SZREG + 1*SZXREG
+       xvld    xr2, sp, 9*SZREG + 2*SZXREG
+       xvld    xr3, sp, 9*SZREG + 3*SZXREG
+       xvld    xr4, sp, 9*SZREG + 4*SZXREG
+       xvld    xr5, sp, 9*SZREG + 5*SZXREG
+       xvld    xr6, sp, 9*SZREG + 6*SZXREG
+       xvld    xr7, sp, 9*SZREG + 7*SZXREG
 #elif defined USE_LSX
-       vld     vr0, sp, 9*SZREG + 8*SZFREG + 0*SZVREG
-       vld     vr1, sp, 9*SZREG + 8*SZFREG + 1*SZVREG
-       vld     vr2, sp, 9*SZREG + 8*SZFREG + 2*SZVREG
-       vld     vr3, sp, 9*SZREG + 8*SZFREG + 3*SZVREG
-       vld     vr4, sp, 9*SZREG + 8*SZFREG + 4*SZVREG
-       vld     vr5, sp, 9*SZREG + 8*SZFREG + 5*SZVREG
-       vld     vr6, sp, 9*SZREG + 8*SZFREG + 6*SZVREG
-       vld     vr7, sp, 9*SZREG + 8*SZFREG + 7*SZVREG
+       vld     vr0, sp, 9*SZREG + 0*SZVREG
+       vld     vr1, sp, 9*SZREG + 1*SZVREG
+       vld     vr2, sp, 9*SZREG + 2*SZVREG
+       vld     vr3, sp, 9*SZREG + 3*SZVREG
+       vld     vr4, sp, 9*SZREG + 4*SZVREG
+       vld     vr5, sp, 9*SZREG + 5*SZVREG
+       vld     vr6, sp, 9*SZREG + 6*SZVREG
+       vld     vr7, sp, 9*SZREG + 7*SZVREG
 #elif !defined __loongarch_soft_float
        FREG_L  fa0, sp, 9*SZREG + 0*SZFREG
        FREG_L  fa1, sp, 9*SZREG + 1*SZFREG
index c37b0fd19d6cf31c28ac6837d29fe1e4fe753732..46902246210239acf5483291c69eee40ae0d7f4d 100644 (file)
@@ -57,4 +57,4 @@ __ieee754_scalbf (float x, float fn)
 
   return x;
 }
-libm_alias_finite (__ieee754_scalb, __scalb)
+libm_alias_finite (__ieee754_scalbf, __scalbf)
diff --git a/sysdeps/m68k/bits/wordsize.h b/sysdeps/m68k/bits/wordsize.h
new file mode 100644 (file)
index 0000000..6ecbfe7
--- /dev/null
@@ -0,0 +1,21 @@
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define __WORDSIZE                     32
+#define __WORDSIZE_TIME64_COMPAT32     1
+#define __WORDSIZE32_SIZE_ULONG                0
+#define __WORDSIZE32_PTRDIFF_LONG      0
diff --git a/sysdeps/m68k/utmp-size.h b/sysdeps/m68k/utmp-size.h
new file mode 100644 (file)
index 0000000..5946685
--- /dev/null
@@ -0,0 +1,3 @@
+/* m68k has 2-byte alignment.  */
+#define UTMP_SIZE 382
+#define LASTLOG_SIZE 292
index 5184e5eee1cd430451aadfc8d0899bfdcb46a8f0..d3834f3b6955885708e33d04e4dd69d2b9f768fe 100644 (file)
@@ -62,12 +62,6 @@ __get_nprocs (void)
 libc_hidden_def (__get_nprocs)
 weak_alias (__get_nprocs, get_nprocs)
 
-int
-__get_nprocs_sched (void)
-{
-  return __get_nprocs ();
-}
-
 /* Return the number of physical pages on the system. */
 long int
 __get_phys_pages (void)
diff --git a/sysdeps/microblaze/bits/wordsize.h b/sysdeps/microblaze/bits/wordsize.h
new file mode 100644 (file)
index 0000000..6ecbfe7
--- /dev/null
@@ -0,0 +1,21 @@
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define __WORDSIZE                     32
+#define __WORDSIZE_TIME64_COMPAT32     1
+#define __WORDSIZE32_SIZE_ULONG                0
+#define __WORDSIZE32_PTRDIFF_LONG      0
diff --git a/sysdeps/microblaze/utmp-size.h b/sysdeps/microblaze/utmp-size.h
new file mode 100644 (file)
index 0000000..8f21ebe
--- /dev/null
@@ -0,0 +1,2 @@
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
index 9d7d961f3e1ebebf99e987adb511d35030a977dd..cb72a0869a8005546b4d23fac206fcd69e9530d3 100644 (file)
 
 #define __WORDSIZE                     _MIPS_SZPTR
 
-#if _MIPS_SIM == _ABI64
-# define __WORDSIZE_TIME64_COMPAT32    1
-#else
-# define __WORDSIZE_TIME64_COMPAT32    0
-#endif
+#define __WORDSIZE_TIME64_COMPAT32     1
 
 #if __WORDSIZE == 32
 #define __WORDSIZE32_SIZE_ULONG                0
diff --git a/sysdeps/mips/utmp-size.h b/sysdeps/mips/utmp-size.h
new file mode 100644 (file)
index 0000000..8f21ebe
--- /dev/null
@@ -0,0 +1,2 @@
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
diff --git a/sysdeps/nios2/bits/wordsize.h b/sysdeps/nios2/bits/wordsize.h
new file mode 100644 (file)
index 0000000..6ecbfe7
--- /dev/null
@@ -0,0 +1,21 @@
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define __WORDSIZE                     32
+#define __WORDSIZE_TIME64_COMPAT32     1
+#define __WORDSIZE32_SIZE_ULONG                0
+#define __WORDSIZE32_PTRDIFF_LONG      0
diff --git a/sysdeps/nios2/utmp-size.h b/sysdeps/nios2/utmp-size.h
new file mode 100644 (file)
index 0000000..8f21ebe
--- /dev/null
@@ -0,0 +1,2 @@
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
diff --git a/sysdeps/or1k/utmp-size.h b/sysdeps/or1k/utmp-size.h
new file mode 100644 (file)
index 0000000..6b3653a
--- /dev/null
@@ -0,0 +1,3 @@
+/* or1k has less padding than other architectures with 64-bit time_t.  */
+#define UTMP_SIZE 392
+#define LASTLOG_SIZE 296
index 0356b622be6dda5e6ac9bf70c9813cc1351a0b81..da573bea2427981fbc19636ab21c36b884638f69 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 04ca9debf00d7ee97ddf83dcd2e66c139bcd9d7c..6993fb6b29ea3f743dedda57771ef9e4dce2169d 100644 (file)
@@ -2,10 +2,9 @@
 
 #if defined __powerpc64__
 # define __WORDSIZE    64
-# define __WORDSIZE_TIME64_COMPAT32    1
 #else
 # define __WORDSIZE    32
-# define __WORDSIZE_TIME64_COMPAT32    0
 # define __WORDSIZE32_SIZE_ULONG       0
 # define __WORDSIZE32_PTRDIFF_LONG     0
 #endif
+#define __WORDSIZE_TIME64_COMPAT32     1
index 04ca9debf00d7ee97ddf83dcd2e66c139bcd9d7c..6993fb6b29ea3f743dedda57771ef9e4dce2169d 100644 (file)
@@ -2,10 +2,9 @@
 
 #if defined __powerpc64__
 # define __WORDSIZE    64
-# define __WORDSIZE_TIME64_COMPAT32    1
 #else
 # define __WORDSIZE    32
-# define __WORDSIZE_TIME64_COMPAT32    0
 # define __WORDSIZE32_SIZE_ULONG       0
 # define __WORDSIZE32_PTRDIFF_LONG     0
 #endif
+#define __WORDSIZE_TIME64_COMPAT32     1
index 9b8943bc91916a53acad2aa29bf05b505356da5d..7fa8a355b5ae444a3cf746e77e994da64815a1cb 100644 (file)
@@ -79,6 +79,7 @@ elf_host_tolerates_class (const Elf64_Ehdr *ehdr)
 static inline Elf64_Addr
 elf_machine_load_address (void) __attribute__ ((const));
 
+#ifndef __PCREL__
 static inline Elf64_Addr
 elf_machine_load_address (void)
 {
@@ -106,6 +107,24 @@ elf_machine_dynamic (void)
   /* Then subtract off the load address offset.  */
   return runtime_dynamic - elf_machine_load_address() ;
 }
+#else /* __PCREL__ */
+/* In PCREL mode, r2 may have been clobbered.  Rely on relative
+   relocations instead.  */
+
+static inline ElfW(Addr)
+elf_machine_load_address (void)
+{
+  extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
+  return (ElfW(Addr)) &__ehdr_start;
+}
+
+static inline ElfW(Addr)
+elf_machine_dynamic (void)
+{
+  extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
+  return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address ();
+}
+#endif /* __PCREL__ */
 
 /* The PLT uses Elf64_Rela relocs.  */
 #define elf_machine_relplt elf_machine_rela
diff --git a/sysdeps/powerpc/utmp-size.h b/sysdeps/powerpc/utmp-size.h
new file mode 100644 (file)
index 0000000..8f21ebe
--- /dev/null
@@ -0,0 +1,2 @@
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
index e5db929d205e05fbbc841d169b7af9baa70dbb05..0e331a7445ed12ffe07d4066040bb19360074f2e 100644 (file)
 # define __unlink unlink
 #endif
 
+#define SEM_OPEN_FLAGS (O_RDWR | O_NOFOLLOW | O_CLOEXEC)
+
 sem_t *
 __sem_open (const char *name, int oflag, ...)
 {
   int fd;
-  int open_flags;
   sem_t *result;
 
   /* Check that shared futexes are supported.  */
@@ -65,10 +66,8 @@ __sem_open (const char *name, int oflag, ...)
   /* If the semaphore object has to exist simply open it.  */
   if ((oflag & O_CREAT) == 0 || (oflag & O_EXCL) == 0)
     {
-      open_flags = O_RDWR | O_NOFOLLOW | O_CLOEXEC;
-      open_flags |= (oflag & ~(O_CREAT|O_ACCMODE));
     try_again:
-      fd = __open (dirname.name, open_flags);
+      fd = __open (dirname.name, (oflag & O_EXCL) | SEM_OPEN_FLAGS);
 
       if (fd == -1)
        {
@@ -135,8 +134,7 @@ __sem_open (const char *name, int oflag, ...)
            }
 
          /* Open the file.  Make sure we do not overwrite anything.  */
-         open_flags = O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC;
-         fd = __open (tmpfname, open_flags, mode);
+         fd = __open (tmpfname, O_CREAT | O_EXCL | SEM_OPEN_FLAGS, mode);
          if (fd == -1)
            {
              if (errno == EEXIST)
index ff803386be43ded13ab3c65c47e7cca6649c6029..ace925ca67242533c4d4b86d7c51925de5e3b404 100644 (file)
@@ -18,6 +18,7 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
+#include <errno.h>
 #include <support/check.h>
 #include <support/xstdio.h>
 #include <support/xthread.h>
@@ -46,13 +47,19 @@ tf (void *arg)
 
   /* Wait indefinitely for cancellation, which only works if asynchronous
      cancellation is enabled.  */
-#if defined SYS_ppoll || defined SYS_ppoll_time64
-# ifndef SYS_ppoll_time64
-#  define SYS_ppoll_time64 SYS_ppoll
+#ifdef SYS_ppoll_time64
+  long int ret = syscall (SYS_ppoll_time64, NULL, 0, NULL, NULL);
+  (void) ret;
+# ifdef SYS_ppoll
+  if (ret == -1 && errno == ENOSYS)
+    syscall (SYS_ppoll, NULL, 0, NULL, NULL);
 # endif
-  syscall (SYS_ppoll_time64, NULL, 0, NULL, NULL);
 #else
+# ifdef SYS_ppoll
+  syscall (SYS_ppoll, NULL, 0, NULL, NULL);
+# else
   for (;;);
+# endif
 #endif
 
   return 0;
diff --git a/sysdeps/riscv/utmp-size.h b/sysdeps/riscv/utmp-size.h
new file mode 100644 (file)
index 0000000..8f21ebe
--- /dev/null
@@ -0,0 +1,2 @@
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
index bdf3c7bbe0a376485912ced41713f3321a612b5e..fadd63087a3343c117aeddf478685f210735e032 100644 (file)
@@ -25,7 +25,9 @@
 
 # include <string/memrchr.c>
 
-# if defined SHARED && IS_IN (libc)
+# if HAVE_MEMRCHR_IFUNC
+#  if defined SHARED && IS_IN (libc)
 __hidden_ver1 (__memrchr_c, __GI___memrchr, __memrchr_c);
+#  endif
 # endif
 #endif
index f6f5bae3111ca783ab6913355740db1658cb0d88..97fbc16edb18c85a0201c9a4a490c14263ba6dba 100644 (file)
@@ -24,7 +24,9 @@
 # endif
 
 # include <string/strchrnul.c>
-# if defined SHARED && IS_IN (libc)
+# if HAVE_STRCHRNUL_IFUNC
+#  if defined SHARED && IS_IN (libc)
 __hidden_ver1 (__strchrnul_c, __GI___strchrnul, __strchrnul_c);
+#  endif
 # endif
 #endif
diff --git a/sysdeps/sh/bits/wordsize.h b/sysdeps/sh/bits/wordsize.h
new file mode 100644 (file)
index 0000000..6ecbfe7
--- /dev/null
@@ -0,0 +1,21 @@
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define __WORDSIZE                     32
+#define __WORDSIZE_TIME64_COMPAT32     1
+#define __WORDSIZE32_SIZE_ULONG                0
+#define __WORDSIZE32_PTRDIFF_LONG      0
diff --git a/sysdeps/sh/utmp-size.h b/sysdeps/sh/utmp-size.h
new file mode 100644 (file)
index 0000000..8f21ebe
--- /dev/null
@@ -0,0 +1,2 @@
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
index 2f66f10d7206731a2110721685d0ac6dc184ab14..a2e79e0fa9dc41d92fb8bd45e99a55f90ed816c5 100644 (file)
@@ -1,11 +1,6 @@
 /* Determine the wordsize from the preprocessor defines.  */
 
-#if defined __arch64__ || defined __sparcv9
-# define __WORDSIZE    64
-# define __WORDSIZE_TIME64_COMPAT32    1
-#else
-# define __WORDSIZE    32
-# define __WORDSIZE_TIME64_COMPAT32    0
-# define __WORDSIZE32_SIZE_ULONG       0
-# define __WORDSIZE32_PTRDIFF_LONG     0
-#endif
+#define __WORDSIZE     32
+#define __WORDSIZE_TIME64_COMPAT32     1
+#define __WORDSIZE32_SIZE_ULONG        0
+#define __WORDSIZE32_PTRDIFF_LONG      0
index ca29ff568501787541f024e2c5a32cdab4473c8b..1dc3a640e874360abe7b3f84b3a599c1ea384f3c 100644 (file)
@@ -55,7 +55,7 @@ ENTRY(memset)
 
        andcc           %o0, 3, %o2
        bne             3f
-4:      andcc          %o0, 4, %g0
+5:      andcc          %o0, 4, %g0
 
        be              2f
         mov            %g3, %g2
@@ -139,7 +139,7 @@ ENTRY(memset)
        stb             %g3, [%o0 + 0x02]
 2:     sub             %o2, 4, %o2
        add             %o1, %o2, %o1
-       b               4b
+       b               5b
         sub            %o0, %o2, %o0
 END(memset)
 libc_hidden_builtin_def (memset)
index 2f66f10d7206731a2110721685d0ac6dc184ab14..ea103e5970829abc52731614b8835e1796606b4d 100644 (file)
@@ -2,10 +2,9 @@
 
 #if defined __arch64__ || defined __sparcv9
 # define __WORDSIZE    64
-# define __WORDSIZE_TIME64_COMPAT32    1
 #else
 # define __WORDSIZE    32
-# define __WORDSIZE_TIME64_COMPAT32    0
 # define __WORDSIZE32_SIZE_ULONG       0
 # define __WORDSIZE32_PTRDIFF_LONG     0
 #endif
+#define __WORDSIZE_TIME64_COMPAT32     1
index db6f4f0e842b9535a400794408b61b6172a5cd0e..62b19ebc1b86e823bb8a152590c1439ed92716a8 100644 (file)
@@ -38,7 +38,7 @@ ENTRY(memmove)
 /*
  * normal, copy forwards
  */
-2:     ble     %XCC, .Ldbytecp
+2:     bleu    %XCC, .Ldbytecp
         andcc  %o1, 3, %o5     /* is src word aligned  */
        bz,pn   %icc, .Laldst
         cmp    %o5, 2          /* is src half-word aligned  */
index 687e6261823e7dcef2bb30c302e2829a6bfdeeae..151baa5e10f72c0c68274154a3abf8cbaf8a9723 100644 (file)
@@ -76,6 +76,15 @@ C_LABEL(name)                                \
        cfi_endproc;                    \
        .size name, . - name
 
+#define ENTRY_NOCFI(name)                      \
+       .align  4;                      \
+       .global C_SYMBOL_NAME(name);    \
+       .type   name, @function;        \
+C_LABEL(name)
+
+#define END_NOCFI(name)                        \
+       .size name, . - name
+
 #undef LOC
 #define LOC(name)  .L##name
 
diff --git a/sysdeps/sparc/utmp-size.h b/sysdeps/sparc/utmp-size.h
new file mode 100644 (file)
index 0000000..8f21ebe
--- /dev/null
@@ -0,0 +1,2 @@
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
index 55c7ed39beac4710ad5492cb60c20a7616729a82..b251c2d4171c9002b5ade74896547b015595a27c 100644 (file)
@@ -98,3 +98,4 @@
 #define HWCAP2_SME_BI32I32     (1UL << 40)
 #define HWCAP2_SME_B16B16      (1UL << 41)
 #define HWCAP2_SME_F16F16      (1UL << 42)
+#define HWCAP2_MOPS            (1UL << 43)
index dc09c1c8274855c8215c2c6d57af9a2b5f8a7e2f..4a205a6b35050ffcfac771b4b4ff2d9fb7581f93 100644 (file)
@@ -20,6 +20,7 @@
 #include <sys/auxv.h>
 #include <elf/dl-hwcaps.h>
 #include <sys/prctl.h>
+#include <sys/utsname.h>
 
 #define DCZID_DZP_MASK (1 << 4)
 #define DCZID_BS_MASK (0xf)
@@ -37,11 +38,9 @@ struct cpu_list
 };
 
 static struct cpu_list cpu_list[] = {
-      {"falkor",        0x510FC000},
       {"thunderxt88",   0x430F0A10},
       {"thunderx2t99",   0x431F0AF0},
       {"thunderx2t99p1", 0x420F5160},
-      {"phecda",        0x680F0000},
       {"ares",          0x411FD0C0},
       {"emag",          0x503F0001},
       {"kunpeng920",    0x481FD010},
@@ -59,6 +58,46 @@ get_midr_from_mcpu (const char *mcpu)
   return UINT64_MAX;
 }
 
+#if __LINUX_KERNEL_VERSION < 0x060200
+
+/* Return true if we prefer using SVE in string ifuncs.  Old kernels disable
+   SVE after every system call which results in unnecessary traps if memcpy
+   uses SVE.  This is true for kernels between 4.15.0 and before 6.2.0, except
+   for 5.14.0 which was patched.  For these versions return false to avoid using
+   SVE ifuncs.
+   Parse the kernel version into a 24-bit kernel.major.minor value without
+   calling any library functions.  If uname() is not supported or if the version
+   format is not recognized, assume the kernel is modern and return true.  */
+
+static inline bool
+prefer_sve_ifuncs (void)
+{
+  struct utsname buf;
+  const char *p = &buf.release[0];
+  int kernel = 0;
+  int val;
+
+  if (__uname (&buf) < 0)
+    return true;
+
+  for (int shift = 16; shift >= 0; shift -= 8)
+    {
+      for (val = 0; *p >= '0' && *p <= '9'; p++)
+       val = val * 10 + *p - '0';
+      kernel |= (val & 255) << shift;
+      if (*p++ != '.')
+       break;
+    }
+
+  if (kernel >= 0x060200 || kernel == 0x050e00)
+    return true;
+  if (kernel >= 0x040f00)
+    return false;
+  return true;
+}
+
+#endif
+
 static inline void
 init_cpu_features (struct cpu_features *cpu_features)
 {
@@ -120,4 +159,14 @@ init_cpu_features (struct cpu_features *cpu_features)
 
   /* Check if SVE is supported.  */
   cpu_features->sve = GLRO (dl_hwcap) & HWCAP_SVE;
+
+  cpu_features->prefer_sve_ifuncs = cpu_features->sve;
+
+#if __LINUX_KERNEL_VERSION < 0x060200
+  if (cpu_features->sve)
+    cpu_features->prefer_sve_ifuncs = prefer_sve_ifuncs ();
+#endif
+
+  /* Check if MOPS is supported.  */
+  cpu_features->mops = GLRO (dl_hwcap2) & HWCAP2_MOPS;
 }
index d67d286b536ea599dcd8873fa2b882c5c27e8b05..351a619dcb221ffccf83ec888df0004da0391d9d 100644 (file)
 #define IS_THUNDERX2(midr) (MIDR_IMPLEMENTOR(midr) == 'C'       \
                           && MIDR_PARTNUM(midr) == 0xaf)
 
-#define IS_FALKOR(midr) (MIDR_IMPLEMENTOR(midr) == 'Q'                       \
-                        && MIDR_PARTNUM(midr) == 0xc00)
-
-#define IS_PHECDA(midr) (MIDR_IMPLEMENTOR(midr) == 'h'                       \
-                        && MIDR_PARTNUM(midr) == 0x000)
 #define IS_NEOVERSE_N1(midr) (MIDR_IMPLEMENTOR(midr) == 'A'                  \
                              && MIDR_PARTNUM(midr) == 0xd0c)
 #define IS_NEOVERSE_N2(midr) (MIDR_IMPLEMENTOR(midr) == 'A'                  \
@@ -76,6 +71,8 @@ struct cpu_features
   /* Currently, the GLIBC memory tagging tunable only defines 8 bits.  */
   uint8_t mte_state;
   bool sve;
+  bool prefer_sve_ifuncs;
+  bool mops;
 };
 
 #endif /* _CPU_FEATURES_AARCH64_H  */
index 311f5b16ce7426adee118d34996c1205dd0b82f5..d641f57b019816fcf738e119fefc3ba892971f44 100644 (file)
@@ -47,6 +47,7 @@ extern ssize_t process_vm_writev (pid_t __pid, const struct iovec *__lvec,
 #define RWF_SYNC       0x00000004 /* per-IO O_SYNC.  */
 #define RWF_NOWAIT     0x00000008 /* per-IO nonblocking mode.  */
 #define RWF_APPEND     0x00000010 /* per-IO O_APPEND.  */
+#define RWF_NOAPPEND   0x00000020 /* per-IO negation of O_APPEND */
 
 __END_DECLS
 
index 2b0b8b6368f77890d4dfe175596f0186a3e75d61..3aa6a00348cc87a086b290060df3ae71af0ef645 100644 (file)
@@ -66,25 +66,10 @@ static struct cached_data *cache;
 __libc_lock_define_initialized (static, lock);
 
 
-#if IS_IN (nscd)
-static uint32_t nl_timestamp;
-
-uint32_t
-__bump_nl_timestamp (void)
-{
-  if (atomic_fetch_add_relaxed (&nl_timestamp, 1) + 1 == 0)
-    atomic_fetch_add_relaxed (&nl_timestamp, 1);
-
-  return nl_timestamp;
-}
-#endif
-
 static inline uint32_t
 get_nl_timestamp (void)
 {
-#if IS_IN (nscd)
-  return nl_timestamp;
-#elif defined USE_NSCD
+#if defined USE_NSCD
   return __nscd_get_nl_timestamp ();
 #else
   return 0;
index b0b6c154acab6ff635399835459401387700778c..1ea7f1f01fd18fa25ff72697343f654286dec61a 100644 (file)
@@ -29,7 +29,7 @@
 #include <sys/sysinfo.h>
 #include <sysdep.h>
 
-int
+static int
 __get_nprocs_sched (void)
 {
   enum
diff --git a/sysdeps/unix/sysv/linux/hppa/bits/wordsize.h b/sysdeps/unix/sysv/linux/hppa/bits/wordsize.h
new file mode 100644 (file)
index 0000000..6ecbfe7
--- /dev/null
@@ -0,0 +1,21 @@
+/* Copyright (C) 1999-2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define __WORDSIZE                     32
+#define __WORDSIZE_TIME64_COMPAT32     1
+#define __WORDSIZE32_SIZE_ULONG                0
+#define __WORDSIZE32_PTRDIFF_LONG      0
index 51d4a1b082a0283d471bae70feff8f48b3682c32..822c41fcebbf39dfea57ffb287bdcc40c97fa2cd 100644 (file)
@@ -52,7 +52,14 @@ xset_thread_area (struct user_desc *u_info)
 static void
 xmodify_ldt (int func, const void *ptr, unsigned long bytecount)
 {
-  TEST_VERIFY_EXIT (syscall (SYS_modify_ldt, 1, ptr, bytecount) == 0);
+  long ret = syscall (SYS_modify_ldt, func, ptr, bytecount);
+
+  if (ret == -1)
+    {
+      if (errno == ENOSYS)
+       FAIL_UNSUPPORTED ("modify_ldt not supported");
+      FAIL_EXIT1 ("modify_ldt failed (errno=%d)", errno);
+    }
 }
 
 static int
index f7615a447e27f2307f1a15bb68638ebe6c4bccbb..d8a291a33197561790a4e99f9db9693b19ffd98b 100644 (file)
@@ -33,7 +33,7 @@
 # define __O_LARGEFILE 0200000
 #endif
 
-#if __WORDSIZE == 64
+#if __WORDSIZE == 64 && !defined __USE_FILE_OFFSET64
 # define F_GETLK       5
 # define F_SETLK       6
 # define F_SETLKW      7
index 04ca9debf00d7ee97ddf83dcd2e66c139bcd9d7c..6993fb6b29ea3f743dedda57771ef9e4dce2169d 100644 (file)
@@ -2,10 +2,9 @@
 
 #if defined __powerpc64__
 # define __WORDSIZE    64
-# define __WORDSIZE_TIME64_COMPAT32    1
 #else
 # define __WORDSIZE    32
-# define __WORDSIZE_TIME64_COMPAT32    0
 # define __WORDSIZE32_SIZE_ULONG       0
 # define __WORDSIZE32_PTRDIFF_LONG     0
 #endif
+#define __WORDSIZE_TIME64_COMPAT32     1
index 5d8d8733833190514fb75702d03dff33115b9868..fd1e509cf4602980d7d4237d9f3bf8c3a2272ef0 100644 (file)
@@ -53,6 +53,7 @@ ENTRY(__clone)
        br      %r14
 error:
        lhi     %r2,-EINVAL
+       lm      %r6,%r7,24(%r15)        /* Load registers.  */
        j       SYSCALL_ERROR_LABEL
 PSEUDO_END (__clone)
 
index f1c4288a3d4c10a7303edd201d026eba4fe42e95..7b37b18010aa4e8b8c0e8775c23a214ce1c04192 100644 (file)
@@ -54,6 +54,7 @@ ENTRY(__clone)
        br      %r14
 error:
        lghi    %r2,-EINVAL
+       lmg     %r6,%r7,48(%r15)        /* Restore registers.  */
        jg      SYSCALL_ERROR_LABEL
 PSEUDO_END (__clone)
 
index 4457d714bc45a5df47104da17748a6bd50d4f2b7..22700ef846497323e32ae8695576b30c78cf99ef 100644 (file)
@@ -33,17 +33,9 @@ vsyscall_sched_getcpu (void)
   return r == -1 ? r : cpu;
 }
 
-#ifdef RSEQ_SIG
 int
 sched_getcpu (void)
 {
   int cpu_id = THREAD_GETMEM_VOLATILE (THREAD_SELF, rseq_area.cpu_id);
   return __glibc_likely (cpu_id >= 0) ? cpu_id : vsyscall_sched_getcpu ();
 }
-#else /* RSEQ_SIG */
-int
-sched_getcpu (void)
-{
-  return vsyscall_sched_getcpu ();
-}
-#endif /* RSEQ_SIG */
index 7562875ee23ba8c52156e7e0fa1f4457ae15286e..ea103e5970829abc52731614b8835e1796606b4d 100644 (file)
@@ -2,10 +2,9 @@
 
 #if defined __arch64__ || defined __sparcv9
 # define __WORDSIZE    64
-# define __WORDSIZE_TIME64_COMPAT32    1
 #else
 # define __WORDSIZE    32
 # define __WORDSIZE32_SIZE_ULONG       0
 # define __WORDSIZE32_PTRDIFF_LONG     0
-# define __WORDSIZE_TIME64_COMPAT32    0
 #endif
+#define __WORDSIZE_TIME64_COMPAT32     1
index cf509c8d5ced47cdf6a7f300802cc12a6d1efb46..1962f9053ca7b0fa055b5cd3a4bcae2e57ac9a4e 100644 (file)
 
    [1] https://lkml.org/lkml/2016/5/27/465  */
 
-ENTRY (__rt_sigreturn_stub)
+       nop
+       nop
+
+ENTRY_NOCFI (__rt_sigreturn_stub)
        mov     __NR_rt_sigreturn, %g1
        ta      0x10
-END (__rt_sigreturn_stub)
+END_NOCFI (__rt_sigreturn_stub)
 
-ENTRY (__sigreturn_stub)
+ENTRY_NOCFI (__sigreturn_stub)
        mov     __NR_sigreturn, %g1
        ta      0x10
-END (__sigreturn_stub)
+END_NOCFI (__sigreturn_stub)
index 7fac04f65791c51e84f4457b876f2624e8e96fd7..f089bcaf68d976487eabeb345bd3503521cb480f 100644 (file)
 
    [1] https://lkml.org/lkml/2016/5/27/465  */
 
-ENTRY (__rt_sigreturn_stub)
+       nop
+       nop
+
+ENTRY_NOCFI (__rt_sigreturn_stub)
        mov     __NR_rt_sigreturn, %g1
        ta      0x6d
-END (__rt_sigreturn_stub)
+END_NOCFI (__rt_sigreturn_stub)
index 56348707d48f049e70b524e8a8f6be2e8a0fff58..95bd0f6ccbc5d354ce740089bcd86c4c49d842da 100644 (file)
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-/* BZ #2386 */
+/* BZ #2386, BZ #31402 */
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sched.h>
+#include <stackinfo.h>  /* For _STACK_GROWS_{UP,DOWN}.  */
+#include <support/check.h>
+
+volatile unsigned v = 0xdeadbeef;
 
 #ifdef __ia64__
 extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
@@ -35,26 +39,72 @@ int child_fn(void *arg)
 }
 
 static int
-do_test (void)
+__attribute__((noinline))
+do_clone (int (*fn)(void *), void *stack)
 {
   int result;
+  unsigned int a = v;
+  unsigned int b = v;
+  unsigned int c = v;
+  unsigned int d = v;
+  unsigned int e = v;
+  unsigned int f = v;
+  unsigned int g = v;
+  unsigned int h = v;
+  unsigned int i = v;
+  unsigned int j = v;
+  unsigned int k = v;
+  unsigned int l = v;
+  unsigned int m = v;
+  unsigned int n = v;
+  unsigned int o = v;
 
 #ifdef __ia64__
-  result = __clone2 (child_fn, NULL, 0, 0, NULL, NULL, NULL);
+  result = __clone2 (fn, stack, stack != NULL ? 128 * 1024 : 0, 0, NULL, NULL,
+                    NULL);
+#else
+  result = clone (fn, stack, 0, NULL);
+#endif
+
+  /* Check that clone does not clobber call-saved registers.  */
+  TEST_VERIFY (a == v && b == v && c == v && d == v && e == v && f == v
+              && g == v && h == v && i == v && j == v && k == v && l == v
+              && m == v && n == v && o == v);
+
+  return result;
+}
+
+static void
+__attribute__((noinline))
+do_test_single (int (*fn)(void *), void *stack)
+{
+  printf ("%s (fn=%p, stack=%p)\n", __FUNCTION__, fn, stack);
+  errno = 0;
+
+  int result = do_clone (fn, stack);
+
+  TEST_COMPARE (errno, EINVAL);
+  TEST_COMPARE (result, -1);
+}
+
+static int
+do_test (void)
+{
+  char st[128 * 1024] __attribute__ ((aligned));
+  void *stack = NULL;
+#if defined __ia64__ || _STACK_GROWS_UP
+  stack = st;
+#elif _STACK_GROWS_DOWN
+  stack = st + sizeof (st);
 #else
-  result = clone (child_fn, NULL, 0, NULL);
+# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
 #endif
 
-  if (errno != EINVAL || result != -1)
-    {
-      printf ("FAIL: clone()=%d (wanted -1) errno=%d (wanted %d)\n",
-              result, errno, EINVAL);
-      return 1;
-    }
+  do_test_single (child_fn, NULL);
+  do_test_single (NULL, stack);
+  do_test_single (NULL, NULL);
 
-  puts ("All OK");
   return 0;
 }
 
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
+#include <support/test-driver.c>
index 70f652bca14d65c1de5a21669e7c0ffb8ecfe5ea..3f40aa76f99c75e5aabc1390ab4a2ff4647e6035 100644 (file)
@@ -8,10 +8,9 @@
 #define __WORDSIZE32_PTRDIFF_LONG      0
 #endif
 
+#define __WORDSIZE_TIME64_COMPAT32 1
+
 #ifdef __x86_64__
-# define __WORDSIZE_TIME64_COMPAT32    1
 /* Both x86-64 and x32 use the 64-bit system call interface.  */
 # define __SYSCALL_WORDSIZE            64
-#else
-# define __WORDSIZE_TIME64_COMPAT32    0
 #endif
index cd4d0351ae2cfd78a1394a21afea6ccc35f454b8..5ddb35c9d9ff467037d38e39c35f315bf7961adf 100644 (file)
@@ -315,40 +315,206 @@ 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_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:
-      return ecx ? ((ebx >> 22) & 0x3ff) + 1 : 0;
-    case _SC_LEVEL1_ICACHE_LINESIZE:
-    case _SC_LEVEL1_DCACHE_LINESIZE:
-    case _SC_LEVEL2_CACHE_LINESIZE:
+      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 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;
+      return (edx & 0xf000) == 0 ? 0 : edx & 0xff;
+
     default:
       __builtin_unreachable ();
     }
@@ -604,11 +770,10 @@ get_common_cache_info (long int *shared_ptr, long int * shared_per_thread_ptr, u
             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;
        }
+      /* 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.  */
@@ -703,7 +868,6 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
       data = handle_amd (_SC_LEVEL1_DCACHE_SIZE);
       core = handle_amd (_SC_LEVEL2_CACHE_SIZE);
       shared = handle_amd (_SC_LEVEL3_CACHE_SIZE);
-      shared_per_thread = shared;
 
       level1_icache_size = handle_amd (_SC_LEVEL1_ICACHE_SIZE);
       level1_icache_linesize = handle_amd (_SC_LEVEL1_ICACHE_LINESIZE);
@@ -716,13 +880,20 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
       level3_cache_size = shared;
       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;
+        }
 
-      if (shared_per_thread <= 0)
-       shared_per_thread = shared;
+      shared_per_thread = shared;
     }
 
   cpu_features->level1_icache_size = level1_icache_size;
index 32daf51053f2101b6b9f8ecb15ddbb8da86a57af..f85356b589f0bb26372e155687ec8516f67d281f 100644 (file)
@@ -65,7 +65,7 @@ do_test (int argc, char **argv)
 #endif
   fails += CHECK_FEATURE_ACTIVE (avx, AVX);
   fails += CHECK_FEATURE_ACTIVE (avx2, AVX2);
-#if __GNUC_PREREQ (7, 0)
+#if __GNUC_PREREQ (7, 0) && !__GNUC_PREREQ (15, 0)
   fails += CHECK_FEATURE_ACTIVE (avx5124fmaps, AVX512_4FMAPS);
   fails += CHECK_FEATURE_ACTIVE (avx5124vnniw, AVX512_4VNNIW);
 #endif
@@ -92,14 +92,18 @@ do_test (int argc, char **argv)
 #if __GNUC_PREREQ (6, 0)
   fails += CHECK_FEATURE_ACTIVE (avx512bw, AVX512BW);
   fails += CHECK_FEATURE_ACTIVE (avx512cd, AVX512CD);
+# if !__GNUC_PREREQ (15, 0)
   fails += CHECK_FEATURE_ACTIVE (avx512er, AVX512ER);
+# endif
   fails += CHECK_FEATURE_ACTIVE (avx512dq, AVX512DQ);
 #endif
 #if __GNUC_PREREQ (5, 0)
   fails += CHECK_FEATURE_ACTIVE (avx512f, AVX512F);
 #endif
 #if __GNUC_PREREQ (6, 0)
+# if !__GNUC_PREREQ (15, 0)
   fails += CHECK_FEATURE_ACTIVE (avx512pf, AVX512PF);
+# endif
   fails += CHECK_FEATURE_ACTIVE (avx512vl, AVX512VL);
 #endif
 #if __GNUC_PREREQ (5, 0)
@@ -148,7 +152,9 @@ do_test (int argc, char **argv)
 #endif
   fails += CHECK_FEATURE_ACTIVE (popcnt, POPCNT);
 #if __GNUC_PREREQ (11, 0)
+# if !__GNUC_PREREQ (15, 0)
   fails += CHECK_FEATURE_ACTIVE (prefetchwt1, PREFETCHWT1);
+# endif
   fails += CHECK_FEATURE_ACTIVE (ptwrite, PTWRITE);
   fails += CHECK_FEATURE_ACTIVE (rdpid, RDPID);
   fails += CHECK_FEATURE_ACTIVE (rdrnd, RDRAND);
diff --git a/sysdeps/x86/utmp-size.h b/sysdeps/x86/utmp-size.h
new file mode 100644 (file)
index 0000000..8f21ebe
--- /dev/null
@@ -0,0 +1,2 @@
+#define UTMP_SIZE 384
+#define LASTLOG_SIZE 292
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 a1c13d4906191a5e6f251a3055edb705dd4f018f..0c6680735c96bb2ff8f143412077276ea597c9e0 100644 (file)
@@ -26,13 +26,13 @@ int
 ffsll (long long int x)
 {
   long long int cnt;
-  long long int tmp;
 
-  asm ("bsfq %2,%0\n"          /* Count low bits in X and store in %1.  */
-       "cmoveq %1,%0\n"                /* If number was zero, use -1 as result.  */
-       : "=&r" (cnt), "=r" (tmp) : "rm" (x), "1" (-1));
+  asm ("mov $-1,%k0\n" /* Initialize cnt to -1.  */
+       "bsf %1,%0\n"   /* Count low bits in x and store in cnt.  */
+       "inc %k0\n"     /* Increment cnt by 1.  */
+       : "=&r" (cnt) : "r" (x));
 
-  return cnt + 1;
+  return cnt;
 }
 
 #ifndef __ILP32__
index d98500a78a3706b71b8710209562750f31b9e1fb..4922cba6576b67128382e24ae43e77d8504c50b0 100644 (file)
@@ -1 +1 @@
-/* Implemented in memcpy.S.  */
+/* Implemented in memmove.S.  */
index f0b84e3b520466ba435cd45222c10cf0915dc013..c3c08165e12a466ad585e85bcb6328923f639573 100644 (file)
@@ -46,6 +46,9 @@ weak_alias (__mempcpy, mempcpy)
 
 #ifndef USE_MULTIARCH
 libc_hidden_builtin_def (memmove)
+libc_hidden_builtin_def (__memmove_chk)
+libc_hidden_builtin_def (__memcpy_chk)
+libc_hidden_builtin_def (__mempcpy_chk)
 # if defined SHARED && IS_IN (libc)
 strong_alias (memmove, __memcpy)
 libc_hidden_ver (memmove, memcpy)
index 7c99df36db2a0c6fd067bd784f6fb15252833746..c6df24e8de6a9faa22b836a860c032a259127c94 100644 (file)
@@ -32,6 +32,7 @@
 #include "isa-default-impl.h"
 
 libc_hidden_builtin_def (memset)
+libc_hidden_builtin_def (__memset_chk)
 
 #if IS_IN (libc)
 libc_hidden_def (__wmemset)