parent
85132eb253
commit
0f019b72be
@ -0,0 +1,154 @@
|
||||
commit cca9684f2d7a74fc0b28bfb1859955e0e28d7b4b
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Aug 3 11:41:53 2022 +0200
|
||||
|
||||
stdio: Clean up __libc_message after unconditional abort
|
||||
|
||||
Since commit ec2c1fcefb200c6cb7e09553f3c6af8815013d83 ("malloc:
|
||||
Abort on heap corruption, without a backtrace [BZ #21754]"),
|
||||
__libc_message always terminates the process. Since commit
|
||||
a289ea09ea843ced6e5277c2f2e63c357bc7f9a3 ("Do not print backtraces
|
||||
on fatal glibc errors"), the backtrace facility has been removed.
|
||||
Therefore, remove enum __libc_message_action and the action
|
||||
argument of __libc_message, and mark __libc_message as _No_return.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/debug/fortify_fail.c b/debug/fortify_fail.c
|
||||
index 9fa07af4867c2bd1..1b490d9da78b8d0d 100644
|
||||
--- a/debug/fortify_fail.c
|
||||
+++ b/debug/fortify_fail.c
|
||||
@@ -21,8 +21,6 @@ void
|
||||
__attribute__ ((noreturn))
|
||||
__fortify_fail (const char *msg)
|
||||
{
|
||||
- /* The loop is added only to keep gcc happy. */
|
||||
- while (1)
|
||||
- __libc_message (do_abort, "*** %s ***: terminated\n", msg);
|
||||
+ __libc_message ("*** %s ***: terminated\n", msg);
|
||||
}
|
||||
libc_hidden_def (__fortify_fail)
|
||||
diff --git a/include/stdio.h b/include/stdio.h
|
||||
index 23b7fd288cdaba66..3d4544575318a934 100644
|
||||
--- a/include/stdio.h
|
||||
+++ b/include/stdio.h
|
||||
@@ -143,18 +143,11 @@ extern int __gen_tempname (char *__tmpl, int __suffixlen, int __flags,
|
||||
# define __GT_DIR 1 /* create a directory */
|
||||
# define __GT_NOCREATE 2 /* just find a name not currently in use */
|
||||
|
||||
-enum __libc_message_action
|
||||
-{
|
||||
- do_message = 0, /* Print message. */
|
||||
- do_abort = 1 << 0, /* Abort. */
|
||||
-};
|
||||
-
|
||||
/* Print out MESSAGE (which should end with a newline) on the error output
|
||||
and abort. */
|
||||
extern void __libc_fatal (const char *__message)
|
||||
__attribute__ ((__noreturn__));
|
||||
-extern void __libc_message (enum __libc_message_action action,
|
||||
- const char *__fnt, ...) attribute_hidden;
|
||||
+_Noreturn void __libc_message (const char *__fnt, ...) attribute_hidden;
|
||||
extern void __fortify_fail (const char *msg) __attribute__ ((__noreturn__));
|
||||
libc_hidden_proto (__fortify_fail)
|
||||
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index d31e985ecce968fe..918e7936f1983437 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -298,8 +298,7 @@ _Noreturn static void
|
||||
__malloc_assert (const char *assertion, const char *file, unsigned int line,
|
||||
const char *function)
|
||||
{
|
||||
- __libc_message (do_abort, "\
|
||||
-Fatal glibc error: malloc assertion failure in %s: %s\n",
|
||||
+ __libc_message ("Fatal glibc error: malloc assertion failure in %s: %s\n",
|
||||
function, assertion);
|
||||
__builtin_unreachable ();
|
||||
}
|
||||
@@ -5528,7 +5527,7 @@ static void
|
||||
malloc_printerr (const char *str)
|
||||
{
|
||||
#if IS_IN (libc)
|
||||
- __libc_message (do_abort, "%s\n", str);
|
||||
+ __libc_message ("%s\n", str);
|
||||
#else
|
||||
__libc_fatal (str);
|
||||
#endif
|
||||
diff --git a/sysdeps/posix/libc_fatal.c b/sysdeps/posix/libc_fatal.c
|
||||
index 6d24bee6134856d1..1feacfbeba765035 100644
|
||||
--- a/sysdeps/posix/libc_fatal.c
|
||||
+++ b/sysdeps/posix/libc_fatal.c
|
||||
@@ -54,7 +54,7 @@ struct str_list
|
||||
|
||||
/* Abort with an error message. */
|
||||
void
|
||||
-__libc_message (enum __libc_message_action action, const char *fmt, ...)
|
||||
+__libc_message (const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int fd = -1;
|
||||
@@ -123,36 +123,31 @@ __libc_message (enum __libc_message_action action, const char *fmt, ...)
|
||||
|
||||
WRITEV_FOR_FATAL (fd, iov, nlist, total);
|
||||
|
||||
- if ((action & do_abort))
|
||||
+ total = (total + 1 + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1);
|
||||
+ struct abort_msg_s *buf = __mmap (NULL, total,
|
||||
+ PROT_READ | PROT_WRITE,
|
||||
+ MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
+ if (__glibc_likely (buf != MAP_FAILED))
|
||||
{
|
||||
- total = ((total + 1 + GLRO(dl_pagesize) - 1)
|
||||
- & ~(GLRO(dl_pagesize) - 1));
|
||||
- struct abort_msg_s *buf = __mmap (NULL, total,
|
||||
- PROT_READ | PROT_WRITE,
|
||||
- MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
- if (__glibc_likely (buf != MAP_FAILED))
|
||||
- {
|
||||
- buf->size = total;
|
||||
- char *wp = buf->msg;
|
||||
- for (int cnt = 0; cnt < nlist; ++cnt)
|
||||
- wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len);
|
||||
- *wp = '\0';
|
||||
-
|
||||
- /* We have to free the old buffer since the application might
|
||||
- catch the SIGABRT signal. */
|
||||
- struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg,
|
||||
- buf);
|
||||
- if (old != NULL)
|
||||
- __munmap (old, old->size);
|
||||
- }
|
||||
+ buf->size = total;
|
||||
+ char *wp = buf->msg;
|
||||
+ for (int cnt = 0; cnt < nlist; ++cnt)
|
||||
+ wp = mempcpy (wp, iov[cnt].iov_base, iov[cnt].iov_len);
|
||||
+ *wp = '\0';
|
||||
+
|
||||
+ /* We have to free the old buffer since the application might
|
||||
+ catch the SIGABRT signal. */
|
||||
+ struct abort_msg_s *old = atomic_exchange_acq (&__abort_msg,
|
||||
+ buf);
|
||||
+ if (old != NULL)
|
||||
+ __munmap (old, old->size);
|
||||
}
|
||||
}
|
||||
|
||||
va_end (ap);
|
||||
|
||||
- if ((action & do_abort))
|
||||
- /* Kill the application. */
|
||||
- abort ();
|
||||
+ /* Kill the application. */
|
||||
+ abort ();
|
||||
}
|
||||
|
||||
|
||||
@@ -161,6 +156,6 @@ __libc_fatal (const char *message)
|
||||
{
|
||||
/* The loop is added only to keep gcc happy. */
|
||||
while (1)
|
||||
- __libc_message (do_abort, "%s", message);
|
||||
+ __libc_message ("%s", message);
|
||||
}
|
||||
libc_hidden_def (__libc_fatal)
|
@ -0,0 +1,45 @@
|
||||
commit 68e036f27f31c3378201702e182246504fb00f87
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Aug 3 11:41:53 2022 +0200
|
||||
|
||||
nptl: Remove uses of assert_perror
|
||||
|
||||
__pthread_sigmask cannot actually fail with valid pointer arguments
|
||||
(it would need a really broken seccomp filter), and we do not check
|
||||
for errors elsewhere.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/sysdeps/nptl/gai_misc.h b/sysdeps/nptl/gai_misc.h
|
||||
index 261e24dae62d7871..700fd5c46b4b7c82 100644
|
||||
--- a/sysdeps/nptl/gai_misc.h
|
||||
+++ b/sysdeps/nptl/gai_misc.h
|
||||
@@ -81,9 +81,7 @@ __gai_start_notify_thread (void)
|
||||
{
|
||||
sigset_t ss;
|
||||
sigemptyset (&ss);
|
||||
- int sigerr __attribute__ ((unused));
|
||||
- sigerr = __pthread_sigmask (SIG_SETMASK, &ss, NULL);
|
||||
- assert_perror (sigerr);
|
||||
+ (void) __pthread_sigmask (SIG_SETMASK, &ss, NULL);
|
||||
}
|
||||
|
||||
extern inline int
|
||||
@@ -106,15 +104,12 @@ __gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *),
|
||||
sigset_t ss;
|
||||
sigset_t oss;
|
||||
sigfillset (&ss);
|
||||
- int sigerr __attribute__ ((unused));
|
||||
- sigerr = __pthread_sigmask (SIG_SETMASK, &ss, &oss);
|
||||
- assert_perror (sigerr);
|
||||
+ (void) __pthread_sigmask (SIG_SETMASK, &ss, &oss);
|
||||
|
||||
int ret = __pthread_create (threadp, &attr, tf, arg);
|
||||
|
||||
/* Restore the signal mask. */
|
||||
- sigerr = __pthread_sigmask (SIG_SETMASK, &oss, NULL);
|
||||
- assert_perror (sigerr);
|
||||
+ (void) __pthread_sigmask (SIG_SETMASK, &oss, NULL);
|
||||
|
||||
(void) __pthread_attr_destroy (&attr);
|
||||
return ret;
|
@ -0,0 +1,164 @@
|
||||
commit 9001cb1102cddba54f0e84e147dfbb0356067356
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Aug 3 11:41:53 2022 +0200
|
||||
|
||||
assert: Do not use stderr in libc-internal assert
|
||||
|
||||
Redirect internal assertion failures to __libc_assert_fail, based on
|
||||
based on __libc_message, which writes directly to STDERR_FILENO
|
||||
and calls abort. Also disable message translation and reword the
|
||||
error message slightly (adjusting stdlib/tst-bz20544 accordingly).
|
||||
|
||||
As a result of these changes, malloc no longer needs its own
|
||||
redefinition of __assert_fail.
|
||||
|
||||
__libc_assert_fail needs to be stubbed out during rtld dependency
|
||||
analysis because the rtld rebuilds turn __libc_assert_fail into
|
||||
__assert_fail, which is unconditionally provided by elf/dl-minimal.c.
|
||||
|
||||
This change is not possible for the public assert macro and its
|
||||
__assert_fail function because POSIX requires that the diagnostic
|
||||
is written to stderr.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/assert/Makefile b/assert/Makefile
|
||||
index 0008de34cb484a13..2bc9e2214e3e9a8b 100644
|
||||
--- a/assert/Makefile
|
||||
+++ b/assert/Makefile
|
||||
@@ -24,7 +24,12 @@ include ../Makeconfig
|
||||
|
||||
headers := assert.h
|
||||
|
||||
-routines := assert assert-perr __assert
|
||||
+routines := \
|
||||
+ __assert \
|
||||
+ __libc_assert_fail \
|
||||
+ assert \
|
||||
+ assert-perr \
|
||||
+ # routines
|
||||
tests := test-assert test-assert-perr tst-assert-c++ tst-assert-g++
|
||||
|
||||
ifeq ($(have-cxx-thread_local),yes)
|
||||
diff --git a/assert/__libc_assert_fail.c b/assert/__libc_assert_fail.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..149d5feae12f4af8
|
||||
--- /dev/null
|
||||
+++ b/assert/__libc_assert_fail.c
|
||||
@@ -0,0 +1,33 @@
|
||||
+/* libc-internal assert that calls __libc_message.
|
||||
+ Copyright (C) 2022 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 <_itoa.h>
|
||||
+#include <array_length.h>
|
||||
+#include <intprops.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+void
|
||||
+__libc_assert_fail (const char *assertion, const char *file, unsigned int line,
|
||||
+ const char *function)
|
||||
+{
|
||||
+ char linebuf[INT_BUFSIZE_BOUND (unsigned int)];
|
||||
+ array_end (linebuf)[-1] = '\0';
|
||||
+ char *linestr = _itoa_word (line, array_end (linebuf) - 1, 10, 0);
|
||||
+ __libc_message ("Fatal glibc error: %s:%s (%s): assertion failed: %s\n",
|
||||
+ file, linestr, function, assertion);
|
||||
+}
|
||||
diff --git a/assert/assert.c b/assert/assert.c
|
||||
index 8a277dce008b3495..989126c7e5b6b265 100644
|
||||
--- a/assert/assert.c
|
||||
+++ b/assert/assert.c
|
||||
@@ -101,4 +101,3 @@ __assert_fail (const char *assertion, const char *file, unsigned int line,
|
||||
__assert_fail_base (_("%s%s%s:%u: %s%sAssertion `%s' failed.\n%n"),
|
||||
assertion, file, line, function);
|
||||
}
|
||||
-hidden_def(__assert_fail)
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index 613d244e7781d479..2b547d5b58f1759b 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -1158,6 +1158,7 @@ $(objpfx)dl-allobjs.os: $(all-rtld-routines:%=$(objpfx)%.os)
|
||||
rtld-stubbed-symbols = \
|
||||
__GI___pthread_disable_asynccancel \
|
||||
__GI___pthread_enable_asynccancel \
|
||||
+ __libc_assert_fail \
|
||||
__pthread_disable_asynccancel \
|
||||
__pthread_enable_asynccancel \
|
||||
calloc \
|
||||
diff --git a/include/assert.h b/include/assert.h
|
||||
index 61cc8aa22ff4b913..c812808f9b767964 100644
|
||||
--- a/include/assert.h
|
||||
+++ b/include/assert.h
|
||||
@@ -20,8 +20,14 @@ extern void __assert_fail_base (const char *fmt, const char *assertion,
|
||||
const char *function)
|
||||
__THROW __attribute__ ((__noreturn__)) attribute_hidden;
|
||||
|
||||
-# if IS_IN (libc) || (IS_IN (rtld) && !defined NO_RTLD_HIDDEN)
|
||||
-hidden_proto (__assert_fail)
|
||||
-hidden_proto (__assert_perror_fail)
|
||||
+rtld_hidden_proto (__assert_fail)
|
||||
+rtld_hidden_proto (__assert_perror_fail)
|
||||
+libc_hidden_proto (__assert_perror_fail)
|
||||
+
|
||||
+
|
||||
+# if IS_IN (libc)
|
||||
+/* Redirect to the internal version which does not use stderr. */
|
||||
+extern _Noreturn __typeof (__assert_fail) __libc_assert_fail attribute_hidden;
|
||||
+# define __assert_fail __libc_assert_fail
|
||||
# endif
|
||||
#endif
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index 918e7936f1983437..2edb469d5dbf1203 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -289,22 +289,6 @@
|
||||
#define MALLOC_DEBUG 0
|
||||
#endif
|
||||
|
||||
-#if IS_IN (libc)
|
||||
-#ifndef NDEBUG
|
||||
-# define __assert_fail(assertion, file, line, function) \
|
||||
- __malloc_assert(assertion, file, line, function)
|
||||
-
|
||||
-_Noreturn static void
|
||||
-__malloc_assert (const char *assertion, const char *file, unsigned int line,
|
||||
- const char *function)
|
||||
-{
|
||||
- __libc_message ("Fatal glibc error: malloc assertion failure in %s: %s\n",
|
||||
- function, assertion);
|
||||
- __builtin_unreachable ();
|
||||
-}
|
||||
-#endif
|
||||
-#endif
|
||||
-
|
||||
#if USE_TCACHE
|
||||
/* We want 64 entries. This is an arbitrary limit, which tunables can reduce. */
|
||||
# define TCACHE_MAX_BINS 64
|
||||
diff --git a/stdlib/tst-bz20544.c b/stdlib/tst-bz20544.c
|
||||
index 4aa5793b8994d1f6..1337a3952c30e517 100644
|
||||
--- a/stdlib/tst-bz20544.c
|
||||
+++ b/stdlib/tst-bz20544.c
|
||||
@@ -78,7 +78,7 @@ test_bz20544_cxa_at_quick_exit (void *closure)
|
||||
static void
|
||||
test_one_fn (void (*test_fn) (void *))
|
||||
{
|
||||
- const char expected_error[] = "Assertion `func != NULL' failed.\n";
|
||||
+ const char expected_error[] = "assertion failed: func != NULL\n";
|
||||
struct support_capture_subprocess result;
|
||||
result = support_capture_subprocess (test_fn, NULL);
|
||||
support_capture_subprocess_check (&result, "bz20544", -SIGABRT,
|
@ -0,0 +1,22 @@
|
||||
commit 8fabe0e632bd441c760f878d1022c378f04f8497
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Aug 4 06:17:50 2022 +0200
|
||||
|
||||
Linux: Remove exit system call from _exit
|
||||
|
||||
exit only terminates the current thread, not the whole process, so it
|
||||
is the wrong fallback system call in this context. All supported
|
||||
Linux versions implement the exit_group system call anyway.
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/_exit.c b/sysdeps/unix/sysv/linux/_exit.c
|
||||
index 2f0ec35459f25314..cd1270ac9b2b5b2b 100644
|
||||
--- a/sysdeps/unix/sysv/linux/_exit.c
|
||||
+++ b/sysdeps/unix/sysv/linux/_exit.c
|
||||
@@ -28,7 +28,6 @@ _exit (int status)
|
||||
while (1)
|
||||
{
|
||||
INLINE_SYSCALL (exit_group, 1, status);
|
||||
- INLINE_SYSCALL (exit, 1, status);
|
||||
|
||||
#ifdef ABORT_INSTRUCTION
|
||||
ABORT_INSTRUCTION;
|
@ -0,0 +1,69 @@
|
||||
Very limited backport of the following upstream commit, to obtain
|
||||
the definition of __getrandom_nocancel.
|
||||
|
||||
commit 6f4e0fcfa2d2b0915816a3a3a1d48b4763a7dee2
|
||||
Author: Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>
|
||||
Date: Thu Jul 21 10:04:59 2022 -0300
|
||||
|
||||
stdlib: Add arc4random, arc4random_buf, and arc4random_uniform (BZ #4417)
|
||||
|
||||
With the INTERNAL_SYSCALL_CALL change from this patch already applied:
|
||||
|
||||
commit 609c9d0951da387cd523b5db42a82d38dabc37c4
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Thu Sep 29 16:18:06 2022 -0300
|
||||
|
||||
malloc: Do not clobber errno on __getrandom_nocancel (BZ #29624)
|
||||
|
||||
Use INTERNAL_SYSCALL_CALL instead of INLINE_SYSCALL_CALL. This
|
||||
requires emulate the semantic for hurd call (so __arc4random_buf
|
||||
uses the fallback).
|
||||
|
||||
Checked on x86_64-linux-gnu.
|
||||
|
||||
Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
|
||||
|
||||
diff --git a/sysdeps/generic/not-cancel.h b/sysdeps/generic/not-cancel.h
|
||||
index 8a3772a1fe66271e..14188041c2c0ad57 100644
|
||||
--- a/sysdeps/generic/not-cancel.h
|
||||
+++ b/sysdeps/generic/not-cancel.h
|
||||
@@ -49,5 +49,7 @@
|
||||
(void) __writev (fd, iov, n)
|
||||
#define __fcntl64_nocancel(fd, cmd, ...) \
|
||||
__fcntl64 (fd, cmd, __VA_ARGS__)
|
||||
+#define __getrandom_nocancel(buf, size, flags) \
|
||||
+ __getrandom (buf, size, flags)
|
||||
|
||||
#endif /* NOT_CANCEL_H */
|
||||
diff --git a/sysdeps/mach/hurd/not-cancel.h b/sysdeps/mach/hurd/not-cancel.h
|
||||
index cd320cb721e6ff7e..7a3d2cc3532cf866 100644
|
||||
--- a/sysdeps/mach/hurd/not-cancel.h
|
||||
+++ b/sysdeps/mach/hurd/not-cancel.h
|
||||
@@ -75,6 +75,9 @@ __typeof (__fcntl) __fcntl_nocancel;
|
||||
#define __fcntl64_nocancel(...) \
|
||||
__fcntl_nocancel (__VA_ARGS__)
|
||||
|
||||
+#define __getrandom_nocancel(buf, size, flags) \
|
||||
+ __getrandom (buf, size, flags)
|
||||
+
|
||||
#if IS_IN (libc)
|
||||
hidden_proto (__close_nocancel)
|
||||
hidden_proto (__close_nocancel_nostatus)
|
||||
diff --git a/sysdeps/unix/sysv/linux/not-cancel.h b/sysdeps/unix/sysv/linux/not-cancel.h
|
||||
index f06d57426a40227e..d2bb59acddbcfee0 100644
|
||||
--- a/sysdeps/unix/sysv/linux/not-cancel.h
|
||||
+++ b/sysdeps/unix/sysv/linux/not-cancel.h
|
||||
@@ -68,6 +68,13 @@ __writev_nocancel_nostatus (int fd, const struct iovec *iov, int iovcnt)
|
||||
INTERNAL_SYSCALL_CALL (writev, fd, iov, iovcnt);
|
||||
}
|
||||
|
||||
+static inline int
|
||||
+__getrandom_nocancel (void *buf, size_t buflen, unsigned int flags)
|
||||
+{
|
||||
+ return INTERNAL_SYSCALL_CALL (getrandom, buf, buflen, flags);
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* Uncancelable fcntl. */
|
||||
__typeof (__fcntl) __fcntl64_nocancel;
|
||||
|
@ -0,0 +1,35 @@
|
||||
commit 7187efd0aa270c83c428ea6cd0e1cffc34b41a74
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Aug 1 15:49:07 2022 +0200
|
||||
|
||||
malloc: Use __getrandom_nocancel during tcache initiailization
|
||||
|
||||
Cancellation currently cannot happen at this point because dlopen
|
||||
as used by the unwind link always performs additional allocations
|
||||
for libgcc_s.so.1, even if it has been loaded already as a dependency
|
||||
of the main executable. But it seems prudent not to rely on this
|
||||
quirk.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/malloc/malloc.c b/malloc/malloc.c
|
||||
index 2edb469d5dbf1203..375f50f5db13e234 100644
|
||||
--- a/malloc/malloc.c
|
||||
+++ b/malloc/malloc.c
|
||||
@@ -256,6 +256,7 @@
|
||||
/* For tcache double-free check. */
|
||||
#include <random-bits.h>
|
||||
#include <sys/random.h>
|
||||
+#include <not-cancel.h>
|
||||
|
||||
/*
|
||||
Debugging:
|
||||
@@ -3025,7 +3026,7 @@ static uintptr_t tcache_key;
|
||||
static void
|
||||
tcache_key_initialize (void)
|
||||
{
|
||||
- if (__getrandom (&tcache_key, sizeof(tcache_key), GRND_NONBLOCK)
|
||||
+ if (__getrandom_nocancel (&tcache_key, sizeof(tcache_key), GRND_NONBLOCK)
|
||||
!= sizeof (tcache_key))
|
||||
{
|
||||
tcache_key = random_bits ();
|
@ -0,0 +1,94 @@
|
||||
commit dd2315a866a4ac2b838ea1cb10c5ea1c35d51a2f
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 16 08:27:50 2022 +0200
|
||||
|
||||
elf: Run tst-audit-tlsdesc, tst-audit-tlsdesc-dlopen everywhere
|
||||
|
||||
The test is valid for all TLS models, but we want to make a reasonable
|
||||
effort to test the GNU2 model specifically. For example, aarch64
|
||||
defaults to GNU2, but does not have -mtls-dialect=gnu2, and the test
|
||||
was not run there.
|
||||
|
||||
Suggested-by: Martin Coufal <mcoufal@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
elf/Makefile
|
||||
(missing tst-align3 test downstream)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index ea1512549be3f628..613d244e7781d479 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -361,6 +361,8 @@ tests += \
|
||||
tst-addr1 \
|
||||
tst-align \
|
||||
tst-align2 \
|
||||
+ tst-audit-tlsdesc \
|
||||
+ tst-audit-tlsdesc-dlopen \
|
||||
tst-audit1 \
|
||||
tst-audit2 \
|
||||
tst-audit8 \
|
||||
@@ -679,6 +681,8 @@ modules-names = \
|
||||
tst-alignmod2 \
|
||||
tst-array2dep \
|
||||
tst-array5dep \
|
||||
+ tst-audit-tlsdesc-mod1 \
|
||||
+ tst-audit-tlsdesc-mod2 \
|
||||
tst-audit11mod1 \
|
||||
tst-audit11mod2 \
|
||||
tst-audit12mod1 \
|
||||
@@ -712,6 +716,7 @@ modules-names = \
|
||||
tst-auditmanymod7 \
|
||||
tst-auditmanymod8 \
|
||||
tst-auditmanymod9 \
|
||||
+ tst-auditmod-tlsdesc \
|
||||
tst-auditmod1 \
|
||||
tst-auditmod9a \
|
||||
tst-auditmod9b \
|
||||
@@ -889,23 +894,8 @@ modules-names += tst-gnu2-tls1mod
|
||||
$(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so
|
||||
tst-gnu2-tls1mod.so-no-z-defs = yes
|
||||
CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2
|
||||
+endif # $(have-mtls-dialect-gnu2)
|
||||
|
||||
-tests += tst-audit-tlsdesc tst-audit-tlsdesc-dlopen
|
||||
-modules-names += tst-audit-tlsdesc-mod1 tst-audit-tlsdesc-mod2 tst-auditmod-tlsdesc
|
||||
-$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \
|
||||
- $(objpfx)tst-audit-tlsdesc-mod2.so \
|
||||
- $(shared-thread-library)
|
||||
-CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=gnu2
|
||||
-CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=gnu2
|
||||
-$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library)
|
||||
-$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \
|
||||
- $(objpfx)tst-audit-tlsdesc-mod2.so
|
||||
-$(objpfx)tst-audit-tlsdesc-mod1.so: $(objpfx)tst-audit-tlsdesc-mod2.so
|
||||
-$(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so
|
||||
-tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
|
||||
-$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so
|
||||
-tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
|
||||
-endif
|
||||
ifeq (yes,$(have-protected-data))
|
||||
modules-names += tst-protected1moda tst-protected1modb
|
||||
tests += tst-protected1a tst-protected1b
|
||||
@@ -2656,3 +2646,21 @@ $(objpfx)tst-tls-allocation-failure-static-patched.out: \
|
||||
grep -q '^Fatal glibc error: Cannot allocate TLS block$$' $@ \
|
||||
&& grep -q '^status: 127$$' $@; \
|
||||
$(evaluate-test)
|
||||
+
|
||||
+$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-audit-tlsdesc-mod1.so \
|
||||
+ $(objpfx)tst-audit-tlsdesc-mod2.so \
|
||||
+ $(shared-thread-library)
|
||||
+ifeq (yes,$(have-mtls-dialect-gnu2))
|
||||
+# The test is valid for all TLS types, but we want to exercise GNU2
|
||||
+# TLS if possible.
|
||||
+CFLAGS-tst-audit-tlsdesc-mod1.c += -mtls-dialect=gnu2
|
||||
+CFLAGS-tst-audit-tlsdesc-mod2.c += -mtls-dialect=gnu2
|
||||
+endif
|
||||
+$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library)
|
||||
+$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-audit-tlsdesc-mod1.so \
|
||||
+ $(objpfx)tst-audit-tlsdesc-mod2.so
|
||||
+$(objpfx)tst-audit-tlsdesc-mod1.so: $(objpfx)tst-audit-tlsdesc-mod2.so
|
||||
+$(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so
|
||||
+tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
|
||||
+$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so
|
||||
+tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
|
@ -0,0 +1,37 @@
|
||||
commit 183d99737298bb3200f0610fdcd1c7549c8ed560
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Sep 6 07:38:10 2022 +0200
|
||||
|
||||
scripts/dso-ordering-test.py: Generate program run-time dependencies
|
||||
|
||||
The main program needs to depend on all shared objects, even objects
|
||||
that have link-time dependencies among shared objects. Filtering
|
||||
out shared objects that already have an link-time dependencies is not
|
||||
necessary here; make will do this automatically.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/scripts/dso-ordering-test.py b/scripts/dso-ordering-test.py
|
||||
index bde0406be9da14fc..4ffcff6136145ef1 100644
|
||||
--- a/scripts/dso-ordering-test.py
|
||||
+++ b/scripts/dso-ordering-test.py
|
||||
@@ -707,13 +707,12 @@ def process_testcase(t):
|
||||
"\t$(compile.c) $(OUTPUT_OPTION)\n")
|
||||
makefile.write (rule)
|
||||
|
||||
- not_depended_objs = find_objs_not_depended_on(test_descr)
|
||||
- if not_depended_objs:
|
||||
- depstr = ""
|
||||
- for dep in not_depended_objs:
|
||||
- depstr += (" $(objpfx)" + test_subdir + "/"
|
||||
- + test_name + "-" + dep + ".so")
|
||||
- makefile.write("$(objpfx)%s.out:%s\n" % (base_test_name, depstr))
|
||||
+ # Ensure that all shared objects are built before running the
|
||||
+ # test, whether there link-time dependencies or not.
|
||||
+ depobjs = ["$(objpfx){}/{}-{}.so".format(test_subdir, test_name, dep)
|
||||
+ for dep in test_descr.objs]
|
||||
+ makefile.write("$(objpfx){}.out: {}\n".format(
|
||||
+ base_test_name, " ".join(depobjs)))
|
||||
|
||||
# Add main executable to test-srcs
|
||||
makefile.write("test-srcs += %s/%s\n" % (test_subdir, test_name))
|
@ -0,0 +1,79 @@
|
||||
commit dbb75513f5cf9285c77c9e55777c5c35b653f890
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Sep 6 07:38:10 2022 +0200
|
||||
|
||||
elf: Rename _dl_sort_maps parameter from skip to force_first
|
||||
|
||||
The new implementation will not be able to skip an arbitrary number
|
||||
of objects.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
|
||||
index 72f4ff0e6eda3377..7c614bca5d8115c6 100644
|
||||
--- a/elf/dl-sort-maps.c
|
||||
+++ b/elf/dl-sort-maps.c
|
||||
@@ -27,12 +27,12 @@
|
||||
If FOR_FINI is true, this is called for finishing an object. */
|
||||
static void
|
||||
_dl_sort_maps_original (struct link_map **maps, unsigned int nmaps,
|
||||
- unsigned int skip, bool for_fini)
|
||||
+ bool force_first, bool for_fini)
|
||||
{
|
||||
/* Allows caller to do the common optimization of skipping the first map,
|
||||
usually the main binary. */
|
||||
- maps += skip;
|
||||
- nmaps -= skip;
|
||||
+ maps += force_first;
|
||||
+ nmaps -= force_first;
|
||||
|
||||
/* A list of one element need not be sorted. */
|
||||
if (nmaps <= 1)
|
||||
@@ -182,7 +182,7 @@ dfs_traversal (struct link_map ***rpo, struct link_map *map,
|
||||
|
||||
static void
|
||||
_dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
|
||||
- unsigned int skip __attribute__ ((unused)), bool for_fini)
|
||||
+ bool force_first __attribute__ ((unused)), bool for_fini)
|
||||
{
|
||||
for (int i = nmaps - 1; i >= 0; i--)
|
||||
maps[i]->l_visited = 0;
|
||||
@@ -286,7 +286,7 @@ _dl_sort_maps_init (void)
|
||||
|
||||
void
|
||||
_dl_sort_maps (struct link_map **maps, unsigned int nmaps,
|
||||
- unsigned int skip, bool for_fini)
|
||||
+ bool force_first, bool for_fini)
|
||||
{
|
||||
/* It can be tempting to use a static function pointer to store and call
|
||||
the current selected sorting algorithm routine, but experimentation
|
||||
@@ -296,9 +296,9 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps,
|
||||
input cases. A simple if-case with direct function calls appears to
|
||||
be the fastest. */
|
||||
if (__glibc_likely (GLRO(dl_dso_sort_algo) == dso_sort_algorithm_original))
|
||||
- _dl_sort_maps_original (maps, nmaps, skip, for_fini);
|
||||
+ _dl_sort_maps_original (maps, nmaps, force_first, for_fini);
|
||||
else
|
||||
- _dl_sort_maps_dfs (maps, nmaps, skip, for_fini);
|
||||
+ _dl_sort_maps_dfs (maps, nmaps, force_first, for_fini);
|
||||
}
|
||||
|
||||
#endif /* HAVE_TUNABLES. */
|
||||
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||
index 87ad2f3f4d89eb7d..8c0fe98f69a88f1e 100644
|
||||
--- a/sysdeps/generic/ldsodefs.h
|
||||
+++ b/sysdeps/generic/ldsodefs.h
|
||||
@@ -1106,9 +1106,11 @@ extern void _dl_init (struct link_map *main_map, int argc, char **argv,
|
||||
initializer functions have completed. */
|
||||
extern void _dl_fini (void) attribute_hidden;
|
||||
|
||||
-/* Sort array MAPS according to dependencies of the contained objects. */
|
||||
+/* Sort array MAPS according to dependencies of the contained objects.
|
||||
+ If FORCE_FIRST, MAPS[0] keeps its place even if the dependencies
|
||||
+ say otherwise. */
|
||||
extern void _dl_sort_maps (struct link_map **maps, unsigned int nmaps,
|
||||
- unsigned int skip, bool for_fini) attribute_hidden;
|
||||
+ bool force_first, bool for_fini) attribute_hidden;
|
||||
|
||||
/* The dynamic linker calls this function before and having changing
|
||||
any shared object mappings. The `r_state' member of `struct r_debug'
|
@ -0,0 +1,90 @@
|
||||
commit 1df71d32fe5f5905ffd5d100e5e9ca8ad6210891
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Sep 20 11:00:42 2022 +0200
|
||||
|
||||
elf: Implement force_first handling in _dl_sort_maps_dfs (bug 28937)
|
||||
|
||||
The implementation in _dl_close_worker requires that the first
|
||||
element of l_initfini is always this very map (“We are always the
|
||||
zeroth entry, and since we don't include ourselves in the
|
||||
dependency analysis start at 1.”). Rather than fixing that
|
||||
assumption, this commit adds an implementation of the force_first
|
||||
argument to the new dependency sorting algorithm. This also means
|
||||
that the directly dlopen'ed shared object is always initialized last,
|
||||
which is the least surprising behavior in the presence of cycles.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c
|
||||
index 7c614bca5d8115c6..e8ef5e8b3588ab53 100644
|
||||
--- a/elf/dl-sort-maps.c
|
||||
+++ b/elf/dl-sort-maps.c
|
||||
@@ -182,8 +182,9 @@ dfs_traversal (struct link_map ***rpo, struct link_map *map,
|
||||
|
||||
static void
|
||||
_dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
|
||||
- bool force_first __attribute__ ((unused)), bool for_fini)
|
||||
+ bool force_first, bool for_fini)
|
||||
{
|
||||
+ struct link_map *first_map = maps[0];
|
||||
for (int i = nmaps - 1; i >= 0; i--)
|
||||
maps[i]->l_visited = 0;
|
||||
|
||||
@@ -208,14 +209,6 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
|
||||
Adjusting the order so that maps[0] is last traversed naturally avoids
|
||||
this problem.
|
||||
|
||||
- Further, the old "optimization" of skipping the main object at maps[0]
|
||||
- from the call-site (i.e. _dl_sort_maps(maps+1,nmaps-1)) is in general
|
||||
- no longer valid, since traversing along object dependency-links
|
||||
- may "find" the main object even when it is not included in the initial
|
||||
- order (e.g. a dlopen()'ed shared object can have circular dependencies
|
||||
- linked back to itself). In such a case, traversing N-1 objects will
|
||||
- create a N-object result, and raise problems.
|
||||
-
|
||||
To summarize, just passing in the full list, and iterating from back
|
||||
to front makes things much more straightforward. */
|
||||
|
||||
@@ -274,6 +267,27 @@ _dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps,
|
||||
}
|
||||
|
||||
memcpy (maps, rpo, sizeof (struct link_map *) * nmaps);
|
||||
+
|
||||
+ /* Skipping the first object at maps[0] is not valid in general,
|
||||
+ since traversing along object dependency-links may "find" that
|
||||
+ first object even when it is not included in the initial order
|
||||
+ (e.g., a dlopen'ed shared object can have circular dependencies
|
||||
+ linked back to itself). In such a case, traversing N-1 objects
|
||||
+ will create a N-object result, and raise problems. Instead,
|
||||
+ force the object back into first place after sorting. This naive
|
||||
+ approach may introduce further dependency ordering violations
|
||||
+ compared to rotating the cycle until the first map is again in
|
||||
+ the first position, but as there is a cycle, at least one
|
||||
+ violation is already present. */
|
||||
+ if (force_first && maps[0] != first_map)
|
||||
+ {
|
||||
+ int i;
|
||||
+ for (i = 0; maps[i] != first_map; ++i)
|
||||
+ ;
|
||||
+ assert (i < nmaps);
|
||||
+ memmove (&maps[1], maps, i * sizeof (maps[0]));
|
||||
+ maps[0] = first_map;
|
||||
+ }
|
||||
}
|
||||
|
||||
void
|
||||
diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def
|
||||
index 5f7f18ef270bc12d..4bf9052db16fb352 100644
|
||||
--- a/elf/dso-sort-tests-1.def
|
||||
+++ b/elf/dso-sort-tests-1.def
|
||||
@@ -64,3 +64,10 @@ output: b>a>{}<a<b
|
||||
tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};a->b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c
|
||||
output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<a<c<d<g<f<b<e];}
|
||||
output(glibc.rtld.dynamic_sort=2): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[<g<f<a<b<c<d<e];}
|
||||
+
|
||||
+# Test that even in the presence of dependency loops involving dlopen'ed
|
||||
+# object, that object is initialized last (and not unloaded prematurely).
|
||||
+# Final destructor order is indeterminate due to the cycle.
|
||||
+tst-bz28937: {+a;+b;-b;+c;%c};a->a1;a->a2;a2->a;b->b1;c->a1;c=>a1
|
||||
+output(glibc.rtld.dynamic_sort=1): {+a[a2>a1>a>];+b[b1>b>];-b[<b<b1];+c[c>];%c(a1());}<a<a2<c<a1
|
||||
+output(glibc.rtld.dynamic_sort=2): {+a[a2>a1>a>];+b[b1>b>];-b[<b<b1];+c[c>];%c(a1());}<a2<a<c<a1
|
@ -0,0 +1,589 @@
|
||||
commit 1d495912a746e2a1ffb780c9a81fd234ec2464e8
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
nss_dns: Rewrite _nss_dns_gethostbyname4_r using current interfaces
|
||||
|
||||
Introduce struct alloc_buffer to this function, and use it and
|
||||
struct ns_rr_cursor in gaih_getanswer_slice. Adjust gaih_getanswer
|
||||
and gaih_getanswer_noaaaa accordingly.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 1cb3be71f04d98eb..36789965c06757d0 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -101,13 +101,6 @@
|
||||
#endif
|
||||
#define MAXHOSTNAMELEN 256
|
||||
|
||||
-/* We need this time later. */
|
||||
-typedef union querybuf
|
||||
-{
|
||||
- HEADER hdr;
|
||||
- u_char buf[MAXPACKET];
|
||||
-} querybuf;
|
||||
-
|
||||
/* For historic reasons, pointers to IP addresses are char *, so use a
|
||||
single list type for addresses and host names. */
|
||||
#define DYNARRAY_STRUCT ptrlist
|
||||
@@ -126,18 +119,18 @@ static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen,
|
||||
char **hnamep, int *errnop,
|
||||
int *h_errnop, int32_t *ttlp);
|
||||
|
||||
-static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1,
|
||||
- const querybuf *answer2, int anslen2,
|
||||
- const char *qname,
|
||||
+static enum nss_status gaih_getanswer (unsigned char *packet1,
|
||||
+ size_t packet1len,
|
||||
+ unsigned char *packet2,
|
||||
+ size_t packet2len,
|
||||
+ struct alloc_buffer *abuf,
|
||||
struct gaih_addrtuple **pat,
|
||||
- char *buffer, size_t buflen,
|
||||
int *errnop, int *h_errnop,
|
||||
int32_t *ttlp);
|
||||
-static enum nss_status gaih_getanswer_noaaaa (const querybuf *answer1,
|
||||
- int anslen1,
|
||||
- const char *qname,
|
||||
+static enum nss_status gaih_getanswer_noaaaa (unsigned char *packet,
|
||||
+ size_t packetlen,
|
||||
+ struct alloc_buffer *abuf,
|
||||
struct gaih_addrtuple **pat,
|
||||
- char *buffer, size_t buflen,
|
||||
int *errnop, int *h_errnop,
|
||||
int32_t *ttlp);
|
||||
|
||||
@@ -409,17 +402,13 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
|
||||
name = cp;
|
||||
}
|
||||
|
||||
- union
|
||||
- {
|
||||
- querybuf *buf;
|
||||
- u_char *ptr;
|
||||
- } host_buffer;
|
||||
- querybuf *orig_host_buffer;
|
||||
- host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048);
|
||||
+ unsigned char dns_packet_buffer[2048];
|
||||
+ unsigned char *alt_dns_packet_buffer = dns_packet_buffer;
|
||||
u_char *ans2p = NULL;
|
||||
int nans2p = 0;
|
||||
int resplen2 = 0;
|
||||
int ans2p_malloced = 0;
|
||||
+ struct alloc_buffer abuf = alloc_buffer_create (buffer, buflen);
|
||||
|
||||
|
||||
int olderr = errno;
|
||||
@@ -428,22 +417,21 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
|
||||
if ((ctx->resp->options & RES_NOAAAA) == 0)
|
||||
{
|
||||
n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
|
||||
- host_buffer.buf->buf, 2048, &host_buffer.ptr,
|
||||
- &ans2p, &nans2p, &resplen2, &ans2p_malloced);
|
||||
+ dns_packet_buffer, sizeof (dns_packet_buffer),
|
||||
+ &alt_dns_packet_buffer, &ans2p, &nans2p,
|
||||
+ &resplen2, &ans2p_malloced);
|
||||
if (n >= 0)
|
||||
- status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
|
||||
- resplen2, name, pat, buffer, buflen,
|
||||
- errnop, herrnop, ttlp);
|
||||
+ status = gaih_getanswer (alt_dns_packet_buffer, n, ans2p, resplen2,
|
||||
+ &abuf, pat, errnop, herrnop, ttlp);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = __res_context_search (ctx, name, C_IN, T_A,
|
||||
- host_buffer.buf->buf, 2048, NULL,
|
||||
- NULL, NULL, NULL, NULL);
|
||||
+ dns_packet_buffer, sizeof (dns_packet_buffer),
|
||||
+ NULL, NULL, NULL, NULL, NULL);
|
||||
if (n >= 0)
|
||||
- status = gaih_getanswer_noaaaa (host_buffer.buf, n,
|
||||
- name, pat, buffer, buflen,
|
||||
- errnop, herrnop, ttlp);
|
||||
+ status = gaih_getanswer_noaaaa (alt_dns_packet_buffer, n,
|
||||
+ &abuf, pat, errnop, herrnop, ttlp);
|
||||
}
|
||||
if (n < 0)
|
||||
{
|
||||
@@ -474,12 +462,20 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
|
||||
__set_errno (olderr);
|
||||
}
|
||||
|
||||
+ /* Implement the buffer resizing protocol. */
|
||||
+ if (alloc_buffer_has_failed (&abuf))
|
||||
+ {
|
||||
+ *errnop = ERANGE;
|
||||
+ *herrnop = NETDB_INTERNAL;
|
||||
+ status = NSS_STATUS_TRYAGAIN;
|
||||
+ }
|
||||
+
|
||||
/* Check whether ans2p was separately allocated. */
|
||||
if (ans2p_malloced)
|
||||
free (ans2p);
|
||||
|
||||
- if (host_buffer.buf != orig_host_buffer)
|
||||
- free (host_buffer.buf);
|
||||
+ if (alt_dns_packet_buffer != dns_packet_buffer)
|
||||
+ free (alt_dns_packet_buffer);
|
||||
|
||||
__resolv_context_put (ctx);
|
||||
return status;
|
||||
@@ -893,259 +889,152 @@ getanswer_ptr (unsigned char *packet, size_t packetlen,
|
||||
return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
|
||||
+/* Parses DNS data found in PACKETLEN bytes at PACKET in struct
|
||||
+ gaih_addrtuple address tuples. The new address tuples are linked
|
||||
+ from **TAILP, with backing store allocated from ABUF, and *TAILP is
|
||||
+ updated to point where the next tuple pointer should be stored. If
|
||||
+ TTLP is not null, *TTLP is updated to reflect the minimum TTL. If
|
||||
+ STORE_CANON is true, the canonical name is stored as part of the
|
||||
+ first address tuple being written. */
|
||||
static enum nss_status
|
||||
-gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
- struct gaih_addrtuple ***patp,
|
||||
- char **bufferp, size_t *buflenp,
|
||||
- int *errnop, int *h_errnop, int32_t *ttlp, int *firstp)
|
||||
+gaih_getanswer_slice (unsigned char *packet, size_t packetlen,
|
||||
+ struct alloc_buffer *abuf,
|
||||
+ struct gaih_addrtuple ***tailp,
|
||||
+ int *errnop, int *h_errnop, int32_t *ttlp,
|
||||
+ bool store_canon)
|
||||
{
|
||||
- char *buffer = *bufferp;
|
||||
- size_t buflen = *buflenp;
|
||||
-
|
||||
- struct gaih_addrtuple **pat = *patp;
|
||||
- const HEADER *hp = &answer->hdr;
|
||||
- int ancount = ntohs (hp->ancount);
|
||||
- int qdcount = ntohs (hp->qdcount);
|
||||
- const u_char *cp = answer->buf + HFIXEDSZ;
|
||||
- const u_char *end_of_message = answer->buf + anslen;
|
||||
- if (__glibc_unlikely (qdcount != 1))
|
||||
- {
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
- }
|
||||
-
|
||||
- u_char packtmp[NS_MAXCDNAME];
|
||||
- int n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
- packtmp, sizeof packtmp);
|
||||
- /* We unpack the name to check it for validity. But we do not need
|
||||
- it later. */
|
||||
- if (n != -1 && __ns_name_ntop (packtmp, buffer, buflen) == -1)
|
||||
- {
|
||||
- if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
- {
|
||||
- too_small:
|
||||
- *errnop = ERANGE;
|
||||
- *h_errnop = NETDB_INTERNAL;
|
||||
- return NSS_STATUS_TRYAGAIN;
|
||||
- }
|
||||
-
|
||||
- n = -1;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (n < 0))
|
||||
- {
|
||||
- *errnop = errno;
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
- }
|
||||
- if (__glibc_unlikely (__libc_res_hnok (buffer) == 0))
|
||||
+ struct ns_rr_cursor c;
|
||||
+ if (!__ns_rr_cursor_init (&c, packet, packetlen))
|
||||
{
|
||||
- errno = EBADMSG;
|
||||
- *errnop = EBADMSG;
|
||||
+ /* This should not happen because __res_context_query already
|
||||
+ perfroms response validation. */
|
||||
*h_errnop = NO_RECOVERY;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- cp += n + QFIXEDSZ;
|
||||
+ bool haveanswer = false; /* Set to true if at least one address. */
|
||||
+ uint16_t qtype = ns_rr_cursor_qtype (&c);
|
||||
+ int ancount = ns_rr_cursor_ancount (&c);
|
||||
+ const unsigned char *expected_name = ns_rr_cursor_qname (&c);
|
||||
+ /* expected_name may be updated to point into this buffer. */
|
||||
+ unsigned char name_buffer[NS_MAXCDNAME];
|
||||
|
||||
- int haveanswer = 0;
|
||||
- int had_error = 0;
|
||||
- char *canon = NULL;
|
||||
- char *h_name = NULL;
|
||||
- int h_namelen = 0;
|
||||
+ /* This is a pointer to a possibly-compressed name in the packet.
|
||||
+ Eventually it is equivalent to the canonical name. If needed, it
|
||||
+ is uncompressed and translated to text form when the first
|
||||
+ address tuple is encountered. */
|
||||
+ const unsigned char *compressed_alias_name = expected_name;
|
||||
|
||||
- if (ancount == 0)
|
||||
+ if (ancount == 0 || !__res_binary_hnok (compressed_alias_name))
|
||||
{
|
||||
*h_errnop = HOST_NOT_FOUND;
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
- while (ancount-- > 0 && cp < end_of_message && had_error == 0)
|
||||
+ for (; ancount > -0; --ancount)
|
||||
{
|
||||
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
- packtmp, sizeof packtmp);
|
||||
- if (n != -1 &&
|
||||
- (h_namelen = __ns_name_ntop (packtmp, buffer, buflen)) == -1)
|
||||
- {
|
||||
- if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
- goto too_small;
|
||||
-
|
||||
- n = -1;
|
||||
- }
|
||||
- if (__glibc_unlikely (n < 0))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
- if (*firstp && canon == NULL && __libc_res_hnok (buffer))
|
||||
- {
|
||||
- h_name = buffer;
|
||||
- buffer += h_namelen;
|
||||
- buflen -= h_namelen;
|
||||
- }
|
||||
-
|
||||
- cp += n; /* name */
|
||||
-
|
||||
- if (__glibc_unlikely (cp + 10 > end_of_message))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- uint16_t type;
|
||||
- NS_GET16 (type, cp);
|
||||
- uint16_t class;
|
||||
- NS_GET16 (class, cp);
|
||||
- int32_t ttl;
|
||||
- NS_GET32 (ttl, cp);
|
||||
- NS_GET16 (n, cp); /* RDATA length. */
|
||||
-
|
||||
- if (end_of_message - cp < n)
|
||||
+ struct ns_rr_wire rr;
|
||||
+ if (!__ns_rr_cursor_next (&c, &rr))
|
||||
{
|
||||
- /* RDATA extends beyond the end of the packet. */
|
||||
- ++had_error;
|
||||
- continue;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
- if (class != C_IN)
|
||||
- {
|
||||
- cp += n;
|
||||
- continue;
|
||||
- }
|
||||
+ /* Update TTL for known record types. */
|
||||
+ if ((rr.rtype == T_CNAME || rr.rtype == qtype)
|
||||
+ && ttlp != NULL && *ttlp > rr.ttl)
|
||||
+ *ttlp = rr.ttl;
|
||||
|
||||
- if (type == T_CNAME)
|
||||
+ if (rr.rtype == T_CNAME)
|
||||
{
|
||||
- char tbuf[MAXDNAME];
|
||||
-
|
||||
- /* A CNAME could also have a TTL entry. */
|
||||
- if (ttlp != NULL && ttl < *ttlp)
|
||||
- *ttlp = ttl;
|
||||
-
|
||||
- n = __libc_dn_expand (answer->buf, end_of_message, cp,
|
||||
- tbuf, sizeof tbuf);
|
||||
- if (__glibc_unlikely (n < 0))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
- cp += n;
|
||||
-
|
||||
- if (*firstp && __libc_res_hnok (tbuf))
|
||||
+ /* NB: No check for owner name match, based on historic
|
||||
+ precedent. Record the CNAME target as the new expected
|
||||
+ name. */
|
||||
+ int n = __ns_name_unpack (c.begin, c.end, rr.rdata,
|
||||
+ name_buffer, sizeof (name_buffer));
|
||||
+ if (n < 0)
|
||||
{
|
||||
- /* Reclaim buffer space. */
|
||||
- if (h_name + h_namelen == buffer)
|
||||
- {
|
||||
- buffer = h_name;
|
||||
- buflen += h_namelen;
|
||||
- }
|
||||
-
|
||||
- n = strlen (tbuf) + 1;
|
||||
- if (__glibc_unlikely (n > buflen))
|
||||
- goto too_small;
|
||||
- if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- canon = buffer;
|
||||
- buffer = __mempcpy (buffer, tbuf, n);
|
||||
- buflen -= n;
|
||||
- h_namelen = 0;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- continue;
|
||||
+ expected_name = name_buffer;
|
||||
+ if (store_canon && __res_binary_hnok (name_buffer))
|
||||
+ /* This name can be used as a canonical name. Do not
|
||||
+ translate to text form here to conserve buffer space.
|
||||
+ Point to the compressed name because name_buffer can be
|
||||
+ overwritten with an unusable name later. */
|
||||
+ compressed_alias_name = rr.rdata;
|
||||
}
|
||||
-
|
||||
- /* Stop parsing if we encounter a record with incorrect RDATA
|
||||
- length. */
|
||||
- if (type == T_A || type == T_AAAA)
|
||||
+ else if (rr.rtype == qtype
|
||||
+ && __ns_samebinaryname (rr.rname, expected_name)
|
||||
+ && rr.rdlength == rrtype_to_rdata_length (qtype))
|
||||
{
|
||||
- if (n != rrtype_to_rdata_length (type))
|
||||
+ struct gaih_addrtuple *ntup
|
||||
+ = alloc_buffer_alloc (abuf, struct gaih_addrtuple);
|
||||
+ /* Delay error reporting to the callers (they implement the
|
||||
+ ERANGE buffer resizing handshake). */
|
||||
+ if (ntup != NULL)
|
||||
{
|
||||
- ++had_error;
|
||||
- continue;
|
||||
+ ntup->next = NULL;
|
||||
+ if (store_canon && compressed_alias_name != NULL)
|
||||
+ {
|
||||
+ /* This assumes that all the CNAME records come
|
||||
+ first. Use MAXHOSTNAMELEN instead of
|
||||
+ NS_MAXCDNAME for additional length checking.
|
||||
+ However, these checks are not expected to fail
|
||||
+ because all size NS_MAXCDNAME names should into
|
||||
+ the hname buffer because no escaping is
|
||||
+ needed. */
|
||||
+ char unsigned nbuf[NS_MAXCDNAME];
|
||||
+ char hname[MAXHOSTNAMELEN + 1];
|
||||
+ if (__ns_name_unpack (c.begin, c.end,
|
||||
+ compressed_alias_name,
|
||||
+ nbuf, sizeof (nbuf)) >= 0
|
||||
+ && __ns_name_ntop (nbuf, hname, sizeof (hname)) >= 0)
|
||||
+ /* Space checking is performed by the callers. */
|
||||
+ ntup->name = alloc_buffer_copy_string (abuf, hname);
|
||||
+ store_canon = false;
|
||||
+ }
|
||||
+ else
|
||||
+ ntup->name = NULL;
|
||||
+ if (rr.rdlength == 4)
|
||||
+ ntup->family = AF_INET;
|
||||
+ else
|
||||
+ ntup->family = AF_INET6;
|
||||
+ memcpy (ntup->addr, rr.rdata, rr.rdlength);
|
||||
+ ntup->scopeid = 0;
|
||||
+
|
||||
+ /* Link in the new tuple, and update the tail pointer to
|
||||
+ point to its next field. */
|
||||
+ **tailp = ntup;
|
||||
+ *tailp = &ntup->next;
|
||||
+
|
||||
+ haveanswer = true;
|
||||
}
|
||||
}
|
||||
- else
|
||||
- {
|
||||
- /* Skip unknown records. */
|
||||
- cp += n;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- assert (type == T_A || type == T_AAAA);
|
||||
- if (*pat == NULL)
|
||||
- {
|
||||
- uintptr_t pad = (-(uintptr_t) buffer
|
||||
- % __alignof__ (struct gaih_addrtuple));
|
||||
- buffer += pad;
|
||||
- buflen = buflen > pad ? buflen - pad : 0;
|
||||
-
|
||||
- if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple)))
|
||||
- goto too_small;
|
||||
-
|
||||
- *pat = (struct gaih_addrtuple *) buffer;
|
||||
- buffer += sizeof (struct gaih_addrtuple);
|
||||
- buflen -= sizeof (struct gaih_addrtuple);
|
||||
- }
|
||||
-
|
||||
- (*pat)->name = NULL;
|
||||
- (*pat)->next = NULL;
|
||||
-
|
||||
- if (*firstp)
|
||||
- {
|
||||
- /* We compose a single hostent out of the entire chain of
|
||||
- entries, so the TTL of the hostent is essentially the lowest
|
||||
- TTL in the chain. */
|
||||
- if (ttlp != NULL && ttl < *ttlp)
|
||||
- *ttlp = ttl;
|
||||
-
|
||||
- (*pat)->name = canon ?: h_name;
|
||||
-
|
||||
- *firstp = 0;
|
||||
- }
|
||||
-
|
||||
- (*pat)->family = type == T_A ? AF_INET : AF_INET6;
|
||||
- memcpy ((*pat)->addr, cp, n);
|
||||
- cp += n;
|
||||
- (*pat)->scopeid = 0;
|
||||
-
|
||||
- pat = &((*pat)->next);
|
||||
-
|
||||
- haveanswer = 1;
|
||||
}
|
||||
|
||||
if (haveanswer)
|
||||
{
|
||||
- *patp = pat;
|
||||
- *bufferp = buffer;
|
||||
- *buflenp = buflen;
|
||||
-
|
||||
*h_errnop = NETDB_SUCCESS;
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
-
|
||||
- /* Special case here: if the resolver sent a result but it only
|
||||
- contains a CNAME while we are looking for a T_A or T_AAAA record,
|
||||
- we fail with NOTFOUND instead of TRYAGAIN. */
|
||||
- if (canon != NULL)
|
||||
+ else
|
||||
{
|
||||
+ /* Special case here: if the resolver sent a result but it only
|
||||
+ contains a CNAME while we are looking for a T_A or T_AAAA
|
||||
+ record, we fail with NOTFOUND. */
|
||||
*h_errnop = HOST_NOT_FOUND;
|
||||
return NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
-
|
||||
- *h_errnop = NETDB_INTERNAL;
|
||||
- return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
|
||||
|
||||
static enum nss_status
|
||||
-gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||||
- int anslen2, const char *qname,
|
||||
- struct gaih_addrtuple **pat, char *buffer, size_t buflen,
|
||||
+gaih_getanswer (unsigned char *packet1, size_t packet1len,
|
||||
+ unsigned char *packet2, size_t packet2len,
|
||||
+ struct alloc_buffer *abuf, struct gaih_addrtuple **pat,
|
||||
int *errnop, int *h_errnop, int32_t *ttlp)
|
||||
{
|
||||
- int first = 1;
|
||||
-
|
||||
enum nss_status status = NSS_STATUS_NOTFOUND;
|
||||
|
||||
/* Combining the NSS status of two distinct queries requires some
|
||||
@@ -1157,7 +1046,10 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||||
between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
|
||||
A recoverable TRYAGAIN is almost always due to buffer size issues
|
||||
and returns ERANGE in errno and the caller is expected to retry
|
||||
- with a larger buffer.
|
||||
+ with a larger buffer. (The caller, _nss_dns_gethostbyname4_r,
|
||||
+ ignores the return status if it detects that the result buffer
|
||||
+ has been exhausted and generates a TRYAGAIN failure with an
|
||||
+ ERANGE code.)
|
||||
|
||||
Lastly, you may be tempted to make significant changes to the
|
||||
conditions in this code to bring about symmetry between responses.
|
||||
@@ -1237,36 +1129,30 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||||
is a recoverable error we now return TRYAGIN even if the first
|
||||
response was SUCCESS. */
|
||||
|
||||
- if (anslen1 > 0)
|
||||
- status = gaih_getanswer_slice(answer1, anslen1, qname,
|
||||
- &pat, &buffer, &buflen,
|
||||
- errnop, h_errnop, ttlp,
|
||||
- &first);
|
||||
-
|
||||
- if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
|
||||
- || (status == NSS_STATUS_TRYAGAIN
|
||||
- /* We want to look at the second answer in case of an
|
||||
- NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e.
|
||||
- *h_errnop is NO_RECOVERY. If not, and if the failure was due to
|
||||
- an insufficient buffer (ERANGE), then we need to drop the results
|
||||
- and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can
|
||||
- repeat the query with a larger buffer. */
|
||||
- && (*errnop != ERANGE || *h_errnop == NO_RECOVERY)))
|
||||
- && answer2 != NULL && anslen2 > 0)
|
||||
+ if (packet1len > 0)
|
||||
{
|
||||
- enum nss_status status2 = gaih_getanswer_slice(answer2, anslen2, qname,
|
||||
- &pat, &buffer, &buflen,
|
||||
- errnop, h_errnop, ttlp,
|
||||
- &first);
|
||||
+ status = gaih_getanswer_slice (packet1, packet1len,
|
||||
+ abuf, &pat, errnop, h_errnop, ttlp, true);
|
||||
+ if (alloc_buffer_has_failed (abuf))
|
||||
+ /* Do not try parsing the second packet if a larger result
|
||||
+ buffer is needed. The caller implements the resizing
|
||||
+ protocol because *abuf has been exhausted. */
|
||||
+ return NSS_STATUS_TRYAGAIN; /* Ignored by the caller. */
|
||||
+ }
|
||||
+
|
||||
+ if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND)
|
||||
+ && packet2 != NULL && packet2len > 0)
|
||||
+ {
|
||||
+ enum nss_status status2
|
||||
+ = gaih_getanswer_slice (packet2, packet2len,
|
||||
+ abuf, &pat, errnop, h_errnop, ttlp,
|
||||
+ /* Success means that data with a
|
||||
+ canonical name has already been
|
||||
+ stored. Do not store the name again. */
|
||||
+ status != NSS_STATUS_SUCCESS);
|
||||
/* Use the second response status in some cases. */
|
||||
if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
|
||||
status = status2;
|
||||
- /* Do not return a truncated second response (unless it was
|
||||
- unavoidable e.g. unrecoverable TRYAGAIN). */
|
||||
- if (status == NSS_STATUS_SUCCESS
|
||||
- && (status2 == NSS_STATUS_TRYAGAIN
|
||||
- && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
|
||||
- status = NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
|
||||
return status;
|
||||
@@ -1274,18 +1160,13 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||||
|
||||
/* Variant of gaih_getanswer without a second (AAAA) response. */
|
||||
static enum nss_status
|
||||
-gaih_getanswer_noaaaa (const querybuf *answer1, int anslen1, const char *qname,
|
||||
- struct gaih_addrtuple **pat,
|
||||
- char *buffer, size_t buflen,
|
||||
+gaih_getanswer_noaaaa (unsigned char *packet, size_t packetlen,
|
||||
+ struct alloc_buffer *abuf, struct gaih_addrtuple **pat,
|
||||
int *errnop, int *h_errnop, int32_t *ttlp)
|
||||
{
|
||||
- int first = 1;
|
||||
-
|
||||
enum nss_status status = NSS_STATUS_NOTFOUND;
|
||||
- if (anslen1 > 0)
|
||||
- status = gaih_getanswer_slice (answer1, anslen1, qname,
|
||||
- &pat, &buffer, &buflen,
|
||||
- errnop, h_errnop, ttlp,
|
||||
- &first);
|
||||
+ if (packetlen > 0)
|
||||
+ status = gaih_getanswer_slice (packet, packetlen,
|
||||
+ abuf, &pat, errnop, h_errnop, ttlp, true);
|
||||
return status;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
commit b8c6166b1b75036ab3e4127a1c0aacf52ca93651
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Sep 6 19:43:37 2021 +0200
|
||||
|
||||
locale: Add missing second argument to _Static_assert in C-collate-seq.c
|
||||
|
||||
diff --git a/locale/C-collate-seq.c b/locale/C-collate-seq.c
|
||||
index 4fb82cb8357936b6..40b17f4f90313144 100644
|
||||
--- a/locale/C-collate-seq.c
|
||||
+++ b/locale/C-collate-seq.c
|
||||
@@ -55,7 +55,7 @@ static const char collseqmb[] =
|
||||
|
||||
/* This table must be 256 bytes in size. We index bytes into the
|
||||
table to find the collation sequence. */
|
||||
-_Static_assert (sizeof (collseqmb) == 256);
|
||||
+_Static_assert (sizeof (collseqmb) == 256, "sizeof (collseqmb)");
|
||||
|
||||
static const uint32_t collseqwc[] =
|
||||
{
|
@ -0,0 +1,306 @@
|
||||
Maintain an explicit order of tunables, so that the tunable_list
|
||||
array and the tunable_id_t constant can remain consistent over time.
|
||||
|
||||
Related to this upstream bug:
|
||||
|
||||
Internal tunables ABI depends on awk array iteration order
|
||||
<https://sourceware.org/bugzilla/show_bug.cgi?id=30027>
|
||||
|
||||
The new dl-tunables.list files are already on the sysdeps search
|
||||
path, which is why the existing Makeconfig rule picks them up.
|
||||
The files for RHEL 9.1z were created by applying the gen-tunables.awk
|
||||
part of this patch to RHEL 9.1.0 (glibc-2.34-40.el9_2.1, to be
|
||||
precise). The sysdeps/unix/sysv/linux/**/dl-tunables.list files were
|
||||
created based on the generated error message during the RHEL 9.1.z
|
||||
build.
|
||||
|
||||
Going forward, new tunables will have to be added manually to the end
|
||||
of those files. Existing tunables should not be deleted. For
|
||||
deletion, the script would have to be extended to be able to create
|
||||
gaps in the tunable_list array.
|
||||
|
||||
diff --git a/scripts/gen-tunables.awk b/scripts/gen-tunables.awk
|
||||
index fa63e86d1a51fe61..c5445e95f9fc36e7 100644
|
||||
--- a/scripts/gen-tunables.awk
|
||||
+++ b/scripts/gen-tunables.awk
|
||||
@@ -14,6 +14,7 @@ BEGIN {
|
||||
top_ns=""
|
||||
max_name_len=0
|
||||
max_alias_len=0
|
||||
+ tunable_order_count = 0
|
||||
}
|
||||
|
||||
# Skip over blank lines and comments.
|
||||
@@ -83,6 +84,37 @@ $1 == "}" {
|
||||
next
|
||||
}
|
||||
|
||||
+$1 == "@order" {
|
||||
+ if (top_ns != "") {
|
||||
+ printf("%s:%d: error: invalid @order directive inside namespace %s\n",
|
||||
+ FILENAME, FNR, top_ns) > "/dev/stderr"
|
||||
+ exit 1
|
||||
+ }
|
||||
+ if (NF != 2) {
|
||||
+ printf("%s:%d: error: invalid argument count in @order directive\n",
|
||||
+ FILENAME, FNR) > "/dev/stderr"
|
||||
+ exit 1
|
||||
+ }
|
||||
+ order_arg = $2
|
||||
+ if (split(order_arg, indices, /\./) != 3) {
|
||||
+ printf("%s:%d: error: invalid tunable syntax in @order directive\n",
|
||||
+ FILENAME, FNR) > "/dev/stderr"
|
||||
+ exit 1
|
||||
+ }
|
||||
+ t = indices[1]
|
||||
+ n = indices[2]
|
||||
+ m = indices[3]
|
||||
+ if ((t, n, m) in tunable_order) {
|
||||
+ printf("%s:%d: error: duplicate\"@order %s\"\n" \
|
||||
+ FILENAME, FNR, order_arg) > "/dev/stderr"
|
||||
+ exit 1
|
||||
+ }
|
||||
+ ++tunable_order_count
|
||||
+ tunable_order[t,n,m] = tunable_order_count
|
||||
+ tunable_order_list[tunable_order_count] = t SUBSEP n SUBSEP m
|
||||
+ next
|
||||
+}
|
||||
+
|
||||
# Everything else, which could either be a tunable without any attributes or a
|
||||
# tunable attribute.
|
||||
{
|
||||
@@ -145,6 +177,31 @@ END {
|
||||
exit 1
|
||||
}
|
||||
|
||||
+ missing_order = 0
|
||||
+ for (tnm in types) {
|
||||
+ if (!(tnm in tunable_order)) {
|
||||
+ if (!missing_order) {
|
||||
+ print "error: Missing @order directives:" > "/dev/stderr"
|
||||
+ missing_order = 1
|
||||
+ }
|
||||
+ split(tnm, indices, SUBSEP)
|
||||
+ printf("@order %s.%s.%s\n", indices[1], indices[2], indices[3]) \
|
||||
+ > "/dev/stderr"
|
||||
+ }
|
||||
+ }
|
||||
+ for (i = 1; i <= tunable_order_count; ++i) {
|
||||
+ tnm = tunable_order_list[i]
|
||||
+ if (!(tnm in types)) {
|
||||
+ split(tnm, indices, SUBSEP)
|
||||
+ printf("error: tunable in \"@order %s.%s.%s\" not known\n", \
|
||||
+ indices[1], indices[2], indices[3]) > "/dev/stderr"
|
||||
+ missing_order = 1
|
||||
+ }
|
||||
+ }
|
||||
+ if (missing_order) {
|
||||
+ exit 1
|
||||
+ }
|
||||
+
|
||||
print "/* AUTOGENERATED by gen-tunables.awk. */"
|
||||
print "#ifndef _TUNABLES_H_"
|
||||
print "# error \"Do not include this file directly.\""
|
||||
@@ -155,7 +212,8 @@ END {
|
||||
# Now, the enum names
|
||||
print "\ntypedef enum"
|
||||
print "{"
|
||||
- for (tnm in types) {
|
||||
+ for (i = 1; i <= tunable_order_count; ++i) {
|
||||
+ tnm = tunable_order_list[i]
|
||||
split (tnm, indices, SUBSEP);
|
||||
t = indices[1];
|
||||
n = indices[2];
|
||||
@@ -171,7 +229,8 @@ END {
|
||||
print "# include \"dl-tunable-types.h\""
|
||||
# Finally, the tunable list.
|
||||
print "static tunable_t tunable_list[] attribute_relro = {"
|
||||
- for (tnm in types) {
|
||||
+ for (i = 1; i <= tunable_order_count; ++i) {
|
||||
+ tnm = tunable_order_list[i]
|
||||
split (tnm, indices, SUBSEP);
|
||||
t = indices[1];
|
||||
n = indices[2];
|
||||
diff --git a/sysdeps/unix/sysv/linux/aarch64/dl-tunables.list b/sysdeps/unix/sysv/linux/aarch64/dl-tunables.list
|
||||
new file mode 100644
|
||||
index 0000000000000000..d9d62499be4d67cb
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/aarch64/dl-tunables.list
|
||||
@@ -0,0 +1,28 @@
|
||||
+# Order of tunables in RHEL 9.1.z.
|
||||
+@order glibc.rtld.nns
|
||||
+@order glibc.elision.skip_lock_after_retries
|
||||
+@order glibc.malloc.trim_threshold
|
||||
+@order glibc.malloc.perturb
|
||||
+@order glibc.pthread.rseq
|
||||
+@order glibc.cpu.name
|
||||
+@order glibc.mem.tagging
|
||||
+@order glibc.elision.tries
|
||||
+@order glibc.elision.enable
|
||||
+@order glibc.malloc.mxfast
|
||||
+@order glibc.rtld.dynamic_sort
|
||||
+@order glibc.elision.skip_lock_busy
|
||||
+@order glibc.malloc.top_pad
|
||||
+@order glibc.pthread.stack_cache_size
|
||||
+@order glibc.cpu.hwcap_mask
|
||||
+@order glibc.malloc.mmap_max
|
||||
+@order glibc.elision.skip_trylock_internal_abort
|
||||
+@order glibc.malloc.tcache_unsorted_limit
|
||||
+@order glibc.elision.skip_lock_internal_abort
|
||||
+@order glibc.malloc.arena_max
|
||||
+@order glibc.malloc.mmap_threshold
|
||||
+@order glibc.malloc.tcache_count
|
||||
+@order glibc.malloc.arena_test
|
||||
+@order glibc.pthread.mutex_spin_count
|
||||
+@order glibc.rtld.optional_static_tls
|
||||
+@order glibc.malloc.tcache_max
|
||||
+@order glibc.malloc.check
|
||||
diff --git a/sysdeps/unix/sysv/linux/i386/dl-tunables.list b/sysdeps/unix/sysv/linux/i386/dl-tunables.list
|
||||
new file mode 100644
|
||||
index 0000000000000000..e83962ec3af11691
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/i386/dl-tunables.list
|
||||
@@ -0,0 +1,35 @@
|
||||
+# Order of tunables in RHEL 9.1.z.
|
||||
+@order glibc.rtld.nns
|
||||
+@order glibc.elision.skip_lock_after_retries
|
||||
+@order glibc.malloc.trim_threshold
|
||||
+@order glibc.malloc.perturb
|
||||
+@order glibc.cpu.x86_shared_cache_size
|
||||
+@order glibc.pthread.rseq
|
||||
+@order glibc.mem.tagging
|
||||
+@order glibc.elision.tries
|
||||
+@order glibc.elision.enable
|
||||
+@order glibc.cpu.x86_rep_movsb_threshold
|
||||
+@order glibc.malloc.mxfast
|
||||
+@order glibc.rtld.dynamic_sort
|
||||
+@order glibc.elision.skip_lock_busy
|
||||
+@order glibc.malloc.top_pad
|
||||
+@order glibc.cpu.x86_rep_stosb_threshold
|
||||
+@order glibc.cpu.x86_non_temporal_threshold
|
||||
+@order glibc.cpu.x86_shstk
|
||||
+@order glibc.pthread.stack_cache_size
|
||||
+@order glibc.cpu.hwcap_mask
|
||||
+@order glibc.malloc.mmap_max
|
||||
+@order glibc.elision.skip_trylock_internal_abort
|
||||
+@order glibc.malloc.tcache_unsorted_limit
|
||||
+@order glibc.cpu.x86_ibt
|
||||
+@order glibc.cpu.hwcaps
|
||||
+@order glibc.elision.skip_lock_internal_abort
|
||||
+@order glibc.malloc.arena_max
|
||||
+@order glibc.malloc.mmap_threshold
|
||||
+@order glibc.cpu.x86_data_cache_size
|
||||
+@order glibc.malloc.tcache_count
|
||||
+@order glibc.malloc.arena_test
|
||||
+@order glibc.pthread.mutex_spin_count
|
||||
+@order glibc.rtld.optional_static_tls
|
||||
+@order glibc.malloc.tcache_max
|
||||
+@order glibc.malloc.check
|
||||
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list
|
||||
new file mode 100644
|
||||
index 0000000000000000..8f01840ef57874e7
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/dl-tunables.list
|
||||
@@ -0,0 +1,28 @@
|
||||
+# Order of tunables in RHEL 9.1.z.
|
||||
+@order glibc.rtld.nns
|
||||
+@order glibc.elision.skip_lock_after_retries
|
||||
+@order glibc.malloc.trim_threshold
|
||||
+@order glibc.malloc.perturb
|
||||
+@order glibc.pthread.rseq
|
||||
+@order glibc.mem.tagging
|
||||
+@order glibc.elision.tries
|
||||
+@order glibc.elision.enable
|
||||
+@order glibc.malloc.mxfast
|
||||
+@order glibc.rtld.dynamic_sort
|
||||
+@order glibc.elision.skip_lock_busy
|
||||
+@order glibc.malloc.top_pad
|
||||
+@order glibc.pthread.stack_cache_size
|
||||
+@order glibc.cpu.hwcap_mask
|
||||
+@order glibc.malloc.mmap_max
|
||||
+@order glibc.elision.skip_trylock_internal_abort
|
||||
+@order glibc.malloc.tcache_unsorted_limit
|
||||
+@order glibc.elision.skip_lock_internal_abort
|
||||
+@order glibc.malloc.arena_max
|
||||
+@order glibc.malloc.mmap_threshold
|
||||
+@order glibc.cpu.cached_memopt
|
||||
+@order glibc.malloc.tcache_count
|
||||
+@order glibc.malloc.arena_test
|
||||
+@order glibc.pthread.mutex_spin_count
|
||||
+@order glibc.rtld.optional_static_tls
|
||||
+@order glibc.malloc.tcache_max
|
||||
+@order glibc.malloc.check
|
||||
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list b/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list
|
||||
new file mode 100644
|
||||
index 0000000000000000..c3bc83f33910af22
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/dl-tunables.list
|
||||
@@ -0,0 +1,27 @@
|
||||
+# Order of tunables in RHEL 9.1.z.
|
||||
+@order glibc.rtld.nns
|
||||
+@order glibc.elision.skip_lock_after_retries
|
||||
+@order glibc.malloc.trim_threshold
|
||||
+@order glibc.malloc.perturb
|
||||
+@order glibc.pthread.rseq
|
||||
+@order glibc.mem.tagging
|
||||
+@order glibc.elision.tries
|
||||
+@order glibc.elision.enable
|
||||
+@order glibc.malloc.mxfast
|
||||
+@order glibc.rtld.dynamic_sort
|
||||
+@order glibc.elision.skip_lock_busy
|
||||
+@order glibc.malloc.top_pad
|
||||
+@order glibc.pthread.stack_cache_size
|
||||
+@order glibc.cpu.hwcap_mask
|
||||
+@order glibc.malloc.mmap_max
|
||||
+@order glibc.elision.skip_trylock_internal_abort
|
||||
+@order glibc.malloc.tcache_unsorted_limit
|
||||
+@order glibc.elision.skip_lock_internal_abort
|
||||
+@order glibc.malloc.arena_max
|
||||
+@order glibc.malloc.mmap_threshold
|
||||
+@order glibc.malloc.tcache_count
|
||||
+@order glibc.malloc.arena_test
|
||||
+@order glibc.pthread.mutex_spin_count
|
||||
+@order glibc.rtld.optional_static_tls
|
||||
+@order glibc.malloc.tcache_max
|
||||
+@order glibc.malloc.check
|
||||
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list
|
||||
new file mode 100644
|
||||
index 0000000000000000..e83962ec3af11691
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/x86_64/64/dl-tunables.list
|
||||
@@ -0,0 +1,35 @@
|
||||
+# Order of tunables in RHEL 9.1.z.
|
||||
+@order glibc.rtld.nns
|
||||
+@order glibc.elision.skip_lock_after_retries
|
||||
+@order glibc.malloc.trim_threshold
|
||||
+@order glibc.malloc.perturb
|
||||
+@order glibc.cpu.x86_shared_cache_size
|
||||
+@order glibc.pthread.rseq
|
||||
+@order glibc.mem.tagging
|
||||
+@order glibc.elision.tries
|
||||
+@order glibc.elision.enable
|
||||
+@order glibc.cpu.x86_rep_movsb_threshold
|
||||
+@order glibc.malloc.mxfast
|
||||
+@order glibc.rtld.dynamic_sort
|
||||
+@order glibc.elision.skip_lock_busy
|
||||
+@order glibc.malloc.top_pad
|
||||
+@order glibc.cpu.x86_rep_stosb_threshold
|
||||
+@order glibc.cpu.x86_non_temporal_threshold
|
||||
+@order glibc.cpu.x86_shstk
|
||||
+@order glibc.pthread.stack_cache_size
|
||||
+@order glibc.cpu.hwcap_mask
|
||||
+@order glibc.malloc.mmap_max
|
||||
+@order glibc.elision.skip_trylock_internal_abort
|
||||
+@order glibc.malloc.tcache_unsorted_limit
|
||||
+@order glibc.cpu.x86_ibt
|
||||
+@order glibc.cpu.hwcaps
|
||||
+@order glibc.elision.skip_lock_internal_abort
|
||||
+@order glibc.malloc.arena_max
|
||||
+@order glibc.malloc.mmap_threshold
|
||||
+@order glibc.cpu.x86_data_cache_size
|
||||
+@order glibc.malloc.tcache_count
|
||||
+@order glibc.malloc.arena_test
|
||||
+@order glibc.pthread.mutex_spin_count
|
||||
+@order glibc.rtld.optional_static_tls
|
||||
+@order glibc.malloc.tcache_max
|
||||
+@order glibc.malloc.check
|
@ -0,0 +1,24 @@
|
||||
commit 875b2414cd68df64aeead651a9b05ae9bc3d88ef
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Aug 4 17:54:48 2022 +0200
|
||||
|
||||
dlfcn: Pass caller pointer to static dlopen implementation (bug 29446)
|
||||
|
||||
Fixes commit 0c1c3a771eceec46e66ce1183cf988e2303bd373 ("dlfcn: Move
|
||||
dlopen into libc").
|
||||
|
||||
(cherry picked from commit ed0185e4129130cbe081c221efb758fb400623ce)
|
||||
|
||||
diff --git a/dlfcn/dlopen.c b/dlfcn/dlopen.c
|
||||
index 9c59c751c4eaf7a7..739d17baafe928cc 100644
|
||||
--- a/dlfcn/dlopen.c
|
||||
+++ b/dlfcn/dlopen.c
|
||||
@@ -90,7 +90,7 @@ compat_symbol (libdl, ___dlopen, dlopen, GLIBC_2_1);
|
||||
void *
|
||||
__dlopen (const char *file, int mode, void *dl_caller)
|
||||
{
|
||||
- return dlopen_implementation (file, mode, RETURN_ADDRESS (0));
|
||||
+ return dlopen_implementation (file, mode, dl_caller);
|
||||
}
|
||||
|
||||
void *
|
@ -0,0 +1,54 @@
|
||||
commit 4ab59ce4e5195f98b01748127248fed2b2b77b21
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Tue Aug 2 21:05:07 2022 +0000
|
||||
|
||||
Update syscall lists for Linux 5.19
|
||||
|
||||
Linux 5.19 has no new syscalls, but enables memfd_secret in the uapi
|
||||
headers for RISC-V. Update the version number in syscall-names.list
|
||||
to reflect that it is still current for 5.19 and regenerate the
|
||||
arch-syscall.h headers with build-many-glibcs.py update-syscalls.
|
||||
|
||||
Tested with build-many-glibcs.py.
|
||||
|
||||
(cherry picked from commit fccadcdf5bed7ee67a6cef4714e0b477d6c8472c)
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
|
||||
index bf4be80f8d380963..202520ee254ec02f 100644
|
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h
|
||||
@@ -122,6 +122,7 @@
|
||||
#define __NR_mbind 235
|
||||
#define __NR_membarrier 283
|
||||
#define __NR_memfd_create 279
|
||||
+#define __NR_memfd_secret 447
|
||||
#define __NR_migrate_pages 238
|
||||
#define __NR_mincore 232
|
||||
#define __NR_mkdirat 34
|
||||
diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
|
||||
index d656aedcc2be6009..4e65f337d486de1f 100644
|
||||
--- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
|
||||
+++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h
|
||||
@@ -127,6 +127,7 @@
|
||||
#define __NR_mbind 235
|
||||
#define __NR_membarrier 283
|
||||
#define __NR_memfd_create 279
|
||||
+#define __NR_memfd_secret 447
|
||||
#define __NR_migrate_pages 238
|
||||
#define __NR_mincore 232
|
||||
#define __NR_mkdirat 34
|
||||
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
index 95370e2ec5dbc4a7..9b285d898db9ab9e 100644
|
||||
--- a/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
|
||||
@@ -21,8 +21,8 @@
|
||||
# This file can list all potential system calls. The names are only
|
||||
# used if the installed kernel headers also provide them.
|
||||
|
||||
-# The list of system calls is current as of Linux 5.18.
|
||||
-kernel 5.18
|
||||
+# The list of system calls is current as of Linux 5.19.
|
||||
+kernel 5.19
|
||||
|
||||
FAST_atomic_update
|
||||
FAST_cmpxchg
|
@ -0,0 +1,85 @@
|
||||
commit a88f07f71f051021339682328103a8c75559fc5f
|
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Wed Jun 22 08:24:21 2022 -0700
|
||||
|
||||
stdlib: Remove attr_write from mbstows if dst is NULL [BZ: 29265]
|
||||
|
||||
mbstows is defined if dst is NULL and is defined to special cased if
|
||||
dst is NULL so the fortify objsize check if incorrect in that case.
|
||||
|
||||
Tested on x86-64 linux.
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
(cherry picked from commit 464d189b9622932a75302290625de84931656ec0)
|
||||
|
||||
diff --git a/stdlib/Makefile b/stdlib/Makefile
|
||||
index a4ac30d1f6359561..e13f1ee33c410ae6 100644
|
||||
--- a/stdlib/Makefile
|
||||
+++ b/stdlib/Makefile
|
||||
@@ -217,6 +217,9 @@ CFLAGS-tst-qsort.c += $(stack-align-test-flags)
|
||||
CFLAGS-tst-makecontext.c += -funwind-tables
|
||||
CFLAGS-tst-makecontext2.c += $(stack-align-test-flags)
|
||||
|
||||
+CFLAGS-testmb.c += -D_FORTIFY_SOURCE=2 -Wall -Werror
|
||||
+
|
||||
+
|
||||
# Run a test on the header files we use.
|
||||
tests-special += $(objpfx)isomac.out
|
||||
|
||||
diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h
|
||||
index ccacbdf76a08225a..f0918d5d798a6ac4 100644
|
||||
--- a/stdlib/bits/stdlib.h
|
||||
+++ b/stdlib/bits/stdlib.h
|
||||
@@ -96,6 +96,11 @@ extern size_t __mbstowcs_chk (wchar_t *__restrict __dst,
|
||||
const char *__restrict __src,
|
||||
size_t __len, size_t __dstlen) __THROW
|
||||
__attr_access ((__write_only__, 1, 3)) __attr_access ((__read_only__, 2));
|
||||
+extern size_t __REDIRECT_NTH (__mbstowcs_chk_nulldst,
|
||||
+ (wchar_t *__restrict __dst,
|
||||
+ const char *__restrict __src,
|
||||
+ size_t __len), mbstowcs_chk)
|
||||
+ __attr_access ((__read_only__, 2));
|
||||
extern size_t __REDIRECT_NTH (__mbstowcs_alias,
|
||||
(wchar_t *__restrict __dst,
|
||||
const char *__restrict __src,
|
||||
@@ -108,16 +113,17 @@ extern size_t __REDIRECT_NTH (__mbstowcs_chk_warn,
|
||||
__warnattr ("mbstowcs called with dst buffer smaller than len "
|
||||
"* sizeof (wchar_t)");
|
||||
|
||||
-__fortify_function size_t
|
||||
+__always_inline __fortify_function size_t
|
||||
__NTH (mbstowcs (wchar_t *__restrict __dst, const char *__restrict __src,
|
||||
size_t __len))
|
||||
{
|
||||
- return __glibc_fortify_n (mbstowcs, __len, sizeof (wchar_t),
|
||||
- __glibc_objsize (__dst),
|
||||
- __dst, __src, __len);
|
||||
+ if (__builtin_constant_p (__dst == NULL) && __dst == NULL)
|
||||
+ return __mbstowcs_chk_nulldst (__dst, __src, __len);
|
||||
+ else
|
||||
+ return __glibc_fortify_n (mbstowcs, __len, sizeof (wchar_t),
|
||||
+ __glibc_objsize (__dst), __dst, __src, __len);
|
||||
}
|
||||
|
||||
-
|
||||
extern size_t __wcstombs_chk (char *__restrict __dst,
|
||||
const wchar_t *__restrict __src,
|
||||
size_t __len, size_t __dstlen) __THROW
|
||||
diff --git a/stdlib/testmb.c b/stdlib/testmb.c
|
||||
index 45dae7db61fb3e7b..6ac4dfd21d2d33b8 100644
|
||||
--- a/stdlib/testmb.c
|
||||
+++ b/stdlib/testmb.c
|
||||
@@ -16,6 +16,13 @@ main (int argc, char *argv[])
|
||||
lose = 1;
|
||||
}
|
||||
|
||||
+ i = mbstowcs (NULL, "bar", 4);
|
||||
+ if (!(i == 3 && w[1] == 'a'))
|
||||
+ {
|
||||
+ puts ("mbstowcs FAILED2!");
|
||||
+ lose = 1;
|
||||
+ }
|
||||
+
|
||||
mbstowcs (w, "blah", 5);
|
||||
i = wcstombs (c, w, 10);
|
||||
if (i != 4)
|
@ -0,0 +1,54 @@
|
||||
commit 4bc889c01ce68475ce36f9c67b9a445a6c0218d9
|
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Wed Jun 22 16:34:42 2022 -0700
|
||||
|
||||
stdlib: Fixup mbstowcs NULL __dst handling. [BZ #29279]
|
||||
|
||||
commit 464d189b9622932a75302290625de84931656ec0 (origin/master, origin/HEAD)
|
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Wed Jun 22 08:24:21 2022 -0700
|
||||
|
||||
stdlib: Remove attr_write from mbstows if dst is NULL [BZ: 29265]
|
||||
|
||||
Incorrectly called `__mbstowcs_chk` in the NULL __dst case which is
|
||||
incorrect as in the NULL __dst case we are explicitly skipping
|
||||
the objsize checks.
|
||||
|
||||
As well, remove the `__always_inline` attribute which exists in
|
||||
`__fortify_function`.
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
(cherry picked from commit 220b83d83d32aa9e6f5659e2fa2a63a0024c3e4a)
|
||||
|
||||
diff --git a/stdlib/bits/stdlib.h b/stdlib/bits/stdlib.h
|
||||
index f0918d5d798a6ac4..ac9badc81f3990c5 100644
|
||||
--- a/stdlib/bits/stdlib.h
|
||||
+++ b/stdlib/bits/stdlib.h
|
||||
@@ -96,10 +96,10 @@ extern size_t __mbstowcs_chk (wchar_t *__restrict __dst,
|
||||
const char *__restrict __src,
|
||||
size_t __len, size_t __dstlen) __THROW
|
||||
__attr_access ((__write_only__, 1, 3)) __attr_access ((__read_only__, 2));
|
||||
-extern size_t __REDIRECT_NTH (__mbstowcs_chk_nulldst,
|
||||
+extern size_t __REDIRECT_NTH (__mbstowcs_nulldst,
|
||||
(wchar_t *__restrict __dst,
|
||||
const char *__restrict __src,
|
||||
- size_t __len), mbstowcs_chk)
|
||||
+ size_t __len), mbstowcs)
|
||||
__attr_access ((__read_only__, 2));
|
||||
extern size_t __REDIRECT_NTH (__mbstowcs_alias,
|
||||
(wchar_t *__restrict __dst,
|
||||
@@ -113,12 +113,12 @@ extern size_t __REDIRECT_NTH (__mbstowcs_chk_warn,
|
||||
__warnattr ("mbstowcs called with dst buffer smaller than len "
|
||||
"* sizeof (wchar_t)");
|
||||
|
||||
-__always_inline __fortify_function size_t
|
||||
+__fortify_function size_t
|
||||
__NTH (mbstowcs (wchar_t *__restrict __dst, const char *__restrict __src,
|
||||
size_t __len))
|
||||
{
|
||||
if (__builtin_constant_p (__dst == NULL) && __dst == NULL)
|
||||
- return __mbstowcs_chk_nulldst (__dst, __src, __len);
|
||||
+ return __mbstowcs_nulldst (__dst, __src, __len);
|
||||
else
|
||||
return __glibc_fortify_n (mbstowcs, __len, sizeof (wchar_t),
|
||||
__glibc_objsize (__dst), __dst, __src, __len);
|
@ -0,0 +1,30 @@
|
||||
commit 1fcc7bfee22a07064508b6729cdaa6289851a2b4
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Aug 22 11:04:47 2022 +0200
|
||||
|
||||
alpha: Fix generic brk system call emulation in __brk_call (bug 29490)
|
||||
|
||||
The kernel special-cases the zero argument for alpha brk, and we can
|
||||
use that to restore the generic Linux error handling behavior.
|
||||
|
||||
Fixes commit b57ab258c1140bc45464b4b9908713e3e0ee35aa ("Linux:
|
||||
Introduce __brk_call for invoking the brk system call").
|
||||
|
||||
(cherry picked from commit e7ad26ee3cb74e61d0637c888f24dd478d77af58)
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/alpha/brk_call.h b/sysdeps/unix/sysv/linux/alpha/brk_call.h
|
||||
index b8088cf13f938c88..0b851b6c8664e8d5 100644
|
||||
--- a/sysdeps/unix/sysv/linux/alpha/brk_call.h
|
||||
+++ b/sysdeps/unix/sysv/linux/alpha/brk_call.h
|
||||
@@ -21,8 +21,7 @@ __brk_call (void *addr)
|
||||
{
|
||||
unsigned long int result = INTERNAL_SYSCALL_CALL (brk, addr);
|
||||
if (result == -ENOMEM)
|
||||
- /* Mimic the default error reporting behavior. */
|
||||
- return addr;
|
||||
- else
|
||||
- return (void *) result;
|
||||
+ /* Mimic the generic error reporting behavior. */
|
||||
+ result = INTERNAL_SYSCALL_CALL (brk, 0);
|
||||
+ return (void *) result;
|
||||
}
|
@ -0,0 +1,435 @@
|
||||
commit 68507377f249d165f1f35502d96e9365edb07d9a
|
||||
Author: Arjun Shankar <arjun@redhat.com>
|
||||
Date: Tue Aug 2 11:10:25 2022 +0200
|
||||
|
||||
socket: Check lengths before advancing pointer in CMSG_NXTHDR
|
||||
|
||||
The inline and library functions that the CMSG_NXTHDR macro may expand
|
||||
to increment the pointer to the header before checking the stride of
|
||||
the increment against available space. Since C only allows incrementing
|
||||
pointers to one past the end of an array, the increment must be done
|
||||
after a length check. This commit fixes that and includes a regression
|
||||
test for CMSG_FIRSTHDR and CMSG_NXTHDR.
|
||||
|
||||
The Linux, Hurd, and generic headers are all changed.
|
||||
|
||||
Tested on Linux on armv7hl, i686, x86_64, aarch64, ppc64le, and s390x.
|
||||
|
||||
[BZ #28846]
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 9c443ac4559a47ed99859bd80d14dc4b6dd220a1)
|
||||
|
||||
diff --git a/bits/socket.h b/bits/socket.h
|
||||
index 05ac0249c7da7218..781b1b2d1e0632a8 100644
|
||||
--- a/bits/socket.h
|
||||
+++ b/bits/socket.h
|
||||
@@ -245,6 +245,12 @@ struct cmsghdr
|
||||
+ CMSG_ALIGN (sizeof (struct cmsghdr)))
|
||||
#define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
|
||||
|
||||
+/* Given a length, return the additional padding necessary such that
|
||||
+ len + __CMSG_PADDING(len) == CMSG_ALIGN (len). */
|
||||
+#define __CMSG_PADDING(len) ((sizeof (size_t) \
|
||||
+ - ((len) & (sizeof (size_t) - 1))) \
|
||||
+ & (sizeof (size_t) - 1))
|
||||
+
|
||||
extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr,
|
||||
struct cmsghdr *__cmsg) __THROW;
|
||||
#ifdef __USE_EXTERN_INLINES
|
||||
@@ -254,18 +260,38 @@ extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr,
|
||||
_EXTERN_INLINE struct cmsghdr *
|
||||
__NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg))
|
||||
{
|
||||
+ /* We may safely assume that __cmsg lies between __mhdr->msg_control and
|
||||
+ __mhdr->msg_controllen because the user is required to obtain the first
|
||||
+ cmsg via CMSG_FIRSTHDR, set its length, then obtain subsequent cmsgs
|
||||
+ via CMSG_NXTHDR, setting lengths along the way. However, we don't yet
|
||||
+ trust the value of __cmsg->cmsg_len and therefore do not use it in any
|
||||
+ pointer arithmetic until we check its value. */
|
||||
+
|
||||
+ unsigned char * __msg_control_ptr = (unsigned char *) __mhdr->msg_control;
|
||||
+ unsigned char * __cmsg_ptr = (unsigned char *) __cmsg;
|
||||
+
|
||||
+ size_t __size_needed = sizeof (struct cmsghdr)
|
||||
+ + __CMSG_PADDING (__cmsg->cmsg_len);
|
||||
+
|
||||
+ /* The current header is malformed, too small to be a full header. */
|
||||
if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr))
|
||||
- /* The kernel header does this so there may be a reason. */
|
||||
return (struct cmsghdr *) 0;
|
||||
|
||||
+ /* There isn't enough space between __cmsg and the end of the buffer to
|
||||
+ hold the current cmsg *and* the next one. */
|
||||
+ if (((size_t)
|
||||
+ (__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr)
|
||||
+ < __size_needed)
|
||||
+ || ((size_t)
|
||||
+ (__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr
|
||||
+ - __size_needed)
|
||||
+ < __cmsg->cmsg_len))
|
||||
+
|
||||
+ return (struct cmsghdr *) 0;
|
||||
+
|
||||
+ /* Now, we trust cmsg_len and can use it to find the next header. */
|
||||
__cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
|
||||
+ CMSG_ALIGN (__cmsg->cmsg_len));
|
||||
- if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control
|
||||
- + __mhdr->msg_controllen)
|
||||
- || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len)
|
||||
- > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen)))
|
||||
- /* No more entries. */
|
||||
- return (struct cmsghdr *) 0;
|
||||
return __cmsg;
|
||||
}
|
||||
#endif /* Use `extern inline'. */
|
||||
diff --git a/socket/Makefile b/socket/Makefile
|
||||
index c2de11d73ca1e324..2fdf441bb44bf142 100644
|
||||
--- a/socket/Makefile
|
||||
+++ b/socket/Makefile
|
||||
@@ -34,6 +34,7 @@ routines := accept bind connect getpeername getsockname getsockopt \
|
||||
tests := \
|
||||
tst-accept4 \
|
||||
tst-sockopt \
|
||||
+ tst-cmsghdr \
|
||||
# tests
|
||||
|
||||
tests-internal := \
|
||||
diff --git a/socket/tst-cmsghdr-skeleton.c b/socket/tst-cmsghdr-skeleton.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..7accfa6e54708e2a
|
||||
--- /dev/null
|
||||
+++ b/socket/tst-cmsghdr-skeleton.c
|
||||
@@ -0,0 +1,93 @@
|
||||
+/* Test ancillary data header creation.
|
||||
+ Copyright (C) 2022 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/>. */
|
||||
+
|
||||
+/* We use the preprocessor to generate the function/macro tests instead of
|
||||
+ using indirection because having all the macro expansions alongside
|
||||
+ each other lets the compiler warn us about suspicious pointer
|
||||
+ arithmetic across subsequent CMSG_{FIRST,NXT}HDR expansions. */
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+#include <stddef.h>
|
||||
+
|
||||
+#define RUN_TEST_CONCAT(suffix) run_test_##suffix
|
||||
+#define RUN_TEST_FUNCNAME(suffix) RUN_TEST_CONCAT (suffix)
|
||||
+
|
||||
+static void
|
||||
+RUN_TEST_FUNCNAME (CMSG_NXTHDR_IMPL) (void)
|
||||
+{
|
||||
+ struct msghdr m = {0};
|
||||
+ struct cmsghdr *cmsg;
|
||||
+ char cmsgbuf[3 * CMSG_SPACE (sizeof (PAYLOAD))] = {0};
|
||||
+
|
||||
+ m.msg_control = cmsgbuf;
|
||||
+ m.msg_controllen = sizeof (cmsgbuf);
|
||||
+
|
||||
+ /* First header should point to the start of the buffer. */
|
||||
+ cmsg = CMSG_FIRSTHDR (&m);
|
||||
+ TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf);
|
||||
+
|
||||
+ /* If the first header length consumes the entire buffer, there is no
|
||||
+ space remaining for additional headers. */
|
||||
+ cmsg->cmsg_len = sizeof (cmsgbuf);
|
||||
+ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
|
||||
+ TEST_VERIFY_EXIT (cmsg == NULL);
|
||||
+
|
||||
+ /* The first header length is so big, using it would cause an overflow. */
|
||||
+ cmsg = CMSG_FIRSTHDR (&m);
|
||||
+ TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf);
|
||||
+ cmsg->cmsg_len = SIZE_MAX;
|
||||
+ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
|
||||
+ TEST_VERIFY_EXIT (cmsg == NULL);
|
||||
+
|
||||
+ /* The first header leaves just enough space to hold another header. */
|
||||
+ cmsg = CMSG_FIRSTHDR (&m);
|
||||
+ TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf);
|
||||
+ cmsg->cmsg_len = sizeof (cmsgbuf) - sizeof (struct cmsghdr);
|
||||
+ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
|
||||
+ TEST_VERIFY_EXIT (cmsg != NULL);
|
||||
+
|
||||
+ /* The first header leaves space but not enough for another header. */
|
||||
+ cmsg = CMSG_FIRSTHDR (&m);
|
||||
+ TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf);
|
||||
+ cmsg->cmsg_len ++;
|
||||
+ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
|
||||
+ TEST_VERIFY_EXIT (cmsg == NULL);
|
||||
+
|
||||
+ /* The second header leaves just enough space to hold another header. */
|
||||
+ cmsg = CMSG_FIRSTHDR (&m);
|
||||
+ TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf);
|
||||
+ cmsg->cmsg_len = CMSG_LEN (sizeof (PAYLOAD));
|
||||
+ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
|
||||
+ TEST_VERIFY_EXIT (cmsg != NULL);
|
||||
+ cmsg->cmsg_len = sizeof (cmsgbuf)
|
||||
+ - CMSG_SPACE (sizeof (PAYLOAD)) /* First header. */
|
||||
+ - sizeof (struct cmsghdr);
|
||||
+ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
|
||||
+ TEST_VERIFY_EXIT (cmsg != NULL);
|
||||
+
|
||||
+ /* The second header leaves space but not enough for another header. */
|
||||
+ cmsg = CMSG_FIRSTHDR (&m);
|
||||
+ TEST_VERIFY_EXIT ((char *) cmsg == cmsgbuf);
|
||||
+ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
|
||||
+ TEST_VERIFY_EXIT (cmsg != NULL);
|
||||
+ cmsg->cmsg_len ++;
|
||||
+ cmsg = CMSG_NXTHDR_IMPL (&m, cmsg);
|
||||
+ TEST_VERIFY_EXIT (cmsg == NULL);
|
||||
+
|
||||
+ return;
|
||||
+}
|
||||
diff --git a/socket/tst-cmsghdr.c b/socket/tst-cmsghdr.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..68c96d3c9dd2bce8
|
||||
--- /dev/null
|
||||
+++ b/socket/tst-cmsghdr.c
|
||||
@@ -0,0 +1,56 @@
|
||||
+/* Test ancillary data header creation.
|
||||
+ Copyright (C) 2022 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 <sys/socket.h>
|
||||
+#include <gnu/lib-names.h>
|
||||
+#include <support/xdlfcn.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+#define PAYLOAD "Hello, World!"
|
||||
+
|
||||
+/* CMSG_NXTHDR is a macro that calls an inline function defined in
|
||||
+ bits/socket.h. In case the function cannot be inlined, libc.so carries
|
||||
+ a copy. Both versions need to be tested. */
|
||||
+
|
||||
+#define CMSG_NXTHDR_IMPL CMSG_NXTHDR
|
||||
+#include "tst-cmsghdr-skeleton.c"
|
||||
+#undef CMSG_NXTHDR_IMPL
|
||||
+
|
||||
+static struct cmsghdr * (* cmsg_nxthdr) (struct msghdr *, struct cmsghdr *);
|
||||
+
|
||||
+#define CMSG_NXTHDR_IMPL cmsg_nxthdr
|
||||
+#include "tst-cmsghdr-skeleton.c"
|
||||
+#undef CMSG_NXTHDR_IMPL
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ static void *handle;
|
||||
+
|
||||
+ run_test_CMSG_NXTHDR ();
|
||||
+
|
||||
+ handle = xdlopen (LIBC_SO, RTLD_LAZY);
|
||||
+ cmsg_nxthdr = (struct cmsghdr * (*) (struct msghdr *, struct cmsghdr *))
|
||||
+ xdlsym (handle, "__cmsg_nxthdr");
|
||||
+
|
||||
+ run_test_cmsg_nxthdr ();
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/sysdeps/mach/hurd/bits/socket.h b/sysdeps/mach/hurd/bits/socket.h
|
||||
index 5210a7b44950e957..423eb2df09c3eef9 100644
|
||||
--- a/sysdeps/mach/hurd/bits/socket.h
|
||||
+++ b/sysdeps/mach/hurd/bits/socket.h
|
||||
@@ -249,6 +249,12 @@ struct cmsghdr
|
||||
+ CMSG_ALIGN (sizeof (struct cmsghdr)))
|
||||
#define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
|
||||
|
||||
+/* Given a length, return the additional padding necessary such that
|
||||
+ len + __CMSG_PADDING(len) == CMSG_ALIGN (len). */
|
||||
+#define __CMSG_PADDING(len) ((sizeof (size_t) \
|
||||
+ - ((len) & (sizeof (size_t) - 1))) \
|
||||
+ & (sizeof (size_t) - 1))
|
||||
+
|
||||
extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr,
|
||||
struct cmsghdr *__cmsg) __THROW;
|
||||
#ifdef __USE_EXTERN_INLINES
|
||||
@@ -258,18 +264,38 @@ extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr,
|
||||
_EXTERN_INLINE struct cmsghdr *
|
||||
__NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg))
|
||||
{
|
||||
+ /* We may safely assume that __cmsg lies between __mhdr->msg_control and
|
||||
+ __mhdr->msg_controllen because the user is required to obtain the first
|
||||
+ cmsg via CMSG_FIRSTHDR, set its length, then obtain subsequent cmsgs
|
||||
+ via CMSG_NXTHDR, setting lengths along the way. However, we don't yet
|
||||
+ trust the value of __cmsg->cmsg_len and therefore do not use it in any
|
||||
+ pointer arithmetic until we check its value. */
|
||||
+
|
||||
+ unsigned char * __msg_control_ptr = (unsigned char *) __mhdr->msg_control;
|
||||
+ unsigned char * __cmsg_ptr = (unsigned char *) __cmsg;
|
||||
+
|
||||
+ size_t __size_needed = sizeof (struct cmsghdr)
|
||||
+ + __CMSG_PADDING (__cmsg->cmsg_len);
|
||||
+
|
||||
+ /* The current header is malformed, too small to be a full header. */
|
||||
if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr))
|
||||
- /* The kernel header does this so there may be a reason. */
|
||||
return (struct cmsghdr *) 0;
|
||||
|
||||
+ /* There isn't enough space between __cmsg and the end of the buffer to
|
||||
+ hold the current cmsg *and* the next one. */
|
||||
+ if (((size_t)
|
||||
+ (__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr)
|
||||
+ < __size_needed)
|
||||
+ || ((size_t)
|
||||
+ (__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr
|
||||
+ - __size_needed)
|
||||
+ < __cmsg->cmsg_len))
|
||||
+
|
||||
+ return (struct cmsghdr *) 0;
|
||||
+
|
||||
+ /* Now, we trust cmsg_len and can use it to find the next header. */
|
||||
__cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
|
||||
+ CMSG_ALIGN (__cmsg->cmsg_len));
|
||||
- if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control
|
||||
- + __mhdr->msg_controllen)
|
||||
- || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len)
|
||||
- > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen)))
|
||||
- /* No more entries. */
|
||||
- return (struct cmsghdr *) 0;
|
||||
return __cmsg;
|
||||
}
|
||||
#endif /* Use `extern inline'. */
|
||||
diff --git a/sysdeps/unix/sysv/linux/bits/socket.h b/sysdeps/unix/sysv/linux/bits/socket.h
|
||||
index c81fab840918924e..7d56f877e0a73acb 100644
|
||||
--- a/sysdeps/unix/sysv/linux/bits/socket.h
|
||||
+++ b/sysdeps/unix/sysv/linux/bits/socket.h
|
||||
@@ -306,6 +306,12 @@ struct cmsghdr
|
||||
+ CMSG_ALIGN (sizeof (struct cmsghdr)))
|
||||
#define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len))
|
||||
|
||||
+/* Given a length, return the additional padding necessary such that
|
||||
+ len + __CMSG_PADDING(len) == CMSG_ALIGN (len). */
|
||||
+#define __CMSG_PADDING(len) ((sizeof (size_t) \
|
||||
+ - ((len) & (sizeof (size_t) - 1))) \
|
||||
+ & (sizeof (size_t) - 1))
|
||||
+
|
||||
extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr,
|
||||
struct cmsghdr *__cmsg) __THROW;
|
||||
#ifdef __USE_EXTERN_INLINES
|
||||
@@ -315,18 +321,38 @@ extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr,
|
||||
_EXTERN_INLINE struct cmsghdr *
|
||||
__NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg))
|
||||
{
|
||||
+ /* We may safely assume that __cmsg lies between __mhdr->msg_control and
|
||||
+ __mhdr->msg_controllen because the user is required to obtain the first
|
||||
+ cmsg via CMSG_FIRSTHDR, set its length, then obtain subsequent cmsgs
|
||||
+ via CMSG_NXTHDR, setting lengths along the way. However, we don't yet
|
||||
+ trust the value of __cmsg->cmsg_len and therefore do not use it in any
|
||||
+ pointer arithmetic until we check its value. */
|
||||
+
|
||||
+ unsigned char * __msg_control_ptr = (unsigned char *) __mhdr->msg_control;
|
||||
+ unsigned char * __cmsg_ptr = (unsigned char *) __cmsg;
|
||||
+
|
||||
+ size_t __size_needed = sizeof (struct cmsghdr)
|
||||
+ + __CMSG_PADDING (__cmsg->cmsg_len);
|
||||
+
|
||||
+ /* The current header is malformed, too small to be a full header. */
|
||||
if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr))
|
||||
- /* The kernel header does this so there may be a reason. */
|
||||
return (struct cmsghdr *) 0;
|
||||
|
||||
+ /* There isn't enough space between __cmsg and the end of the buffer to
|
||||
+ hold the current cmsg *and* the next one. */
|
||||
+ if (((size_t)
|
||||
+ (__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr)
|
||||
+ < __size_needed)
|
||||
+ || ((size_t)
|
||||
+ (__msg_control_ptr + __mhdr->msg_controllen - __cmsg_ptr
|
||||
+ - __size_needed)
|
||||
+ < __cmsg->cmsg_len))
|
||||
+
|
||||
+ return (struct cmsghdr *) 0;
|
||||
+
|
||||
+ /* Now, we trust cmsg_len and can use it to find the next header. */
|
||||
__cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
|
||||
+ CMSG_ALIGN (__cmsg->cmsg_len));
|
||||
- if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control
|
||||
- + __mhdr->msg_controllen)
|
||||
- || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len)
|
||||
- > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen)))
|
||||
- /* No more entries. */
|
||||
- return (struct cmsghdr *) 0;
|
||||
return __cmsg;
|
||||
}
|
||||
#endif /* Use `extern inline'. */
|
||||
diff --git a/sysdeps/unix/sysv/linux/cmsg_nxthdr.c b/sysdeps/unix/sysv/linux/cmsg_nxthdr.c
|
||||
index a0fe49f28563d030..535d22e9a037b9a9 100644
|
||||
--- a/sysdeps/unix/sysv/linux/cmsg_nxthdr.c
|
||||
+++ b/sysdeps/unix/sysv/linux/cmsg_nxthdr.c
|
||||
@@ -23,18 +23,38 @@
|
||||
struct cmsghdr *
|
||||
__cmsg_nxthdr (struct msghdr *mhdr, struct cmsghdr *cmsg)
|
||||
{
|
||||
+ /* We may safely assume that cmsg lies between mhdr->msg_control and
|
||||
+ mhdr->msg_controllen because the user is required to obtain the first
|
||||
+ cmsg via CMSG_FIRSTHDR, set its length, then obtain subsequent cmsgs
|
||||
+ via CMSG_NXTHDR, setting lengths along the way. However, we don't yet
|
||||
+ trust the value of cmsg->cmsg_len and therefore do not use it in any
|
||||
+ pointer arithmetic until we check its value. */
|
||||
+
|
||||
+ unsigned char * msg_control_ptr = (unsigned char *) mhdr->msg_control;
|
||||
+ unsigned char * cmsg_ptr = (unsigned char *) cmsg;
|
||||
+
|
||||
+ size_t size_needed = sizeof (struct cmsghdr)
|
||||
+ + __CMSG_PADDING (cmsg->cmsg_len);
|
||||
+
|
||||
+ /* The current header is malformed, too small to be a full header. */
|
||||
if ((size_t) cmsg->cmsg_len < sizeof (struct cmsghdr))
|
||||
- /* The kernel header does this so there may be a reason. */
|
||||
- return NULL;
|
||||
+ return (struct cmsghdr *) 0;
|
||||
+
|
||||
+ /* There isn't enough space between cmsg and the end of the buffer to
|
||||
+ hold the current cmsg *and* the next one. */
|
||||
+ if (((size_t)
|
||||
+ (msg_control_ptr + mhdr->msg_controllen - cmsg_ptr)
|
||||
+ < size_needed)
|
||||
+ || ((size_t)
|
||||
+ (msg_control_ptr + mhdr->msg_controllen - cmsg_ptr
|
||||
+ - size_needed)
|
||||
+ < cmsg->cmsg_len))
|
||||
+
|
||||
+ return (struct cmsghdr *) 0;
|
||||
|
||||
+ /* Now, we trust cmsg_len and can use it to find the next header. */
|
||||
cmsg = (struct cmsghdr *) ((unsigned char *) cmsg
|
||||
+ CMSG_ALIGN (cmsg->cmsg_len));
|
||||
- if ((unsigned char *) (cmsg + 1) > ((unsigned char *) mhdr->msg_control
|
||||
- + mhdr->msg_controllen)
|
||||
- || ((unsigned char *) cmsg + CMSG_ALIGN (cmsg->cmsg_len)
|
||||
- > ((unsigned char *) mhdr->msg_control + mhdr->msg_controllen)))
|
||||
- /* No more entries. */
|
||||
- return NULL;
|
||||
return cmsg;
|
||||
}
|
||||
libc_hidden_def (__cmsg_nxthdr)
|
@ -0,0 +1,212 @@
|
||||
commit 536ddc5c02f1ee82483319863a893ccb381beece
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Aug 26 21:15:43 2022 +0200
|
||||
|
||||
elf: Call __libc_early_init for reused namespaces (bug 29528)
|
||||
|
||||
libc_map is never reset to NULL, neither during dlclose nor on a
|
||||
dlopen call which reuses the namespace structure. As a result, if a
|
||||
namespace is reused, its libc is not initialized properly. The most
|
||||
visible result is a crash in the <ctype.h> functions.
|
||||
|
||||
To prevent similar bugs on namespace reuse from surfacing,
|
||||
unconditionally initialize the chosen namespace to zero using memset.
|
||||
|
||||
(cherry picked from commit d0e357ff45a75553dee3b17ed7d303bfa544f6fe)
|
||||
|
||||
Conflicts:
|
||||
elf/Makefile
|
||||
(usual test differences)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index 2b547d5b58f1759b..feec365e4e5fe9b3 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -399,6 +399,7 @@ tests += \
|
||||
tst-dlmopen3 \
|
||||
tst-dlmopen-dlerror \
|
||||
tst-dlmopen-gethostbyname \
|
||||
+ tst-dlmopen-twice \
|
||||
tst-dlopenfail \
|
||||
tst-dlopenfail-2 \
|
||||
tst-dlopenrpath \
|
||||
@@ -744,6 +745,8 @@ modules-names = \
|
||||
tst-dlmopen1mod \
|
||||
tst-dlmopen-dlerror-mod \
|
||||
tst-dlmopen-gethostbyname-mod \
|
||||
+ tst-dlmopen-twice-mod1 \
|
||||
+ tst-dlmopen-twice-mod2 \
|
||||
tst-dlopenfaillinkmod \
|
||||
tst-dlopenfailmod1 \
|
||||
tst-dlopenfailmod2 \
|
||||
@@ -2665,3 +2668,7 @@ $(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so
|
||||
tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
|
||||
$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc.so
|
||||
tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-auditmod-tlsdesc.so
|
||||
+
|
||||
+$(objpfx)tst-dlmopen-twice.out: \
|
||||
+ $(objpfx)tst-dlmopen-twice-mod1.so \
|
||||
+ $(objpfx)tst-dlmopen-twice-mod2.so
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||
index bc6872632880634e..1ab3c7b5ac2fbc45 100644
|
||||
--- a/elf/dl-open.c
|
||||
+++ b/elf/dl-open.c
|
||||
@@ -839,11 +839,14 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
|
||||
_dl_signal_error (EINVAL, file, NULL, N_("\
|
||||
no more namespaces available for dlmopen()"));
|
||||
}
|
||||
- else if (nsid == GL(dl_nns))
|
||||
- {
|
||||
- __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
|
||||
- ++GL(dl_nns);
|
||||
- }
|
||||
+
|
||||
+ if (nsid == GL(dl_nns))
|
||||
+ ++GL(dl_nns);
|
||||
+
|
||||
+ /* Initialize the new namespace. Most members are
|
||||
+ zero-initialized, only the lock needs special treatment. */
|
||||
+ memset (&GL(dl_ns)[nsid], 0, sizeof (GL(dl_ns)[nsid]));
|
||||
+ __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
|
||||
|
||||
_dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
|
||||
}
|
||||
diff --git a/elf/tst-dlmopen-twice-mod1.c b/elf/tst-dlmopen-twice-mod1.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..0eaf04948ce5263e
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-dlmopen-twice-mod1.c
|
||||
@@ -0,0 +1,37 @@
|
||||
+/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 1.
|
||||
+ Copyright (C) 2022 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>
|
||||
+
|
||||
+static void __attribute__ ((constructor))
|
||||
+init (void)
|
||||
+{
|
||||
+ puts ("info: tst-dlmopen-twice-mod1.so loaded");
|
||||
+ fflush (stdout);
|
||||
+}
|
||||
+
|
||||
+static void __attribute__ ((destructor))
|
||||
+fini (void)
|
||||
+{
|
||||
+ puts ("info: tst-dlmopen-twice-mod1.so about to be unloaded");
|
||||
+ fflush (stdout);
|
||||
+}
|
||||
+
|
||||
+/* Large allocation. The second module does not have this, so it
|
||||
+ should load libc at a different address. */
|
||||
+char large_allocate[16 * 1024 * 1024];
|
||||
diff --git a/elf/tst-dlmopen-twice-mod2.c b/elf/tst-dlmopen-twice-mod2.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..40c6c01f9625e188
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-dlmopen-twice-mod2.c
|
||||
@@ -0,0 +1,50 @@
|
||||
+/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 2.
|
||||
+ Copyright (C) 2022 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 <ctype.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+static void __attribute__ ((constructor))
|
||||
+init (void)
|
||||
+{
|
||||
+ puts ("info: tst-dlmopen-twice-mod2.so loaded");
|
||||
+ fflush (stdout);
|
||||
+}
|
||||
+
|
||||
+static void __attribute__ ((destructor))
|
||||
+fini (void)
|
||||
+{
|
||||
+ puts ("info: tst-dlmopen-twice-mod2.so about to be unloaded");
|
||||
+ fflush (stdout);
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+run_check (void)
|
||||
+{
|
||||
+ puts ("info: about to call isalpha");
|
||||
+ fflush (stdout);
|
||||
+
|
||||
+ volatile char ch = 'a';
|
||||
+ if (!isalpha (ch))
|
||||
+ {
|
||||
+ puts ("error: isalpha ('a') is not true");
|
||||
+ fflush (stdout);
|
||||
+ return 1;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/elf/tst-dlmopen-twice.c b/elf/tst-dlmopen-twice.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..449f3c8fa9f2aa01
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-dlmopen-twice.c
|
||||
@@ -0,0 +1,34 @@
|
||||
+/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Main.
|
||||
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <support/xdlfcn.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so", RTLD_NOW);
|
||||
+ xdlclose (handle);
|
||||
+ handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod2.so", RTLD_NOW);
|
||||
+ int (*run_check) (void) = xdlsym (handle, "run_check");
|
||||
+ TEST_COMPARE (run_check (), 0);
|
||||
+ xdlclose (handle);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
@ -0,0 +1,334 @@
|
||||
commit 2a44960cbc78713c6a2721683a4319d50e71a01f
|
||||
Author: Tulio Magno Quites Machado Filho <tuliom@linux.ibm.com>
|
||||
Date: Thu Jul 7 18:12:58 2022 -0300
|
||||
|
||||
Apply asm redirections in stdio.h before first use [BZ #27087]
|
||||
|
||||
Compilers may not be able to apply asm redirections to functions after
|
||||
these functions are used for the first time, e.g. clang 13.
|
||||
Fix [BZ #27087] by applying all long double-related asm redirections
|
||||
before using functions in bits/stdio.h.
|
||||
However, as these asm redirections depend on the declarations provided
|
||||
by libio/bits/stdio2.h, this header was split in 2:
|
||||
|
||||
- libio/bits/stdio2-decl.h contains all function declarations;
|
||||
- libio/bits/stdio2.h remains with the remaining contents, including
|
||||
redirections.
|
||||
|
||||
This also adds the access attribute to __vsnprintf_chk that was missing.
|
||||
|
||||
Tested with build-many-glibcs.py.
|
||||
|
||||
Reviewed-by: Paul E. Murphy <murphyp@linux.ibm.com>
|
||||
(cherry picked from commit d0fa09a7701956036ff36f8ca188e9fff81553d8)
|
||||
|
||||
diff --git a/include/bits/stdio2-decl.h b/include/bits/stdio2-decl.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..bbb052f192218219
|
||||
--- /dev/null
|
||||
+++ b/include/bits/stdio2-decl.h
|
||||
@@ -0,0 +1 @@
|
||||
+#include <libio/bits/stdio2-decl.h>
|
||||
diff --git a/libio/Makefile b/libio/Makefile
|
||||
index 5336b7d59584927f..981c876940f67fbf 100644
|
||||
--- a/libio/Makefile
|
||||
+++ b/libio/Makefile
|
||||
@@ -23,7 +23,7 @@ subdir := libio
|
||||
include ../Makeconfig
|
||||
|
||||
headers := stdio.h \
|
||||
- bits/stdio.h bits/stdio2.h bits/stdio-ldbl.h \
|
||||
+ bits/stdio.h bits/stdio2.h bits/stdio2-decl.h bits/stdio-ldbl.h \
|
||||
bits/types/FILE.h bits/types/__FILE.h bits/types/struct_FILE.h \
|
||||
bits/types/__fpos_t.h bits/types/__fpos64_t.h \
|
||||
bits/types/cookie_io_functions_t.h
|
||||
diff --git a/libio/bits/stdio2-decl.h b/libio/bits/stdio2-decl.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..e398f7182b98e4d7
|
||||
--- /dev/null
|
||||
+++ b/libio/bits/stdio2-decl.h
|
||||
@@ -0,0 +1,111 @@
|
||||
+/* Checking macros for stdio functions. Declarations only.
|
||||
+ Copyright (C) 2004-2022 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/>. */
|
||||
+
|
||||
+#ifndef _BITS_STDIO2_DEC_H
|
||||
+#define _BITS_STDIO2_DEC_H 1
|
||||
+
|
||||
+#ifndef _STDIO_H
|
||||
+# error "Never include <bits/stdio2-decl.h> directly; use <stdio.h> instead."
|
||||
+#endif
|
||||
+
|
||||
+extern int __sprintf_chk (char *__restrict __s, int __flag, size_t __slen,
|
||||
+ const char *__restrict __format, ...) __THROW
|
||||
+ __attr_access ((__write_only__, 1, 3));
|
||||
+extern int __vsprintf_chk (char *__restrict __s, int __flag, size_t __slen,
|
||||
+ const char *__restrict __format,
|
||||
+ __gnuc_va_list __ap) __THROW
|
||||
+ __attr_access ((__write_only__, 1, 3));
|
||||
+
|
||||
+#if defined __USE_ISOC99 || defined __USE_UNIX98
|
||||
+
|
||||
+extern int __snprintf_chk (char *__restrict __s, size_t __n, int __flag,
|
||||
+ size_t __slen, const char *__restrict __format,
|
||||
+ ...) __THROW
|
||||
+ __attr_access ((__write_only__, 1, 2));
|
||||
+extern int __vsnprintf_chk (char *__restrict __s, size_t __n, int __flag,
|
||||
+ size_t __slen, const char *__restrict __format,
|
||||
+ __gnuc_va_list __ap) __THROW
|
||||
+ __attr_access ((__write_only__, 1, 2));
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+#if __USE_FORTIFY_LEVEL > 1
|
||||
+
|
||||
+extern int __fprintf_chk (FILE *__restrict __stream, int __flag,
|
||||
+ const char *__restrict __format, ...);
|
||||
+extern int __printf_chk (int __flag, const char *__restrict __format, ...);
|
||||
+extern int __vfprintf_chk (FILE *__restrict __stream, int __flag,
|
||||
+ const char *__restrict __format, __gnuc_va_list __ap);
|
||||
+extern int __vprintf_chk (int __flag, const char *__restrict __format,
|
||||
+ __gnuc_va_list __ap);
|
||||
+
|
||||
+# ifdef __USE_XOPEN2K8
|
||||
+extern int __dprintf_chk (int __fd, int __flag, const char *__restrict __fmt,
|
||||
+ ...) __attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
+extern int __vdprintf_chk (int __fd, int __flag,
|
||||
+ const char *__restrict __fmt, __gnuc_va_list __arg)
|
||||
+ __attribute__ ((__format__ (__printf__, 3, 0)));
|
||||
+# endif
|
||||
+
|
||||
+# ifdef __USE_GNU
|
||||
+
|
||||
+extern int __asprintf_chk (char **__restrict __ptr, int __flag,
|
||||
+ const char *__restrict __fmt, ...)
|
||||
+ __THROW __attribute__ ((__format__ (__printf__, 3, 4))) __wur;
|
||||
+extern int __vasprintf_chk (char **__restrict __ptr, int __flag,
|
||||
+ const char *__restrict __fmt, __gnuc_va_list __arg)
|
||||
+ __THROW __attribute__ ((__format__ (__printf__, 3, 0))) __wur;
|
||||
+extern int __obstack_printf_chk (struct obstack *__restrict __obstack,
|
||||
+ int __flag, const char *__restrict __format,
|
||||
+ ...)
|
||||
+ __THROW __attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
+extern int __obstack_vprintf_chk (struct obstack *__restrict __obstack,
|
||||
+ int __flag,
|
||||
+ const char *__restrict __format,
|
||||
+ __gnuc_va_list __args)
|
||||
+ __THROW __attribute__ ((__format__ (__printf__, 3, 0)));
|
||||
+
|
||||
+# endif
|
||||
+#endif
|
||||
+
|
||||
+#if __GLIBC_USE (DEPRECATED_GETS)
|
||||
+extern char *__gets_chk (char *__str, size_t) __wur;
|
||||
+#endif
|
||||
+
|
||||
+extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n,
|
||||
+ FILE *__restrict __stream)
|
||||
+ __wur __attr_access ((__write_only__, 1, 3));
|
||||
+
|
||||
+extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen,
|
||||
+ size_t __size, size_t __n,
|
||||
+ FILE *__restrict __stream) __wur;
|
||||
+
|
||||
+#ifdef __USE_GNU
|
||||
+extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size,
|
||||
+ int __n, FILE *__restrict __stream)
|
||||
+ __wur __attr_access ((__write_only__, 1, 3));
|
||||
+#endif
|
||||
+
|
||||
+#ifdef __USE_MISC
|
||||
+# undef fread_unlocked
|
||||
+extern size_t __fread_unlocked_chk (void *__restrict __ptr, size_t __ptrlen,
|
||||
+ size_t __size, size_t __n,
|
||||
+ FILE *__restrict __stream) __wur;
|
||||
+#endif
|
||||
+
|
||||
+#endif /* bits/stdio2-decl.h. */
|
||||
diff --git a/libio/bits/stdio2.h b/libio/bits/stdio2.h
|
||||
index 40ff16b01b4f4876..4570f86a4496c1ee 100644
|
||||
--- a/libio/bits/stdio2.h
|
||||
+++ b/libio/bits/stdio2.h
|
||||
@@ -23,14 +23,6 @@
|
||||
# error "Never include <bits/stdio2.h> directly; use <stdio.h> instead."
|
||||
#endif
|
||||
|
||||
-extern int __sprintf_chk (char *__restrict __s, int __flag, size_t __slen,
|
||||
- const char *__restrict __format, ...) __THROW
|
||||
- __attr_access ((__write_only__, 1, 3));
|
||||
-extern int __vsprintf_chk (char *__restrict __s, int __flag, size_t __slen,
|
||||
- const char *__restrict __format,
|
||||
- __gnuc_va_list __ap) __THROW
|
||||
- __attr_access ((__write_only__, 1, 3));
|
||||
-
|
||||
#ifdef __va_arg_pack
|
||||
__fortify_function int
|
||||
__NTH (sprintf (char *__restrict __s, const char *__restrict __fmt, ...))
|
||||
@@ -54,15 +46,6 @@ __NTH (vsprintf (char *__restrict __s, const char *__restrict __fmt,
|
||||
}
|
||||
|
||||
#if defined __USE_ISOC99 || defined __USE_UNIX98
|
||||
-
|
||||
-extern int __snprintf_chk (char *__restrict __s, size_t __n, int __flag,
|
||||
- size_t __slen, const char *__restrict __format,
|
||||
- ...) __THROW
|
||||
- __attr_access ((__write_only__, 1, 2));
|
||||
-extern int __vsnprintf_chk (char *__restrict __s, size_t __n, int __flag,
|
||||
- size_t __slen, const char *__restrict __format,
|
||||
- __gnuc_va_list __ap) __THROW;
|
||||
-
|
||||
# ifdef __va_arg_pack
|
||||
__fortify_function int
|
||||
__NTH (snprintf (char *__restrict __s, size_t __n,
|
||||
@@ -89,15 +72,6 @@ __NTH (vsnprintf (char *__restrict __s, size_t __n,
|
||||
#endif
|
||||
|
||||
#if __USE_FORTIFY_LEVEL > 1
|
||||
-
|
||||
-extern int __fprintf_chk (FILE *__restrict __stream, int __flag,
|
||||
- const char *__restrict __format, ...);
|
||||
-extern int __printf_chk (int __flag, const char *__restrict __format, ...);
|
||||
-extern int __vfprintf_chk (FILE *__restrict __stream, int __flag,
|
||||
- const char *__restrict __format, __gnuc_va_list __ap);
|
||||
-extern int __vprintf_chk (int __flag, const char *__restrict __format,
|
||||
- __gnuc_va_list __ap);
|
||||
-
|
||||
# ifdef __va_arg_pack
|
||||
__fortify_function int
|
||||
fprintf (FILE *__restrict __stream, const char *__restrict __fmt, ...)
|
||||
@@ -136,12 +110,6 @@ vfprintf (FILE *__restrict __stream,
|
||||
}
|
||||
|
||||
# ifdef __USE_XOPEN2K8
|
||||
-extern int __dprintf_chk (int __fd, int __flag, const char *__restrict __fmt,
|
||||
- ...) __attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
-extern int __vdprintf_chk (int __fd, int __flag,
|
||||
- const char *__restrict __fmt, __gnuc_va_list __arg)
|
||||
- __attribute__ ((__format__ (__printf__, 3, 0)));
|
||||
-
|
||||
# ifdef __va_arg_pack
|
||||
__fortify_function int
|
||||
dprintf (int __fd, const char *__restrict __fmt, ...)
|
||||
@@ -162,23 +130,6 @@ vdprintf (int __fd, const char *__restrict __fmt, __gnuc_va_list __ap)
|
||||
# endif
|
||||
|
||||
# ifdef __USE_GNU
|
||||
-
|
||||
-extern int __asprintf_chk (char **__restrict __ptr, int __flag,
|
||||
- const char *__restrict __fmt, ...)
|
||||
- __THROW __attribute__ ((__format__ (__printf__, 3, 4))) __wur;
|
||||
-extern int __vasprintf_chk (char **__restrict __ptr, int __flag,
|
||||
- const char *__restrict __fmt, __gnuc_va_list __arg)
|
||||
- __THROW __attribute__ ((__format__ (__printf__, 3, 0))) __wur;
|
||||
-extern int __obstack_printf_chk (struct obstack *__restrict __obstack,
|
||||
- int __flag, const char *__restrict __format,
|
||||
- ...)
|
||||
- __THROW __attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
-extern int __obstack_vprintf_chk (struct obstack *__restrict __obstack,
|
||||
- int __flag,
|
||||
- const char *__restrict __format,
|
||||
- __gnuc_va_list __args)
|
||||
- __THROW __attribute__ ((__format__ (__printf__, 3, 0)));
|
||||
-
|
||||
# ifdef __va_arg_pack
|
||||
__fortify_function int
|
||||
__NTH (asprintf (char **__restrict __ptr, const char *__restrict __fmt, ...))
|
||||
@@ -231,7 +182,6 @@ __NTH (obstack_vprintf (struct obstack *__restrict __obstack,
|
||||
#endif
|
||||
|
||||
#if __GLIBC_USE (DEPRECATED_GETS)
|
||||
-extern char *__gets_chk (char *__str, size_t) __wur;
|
||||
extern char *__REDIRECT (__gets_warn, (char *__str), gets)
|
||||
__wur __warnattr ("please use fgets or getline instead, gets can't "
|
||||
"specify buffer size");
|
||||
@@ -245,9 +195,6 @@ gets (char *__str)
|
||||
}
|
||||
#endif
|
||||
|
||||
-extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n,
|
||||
- FILE *__restrict __stream)
|
||||
- __wur __attr_access ((__write_only__, 1, 3));
|
||||
extern char *__REDIRECT (__fgets_alias,
|
||||
(char *__restrict __s, int __n,
|
||||
FILE *__restrict __stream), fgets)
|
||||
@@ -269,9 +216,6 @@ fgets (char *__restrict __s, int __n, FILE *__restrict __stream)
|
||||
return __fgets_chk (__s, sz, __n, __stream);
|
||||
}
|
||||
|
||||
-extern size_t __fread_chk (void *__restrict __ptr, size_t __ptrlen,
|
||||
- size_t __size, size_t __n,
|
||||
- FILE *__restrict __stream) __wur;
|
||||
extern size_t __REDIRECT (__fread_alias,
|
||||
(void *__restrict __ptr, size_t __size,
|
||||
size_t __n, FILE *__restrict __stream),
|
||||
@@ -297,9 +241,6 @@ fread (void *__restrict __ptr, size_t __size, size_t __n,
|
||||
}
|
||||
|
||||
#ifdef __USE_GNU
|
||||
-extern char *__fgets_unlocked_chk (char *__restrict __s, size_t __size,
|
||||
- int __n, FILE *__restrict __stream)
|
||||
- __wur __attr_access ((__write_only__, 1, 3));
|
||||
extern char *__REDIRECT (__fgets_unlocked_alias,
|
||||
(char *__restrict __s, int __n,
|
||||
FILE *__restrict __stream), fgets_unlocked)
|
||||
@@ -324,9 +265,6 @@ fgets_unlocked (char *__restrict __s, int __n, FILE *__restrict __stream)
|
||||
|
||||
#ifdef __USE_MISC
|
||||
# undef fread_unlocked
|
||||
-extern size_t __fread_unlocked_chk (void *__restrict __ptr, size_t __ptrlen,
|
||||
- size_t __size, size_t __n,
|
||||
- FILE *__restrict __stream) __wur;
|
||||
extern size_t __REDIRECT (__fread_unlocked_alias,
|
||||
(void *__restrict __ptr, size_t __size,
|
||||
size_t __n, FILE *__restrict __stream),
|
||||
diff --git a/libio/stdio.h b/libio/stdio.h
|
||||
index abefe640e52d18d5..d36e61c56bbb3117 100644
|
||||
--- a/libio/stdio.h
|
||||
+++ b/libio/stdio.h
|
||||
@@ -879,20 +879,27 @@ extern void funlockfile (FILE *__stream) __THROW;
|
||||
extern int __uflow (FILE *);
|
||||
extern int __overflow (FILE *, int);
|
||||
|
||||
+#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
|
||||
+/* Declare all functions from bits/stdio2-decl.h first. */
|
||||
+# include <bits/stdio2-decl.h>
|
||||
+#endif
|
||||
+
|
||||
+/* The following headers provide asm redirections. These redirections must
|
||||
+ appear before the first usage of these functions, e.g. in bits/stdio.h. */
|
||||
+#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
|
||||
+# include <bits/stdio-ldbl.h>
|
||||
+#endif
|
||||
+
|
||||
/* If we are compiling with optimizing read this file. It contains
|
||||
several optimizing inline functions and macros. */
|
||||
#ifdef __USE_EXTERN_INLINES
|
||||
# include <bits/stdio.h>
|
||||
#endif
|
||||
#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
|
||||
+/* Now include the function definitions and redirects too. */
|
||||
# include <bits/stdio2.h>
|
||||
#endif
|
||||
|
||||
-#include <bits/floatn.h>
|
||||
-#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
|
||||
-# include <bits/stdio-ldbl.h>
|
||||
-#endif
|
||||
-
|
||||
__END_DECLS
|
||||
|
||||
#endif /* <stdio.h> included. */
|
@ -0,0 +1,414 @@
|
||||
commit b41c535f46e7e7bbd8ff2ac68b94c2348e2f66e4
|
||||
Author: Raphael Moreira Zinsly <rzinsly@linux.ibm.com>
|
||||
Date: Wed Aug 24 11:43:37 2022 -0300
|
||||
|
||||
Apply asm redirections in wchar.h before first use
|
||||
|
||||
Similar to d0fa09a770, but for wchar.h. Fixes [BZ #27087] by applying
|
||||
all long double related asm redirections before using functions in
|
||||
bits/wchar2.h.
|
||||
Moves the function declarations from wcsmbs/bits/wchar2.h to a new file
|
||||
wcsmbs/bits/wchar2-decl.h that will be included first in wcsmbs/wchar.h.
|
||||
|
||||
Tested with build-many-glibcs.py.
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
(cherry picked from commit c7509d49c4e8fa494120c5ead21338559dad16f5)
|
||||
|
||||
diff --git a/include/bits/wchar2-decl.h b/include/bits/wchar2-decl.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..00b1b93342ef28ff
|
||||
--- /dev/null
|
||||
+++ b/include/bits/wchar2-decl.h
|
||||
@@ -0,0 +1 @@
|
||||
+#include <wcsmbs/bits/wchar2-decl.h>
|
||||
diff --git a/wcsmbs/Makefile b/wcsmbs/Makefile
|
||||
index f38eb5cfe16fd3d7..5fe755e65df6c621 100644
|
||||
--- a/wcsmbs/Makefile
|
||||
+++ b/wcsmbs/Makefile
|
||||
@@ -22,8 +22,9 @@ subdir := wcsmbs
|
||||
|
||||
include ../Makeconfig
|
||||
|
||||
-headers := wchar.h bits/wchar.h bits/wchar2.h bits/wchar-ldbl.h uchar.h \
|
||||
- bits/types/__mbstate_t.h bits/types/mbstate_t.h bits/types/wint_t.h
|
||||
+headers := wchar.h bits/wchar.h bits/wchar2.h bits/wchar2-decl.h \
|
||||
+ bits/wchar-ldbl.h uchar.h bits/types/__mbstate_t.h \
|
||||
+ bits/types/mbstate_t.h bits/types/wint_t.h
|
||||
|
||||
routines := wcscat wcschr wcscmp wcscpy wcscspn wcsdup wcslen wcsncat \
|
||||
wcsncmp wcsncpy wcspbrk wcsrchr wcsspn wcstok wcsstr wmemchr \
|
||||
diff --git a/wcsmbs/bits/wchar2-decl.h b/wcsmbs/bits/wchar2-decl.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..8e1735c33b7f7e78
|
||||
--- /dev/null
|
||||
+++ b/wcsmbs/bits/wchar2-decl.h
|
||||
@@ -0,0 +1,124 @@
|
||||
+/* Checking macros for wchar functions. Declarations only.
|
||||
+ Copyright (C) 2004-2022 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/>. */
|
||||
+
|
||||
+#ifndef _BITS_WCHAR2_DECL_H
|
||||
+#define _BITS_WCHAR2_DECL_H 1
|
||||
+
|
||||
+#ifndef _WCHAR_H
|
||||
+# error "Never include <bits/wchar2-decl.h> directly; use <wchar.h> instead."
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+extern wchar_t *__wmemcpy_chk (wchar_t *__restrict __s1,
|
||||
+ const wchar_t *__restrict __s2, size_t __n,
|
||||
+ size_t __ns1) __THROW;
|
||||
+extern wchar_t *__wmemmove_chk (wchar_t *__s1, const wchar_t *__s2,
|
||||
+ size_t __n, size_t __ns1) __THROW;
|
||||
+
|
||||
+
|
||||
+#ifdef __USE_GNU
|
||||
+
|
||||
+extern wchar_t *__wmempcpy_chk (wchar_t *__restrict __s1,
|
||||
+ const wchar_t *__restrict __s2, size_t __n,
|
||||
+ size_t __ns1) __THROW;
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+extern wchar_t *__wmemset_chk (wchar_t *__s, wchar_t __c, size_t __n,
|
||||
+ size_t __ns) __THROW;
|
||||
+extern wchar_t *__wcscpy_chk (wchar_t *__restrict __dest,
|
||||
+ const wchar_t *__restrict __src,
|
||||
+ size_t __n) __THROW;
|
||||
+extern wchar_t *__wcpcpy_chk (wchar_t *__restrict __dest,
|
||||
+ const wchar_t *__restrict __src,
|
||||
+ size_t __destlen) __THROW;
|
||||
+extern wchar_t *__wcsncpy_chk (wchar_t *__restrict __dest,
|
||||
+ const wchar_t *__restrict __src, size_t __n,
|
||||
+ size_t __destlen) __THROW;
|
||||
+extern wchar_t *__wcpncpy_chk (wchar_t *__restrict __dest,
|
||||
+ const wchar_t *__restrict __src, size_t __n,
|
||||
+ size_t __destlen) __THROW;
|
||||
+extern wchar_t *__wcscat_chk (wchar_t *__restrict __dest,
|
||||
+ const wchar_t *__restrict __src,
|
||||
+ size_t __destlen) __THROW;
|
||||
+extern wchar_t *__wcsncat_chk (wchar_t *__restrict __dest,
|
||||
+ const wchar_t *__restrict __src,
|
||||
+ size_t __n, size_t __destlen) __THROW;
|
||||
+extern int __swprintf_chk (wchar_t *__restrict __s, size_t __n,
|
||||
+ int __flag, size_t __s_len,
|
||||
+ const wchar_t *__restrict __format, ...)
|
||||
+ __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 6))) */;
|
||||
+extern int __vswprintf_chk (wchar_t *__restrict __s, size_t __n,
|
||||
+ int __flag, size_t __s_len,
|
||||
+ const wchar_t *__restrict __format,
|
||||
+ __gnuc_va_list __arg)
|
||||
+ __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 0))) */;
|
||||
+
|
||||
+#if __USE_FORTIFY_LEVEL > 1
|
||||
+
|
||||
+extern int __fwprintf_chk (__FILE *__restrict __stream, int __flag,
|
||||
+ const wchar_t *__restrict __format, ...);
|
||||
+extern int __wprintf_chk (int __flag, const wchar_t *__restrict __format,
|
||||
+ ...);
|
||||
+extern int __vfwprintf_chk (__FILE *__restrict __stream, int __flag,
|
||||
+ const wchar_t *__restrict __format,
|
||||
+ __gnuc_va_list __ap);
|
||||
+extern int __vwprintf_chk (int __flag, const wchar_t *__restrict __format,
|
||||
+ __gnuc_va_list __ap);
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+extern wchar_t *__fgetws_chk (wchar_t *__restrict __s, size_t __size, int __n,
|
||||
+ __FILE *__restrict __stream) __wur;
|
||||
+
|
||||
+#ifdef __USE_GNU
|
||||
+
|
||||
+extern wchar_t *__fgetws_unlocked_chk (wchar_t *__restrict __s, size_t __size,
|
||||
+ int __n, __FILE *__restrict __stream)
|
||||
+ __wur;
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+extern size_t __wcrtomb_chk (char *__restrict __s, wchar_t __wchar,
|
||||
+ mbstate_t *__restrict __p,
|
||||
+ size_t __buflen) __THROW __wur;
|
||||
+extern size_t __mbsrtowcs_chk (wchar_t *__restrict __dst,
|
||||
+ const char **__restrict __src,
|
||||
+ size_t __len, mbstate_t *__restrict __ps,
|
||||
+ size_t __dstlen) __THROW;
|
||||
+extern size_t __wcsrtombs_chk (char *__restrict __dst,
|
||||
+ const wchar_t **__restrict __src,
|
||||
+ size_t __len, mbstate_t *__restrict __ps,
|
||||
+ size_t __dstlen) __THROW;
|
||||
+
|
||||
+#ifdef __USE_XOPEN2K8
|
||||
+
|
||||
+extern size_t __mbsnrtowcs_chk (wchar_t *__restrict __dst,
|
||||
+ const char **__restrict __src, size_t __nmc,
|
||||
+ size_t __len, mbstate_t *__restrict __ps,
|
||||
+ size_t __dstlen) __THROW;
|
||||
+extern size_t __wcsnrtombs_chk (char *__restrict __dst,
|
||||
+ const wchar_t **__restrict __src,
|
||||
+ size_t __nwc, size_t __len,
|
||||
+ mbstate_t *__restrict __ps, size_t __dstlen)
|
||||
+ __THROW;
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+#endif /* bits/wchar2-decl.h. */
|
||||
diff --git a/wcsmbs/bits/wchar2.h b/wcsmbs/bits/wchar2.h
|
||||
index 88c1fdfcd34292f4..50151b424d85a032 100644
|
||||
--- a/wcsmbs/bits/wchar2.h
|
||||
+++ b/wcsmbs/bits/wchar2.h
|
||||
@@ -21,9 +21,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
-extern wchar_t *__wmemcpy_chk (wchar_t *__restrict __s1,
|
||||
- const wchar_t *__restrict __s2, size_t __n,
|
||||
- size_t __ns1) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wmemcpy_alias,
|
||||
(wchar_t *__restrict __s1,
|
||||
const wchar_t *__restrict __s2, size_t __n),
|
||||
@@ -45,8 +42,6 @@ __NTH (wmemcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2,
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wmemmove_chk (wchar_t *__s1, const wchar_t *__s2,
|
||||
- size_t __n, size_t __ns1) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wmemmove_alias, (wchar_t *__s1,
|
||||
const wchar_t *__s2,
|
||||
size_t __n), wmemmove);
|
||||
@@ -66,9 +61,6 @@ __NTH (wmemmove (wchar_t *__s1, const wchar_t *__s2, size_t __n))
|
||||
|
||||
|
||||
#ifdef __USE_GNU
|
||||
-extern wchar_t *__wmempcpy_chk (wchar_t *__restrict __s1,
|
||||
- const wchar_t *__restrict __s2, size_t __n,
|
||||
- size_t __ns1) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wmempcpy_alias,
|
||||
(wchar_t *__restrict __s1,
|
||||
const wchar_t *__restrict __s2,
|
||||
@@ -91,8 +83,6 @@ __NTH (wmempcpy (wchar_t *__restrict __s1, const wchar_t *__restrict __s2,
|
||||
#endif
|
||||
|
||||
|
||||
-extern wchar_t *__wmemset_chk (wchar_t *__s, wchar_t __c, size_t __n,
|
||||
- size_t __ns) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wmemset_alias, (wchar_t *__s, wchar_t __c,
|
||||
size_t __n), wmemset);
|
||||
extern wchar_t *__REDIRECT_NTH (__wmemset_chk_warn,
|
||||
@@ -110,9 +100,6 @@ __NTH (wmemset (wchar_t *__s, wchar_t __c, size_t __n))
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wcscpy_chk (wchar_t *__restrict __dest,
|
||||
- const wchar_t *__restrict __src,
|
||||
- size_t __n) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wcscpy_alias,
|
||||
(wchar_t *__restrict __dest,
|
||||
const wchar_t *__restrict __src), wcscpy);
|
||||
@@ -127,9 +114,6 @@ __NTH (wcscpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wcpcpy_chk (wchar_t *__restrict __dest,
|
||||
- const wchar_t *__restrict __src,
|
||||
- size_t __destlen) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wcpcpy_alias,
|
||||
(wchar_t *__restrict __dest,
|
||||
const wchar_t *__restrict __src), wcpcpy);
|
||||
@@ -144,9 +128,6 @@ __NTH (wcpcpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wcsncpy_chk (wchar_t *__restrict __dest,
|
||||
- const wchar_t *__restrict __src, size_t __n,
|
||||
- size_t __destlen) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wcsncpy_alias,
|
||||
(wchar_t *__restrict __dest,
|
||||
const wchar_t *__restrict __src,
|
||||
@@ -168,9 +149,6 @@ __NTH (wcsncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wcpncpy_chk (wchar_t *__restrict __dest,
|
||||
- const wchar_t *__restrict __src, size_t __n,
|
||||
- size_t __destlen) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wcpncpy_alias,
|
||||
(wchar_t *__restrict __dest,
|
||||
const wchar_t *__restrict __src,
|
||||
@@ -192,9 +170,6 @@ __NTH (wcpncpy (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wcscat_chk (wchar_t *__restrict __dest,
|
||||
- const wchar_t *__restrict __src,
|
||||
- size_t __destlen) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wcscat_alias,
|
||||
(wchar_t *__restrict __dest,
|
||||
const wchar_t *__restrict __src), wcscat);
|
||||
@@ -209,9 +184,6 @@ __NTH (wcscat (wchar_t *__restrict __dest, const wchar_t *__restrict __src))
|
||||
}
|
||||
|
||||
|
||||
-extern wchar_t *__wcsncat_chk (wchar_t *__restrict __dest,
|
||||
- const wchar_t *__restrict __src,
|
||||
- size_t __n, size_t __destlen) __THROW;
|
||||
extern wchar_t *__REDIRECT_NTH (__wcsncat_alias,
|
||||
(wchar_t *__restrict __dest,
|
||||
const wchar_t *__restrict __src,
|
||||
@@ -228,10 +200,6 @@ __NTH (wcsncat (wchar_t *__restrict __dest, const wchar_t *__restrict __src,
|
||||
}
|
||||
|
||||
|
||||
-extern int __swprintf_chk (wchar_t *__restrict __s, size_t __n,
|
||||
- int __flag, size_t __s_len,
|
||||
- const wchar_t *__restrict __format, ...)
|
||||
- __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 6))) */;
|
||||
|
||||
extern int __REDIRECT_NTH_LDBL (__swprintf_alias,
|
||||
(wchar_t *__restrict __s, size_t __n,
|
||||
@@ -258,11 +226,6 @@ __NTH (swprintf (wchar_t *__restrict __s, size_t __n,
|
||||
: swprintf (s, n, __VA_ARGS__))
|
||||
#endif
|
||||
|
||||
-extern int __vswprintf_chk (wchar_t *__restrict __s, size_t __n,
|
||||
- int __flag, size_t __s_len,
|
||||
- const wchar_t *__restrict __format,
|
||||
- __gnuc_va_list __arg)
|
||||
- __THROW /* __attribute__ ((__format__ (__wprintf__, 5, 0))) */;
|
||||
|
||||
extern int __REDIRECT_NTH_LDBL (__vswprintf_alias,
|
||||
(wchar_t *__restrict __s, size_t __n,
|
||||
@@ -283,16 +246,6 @@ __NTH (vswprintf (wchar_t *__restrict __s, size_t __n,
|
||||
|
||||
#if __USE_FORTIFY_LEVEL > 1
|
||||
|
||||
-extern int __fwprintf_chk (__FILE *__restrict __stream, int __flag,
|
||||
- const wchar_t *__restrict __format, ...);
|
||||
-extern int __wprintf_chk (int __flag, const wchar_t *__restrict __format,
|
||||
- ...);
|
||||
-extern int __vfwprintf_chk (__FILE *__restrict __stream, int __flag,
|
||||
- const wchar_t *__restrict __format,
|
||||
- __gnuc_va_list __ap);
|
||||
-extern int __vwprintf_chk (int __flag, const wchar_t *__restrict __format,
|
||||
- __gnuc_va_list __ap);
|
||||
-
|
||||
# ifdef __va_arg_pack
|
||||
__fortify_function int
|
||||
wprintf (const wchar_t *__restrict __fmt, ...)
|
||||
@@ -328,8 +281,6 @@ vfwprintf (__FILE *__restrict __stream,
|
||||
|
||||
#endif
|
||||
|
||||
-extern wchar_t *__fgetws_chk (wchar_t *__restrict __s, size_t __size, int __n,
|
||||
- __FILE *__restrict __stream) __wur;
|
||||
extern wchar_t *__REDIRECT (__fgetws_alias,
|
||||
(wchar_t *__restrict __s, int __n,
|
||||
__FILE *__restrict __stream), fgetws) __wur;
|
||||
@@ -351,9 +302,6 @@ fgetws (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream)
|
||||
}
|
||||
|
||||
#ifdef __USE_GNU
|
||||
-extern wchar_t *__fgetws_unlocked_chk (wchar_t *__restrict __s, size_t __size,
|
||||
- int __n, __FILE *__restrict __stream)
|
||||
- __wur;
|
||||
extern wchar_t *__REDIRECT (__fgetws_unlocked_alias,
|
||||
(wchar_t *__restrict __s, int __n,
|
||||
__FILE *__restrict __stream), fgetws_unlocked)
|
||||
@@ -379,9 +327,6 @@ fgetws_unlocked (wchar_t *__restrict __s, int __n, __FILE *__restrict __stream)
|
||||
#endif
|
||||
|
||||
|
||||
-extern size_t __wcrtomb_chk (char *__restrict __s, wchar_t __wchar,
|
||||
- mbstate_t *__restrict __p,
|
||||
- size_t __buflen) __THROW __wur;
|
||||
extern size_t __REDIRECT_NTH (__wcrtomb_alias,
|
||||
(char *__restrict __s, wchar_t __wchar,
|
||||
mbstate_t *__restrict __ps), wcrtomb) __wur;
|
||||
@@ -404,10 +349,6 @@ __NTH (wcrtomb (char *__restrict __s, wchar_t __wchar,
|
||||
}
|
||||
|
||||
|
||||
-extern size_t __mbsrtowcs_chk (wchar_t *__restrict __dst,
|
||||
- const char **__restrict __src,
|
||||
- size_t __len, mbstate_t *__restrict __ps,
|
||||
- size_t __dstlen) __THROW;
|
||||
extern size_t __REDIRECT_NTH (__mbsrtowcs_alias,
|
||||
(wchar_t *__restrict __dst,
|
||||
const char **__restrict __src,
|
||||
@@ -431,10 +372,6 @@ __NTH (mbsrtowcs (wchar_t *__restrict __dst, const char **__restrict __src,
|
||||
}
|
||||
|
||||
|
||||
-extern size_t __wcsrtombs_chk (char *__restrict __dst,
|
||||
- const wchar_t **__restrict __src,
|
||||
- size_t __len, mbstate_t *__restrict __ps,
|
||||
- size_t __dstlen) __THROW;
|
||||
extern size_t __REDIRECT_NTH (__wcsrtombs_alias,
|
||||
(char *__restrict __dst,
|
||||
const wchar_t **__restrict __src,
|
||||
@@ -458,10 +395,6 @@ __NTH (wcsrtombs (char *__restrict __dst, const wchar_t **__restrict __src,
|
||||
|
||||
|
||||
#ifdef __USE_XOPEN2K8
|
||||
-extern size_t __mbsnrtowcs_chk (wchar_t *__restrict __dst,
|
||||
- const char **__restrict __src, size_t __nmc,
|
||||
- size_t __len, mbstate_t *__restrict __ps,
|
||||
- size_t __dstlen) __THROW;
|
||||
extern size_t __REDIRECT_NTH (__mbsnrtowcs_alias,
|
||||
(wchar_t *__restrict __dst,
|
||||
const char **__restrict __src, size_t __nmc,
|
||||
@@ -485,11 +418,6 @@ __NTH (mbsnrtowcs (wchar_t *__restrict __dst, const char **__restrict __src,
|
||||
}
|
||||
|
||||
|
||||
-extern size_t __wcsnrtombs_chk (char *__restrict __dst,
|
||||
- const wchar_t **__restrict __src,
|
||||
- size_t __nwc, size_t __len,
|
||||
- mbstate_t *__restrict __ps, size_t __dstlen)
|
||||
- __THROW;
|
||||
extern size_t __REDIRECT_NTH (__wcsnrtombs_alias,
|
||||
(char *__restrict __dst,
|
||||
const wchar_t **__restrict __src,
|
||||
diff --git a/wcsmbs/wchar.h b/wcsmbs/wchar.h
|
||||
index 075776890f214842..1c6d4026c46b7306 100644
|
||||
--- a/wcsmbs/wchar.h
|
||||
+++ b/wcsmbs/wchar.h
|
||||
@@ -864,14 +864,21 @@ extern size_t wcsftime_l (wchar_t *__restrict __s, size_t __maxsize,
|
||||
|
||||
/* Define some macros helping to catch buffer overflows. */
|
||||
#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
|
||||
-# include <bits/wchar2.h>
|
||||
+/* Declare all functions from bits/wchar2-decl.h first. */
|
||||
+# include <bits/wchar2-decl.h>
|
||||
#endif
|
||||
|
||||
-#include <bits/floatn.h>
|
||||
+/* The following headers provide asm redirections. These redirections must
|
||||
+ appear before the first usage of these functions, e.g. in bits/wchar.h. */
|
||||
#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
|
||||
# include <bits/wchar-ldbl.h>
|
||||
#endif
|
||||
|
||||
+#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
|
||||
+/* Now include the function definitions and redirects too. */
|
||||
+# include <bits/wchar2.h>
|
||||
+#endif
|
||||
+
|
||||
__END_DECLS
|
||||
|
||||
#endif /* wchar.h */
|
@ -0,0 +1,40 @@
|
||||
commit 2b3d020055bea4fbbfc0ca2362d46038487c6dfd
|
||||
Author: Fabian Vogt <fvogt@suse.de>
|
||||
Date: Wed Jul 27 11:44:07 2022 +0200
|
||||
|
||||
nscd: Fix netlink cache invalidation if epoll is used [BZ #29415]
|
||||
|
||||
Processes cache network interface information such as whether IPv4 or IPv6
|
||||
are enabled. This is only checked again if the "netlink timestamp" provided
|
||||
by nscd changed, which is triggered by netlink socket activity.
|
||||
|
||||
However, in the epoll handler for the netlink socket, it was missed to
|
||||
assign the new timestamp to the nscd database. The handler for plain poll
|
||||
did that properly, copy that over.
|
||||
|
||||
This bug caused that e.g. processes which started before network
|
||||
configuration got unusuable addresses from getaddrinfo, like IPv6 only even
|
||||
though only IPv4 is available:
|
||||
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1041
|
||||
|
||||
It's a bit hard to reproduce, so I verified this by checking the timestamp
|
||||
on calls to __check_pf manually. Without this patch it's stuck at 1, now
|
||||
it's increasing on network changes as expected.
|
||||
|
||||
Signed-off-by: Fabian Vogt <fvogt@suse.de>
|
||||
(cherry picked from commit 02ca25fef2785974011e9c5beecc99b900b69fd7)
|
||||
|
||||
diff --git a/nscd/connections.c b/nscd/connections.c
|
||||
index 3f0bda4e97edb9df..bc941715cff47c49 100644
|
||||
--- a/nscd/connections.c
|
||||
+++ b/nscd/connections.c
|
||||
@@ -2285,7 +2285,8 @@ main_loop_epoll (int efd)
|
||||
sizeof (buf))) != -1)
|
||||
;
|
||||
|
||||
- __bump_nl_timestamp ();
|
||||
+ dbs[hstdb].head->extra_data[NSCD_HST_IDX_CONF_TIMESTAMP]
|
||||
+ = __bump_nl_timestamp ();
|
||||
}
|
||||
# endif
|
||||
else
|
@ -0,0 +1,55 @@
|
||||
commit 2ff6775ad341b10a08e3b27d6e1df1da637747c7
|
||||
Author: Javier Pello <devel@otheo.eu>
|
||||
Date: Mon Sep 5 20:09:01 2022 +0200
|
||||
|
||||
elf: Fix hwcaps string size overestimation
|
||||
|
||||
Commit dad90d528259b669342757c37dedefa8577e2636 added glibc-hwcaps
|
||||
support for LD_LIBRARY_PATH and, for this, it adjusted the total
|
||||
string size required in _dl_important_hwcaps. However, in doing so
|
||||
it inadvertently altered the calculation of the size required for
|
||||
the power set strings, as the computation of the power set string
|
||||
size depended on the first value assigned to the total variable,
|
||||
which is later shifted, resulting in overallocation of string
|
||||
space. Fix this now by using a different variable to hold the
|
||||
string size required for glibc-hwcaps.
|
||||
|
||||
Signed-off-by: Javier Pello <devel@otheo.eu>
|
||||
(cherry picked from commit a23820f6052a740246fdc7dcd9c43ce8eed0c45a)
|
||||
|
||||
diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
|
||||
index e3c611e005ffbc0d..045911eb6d5d315a 100644
|
||||
--- a/elf/dl-hwcaps.c
|
||||
+++ b/elf/dl-hwcaps.c
|
||||
@@ -193,7 +193,7 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
|
||||
/* Each hwcaps subdirectory has a GLIBC_HWCAPS_PREFIX string prefix
|
||||
and a "/" suffix once stored in the result. */
|
||||
hwcaps_counts.maximum_length += strlen (GLIBC_HWCAPS_PREFIX) + 1;
|
||||
- size_t total = (hwcaps_counts.count * (strlen (GLIBC_HWCAPS_PREFIX) + 1)
|
||||
+ size_t hwcaps_sz = (hwcaps_counts.count * (strlen (GLIBC_HWCAPS_PREFIX) + 1)
|
||||
+ hwcaps_counts.total_length);
|
||||
|
||||
/* Count the number of bits set in the masked value. */
|
||||
@@ -229,11 +229,12 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
|
||||
assert (m == cnt);
|
||||
|
||||
/* Determine the total size of all strings together. */
|
||||
+ size_t total;
|
||||
if (cnt == 1)
|
||||
- total += temp[0].len + 1;
|
||||
+ total = temp[0].len + 1;
|
||||
else
|
||||
{
|
||||
- total += temp[0].len + temp[cnt - 1].len + 2;
|
||||
+ total = temp[0].len + temp[cnt - 1].len + 2;
|
||||
if (cnt > 2)
|
||||
{
|
||||
total <<= 1;
|
||||
@@ -255,6 +256,7 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
|
||||
/* This is the overall result, including both glibc-hwcaps
|
||||
subdirectories and the legacy hwcaps subdirectories using the
|
||||
power set construction. */
|
||||
+ total += hwcaps_sz;
|
||||
struct r_strlenpair *overall_result
|
||||
= malloc (*sz * sizeof (*result) + total);
|
||||
if (overall_result == NULL)
|
@ -0,0 +1,62 @@
|
||||
commit f50a6c843a5b5186c0aa73747de033e08ef8246d
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Sep 20 12:12:43 2022 +0200
|
||||
|
||||
gconv: Use 64-bit interfaces in gconv_parseconfdir (bug 29583)
|
||||
|
||||
It's possible that inode numbers are outside the 32-bit range.
|
||||
The existing code only handles the in-libc case correctly, and
|
||||
still uses the legacy interfaces when building iconv.
|
||||
|
||||
Suggested-by: Helge Deller <deller@gmx.de>
|
||||
(cherry picked from commit f97905f24631097af325d6a231093071c3077a5f)
|
||||
|
||||
diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
|
||||
index 79398a980cde84e3..741cf7c67e36eccd 100644
|
||||
--- a/iconv/gconv_parseconfdir.h
|
||||
+++ b/iconv/gconv_parseconfdir.h
|
||||
@@ -29,14 +29,14 @@
|
||||
# define isspace(__c) __isspace_l ((__c), _nl_C_locobj_ptr)
|
||||
# define asprintf __asprintf
|
||||
# define opendir __opendir
|
||||
-# define readdir __readdir
|
||||
+# define readdir64 __readdir64
|
||||
# define closedir __closedir
|
||||
# define mempcpy __mempcpy
|
||||
-# define struct_stat struct __stat64_t64
|
||||
-# define lstat __lstat64_time64
|
||||
+# define struct_stat64 struct __stat64_t64
|
||||
+# define lstat64 __lstat64_time64
|
||||
# define feof_unlocked __feof_unlocked
|
||||
#else
|
||||
-# define struct_stat struct stat
|
||||
+# define struct_stat64 struct stat64
|
||||
#endif
|
||||
|
||||
/* Name of the file containing the module information in the directories
|
||||
@@ -148,8 +148,8 @@ gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len)
|
||||
DIR *confdir = opendir (buf);
|
||||
if (confdir != NULL)
|
||||
{
|
||||
- struct dirent *ent;
|
||||
- while ((ent = readdir (confdir)) != NULL)
|
||||
+ struct dirent64 *ent;
|
||||
+ while ((ent = readdir64 (confdir)) != NULL)
|
||||
{
|
||||
if (ent->d_type != DT_REG && ent->d_type != DT_UNKNOWN)
|
||||
continue;
|
||||
@@ -161,12 +161,12 @@ gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len)
|
||||
&& strcmp (ent->d_name + len - strlen (suffix), suffix) == 0)
|
||||
{
|
||||
char *conf;
|
||||
- struct_stat st;
|
||||
+ struct_stat64 st;
|
||||
if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
|
||||
continue;
|
||||
|
||||
if (ent->d_type != DT_UNKNOWN
|
||||
- || (lstat (conf, &st) != -1 && S_ISREG (st.st_mode)))
|
||||
+ || (lstat64 (conf, &st) != -1 && S_ISREG (st.st_mode)))
|
||||
found |= read_conf_file (conf, dir, dir_len);
|
||||
|
||||
free (conf);
|
@ -0,0 +1,399 @@
|
||||
commit 1a3afdfe319a142228498f7a4ee82ac3917d97e8
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add tst-resolv-byaddr for testing reverse lookup
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 0b99828d54e5d1fc8f5ad3edf5ba262ad2e9c5b0)
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index e8269dcb5bcf216b..78165eb99e98b525 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -92,6 +92,7 @@ tests += \
|
||||
tst-res_hnok \
|
||||
tst-resolv-basic \
|
||||
tst-resolv-binary \
|
||||
+ tst-resolv-byaddr \
|
||||
tst-resolv-edns \
|
||||
tst-resolv-network \
|
||||
tst-resolv-noaaaa \
|
||||
@@ -251,6 +252,7 @@ $(objpfx)tst-resolv-ai_idn-nolibidn2.out: \
|
||||
$(gen-locales) $(objpfx)tst-no-libidn2.so
|
||||
$(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
+$(objpfx)tst-resolv-byaddr: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-res_init: $(objpfx)libresolv.so
|
||||
diff --git a/resolv/tst-resolv-byaddr.c b/resolv/tst-resolv-byaddr.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..6299e89837da58c6
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-byaddr.c
|
||||
@@ -0,0 +1,326 @@
|
||||
+/* Test reverse DNS lookup.
|
||||
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <arpa/inet.h>
|
||||
+#include <errno.h>
|
||||
+#include <netdb.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/check_nss.h>
|
||||
+#include <support/next_to_fault.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+#include "tst-resolv-maybe_insert_sig.h"
|
||||
+
|
||||
+/* QNAME format:
|
||||
+
|
||||
+ ADDRESSES.CNAMES...(lots of 0s)...8.b.d.0.1.0.0.2.ip6.arpa.
|
||||
+ CNAMES|ADDRESSES.2.0.192.in-addr-arpa.
|
||||
+
|
||||
+ For the IPv4 reverse lookup, the address count is in the lower
|
||||
+ bits.
|
||||
+
|
||||
+ CNAMES is the length of the CNAME chain, ADDRESSES is the number of
|
||||
+ addresses in the response. The special value 15 means that there
|
||||
+ are no addresses, and the RCODE is NXDOMAIN. */
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ TEST_COMPARE (qclass, C_IN);
|
||||
+ TEST_COMPARE (qtype, T_PTR);
|
||||
+
|
||||
+ unsigned int addresses, cnames, bits;
|
||||
+ char *tail;
|
||||
+ if (strstr (qname, "ip6.arpa") != NULL
|
||||
+ && sscanf (qname, "%x.%x.%ms", &addresses, &cnames, &tail) == 3)
|
||||
+ TEST_COMPARE_STRING (tail, "\
|
||||
+0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa");
|
||||
+ else if (sscanf (qname, "%u.%ms", &bits, &tail) == 2)
|
||||
+ {
|
||||
+ TEST_COMPARE_STRING (tail, "2.0.192.in-addr.arpa");
|
||||
+ addresses = bits & 0x0f;
|
||||
+ cnames = bits >> 4;
|
||||
+ }
|
||||
+ else
|
||||
+ FAIL_EXIT1 ("invalid QNAME: %s", qname);
|
||||
+ free (tail);
|
||||
+
|
||||
+ int rcode;
|
||||
+ if (addresses == 15)
|
||||
+ {
|
||||
+ /* Special case: Use no addresses with NXDOMAIN response. */
|
||||
+ rcode = ns_r_nxdomain;
|
||||
+ addresses = 0;
|
||||
+ }
|
||||
+ else
|
||||
+ rcode = 0;
|
||||
+
|
||||
+ struct resolv_response_flags flags = { .rcode = rcode };
|
||||
+ resolv_response_init (b, flags);
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ resolv_response_section (b, ns_s_an);
|
||||
+ maybe_insert_sig (b, qname);
|
||||
+
|
||||
+ /* Provide the requested number of CNAME records. */
|
||||
+ char *previous_name = (char *) qname;
|
||||
+ for (int unique = 0; unique < cnames; ++unique)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, previous_name, qclass, T_CNAME, 60);
|
||||
+ char *new_name = xasprintf ("%d.alias.example", unique);
|
||||
+ resolv_response_add_name (b, new_name);
|
||||
+ resolv_response_close_record (b);
|
||||
+
|
||||
+ maybe_insert_sig (b, qname);
|
||||
+
|
||||
+ if (previous_name != qname)
|
||||
+ free (previous_name);
|
||||
+ previous_name = new_name;
|
||||
+ }
|
||||
+
|
||||
+ for (int unique = 0; unique < addresses; ++unique)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, previous_name, qclass, T_PTR, 60);
|
||||
+ char *ptr = xasprintf ("unique-%d.cnames-%u.addresses-%u.example",
|
||||
+ unique, cnames, addresses);
|
||||
+ resolv_response_add_name (b, ptr);
|
||||
+ free (ptr);
|
||||
+ resolv_response_close_record (b);
|
||||
+ }
|
||||
+
|
||||
+ if (previous_name != qname)
|
||||
+ free (previous_name);
|
||||
+}
|
||||
+
|
||||
+/* Used to check that gethostbyaddr_r does not write past the buffer
|
||||
+ end. */
|
||||
+static struct support_next_to_fault ntf;
|
||||
+
|
||||
+/* Perform a gethostbyaddr call and check the result. */
|
||||
+static void
|
||||
+check_gethostbyaddr (const char *address, const char *expected)
|
||||
+{
|
||||
+ unsigned char bytes[16];
|
||||
+ unsigned int byteslen;
|
||||
+ int family;
|
||||
+ if (strchr (address, ':') != NULL)
|
||||
+ {
|
||||
+ family = AF_INET6;
|
||||
+ byteslen = 16;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ family = AF_INET;
|
||||
+ byteslen = 4;
|
||||
+ }
|
||||
+ TEST_COMPARE (inet_pton (family, address, bytes), 1);
|
||||
+
|
||||
+ struct hostent *e = gethostbyaddr (bytes, byteslen, family);
|
||||
+ check_hostent (address, e, expected);
|
||||
+
|
||||
+ if (e == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ /* Try gethostbyaddr_r with increasing sizes until success. First
|
||||
+ compute a reasonable minimum buffer size, to avoid many pointless
|
||||
+ attempts. */
|
||||
+ size_t minimum_size = strlen (e->h_name);
|
||||
+ for (int i = 0; e->h_addr_list[i] != NULL; ++i)
|
||||
+ minimum_size += e->h_length + sizeof (char *);
|
||||
+ for (int i = 0; e->h_aliases[i] != NULL; ++i)
|
||||
+ minimum_size += strlen (e->h_aliases[i]) + 1 + sizeof (char *);
|
||||
+
|
||||
+ /* Gradually increase the size until success. */
|
||||
+ for (size_t size = minimum_size; size < ntf.length; ++size)
|
||||
+ {
|
||||
+ struct hostent result;
|
||||
+ int herrno;
|
||||
+ int ret = gethostbyaddr_r (bytes, byteslen, family, &result,
|
||||
+ ntf.buffer + ntf.length - size, size,
|
||||
+ &e, &herrno);
|
||||
+ if (ret == ERANGE)
|
||||
+ /* Retry with larger size. */
|
||||
+ TEST_COMPARE (herrno, NETDB_INTERNAL);
|
||||
+ else if (ret == 0)
|
||||
+ {
|
||||
+ TEST_VERIFY (size > minimum_size);
|
||||
+ check_hostent (address, e, expected);
|
||||
+ return;
|
||||
+ }
|
||||
+ else
|
||||
+ FAIL_EXIT1 ("Unexpected gethostbyaddr_r failure: %d", ret);
|
||||
+ }
|
||||
+
|
||||
+ FAIL_EXIT1 ("gethostbyaddr_r always failed for: %s", address);
|
||||
+}
|
||||
+
|
||||
+/* Perform a getnameinfo call and check the result. */
|
||||
+static void
|
||||
+check_getnameinfo (const char *address, const char *expected)
|
||||
+{
|
||||
+ struct sockaddr_in sin = { };
|
||||
+ struct sockaddr_in6 sin6 = { };
|
||||
+ void *sa;
|
||||
+ socklen_t salen;
|
||||
+ if (strchr (address, ':') != NULL)
|
||||
+ {
|
||||
+ sin6.sin6_family = AF_INET6;
|
||||
+ TEST_COMPARE (inet_pton (AF_INET6, address, &sin6.sin6_addr), 1);
|
||||
+ sin6.sin6_port = htons (80);
|
||||
+ sa = &sin6;
|
||||
+ salen = sizeof (sin6);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ sin.sin_family = AF_INET;
|
||||
+ TEST_COMPARE (inet_pton (AF_INET, address, &sin.sin_addr), 1);
|
||||
+ sin.sin_port = htons (80);
|
||||
+ sa = &sin;
|
||||
+ salen = sizeof (sin);
|
||||
+ }
|
||||
+
|
||||
+ char host[64];
|
||||
+ char service[64];
|
||||
+ int ret = getnameinfo (sa, salen, host,
|
||||
+ sizeof (host), service, sizeof (service),
|
||||
+ NI_NAMEREQD | NI_NUMERICSERV);
|
||||
+ switch (ret)
|
||||
+ {
|
||||
+ case 0:
|
||||
+ TEST_COMPARE_STRING (host, expected);
|
||||
+ TEST_COMPARE_STRING (service, "80");
|
||||
+ break;
|
||||
+ case EAI_SYSTEM:
|
||||
+ TEST_COMPARE_STRING (strerror (errno), expected);
|
||||
+ break;
|
||||
+ default:
|
||||
+ TEST_COMPARE_STRING (gai_strerror (ret), expected);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ /* Some reasonably upper bound for the maximum response size. */
|
||||
+ ntf = support_next_to_fault_allocate (4096);
|
||||
+
|
||||
+ struct resolv_test *obj = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response
|
||||
+ });
|
||||
+
|
||||
+ for (int do_insert_sig = 0; do_insert_sig < 2; ++do_insert_sig)
|
||||
+ {
|
||||
+ insert_sig = do_insert_sig;
|
||||
+
|
||||
+ /* No PTR record, RCODE=0. */
|
||||
+ check_gethostbyaddr ("192.0.2.0", "error: NO_RECOVERY\n");
|
||||
+ check_getnameinfo ("192.0.2.0", "Name or service not known");
|
||||
+ check_gethostbyaddr ("192.0.2.16", "error: NO_RECOVERY\n");
|
||||
+ check_getnameinfo ("192.0.2.16", "Name or service not known");
|
||||
+ check_gethostbyaddr ("192.0.2.32", "error: NO_RECOVERY\n");
|
||||
+ check_getnameinfo ("192.0.2.32", "Name or service not known");
|
||||
+ check_gethostbyaddr ("2001:db8::", "error: NO_RECOVERY\n");
|
||||
+ check_getnameinfo ("2001:db8::", "Name or service not known");
|
||||
+ check_gethostbyaddr ("2001:db8::10", "error: NO_RECOVERY\n");
|
||||
+ check_getnameinfo ("2001:db8::10", "Name or service not known");
|
||||
+ check_gethostbyaddr ("2001:db8::20", "error: NO_RECOVERY\n");
|
||||
+ check_getnameinfo ("2001:db8::20", "Name or service not known");
|
||||
+
|
||||
+ /* No PTR record, NXDOMAIN. */
|
||||
+ check_gethostbyaddr ("192.0.2.15", "error: HOST_NOT_FOUND\n");
|
||||
+ check_getnameinfo ("192.0.2.15", "Name or service not known");
|
||||
+ check_gethostbyaddr ("192.0.2.31", "error: HOST_NOT_FOUND\n");
|
||||
+ check_getnameinfo ("192.0.2.31", "Name or service not known");
|
||||
+ check_gethostbyaddr ("192.0.2.47", "error: HOST_NOT_FOUND\n");
|
||||
+ check_getnameinfo ("192.0.2.47", "Name or service not known");
|
||||
+ check_gethostbyaddr ("2001:db8::f", "error: HOST_NOT_FOUND\n");
|
||||
+ check_getnameinfo ("2001:db8::f", "Name or service not known");
|
||||
+ check_gethostbyaddr ("2001:db8::1f", "error: HOST_NOT_FOUND\n");
|
||||
+ check_getnameinfo ("2001:db8::1f", "Name or service not known");
|
||||
+ check_gethostbyaddr ("2001:db8::2f", "error: HOST_NOT_FOUND\n");
|
||||
+ check_getnameinfo ("2001:db8::2f", "Name or service not known");
|
||||
+
|
||||
+ /* Actual response data. Only the first PTR record is returned. */
|
||||
+ check_gethostbyaddr ("192.0.2.1",
|
||||
+ "name: unique-0.cnames-0.addresses-1.example\n"
|
||||
+ "address: 192.0.2.1\n");
|
||||
+ check_getnameinfo ("192.0.2.1",
|
||||
+ "unique-0.cnames-0.addresses-1.example");
|
||||
+ check_gethostbyaddr ("192.0.2.17",
|
||||
+ "name: unique-0.cnames-1.addresses-1.example\n"
|
||||
+ "address: 192.0.2.17\n");
|
||||
+ check_getnameinfo ("192.0.2.17",
|
||||
+ "unique-0.cnames-1.addresses-1.example");
|
||||
+ check_gethostbyaddr ("192.0.2.18",
|
||||
+ "name: unique-0.cnames-1.addresses-2.example\n"
|
||||
+ "address: 192.0.2.18\n");
|
||||
+ check_getnameinfo ("192.0.2.18",
|
||||
+ "unique-0.cnames-1.addresses-2.example");
|
||||
+ check_gethostbyaddr ("192.0.2.33",
|
||||
+ "name: unique-0.cnames-2.addresses-1.example\n"
|
||||
+ "address: 192.0.2.33\n");
|
||||
+ check_getnameinfo ("192.0.2.33",
|
||||
+ "unique-0.cnames-2.addresses-1.example");
|
||||
+ check_gethostbyaddr ("192.0.2.34",
|
||||
+ "name: unique-0.cnames-2.addresses-2.example\n"
|
||||
+ "address: 192.0.2.34\n");
|
||||
+ check_getnameinfo ("192.0.2.34",
|
||||
+ "unique-0.cnames-2.addresses-2.example");
|
||||
+
|
||||
+ /* Same for IPv6 addresses. */
|
||||
+ check_gethostbyaddr ("2001:db8::1",
|
||||
+ "name: unique-0.cnames-0.addresses-1.example\n"
|
||||
+ "address: 2001:db8::1\n");
|
||||
+ check_getnameinfo ("2001:db8::1",
|
||||
+ "unique-0.cnames-0.addresses-1.example");
|
||||
+ check_gethostbyaddr ("2001:db8::11",
|
||||
+ "name: unique-0.cnames-1.addresses-1.example\n"
|
||||
+ "address: 2001:db8::11\n");
|
||||
+ check_getnameinfo ("2001:db8::11",
|
||||
+ "unique-0.cnames-1.addresses-1.example");
|
||||
+ check_gethostbyaddr ("2001:db8::12",
|
||||
+ "name: unique-0.cnames-1.addresses-2.example\n"
|
||||
+ "address: 2001:db8::12\n");
|
||||
+ check_getnameinfo ("2001:db8::12",
|
||||
+ "unique-0.cnames-1.addresses-2.example");
|
||||
+ check_gethostbyaddr ("2001:db8::21",
|
||||
+ "name: unique-0.cnames-2.addresses-1.example\n"
|
||||
+ "address: 2001:db8::21\n");
|
||||
+ check_getnameinfo ("2001:db8::21",
|
||||
+ "unique-0.cnames-2.addresses-1.example");
|
||||
+ check_gethostbyaddr ("2001:db8::22",
|
||||
+ "name: unique-0.cnames-2.addresses-2.example\n"
|
||||
+ "address: 2001:db8::22\n");
|
||||
+ check_getnameinfo ("2001:db8::22",
|
||||
+ "unique-0.cnames-2.addresses-2.example");
|
||||
+ }
|
||||
+
|
||||
+ resolv_test_end (obj);
|
||||
+
|
||||
+ support_next_to_fault_free (&ntf);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
diff --git a/resolv/tst-resolv-maybe_insert_sig.h b/resolv/tst-resolv-maybe_insert_sig.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..05725225af0818cb
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-maybe_insert_sig.h
|
||||
@@ -0,0 +1,32 @@
|
||||
+/* Code snippet for optionally inserting ignored SIG records in resolver tests.
|
||||
+ Copyright (C) 2022 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/>. */
|
||||
+
|
||||
+/* Set to true for an alternative pass that inserts (ignored) SIG
|
||||
+ records. This does not alter the response, so this property is not
|
||||
+ encoded in the QNAME. The variable needs to be volatile because
|
||||
+ leaf attributes tell GCC that the response function is not
|
||||
+ called. */
|
||||
+static volatile bool insert_sig;
|
||||
+
|
||||
+static void
|
||||
+maybe_insert_sig (struct resolv_response_builder *b, const char *owner)
|
||||
+{
|
||||
+ resolv_response_open_record (b, owner, C_IN, T_SIG, 60);
|
||||
+ resolv_response_add_data (b, "", 1);
|
||||
+ resolv_response_close_record (b);
|
||||
+}
|
@ -0,0 +1,289 @@
|
||||
commit 6a833d798e87536587cd4cc14fe8d078f80b14a0
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add tst-resolv-aliases
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 87aa98aa80627553a66bdcad2701fd6307723645)
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 78165eb99e98b525..567f4c2dcf5749df 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -90,6 +90,7 @@ tests += \
|
||||
tst-ns_name_pton \
|
||||
tst-res_hconf_reorder \
|
||||
tst-res_hnok \
|
||||
+ tst-resolv-aliases \
|
||||
tst-resolv-basic \
|
||||
tst-resolv-binary \
|
||||
tst-resolv-byaddr \
|
||||
@@ -250,6 +251,7 @@ $(objpfx)tst-resolv-ai_idn.out: $(gen-locales)
|
||||
$(objpfx)tst-resolv-ai_idn-latin1.out: $(gen-locales)
|
||||
$(objpfx)tst-resolv-ai_idn-nolibidn2.out: \
|
||||
$(gen-locales) $(objpfx)tst-no-libidn2.so
|
||||
+$(objpfx)tst-resolv-aliases: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
$(objpfx)tst-resolv-byaddr: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
diff --git a/resolv/tst-resolv-aliases.c b/resolv/tst-resolv-aliases.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..b212823aa07ceb21
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-aliases.c
|
||||
@@ -0,0 +1,254 @@
|
||||
+/* Test alias handling (mainly for gethostbyname).
|
||||
+ Copyright (C) 2022 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 <array_length.h>
|
||||
+#include <arpa/inet.h>
|
||||
+#include <netdb.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/check_nss.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/support.h>
|
||||
+
|
||||
+#include "tst-resolv-maybe_insert_sig.h"
|
||||
+
|
||||
+/* QNAME format:
|
||||
+
|
||||
+ aADDRESSES-cCNAMES.example.net
|
||||
+
|
||||
+ CNAMES is the length of the CNAME chain, ADDRESSES is the number of
|
||||
+ addresses in the response. The special value 255 means that there
|
||||
+ are no addresses, and the RCODE is NXDOMAIN. */
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ TEST_COMPARE (qclass, C_IN);
|
||||
+ if (qtype != T_A)
|
||||
+ TEST_COMPARE (qtype, T_AAAA);
|
||||
+
|
||||
+ unsigned int addresses, cnames;
|
||||
+ char *tail;
|
||||
+ if (sscanf (qname, "a%u-c%u%ms", &addresses, &cnames, &tail) == 3)
|
||||
+ {
|
||||
+ if (strcmp (tail, ".example.com") == 0
|
||||
+ || strcmp (tail, ".example.net.example.net") == 0
|
||||
+ || strcmp (tail, ".example.net.example.com") == 0)
|
||||
+ /* These only happen after NXDOMAIN. */
|
||||
+ TEST_VERIFY (addresses == 255);
|
||||
+ else if (strcmp (tail, ".example.net") != 0)
|
||||
+ FAIL_EXIT1 ("invalid QNAME: %s", qname);
|
||||
+ }
|
||||
+ free (tail);
|
||||
+
|
||||
+ int rcode;
|
||||
+ if (addresses == 255)
|
||||
+ {
|
||||
+ /* Special case: Use no addresses with NXDOMAIN response. */
|
||||
+ rcode = ns_r_nxdomain;
|
||||
+ addresses = 0;
|
||||
+ }
|
||||
+ else
|
||||
+ rcode = 0;
|
||||
+
|
||||
+ struct resolv_response_flags flags = { .rcode = rcode };
|
||||
+ resolv_response_init (b, flags);
|
||||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||||
+ resolv_response_section (b, ns_s_an);
|
||||
+ maybe_insert_sig (b, qname);
|
||||
+
|
||||
+ /* Provide the requested number of CNAME records. */
|
||||
+ char *previous_name = (char *) qname;
|
||||
+ for (int unique = 0; unique < cnames; ++unique)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, previous_name, qclass, T_CNAME, 60);
|
||||
+ char *new_name = xasprintf ("%d.alias.example", unique);
|
||||
+ resolv_response_add_name (b, new_name);
|
||||
+ resolv_response_close_record (b);
|
||||
+
|
||||
+ maybe_insert_sig (b, qname);
|
||||
+
|
||||
+ if (previous_name != qname)
|
||||
+ free (previous_name);
|
||||
+ previous_name = new_name;
|
||||
+ }
|
||||
+
|
||||
+ for (int unique = 0; unique < addresses; ++unique)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, previous_name, qclass, qtype, 60);
|
||||
+
|
||||
+ if (qtype == T_A)
|
||||
+ {
|
||||
+ char ipv4[4] = {192, 0, 2, 1 + unique};
|
||||
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
|
||||
+ }
|
||||
+ else if (qtype == T_AAAA)
|
||||
+ {
|
||||
+ char ipv6[16] =
|
||||
+ {
|
||||
+ 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
+ 1 + unique
|
||||
+ };
|
||||
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
|
||||
+ }
|
||||
+ resolv_response_close_record (b);
|
||||
+ }
|
||||
+
|
||||
+ if (previous_name != qname)
|
||||
+ free (previous_name);
|
||||
+}
|
||||
+
|
||||
+static char *
|
||||
+make_qname (bool do_search, int cnames, int addresses)
|
||||
+{
|
||||
+ return xasprintf ("a%d-c%d%s",
|
||||
+ addresses, cnames, do_search ? "" : ".example.net");
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+check_cnames_failure (int af, bool do_search, int cnames, int addresses)
|
||||
+{
|
||||
+ char *qname = make_qname (do_search, cnames, addresses);
|
||||
+
|
||||
+ struct hostent *e;
|
||||
+ if (af == AF_UNSPEC)
|
||||
+ e = gethostbyname (qname);
|
||||
+ else
|
||||
+ e = gethostbyname2 (qname, af);
|
||||
+
|
||||
+ if (addresses == 0)
|
||||
+ check_hostent (qname, e, "error: NO_RECOVERY\n");
|
||||
+ else
|
||||
+ check_hostent (qname, e, "error: HOST_NOT_FOUND\n");
|
||||
+
|
||||
+ free (qname);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+check (int af, bool do_search, int cnames, int addresses)
|
||||
+{
|
||||
+ char *qname = make_qname (do_search, cnames, addresses);
|
||||
+ char *fqdn = make_qname (false, cnames, addresses);
|
||||
+
|
||||
+ struct hostent *e;
|
||||
+ if (af == AF_UNSPEC)
|
||||
+ e = gethostbyname (qname);
|
||||
+ else
|
||||
+ e = gethostbyname2 (qname, af);
|
||||
+ if (e == NULL)
|
||||
+ FAIL_EXIT1 ("unexpected failure for %d, %d, %d", af, cnames, addresses);
|
||||
+
|
||||
+ if (af == AF_UNSPEC || af == AF_INET)
|
||||
+ {
|
||||
+ TEST_COMPARE (e->h_addrtype, AF_INET);
|
||||
+ TEST_COMPARE (e->h_length, 4);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ TEST_COMPARE (e->h_addrtype, AF_INET6);
|
||||
+ TEST_COMPARE (e->h_length, 16);
|
||||
+ }
|
||||
+
|
||||
+ for (int i = 0; i < addresses; ++i)
|
||||
+ {
|
||||
+ char ipv4[4] = {192, 0, 2, 1 + i};
|
||||
+ char ipv6[16] =
|
||||
+ { 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 + i };
|
||||
+ char *expected = e->h_addrtype == AF_INET ? ipv4 : ipv6;
|
||||
+ TEST_COMPARE_BLOB (e->h_addr_list[i], e->h_length,
|
||||
+ expected, e->h_length);
|
||||
+ }
|
||||
+ TEST_VERIFY (e->h_addr_list[addresses] == NULL);
|
||||
+
|
||||
+
|
||||
+ if (cnames == 0)
|
||||
+ {
|
||||
+ /* QNAME is fully qualified. */
|
||||
+ TEST_COMPARE_STRING (e->h_name, fqdn);
|
||||
+ TEST_VERIFY (e->h_aliases[0] == NULL);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Fully-qualified QNAME is demoted to an aliases. */
|
||||
+ TEST_COMPARE_STRING (e->h_aliases[0], fqdn);
|
||||
+
|
||||
+ for (int i = 1; i <= cnames; ++i)
|
||||
+ {
|
||||
+ char *expected = xasprintf ("%d.alias.example", i - 1);
|
||||
+ if (i == cnames)
|
||||
+ TEST_COMPARE_STRING (e->h_name, expected);
|
||||
+ else
|
||||
+ TEST_COMPARE_STRING (e->h_aliases[i], expected);
|
||||
+ free (expected);
|
||||
+ }
|
||||
+ TEST_VERIFY (e->h_aliases[cnames] == NULL);
|
||||
+ }
|
||||
+
|
||||
+ free (fqdn);
|
||||
+ free (qname);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct resolv_test *obj = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response,
|
||||
+ .search = { "example.net", "example.com" },
|
||||
+ });
|
||||
+
|
||||
+ static const int families[] = { AF_UNSPEC, AF_INET, AF_INET6 };
|
||||
+
|
||||
+ for (int do_insert_sig = 0; do_insert_sig < 2; ++do_insert_sig)
|
||||
+ {
|
||||
+ insert_sig = do_insert_sig;
|
||||
+
|
||||
+ /* If do_search is true, a bare host name (for example, a1-c1)
|
||||
+ is used. This exercises search path processing and FQDN
|
||||
+ qualification. */
|
||||
+ for (int do_search = 0; do_search < 2; ++do_search)
|
||||
+ for (const int *paf = families; paf != array_end (families); ++paf)
|
||||
+ {
|
||||
+ for (int cnames = 0; cnames <= 100; ++cnames)
|
||||
+ {
|
||||
+ check_cnames_failure (*paf, do_search, cnames, 0);
|
||||
+ /* Now with NXDOMAIN responses. */
|
||||
+ check_cnames_failure (*paf, do_search, cnames, 255);
|
||||
+ }
|
||||
+
|
||||
+ for (int cnames = 0; cnames <= 10; ++cnames)
|
||||
+ for (int addresses = 1; addresses <= 10; ++addresses)
|
||||
+ check (*paf, do_search, cnames, addresses);
|
||||
+
|
||||
+ /* The current implementation is limited to 47 aliases.
|
||||
+ Addresses do not have such a limit. */
|
||||
+ check (*paf, do_search, 47, 60);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ resolv_test_end (obj);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
@ -0,0 +1,58 @@
|
||||
commit 4d2e67d6e5c910114dbccd17d9b93f06552c0024
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add internal __res_binary_hnok function
|
||||
|
||||
During package parsing, only the binary representation is available,
|
||||
and it is convenient to check that directly for conformance with host
|
||||
name requirements.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit c79327bf00a4be6d60259227acc78ef80ead3622)
|
||||
|
||||
diff --git a/include/resolv.h b/include/resolv.h
|
||||
index 3590b6f496d47710..4dbbac3800b7ef30 100644
|
||||
--- a/include/resolv.h
|
||||
+++ b/include/resolv.h
|
||||
@@ -70,5 +70,8 @@ libc_hidden_proto (__libc_res_nameinquery)
|
||||
extern __typeof (__res_queriesmatch) __libc_res_queriesmatch;
|
||||
libc_hidden_proto (__libc_res_queriesmatch)
|
||||
|
||||
+/* Variant of res_hnok which operates on binary (but uncompressed) names. */
|
||||
+bool __res_binary_hnok (const unsigned char *dn) attribute_hidden;
|
||||
+
|
||||
# endif /* _RESOLV_H_ && !_ISOMAC */
|
||||
#endif
|
||||
diff --git a/resolv/res-name-checking.c b/resolv/res-name-checking.c
|
||||
index 2c603494fa3ca992..513ddb5f6b12ccb0 100644
|
||||
--- a/resolv/res-name-checking.c
|
||||
+++ b/resolv/res-name-checking.c
|
||||
@@ -138,6 +138,12 @@ binary_leading_dash (const unsigned char *dn)
|
||||
return dn[0] > 0 && dn[1] == '-';
|
||||
}
|
||||
|
||||
+bool
|
||||
+__res_binary_hnok (const unsigned char *dn)
|
||||
+{
|
||||
+ return !binary_leading_dash (dn) && binary_hnok (dn);
|
||||
+}
|
||||
+
|
||||
/* Return 1 if res_hnok is a valid host name. Labels must only
|
||||
contain [0-9a-zA-Z_-] characters, and the name must not start with
|
||||
a '-'. The latter is to avoid confusion with program options. */
|
||||
@@ -145,11 +151,9 @@ int
|
||||
___res_hnok (const char *dn)
|
||||
{
|
||||
unsigned char buf[NS_MAXCDNAME];
|
||||
- if (!printable_string (dn)
|
||||
- || __ns_name_pton (dn, buf, sizeof (buf)) < 0
|
||||
- || binary_leading_dash (buf))
|
||||
- return 0;
|
||||
- return binary_hnok (buf);
|
||||
+ return (printable_string (dn)
|
||||
+ && __ns_name_pton (dn, buf, sizeof (buf)) >= 0
|
||||
+ && __res_binary_hnok (buf));
|
||||
}
|
||||
versioned_symbol (libc, ___res_hnok, res_hnok, GLIBC_2_34);
|
||||
versioned_symbol (libc, ___res_hnok, __libc_res_hnok, GLIBC_PRIVATE);
|
@ -0,0 +1,182 @@
|
||||
commit bb8adbba4f5d9237a144786ba8e504039beff161
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add the __ns_samebinaryname function
|
||||
|
||||
During packet parsing, only the binary name is available. If the name
|
||||
equality check is performed before conversion to text, we can sometimes
|
||||
skip the last step.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 394085a34d25a51513019a4dc411acd3527fbd33)
|
||||
|
||||
diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h
|
||||
index 53f1dbc7c3f659e9..bb1dede187cf1500 100644
|
||||
--- a/include/arpa/nameser.h
|
||||
+++ b/include/arpa/nameser.h
|
||||
@@ -55,6 +55,12 @@ int __ns_name_ntop (const unsigned char *, char *, size_t) __THROW;
|
||||
int __ns_name_unpack (const unsigned char *, const unsigned char *,
|
||||
const unsigned char *, unsigned char *, size_t) __THROW;
|
||||
|
||||
+/* Like ns_samename, but for uncompressed binary names. Return true
|
||||
+ if the two arguments compare are equal as case-insensitive domain
|
||||
+ names. */
|
||||
+_Bool __ns_samebinaryname (const unsigned char *, const unsigned char *)
|
||||
+ attribute_hidden;
|
||||
+
|
||||
#define ns_msg_getflag(handle, flag) \
|
||||
(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift)
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 567f4c2dcf5749df..0b4fa30716af3b8a 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -46,6 +46,7 @@ routines := \
|
||||
ns_name_skip \
|
||||
ns_name_uncompress \
|
||||
ns_name_unpack \
|
||||
+ ns_samebinaryname \
|
||||
ns_samename \
|
||||
nsap_addr \
|
||||
nss_dns_functions \
|
||||
@@ -107,6 +108,10 @@ tests += \
|
||||
tests-internal += tst-resolv-txnid-collision
|
||||
tests-static += tst-resolv-txnid-collision
|
||||
|
||||
+# Likewise for __ns_samebinaryname.
|
||||
+tests-internal += tst-ns_samebinaryname
|
||||
+tests-static += tst-ns_samebinaryname
|
||||
+
|
||||
# These tests need libdl.
|
||||
ifeq (yes,$(build-shared))
|
||||
tests += \
|
||||
diff --git a/resolv/ns_samebinaryname.c b/resolv/ns_samebinaryname.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..9a47d8e97a84c759
|
||||
--- /dev/null
|
||||
+++ b/resolv/ns_samebinaryname.c
|
||||
@@ -0,0 +1,55 @@
|
||||
+/* Compare two binary domain names for quality.
|
||||
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <arpa/nameser.h>
|
||||
+#include <stdbool.h>
|
||||
+
|
||||
+/* Convert ASCII letters to upper case. */
|
||||
+static inline int
|
||||
+ascii_toupper (unsigned char ch)
|
||||
+{
|
||||
+ if (ch >= 'a' && ch <= 'z')
|
||||
+ return ch - 'a' + 'A';
|
||||
+ else
|
||||
+ return ch;
|
||||
+}
|
||||
+
|
||||
+bool
|
||||
+__ns_samebinaryname (const unsigned char *a, const unsigned char *b)
|
||||
+{
|
||||
+ while (*a != 0 && *b != 0)
|
||||
+ {
|
||||
+ if (*a != *b)
|
||||
+ /* Different label length. */
|
||||
+ return false;
|
||||
+ int labellen = *a;
|
||||
+ ++a;
|
||||
+ ++b;
|
||||
+ for (int i = 0; i < labellen; ++i)
|
||||
+ {
|
||||
+ if (*a != *b && ascii_toupper (*a) != ascii_toupper (*b))
|
||||
+ /* Different character in label. */
|
||||
+ return false;
|
||||
+ ++a;
|
||||
+ ++b;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Match if both names are at the root label. */
|
||||
+ return *a == 0 && *b == 0;
|
||||
+}
|
||||
diff --git a/resolv/tst-ns_samebinaryname.c b/resolv/tst-ns_samebinaryname.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..b06ac610b4cde8be
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-ns_samebinaryname.c
|
||||
@@ -0,0 +1,62 @@
|
||||
+/* Test the __ns_samebinaryname function.
|
||||
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <arpa/nameser.h>
|
||||
+#include <array_length.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdio.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+/* First character denotes the comparison group: All names with the
|
||||
+ same first character are expected to compare equal. */
|
||||
+static const char *const cases[] =
|
||||
+ {
|
||||
+ " ",
|
||||
+ "1\001a", "1\001A",
|
||||
+ "2\002ab", "2\002aB", "2\002Ab", "2\002AB",
|
||||
+ "3\001a\002ab", "3\001A\002ab",
|
||||
+ "w\003www\007example\003com", "w\003Www\007Example\003Com",
|
||||
+ "w\003WWW\007EXAMPLE\003COM",
|
||||
+ "W\003WWW", "W\003www",
|
||||
+ };
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ for (int i = 0; i < array_length (cases); ++i)
|
||||
+ for (int j = 0; j < array_length (cases); ++j)
|
||||
+ {
|
||||
+ unsigned char *a = (unsigned char *) &cases[i][1];
|
||||
+ unsigned char *b = (unsigned char *) &cases[j][1];
|
||||
+ bool actual = __ns_samebinaryname (a, b);
|
||||
+ bool expected = cases[i][0] == cases[j][0];
|
||||
+ if (actual != expected)
|
||||
+ {
|
||||
+ char a1[NS_MAXDNAME];
|
||||
+ TEST_VERIFY (ns_name_ntop (a, a1, sizeof (a1)) > 0);
|
||||
+ char b1[NS_MAXDNAME];
|
||||
+ TEST_VERIFY (ns_name_ntop (b, b1, sizeof (b1)) > 0);
|
||||
+ printf ("error: \"%s\" \"%s\": expected %s\n",
|
||||
+ a1, b1, expected ? "equal" : "unqueal");
|
||||
+ support_record_failure ();
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
@ -0,0 +1,272 @@
|
||||
commit c288e032ae107c48679ef3c46fb84af6de0a6baf
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add internal __ns_name_length_uncompressed function
|
||||
|
||||
This function is useful for checking that the question name is
|
||||
uncompressed (as it should be).
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 78b1a4f0e49064e5dfb686c7cd87bd4df2640b29)
|
||||
|
||||
diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h
|
||||
index bb1dede187cf1500..6e4808f00d60caf9 100644
|
||||
--- a/include/arpa/nameser.h
|
||||
+++ b/include/arpa/nameser.h
|
||||
@@ -95,5 +95,13 @@ libc_hidden_proto (__ns_name_unpack)
|
||||
extern __typeof (ns_samename) __libc_ns_samename;
|
||||
libc_hidden_proto (__libc_ns_samename)
|
||||
|
||||
+/* Packet parser helper functions. */
|
||||
+
|
||||
+/* Verify that P points to an uncompressed domain name in wire format.
|
||||
+ On success, return the length of the encoded name, including the
|
||||
+ terminating null byte. On failure, return -1 and set errno. EOM
|
||||
+ must point one past the last byte in the packet. */
|
||||
+int __ns_name_length_uncompressed (const unsigned char *p,
|
||||
+ const unsigned char *eom) attribute_hidden;
|
||||
# endif /* !_ISOMAC */
|
||||
#endif
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 0b4fa30716af3b8a..308f18622a04965a 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -40,6 +40,7 @@ routines := \
|
||||
inet_pton \
|
||||
ns_makecanon \
|
||||
ns_name_compress \
|
||||
+ ns_name_length_uncompressed \
|
||||
ns_name_ntop \
|
||||
ns_name_pack \
|
||||
ns_name_pton \
|
||||
@@ -112,6 +113,10 @@ tests-static += tst-resolv-txnid-collision
|
||||
tests-internal += tst-ns_samebinaryname
|
||||
tests-static += tst-ns_samebinaryname
|
||||
|
||||
+# Likewise for __ns_name_length_uncompressed.
|
||||
+tests-internal += tst-ns_name_length_uncompressed
|
||||
+tests-static += tst-ns_name_length_uncompressed
|
||||
+
|
||||
# These tests need libdl.
|
||||
ifeq (yes,$(build-shared))
|
||||
tests += \
|
||||
diff --git a/resolv/ns_name_length_uncompressed.c b/resolv/ns_name_length_uncompressed.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..51296b47efbf1849
|
||||
--- /dev/null
|
||||
+++ b/resolv/ns_name_length_uncompressed.c
|
||||
@@ -0,0 +1,72 @@
|
||||
+/* Skip over an uncompressed name in wire format.
|
||||
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <arpa/nameser.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdbool.h>
|
||||
+
|
||||
+int
|
||||
+__ns_name_length_uncompressed (const unsigned char *p,
|
||||
+ const unsigned char *eom)
|
||||
+{
|
||||
+ const unsigned char *start = p;
|
||||
+
|
||||
+ while (true)
|
||||
+ {
|
||||
+ if (p == eom)
|
||||
+ {
|
||||
+ /* Truncated packet: no room for label length. */
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ unsigned char b = *p;
|
||||
+ ++p;
|
||||
+ if (b == 0)
|
||||
+ {
|
||||
+ /* Root label. */
|
||||
+ size_t length = p - start;
|
||||
+ if (length > NS_MAXCDNAME)
|
||||
+ {
|
||||
+ /* Domain name too long. */
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ return length;
|
||||
+ }
|
||||
+
|
||||
+ if (b <= 63)
|
||||
+ {
|
||||
+ /* Regular label. */
|
||||
+ if (b <= eom - p)
|
||||
+ p += b;
|
||||
+ else
|
||||
+ {
|
||||
+ /* Truncated packet: label incomplete. */
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Compression reference or corrupted label length. */
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/resolv/tst-ns_name_length_uncompressed.c b/resolv/tst-ns_name_length_uncompressed.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..c4a2904db75d1221
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-ns_name_length_uncompressed.c
|
||||
@@ -0,0 +1,135 @@
|
||||
+/* Test __ns_name_length_uncompressed.
|
||||
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <arpa/nameser.h>
|
||||
+#include <array_length.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdio.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/next_to_fault.h>
|
||||
+
|
||||
+/* Reference implementation based on other building blocks. */
|
||||
+static int
|
||||
+reference_length (const unsigned char *p, const unsigned char *eom)
|
||||
+{
|
||||
+ unsigned char buf[NS_MAXCDNAME];
|
||||
+ int n = __ns_name_unpack (p, eom, p, buf, sizeof (buf));
|
||||
+ if (n < 0)
|
||||
+ return n;
|
||||
+ const unsigned char *q = buf;
|
||||
+ if (__ns_name_skip (&q, array_end (buf)) < 0)
|
||||
+ return -1;
|
||||
+ if (q - buf != n)
|
||||
+ /* Compressed name. */
|
||||
+ return -1;
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ {
|
||||
+ unsigned char buf[] = { 3, 'w', 'w', 'w', 0, 0, 0 };
|
||||
+ TEST_COMPARE (reference_length (buf, array_end (buf)), sizeof (buf) - 2);
|
||||
+ TEST_COMPARE (__ns_name_length_uncompressed (buf, array_end (buf)),
|
||||
+ sizeof (buf) - 2);
|
||||
+ TEST_COMPARE (reference_length (array_end (buf) - 1, array_end (buf)), 1);
|
||||
+ TEST_COMPARE (__ns_name_length_uncompressed (array_end (buf) - 1,
|
||||
+ array_end (buf)), 1);
|
||||
+ buf[4] = 0xc0; /* Forward compression reference. */
|
||||
+ buf[5] = 0x06;
|
||||
+ TEST_COMPARE (reference_length (buf, array_end (buf)), -1);
|
||||
+ TEST_COMPARE (__ns_name_length_uncompressed (buf, array_end (buf)), -1);
|
||||
+ }
|
||||
+
|
||||
+ struct support_next_to_fault ntf = support_next_to_fault_allocate (300);
|
||||
+
|
||||
+ /* Buffer region with all possible bytes at start and end. */
|
||||
+ for (int length = 1; length <= 300; ++length)
|
||||
+ {
|
||||
+ unsigned char *end = (unsigned char *) ntf.buffer + ntf.length;
|
||||
+ unsigned char *start = end - length;
|
||||
+ memset (start, 'X', length);
|
||||
+ for (int first = 0; first <= 255; ++first)
|
||||
+ {
|
||||
+ *start = first;
|
||||
+ for (int last = 0; last <= 255; ++last)
|
||||
+ {
|
||||
+ start[length - 1] = last;
|
||||
+ TEST_COMPARE (reference_length (start, end),
|
||||
+ __ns_name_length_uncompressed (start, end));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Poor man's fuzz testing: patch two bytes. */
|
||||
+ {
|
||||
+ unsigned char ref[] =
|
||||
+ {
|
||||
+ 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'n', 'e', 't', 0, 0, 0
|
||||
+ };
|
||||
+ TEST_COMPARE (reference_length (ref, array_end (ref)), 13);
|
||||
+ TEST_COMPARE (__ns_name_length_uncompressed (ref, array_end (ref)), 13);
|
||||
+
|
||||
+ int good = 0;
|
||||
+ int bad = 0;
|
||||
+ for (int length = 1; length <= sizeof (ref); ++length)
|
||||
+ {
|
||||
+ unsigned char *end = (unsigned char *) ntf.buffer + ntf.length;
|
||||
+ unsigned char *start = end - length;
|
||||
+ memcpy (start, ref, length);
|
||||
+
|
||||
+ for (int patch1_pos = 0; patch1_pos < length; ++patch1_pos)
|
||||
+ {
|
||||
+ for (int patch1_value = 0; patch1_value <= 255; ++patch1_value)
|
||||
+ {
|
||||
+ start[patch1_pos] = patch1_value;
|
||||
+ for (int patch2_pos = 0; patch2_pos < length; ++patch2_pos)
|
||||
+ {
|
||||
+ for (int patch2_value = 0; patch2_value <= 255;
|
||||
+ ++patch2_value)
|
||||
+ {
|
||||
+ start[patch2_pos] = patch2_value;
|
||||
+ int expected = reference_length (start, end);
|
||||
+ errno = EINVAL;
|
||||
+ int actual
|
||||
+ = __ns_name_length_uncompressed (start, end);
|
||||
+ if (actual > 0)
|
||||
+ ++good;
|
||||
+ else
|
||||
+ {
|
||||
+ TEST_COMPARE (errno, EMSGSIZE);
|
||||
+ ++bad;
|
||||
+ }
|
||||
+ TEST_COMPARE (expected, actual);
|
||||
+ }
|
||||
+ start[patch2_pos] = ref[patch2_pos];
|
||||
+ }
|
||||
+ }
|
||||
+ start[patch1_pos] = ref[patch1_pos];
|
||||
+ }
|
||||
+ }
|
||||
+ printf ("info: patched inputs with success: %d\n", good);
|
||||
+ printf ("info: patched inputs with failure: %d\n", bad);
|
||||
+ }
|
||||
+
|
||||
+ support_next_to_fault_free (&ntf);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
@ -0,0 +1,532 @@
|
||||
commit e7c03f47651bd451ebf2c3c65899491d0bf7167e
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add DNS packet parsing helpers geared towards wire format
|
||||
|
||||
The public parser functions around the ns_rr record type produce
|
||||
textual domain names, but usually, this is not what we need while
|
||||
parsing DNS packets within glibc. This commit adds two new helper
|
||||
functions, __ns_rr_cursor_init and __ns_rr_cursor_next, for writing
|
||||
packet parsers, and struct ns_rr_cursor, struct ns_rr_wire as
|
||||
supporting types.
|
||||
|
||||
In theory, it is possible to avoid copying the owner name
|
||||
into the rname field in __ns_rr_cursor_next, but this would need
|
||||
more functions that work on compressed names.
|
||||
|
||||
Eventually, __res_context_send could be enhanced to preserve the
|
||||
result of the packet parsing that is necessary for matching the
|
||||
incoming UDP packets, so that this works does not have to be done
|
||||
twice.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 857c890d9b42c50c8a94b76d47d4a61ab6d2f49c)
|
||||
|
||||
diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h
|
||||
index 6e4808f00d60caf9..c27e7886b7891997 100644
|
||||
--- a/include/arpa/nameser.h
|
||||
+++ b/include/arpa/nameser.h
|
||||
@@ -103,5 +103,97 @@ libc_hidden_proto (__libc_ns_samename)
|
||||
must point one past the last byte in the packet. */
|
||||
int __ns_name_length_uncompressed (const unsigned char *p,
|
||||
const unsigned char *eom) attribute_hidden;
|
||||
+
|
||||
+/* Iterator over the resource records in a DNS packet. */
|
||||
+struct ns_rr_cursor
|
||||
+{
|
||||
+ /* These members are not changed after initialization. */
|
||||
+ const unsigned char *begin; /* First byte of packet. */
|
||||
+ const unsigned char *end; /* One past the last byte of the packet. */
|
||||
+ const unsigned char *first_rr; /* First resource record (or packet end). */
|
||||
+
|
||||
+ /* Advanced towards the end while reading the packet. */
|
||||
+ const unsigned char *current;
|
||||
+};
|
||||
+
|
||||
+/* Returns the RCODE field from the DNS header. */
|
||||
+static inline int
|
||||
+ns_rr_cursor_rcode (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ return c->begin[3] & 0x0f; /* Lower 4 bits at offset 3. */
|
||||
+}
|
||||
+
|
||||
+/* Returns the length of the answer section according to the DNS header. */
|
||||
+static inline int
|
||||
+ns_rr_cursor_ancount (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ return c->begin[6] * 256 + c->begin[7]; /* 16 bits at offset 6. */
|
||||
+}
|
||||
+
|
||||
+/* Returns the length of the authority (name server) section according
|
||||
+ to the DNS header. */
|
||||
+static inline int
|
||||
+ns_rr_cursor_nscount (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ return c->begin[8] * 256 + c->begin[9]; /* 16 bits at offset 8. */
|
||||
+}
|
||||
+
|
||||
+/* Returns the length of the additional data section according to the
|
||||
+ DNS header. */
|
||||
+static inline int
|
||||
+ns_rr_cursor_adcount (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ return c->begin[10] * 256 + c->begin[11]; /* 16 bits at offset 10. */
|
||||
+}
|
||||
+
|
||||
+/* Returns a pointer to the uncompressed question name in wire
|
||||
+ format. */
|
||||
+static inline const unsigned char *
|
||||
+ns_rr_cursor_qname (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ return c->begin + 12; /* QNAME starts right after the header. */
|
||||
+}
|
||||
+
|
||||
+/* Returns the question type of the first and only question. */
|
||||
+static inline const int
|
||||
+ns_rr_cursor_qtype (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ /* 16 bits 4 bytes back from the first RR header start. */
|
||||
+ return c->first_rr[-4] * 256 + c->first_rr[-3];
|
||||
+}
|
||||
+
|
||||
+/* Returns the clss of the first and only question (usally C_IN). */
|
||||
+static inline const int
|
||||
+ns_rr_cursor_qclass (const struct ns_rr_cursor *c)
|
||||
+{
|
||||
+ /* 16 bits 2 bytes back from the first RR header start. */
|
||||
+ return c->first_rr[-2] * 256 + c->first_rr[-1];
|
||||
+}
|
||||
+
|
||||
+/* Initializes *C to cover the packet [BUF, BUF+LEN). Returns false
|
||||
+ if LEN is less than sizeof (*HD), if the packet does not contain a
|
||||
+ full (uncompressed) question, or if the question count is not 1. */
|
||||
+_Bool __ns_rr_cursor_init (struct ns_rr_cursor *c,
|
||||
+ const unsigned char *buf, size_t len)
|
||||
+ attribute_hidden;
|
||||
+
|
||||
+/* Like ns_rr, but the record owner name is not decoded into text format. */
|
||||
+struct ns_rr_wire
|
||||
+{
|
||||
+ unsigned char rname[NS_MAXCDNAME]; /* Owner name of the record. */
|
||||
+ uint16_t rtype; /* Resource record type (T_*). */
|
||||
+ uint16_t rclass; /* Resource record class (C_*). */
|
||||
+ uint32_t ttl; /* Time-to-live field. */
|
||||
+ const unsigned char *rdata; /* Start of resource record data. */
|
||||
+ uint16_t rdlength; /* Length of the data at rdata, in bytes. */
|
||||
+};
|
||||
+
|
||||
+/* Attempts to parse the record at C into *RR. On success, return
|
||||
+ true, and C is advanced past the record, and RR->rdata points to
|
||||
+ the record data. On failure, errno is set to EMSGSIZE, and false
|
||||
+ is returned. */
|
||||
+_Bool __ns_rr_cursor_next (struct ns_rr_cursor *c, struct ns_rr_wire *rr)
|
||||
+ attribute_hidden;
|
||||
+
|
||||
# endif /* !_ISOMAC */
|
||||
#endif
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index 308f18622a04965a..fded244d61068060 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -47,6 +47,8 @@ routines := \
|
||||
ns_name_skip \
|
||||
ns_name_uncompress \
|
||||
ns_name_unpack \
|
||||
+ ns_rr_cursor_init \
|
||||
+ ns_rr_cursor_next \
|
||||
ns_samebinaryname \
|
||||
ns_samename \
|
||||
nsap_addr \
|
||||
@@ -117,6 +119,10 @@ tests-static += tst-ns_samebinaryname
|
||||
tests-internal += tst-ns_name_length_uncompressed
|
||||
tests-static += tst-ns_name_length_uncompressed
|
||||
|
||||
+# Likewise for struct ns_rr_cursor and its functions.
|
||||
+tests-internal += tst-ns_rr_cursor
|
||||
+tests-static += tst-ns_rr_cursor
|
||||
+
|
||||
# These tests need libdl.
|
||||
ifeq (yes,$(build-shared))
|
||||
tests += \
|
||||
diff --git a/resolv/ns_rr_cursor_init.c b/resolv/ns_rr_cursor_init.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..6ee80b30e927ecb7
|
||||
--- /dev/null
|
||||
+++ b/resolv/ns_rr_cursor_init.c
|
||||
@@ -0,0 +1,62 @@
|
||||
+/* Initialize a simple DNS packet parser.
|
||||
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <arpa/nameser.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+bool
|
||||
+__ns_rr_cursor_init (struct ns_rr_cursor *c,
|
||||
+ const unsigned char *buf, size_t len)
|
||||
+{
|
||||
+ c->begin = buf;
|
||||
+ c->end = buf + len;
|
||||
+
|
||||
+ /* Check for header size and 16-bit question count value (it must be 1). */
|
||||
+ if (len < 12 || buf[4] != 0 || buf[5] != 1)
|
||||
+ {
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ c->current = c->end;
|
||||
+ return false;
|
||||
+ }
|
||||
+ c->current = buf + 12;
|
||||
+
|
||||
+ int consumed = __ns_name_length_uncompressed (c->current, c->end);
|
||||
+ if (consumed < 0)
|
||||
+ {
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ c->current = c->end;
|
||||
+ c->first_rr = NULL;
|
||||
+ return false;
|
||||
+ }
|
||||
+ c->current += consumed;
|
||||
+
|
||||
+ /* Ensure there is room for question type and class. */
|
||||
+ if (c->end - c->current < 4)
|
||||
+ {
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ c->current = c->end;
|
||||
+ c->first_rr = NULL;
|
||||
+ return false;
|
||||
+ }
|
||||
+ c->current += 4;
|
||||
+ c->first_rr = c->current;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
diff --git a/resolv/ns_rr_cursor_next.c b/resolv/ns_rr_cursor_next.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..33652fc5da322d69
|
||||
--- /dev/null
|
||||
+++ b/resolv/ns_rr_cursor_next.c
|
||||
@@ -0,0 +1,74 @@
|
||||
+/* Simple DNS record parser without textual name decoding.
|
||||
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <arpa/nameser.h>
|
||||
+#include <errno.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <string.h>
|
||||
+
|
||||
+bool
|
||||
+__ns_rr_cursor_next (struct ns_rr_cursor *c, struct ns_rr_wire *rr)
|
||||
+{
|
||||
+ rr->rdata = NULL;
|
||||
+
|
||||
+ /* Extract the record owner name. */
|
||||
+ int consumed = __ns_name_unpack (c->begin, c->end, c->current,
|
||||
+ rr->rname, sizeof (rr->rname));
|
||||
+ if (consumed < 0)
|
||||
+ {
|
||||
+ memset (rr, 0, sizeof (*rr));
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return false;
|
||||
+ }
|
||||
+ c->current += consumed;
|
||||
+
|
||||
+ /* Extract the metadata. */
|
||||
+ struct
|
||||
+ {
|
||||
+ uint16_t rtype;
|
||||
+ uint16_t rclass;
|
||||
+ uint32_t ttl;
|
||||
+ uint16_t rdlength;
|
||||
+ } __attribute__ ((packed)) metadata;
|
||||
+ _Static_assert (sizeof (metadata) == 10, "sizeof metadata");
|
||||
+ if (c->end - c->current < sizeof (metadata))
|
||||
+ {
|
||||
+ memset (rr, 0, sizeof (*rr));
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return false;
|
||||
+ }
|
||||
+ memcpy (&metadata, c->current, sizeof (metadata));
|
||||
+ c->current += sizeof (metadata);
|
||||
+ /* Endianess conversion. */
|
||||
+ rr->rtype = ntohs (metadata.rtype);
|
||||
+ rr->rclass = ntohs (metadata.rclass);
|
||||
+ rr->ttl = ntohl (metadata.ttl);
|
||||
+ rr->rdlength = ntohs (metadata.rdlength);
|
||||
+
|
||||
+ /* Extract record data. */
|
||||
+ if (c->end - c->current < rr->rdlength)
|
||||
+ {
|
||||
+ memset (rr, 0, sizeof (*rr));
|
||||
+ __set_errno (EMSGSIZE);
|
||||
+ return false;
|
||||
+ }
|
||||
+ rr->rdata = c->current;
|
||||
+ c->current += rr->rdlength;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
diff --git a/resolv/tst-ns_rr_cursor.c b/resolv/tst-ns_rr_cursor.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..c3c09089053d0c40
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-ns_rr_cursor.c
|
||||
@@ -0,0 +1,227 @@
|
||||
+/* Tests for resource record parsing.
|
||||
+ Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <arpa/nameser.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/next_to_fault.h>
|
||||
+
|
||||
+/* Reference packet for packet parsing. */
|
||||
+static const unsigned char valid_packet[] =
|
||||
+ { 0x11, 0x12, 0x13, 0x14,
|
||||
+ 0x00, 0x01, /* Question count. */
|
||||
+ 0x00, 0x02, /* Answer count. */
|
||||
+ 0x21, 0x22, 0x23, 0x24, /* Other counts (not actually in packet). */
|
||||
+ 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0,
|
||||
+ 0x00, 0x1c, /* Question type: AAAA. */
|
||||
+ 0x00, 0x01, /* Question class: IN. */
|
||||
+ 0xc0, 0x0c, /* Compression reference to QNAME. */
|
||||
+ 0x00, 0x1c, /* Record type: AAAA. */
|
||||
+ 0x00, 0x01, /* Record class: IN. */
|
||||
+ 0x12, 0x34, 0x56, 0x78, /* Record TTL. */
|
||||
+ 0x00, 0x10, /* Record data length (16 bytes). */
|
||||
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* IPv6 address. */
|
||||
+ 0xc0, 0x0c, /* Compression reference to QNAME. */
|
||||
+ 0x00, 0x1c, /* Record type: AAAA. */
|
||||
+ 0x00, 0x01, /* Record class: IN. */
|
||||
+ 0x11, 0x33, 0x55, 0x77, /* Record TTL. */
|
||||
+ 0x00, 0x10, /* Record data length (16 bytes). */
|
||||
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* IPv6 address. */
|
||||
+ };
|
||||
+
|
||||
+/* Special offsets in valid_packet. */
|
||||
+enum
|
||||
+ {
|
||||
+ offset_of_first_record = 29,
|
||||
+ offset_of_second_record = 57,
|
||||
+ };
|
||||
+
|
||||
+/* Check that parsing valid_packet succeeds. */
|
||||
+static void
|
||||
+test_valid (void)
|
||||
+{
|
||||
+ struct ns_rr_cursor c;
|
||||
+ TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, valid_packet,
|
||||
+ sizeof (valid_packet)));
|
||||
+ TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
|
||||
+ TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
|
||||
+ TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
|
||||
+ TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
|
||||
+ TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
|
||||
+ TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
|
||||
+ TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
|
||||
+ TEST_COMPARE (c.current - valid_packet, offset_of_first_record);
|
||||
+
|
||||
+ struct ns_rr_wire r;
|
||||
+ TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
|
||||
+ TEST_COMPARE (r.rtype, T_AAAA);
|
||||
+ TEST_COMPARE (r.rclass, C_IN);
|
||||
+ TEST_COMPARE (r.ttl, 0x12345678);
|
||||
+ TEST_COMPARE_BLOB (r.rdata, r.rdlength,
|
||||
+ "\x90\x91\x92\x93\x94\x95\x96\x97"
|
||||
+ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16);
|
||||
+ TEST_COMPARE (c.current - valid_packet, offset_of_second_record);
|
||||
+ TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
|
||||
+ TEST_COMPARE (r.rtype, T_AAAA);
|
||||
+ TEST_COMPARE (r.rclass, C_IN);
|
||||
+ TEST_COMPARE (r.ttl, 0x11335577);
|
||||
+ TEST_COMPARE_BLOB (r.rdata, r.rdlength,
|
||||
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
|
||||
+ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf", 16);
|
||||
+ TEST_VERIFY (c.current == c.end);
|
||||
+}
|
||||
+
|
||||
+/* Check that trying to parse a packet with a compressed QNAME fails. */
|
||||
+static void
|
||||
+test_compressed_qname (void)
|
||||
+{
|
||||
+ static const unsigned char packet[] =
|
||||
+ { 0x11, 0x12, 0x13, 0x14,
|
||||
+ 0x00, 0x01, /* Question count. */
|
||||
+ 0x00, 0x00, /* Answer count. */
|
||||
+ 0x00, 0x00, 0x00, 0x00, /* Other counts. */
|
||||
+ 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
|
||||
+ 0x00, 0x01, /* Question type: A. */
|
||||
+ 0x00, 0x01, /* Question class: IN. */
|
||||
+ };
|
||||
+
|
||||
+ struct ns_rr_cursor c;
|
||||
+ TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet)));
|
||||
+}
|
||||
+
|
||||
+/* Check that trying to parse a packet with two questions fails. */
|
||||
+static void
|
||||
+test_two_questions (void)
|
||||
+{
|
||||
+ static const unsigned char packet[] =
|
||||
+ { 0x11, 0x12, 0x13, 0x14,
|
||||
+ 0x00, 0x02, /* Question count. */
|
||||
+ 0x00, 0x00, /* Answer count. */
|
||||
+ 0x00, 0x00, 0x00, 0x00, /* Other counts. */
|
||||
+ 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
|
||||
+ 0x00, 0x01, /* Question type: A. */
|
||||
+ 0x00, 0x01, /* Question class: IN. */
|
||||
+ 3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
|
||||
+ 0x00, 0x1c, /* Question type: AAAA. */
|
||||
+ 0x00, 0x01, /* Question class: IN. */
|
||||
+ };
|
||||
+
|
||||
+ struct ns_rr_cursor c;
|
||||
+ TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet)));
|
||||
+}
|
||||
+
|
||||
+/* Used to check that parsing truncated packets does not over-read. */
|
||||
+static struct support_next_to_fault ntf;
|
||||
+
|
||||
+/* Truncated packet in the second resource record. */
|
||||
+static void
|
||||
+test_truncated_one_rr (size_t length)
|
||||
+{
|
||||
+ unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
|
||||
+ unsigned char *start = end - length;
|
||||
+
|
||||
+ /* Produce the truncated packet. */
|
||||
+ memcpy (start, valid_packet, length);
|
||||
+
|
||||
+ struct ns_rr_cursor c;
|
||||
+ TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, start, length));
|
||||
+ TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
|
||||
+ TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
|
||||
+ TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
|
||||
+ TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
|
||||
+ TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
|
||||
+ TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
|
||||
+ TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
|
||||
+ TEST_COMPARE (c.current - start, offset_of_first_record);
|
||||
+
|
||||
+ struct ns_rr_wire r;
|
||||
+ TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
|
||||
+ TEST_COMPARE (r.rtype, T_AAAA);
|
||||
+ TEST_COMPARE (r.rclass, C_IN);
|
||||
+ TEST_COMPARE (r.ttl, 0x12345678);
|
||||
+ TEST_COMPARE_BLOB (r.rdata, r.rdlength,
|
||||
+ "\x90\x91\x92\x93\x94\x95\x96\x97"
|
||||
+ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16);
|
||||
+ TEST_COMPARE (c.current - start, offset_of_second_record);
|
||||
+ TEST_VERIFY (!__ns_rr_cursor_next (&c, &r));
|
||||
+}
|
||||
+
|
||||
+/* Truncated packet in the first resource record. */
|
||||
+static void
|
||||
+test_truncated_no_rr (size_t length)
|
||||
+{
|
||||
+ unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
|
||||
+ unsigned char *start = end - length;
|
||||
+
|
||||
+ /* Produce the truncated packet. */
|
||||
+ memcpy (start, valid_packet, length);
|
||||
+
|
||||
+ struct ns_rr_cursor c;
|
||||
+ TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, start, length));
|
||||
+ TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
|
||||
+ TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
|
||||
+ TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
|
||||
+ TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
|
||||
+ TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
|
||||
+ TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
|
||||
+ TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
|
||||
+ TEST_COMPARE (c.current - start, offset_of_first_record);
|
||||
+
|
||||
+ struct ns_rr_wire r;
|
||||
+ TEST_VERIFY (!__ns_rr_cursor_next (&c, &r));
|
||||
+}
|
||||
+
|
||||
+/* Truncated packet before first resource record. */
|
||||
+static void
|
||||
+test_truncated_before_rr (size_t length)
|
||||
+{
|
||||
+ unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
|
||||
+ unsigned char *start = end - length;
|
||||
+
|
||||
+ /* Produce the truncated packet. */
|
||||
+ memcpy (start, valid_packet, length);
|
||||
+
|
||||
+ struct ns_rr_cursor c;
|
||||
+ TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, start, length));
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ ntf = support_next_to_fault_allocate (sizeof (valid_packet));
|
||||
+
|
||||
+ test_valid ();
|
||||
+ test_compressed_qname ();
|
||||
+ test_two_questions ();
|
||||
+
|
||||
+ for (int length = offset_of_second_record; length < sizeof (valid_packet);
|
||||
+ ++length)
|
||||
+ test_truncated_one_rr (length);
|
||||
+ for (int length = offset_of_first_record; length < offset_of_second_record;
|
||||
+ ++length)
|
||||
+ test_truncated_no_rr (length);
|
||||
+ for (int length = 0; length < offset_of_first_record; ++length)
|
||||
+ test_truncated_before_rr (length);
|
||||
+
|
||||
+ support_next_to_fault_free (&ntf);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
@ -0,0 +1,447 @@
|
||||
commit d9c979abf9307ef3e27dbe65317430977bb322c7
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
nss_dns: Split getanswer_ptr from getanswer_r
|
||||
|
||||
And expand the use of name_ok and qtype in getanswer_ptr (the
|
||||
former also in getanswer_r).
|
||||
|
||||
After further cleanups, not much code will be shared between the
|
||||
two functions.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 0dcc43e9981005540bf39dc7bf33fbab62cf9e84)
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 6e83fca1c5b1f98c..a6bf73a091968358 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -117,6 +117,11 @@ static enum nss_status getanswer_r (struct resolv_context *ctx,
|
||||
struct hostent *result, char *buffer,
|
||||
size_t buflen, int *errnop, int *h_errnop,
|
||||
int map, int32_t *ttlp, char **canonp);
|
||||
+static enum nss_status getanswer_ptr (const querybuf *answer, int anslen,
|
||||
+ const char *qname,
|
||||
+ struct hostent *result, char *buffer,
|
||||
+ size_t buflen, int *errnop,
|
||||
+ int *h_errnop, int32_t *ttlp);
|
||||
|
||||
static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1,
|
||||
const querybuf *answer2, int anslen2,
|
||||
@@ -562,9 +567,8 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
|
||||
return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
- status = getanswer_r
|
||||
- (ctx, host_buffer.buf, n, qbuf, T_PTR, result, buffer, buflen,
|
||||
- errnop, h_errnop, 0 /* XXX */, ttlp, NULL);
|
||||
+ status = getanswer_ptr (host_buffer.buf, n, qbuf, result,
|
||||
+ buffer, buflen, errnop, h_errnop, ttlp);
|
||||
if (host_buffer.buf != orig_host_buffer)
|
||||
free (host_buffer.buf);
|
||||
if (status != NSS_STATUS_SUCCESS)
|
||||
@@ -660,8 +664,6 @@ getanswer_r (struct resolv_context *ctx,
|
||||
int haveanswer, had_error;
|
||||
char *bp, **ap, **hap;
|
||||
char tbuf[MAXDNAME];
|
||||
- const char *tname;
|
||||
- int (*name_ok) (const char *);
|
||||
u_char packtmp[NS_MAXCDNAME];
|
||||
int have_to_map = 0;
|
||||
uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||||
@@ -680,22 +682,8 @@ getanswer_r (struct resolv_context *ctx,
|
||||
if (buflen - sizeof (struct host_data) != linebuflen)
|
||||
linebuflen = INT_MAX;
|
||||
|
||||
- tname = qname;
|
||||
result->h_name = NULL;
|
||||
end_of_message = answer->buf + anslen;
|
||||
- switch (qtype)
|
||||
- {
|
||||
- case T_A:
|
||||
- case T_AAAA:
|
||||
- name_ok = __libc_res_hnok;
|
||||
- break;
|
||||
- case T_PTR:
|
||||
- name_ok = __libc_res_dnok;
|
||||
- break;
|
||||
- default:
|
||||
- *errnop = ENOENT;
|
||||
- return NSS_STATUS_UNAVAIL; /* XXX should be abort(); */
|
||||
- }
|
||||
|
||||
/*
|
||||
* find first satisfactory answer
|
||||
@@ -730,7 +718,7 @@ getanswer_r (struct resolv_context *ctx,
|
||||
*h_errnop = NO_RECOVERY;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- if (__glibc_unlikely (name_ok (bp) == 0))
|
||||
+ if (__glibc_unlikely (__libc_res_hnok (bp) == 0))
|
||||
{
|
||||
errno = EBADMSG;
|
||||
*errnop = EBADMSG;
|
||||
@@ -784,7 +772,7 @@ getanswer_r (struct resolv_context *ctx,
|
||||
n = -1;
|
||||
}
|
||||
|
||||
- if (__glibc_unlikely (n < 0 || (*name_ok) (bp) == 0))
|
||||
+ if (__glibc_unlikely (n < 0 || __libc_res_hnok (bp) == 0))
|
||||
{
|
||||
++had_error;
|
||||
continue;
|
||||
@@ -817,7 +805,7 @@ getanswer_r (struct resolv_context *ctx,
|
||||
continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
|
||||
- if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME)
|
||||
+ if (type == T_CNAME)
|
||||
{
|
||||
/* A CNAME could also have a TTL entry. */
|
||||
if (ttlp != NULL && ttl < *ttlp)
|
||||
@@ -827,7 +815,7 @@ getanswer_r (struct resolv_context *ctx,
|
||||
continue;
|
||||
n = __libc_dn_expand (answer->buf, end_of_message, cp,
|
||||
tbuf, sizeof tbuf);
|
||||
- if (__glibc_unlikely (n < 0 || (*name_ok) (tbuf) == 0))
|
||||
+ if (__glibc_unlikely (n < 0 || __libc_res_hnok (tbuf) == 0))
|
||||
{
|
||||
++had_error;
|
||||
continue;
|
||||
@@ -858,7 +846,260 @@ getanswer_r (struct resolv_context *ctx,
|
||||
continue;
|
||||
}
|
||||
|
||||
- if (qtype == T_PTR && type == T_CNAME)
|
||||
+ if (type == T_A && qtype == T_AAAA && map)
|
||||
+ have_to_map = 1;
|
||||
+ else if (__glibc_unlikely (type != qtype))
|
||||
+ {
|
||||
+ cp += n;
|
||||
+ continue; /* XXX - had_error++ ? */
|
||||
+ }
|
||||
+
|
||||
+ switch (type)
|
||||
+ {
|
||||
+ case T_A:
|
||||
+ case T_AAAA:
|
||||
+ if (__glibc_unlikely (__strcasecmp (result->h_name, bp) != 0))
|
||||
+ {
|
||||
+ cp += n;
|
||||
+ continue; /* XXX - had_error++ ? */
|
||||
+ }
|
||||
+
|
||||
+ /* Stop parsing at a record whose length is incorrect. */
|
||||
+ if (n != rrtype_to_rdata_length (type))
|
||||
+ {
|
||||
+ ++had_error;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Skip records of the wrong type. */
|
||||
+ if (n != result->h_length)
|
||||
+ {
|
||||
+ cp += n;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (!haveanswer)
|
||||
+ {
|
||||
+ int nn;
|
||||
+
|
||||
+ /* We compose a single hostent out of the entire chain of
|
||||
+ entries, so the TTL of the hostent is essentially the lowest
|
||||
+ TTL in the chain. */
|
||||
+ if (ttlp != NULL && ttl < *ttlp)
|
||||
+ *ttlp = ttl;
|
||||
+ if (canonp != NULL)
|
||||
+ *canonp = bp;
|
||||
+ result->h_name = bp;
|
||||
+ nn = strlen (bp) + 1; /* for the \0 */
|
||||
+ bp += nn;
|
||||
+ linebuflen -= nn;
|
||||
+ }
|
||||
+
|
||||
+ /* Provide sufficient alignment for both address
|
||||
+ families. */
|
||||
+ enum { align = 4 };
|
||||
+ _Static_assert ((align % __alignof__ (struct in_addr)) == 0,
|
||||
+ "struct in_addr alignment");
|
||||
+ _Static_assert ((align % __alignof__ (struct in6_addr)) == 0,
|
||||
+ "struct in6_addr alignment");
|
||||
+ {
|
||||
+ char *new_bp = PTR_ALIGN_UP (bp, align);
|
||||
+ linebuflen -= new_bp - bp;
|
||||
+ bp = new_bp;
|
||||
+ }
|
||||
+
|
||||
+ if (__glibc_unlikely (n > linebuflen))
|
||||
+ goto too_small;
|
||||
+ bp = __mempcpy (*hap++ = bp, cp, n);
|
||||
+ cp += n;
|
||||
+ linebuflen -= n;
|
||||
+ break;
|
||||
+ default:
|
||||
+ abort ();
|
||||
+ }
|
||||
+ if (had_error == 0)
|
||||
+ ++haveanswer;
|
||||
+ }
|
||||
+
|
||||
+ if (haveanswer > 0)
|
||||
+ {
|
||||
+ *ap = NULL;
|
||||
+ *hap = NULL;
|
||||
+ /*
|
||||
+ * Note: we sort even if host can take only one address
|
||||
+ * in its return structures - should give it the "best"
|
||||
+ * address in that case, not some random one
|
||||
+ */
|
||||
+ if (haveanswer > 1 && qtype == T_A
|
||||
+ && __resolv_context_sort_count (ctx) > 0)
|
||||
+ addrsort (ctx, host_data->h_addr_ptrs, haveanswer);
|
||||
+
|
||||
+ if (result->h_name == NULL)
|
||||
+ {
|
||||
+ n = strlen (qname) + 1; /* For the \0. */
|
||||
+ if (n > linebuflen)
|
||||
+ goto too_small;
|
||||
+ if (n >= MAXHOSTNAMELEN)
|
||||
+ goto no_recovery;
|
||||
+ result->h_name = bp;
|
||||
+ bp = __mempcpy (bp, qname, n); /* Cannot overflow. */
|
||||
+ linebuflen -= n;
|
||||
+ }
|
||||
+
|
||||
+ if (have_to_map)
|
||||
+ if (map_v4v6_hostent (result, &bp, &linebuflen))
|
||||
+ goto too_small;
|
||||
+ *h_errnop = NETDB_SUCCESS;
|
||||
+ return NSS_STATUS_SUCCESS;
|
||||
+ }
|
||||
+ no_recovery:
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ *errnop = ENOENT;
|
||||
+ /* Special case here: if the resolver sent a result but it only
|
||||
+ contains a CNAME while we are looking for a T_A or T_AAAA record,
|
||||
+ we fail with NOTFOUND instead of TRYAGAIN. */
|
||||
+ return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases
|
||||
+ ? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN);
|
||||
+}
|
||||
+
|
||||
+static enum nss_status
|
||||
+getanswer_ptr (const querybuf *answer, int anslen, const char *qname,
|
||||
+ struct hostent *result, char *buffer, size_t buflen,
|
||||
+ int *errnop, int *h_errnop, int32_t *ttlp)
|
||||
+{
|
||||
+ struct host_data
|
||||
+ {
|
||||
+ char *aliases[MAX_NR_ALIASES];
|
||||
+ unsigned char host_addr[16]; /* IPv4 or IPv6 */
|
||||
+ char *h_addr_ptrs[0];
|
||||
+ } *host_data;
|
||||
+ int linebuflen;
|
||||
+ const HEADER *hp;
|
||||
+ const u_char *end_of_message, *cp;
|
||||
+ int n, ancount, qdcount;
|
||||
+ int haveanswer, had_error;
|
||||
+ char *bp, **ap, **hap;
|
||||
+ char tbuf[MAXDNAME];
|
||||
+ const char *tname;
|
||||
+ u_char packtmp[NS_MAXCDNAME];
|
||||
+ uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||||
+ buffer += pad;
|
||||
+ buflen = buflen > pad ? buflen - pad : 0;
|
||||
+ if (__glibc_unlikely (buflen < sizeof (struct host_data)))
|
||||
+ {
|
||||
+ /* The buffer is too small. */
|
||||
+ too_small:
|
||||
+ *errnop = ERANGE;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
+ return NSS_STATUS_TRYAGAIN;
|
||||
+ }
|
||||
+ host_data = (struct host_data *) buffer;
|
||||
+ linebuflen = buflen - sizeof (struct host_data);
|
||||
+ if (buflen - sizeof (struct host_data) != linebuflen)
|
||||
+ linebuflen = INT_MAX;
|
||||
+
|
||||
+ tname = qname;
|
||||
+ result->h_name = NULL;
|
||||
+ end_of_message = answer->buf + anslen;
|
||||
+
|
||||
+ /*
|
||||
+ * find first satisfactory answer
|
||||
+ */
|
||||
+ hp = &answer->hdr;
|
||||
+ ancount = ntohs (hp->ancount);
|
||||
+ qdcount = ntohs (hp->qdcount);
|
||||
+ cp = answer->buf + HFIXEDSZ;
|
||||
+ if (__glibc_unlikely (qdcount != 1))
|
||||
+ {
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
+ if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen)
|
||||
+ goto too_small;
|
||||
+ bp = (char *) &host_data->h_addr_ptrs[ancount + 1];
|
||||
+ linebuflen -= (ancount + 1) * sizeof (char *);
|
||||
+
|
||||
+ n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
+ packtmp, sizeof packtmp);
|
||||
+ if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
+ {
|
||||
+ if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
+ goto too_small;
|
||||
+
|
||||
+ n = -1;
|
||||
+ }
|
||||
+
|
||||
+ if (__glibc_unlikely (n < 0))
|
||||
+ {
|
||||
+ *errnop = errno;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
+ if (__glibc_unlikely (__libc_res_dnok (bp) == 0))
|
||||
+ {
|
||||
+ errno = EBADMSG;
|
||||
+ *errnop = EBADMSG;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
+ cp += n + QFIXEDSZ;
|
||||
+
|
||||
+ ap = host_data->aliases;
|
||||
+ *ap = NULL;
|
||||
+ result->h_aliases = host_data->aliases;
|
||||
+ hap = host_data->h_addr_ptrs;
|
||||
+ *hap = NULL;
|
||||
+ result->h_addr_list = host_data->h_addr_ptrs;
|
||||
+ haveanswer = 0;
|
||||
+ had_error = 0;
|
||||
+
|
||||
+ while (ancount-- > 0 && cp < end_of_message && had_error == 0)
|
||||
+ {
|
||||
+ int type, class;
|
||||
+
|
||||
+ n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
+ packtmp, sizeof packtmp);
|
||||
+ if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
+ {
|
||||
+ if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
+ goto too_small;
|
||||
+
|
||||
+ n = -1;
|
||||
+ }
|
||||
+
|
||||
+ if (__glibc_unlikely (n < 0 || __libc_res_dnok (bp) == 0))
|
||||
+ {
|
||||
+ ++had_error;
|
||||
+ continue;
|
||||
+ }
|
||||
+ cp += n; /* name */
|
||||
+
|
||||
+ if (__glibc_unlikely (cp + 10 > end_of_message))
|
||||
+ {
|
||||
+ ++had_error;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ NS_GET16 (type, cp);
|
||||
+ NS_GET16 (class, cp);
|
||||
+ int32_t ttl;
|
||||
+ NS_GET32 (ttl, cp);
|
||||
+ NS_GET16 (n, cp); /* RDATA length. */
|
||||
+
|
||||
+ if (end_of_message - cp < n)
|
||||
+ {
|
||||
+ /* RDATA extends beyond the end of the packet. */
|
||||
+ ++had_error;
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ if (__glibc_unlikely (class != C_IN))
|
||||
+ {
|
||||
+ /* XXX - debug? syslog? */
|
||||
+ cp += n;
|
||||
+ continue; /* XXX - had_error++ ? */
|
||||
+ }
|
||||
+
|
||||
+ if (type == T_CNAME)
|
||||
{
|
||||
/* A CNAME could also have a TTL entry. */
|
||||
if (ttlp != NULL && ttl < *ttlp)
|
||||
@@ -887,14 +1128,6 @@ getanswer_r (struct resolv_context *ctx,
|
||||
continue;
|
||||
}
|
||||
|
||||
- if (type == T_A && qtype == T_AAAA && map)
|
||||
- have_to_map = 1;
|
||||
- else if (__glibc_unlikely (type != qtype))
|
||||
- {
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
- }
|
||||
-
|
||||
switch (type)
|
||||
{
|
||||
case T_PTR:
|
||||
@@ -956,8 +1189,6 @@ getanswer_r (struct resolv_context *ctx,
|
||||
TTL in the chain. */
|
||||
if (ttlp != NULL && ttl < *ttlp)
|
||||
*ttlp = ttl;
|
||||
- if (canonp != NULL)
|
||||
- *canonp = bp;
|
||||
result->h_name = bp;
|
||||
nn = strlen (bp) + 1; /* for the \0 */
|
||||
bp += nn;
|
||||
@@ -984,7 +1215,8 @@ getanswer_r (struct resolv_context *ctx,
|
||||
linebuflen -= n;
|
||||
break;
|
||||
default:
|
||||
- abort ();
|
||||
+ cp += n;
|
||||
+ continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
if (had_error == 0)
|
||||
++haveanswer;
|
||||
@@ -994,14 +1226,6 @@ getanswer_r (struct resolv_context *ctx,
|
||||
{
|
||||
*ap = NULL;
|
||||
*hap = NULL;
|
||||
- /*
|
||||
- * Note: we sort even if host can take only one address
|
||||
- * in its return structures - should give it the "best"
|
||||
- * address in that case, not some random one
|
||||
- */
|
||||
- if (haveanswer > 1 && qtype == T_A
|
||||
- && __resolv_context_sort_count (ctx) > 0)
|
||||
- addrsort (ctx, host_data->h_addr_ptrs, haveanswer);
|
||||
|
||||
if (result->h_name == NULL)
|
||||
{
|
||||
@@ -1015,23 +1239,15 @@ getanswer_r (struct resolv_context *ctx,
|
||||
linebuflen -= n;
|
||||
}
|
||||
|
||||
- if (have_to_map)
|
||||
- if (map_v4v6_hostent (result, &bp, &linebuflen))
|
||||
- goto too_small;
|
||||
*h_errnop = NETDB_SUCCESS;
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
no_recovery:
|
||||
*h_errnop = NO_RECOVERY;
|
||||
*errnop = ENOENT;
|
||||
- /* Special case here: if the resolver sent a result but it only
|
||||
- contains a CNAME while we are looking for a T_A or T_AAAA record,
|
||||
- we fail with NOTFOUND instead of TRYAGAIN. */
|
||||
- return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases
|
||||
- ? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN);
|
||||
+ return NSS_STATUS_TRYAGAIN;
|
||||
}
|
||||
|
||||
-
|
||||
static enum nss_status
|
||||
gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
struct gaih_addrtuple ***patp,
|
@ -0,0 +1,507 @@
|
||||
commit 32e5db37684ffcbc6ae34fcc6cdcf28670506baa
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
nss_dns: Rewrite _nss_dns_gethostbyaddr2_r and getanswer_ptr
|
||||
|
||||
The simplification takes advantage of the split from getanswer_r.
|
||||
It fixes various aliases issues, and optimizes NSS buffer usage.
|
||||
The new DNS packet parsing helpers are used, too.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit e32547d661a43da63368e488b6cfa9c53b4dcf92)
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index a6bf73a091968358..2cd7170f20b60588 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -70,6 +70,7 @@
|
||||
* --Copyright--
|
||||
*/
|
||||
|
||||
+#include <alloc_buffer.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
@@ -117,10 +118,9 @@ static enum nss_status getanswer_r (struct resolv_context *ctx,
|
||||
struct hostent *result, char *buffer,
|
||||
size_t buflen, int *errnop, int *h_errnop,
|
||||
int map, int32_t *ttlp, char **canonp);
|
||||
-static enum nss_status getanswer_ptr (const querybuf *answer, int anslen,
|
||||
- const char *qname,
|
||||
- struct hostent *result, char *buffer,
|
||||
- size_t buflen, int *errnop,
|
||||
+static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen,
|
||||
+ struct alloc_buffer *abuf,
|
||||
+ char **hnamep, int *errnop,
|
||||
int *h_errnop, int32_t *ttlp);
|
||||
|
||||
static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1,
|
||||
@@ -457,36 +457,21 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
|
||||
static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
|
||||
static const u_char v6local[] = { 0,0, 0,1 };
|
||||
const u_char *uaddr = (const u_char *)addr;
|
||||
- struct host_data
|
||||
- {
|
||||
- char *aliases[MAX_NR_ALIASES];
|
||||
- unsigned char host_addr[16]; /* IPv4 or IPv6 */
|
||||
- char *h_addr_ptrs[MAX_NR_ADDRS + 1];
|
||||
- char linebuffer[0];
|
||||
- } *host_data = (struct host_data *) buffer;
|
||||
- union
|
||||
- {
|
||||
- querybuf *buf;
|
||||
- u_char *ptr;
|
||||
- } host_buffer;
|
||||
- querybuf *orig_host_buffer;
|
||||
char qbuf[MAXDNAME+1], *qp = NULL;
|
||||
size_t size;
|
||||
int n, status;
|
||||
int olderr = errno;
|
||||
|
||||
- uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||||
- buffer += pad;
|
||||
- buflen = buflen > pad ? buflen - pad : 0;
|
||||
-
|
||||
- if (__glibc_unlikely (buflen < sizeof (struct host_data)))
|
||||
- {
|
||||
- *errnop = ERANGE;
|
||||
- *h_errnop = NETDB_INTERNAL;
|
||||
- return NSS_STATUS_TRYAGAIN;
|
||||
- }
|
||||
-
|
||||
- host_data = (struct host_data *) buffer;
|
||||
+ /* Prepare the allocation buffer. Store the pointer array first, to
|
||||
+ benefit from buffer alignment. */
|
||||
+ struct alloc_buffer abuf = alloc_buffer_create (buffer, buflen);
|
||||
+ char **address_array = alloc_buffer_alloc_array (&abuf, char *, 2);
|
||||
+ if (address_array == NULL)
|
||||
+ {
|
||||
+ *errnop = ERANGE;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
+ return NSS_STATUS_TRYAGAIN;
|
||||
+ }
|
||||
|
||||
struct resolv_context *ctx = __resolv_context_get ();
|
||||
if (ctx == NULL)
|
||||
@@ -530,8 +515,6 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
- host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
|
||||
-
|
||||
switch (af)
|
||||
{
|
||||
case AF_INET:
|
||||
@@ -555,35 +538,52 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
|
||||
break;
|
||||
}
|
||||
|
||||
- n = __res_context_query (ctx, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
|
||||
- 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
|
||||
+ unsigned char dns_packet_buffer[1024];
|
||||
+ unsigned char *alt_dns_packet_buffer = dns_packet_buffer;
|
||||
+ n = __res_context_query (ctx, qbuf, C_IN, T_PTR,
|
||||
+ dns_packet_buffer, sizeof (dns_packet_buffer),
|
||||
+ &alt_dns_packet_buffer,
|
||||
+ NULL, NULL, NULL, NULL);
|
||||
if (n < 0)
|
||||
{
|
||||
*h_errnop = h_errno;
|
||||
__set_errno (olderr);
|
||||
- if (host_buffer.buf != orig_host_buffer)
|
||||
- free (host_buffer.buf);
|
||||
+ if (alt_dns_packet_buffer != dns_packet_buffer)
|
||||
+ free (alt_dns_packet_buffer);
|
||||
__resolv_context_put (ctx);
|
||||
return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
- status = getanswer_ptr (host_buffer.buf, n, qbuf, result,
|
||||
- buffer, buflen, errnop, h_errnop, ttlp);
|
||||
- if (host_buffer.buf != orig_host_buffer)
|
||||
- free (host_buffer.buf);
|
||||
+ status = getanswer_ptr (alt_dns_packet_buffer, n,
|
||||
+ &abuf, &result->h_name, errnop, h_errnop, ttlp);
|
||||
+
|
||||
+ if (alt_dns_packet_buffer != dns_packet_buffer)
|
||||
+ free (alt_dns_packet_buffer);
|
||||
+ __resolv_context_put (ctx);
|
||||
+
|
||||
if (status != NSS_STATUS_SUCCESS)
|
||||
- {
|
||||
- __resolv_context_put (ctx);
|
||||
- return status;
|
||||
- }
|
||||
+ return status;
|
||||
|
||||
+ /* result->h_name has already been set by getanswer_ptr. */
|
||||
result->h_addrtype = af;
|
||||
result->h_length = len;
|
||||
- memcpy (host_data->host_addr, addr, len);
|
||||
- host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
|
||||
- host_data->h_addr_ptrs[1] = NULL;
|
||||
+ /* Increase the alignment to 4, in case there are applications out
|
||||
+ there that expect at least this level of address alignment. */
|
||||
+ address_array[0] = (char *) alloc_buffer_next (&abuf, uint32_t);
|
||||
+ alloc_buffer_copy_bytes (&abuf, uaddr, len);
|
||||
+ address_array[1] = NULL;
|
||||
+
|
||||
+ /* This check also covers allocation failure in getanswer_ptr. */
|
||||
+ if (alloc_buffer_has_failed (&abuf))
|
||||
+ {
|
||||
+ *errnop = ERANGE;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
+ return NSS_STATUS_TRYAGAIN;
|
||||
+ }
|
||||
+ result->h_addr_list = address_array;
|
||||
+ result->h_aliases = &address_array[1]; /* Points to NULL. */
|
||||
+
|
||||
*h_errnop = NETDB_SUCCESS;
|
||||
- __resolv_context_put (ctx);
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
libc_hidden_def (_nss_dns_gethostbyaddr2_r)
|
||||
@@ -962,287 +962,86 @@ getanswer_r (struct resolv_context *ctx,
|
||||
}
|
||||
|
||||
static enum nss_status
|
||||
-getanswer_ptr (const querybuf *answer, int anslen, const char *qname,
|
||||
- struct hostent *result, char *buffer, size_t buflen,
|
||||
+getanswer_ptr (unsigned char *packet, size_t packetlen,
|
||||
+ struct alloc_buffer *abuf, char **hnamep,
|
||||
int *errnop, int *h_errnop, int32_t *ttlp)
|
||||
{
|
||||
- struct host_data
|
||||
- {
|
||||
- char *aliases[MAX_NR_ALIASES];
|
||||
- unsigned char host_addr[16]; /* IPv4 or IPv6 */
|
||||
- char *h_addr_ptrs[0];
|
||||
- } *host_data;
|
||||
- int linebuflen;
|
||||
- const HEADER *hp;
|
||||
- const u_char *end_of_message, *cp;
|
||||
- int n, ancount, qdcount;
|
||||
- int haveanswer, had_error;
|
||||
- char *bp, **ap, **hap;
|
||||
- char tbuf[MAXDNAME];
|
||||
- const char *tname;
|
||||
- u_char packtmp[NS_MAXCDNAME];
|
||||
- uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||||
- buffer += pad;
|
||||
- buflen = buflen > pad ? buflen - pad : 0;
|
||||
- if (__glibc_unlikely (buflen < sizeof (struct host_data)))
|
||||
- {
|
||||
- /* The buffer is too small. */
|
||||
- too_small:
|
||||
- *errnop = ERANGE;
|
||||
- *h_errnop = NETDB_INTERNAL;
|
||||
- return NSS_STATUS_TRYAGAIN;
|
||||
- }
|
||||
- host_data = (struct host_data *) buffer;
|
||||
- linebuflen = buflen - sizeof (struct host_data);
|
||||
- if (buflen - sizeof (struct host_data) != linebuflen)
|
||||
- linebuflen = INT_MAX;
|
||||
-
|
||||
- tname = qname;
|
||||
- result->h_name = NULL;
|
||||
- end_of_message = answer->buf + anslen;
|
||||
-
|
||||
- /*
|
||||
- * find first satisfactory answer
|
||||
- */
|
||||
- hp = &answer->hdr;
|
||||
- ancount = ntohs (hp->ancount);
|
||||
- qdcount = ntohs (hp->qdcount);
|
||||
- cp = answer->buf + HFIXEDSZ;
|
||||
- if (__glibc_unlikely (qdcount != 1))
|
||||
- {
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
- }
|
||||
- if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen)
|
||||
- goto too_small;
|
||||
- bp = (char *) &host_data->h_addr_ptrs[ancount + 1];
|
||||
- linebuflen -= (ancount + 1) * sizeof (char *);
|
||||
-
|
||||
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
- packtmp, sizeof packtmp);
|
||||
- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
+ struct ns_rr_cursor c;
|
||||
+ if (!__ns_rr_cursor_init (&c, packet, packetlen))
|
||||
{
|
||||
- if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
- goto too_small;
|
||||
-
|
||||
- n = -1;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (n < 0))
|
||||
- {
|
||||
- *errnop = errno;
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
- }
|
||||
- if (__glibc_unlikely (__libc_res_dnok (bp) == 0))
|
||||
- {
|
||||
- errno = EBADMSG;
|
||||
- *errnop = EBADMSG;
|
||||
+ /* This should not happen because __res_context_query already
|
||||
+ perfroms response validation. */
|
||||
*h_errnop = NO_RECOVERY;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- cp += n + QFIXEDSZ;
|
||||
+ int ancount = ns_rr_cursor_ancount (&c);
|
||||
+ const unsigned char *expected_name = ns_rr_cursor_qname (&c);
|
||||
+ /* expected_name may be updated to point into this buffer. */
|
||||
+ unsigned char name_buffer[NS_MAXCDNAME];
|
||||
|
||||
- ap = host_data->aliases;
|
||||
- *ap = NULL;
|
||||
- result->h_aliases = host_data->aliases;
|
||||
- hap = host_data->h_addr_ptrs;
|
||||
- *hap = NULL;
|
||||
- result->h_addr_list = host_data->h_addr_ptrs;
|
||||
- haveanswer = 0;
|
||||
- had_error = 0;
|
||||
-
|
||||
- while (ancount-- > 0 && cp < end_of_message && had_error == 0)
|
||||
+ while (ancount > 0)
|
||||
{
|
||||
- int type, class;
|
||||
-
|
||||
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
- packtmp, sizeof packtmp);
|
||||
- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
+ struct ns_rr_wire rr;
|
||||
+ if (!__ns_rr_cursor_next (&c, &rr))
|
||||
{
|
||||
- if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
- goto too_small;
|
||||
-
|
||||
- n = -1;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (n < 0 || __libc_res_dnok (bp) == 0))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
- cp += n; /* name */
|
||||
-
|
||||
- if (__glibc_unlikely (cp + 10 > end_of_message))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
- NS_GET16 (type, cp);
|
||||
- NS_GET16 (class, cp);
|
||||
- int32_t ttl;
|
||||
- NS_GET32 (ttl, cp);
|
||||
- NS_GET16 (n, cp); /* RDATA length. */
|
||||
+ /* Skip over records with the wrong class. */
|
||||
+ if (rr.rclass != C_IN)
|
||||
+ continue;
|
||||
|
||||
- if (end_of_message - cp < n)
|
||||
- {
|
||||
- /* RDATA extends beyond the end of the packet. */
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (class != C_IN))
|
||||
- {
|
||||
- /* XXX - debug? syslog? */
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
- }
|
||||
+ /* Update TTL for known record types. */
|
||||
+ if ((rr.rtype == T_CNAME || rr.rtype == T_PTR)
|
||||
+ && ttlp != NULL && *ttlp > rr.ttl)
|
||||
+ *ttlp = rr.ttl;
|
||||
|
||||
- if (type == T_CNAME)
|
||||
+ if (rr.rtype == T_CNAME)
|
||||
{
|
||||
- /* A CNAME could also have a TTL entry. */
|
||||
- if (ttlp != NULL && ttl < *ttlp)
|
||||
- *ttlp = ttl;
|
||||
-
|
||||
- n = __libc_dn_expand (answer->buf, end_of_message, cp,
|
||||
- tbuf, sizeof tbuf);
|
||||
- if (__glibc_unlikely (n < 0 || __libc_res_dnok (tbuf) == 0))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
- cp += n;
|
||||
- /* Get canonical name. */
|
||||
- n = strlen (tbuf) + 1; /* For the \0. */
|
||||
- if (__glibc_unlikely (n > linebuflen))
|
||||
- goto too_small;
|
||||
- if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||||
+ /* NB: No check for owner name match, based on historic
|
||||
+ precedent. Record the CNAME target as the new expected
|
||||
+ name. */
|
||||
+ int n = __ns_name_unpack (c.begin, c.end, rr.rdata,
|
||||
+ name_buffer, sizeof (name_buffer));
|
||||
+ if (n < 0)
|
||||
{
|
||||
- ++had_error;
|
||||
- continue;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- tname = bp;
|
||||
- bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
|
||||
- linebuflen -= n;
|
||||
- continue;
|
||||
+ expected_name = name_buffer;
|
||||
}
|
||||
-
|
||||
- switch (type)
|
||||
+ else if (rr.rtype == T_PTR
|
||||
+ && __ns_samebinaryname (rr.rname, expected_name))
|
||||
{
|
||||
- case T_PTR:
|
||||
- if (__glibc_unlikely (__strcasecmp (tname, bp) != 0))
|
||||
- {
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
- }
|
||||
-
|
||||
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
- packtmp, sizeof packtmp);
|
||||
- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
- {
|
||||
- if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
- goto too_small;
|
||||
-
|
||||
- n = -1;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (n < 0 || __libc_res_hnok (bp) == 0))
|
||||
+ /* Decompress the target of the PTR record. This is the
|
||||
+ host name we are looking for. We can only use it if it
|
||||
+ is syntactically valid. Historically, only one host name
|
||||
+ is returned here. If the recursive resolver performs DNS
|
||||
+ record rotation, the returned host name is essentially
|
||||
+ random, which is why multiple PTR records are rarely
|
||||
+ used. Use MAXHOSTNAMELEN instead of NS_MAXCDNAME for
|
||||
+ additional length checking. */
|
||||
+ char hname[MAXHOSTNAMELEN + 1];
|
||||
+ if (__ns_name_unpack (c.begin, c.end, rr.rdata,
|
||||
+ name_buffer, sizeof (name_buffer)) < 0
|
||||
+ || !__res_binary_hnok (expected_name)
|
||||
+ || __ns_name_ntop (name_buffer, hname, sizeof (hname)) < 0)
|
||||
{
|
||||
- ++had_error;
|
||||
- break;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- if (ttlp != NULL && ttl < *ttlp)
|
||||
- *ttlp = ttl;
|
||||
- /* bind would put multiple PTR records as aliases, but we don't do
|
||||
- that. */
|
||||
- result->h_name = bp;
|
||||
- *h_errnop = NETDB_SUCCESS;
|
||||
+ /* Successful allocation is checked by the caller. */
|
||||
+ *hnamep = alloc_buffer_copy_string (abuf, hname);
|
||||
return NSS_STATUS_SUCCESS;
|
||||
- case T_A:
|
||||
- case T_AAAA:
|
||||
- if (__glibc_unlikely (__strcasecmp (result->h_name, bp) != 0))
|
||||
- {
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
- }
|
||||
-
|
||||
- /* Stop parsing at a record whose length is incorrect. */
|
||||
- if (n != rrtype_to_rdata_length (type))
|
||||
- {
|
||||
- ++had_error;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- /* Skip records of the wrong type. */
|
||||
- if (n != result->h_length)
|
||||
- {
|
||||
- cp += n;
|
||||
- continue;
|
||||
- }
|
||||
- if (!haveanswer)
|
||||
- {
|
||||
- int nn;
|
||||
-
|
||||
- /* We compose a single hostent out of the entire chain of
|
||||
- entries, so the TTL of the hostent is essentially the lowest
|
||||
- TTL in the chain. */
|
||||
- if (ttlp != NULL && ttl < *ttlp)
|
||||
- *ttlp = ttl;
|
||||
- result->h_name = bp;
|
||||
- nn = strlen (bp) + 1; /* for the \0 */
|
||||
- bp += nn;
|
||||
- linebuflen -= nn;
|
||||
- }
|
||||
-
|
||||
- /* Provide sufficient alignment for both address
|
||||
- families. */
|
||||
- enum { align = 4 };
|
||||
- _Static_assert ((align % __alignof__ (struct in_addr)) == 0,
|
||||
- "struct in_addr alignment");
|
||||
- _Static_assert ((align % __alignof__ (struct in6_addr)) == 0,
|
||||
- "struct in6_addr alignment");
|
||||
- {
|
||||
- char *new_bp = PTR_ALIGN_UP (bp, align);
|
||||
- linebuflen -= new_bp - bp;
|
||||
- bp = new_bp;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (n > linebuflen))
|
||||
- goto too_small;
|
||||
- bp = __mempcpy (*hap++ = bp, cp, n);
|
||||
- cp += n;
|
||||
- linebuflen -= n;
|
||||
- break;
|
||||
- default:
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
}
|
||||
- if (had_error == 0)
|
||||
- ++haveanswer;
|
||||
}
|
||||
|
||||
- if (haveanswer > 0)
|
||||
- {
|
||||
- *ap = NULL;
|
||||
- *hap = NULL;
|
||||
-
|
||||
- if (result->h_name == NULL)
|
||||
- {
|
||||
- n = strlen (qname) + 1; /* For the \0. */
|
||||
- if (n > linebuflen)
|
||||
- goto too_small;
|
||||
- if (n >= MAXHOSTNAMELEN)
|
||||
- goto no_recovery;
|
||||
- result->h_name = bp;
|
||||
- bp = __mempcpy (bp, qname, n); /* Cannot overflow. */
|
||||
- linebuflen -= n;
|
||||
- }
|
||||
+ /* No PTR record found. */
|
||||
+ if (ttlp != NULL)
|
||||
+ /* No caching of negative responses. */
|
||||
+ *ttlp = 0;
|
||||
|
||||
- *h_errnop = NETDB_SUCCESS;
|
||||
- return NSS_STATUS_SUCCESS;
|
||||
- }
|
||||
- no_recovery:
|
||||
*h_errnop = NO_RECOVERY;
|
||||
*errnop = ENOENT;
|
||||
return NSS_STATUS_TRYAGAIN;
|
@ -0,0 +1,311 @@
|
||||
commit 7267341ec1b5c591c2e7946d0604d3cf1423db7d
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
nss_dns: Remove remnants of IPv6 address mapping
|
||||
|
||||
res_use_inet6 always returns false since commit 3f8b44be0a658266adff5
|
||||
("resolv: Remove support for RES_USE_INET6 and the inet6 option").
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit a7fc30b522a0cd7c8c5e7e285b9531b704e02f04)
|
||||
|
||||
diff --git a/resolv/README b/resolv/README
|
||||
index 514e9bb617e710f1..2146bc3b27a6dc56 100644
|
||||
--- a/resolv/README
|
||||
+++ b/resolv/README
|
||||
@@ -146,6 +146,3 @@ res_libc.c is home-brewn, although parts of it are taken from res_data.c.
|
||||
|
||||
res_hconf.c and res_hconf.h were contributed by David Mosberger, and
|
||||
do not come from BIND.
|
||||
-
|
||||
-The files gethnamaddr.c, mapv4v6addr.h and mapv4v6hostent.h are
|
||||
-leftovers from BIND 4.9.7.
|
||||
diff --git a/resolv/mapv4v6addr.h b/resolv/mapv4v6addr.h
|
||||
deleted file mode 100644
|
||||
index 7f85f7d5e393ec5f..0000000000000000
|
||||
--- a/resolv/mapv4v6addr.h
|
||||
+++ /dev/null
|
||||
@@ -1,69 +0,0 @@
|
||||
-/*
|
||||
- * ++Copyright++ 1985, 1988, 1993
|
||||
- * -
|
||||
- * Copyright (c) 1985, 1988, 1993
|
||||
- * The Regents of the University of California. All rights reserved.
|
||||
- *
|
||||
- * Redistribution and use in source and binary forms, with or without
|
||||
- * modification, are permitted provided that the following conditions
|
||||
- * are met:
|
||||
- * 1. Redistributions of source code must retain the above copyright
|
||||
- * notice, this list of conditions and the following disclaimer.
|
||||
- * 2. Redistributions in binary form must reproduce the above copyright
|
||||
- * notice, this list of conditions and the following disclaimer in the
|
||||
- * documentation and/or other materials provided with the distribution.
|
||||
- * 4. Neither the name of the University nor the names of its contributors
|
||||
- * may be used to endorse or promote products derived from this software
|
||||
- * without specific prior written permission.
|
||||
- *
|
||||
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
- * SUCH DAMAGE.
|
||||
- * -
|
||||
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
- *
|
||||
- * Permission to use, copy, modify, and distribute this software for any
|
||||
- * purpose with or without fee is hereby granted, provided that the above
|
||||
- * copyright notice and this permission notice appear in all copies, and that
|
||||
- * the name of Digital Equipment Corporation not be used in advertising or
|
||||
- * publicity pertaining to distribution of the document or software without
|
||||
- * specific, written prior permission.
|
||||
- *
|
||||
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
- * SOFTWARE.
|
||||
- * -
|
||||
- * --Copyright--
|
||||
- */
|
||||
-
|
||||
-#include <string.h>
|
||||
-#include <arpa/nameser.h>
|
||||
-
|
||||
-static void
|
||||
-map_v4v6_address (const char *src, char *dst)
|
||||
-{
|
||||
- u_char *p = (u_char *) dst;
|
||||
- int i;
|
||||
-
|
||||
- /* Move the IPv4 part to the right position. */
|
||||
- memcpy (dst + 12, src, INADDRSZ);
|
||||
-
|
||||
- /* Mark this ipv6 addr as a mapped ipv4. */
|
||||
- for (i = 0; i < 10; i++)
|
||||
- *p++ = 0x00;
|
||||
- *p++ = 0xff;
|
||||
- *p = 0xff;
|
||||
-}
|
||||
diff --git a/resolv/mapv4v6hostent.h b/resolv/mapv4v6hostent.h
|
||||
deleted file mode 100644
|
||||
index c11038adf33f154d..0000000000000000
|
||||
--- a/resolv/mapv4v6hostent.h
|
||||
+++ /dev/null
|
||||
@@ -1,84 +0,0 @@
|
||||
-/*
|
||||
- * ++Copyright++ 1985, 1988, 1993
|
||||
- * -
|
||||
- * Copyright (c) 1985, 1988, 1993
|
||||
- * The Regents of the University of California. All rights reserved.
|
||||
- *
|
||||
- * Redistribution and use in source and binary forms, with or without
|
||||
- * modification, are permitted provided that the following conditions
|
||||
- * are met:
|
||||
- * 1. Redistributions of source code must retain the above copyright
|
||||
- * notice, this list of conditions and the following disclaimer.
|
||||
- * 2. Redistributions in binary form must reproduce the above copyright
|
||||
- * notice, this list of conditions and the following disclaimer in the
|
||||
- * documentation and/or other materials provided with the distribution.
|
||||
- * 4. Neither the name of the University nor the names of its contributors
|
||||
- * may be used to endorse or promote products derived from this software
|
||||
- * without specific prior written permission.
|
||||
- *
|
||||
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
- * SUCH DAMAGE.
|
||||
- * -
|
||||
- * Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||||
- *
|
||||
- * Permission to use, copy, modify, and distribute this software for any
|
||||
- * purpose with or without fee is hereby granted, provided that the above
|
||||
- * copyright notice and this permission notice appear in all copies, and that
|
||||
- * the name of Digital Equipment Corporation not be used in advertising or
|
||||
- * publicity pertaining to distribution of the document or software without
|
||||
- * specific, written prior permission.
|
||||
- *
|
||||
- * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||||
- * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||||
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||||
- * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||||
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
- * SOFTWARE.
|
||||
- * -
|
||||
- * --Copyright--
|
||||
- */
|
||||
-
|
||||
-#include <arpa/nameser.h>
|
||||
-#include <sys/socket.h>
|
||||
-
|
||||
-typedef union {
|
||||
- int32_t al;
|
||||
- char ac;
|
||||
-} align;
|
||||
-
|
||||
-static int
|
||||
-map_v4v6_hostent (struct hostent *hp, char **bpp, int *lenp)
|
||||
-{
|
||||
- char **ap;
|
||||
-
|
||||
- if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
|
||||
- return 0;
|
||||
- hp->h_addrtype = AF_INET6;
|
||||
- hp->h_length = IN6ADDRSZ;
|
||||
- for (ap = hp->h_addr_list; *ap; ap++)
|
||||
- {
|
||||
- int i = sizeof (align) - ((u_long) *bpp % sizeof (align));
|
||||
-
|
||||
- if (*lenp < (i + IN6ADDRSZ))
|
||||
- /* Out of memory. */
|
||||
- return 1;
|
||||
- *bpp += i;
|
||||
- *lenp -= i;
|
||||
- map_v4v6_address (*ap, *bpp);
|
||||
- *ap = *bpp;
|
||||
- *bpp += IN6ADDRSZ;
|
||||
- *lenp -= IN6ADDRSZ;
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 2cd7170f20b60588..f8dc5a0a7d1eb156 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -88,10 +88,6 @@
|
||||
#include <resolv/resolv-internal.h>
|
||||
#include <resolv/resolv_context.h>
|
||||
|
||||
-/* Get implementations of some internal functions. */
|
||||
-#include <resolv/mapv4v6addr.h>
|
||||
-#include <resolv/mapv4v6hostent.h>
|
||||
-
|
||||
#define RESOLVSORT
|
||||
|
||||
#if PACKETSZ > 65536
|
||||
@@ -117,7 +113,7 @@ static enum nss_status getanswer_r (struct resolv_context *ctx,
|
||||
const char *qname, int qtype,
|
||||
struct hostent *result, char *buffer,
|
||||
size_t buflen, int *errnop, int *h_errnop,
|
||||
- int map, int32_t *ttlp, char **canonp);
|
||||
+ int32_t *ttlp, char **canonp);
|
||||
static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen,
|
||||
struct alloc_buffer *abuf,
|
||||
char **hnamep, int *errnop,
|
||||
@@ -198,7 +194,6 @@ gethostbyname3_context (struct resolv_context *ctx,
|
||||
char tmp[NS_MAXDNAME];
|
||||
int size, type, n;
|
||||
const char *cp;
|
||||
- int map = 0;
|
||||
int olderr = errno;
|
||||
enum nss_status status;
|
||||
|
||||
@@ -259,32 +254,12 @@ gethostbyname3_context (struct resolv_context *ctx,
|
||||
*errnop = EAGAIN;
|
||||
else
|
||||
__set_errno (olderr);
|
||||
-
|
||||
- /* If we are looking for an IPv6 address and mapping is enabled
|
||||
- by having the RES_USE_INET6 bit in _res.options set, we try
|
||||
- another lookup. */
|
||||
- if (af == AF_INET6 && res_use_inet6 ())
|
||||
- n = __res_context_search (ctx, name, C_IN, T_A, host_buffer.buf->buf,
|
||||
- host_buffer.buf != orig_host_buffer
|
||||
- ? MAXPACKET : 1024, &host_buffer.ptr,
|
||||
- NULL, NULL, NULL, NULL);
|
||||
-
|
||||
- if (n < 0)
|
||||
- {
|
||||
- if (host_buffer.buf != orig_host_buffer)
|
||||
- free (host_buffer.buf);
|
||||
- return status;
|
||||
- }
|
||||
-
|
||||
- map = 1;
|
||||
-
|
||||
- result->h_addrtype = AF_INET;
|
||||
- result->h_length = INADDRSZ;
|
||||
}
|
||||
+ else
|
||||
+ status = getanswer_r
|
||||
+ (ctx, host_buffer.buf, n, name, type, result, buffer, buflen,
|
||||
+ errnop, h_errnop, ttlp, canonp);
|
||||
|
||||
- status = getanswer_r
|
||||
- (ctx, host_buffer.buf, n, name, type, result, buffer, buflen,
|
||||
- errnop, h_errnop, map, ttlp, canonp);
|
||||
if (host_buffer.buf != orig_host_buffer)
|
||||
free (host_buffer.buf);
|
||||
return status;
|
||||
@@ -330,13 +305,8 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result,
|
||||
*h_errnop = NETDB_INTERNAL;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- status = NSS_STATUS_NOTFOUND;
|
||||
- if (res_use_inet6 ())
|
||||
- status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer,
|
||||
- buflen, errnop, h_errnop, NULL, NULL);
|
||||
- if (status == NSS_STATUS_NOTFOUND)
|
||||
- status = gethostbyname3_context (ctx, name, AF_INET, result, buffer,
|
||||
- buflen, errnop, h_errnop, NULL, NULL);
|
||||
+ status = gethostbyname3_context (ctx, name, AF_INET, result, buffer,
|
||||
+ buflen, errnop, h_errnop, NULL, NULL);
|
||||
__resolv_context_put (ctx);
|
||||
return status;
|
||||
}
|
||||
@@ -649,7 +619,7 @@ static enum nss_status
|
||||
getanswer_r (struct resolv_context *ctx,
|
||||
const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
struct hostent *result, char *buffer, size_t buflen,
|
||||
- int *errnop, int *h_errnop, int map, int32_t *ttlp, char **canonp)
|
||||
+ int *errnop, int *h_errnop, int32_t *ttlp, char **canonp)
|
||||
{
|
||||
struct host_data
|
||||
{
|
||||
@@ -665,7 +635,6 @@ getanswer_r (struct resolv_context *ctx,
|
||||
char *bp, **ap, **hap;
|
||||
char tbuf[MAXDNAME];
|
||||
u_char packtmp[NS_MAXCDNAME];
|
||||
- int have_to_map = 0;
|
||||
uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||||
buffer += pad;
|
||||
buflen = buflen > pad ? buflen - pad : 0;
|
||||
@@ -846,9 +815,7 @@ getanswer_r (struct resolv_context *ctx,
|
||||
continue;
|
||||
}
|
||||
|
||||
- if (type == T_A && qtype == T_AAAA && map)
|
||||
- have_to_map = 1;
|
||||
- else if (__glibc_unlikely (type != qtype))
|
||||
+ if (__glibc_unlikely (type != qtype))
|
||||
{
|
||||
cp += n;
|
||||
continue; /* XXX - had_error++ ? */
|
||||
@@ -945,9 +912,6 @@ getanswer_r (struct resolv_context *ctx,
|
||||
linebuflen -= n;
|
||||
}
|
||||
|
||||
- if (have_to_map)
|
||||
- if (map_v4v6_hostent (result, &bp, &linebuflen))
|
||||
- goto too_small;
|
||||
*h_errnop = NETDB_SUCCESS;
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
@ -0,0 +1,565 @@
|
||||
commit 9abc40d9b514fc51cd1a052d32d092a827c6e21a
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
nss_dns: Rewrite getanswer_r to match getanswer_ptr (bug 12154, bug 29305)
|
||||
|
||||
Allocate the pointer arrays only at the end, when their sizes
|
||||
are known. This addresses bug 29305.
|
||||
|
||||
Skip over invalid names instead of failing lookups. This partially
|
||||
fixes bug 12154 (for gethostbyname, fixing getaddrinfo requires
|
||||
different changes).
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit d101d836e7e4bd1d4e4972b0e0bd0a55c9b650fa)
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index f8dc5a0a7d1eb156..10c21e1e827cde12 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -108,12 +108,19 @@ typedef union querybuf
|
||||
u_char buf[MAXPACKET];
|
||||
} querybuf;
|
||||
|
||||
-static enum nss_status getanswer_r (struct resolv_context *ctx,
|
||||
- const querybuf *answer, int anslen,
|
||||
- const char *qname, int qtype,
|
||||
- struct hostent *result, char *buffer,
|
||||
- size_t buflen, int *errnop, int *h_errnop,
|
||||
- int32_t *ttlp, char **canonp);
|
||||
+/* For historic reasons, pointers to IP addresses are char *, so use a
|
||||
+ single list type for addresses and host names. */
|
||||
+#define DYNARRAY_STRUCT ptrlist
|
||||
+#define DYNARRAY_ELEMENT char *
|
||||
+#define DYNARRAY_PREFIX ptrlist_
|
||||
+#include <malloc/dynarray-skeleton.c>
|
||||
+
|
||||
+static enum nss_status getanswer_r (unsigned char *packet, size_t packetlen,
|
||||
+ uint16_t qtype, struct alloc_buffer *abuf,
|
||||
+ struct ptrlist *addresses,
|
||||
+ struct ptrlist *aliases,
|
||||
+ int *errnop, int *h_errnop, int32_t *ttlp);
|
||||
+static void addrsort (struct resolv_context *ctx, char **ap, int num);
|
||||
static enum nss_status getanswer_ptr (unsigned char *packet, size_t packetlen,
|
||||
struct alloc_buffer *abuf,
|
||||
char **hnamep, int *errnop,
|
||||
@@ -185,12 +192,6 @@ gethostbyname3_context (struct resolv_context *ctx,
|
||||
char *buffer, size_t buflen, int *errnop,
|
||||
int *h_errnop, int32_t *ttlp, char **canonp)
|
||||
{
|
||||
- union
|
||||
- {
|
||||
- querybuf *buf;
|
||||
- u_char *ptr;
|
||||
- } host_buffer;
|
||||
- querybuf *orig_host_buffer;
|
||||
char tmp[NS_MAXDNAME];
|
||||
int size, type, n;
|
||||
const char *cp;
|
||||
@@ -224,10 +225,12 @@ gethostbyname3_context (struct resolv_context *ctx,
|
||||
&& (cp = __res_context_hostalias (ctx, name, tmp, sizeof (tmp))) != NULL)
|
||||
name = cp;
|
||||
|
||||
- host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
|
||||
+ unsigned char dns_packet_buffer[1024];
|
||||
+ unsigned char *alt_dns_packet_buffer = dns_packet_buffer;
|
||||
|
||||
- n = __res_context_search (ctx, name, C_IN, type, host_buffer.buf->buf,
|
||||
- 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
|
||||
+ n = __res_context_search (ctx, name, C_IN, type,
|
||||
+ dns_packet_buffer, sizeof (dns_packet_buffer),
|
||||
+ &alt_dns_packet_buffer, NULL, NULL, NULL, NULL);
|
||||
if (n < 0)
|
||||
{
|
||||
switch (errno)
|
||||
@@ -256,12 +259,77 @@ gethostbyname3_context (struct resolv_context *ctx,
|
||||
__set_errno (olderr);
|
||||
}
|
||||
else
|
||||
- status = getanswer_r
|
||||
- (ctx, host_buffer.buf, n, name, type, result, buffer, buflen,
|
||||
- errnop, h_errnop, ttlp, canonp);
|
||||
+ {
|
||||
+ struct alloc_buffer abuf = alloc_buffer_create (buffer, buflen);
|
||||
|
||||
- if (host_buffer.buf != orig_host_buffer)
|
||||
- free (host_buffer.buf);
|
||||
+ struct ptrlist addresses;
|
||||
+ ptrlist_init (&addresses);
|
||||
+ struct ptrlist aliases;
|
||||
+ ptrlist_init (&aliases);
|
||||
+
|
||||
+ status = getanswer_r (alt_dns_packet_buffer, n, type,
|
||||
+ &abuf, &addresses, &aliases,
|
||||
+ errnop, h_errnop, ttlp);
|
||||
+ if (status == NSS_STATUS_SUCCESS)
|
||||
+ {
|
||||
+ if (ptrlist_has_failed (&addresses)
|
||||
+ || ptrlist_has_failed (&aliases))
|
||||
+ {
|
||||
+ /* malloc failure. Do not retry using the ERANGE protocol. */
|
||||
+ *errnop = ENOMEM;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
+ status = NSS_STATUS_UNAVAIL;
|
||||
+ }
|
||||
+
|
||||
+ /* Reserve the address and alias arrays in the result
|
||||
+ buffer. Both are NULL-terminated, but the first element
|
||||
+ of the alias array is stored in h_name, so no extra space
|
||||
+ for the NULL terminator is needed there. */
|
||||
+ result->h_addr_list
|
||||
+ = alloc_buffer_alloc_array (&abuf, char *,
|
||||
+ ptrlist_size (&addresses) + 1);
|
||||
+ result->h_aliases
|
||||
+ = alloc_buffer_alloc_array (&abuf, char *,
|
||||
+ ptrlist_size (&aliases));
|
||||
+ if (alloc_buffer_has_failed (&abuf))
|
||||
+ {
|
||||
+ /* Retry using the ERANGE protocol. */
|
||||
+ *errnop = ERANGE;
|
||||
+ *h_errnop = NETDB_INTERNAL;
|
||||
+ status = NSS_STATUS_TRYAGAIN;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ /* Copy the address list and NULL-terminate it. */
|
||||
+ memcpy (result->h_addr_list, ptrlist_begin (&addresses),
|
||||
+ ptrlist_size (&addresses) * sizeof (char *));
|
||||
+ result->h_addr_list[ptrlist_size (&addresses)] = NULL;
|
||||
+
|
||||
+ /* Sort the address list if requested. */
|
||||
+ if (type == T_A && __resolv_context_sort_count (ctx) > 0)
|
||||
+ addrsort (ctx, result->h_addr_list, ptrlist_size (&addresses));
|
||||
+
|
||||
+ /* Copy the aliases, excluding the last one. */
|
||||
+ memcpy (result->h_aliases, ptrlist_begin (&aliases),
|
||||
+ (ptrlist_size (&aliases) - 1) * sizeof (char *));
|
||||
+ result->h_aliases[ptrlist_size (&aliases) - 1] = NULL;
|
||||
+
|
||||
+ /* The last alias goes into h_name. */
|
||||
+ assert (ptrlist_size (&aliases) >= 1);
|
||||
+ result->h_name = ptrlist_end (&aliases)[-1];
|
||||
+
|
||||
+ /* This is also the canonical name. */
|
||||
+ if (canonp != NULL)
|
||||
+ *canonp = result->h_name;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ptrlist_free (&aliases);
|
||||
+ ptrlist_free (&addresses);
|
||||
+ }
|
||||
+
|
||||
+ if (alt_dns_packet_buffer != dns_packet_buffer)
|
||||
+ free (alt_dns_packet_buffer);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -615,314 +683,128 @@ addrsort (struct resolv_context *ctx, char **ap, int num)
|
||||
break;
|
||||
}
|
||||
|
||||
-static enum nss_status
|
||||
-getanswer_r (struct resolv_context *ctx,
|
||||
- const querybuf *answer, int anslen, const char *qname, int qtype,
|
||||
- struct hostent *result, char *buffer, size_t buflen,
|
||||
- int *errnop, int *h_errnop, int32_t *ttlp, char **canonp)
|
||||
+/* Convert the uncompressed, binary domain name CDNAME into its
|
||||
+ textual representation and add it to the end of ALIASES, allocating
|
||||
+ space for a copy of the name from ABUF. Skip adding the name if it
|
||||
+ is not a valid host name, and return false in that case, otherwise
|
||||
+ true. */
|
||||
+static bool
|
||||
+getanswer_r_store_alias (const unsigned char *cdname,
|
||||
+ struct alloc_buffer *abuf,
|
||||
+ struct ptrlist *aliases)
|
||||
{
|
||||
- struct host_data
|
||||
- {
|
||||
- char *aliases[MAX_NR_ALIASES];
|
||||
- unsigned char host_addr[16]; /* IPv4 or IPv6 */
|
||||
- char *h_addr_ptrs[0];
|
||||
- } *host_data;
|
||||
- int linebuflen;
|
||||
- const HEADER *hp;
|
||||
- const u_char *end_of_message, *cp;
|
||||
- int n, ancount, qdcount;
|
||||
- int haveanswer, had_error;
|
||||
- char *bp, **ap, **hap;
|
||||
- char tbuf[MAXDNAME];
|
||||
- u_char packtmp[NS_MAXCDNAME];
|
||||
- uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||||
- buffer += pad;
|
||||
- buflen = buflen > pad ? buflen - pad : 0;
|
||||
- if (__glibc_unlikely (buflen < sizeof (struct host_data)))
|
||||
- {
|
||||
- /* The buffer is too small. */
|
||||
- too_small:
|
||||
- *errnop = ERANGE;
|
||||
- *h_errnop = NETDB_INTERNAL;
|
||||
- return NSS_STATUS_TRYAGAIN;
|
||||
- }
|
||||
- host_data = (struct host_data *) buffer;
|
||||
- linebuflen = buflen - sizeof (struct host_data);
|
||||
- if (buflen - sizeof (struct host_data) != linebuflen)
|
||||
- linebuflen = INT_MAX;
|
||||
-
|
||||
- result->h_name = NULL;
|
||||
- end_of_message = answer->buf + anslen;
|
||||
-
|
||||
- /*
|
||||
- * find first satisfactory answer
|
||||
- */
|
||||
- hp = &answer->hdr;
|
||||
- ancount = ntohs (hp->ancount);
|
||||
- qdcount = ntohs (hp->qdcount);
|
||||
- cp = answer->buf + HFIXEDSZ;
|
||||
- if (__glibc_unlikely (qdcount != 1))
|
||||
- {
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
- }
|
||||
- if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen)
|
||||
- goto too_small;
|
||||
- bp = (char *) &host_data->h_addr_ptrs[ancount + 1];
|
||||
- linebuflen -= (ancount + 1) * sizeof (char *);
|
||||
-
|
||||
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
- packtmp, sizeof packtmp);
|
||||
- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
- {
|
||||
- if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
- goto too_small;
|
||||
-
|
||||
- n = -1;
|
||||
- }
|
||||
+ /* Filter out domain names that are not host names. */
|
||||
+ if (!__res_binary_hnok (cdname))
|
||||
+ return false;
|
||||
+
|
||||
+ /* Note: Not NS_MAXCDNAME, so that __ns_name_ntop implicitly checks
|
||||
+ for length. */
|
||||
+ char dname[MAXHOSTNAMELEN + 1];
|
||||
+ if (__ns_name_ntop (cdname, dname, sizeof (dname)) < 0)
|
||||
+ return false;
|
||||
+ /* Do not report an error on allocation failure, instead store NULL
|
||||
+ or do nothing. getanswer_r's caller will see NSS_STATUS_SUCCESS
|
||||
+ and detect the memory allocation failure or buffer space
|
||||
+ exhaustion, and report it accordingly. */
|
||||
+ ptrlist_add (aliases, alloc_buffer_copy_string (abuf, dname));
|
||||
+ return true;
|
||||
+}
|
||||
|
||||
- if (__glibc_unlikely (n < 0))
|
||||
- {
|
||||
- *errnop = errno;
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- return NSS_STATUS_UNAVAIL;
|
||||
- }
|
||||
- if (__glibc_unlikely (__libc_res_hnok (bp) == 0))
|
||||
+static enum nss_status __attribute__ ((noinline))
|
||||
+getanswer_r (unsigned char *packet, size_t packetlen, uint16_t qtype,
|
||||
+ struct alloc_buffer *abuf,
|
||||
+ struct ptrlist *addresses, struct ptrlist *aliases,
|
||||
+ int *errnop, int *h_errnop, int32_t *ttlp)
|
||||
+{
|
||||
+ struct ns_rr_cursor c;
|
||||
+ if (!__ns_rr_cursor_init (&c, packet, packetlen))
|
||||
{
|
||||
- errno = EBADMSG;
|
||||
- *errnop = EBADMSG;
|
||||
+ /* This should not happen because __res_context_query already
|
||||
+ perfroms response validation. */
|
||||
*h_errnop = NO_RECOVERY;
|
||||
return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- cp += n + QFIXEDSZ;
|
||||
|
||||
- if (qtype == T_A || qtype == T_AAAA)
|
||||
+ /* Treat the QNAME just like an alias. Error out if it is not a
|
||||
+ valid host name. */
|
||||
+ if (ns_rr_cursor_rcode (&c) == NXDOMAIN
|
||||
+ || !getanswer_r_store_alias (ns_rr_cursor_qname (&c), abuf, aliases))
|
||||
{
|
||||
- /* res_send() has already verified that the query name is the
|
||||
- * same as the one we sent; this just gets the expanded name
|
||||
- * (i.e., with the succeeding search-domain tacked on).
|
||||
- */
|
||||
- n = strlen (bp) + 1; /* for the \0 */
|
||||
- if (n >= MAXHOSTNAMELEN)
|
||||
- {
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- *errnop = ENOENT;
|
||||
- return NSS_STATUS_TRYAGAIN;
|
||||
- }
|
||||
- result->h_name = bp;
|
||||
- bp += n;
|
||||
- linebuflen -= n;
|
||||
- if (linebuflen < 0)
|
||||
- goto too_small;
|
||||
- /* The qname can be abbreviated, but h_name is now absolute. */
|
||||
- qname = result->h_name;
|
||||
+ if (ttlp != NULL)
|
||||
+ /* No negative caching. */
|
||||
+ *ttlp = 0;
|
||||
+ *h_errnop = HOST_NOT_FOUND;
|
||||
+ *errnop = ENOENT;
|
||||
+ return NSS_STATUS_NOTFOUND;
|
||||
}
|
||||
|
||||
- ap = host_data->aliases;
|
||||
- *ap = NULL;
|
||||
- result->h_aliases = host_data->aliases;
|
||||
- hap = host_data->h_addr_ptrs;
|
||||
- *hap = NULL;
|
||||
- result->h_addr_list = host_data->h_addr_ptrs;
|
||||
- haveanswer = 0;
|
||||
- had_error = 0;
|
||||
+ int ancount = ns_rr_cursor_ancount (&c);
|
||||
+ const unsigned char *expected_name = ns_rr_cursor_qname (&c);
|
||||
+ /* expected_name may be updated to point into this buffer. */
|
||||
+ unsigned char name_buffer[NS_MAXCDNAME];
|
||||
|
||||
- while (ancount-- > 0 && cp < end_of_message && had_error == 0)
|
||||
+ for (; ancount > 0; --ancount)
|
||||
{
|
||||
- int type, class;
|
||||
-
|
||||
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
|
||||
- packtmp, sizeof packtmp);
|
||||
- if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
|
||||
- {
|
||||
- if (__glibc_unlikely (errno == EMSGSIZE))
|
||||
- goto too_small;
|
||||
-
|
||||
- n = -1;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (n < 0 || __libc_res_hnok (bp) == 0))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
- cp += n; /* name */
|
||||
-
|
||||
- if (__glibc_unlikely (cp + 10 > end_of_message))
|
||||
+ struct ns_rr_wire rr;
|
||||
+ if (!__ns_rr_cursor_next (&c, &rr))
|
||||
{
|
||||
- ++had_error;
|
||||
- continue;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
|
||||
- NS_GET16 (type, cp);
|
||||
- NS_GET16 (class, cp);
|
||||
- int32_t ttl;
|
||||
- NS_GET32 (ttl, cp);
|
||||
- NS_GET16 (n, cp); /* RDATA length. */
|
||||
-
|
||||
- if (end_of_message - cp < n)
|
||||
- {
|
||||
- /* RDATA extends beyond the end of the packet. */
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
+ /* Skip over records with the wrong class. */
|
||||
+ if (rr.rclass != C_IN)
|
||||
+ continue;
|
||||
|
||||
- if (__glibc_unlikely (class != C_IN))
|
||||
- {
|
||||
- /* XXX - debug? syslog? */
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
- }
|
||||
+ /* Update TTL for recognized record types. */
|
||||
+ if ((rr.rtype == T_CNAME || rr.rtype == qtype)
|
||||
+ && ttlp != NULL && *ttlp > rr.ttl)
|
||||
+ *ttlp = rr.ttl;
|
||||
|
||||
- if (type == T_CNAME)
|
||||
+ if (rr.rtype == T_CNAME)
|
||||
{
|
||||
- /* A CNAME could also have a TTL entry. */
|
||||
- if (ttlp != NULL && ttl < *ttlp)
|
||||
- *ttlp = ttl;
|
||||
-
|
||||
- if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
|
||||
- continue;
|
||||
- n = __libc_dn_expand (answer->buf, end_of_message, cp,
|
||||
- tbuf, sizeof tbuf);
|
||||
- if (__glibc_unlikely (n < 0 || __libc_res_hnok (tbuf) == 0))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
- cp += n;
|
||||
- /* Store alias. */
|
||||
- *ap++ = bp;
|
||||
- n = strlen (bp) + 1; /* For the \0. */
|
||||
- if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||||
- {
|
||||
- ++had_error;
|
||||
- continue;
|
||||
- }
|
||||
- bp += n;
|
||||
- linebuflen -= n;
|
||||
- /* Get canonical name. */
|
||||
- n = strlen (tbuf) + 1; /* For the \0. */
|
||||
- if (__glibc_unlikely (n > linebuflen))
|
||||
- goto too_small;
|
||||
- if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||||
+ /* NB: No check for owner name match, based on historic
|
||||
+ precedent. Record the CNAME target as the new expected
|
||||
+ name. */
|
||||
+ int n = __ns_name_unpack (c.begin, c.end, rr.rdata,
|
||||
+ name_buffer, sizeof (name_buffer));
|
||||
+ if (n < 0)
|
||||
{
|
||||
- ++had_error;
|
||||
- continue;
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ return NSS_STATUS_UNAVAIL;
|
||||
}
|
||||
- result->h_name = bp;
|
||||
- bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */
|
||||
- linebuflen -= n;
|
||||
- continue;
|
||||
+ /* And store the new name as an alias. */
|
||||
+ getanswer_r_store_alias (name_buffer, abuf, aliases);
|
||||
+ expected_name = name_buffer;
|
||||
}
|
||||
-
|
||||
- if (__glibc_unlikely (type != qtype))
|
||||
+ else if (rr.rtype == qtype
|
||||
+ && __ns_samebinaryname (rr.rname, expected_name)
|
||||
+ && rr.rdlength == rrtype_to_rdata_length (qtype))
|
||||
{
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
+ /* Make a copy of the address and store it. Increase the
|
||||
+ alignment to 4, in case there are applications out there
|
||||
+ that expect at least this level of address alignment. */
|
||||
+ ptrlist_add (addresses, (char *) alloc_buffer_next (abuf, uint32_t));
|
||||
+ alloc_buffer_copy_bytes (abuf, rr.rdata, rr.rdlength);
|
||||
}
|
||||
-
|
||||
- switch (type)
|
||||
- {
|
||||
- case T_A:
|
||||
- case T_AAAA:
|
||||
- if (__glibc_unlikely (__strcasecmp (result->h_name, bp) != 0))
|
||||
- {
|
||||
- cp += n;
|
||||
- continue; /* XXX - had_error++ ? */
|
||||
- }
|
||||
-
|
||||
- /* Stop parsing at a record whose length is incorrect. */
|
||||
- if (n != rrtype_to_rdata_length (type))
|
||||
- {
|
||||
- ++had_error;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- /* Skip records of the wrong type. */
|
||||
- if (n != result->h_length)
|
||||
- {
|
||||
- cp += n;
|
||||
- continue;
|
||||
- }
|
||||
- if (!haveanswer)
|
||||
- {
|
||||
- int nn;
|
||||
-
|
||||
- /* We compose a single hostent out of the entire chain of
|
||||
- entries, so the TTL of the hostent is essentially the lowest
|
||||
- TTL in the chain. */
|
||||
- if (ttlp != NULL && ttl < *ttlp)
|
||||
- *ttlp = ttl;
|
||||
- if (canonp != NULL)
|
||||
- *canonp = bp;
|
||||
- result->h_name = bp;
|
||||
- nn = strlen (bp) + 1; /* for the \0 */
|
||||
- bp += nn;
|
||||
- linebuflen -= nn;
|
||||
- }
|
||||
-
|
||||
- /* Provide sufficient alignment for both address
|
||||
- families. */
|
||||
- enum { align = 4 };
|
||||
- _Static_assert ((align % __alignof__ (struct in_addr)) == 0,
|
||||
- "struct in_addr alignment");
|
||||
- _Static_assert ((align % __alignof__ (struct in6_addr)) == 0,
|
||||
- "struct in6_addr alignment");
|
||||
- {
|
||||
- char *new_bp = PTR_ALIGN_UP (bp, align);
|
||||
- linebuflen -= new_bp - bp;
|
||||
- bp = new_bp;
|
||||
- }
|
||||
-
|
||||
- if (__glibc_unlikely (n > linebuflen))
|
||||
- goto too_small;
|
||||
- bp = __mempcpy (*hap++ = bp, cp, n);
|
||||
- cp += n;
|
||||
- linebuflen -= n;
|
||||
- break;
|
||||
- default:
|
||||
- abort ();
|
||||
- }
|
||||
- if (had_error == 0)
|
||||
- ++haveanswer;
|
||||
}
|
||||
|
||||
- if (haveanswer > 0)
|
||||
+ if (ptrlist_size (addresses) == 0)
|
||||
{
|
||||
- *ap = NULL;
|
||||
- *hap = NULL;
|
||||
- /*
|
||||
- * Note: we sort even if host can take only one address
|
||||
- * in its return structures - should give it the "best"
|
||||
- * address in that case, not some random one
|
||||
- */
|
||||
- if (haveanswer > 1 && qtype == T_A
|
||||
- && __resolv_context_sort_count (ctx) > 0)
|
||||
- addrsort (ctx, host_data->h_addr_ptrs, haveanswer);
|
||||
-
|
||||
- if (result->h_name == NULL)
|
||||
- {
|
||||
- n = strlen (qname) + 1; /* For the \0. */
|
||||
- if (n > linebuflen)
|
||||
- goto too_small;
|
||||
- if (n >= MAXHOSTNAMELEN)
|
||||
- goto no_recovery;
|
||||
- result->h_name = bp;
|
||||
- bp = __mempcpy (bp, qname, n); /* Cannot overflow. */
|
||||
- linebuflen -= n;
|
||||
- }
|
||||
+ /* No address record found. */
|
||||
+ if (ttlp != NULL)
|
||||
+ /* No caching of negative responses. */
|
||||
+ *ttlp = 0;
|
||||
|
||||
+ *h_errnop = NO_RECOVERY;
|
||||
+ *errnop = ENOENT;
|
||||
+ return NSS_STATUS_TRYAGAIN;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
*h_errnop = NETDB_SUCCESS;
|
||||
return NSS_STATUS_SUCCESS;
|
||||
}
|
||||
- no_recovery:
|
||||
- *h_errnop = NO_RECOVERY;
|
||||
- *errnop = ENOENT;
|
||||
- /* Special case here: if the resolver sent a result but it only
|
||||
- contains a CNAME while we are looking for a T_A or T_AAAA record,
|
||||
- we fail with NOTFOUND instead of TRYAGAIN. */
|
||||
- return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases
|
||||
- ? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN);
|
||||
}
|
||||
|
||||
static enum nss_status
|
@ -0,0 +1,51 @@
|
||||
commit c36e7cca3571b0c92b09409c1df86a142596c210
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
nss_dns: In gaih_getanswer_slice, skip strange aliases (bug 12154)
|
||||
|
||||
If the name is not a host name, skip adding it to the result, instead
|
||||
of reporting query failure. This fixes bug 12154 for getaddrinfo.
|
||||
|
||||
This commit still keeps the old parsing code, and only adjusts when
|
||||
a host name is copied.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 32b599ac8c21c4c332cc3900a792a1395bca79c7)
|
||||
|
||||
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
|
||||
index 10c21e1e827cde12..1cb3be71f04d98eb 100644
|
||||
--- a/resolv/nss_dns/dns-host.c
|
||||
+++ b/resolv/nss_dns/dns-host.c
|
||||
@@ -971,12 +971,12 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
|
||||
n = -1;
|
||||
}
|
||||
- if (__glibc_unlikely (n < 0 || __libc_res_hnok (buffer) == 0))
|
||||
+ if (__glibc_unlikely (n < 0))
|
||||
{
|
||||
++had_error;
|
||||
continue;
|
||||
}
|
||||
- if (*firstp && canon == NULL)
|
||||
+ if (*firstp && canon == NULL && __libc_res_hnok (buffer))
|
||||
{
|
||||
h_name = buffer;
|
||||
buffer += h_namelen;
|
||||
@@ -1022,14 +1022,14 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||||
|
||||
n = __libc_dn_expand (answer->buf, end_of_message, cp,
|
||||
tbuf, sizeof tbuf);
|
||||
- if (__glibc_unlikely (n < 0 || __libc_res_hnok (tbuf) == 0))
|
||||
+ if (__glibc_unlikely (n < 0))
|
||||
{
|
||||
++had_error;
|
||||
continue;
|
||||
}
|
||||
cp += n;
|
||||
|
||||
- if (*firstp)
|
||||
+ if (*firstp && __libc_res_hnok (tbuf))
|
||||
{
|
||||
/* Reclaim buffer space. */
|
||||
if (h_name + h_namelen == buffer)
|
@ -0,0 +1,449 @@
|
||||
commit 480c820493add16e8dda6f3189d834223e1f4f39
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Aug 30 10:02:49 2022 +0200
|
||||
|
||||
resolv: Add new tst-resolv-invalid-cname
|
||||
|
||||
This test checks resolution through CNAME chains that do not contain
|
||||
host names (bug 12154).
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 9caf782276ecea4bc86fc94fbb52779736f3106d)
|
||||
|
||||
Conflicts:
|
||||
resolv/Makefile
|
||||
(usual test differences)
|
||||
|
||||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||||
index fded244d61068060..ea1518ec2da860c1 100644
|
||||
--- a/resolv/Makefile
|
||||
+++ b/resolv/Makefile
|
||||
@@ -99,6 +99,7 @@ tests += \
|
||||
tst-resolv-binary \
|
||||
tst-resolv-byaddr \
|
||||
tst-resolv-edns \
|
||||
+ tst-resolv-invalid-cname \
|
||||
tst-resolv-network \
|
||||
tst-resolv-noaaaa \
|
||||
tst-resolv-nondecimal \
|
||||
@@ -279,6 +280,8 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \
|
||||
$(objpfx)tst-resolv-res_init-thread: $(objpfx)libresolv.so \
|
||||
$(shared-thread-library)
|
||||
$(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library)
|
||||
+$(objpfx)tst-resolv-invalid-cname: $(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)
|
||||
diff --git a/resolv/tst-resolv-invalid-cname.c b/resolv/tst-resolv-invalid-cname.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..ae2d4419b1978c02
|
||||
--- /dev/null
|
||||
+++ b/resolv/tst-resolv-invalid-cname.c
|
||||
@@ -0,0 +1,406 @@
|
||||
+/* Test handling of CNAMEs with non-host domain names (bug 12154).
|
||||
+ Copyright (C) 2022 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 <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/check_nss.h>
|
||||
+#include <support/resolv_test.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/xmemstream.h>
|
||||
+
|
||||
+/* Query strings describe the CNAME chain in the response. They have
|
||||
+ the format "bitsBITS.countCOUNT.example.", where BITS and COUNT are
|
||||
+ replaced by unsigned decimal numbers. COUNT is the number of CNAME
|
||||
+ records in the response. BITS has two bits for each CNAME record,
|
||||
+ describing a special prefix that is added to that CNAME.
|
||||
+
|
||||
+ 0: No special leading label.
|
||||
+ 1: Starting with "*.".
|
||||
+ 2: Starting with "-x.".
|
||||
+ 3: Starting with "star.*.".
|
||||
+
|
||||
+ The first CNAME in the response using the two least significant
|
||||
+ bits.
|
||||
+
|
||||
+ For PTR queries, the QNAME format is different, it is either
|
||||
+ COUNT.BITS.168.192.in-addr.arpa. (with BITS and COUNT still
|
||||
+ decimal), or:
|
||||
+
|
||||
+COUNT.BITS0.BITS1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.
|
||||
+
|
||||
+ where BITS and COUNT are hexadecimal. */
|
||||
+
|
||||
+static void
|
||||
+response (const struct resolv_response_context *ctx,
|
||||
+ struct resolv_response_builder *b,
|
||||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||||
+{
|
||||
+ TEST_COMPARE (qclass, C_IN);
|
||||
+
|
||||
+ /* The only other query type besides A is PTR. */
|
||||
+ if (qtype != T_A && qtype != T_AAAA)
|
||||
+ TEST_COMPARE (qtype, T_PTR);
|
||||
+
|
||||
+ unsigned int bits, bits1, count;
|
||||
+ char *tail = NULL;
|
||||
+ if (sscanf (qname, "bits%u.count%u.%ms", &bits, &count, &tail) == 3)
|
||||
+ TEST_COMPARE_STRING (tail, "example");
|
||||
+ else if (strstr (qname, "in-addr.arpa") != NULL
|
||||
+ && sscanf (qname, "%u.%u.%ms", &bits, &count, &tail) == 3)
|
||||
+ TEST_COMPARE_STRING (tail, "168.192.in-addr.arpa");
|
||||
+ else if (sscanf (qname, "%x.%x.%x.%ms", &bits, &bits1, &count, &tail) == 4)
|
||||
+ {
|
||||
+ TEST_COMPARE_STRING (tail, "\
|
||||
+0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa");
|
||||
+ bits |= bits1 << 4;
|
||||
+ }
|
||||
+ else
|
||||
+ FAIL_EXIT1 ("invalid QNAME: %s\n", qname);
|
||||
+ free (tail);
|
||||
+
|
||||
+ 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);
|
||||
+
|
||||
+ /* Provide the requested number of CNAME records. */
|
||||
+ char *previous_name = (char *) qname;
|
||||
+ unsigned int original_bits = bits;
|
||||
+ for (int unique = 0; unique < count; ++unique)
|
||||
+ {
|
||||
+ resolv_response_open_record (b, previous_name, qclass, T_CNAME, 60);
|
||||
+
|
||||
+ static const char bits_to_prefix[4][8] = { "", "*.", "-x.", "star.*." };
|
||||
+ char *new_name = xasprintf ("%sunique%d.example",
|
||||
+ bits_to_prefix[bits & 3], unique);
|
||||
+ bits >>= 2;
|
||||
+ resolv_response_add_name (b, new_name);
|
||||
+ resolv_response_close_record (b);
|
||||
+
|
||||
+ if (previous_name != qname)
|
||||
+ free (previous_name);
|
||||
+ previous_name = new_name;
|
||||
+ }
|
||||
+
|
||||
+ /* Actual answer record. */
|
||||
+ resolv_response_open_record (b, previous_name, qclass, qtype, 60);
|
||||
+ switch (qtype)
|
||||
+ {
|
||||
+ case T_A:
|
||||
+ {
|
||||
+ char ipv4[4] = {192, 168, count, original_bits};
|
||||
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
|
||||
+ }
|
||||
+ break;
|
||||
+ case T_AAAA:
|
||||
+ {
|
||||
+ char ipv6[16] =
|
||||
+ {
|
||||
+ 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
+ count, original_bits
|
||||
+ };
|
||||
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
|
||||
+ }
|
||||
+ break;
|
||||
+
|
||||
+ case T_PTR:
|
||||
+ {
|
||||
+ char *name = xasprintf ("bits%u.count%u.example",
|
||||
+ original_bits, count);
|
||||
+ resolv_response_add_name (b, name);
|
||||
+ free (name);
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ resolv_response_close_record (b);
|
||||
+
|
||||
+ if (previous_name != qname)
|
||||
+ free (previous_name);
|
||||
+}
|
||||
+
|
||||
+/* Controls which name resolution function is invoked. */
|
||||
+enum test_mode
|
||||
+ {
|
||||
+ byname, /* gethostbyname. */
|
||||
+ byname2, /* gethostbyname2. */
|
||||
+ gai, /* getaddrinfo without AI_CANONNAME. */
|
||||
+ gai_canon, /* getaddrinfo with AI_CANONNAME. */
|
||||
+
|
||||
+ test_mode_num /* Number of enum values. */
|
||||
+ };
|
||||
+
|
||||
+static const char *
|
||||
+test_mode_to_string (enum test_mode mode)
|
||||
+{
|
||||
+ switch (mode)
|
||||
+ {
|
||||
+ case byname:
|
||||
+ return "byname";
|
||||
+ case byname2:
|
||||
+ return "byname2";
|
||||
+ case gai:
|
||||
+ return "gai";
|
||||
+ case gai_canon:
|
||||
+ return "gai_canon";
|
||||
+ case test_mode_num:
|
||||
+ /* Report error below. */
|
||||
+ }
|
||||
+ FAIL_EXIT1 ("invalid test_mode: %d", mode);
|
||||
+}
|
||||
+
|
||||
+/* Append the name and aliases to OUT. */
|
||||
+static void
|
||||
+append_names (FILE *out, const char *qname, int bits, int count,
|
||||
+ enum test_mode mode)
|
||||
+{
|
||||
+ /* Largest valid index which has a corresponding zero in bits
|
||||
+ (meaning a syntactically valid CNAME). */
|
||||
+ int last_valid_cname = -1;
|
||||
+
|
||||
+ for (int i = 0; i < count; ++i)
|
||||
+ if ((bits & (3 << (i * 2))) == 0)
|
||||
+ last_valid_cname = i;
|
||||
+
|
||||
+ if (mode != gai)
|
||||
+ {
|
||||
+ const char *label;
|
||||
+ if (mode == gai_canon)
|
||||
+ label = "canonname";
|
||||
+ else
|
||||
+ label = "name";
|
||||
+ if (last_valid_cname >= 0)
|
||||
+ fprintf (out, "%s: unique%d.example\n", label, last_valid_cname);
|
||||
+ else
|
||||
+ fprintf (out, "%s: %s\n", label, qname);
|
||||
+ }
|
||||
+
|
||||
+ if (mode == byname || mode == byname2)
|
||||
+ {
|
||||
+ if (last_valid_cname >= 0)
|
||||
+ fprintf (out, "alias: %s\n", qname);
|
||||
+ for (int i = 0; i < count; ++i)
|
||||
+ {
|
||||
+ if ((bits & (3 << (i * 2))) == 0 && i != last_valid_cname)
|
||||
+ fprintf (out, "alias: unique%d.example\n", i);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Append the address information to OUT. */
|
||||
+static void
|
||||
+append_addresses (FILE *out, int af, int bits, int count, enum test_mode mode)
|
||||
+{
|
||||
+ int last = count * 256 + bits;
|
||||
+ if (mode == gai || mode == gai_canon)
|
||||
+ {
|
||||
+ if (af == AF_INET || af == AF_UNSPEC)
|
||||
+ fprintf (out, "address: STREAM/TCP 192.168.%d.%d 80\n", count, bits);
|
||||
+ if (af == AF_INET6 || af == AF_UNSPEC)
|
||||
+ {
|
||||
+ if (last == 0)
|
||||
+ fprintf (out, "address: STREAM/TCP 2001:db8:: 80\n");
|
||||
+ else
|
||||
+ fprintf (out, "address: STREAM/TCP 2001:db8::%x 80\n", last);
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ TEST_VERIFY (af != AF_UNSPEC);
|
||||
+ if (af == AF_INET)
|
||||
+ fprintf (out, "address: 192.168.%d.%d\n", count, bits);
|
||||
+ if (af == AF_INET6)
|
||||
+ {
|
||||
+ if (last == 0)
|
||||
+ fprintf (out, "address: 2001:db8::\n");
|
||||
+ else
|
||||
+ fprintf (out, "address: 2001:db8::%x\n", last);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Perform one test using a forward lookup. */
|
||||
+static void
|
||||
+check_forward (int af, int bits, int count, enum test_mode mode)
|
||||
+{
|
||||
+ char *qname = xasprintf ("bits%d.count%d.example", bits, count);
|
||||
+ char *label = xasprintf ("af=%d bits=%d count=%d mode=%s qname=%s",
|
||||
+ af, bits, count, test_mode_to_string (mode), qname);
|
||||
+
|
||||
+ struct xmemstream expected;
|
||||
+ xopen_memstream (&expected);
|
||||
+ if (mode == gai_canon)
|
||||
+ fprintf (expected.out, "flags: AI_CANONNAME\n");
|
||||
+ append_names (expected.out, qname, bits, count, mode);
|
||||
+ append_addresses (expected.out, af, bits, count, mode);
|
||||
+ xfclose_memstream (&expected);
|
||||
+
|
||||
+ if (mode == gai || mode == gai_canon)
|
||||
+ {
|
||||
+ struct addrinfo *ai;
|
||||
+ struct addrinfo hints =
|
||||
+ {
|
||||
+ .ai_family = af,
|
||||
+ .ai_socktype = SOCK_STREAM,
|
||||
+ };
|
||||
+ if (mode == gai_canon)
|
||||
+ hints.ai_flags |= AI_CANONNAME;
|
||||
+ int ret = getaddrinfo (qname, "80", &hints, &ai);
|
||||
+ check_addrinfo (label, ai, ret, expected.buffer);
|
||||
+ if (ret == 0)
|
||||
+ freeaddrinfo (ai);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ struct hostent *e;
|
||||
+ if (mode == gai)
|
||||
+ {
|
||||
+ TEST_COMPARE (af, AF_INET);
|
||||
+ e = gethostbyname (qname);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (af != AF_INET)
|
||||
+ TEST_COMPARE (af, AF_INET6);
|
||||
+ e = gethostbyname2 (qname, af);
|
||||
+ }
|
||||
+ check_hostent (label, e, expected.buffer);
|
||||
+ }
|
||||
+
|
||||
+ free (expected.buffer);
|
||||
+ free (label);
|
||||
+ free (qname);
|
||||
+}
|
||||
+
|
||||
+/* Perform one check using a reverse lookup. */
|
||||
+
|
||||
+static void
|
||||
+check_reverse (int af, int bits, int count)
|
||||
+{
|
||||
+ TEST_VERIFY (af == AF_INET || af == AF_INET6);
|
||||
+
|
||||
+ char *label = xasprintf ("af=%d bits=%d count=%d", af, bits, count);
|
||||
+ char *fqdn = xasprintf ("bits%d.count%d.example", bits, count);
|
||||
+
|
||||
+ struct xmemstream expected;
|
||||
+ xopen_memstream (&expected);
|
||||
+ fprintf (expected.out, "name: %s\n", fqdn);
|
||||
+ append_addresses (expected.out, af, bits, count, byname);
|
||||
+ xfclose_memstream (&expected);
|
||||
+
|
||||
+ char addr[16] = { 0 };
|
||||
+ socklen_t addrlen;
|
||||
+ if (af == AF_INET)
|
||||
+ {
|
||||
+ addr[0] = 192;
|
||||
+ addr[1] = 168;
|
||||
+ addr[2] = count;
|
||||
+ addr[3] = bits;
|
||||
+ addrlen = 4;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ addr[0] = 0x20;
|
||||
+ addr[1] = 0x01;
|
||||
+ addr[2] = 0x0d;
|
||||
+ addr[3] = 0xb8;
|
||||
+ addr[14] = count;
|
||||
+ addr[15] = bits;
|
||||
+ addrlen = 16;
|
||||
+ }
|
||||
+
|
||||
+ struct hostent *e = gethostbyaddr (addr, addrlen, af);
|
||||
+ check_hostent (label, e, expected.buffer);
|
||||
+
|
||||
+ /* getnameinfo check is different. There is no generic check_*
|
||||
+ function for it. */
|
||||
+ {
|
||||
+ struct sockaddr_in sin = { };
|
||||
+ struct sockaddr_in6 sin6 = { };
|
||||
+ void *sa;
|
||||
+ socklen_t salen;
|
||||
+ if (af == AF_INET)
|
||||
+ {
|
||||
+ sin.sin_family = AF_INET;
|
||||
+ memcpy (&sin.sin_addr, addr, addrlen);
|
||||
+ sin.sin_port = htons (80);
|
||||
+ sa = &sin;
|
||||
+ salen = sizeof (sin);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ sin6.sin6_family = AF_INET6;
|
||||
+ memcpy (&sin6.sin6_addr, addr, addrlen);
|
||||
+ sin6.sin6_port = htons (80);
|
||||
+ sa = &sin6;
|
||||
+ salen = sizeof (sin6);
|
||||
+ }
|
||||
+
|
||||
+ char host[64];
|
||||
+ char service[64];
|
||||
+ int ret = getnameinfo (sa, salen, host,
|
||||
+ sizeof (host), service, sizeof (service),
|
||||
+ NI_NAMEREQD | NI_NUMERICSERV);
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ TEST_COMPARE_STRING (host, fqdn);
|
||||
+ TEST_COMPARE_STRING (service, "80");
|
||||
+ }
|
||||
+
|
||||
+ free (expected.buffer);
|
||||
+ free (fqdn);
|
||||
+ free (label);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ struct resolv_test *obj = resolv_test_start
|
||||
+ ((struct resolv_redirect_config)
|
||||
+ {
|
||||
+ .response_callback = response
|
||||
+ });
|
||||
+
|
||||
+ for (int count = 0; count <= 3; ++count)
|
||||
+ for (int bits = 0; bits <= 1 << (count * 2); ++bits)
|
||||
+ {
|
||||
+ if (count > 0 && bits == count)
|
||||
+ /* The last bits value is only checked if count == 0. */
|
||||
+ continue;
|
||||
+
|
||||
+ for (enum test_mode mode = 0; mode < test_mode_num; ++mode)
|
||||
+ {
|
||||
+ check_forward (AF_INET, bits, count, mode);
|
||||
+ if (mode != byname)
|
||||
+ check_forward (AF_INET6, bits, count, mode);
|
||||
+ if (mode == gai || mode == gai_canon)
|
||||
+ check_forward (AF_UNSPEC, bits, count, mode);
|
||||
+ }
|
||||
+
|
||||
+ check_reverse (AF_INET, bits, count);
|
||||
+ check_reverse (AF_INET6, bits, count);
|
||||
+ }
|
||||
+
|
||||
+ resolv_test_end (obj);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
@ -0,0 +1,33 @@
|
||||
commit a2e259014f8a0e5f3ff938314f3087b74255804d
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Thu Nov 11 06:31:51 2021 -0800
|
||||
|
||||
Avoid extra load with CAS in __pthread_mutex_lock_full [BZ #28537]
|
||||
|
||||
Replace boolean CAS with value CAS to avoid the extra load.
|
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
(cherry picked from commit 0b82747dc48d5bf0871bdc6da8cb6eec1256355f)
|
||||
|
||||
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
|
||||
index da624f322d06d0ee..a04e0158451c8fff 100644
|
||||
--- a/nptl/pthread_mutex_lock.c
|
||||
+++ b/nptl/pthread_mutex_lock.c
|
||||
@@ -298,12 +298,12 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
|
||||
meantime. */
|
||||
if ((oldval & FUTEX_WAITERS) == 0)
|
||||
{
|
||||
- if (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock,
|
||||
- oldval | FUTEX_WAITERS,
|
||||
- oldval)
|
||||
- != 0)
|
||||
+ int val;
|
||||
+ if ((val = atomic_compare_and_exchange_val_acq
|
||||
+ (&mutex->__data.__lock, oldval | FUTEX_WAITERS,
|
||||
+ oldval)) != oldval)
|
||||
{
|
||||
- oldval = mutex->__data.__lock;
|
||||
+ oldval = val;
|
||||
continue;
|
||||
}
|
||||
oldval |= FUTEX_WAITERS;
|
@ -0,0 +1,33 @@
|
||||
commit ed8300c054cae4aeb0bbfa043f5fccc91a4adbf5
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Thu Nov 11 06:54:01 2021 -0800
|
||||
|
||||
Avoid extra load with CAS in __pthread_mutex_clocklock_common [BZ #28537]
|
||||
|
||||
Replace boolean CAS with value CAS to avoid the extra load.
|
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
(cherry picked from commit 49302b8fdf9103b6fc0a398678668a22fa19574c)
|
||||
|
||||
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
|
||||
index 11ad7005d07afc6e..90cede9446e33fcf 100644
|
||||
--- a/nptl/pthread_mutex_timedlock.c
|
||||
+++ b/nptl/pthread_mutex_timedlock.c
|
||||
@@ -234,12 +234,12 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,
|
||||
meantime. */
|
||||
if ((oldval & FUTEX_WAITERS) == 0)
|
||||
{
|
||||
- if (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock,
|
||||
- oldval | FUTEX_WAITERS,
|
||||
- oldval)
|
||||
- != 0)
|
||||
+ int val;
|
||||
+ if ((val = atomic_compare_and_exchange_val_acq
|
||||
+ (&mutex->__data.__lock, oldval | FUTEX_WAITERS,
|
||||
+ oldval)) != oldval)
|
||||
{
|
||||
- oldval = mutex->__data.__lock;
|
||||
+ oldval = val;
|
||||
continue;
|
||||
}
|
||||
oldval |= FUTEX_WAITERS;
|
@ -0,0 +1,46 @@
|
||||
commit a6b81f605dfba8650ea1f80122f41eb8e6c73dc7
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Tue Nov 2 18:33:07 2021 -0700
|
||||
|
||||
Add LLL_MUTEX_READ_LOCK [BZ #28537]
|
||||
|
||||
CAS instruction is expensive. From the x86 CPU's point of view, getting
|
||||
a cache line for writing is more expensive than reading. See Appendix
|
||||
A.2 Spinlock in:
|
||||
|
||||
https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/xeon-lock-scaling-analysis-paper.pdf
|
||||
|
||||
The full compare and swap will grab the cache line exclusive and cause
|
||||
excessive cache line bouncing.
|
||||
|
||||
Add LLL_MUTEX_READ_LOCK to do an atomic load and skip CAS in spinlock
|
||||
loop if compare may fail to reduce cache line bouncing on contended locks.
|
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
(cherry picked from commit d672a98a1af106bd68deb15576710cd61363f7a6)
|
||||
|
||||
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
|
||||
index a04e0158451c8fff..9f40928cc6b9a067 100644
|
||||
--- a/nptl/pthread_mutex_lock.c
|
||||
+++ b/nptl/pthread_mutex_lock.c
|
||||
@@ -65,6 +65,11 @@ lll_mutex_lock_optimized (pthread_mutex_t *mutex)
|
||||
# define PTHREAD_MUTEX_VERSIONS 1
|
||||
#endif
|
||||
|
||||
+#ifndef LLL_MUTEX_READ_LOCK
|
||||
+# define LLL_MUTEX_READ_LOCK(mutex) \
|
||||
+ atomic_load_relaxed (&(mutex)->__data.__lock)
|
||||
+#endif
|
||||
+
|
||||
static int __pthread_mutex_lock_full (pthread_mutex_t *mutex)
|
||||
__attribute_noinline__;
|
||||
|
||||
@@ -142,6 +147,8 @@ PTHREAD_MUTEX_LOCK (pthread_mutex_t *mutex)
|
||||
break;
|
||||
}
|
||||
atomic_spin_nop ();
|
||||
+ if (LLL_MUTEX_READ_LOCK (mutex) != 0)
|
||||
+ continue;
|
||||
}
|
||||
while (LLL_MUTEX_TRYLOCK (mutex) != 0);
|
||||
|
@ -0,0 +1,66 @@
|
||||
commit 6bcfbee7277e4faa4b693bd965931f0d1883005d
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Fri Nov 12 11:47:42 2021 -0800
|
||||
|
||||
Move assignment out of the CAS condition
|
||||
|
||||
Update
|
||||
|
||||
commit 49302b8fdf9103b6fc0a398678668a22fa19574c
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Thu Nov 11 06:54:01 2021 -0800
|
||||
|
||||
Avoid extra load with CAS in __pthread_mutex_clocklock_common [BZ #28537]
|
||||
|
||||
Replace boolean CAS with value CAS to avoid the extra load.
|
||||
|
||||
and
|
||||
|
||||
commit 0b82747dc48d5bf0871bdc6da8cb6eec1256355f
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Thu Nov 11 06:31:51 2021 -0800
|
||||
|
||||
Avoid extra load with CAS in __pthread_mutex_lock_full [BZ #28537]
|
||||
|
||||
Replace boolean CAS with value CAS to avoid the extra load.
|
||||
|
||||
by moving assignment out of the CAS condition.
|
||||
|
||||
(cherry picked from commit 120ac6d238825452e8024e2f627da33b2508dfd3)
|
||||
|
||||
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
|
||||
index 9f40928cc6b9a067..49901ffa0a96d659 100644
|
||||
--- a/nptl/pthread_mutex_lock.c
|
||||
+++ b/nptl/pthread_mutex_lock.c
|
||||
@@ -305,10 +305,9 @@ __pthread_mutex_lock_full (pthread_mutex_t *mutex)
|
||||
meantime. */
|
||||
if ((oldval & FUTEX_WAITERS) == 0)
|
||||
{
|
||||
- int val;
|
||||
- if ((val = atomic_compare_and_exchange_val_acq
|
||||
- (&mutex->__data.__lock, oldval | FUTEX_WAITERS,
|
||||
- oldval)) != oldval)
|
||||
+ int val = atomic_compare_and_exchange_val_acq
|
||||
+ (&mutex->__data.__lock, oldval | FUTEX_WAITERS, oldval);
|
||||
+ if (val != oldval)
|
||||
{
|
||||
oldval = val;
|
||||
continue;
|
||||
diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c
|
||||
index 90cede9446e33fcf..2e5506db06ccb1ec 100644
|
||||
--- a/nptl/pthread_mutex_timedlock.c
|
||||
+++ b/nptl/pthread_mutex_timedlock.c
|
||||
@@ -234,10 +234,9 @@ __pthread_mutex_clocklock_common (pthread_mutex_t *mutex,
|
||||
meantime. */
|
||||
if ((oldval & FUTEX_WAITERS) == 0)
|
||||
{
|
||||
- int val;
|
||||
- if ((val = atomic_compare_and_exchange_val_acq
|
||||
- (&mutex->__data.__lock, oldval | FUTEX_WAITERS,
|
||||
- oldval)) != oldval)
|
||||
+ int val = atomic_compare_and_exchange_val_acq
|
||||
+ (&mutex->__data.__lock, oldval | FUTEX_WAITERS, oldval);
|
||||
+ if (val != oldval)
|
||||
{
|
||||
oldval = val;
|
||||
continue;
|
@ -0,0 +1,38 @@
|
||||
commit 43760d33d78f9ea8c8af942b570112ee801b99df
|
||||
Author: Jangwoong Kim <6812skiii@gmail.com>
|
||||
Date: Tue Dec 14 21:30:51 2021 +0900
|
||||
|
||||
nptl: Effectively skip CAS in spinlock loop
|
||||
|
||||
The commit:
|
||||
"Add LLL_MUTEX_READ_LOCK [BZ #28537]"
|
||||
SHA1: d672a98a1af106bd68deb15576710cd61363f7a6
|
||||
|
||||
introduced LLL_MUTEX_READ_LOCK, to skip CAS in spinlock loop
|
||||
if atomic load fails. But, "continue" inside of do-while loop
|
||||
does not skip the evaluation of escape expression, thus CAS
|
||||
is not skipped.
|
||||
|
||||
Replace do-while with while and skip LLL_MUTEX_TRYLOCK if
|
||||
LLL_MUTEX_READ_LOCK fails.
|
||||
|
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
(cherry picked from commit 6b8dbbd03ac88f169b65b5c7d7278576a11d2e44)
|
||||
|
||||
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
|
||||
index 49901ffa0a96d659..bbe754a272b97d91 100644
|
||||
--- a/nptl/pthread_mutex_lock.c
|
||||
+++ b/nptl/pthread_mutex_lock.c
|
||||
@@ -147,10 +147,9 @@ PTHREAD_MUTEX_LOCK (pthread_mutex_t *mutex)
|
||||
break;
|
||||
}
|
||||
atomic_spin_nop ();
|
||||
- if (LLL_MUTEX_READ_LOCK (mutex) != 0)
|
||||
- continue;
|
||||
}
|
||||
- while (LLL_MUTEX_TRYLOCK (mutex) != 0);
|
||||
+ while (LLL_MUTEX_READ_LOCK (mutex) != 0
|
||||
+ || LLL_MUTEX_TRYLOCK (mutex) != 0);
|
||||
|
||||
mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8;
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
commit 04efdcfac405723c23b25d124817bcfc1697e2d8
|
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Wed Apr 27 15:13:02 2022 -0500
|
||||
|
||||
sysdeps: Add 'get_fast_jitter' interace in fast-jitter.h
|
||||
|
||||
'get_fast_jitter' is meant to be used purely for performance
|
||||
purposes. In all cases it's used it should be acceptable to get no
|
||||
randomness (see default case). An example use case is in setting
|
||||
jitter for retries between threads at a lock. There is a
|
||||
performance benefit to having jitter, but only if the jitter can
|
||||
be generated very quickly and ultimately there is no serious issue
|
||||
if no jitter is generated.
|
||||
|
||||
The implementation generally uses 'HP_TIMING_NOW' iff it is
|
||||
inlined (avoid any potential syscall paths).
|
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
|
||||
(cherry picked from commit 911c63a51c690dd1a97dfc587097277029baf00f)
|
||||
|
||||
diff --git a/sysdeps/generic/fast-jitter.h b/sysdeps/generic/fast-jitter.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..4dd53e3475c3dfe6
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/generic/fast-jitter.h
|
||||
@@ -0,0 +1,42 @@
|
||||
+/* Fallback for fast jitter just return 0.
|
||||
+ Copyright (C) 2019-2022 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/>. */
|
||||
+
|
||||
+#ifndef _FAST_JITTER_H
|
||||
+# define _FAST_JITTER_H
|
||||
+
|
||||
+# include <stdint.h>
|
||||
+# include <hp-timing.h>
|
||||
+
|
||||
+/* Baseline just return 0. We could create jitter using a clock or
|
||||
+ 'random_bits' but that may imply a syscall and the goal of
|
||||
+ 'get_fast_jitter' is minimal overhead "randomness" when such
|
||||
+ randomness helps performance. Adding high overhead the function
|
||||
+ defeats the purpose. */
|
||||
+static inline uint32_t
|
||||
+get_fast_jitter (void)
|
||||
+{
|
||||
+# if HP_TIMING_INLINE
|
||||
+ hp_timing_t jitter;
|
||||
+ HP_TIMING_NOW (jitter);
|
||||
+ return (uint32_t) jitter;
|
||||
+# else
|
||||
+ return 0;
|
||||
+# endif
|
||||
+}
|
||||
+
|
||||
+#endif
|
@ -0,0 +1,209 @@
|
||||
commit ea69248445fb9b80da02ee0c7261cba4b1a5532e
|
||||
Author: Wangyang Guo <wangyang.guo@intel.com>
|
||||
Date: Fri May 6 01:50:10 2022 +0000
|
||||
|
||||
nptl: Add backoff mechanism to spinlock loop
|
||||
|
||||
When mutiple threads waiting for lock at the same time, once lock owner
|
||||
releases the lock, waiters will see lock available and all try to lock,
|
||||
which may cause an expensive CAS storm.
|
||||
|
||||
Binary exponential backoff with random jitter is introduced. As try-lock
|
||||
attempt increases, there is more likely that a larger number threads
|
||||
compete for adaptive mutex lock, so increase wait time in exponential.
|
||||
A random jitter is also added to avoid synchronous try-lock from other
|
||||
threads.
|
||||
|
||||
v2: Remove read-check before try-lock for performance.
|
||||
|
||||
v3:
|
||||
1. Restore read-check since it works well in some platform.
|
||||
2. Make backoff arch dependent, and enable it for x86_64.
|
||||
3. Limit max backoff to reduce latency in large critical section.
|
||||
|
||||
v4: Fix strict-prototypes error in sysdeps/nptl/pthread_mutex_backoff.h
|
||||
|
||||
v5: Commit log updated for regression in large critical section.
|
||||
|
||||
Result of pthread-mutex-locks bench
|
||||
|
||||
Test Platform: Xeon 8280L (2 socket, 112 CPUs in total)
|
||||
First Row: thread number
|
||||
First Col: critical section length
|
||||
Values: backoff vs upstream, time based, low is better
|
||||
|
||||
non-critical-length: 1
|
||||
1 2 4 8 16 32 64 112 140
|
||||
0 0.99 0.58 0.52 0.49 0.43 0.44 0.46 0.52 0.54
|
||||
1 0.98 0.43 0.56 0.50 0.44 0.45 0.50 0.56 0.57
|
||||
2 0.99 0.41 0.57 0.51 0.45 0.47 0.48 0.60 0.61
|
||||
4 0.99 0.45 0.59 0.53 0.48 0.49 0.52 0.64 0.65
|
||||
8 1.00 0.66 0.71 0.63 0.56 0.59 0.66 0.72 0.71
|
||||
16 0.97 0.78 0.91 0.73 0.67 0.70 0.79 0.80 0.80
|
||||
32 0.95 1.17 0.98 0.87 0.82 0.86 0.89 0.90 0.90
|
||||
64 0.96 0.95 1.01 1.01 0.98 1.00 1.03 0.99 0.99
|
||||
128 0.99 1.01 1.01 1.17 1.08 1.12 1.02 0.97 1.02
|
||||
|
||||
non-critical-length: 32
|
||||
1 2 4 8 16 32 64 112 140
|
||||
0 1.03 0.97 0.75 0.65 0.58 0.58 0.56 0.70 0.70
|
||||
1 0.94 0.95 0.76 0.65 0.58 0.58 0.61 0.71 0.72
|
||||
2 0.97 0.96 0.77 0.66 0.58 0.59 0.62 0.74 0.74
|
||||
4 0.99 0.96 0.78 0.66 0.60 0.61 0.66 0.76 0.77
|
||||
8 0.99 0.99 0.84 0.70 0.64 0.66 0.71 0.80 0.80
|
||||
16 0.98 0.97 0.95 0.76 0.70 0.73 0.81 0.85 0.84
|
||||
32 1.04 1.12 1.04 0.89 0.82 0.86 0.93 0.91 0.91
|
||||
64 0.99 1.15 1.07 1.00 0.99 1.01 1.05 0.99 0.99
|
||||
128 1.00 1.21 1.20 1.22 1.25 1.31 1.12 1.10 0.99
|
||||
|
||||
non-critical-length: 128
|
||||
1 2 4 8 16 32 64 112 140
|
||||
0 1.02 1.00 0.99 0.67 0.61 0.61 0.61 0.74 0.73
|
||||
1 0.95 0.99 1.00 0.68 0.61 0.60 0.60 0.74 0.74
|
||||
2 1.00 1.04 1.00 0.68 0.59 0.61 0.65 0.76 0.76
|
||||
4 1.00 0.96 0.98 0.70 0.63 0.63 0.67 0.78 0.77
|
||||
8 1.01 1.02 0.89 0.73 0.65 0.67 0.71 0.81 0.80
|
||||
16 0.99 0.96 0.96 0.79 0.71 0.73 0.80 0.84 0.84
|
||||
32 0.99 0.95 1.05 0.89 0.84 0.85 0.94 0.92 0.91
|
||||
64 1.00 0.99 1.16 1.04 1.00 1.02 1.06 0.99 0.99
|
||||
128 1.00 1.06 0.98 1.14 1.39 1.26 1.08 1.02 0.98
|
||||
|
||||
There is regression in large critical section. But adaptive mutex is
|
||||
aimed for "quick" locks. Small critical section is more common when
|
||||
users choose to use adaptive pthread_mutex.
|
||||
|
||||
Signed-off-by: Wangyang Guo <wangyang.guo@intel.com>
|
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
(cherry picked from commit 8162147872491bb5b48e91543b19c49a29ae6b6d)
|
||||
|
||||
diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c
|
||||
index bbe754a272b97d91..8f3f687f2a151d16 100644
|
||||
--- a/nptl/pthread_mutex_lock.c
|
||||
+++ b/nptl/pthread_mutex_lock.c
|
||||
@@ -139,14 +139,26 @@ PTHREAD_MUTEX_LOCK (pthread_mutex_t *mutex)
|
||||
int cnt = 0;
|
||||
int max_cnt = MIN (max_adaptive_count (),
|
||||
mutex->__data.__spins * 2 + 10);
|
||||
+ int spin_count, exp_backoff = 1;
|
||||
+ unsigned int jitter = get_jitter ();
|
||||
do
|
||||
{
|
||||
- if (cnt++ >= max_cnt)
|
||||
+ /* In each loop, spin count is exponential backoff plus
|
||||
+ random jitter, random range is [0, exp_backoff-1]. */
|
||||
+ spin_count = exp_backoff + (jitter & (exp_backoff - 1));
|
||||
+ cnt += spin_count;
|
||||
+ if (cnt >= max_cnt)
|
||||
{
|
||||
+ /* If cnt exceeds max spin count, just go to wait
|
||||
+ queue. */
|
||||
LLL_MUTEX_LOCK (mutex);
|
||||
break;
|
||||
}
|
||||
- atomic_spin_nop ();
|
||||
+ do
|
||||
+ atomic_spin_nop ();
|
||||
+ while (--spin_count > 0);
|
||||
+ /* Prepare for next loop. */
|
||||
+ exp_backoff = get_next_backoff (exp_backoff);
|
||||
}
|
||||
while (LLL_MUTEX_READ_LOCK (mutex) != 0
|
||||
|| LLL_MUTEX_TRYLOCK (mutex) != 0);
|
||||
diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h
|
||||
index b968afc4c6b61b92..ed186ce3df1fde0c 100644
|
||||
--- a/sysdeps/nptl/pthreadP.h
|
||||
+++ b/sysdeps/nptl/pthreadP.h
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <kernel-features.h>
|
||||
#include <errno.h>
|
||||
#include <internal-signals.h>
|
||||
+#include <pthread_mutex_backoff.h>
|
||||
#include "pthread_mutex_conf.h"
|
||||
|
||||
|
||||
diff --git a/sysdeps/nptl/pthread_mutex_backoff.h b/sysdeps/nptl/pthread_mutex_backoff.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..5b26c22ac789f54f
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/nptl/pthread_mutex_backoff.h
|
||||
@@ -0,0 +1,35 @@
|
||||
+/* Pthread mutex backoff configuration.
|
||||
+ Copyright (C) 2022 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/>. */
|
||||
+#ifndef _PTHREAD_MUTEX_BACKOFF_H
|
||||
+#define _PTHREAD_MUTEX_BACKOFF_H 1
|
||||
+
|
||||
+static inline unsigned int
|
||||
+get_jitter (void)
|
||||
+{
|
||||
+ /* Arch dependent random jitter, return 0 disables random. */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static inline int
|
||||
+get_next_backoff (int backoff)
|
||||
+{
|
||||
+ /* Next backoff, return 1 disables mutex backoff. */
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+#endif
|
||||
diff --git a/sysdeps/x86_64/nptl/pthread_mutex_backoff.h b/sysdeps/x86_64/nptl/pthread_mutex_backoff.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..ec74c3d9db61864e
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/x86_64/nptl/pthread_mutex_backoff.h
|
||||
@@ -0,0 +1,39 @@
|
||||
+/* Pthread mutex backoff configuration.
|
||||
+ Copyright (C) 2022 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/>. */
|
||||
+#ifndef _PTHREAD_MUTEX_BACKOFF_H
|
||||
+#define _PTHREAD_MUTEX_BACKOFF_H 1
|
||||
+
|
||||
+#include <fast-jitter.h>
|
||||
+
|
||||
+static inline unsigned int
|
||||
+get_jitter (void)
|
||||
+{
|
||||
+ return get_fast_jitter ();
|
||||
+}
|
||||
+
|
||||
+#define MAX_BACKOFF 16
|
||||
+
|
||||
+static inline int
|
||||
+get_next_backoff (int backoff)
|
||||
+{
|
||||
+ /* Binary expontial backoff. Limiting max backoff
|
||||
+ can reduce latency in large critical section. */
|
||||
+ return (backoff < MAX_BACKOFF) ? backoff << 1 : backoff;
|
||||
+}
|
||||
+
|
||||
+#endif
|
@ -0,0 +1,26 @@
|
||||
commit 95f5089d4a57cd1e738be908c7a628cb7d0ce512
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86: include BMI1 and BMI2 in x86-64-v3 level
|
||||
|
||||
The "System V Application Binary Interface AMD64 Architecture Processor
|
||||
Supplement" mandates the BMI1 and BMI2 CPU features for the x86-64-v3
|
||||
level.
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit b80f16adbd979831bf25ea491e1261e81885c2b6)
|
||||
|
||||
diff --git a/sysdeps/x86/get-isa-level.h b/sysdeps/x86/get-isa-level.h
|
||||
index aa80f56ca635e54b..785c25a835edf004 100644
|
||||
--- a/sysdeps/x86/get-isa-level.h
|
||||
+++ b/sysdeps/x86/get-isa-level.h
|
||||
@@ -47,6 +47,8 @@ get_isa_level (const struct cpu_features *cpu_features)
|
||||
isa_level |= GNU_PROPERTY_X86_ISA_1_V2;
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, AVX2)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI1)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI2)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, F16C)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, FMA)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, LZCNT)
|
@ -0,0 +1,111 @@
|
||||
commit 414fc856ff4e011e62b88a21d30294637a152dc7
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI2 for AVX2 str(n)casecmp implementations
|
||||
|
||||
The AVX2 str(n)casecmp implementations use the 'bzhi' instruction, which
|
||||
belongs to the BMI2 CPU feature.
|
||||
|
||||
NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF
|
||||
as BSF if the CPU doesn't support TZCNT, and produces the same result
|
||||
for non-zero input.
|
||||
|
||||
Partially fixes: b77b06e0e296 ("x86: Optimize strcmp-avx2.S")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit 10f79d3670b036925da63dc532b122d27ce65ff8)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index 8d649e263eb24b8a..ca64b34c146a76f9 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -386,13 +386,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL (i, name, strcasecmp,
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ && CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strcasecmp_evex)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strcasecmp_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strcasecmp_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
@@ -407,13 +410,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL (i, name, strcasecmp_l,
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ && CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strcasecmp_l_evex)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strcasecmp_l_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strcasecmp_l_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strcasecmp_l,
|
||||
@@ -542,13 +548,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL (i, name, strncasecmp,
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ && CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strncasecmp_evex)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strncasecmp_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strncasecmp_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
@@ -564,13 +573,16 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
IFUNC_IMPL (i, name, strncasecmp_l,
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ & CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strncasecmp_l_evex)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strncasecmp_l_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strncasecmp_l_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strncasecmp_l,
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h b/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h
|
||||
index 40819caf5ab10337..e61d6e9497bce9d9 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-strcasecmp.h
|
||||
@@ -32,6 +32,7 @@ IFUNC_SELECTOR (void)
|
||||
const struct cpu_features* cpu_features = __get_cpu_features ();
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX2)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI2)
|
||||
&& CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load))
|
||||
{
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL)
|
@ -0,0 +1,55 @@
|
||||
commit e1561d8cf005a23bcaf514802854b493829a25b1
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI2 for AVX2 strcmp implementation
|
||||
|
||||
The AVX2 strcmp implementation uses the 'bzhi' instruction, which
|
||||
belongs to the BMI2 CPU feature.
|
||||
|
||||
NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF
|
||||
as BSF if the CPU doesn't support TZCNT, and produces the same result
|
||||
for non-zero input.
|
||||
|
||||
Partially fixes: b77b06e0e296 ("x86: Optimize strcmp-avx2.S")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit 4d64c6445735e9b34e2ac8e369312cbfc2f88e17)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index ca64b34c146a76f9..70931f15985334af 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -503,10 +503,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/strcmp.c. */
|
||||
IFUNC_IMPL (i, name, strcmp,
|
||||
IFUNC_IMPL_ADD (array, i, strcmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strcmp_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strcmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strcmp_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strcmp,
|
||||
diff --git a/sysdeps/x86_64/multiarch/strcmp.c b/sysdeps/x86_64/multiarch/strcmp.c
|
||||
index b457fb4c150e4407..0c0cd20a03278a2b 100644
|
||||
--- a/sysdeps/x86_64/multiarch/strcmp.c
|
||||
+++ b/sysdeps/x86_64/multiarch/strcmp.c
|
||||
@@ -40,11 +40,11 @@ IFUNC_SELECTOR (void)
|
||||
const struct cpu_features* cpu_features = __get_cpu_features ();
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX2)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI2)
|
||||
&& CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load))
|
||||
{
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL)
|
||||
- && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW)
|
||||
- && CPU_FEATURE_USABLE_P (cpu_features, BMI2))
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW))
|
||||
return OPTIMIZE (evex);
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, RTM))
|
@ -0,0 +1,62 @@
|
||||
commit b9cbb8dd48b545f3b36b5d411481dc0bd118ee94
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI2 for AVX2 strncmp implementation
|
||||
|
||||
The AVX2 strncmp implementations uses the 'bzhi' instruction, which
|
||||
belongs to the BMI2 CPU feature.
|
||||
|
||||
NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF
|
||||
as BSF if the CPU doesn't support TZCNT, and produces the same result
|
||||
for non-zero input.
|
||||
|
||||
Partially fixes: b77b06e0e296 ("x86: Optimize strcmp-avx2.S")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit fc7de1d9b99ae1676bc626ddca422d7abee0eb48)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index 70931f15985334af..34d5f6efe5421014 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -1022,15 +1022,18 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/strncmp.c. */
|
||||
IFUNC_IMPL (i, name, strncmp,
|
||||
IFUNC_IMPL_ADD (array, i, strncmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strncmp_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strncmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strncmp_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strncmp,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ && CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strncmp_evex)
|
||||
IFUNC_IMPL_ADD (array, i, strncmp, CPU_FEATURE_USABLE (SSE4_2),
|
||||
__strncmp_sse42)
|
||||
diff --git a/sysdeps/x86_64/multiarch/strncmp.c b/sysdeps/x86_64/multiarch/strncmp.c
|
||||
index f94a421784bfe923..7632d7b2dd4447aa 100644
|
||||
--- a/sysdeps/x86_64/multiarch/strncmp.c
|
||||
+++ b/sysdeps/x86_64/multiarch/strncmp.c
|
||||
@@ -39,11 +39,11 @@ IFUNC_SELECTOR (void)
|
||||
const struct cpu_features* cpu_features = __get_cpu_features ();
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX2)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI2)
|
||||
&& CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load))
|
||||
{
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL)
|
||||
- && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW)
|
||||
- && CPU_FEATURE_USABLE_P (cpu_features, BMI2))
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, AVX512BW))
|
||||
return OPTIMIZE (evex);
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, RTM))
|
@ -0,0 +1,51 @@
|
||||
commit 67e863742d98c990b3d3b814b80042c0fa0d50a5
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI2 for AVX2 wcs(n)cmp implementations
|
||||
|
||||
The AVX2 wcs(n)cmp implementations use the 'bzhi' instruction, which
|
||||
belongs to the BMI2 CPU feature.
|
||||
|
||||
NB: It also uses the 'tzcnt' BMI1 instruction, but it is executed as BSF
|
||||
as BSF if the CPU doesn't support TZCNT, and produces the same result
|
||||
for non-zero input.
|
||||
|
||||
Partially fixes: b77b06e0e296 ("x86: Optimize strcmp-avx2.S")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit f31a5a884ed84bd37032729d4d1eb9d06c9f3c29)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index 34d5f6efe5421014..e76a991dc671c1a9 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -693,10 +693,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/wcscmp.c. */
|
||||
IFUNC_IMPL (i, name, wcscmp,
|
||||
IFUNC_IMPL_ADD (array, i, wcscmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__wcscmp_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, wcscmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__wcscmp_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, wcscmp,
|
||||
@@ -709,10 +711,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/wcsncmp.c. */
|
||||
IFUNC_IMPL (i, name, wcsncmp,
|
||||
IFUNC_IMPL_ADD (array, i, wcsncmp,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__wcsncmp_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, wcsncmp,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__wcsncmp_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, wcsncmp,
|
@ -0,0 +1,61 @@
|
||||
commit 94b9c1b6409e34f3f0b2339f77d7ee78087422eb
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI2 for AVX2 (raw|w)memchr implementations
|
||||
|
||||
The AVX2 memchr, rawmemchr and wmemchr implementations use the 'bzhi'
|
||||
and 'sarx' instructions, which belongs to the BMI2 CPU feature.
|
||||
|
||||
Fixes: acfd088a1963 ("x86: Optimize memchr-avx2.S")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit e3e7fab7fe5186d18ca2046d99ba321c27db30ad)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index e76a991dc671c1a9..81640cf00664e3ed 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -41,10 +41,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/memchr.c. */
|
||||
IFUNC_IMPL (i, name, memchr,
|
||||
IFUNC_IMPL_ADD (array, i, memchr,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__memchr_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, memchr,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__memchr_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, memchr,
|
||||
@@ -283,10 +285,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/rawmemchr.c. */
|
||||
IFUNC_IMPL (i, name, rawmemchr,
|
||||
IFUNC_IMPL_ADD (array, i, rawmemchr,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__rawmemchr_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, rawmemchr,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__rawmemchr_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, rawmemchr,
|
||||
@@ -787,10 +791,12 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/wmemchr.c. */
|
||||
IFUNC_IMPL (i, name, wmemchr,
|
||||
IFUNC_IMPL_ADD (array, i, wmemchr,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__wmemchr_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, wmemchr,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__wmemchr_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, wmemchr,
|
@ -0,0 +1,56 @@
|
||||
commit 36d6b9be3d7008a78e1f6e2e2db1947b76b206d8
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI2 and LZCNT for AVX2 memrchr implementation
|
||||
|
||||
The AVX2 memrchr implementation uses the 'shlxl' instruction, which
|
||||
belongs to the BMI2 CPU feature and uses the 'lzcnt' instruction, which
|
||||
belongs to the LZCNT CPU feature.
|
||||
|
||||
Fixes: af5306a735eb ("x86: Optimize memrchr-avx2.S")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit 3c0c78afabfed4b6fc161c159e628fbf14ff370b)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-avx2.h b/sysdeps/x86_64/multiarch/ifunc-avx2.h
|
||||
index 6de72f72724b81ba..52bd00ea5cab6b22 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-avx2.h
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-avx2.h
|
||||
@@ -31,6 +31,7 @@ IFUNC_SELECTOR (void)
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX2)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, BMI2)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, LZCNT)
|
||||
&& CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load))
|
||||
{
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX512VL)
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index 81640cf00664e3ed..d1fc1e75d6706413 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -174,15 +174,21 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/memrchr.c. */
|
||||
IFUNC_IMPL (i, name, memrchr,
|
||||
IFUNC_IMPL_ADD (array, i, memrchr,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
+ && CPU_FEATURE_USABLE (LZCNT)),
|
||||
__memrchr_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, memrchr,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
+ && CPU_FEATURE_USABLE (LZCNT)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__memrchr_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, memrchr,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ && CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
+ && CPU_FEATURE_USABLE (LZCNT)),
|
||||
__memrchr_evex)
|
||||
|
||||
IFUNC_IMPL_ADD (array, i, memrchr, 1, __memrchr_sse2))
|
@ -0,0 +1,78 @@
|
||||
commit e570b865b53f33453d97160791a7d97e38bcc6e8
|
||||
Author: Aurelien Jarno <aurelien@aurel32.net>
|
||||
Date: Mon Oct 3 23:16:46 2022 +0200
|
||||
|
||||
x86-64: Require BMI1/BMI2 for AVX2 strrchr and wcsrchr implementations
|
||||
|
||||
The AVX2 strrchr and wcsrchr implementation uses the 'blsmsk'
|
||||
instruction which belongs to the BMI1 CPU feature and the 'shrx'
|
||||
instruction, which belongs to the BMI2 CPU feature.
|
||||
|
||||
Fixes: df7e295d18ff ("x86: Optimize {str|wcs}rchr-avx2")
|
||||
Partially resolves: BZ #29611
|
||||
|
||||
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
(cherry picked from commit 7e8283170c5d6805b609a040801d819e362a6292)
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-avx2.h b/sysdeps/x86_64/multiarch/ifunc-avx2.h
|
||||
index 52bd00ea5cab6b22..877f007dd6e38fe8 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-avx2.h
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-avx2.h
|
||||
@@ -30,6 +30,7 @@ IFUNC_SELECTOR (void)
|
||||
const struct cpu_features* cpu_features = __get_cpu_features ();
|
||||
|
||||
if (CPU_FEATURE_USABLE_P (cpu_features, AVX2)
|
||||
+ && CPU_FEATURE_USABLE_P (cpu_features, BMI1)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, BMI2)
|
||||
&& CPU_FEATURE_USABLE_P (cpu_features, LZCNT)
|
||||
&& CPU_FEATURES_ARCH_P (cpu_features, AVX_Fast_Unaligned_Load))
|
||||
diff --git a/sysdeps/x86_64/multiarch/ifunc-impl-list.c b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
index d1fc1e75d6706413..84f9e73e2b7df816 100644
|
||||
--- a/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
+++ b/sysdeps/x86_64/multiarch/ifunc-impl-list.c
|
||||
@@ -498,15 +498,21 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/strrchr.c. */
|
||||
IFUNC_IMPL (i, name, strrchr,
|
||||
IFUNC_IMPL_ADD (array, i, strrchr,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI1)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strrchr_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, strrchr,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI1)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__strrchr_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, strrchr,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
- && CPU_FEATURE_USABLE (AVX512BW)),
|
||||
+ && CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI1)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__strrchr_evex)
|
||||
IFUNC_IMPL_ADD (array, i, strrchr, 1, __strrchr_sse2))
|
||||
|
||||
@@ -687,15 +693,20 @@ __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array,
|
||||
/* Support sysdeps/x86_64/multiarch/wcsrchr.c. */
|
||||
IFUNC_IMPL (i, name, wcsrchr,
|
||||
IFUNC_IMPL_ADD (array, i, wcsrchr,
|
||||
- CPU_FEATURE_USABLE (AVX2),
|
||||
+ (CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI1)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)),
|
||||
__wcsrchr_avx2)
|
||||
IFUNC_IMPL_ADD (array, i, wcsrchr,
|
||||
(CPU_FEATURE_USABLE (AVX2)
|
||||
+ && CPU_FEATURE_USABLE (BMI1)
|
||||
+ && CPU_FEATURE_USABLE (BMI2)
|
||||
&& CPU_FEATURE_USABLE (RTM)),
|
||||
__wcsrchr_avx2_rtm)
|
||||
IFUNC_IMPL_ADD (array, i, wcsrchr,
|
||||
(CPU_FEATURE_USABLE (AVX512VL)
|
||||
&& CPU_FEATURE_USABLE (AVX512BW)
|
||||
+ && CPU_FEATURE_USABLE (BMI1)
|
||||
&& CPU_FEATURE_USABLE (BMI2)),
|
||||
__wcsrchr_evex)
|
||||
IFUNC_IMPL_ADD (array, i, wcsrchr, 1, __wcsrchr_sse2))
|
@ -0,0 +1,46 @@
|
||||
commit e3976287b22422787f3cc6fc9adda58304b55bd9
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Tue Oct 4 18:40:25 2022 -0400
|
||||
|
||||
nscd: Drop local address tuple variable [BZ #29607]
|
||||
|
||||
When a request needs to be resent (e.g. due to insufficient buffer
|
||||
space), the references to subsequent tuples in the local variable are
|
||||
stale and should not be used. This used to work by accident before, but
|
||||
since 1d495912a it no longer does. Instead of trying to reset it, just
|
||||
let gethostbyname4_r write into TUMPBUF6 for us, thus maintaining a
|
||||
consistent state at all times. This is now consistent with what is done
|
||||
in gaih_inet for getaddrinfo.
|
||||
|
||||
Resolves: BZ #29607
|
||||
Reported-by: Holger Hoffstätte <holger@applied-asynchrony.com>
|
||||
Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com>
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit 6e33e5c4b73cea7b8aa3de0947123db16200fb65)
|
||||
|
||||
diff --git a/nscd/aicache.c b/nscd/aicache.c
|
||||
index 737ace11cc276021..3b300ad9b7db2297 100644
|
||||
--- a/nscd/aicache.c
|
||||
+++ b/nscd/aicache.c
|
||||
@@ -111,11 +111,10 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||||
"gethostbyname4_r");
|
||||
if (fct4 != NULL)
|
||||
{
|
||||
- struct gaih_addrtuple atmem;
|
||||
struct gaih_addrtuple *at;
|
||||
while (1)
|
||||
{
|
||||
- at = &atmem;
|
||||
+ at = NULL;
|
||||
rc6 = 0;
|
||||
herrno = 0;
|
||||
status[1] = DL_CALL_FCT (fct4, (key, &at,
|
||||
@@ -138,7 +137,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||||
goto next_nip;
|
||||
|
||||
/* We found the data. Count the addresses and the size. */
|
||||
- for (const struct gaih_addrtuple *at2 = at = &atmem; at2 != NULL;
|
||||
+ for (const struct gaih_addrtuple *at2 = at; at2 != NULL;
|
||||
at2 = at2->next)
|
||||
{
|
||||
++naddrs;
|
@ -0,0 +1,55 @@
|
||||
commit c95ef423d78d9a2ec0a8e4141c78165434685c6f
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Sep 13 16:10:20 2022 +0200
|
||||
|
||||
nss: Implement --no-addrconfig option for getent
|
||||
|
||||
The ahosts, ahostsv4, ahostsv6 commands unconditionally pass
|
||||
AI_ADDRCONFIG to getaddrinfo, which is not always desired.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit a623f13adfac47c8634a7288e08f821a846bc650)
|
||||
|
||||
diff --git a/nss/getent.c b/nss/getent.c
|
||||
index ec48ba4bf1f5f788..0f4d549b05da73ac 100644
|
||||
--- a/nss/getent.c
|
||||
+++ b/nss/getent.c
|
||||
@@ -59,6 +59,8 @@ static const struct argp_option args_options[] =
|
||||
{
|
||||
{ "service", 's', N_("CONFIG"), 0, N_("Service configuration to be used") },
|
||||
{ "no-idn", 'i', NULL, 0, N_("disable IDN encoding") },
|
||||
+ { "no-addrconfig", 'A', NULL, 0,
|
||||
+ N_("do not filter out unsupported IPv4/IPv6 addresses (with ahosts*)") },
|
||||
{ NULL, 0, NULL, 0, NULL },
|
||||
};
|
||||
|
||||
@@ -80,6 +82,9 @@ static struct argp argp =
|
||||
/* Additional getaddrinfo flags for IDN encoding. */
|
||||
static int idn_flags = AI_IDN | AI_CANONIDN;
|
||||
|
||||
+/* Set to 0 by --no-addrconfig. */
|
||||
+static int addrconfig_flags = AI_ADDRCONFIG;
|
||||
+
|
||||
/* Print the version information. */
|
||||
static void
|
||||
print_version (FILE *stream, struct argp_state *state)
|
||||
@@ -347,7 +352,7 @@ ahosts_keys_int (int af, int xflags, int number, char *key[])
|
||||
|
||||
struct addrinfo hint;
|
||||
memset (&hint, '\0', sizeof (hint));
|
||||
- hint.ai_flags = (AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME
|
||||
+ hint.ai_flags = (AI_V4MAPPED | addrconfig_flags | AI_CANONNAME
|
||||
| idn_flags | xflags);
|
||||
hint.ai_family = af;
|
||||
|
||||
@@ -906,6 +911,10 @@ parse_option (int key, char *arg, struct argp_state *state)
|
||||
idn_flags = 0;
|
||||
break;
|
||||
|
||||
+ case 'A':
|
||||
+ addrconfig_flags = 0;
|
||||
+ break;
|
||||
+
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
commit 16c7ed6e68c13e5a5efd8ab464ebf9d07b4b0bb3
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Tue Sep 13 16:11:40 2022 +0200
|
||||
|
||||
nss: Fix tst-nss-files-hosts-long on single-stack hosts (bug 24816)
|
||||
|
||||
getent implicitly passes AI_ADDRCONFIG to getaddrinfo by default.
|
||||
Use --no-addrconfig to suppress that, so that both IPv4 and IPv6
|
||||
lookups succeed even if the address family is not supported by the
|
||||
host.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit c75d20b5b27b0a60f0678236f51a4d3b0b058c00)
|
||||
|
||||
diff --git a/nss/tst-nss-files-hosts-long.c b/nss/tst-nss-files-hosts-long.c
|
||||
index 00f8bea409e0b4cb..42676ba4056dbde2 100644
|
||||
--- a/nss/tst-nss-files-hosts-long.c
|
||||
+++ b/nss/tst-nss-files-hosts-long.c
|
||||
@@ -28,14 +28,15 @@ do_test (void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
- /* Run getent to fetch the IPv4 address for host test4.
|
||||
- This forces /etc/hosts to be parsed. */
|
||||
- ret = system("getent ahostsv4 test4");
|
||||
+ /* Run getent to fetch the IPv4 address for host test4. This forces
|
||||
+ /etc/hosts to be parsed. Use --no-addrconfig to return addresses
|
||||
+ even in an IPv6-only environment. */
|
||||
+ ret = system("getent --no-addrconfig ahostsv4 test4");
|
||||
if (ret != 0)
|
||||
FAIL_EXIT1("ahostsv4 failed");
|
||||
|
||||
/* Likewise for IPv6. */
|
||||
- ret = system("getent ahostsv6 test6");
|
||||
+ ret = system("getent --no-addrconfig ahostsv6 test6");
|
||||
if (ret != 0)
|
||||
FAIL_EXIT1("ahostsv6 failed");
|
||||
|
@ -0,0 +1,47 @@
|
||||
commit d5313bcb7e56cd949ca920bb0c741a1d1d4093cf
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Sep 23 19:30:57 2022 +0200
|
||||
|
||||
nss: Use shared prefix in IPv4 address in tst-reload1
|
||||
|
||||
Otherwise, sorting based on the longest-matching prefix in
|
||||
getaddrinfo can reorder the addresses in ways the test does not
|
||||
expect, depending on the IPv4 address of the host.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit c02e29a0ba47d636281e1a026444a1a0a254aa12)
|
||||
|
||||
diff --git a/nss/tst-reload1.c b/nss/tst-reload1.c
|
||||
index 27a18ed9c37607bb..844cfcddc5e0f638 100644
|
||||
--- a/nss/tst-reload1.c
|
||||
+++ b/nss/tst-reload1.c
|
||||
@@ -43,12 +43,12 @@ static struct passwd pwd_table_1[] = {
|
||||
|
||||
static const char *hostaddr_5[] =
|
||||
{
|
||||
- "ABCD", "abcd", "1234", NULL
|
||||
+ "ABCd", "ABCD", "ABC4", NULL
|
||||
};
|
||||
|
||||
static const char *hostaddr_15[] =
|
||||
{
|
||||
- "4321", "ghij", NULL
|
||||
+ "4321", "4322", NULL
|
||||
};
|
||||
|
||||
static const char *hostaddr_25[] =
|
||||
@@ -86,12 +86,12 @@ static const char *hostaddr_6[] =
|
||||
|
||||
static const char *hostaddr_16[] =
|
||||
{
|
||||
- "7890", "a1b2", NULL
|
||||
+ "7890", "7891", NULL
|
||||
};
|
||||
|
||||
static const char *hostaddr_26[] =
|
||||
{
|
||||
- "qwer", "tyui", NULL
|
||||
+ "qwer", "qweR", NULL
|
||||
};
|
||||
|
||||
static struct hostent host_table_2[] = {
|
@ -0,0 +1,92 @@
|
||||
commit 9f55d2e7c42e6ca862a25d3ee3eb2b367811c30d
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Oct 14 12:43:07 2022 +0200
|
||||
|
||||
elf: Do not completely clear reused namespace in dlmopen (bug 29600)
|
||||
|
||||
The data in the _ns_debug member must be preserved, otherwise
|
||||
_dl_debug_initialize enters an infinite loop. To be conservative,
|
||||
only clear the libc_map member for now, to fix bug 29528.
|
||||
|
||||
Fixes commit d0e357ff45a75553dee3b17ed7d303bfa544f6fe
|
||||
("elf: Call __libc_early_init for reused namespaces (bug 29528)"),
|
||||
by reverting most of it.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
Tested-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit 2c42257314536b94cc8d52edede86e94e98c1436)
|
||||
(Conflict in elf/dl-open.c due to missing _r_debug namespace support.)
|
||||
|
||||
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
||||
index 1ab3c7b5ac2fbc45..633b047ad2497296 100644
|
||||
--- a/elf/dl-open.c
|
||||
+++ b/elf/dl-open.c
|
||||
@@ -839,15 +839,13 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
|
||||
_dl_signal_error (EINVAL, file, NULL, N_("\
|
||||
no more namespaces available for dlmopen()"));
|
||||
}
|
||||
+ else if (nsid == GL(dl_nns))
|
||||
+ {
|
||||
+ __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
|
||||
+ ++GL(dl_nns);
|
||||
+ }
|
||||
|
||||
- if (nsid == GL(dl_nns))
|
||||
- ++GL(dl_nns);
|
||||
-
|
||||
- /* Initialize the new namespace. Most members are
|
||||
- zero-initialized, only the lock needs special treatment. */
|
||||
- memset (&GL(dl_ns)[nsid], 0, sizeof (GL(dl_ns)[nsid]));
|
||||
- __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
|
||||
-
|
||||
+ GL(dl_ns)[nsid].libc_map = NULL;
|
||||
_dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
|
||||
}
|
||||
/* Never allow loading a DSO in a namespace which is empty. Such
|
||||
diff --git a/elf/tst-dlmopen-twice.c b/elf/tst-dlmopen-twice.c
|
||||
index 449f3c8fa9f2aa01..70c71fe19c7d0bf9 100644
|
||||
--- a/elf/tst-dlmopen-twice.c
|
||||
+++ b/elf/tst-dlmopen-twice.c
|
||||
@@ -16,18 +16,38 @@
|
||||
License along with the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
-#include <support/xdlfcn.h>
|
||||
+#include <stdio.h>
|
||||
#include <support/check.h>
|
||||
+#include <support/xdlfcn.h>
|
||||
|
||||
-static int
|
||||
-do_test (void)
|
||||
+/* Run the test multiple times, to check finding a new namespace while
|
||||
+ another namespace is already in use. This used to trigger bug 29600. */
|
||||
+static void
|
||||
+recurse (int depth)
|
||||
{
|
||||
- void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so", RTLD_NOW);
|
||||
+ if (depth == 0)
|
||||
+ return;
|
||||
+
|
||||
+ printf ("info: running at depth %d\n", depth);
|
||||
+ void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so",
|
||||
+ RTLD_NOW);
|
||||
xdlclose (handle);
|
||||
handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod2.so", RTLD_NOW);
|
||||
int (*run_check) (void) = xdlsym (handle, "run_check");
|
||||
TEST_COMPARE (run_check (), 0);
|
||||
+ recurse (depth - 1);
|
||||
xdlclose (handle);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ /* First run the test without nesting. */
|
||||
+ recurse (1);
|
||||
+
|
||||
+ /* Then with nesting. The constant needs to be less than the
|
||||
+ internal DL_NNS namespace constant. */
|
||||
+ recurse (10);
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,861 @@
|
||||
commit ca5df795459b9242cd7d787ebf71a09be2244577
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Wed Oct 19 19:14:04 2022 -0300
|
||||
|
||||
linux: Fix generic struct_stat for 64 bit time (BZ# 29657)
|
||||
|
||||
The generic Linux struct_stat misses the conditionals to use
|
||||
bits/struct_stat_time64_helper.h in the __USE_TIME_BITS64 for
|
||||
architecture that uses __TIMESIZE == 32 (currently csky and nios2).
|
||||
|
||||
Since newer ports should not support 32 bit time_t, the generic
|
||||
implementation should be used as default.
|
||||
|
||||
For arm, hppa, and sh a copy of default struct_stat is added,
|
||||
while for csky and nios a new one based on generic is used, along
|
||||
with conditionals to use bits/struct_stat_time64_helper.h.
|
||||
|
||||
The default struct_stat is also replaced with the generic one.
|
||||
|
||||
Checked on aarch64-linux-gnu and arm-linux-gnueabihf.
|
||||
|
||||
(cherry picked from commit 7a6ca82f8007ddbd43e2b8fce806ba7101ee47f5)
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/arm/bits/struct_stat.h b/sysdeps/unix/sysv/linux/arm/bits/struct_stat.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..30ee6279d2701242
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/arm/bits/struct_stat.h
|
||||
@@ -0,0 +1,139 @@
|
||||
+/* Definition for struct stat. Linux/arm version.
|
||||
+ Copyright (C) 2020-2022 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/>. */
|
||||
+
|
||||
+#if !defined _SYS_STAT_H && !defined _FCNTL_H
|
||||
+# error "Never include <bits/struct_stat.h> directly; use <sys/stat.h> instead."
|
||||
+#endif
|
||||
+
|
||||
+#ifndef _BITS_STRUCT_STAT_H
|
||||
+#define _BITS_STRUCT_STAT_H 1
|
||||
+
|
||||
+#include <bits/endian.h>
|
||||
+#include <bits/wordsize.h>
|
||||
+
|
||||
+struct stat
|
||||
+ {
|
||||
+#ifdef __USE_TIME_BITS64
|
||||
+# include <bits/struct_stat_time64_helper.h>
|
||||
+#else
|
||||
+ __dev_t st_dev; /* Device. */
|
||||
+ unsigned short int __pad1;
|
||||
+# ifndef __USE_FILE_OFFSET64
|
||||
+ __ino_t st_ino; /* File serial number. */
|
||||
+# else
|
||||
+ __ino_t __st_ino; /* 32bit file serial number. */
|
||||
+# endif
|
||||
+ __mode_t st_mode; /* File mode. */
|
||||
+ __nlink_t st_nlink; /* Link count. */
|
||||
+ __uid_t st_uid; /* User ID of the file's owner. */
|
||||
+ __gid_t st_gid; /* Group ID of the file's group.*/
|
||||
+ __dev_t st_rdev; /* Device number, if device. */
|
||||
+ unsigned short int __pad2;
|
||||
+# ifndef __USE_FILE_OFFSET64
|
||||
+ __off_t st_size; /* Size of file, in bytes. */
|
||||
+# else
|
||||
+ __off64_t st_size; /* Size of file, in bytes. */
|
||||
+# endif
|
||||
+ __blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
+
|
||||
+# ifndef __USE_FILE_OFFSET64
|
||||
+ __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */
|
||||
+# else
|
||||
+ __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
|
||||
+# endif
|
||||
+# ifdef __USE_XOPEN2K8
|
||||
+ /* Nanosecond resolution timestamps are stored in a format
|
||||
+ equivalent to 'struct timespec'. This is the type used
|
||||
+ whenever possible but the Unix namespace rules do not allow the
|
||||
+ identifier 'timespec' to appear in the <sys/stat.h> header.
|
||||
+ Therefore we have to handle the use of this header in strictly
|
||||
+ standard-compliant sources special. */
|
||||
+ struct timespec st_atim; /* Time of last access. */
|
||||
+ struct timespec st_mtim; /* Time of last modification. */
|
||||
+ struct timespec st_ctim; /* Time of last status change. */
|
||||
+# define st_atime st_atim.tv_sec /* Backward compatibility. */
|
||||
+# define st_mtime st_mtim.tv_sec
|
||||
+# define st_ctime st_ctim.tv_sec
|
||||
+# else
|
||||
+ __time_t st_atime; /* Time of last access. */
|
||||
+ unsigned long int st_atimensec; /* Nscecs of last access. */
|
||||
+ __time_t st_mtime; /* Time of last modification. */
|
||||
+ unsigned long int st_mtimensec; /* Nsecs of last modification. */
|
||||
+ __time_t st_ctime; /* Time of last status change. */
|
||||
+ unsigned long int st_ctimensec; /* Nsecs of last status change. */
|
||||
+# endif
|
||||
+# ifndef __USE_FILE_OFFSET64
|
||||
+ unsigned long int __glibc_reserved4;
|
||||
+ unsigned long int __glibc_reserved5;
|
||||
+# else
|
||||
+ __ino64_t st_ino; /* File serial number. */
|
||||
+# endif
|
||||
+#endif /* __USE_TIME_BITS64 */
|
||||
+ };
|
||||
+
|
||||
+#ifdef __USE_LARGEFILE64
|
||||
+struct stat64
|
||||
+ {
|
||||
+# ifdef __USE_TIME_BITS64
|
||||
+# include <bits/struct_stat_time64_helper.h>
|
||||
+# else
|
||||
+ __dev_t st_dev; /* Device. */
|
||||
+ unsigned int __pad1;
|
||||
+
|
||||
+ __ino_t __st_ino; /* 32bit file serial number. */
|
||||
+ __mode_t st_mode; /* File mode. */
|
||||
+ __nlink_t st_nlink; /* Link count. */
|
||||
+ __uid_t st_uid; /* User ID of the file's owner. */
|
||||
+ __gid_t st_gid; /* Group ID of the file's group.*/
|
||||
+ __dev_t st_rdev; /* Device number, if device. */
|
||||
+ unsigned int __pad2;
|
||||
+ __off64_t st_size; /* Size of file, in bytes. */
|
||||
+ __blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
+
|
||||
+ __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
|
||||
+# ifdef __USE_XOPEN2K8
|
||||
+ /* Nanosecond resolution timestamps are stored in a format
|
||||
+ equivalent to 'struct timespec'. This is the type used
|
||||
+ whenever possible but the Unix namespace rules do not allow the
|
||||
+ identifier 'timespec' to appear in the <sys/stat.h> header.
|
||||
+ Therefore we have to handle the use of this header in strictly
|
||||
+ standard-compliant sources special. */
|
||||
+ struct timespec st_atim; /* Time of last access. */
|
||||
+ struct timespec st_mtim; /* Time of last modification. */
|
||||
+ struct timespec st_ctim; /* Time of last status change. */
|
||||
+# else
|
||||
+ __time_t st_atime; /* Time of last access. */
|
||||
+ unsigned long int st_atimensec; /* Nscecs of last access. */
|
||||
+ __time_t st_mtime; /* Time of last modification. */
|
||||
+ unsigned long int st_mtimensec; /* Nsecs of last modification. */
|
||||
+ __time_t st_ctime; /* Time of last status change. */
|
||||
+ unsigned long int st_ctimensec; /* Nsecs of last status change. */
|
||||
+# endif
|
||||
+ __ino64_t st_ino; /* File serial number. */
|
||||
+# endif /* __USE_TIME_BITS64 */
|
||||
+ };
|
||||
+#endif
|
||||
+
|
||||
+/* Tell code we have these members. */
|
||||
+#define _STATBUF_ST_BLKSIZE
|
||||
+#define _STATBUF_ST_RDEV
|
||||
+/* Nanosecond resolution time values are supported. */
|
||||
+#define _STATBUF_ST_NSEC
|
||||
+
|
||||
+
|
||||
+#endif /* _BITS_STRUCT_STAT_H */
|
||||
diff --git a/sysdeps/unix/sysv/linux/bits/struct_stat.h b/sysdeps/unix/sysv/linux/bits/struct_stat.h
|
||||
index 298418966f4d6e0b..32ef511ae5728276 100644
|
||||
--- a/sysdeps/unix/sysv/linux/bits/struct_stat.h
|
||||
+++ b/sysdeps/unix/sysv/linux/bits/struct_stat.h
|
||||
@@ -26,37 +26,36 @@
|
||||
#include <bits/endian.h>
|
||||
#include <bits/wordsize.h>
|
||||
|
||||
-struct stat
|
||||
- {
|
||||
-#ifdef __USE_TIME_BITS64
|
||||
-# include <bits/struct_stat_time64_helper.h>
|
||||
-#else
|
||||
- __dev_t st_dev; /* Device. */
|
||||
- unsigned short int __pad1;
|
||||
-# ifndef __USE_FILE_OFFSET64
|
||||
- __ino_t st_ino; /* File serial number. */
|
||||
-# else
|
||||
- __ino_t __st_ino; /* 32bit file serial number. */
|
||||
+#if defined __USE_FILE_OFFSET64
|
||||
+# define __field64(type, type64, name) type64 name
|
||||
+#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T
|
||||
+# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T
|
||||
+# error "ino_t and off_t must both be the same type"
|
||||
# endif
|
||||
- __mode_t st_mode; /* File mode. */
|
||||
- __nlink_t st_nlink; /* Link count. */
|
||||
- __uid_t st_uid; /* User ID of the file's owner. */
|
||||
- __gid_t st_gid; /* Group ID of the file's group.*/
|
||||
- __dev_t st_rdev; /* Device number, if device. */
|
||||
- unsigned short int __pad2;
|
||||
-# ifndef __USE_FILE_OFFSET64
|
||||
- __off_t st_size; /* Size of file, in bytes. */
|
||||
-# else
|
||||
- __off64_t st_size; /* Size of file, in bytes. */
|
||||
-# endif
|
||||
- __blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
+# define __field64(type, type64, name) type name
|
||||
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
+# define __field64(type, type64, name) \
|
||||
+ type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad
|
||||
+#else
|
||||
+# define __field64(type, type64, name) \
|
||||
+ int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name
|
||||
+#endif
|
||||
|
||||
-# ifndef __USE_FILE_OFFSET64
|
||||
- __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */
|
||||
-# else
|
||||
- __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
|
||||
-# endif
|
||||
-# ifdef __USE_XOPEN2K8
|
||||
+struct stat
|
||||
+ {
|
||||
+ __dev_t st_dev; /* Device. */
|
||||
+ __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */
|
||||
+ __mode_t st_mode; /* File mode. */
|
||||
+ __nlink_t st_nlink; /* Link count. */
|
||||
+ __uid_t st_uid; /* User ID of the file's owner. */
|
||||
+ __gid_t st_gid; /* Group ID of the file's group.*/
|
||||
+ __dev_t st_rdev; /* Device number, if device. */
|
||||
+ __dev_t __pad1;
|
||||
+ __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */
|
||||
+ __blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
+ int __pad2;
|
||||
+ __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */
|
||||
+#ifdef __USE_XOPEN2K8
|
||||
/* Nanosecond resolution timestamps are stored in a format
|
||||
equivalent to 'struct timespec'. This is the type used
|
||||
whenever possible but the Unix namespace rules do not allow the
|
||||
@@ -66,47 +65,38 @@ struct stat
|
||||
struct timespec st_atim; /* Time of last access. */
|
||||
struct timespec st_mtim; /* Time of last modification. */
|
||||
struct timespec st_ctim; /* Time of last status change. */
|
||||
-# define st_atime st_atim.tv_sec /* Backward compatibility. */
|
||||
-# define st_mtime st_mtim.tv_sec
|
||||
-# define st_ctime st_ctim.tv_sec
|
||||
-# else
|
||||
+# define st_atime st_atim.tv_sec /* Backward compatibility. */
|
||||
+# define st_mtime st_mtim.tv_sec
|
||||
+# define st_ctime st_ctim.tv_sec
|
||||
+#else
|
||||
__time_t st_atime; /* Time of last access. */
|
||||
unsigned long int st_atimensec; /* Nscecs of last access. */
|
||||
__time_t st_mtime; /* Time of last modification. */
|
||||
unsigned long int st_mtimensec; /* Nsecs of last modification. */
|
||||
__time_t st_ctime; /* Time of last status change. */
|
||||
unsigned long int st_ctimensec; /* Nsecs of last status change. */
|
||||
-# endif
|
||||
-# ifndef __USE_FILE_OFFSET64
|
||||
- unsigned long int __glibc_reserved4;
|
||||
- unsigned long int __glibc_reserved5;
|
||||
-# else
|
||||
- __ino64_t st_ino; /* File serial number. */
|
||||
-# endif
|
||||
-#endif /* __USE_TIME_BITS64 */
|
||||
+#endif
|
||||
+ int __glibc_reserved[2];
|
||||
};
|
||||
|
||||
+#undef __field64
|
||||
+
|
||||
#ifdef __USE_LARGEFILE64
|
||||
struct stat64
|
||||
{
|
||||
-# ifdef __USE_TIME_BITS64
|
||||
-# include <bits/struct_stat_time64_helper.h>
|
||||
-# else
|
||||
- __dev_t st_dev; /* Device. */
|
||||
- unsigned int __pad1;
|
||||
-
|
||||
- __ino_t __st_ino; /* 32bit file serial number. */
|
||||
- __mode_t st_mode; /* File mode. */
|
||||
- __nlink_t st_nlink; /* Link count. */
|
||||
- __uid_t st_uid; /* User ID of the file's owner. */
|
||||
- __gid_t st_gid; /* Group ID of the file's group.*/
|
||||
- __dev_t st_rdev; /* Device number, if device. */
|
||||
- unsigned int __pad2;
|
||||
- __off64_t st_size; /* Size of file, in bytes. */
|
||||
- __blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
-
|
||||
- __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
|
||||
-# ifdef __USE_XOPEN2K8
|
||||
+ __dev_t st_dev; /* Device. */
|
||||
+ __ino64_t st_ino; /* File serial number. */
|
||||
+ __mode_t st_mode; /* File mode. */
|
||||
+ __nlink_t st_nlink; /* Link count. */
|
||||
+ __uid_t st_uid; /* User ID of the file's owner. */
|
||||
+ __gid_t st_gid; /* Group ID of the file's group.*/
|
||||
+ __dev_t st_rdev; /* Device number, if device. */
|
||||
+ __dev_t __pad1;
|
||||
+ __off64_t st_size; /* Size of file, in bytes. */
|
||||
+ __blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
+ int __pad2;
|
||||
+ __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */
|
||||
+#ifdef __USE_XOPEN2K8
|
||||
/* Nanosecond resolution timestamps are stored in a format
|
||||
equivalent to 'struct timespec'. This is the type used
|
||||
whenever possible but the Unix namespace rules do not allow the
|
||||
@@ -116,16 +106,15 @@ struct stat64
|
||||
struct timespec st_atim; /* Time of last access. */
|
||||
struct timespec st_mtim; /* Time of last modification. */
|
||||
struct timespec st_ctim; /* Time of last status change. */
|
||||
-# else
|
||||
+#else
|
||||
__time_t st_atime; /* Time of last access. */
|
||||
unsigned long int st_atimensec; /* Nscecs of last access. */
|
||||
__time_t st_mtime; /* Time of last modification. */
|
||||
unsigned long int st_mtimensec; /* Nsecs of last modification. */
|
||||
__time_t st_ctime; /* Time of last status change. */
|
||||
unsigned long int st_ctimensec; /* Nsecs of last status change. */
|
||||
-# endif
|
||||
- __ino64_t st_ino; /* File serial number. */
|
||||
-# endif /* __USE_TIME_BITS64 */
|
||||
+#endif
|
||||
+ int __glibc_reserved[2];
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -135,5 +124,4 @@ struct stat64
|
||||
/* Nanosecond resolution time values are supported. */
|
||||
#define _STATBUF_ST_NSEC
|
||||
|
||||
-
|
||||
#endif /* _BITS_STRUCT_STAT_H */
|
||||
diff --git a/sysdeps/unix/sysv/linux/generic/bits/struct_stat.h b/sysdeps/unix/sysv/linux/csky/bits/struct_stat.h
|
||||
similarity index 91%
|
||||
rename from sysdeps/unix/sysv/linux/generic/bits/struct_stat.h
|
||||
rename to sysdeps/unix/sysv/linux/csky/bits/struct_stat.h
|
||||
index 32ef511ae5728276..f0ee455748d3ee41 100644
|
||||
--- a/sysdeps/unix/sysv/linux/generic/bits/struct_stat.h
|
||||
+++ b/sysdeps/unix/sysv/linux/csky/bits/struct_stat.h
|
||||
@@ -1,5 +1,5 @@
|
||||
-/* Definition for struct stat.
|
||||
- Copyright (C) 2020-2021 Free Software Foundation, Inc.
|
||||
+/* Definition for struct stat. Linux/csky version.
|
||||
+ Copyright (C) 2020-2022 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
|
||||
@@ -43,6 +43,9 @@
|
||||
|
||||
struct stat
|
||||
{
|
||||
+#ifdef __USE_TIME_BITS64
|
||||
+# include <bits/struct_stat_time64_helper.h>
|
||||
+#else
|
||||
__dev_t st_dev; /* Device. */
|
||||
__field64(__ino_t, __ino64_t, st_ino); /* File serial number. */
|
||||
__mode_t st_mode; /* File mode. */
|
||||
@@ -55,7 +58,7 @@ struct stat
|
||||
__blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
int __pad2;
|
||||
__field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */
|
||||
-#ifdef __USE_XOPEN2K8
|
||||
+# ifdef __USE_XOPEN2K8
|
||||
/* Nanosecond resolution timestamps are stored in a format
|
||||
equivalent to 'struct timespec'. This is the type used
|
||||
whenever possible but the Unix namespace rules do not allow the
|
||||
@@ -65,18 +68,19 @@ struct stat
|
||||
struct timespec st_atim; /* Time of last access. */
|
||||
struct timespec st_mtim; /* Time of last modification. */
|
||||
struct timespec st_ctim; /* Time of last status change. */
|
||||
-# define st_atime st_atim.tv_sec /* Backward compatibility. */
|
||||
-# define st_mtime st_mtim.tv_sec
|
||||
-# define st_ctime st_ctim.tv_sec
|
||||
-#else
|
||||
+# define st_atime st_atim.tv_sec /* Backward compatibility. */
|
||||
+# define st_mtime st_mtim.tv_sec
|
||||
+# define st_ctime st_ctim.tv_sec
|
||||
+# else
|
||||
__time_t st_atime; /* Time of last access. */
|
||||
unsigned long int st_atimensec; /* Nscecs of last access. */
|
||||
__time_t st_mtime; /* Time of last modification. */
|
||||
unsigned long int st_mtimensec; /* Nsecs of last modification. */
|
||||
__time_t st_ctime; /* Time of last status change. */
|
||||
unsigned long int st_ctimensec; /* Nsecs of last status change. */
|
||||
-#endif
|
||||
+# endif
|
||||
int __glibc_reserved[2];
|
||||
+#endif
|
||||
};
|
||||
|
||||
#undef __field64
|
||||
@@ -84,6 +88,9 @@ struct stat
|
||||
#ifdef __USE_LARGEFILE64
|
||||
struct stat64
|
||||
{
|
||||
+# ifdef __USE_TIME_BITS64
|
||||
+# include <bits/struct_stat_time64_helper.h>
|
||||
+# else
|
||||
__dev_t st_dev; /* Device. */
|
||||
__ino64_t st_ino; /* File serial number. */
|
||||
__mode_t st_mode; /* File mode. */
|
||||
@@ -96,7 +103,7 @@ struct stat64
|
||||
__blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
int __pad2;
|
||||
__blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */
|
||||
-#ifdef __USE_XOPEN2K8
|
||||
+# ifdef __USE_XOPEN2K8
|
||||
/* Nanosecond resolution timestamps are stored in a format
|
||||
equivalent to 'struct timespec'. This is the type used
|
||||
whenever possible but the Unix namespace rules do not allow the
|
||||
@@ -106,15 +113,16 @@ struct stat64
|
||||
struct timespec st_atim; /* Time of last access. */
|
||||
struct timespec st_mtim; /* Time of last modification. */
|
||||
struct timespec st_ctim; /* Time of last status change. */
|
||||
-#else
|
||||
+# else
|
||||
__time_t st_atime; /* Time of last access. */
|
||||
unsigned long int st_atimensec; /* Nscecs of last access. */
|
||||
__time_t st_mtime; /* Time of last modification. */
|
||||
unsigned long int st_mtimensec; /* Nsecs of last modification. */
|
||||
__time_t st_ctime; /* Time of last status change. */
|
||||
unsigned long int st_ctimensec; /* Nsecs of last status change. */
|
||||
-#endif
|
||||
+# endif
|
||||
int __glibc_reserved[2];
|
||||
+# endif
|
||||
};
|
||||
#endif
|
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/hppa/bits/struct_stat.h b/sysdeps/unix/sysv/linux/hppa/bits/struct_stat.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..38b6e13e68890c29
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/hppa/bits/struct_stat.h
|
||||
@@ -0,0 +1,139 @@
|
||||
+/* Definition for struct stat. Linux/hppa version.
|
||||
+ Copyright (C) 2020-2022 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/>. */
|
||||
+
|
||||
+#if !defined _SYS_STAT_H && !defined _FCNTL_H
|
||||
+# error "Never include <bits/struct_stat.h> directly; use <sys/stat.h> instead."
|
||||
+#endif
|
||||
+
|
||||
+#ifndef _BITS_STRUCT_STAT_H
|
||||
+#define _BITS_STRUCT_STAT_H 1
|
||||
+
|
||||
+#include <bits/endian.h>
|
||||
+#include <bits/wordsize.h>
|
||||
+
|
||||
+struct stat
|
||||
+ {
|
||||
+#ifdef __USE_TIME_BITS64
|
||||
+# include <bits/struct_stat_time64_helper.h>
|
||||
+#else
|
||||
+ __dev_t st_dev; /* Device. */
|
||||
+ unsigned short int __pad1;
|
||||
+# ifndef __USE_FILE_OFFSET64
|
||||
+ __ino_t st_ino; /* File serial number. */
|
||||
+# else
|
||||
+ __ino_t __st_ino; /* 32bit file serial number. */
|
||||
+# endif
|
||||
+ __mode_t st_mode; /* File mode. */
|
||||
+ __nlink_t st_nlink; /* Link count. */
|
||||
+ __uid_t st_uid; /* User ID of the file's owner. */
|
||||
+ __gid_t st_gid; /* Group ID of the file's group.*/
|
||||
+ __dev_t st_rdev; /* Device number, if device. */
|
||||
+ unsigned short int __pad2;
|
||||
+# ifndef __USE_FILE_OFFSET64
|
||||
+ __off_t st_size; /* Size of file, in bytes. */
|
||||
+# else
|
||||
+ __off64_t st_size; /* Size of file, in bytes. */
|
||||
+# endif
|
||||
+ __blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
+
|
||||
+# ifndef __USE_FILE_OFFSET64
|
||||
+ __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */
|
||||
+# else
|
||||
+ __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
|
||||
+# endif
|
||||
+# ifdef __USE_XOPEN2K8
|
||||
+ /* Nanosecond resolution timestamps are stored in a format
|
||||
+ equivalent to 'struct timespec'. This is the type used
|
||||
+ whenever possible but the Unix namespace rules do not allow the
|
||||
+ identifier 'timespec' to appear in the <sys/stat.h> header.
|
||||
+ Therefore we have to handle the use of this header in strictly
|
||||
+ standard-compliant sources special. */
|
||||
+ struct timespec st_atim; /* Time of last access. */
|
||||
+ struct timespec st_mtim; /* Time of last modification. */
|
||||
+ struct timespec st_ctim; /* Time of last status change. */
|
||||
+# define st_atime st_atim.tv_sec /* Backward compatibility. */
|
||||
+# define st_mtime st_mtim.tv_sec
|
||||
+# define st_ctime st_ctim.tv_sec
|
||||
+# else
|
||||
+ __time_t st_atime; /* Time of last access. */
|
||||
+ unsigned long int st_atimensec; /* Nscecs of last access. */
|
||||
+ __time_t st_mtime; /* Time of last modification. */
|
||||
+ unsigned long int st_mtimensec; /* Nsecs of last modification. */
|
||||
+ __time_t st_ctime; /* Time of last status change. */
|
||||
+ unsigned long int st_ctimensec; /* Nsecs of last status change. */
|
||||
+# endif
|
||||
+# ifndef __USE_FILE_OFFSET64
|
||||
+ unsigned long int __glibc_reserved4;
|
||||
+ unsigned long int __glibc_reserved5;
|
||||
+# else
|
||||
+ __ino64_t st_ino; /* File serial number. */
|
||||
+# endif
|
||||
+#endif /* __USE_TIME_BITS64 */
|
||||
+ };
|
||||
+
|
||||
+#ifdef __USE_LARGEFILE64
|
||||
+struct stat64
|
||||
+ {
|
||||
+# ifdef __USE_TIME_BITS64
|
||||
+# include <bits/struct_stat_time64_helper.h>
|
||||
+# else
|
||||
+ __dev_t st_dev; /* Device. */
|
||||
+ unsigned int __pad1;
|
||||
+
|
||||
+ __ino_t __st_ino; /* 32bit file serial number. */
|
||||
+ __mode_t st_mode; /* File mode. */
|
||||
+ __nlink_t st_nlink; /* Link count. */
|
||||
+ __uid_t st_uid; /* User ID of the file's owner. */
|
||||
+ __gid_t st_gid; /* Group ID of the file's group.*/
|
||||
+ __dev_t st_rdev; /* Device number, if device. */
|
||||
+ unsigned int __pad2;
|
||||
+ __off64_t st_size; /* Size of file, in bytes. */
|
||||
+ __blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
+
|
||||
+ __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
|
||||
+# ifdef __USE_XOPEN2K8
|
||||
+ /* Nanosecond resolution timestamps are stored in a format
|
||||
+ equivalent to 'struct timespec'. This is the type used
|
||||
+ whenever possible but the Unix namespace rules do not allow the
|
||||
+ identifier 'timespec' to appear in the <sys/stat.h> header.
|
||||
+ Therefore we have to handle the use of this header in strictly
|
||||
+ standard-compliant sources special. */
|
||||
+ struct timespec st_atim; /* Time of last access. */
|
||||
+ struct timespec st_mtim; /* Time of last modification. */
|
||||
+ struct timespec st_ctim; /* Time of last status change. */
|
||||
+# else
|
||||
+ __time_t st_atime; /* Time of last access. */
|
||||
+ unsigned long int st_atimensec; /* Nscecs of last access. */
|
||||
+ __time_t st_mtime; /* Time of last modification. */
|
||||
+ unsigned long int st_mtimensec; /* Nsecs of last modification. */
|
||||
+ __time_t st_ctime; /* Time of last status change. */
|
||||
+ unsigned long int st_ctimensec; /* Nsecs of last status change. */
|
||||
+# endif
|
||||
+ __ino64_t st_ino; /* File serial number. */
|
||||
+# endif /* __USE_TIME_BITS64 */
|
||||
+ };
|
||||
+#endif
|
||||
+
|
||||
+/* Tell code we have these members. */
|
||||
+#define _STATBUF_ST_BLKSIZE
|
||||
+#define _STATBUF_ST_RDEV
|
||||
+/* Nanosecond resolution time values are supported. */
|
||||
+#define _STATBUF_ST_NSEC
|
||||
+
|
||||
+
|
||||
+#endif /* _BITS_STRUCT_STAT_H */
|
||||
diff --git a/sysdeps/unix/sysv/linux/nios2/bits/struct_stat.h b/sysdeps/unix/sysv/linux/nios2/bits/struct_stat.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..e00e71173e184b48
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/nios2/bits/struct_stat.h
|
||||
@@ -0,0 +1,135 @@
|
||||
+/* Definition for struct stat. Linux/nios2 version.
|
||||
+ Copyright (C) 2020-2022 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/>. */
|
||||
+
|
||||
+#if !defined _SYS_STAT_H && !defined _FCNTL_H
|
||||
+# error "Never include <bits/struct_stat.h> directly; use <sys/stat.h> instead."
|
||||
+#endif
|
||||
+
|
||||
+#ifndef _BITS_STRUCT_STAT_H
|
||||
+#define _BITS_STRUCT_STAT_H 1
|
||||
+
|
||||
+#include <bits/endian.h>
|
||||
+#include <bits/wordsize.h>
|
||||
+
|
||||
+#if defined __USE_FILE_OFFSET64
|
||||
+# define __field64(type, type64, name) type64 name
|
||||
+#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T
|
||||
+# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T
|
||||
+# error "ino_t and off_t must both be the same type"
|
||||
+# endif
|
||||
+# define __field64(type, type64, name) type name
|
||||
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
+# define __field64(type, type64, name) \
|
||||
+ type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad
|
||||
+#else
|
||||
+# define __field64(type, type64, name) \
|
||||
+ int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name
|
||||
+#endif
|
||||
+
|
||||
+struct stat
|
||||
+ {
|
||||
+#ifdef __USE_TIME_BITS64
|
||||
+# include <bits/struct_stat_time64_helper.h>
|
||||
+#else
|
||||
+ __dev_t st_dev; /* Device. */
|
||||
+ __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */
|
||||
+ __mode_t st_mode; /* File mode. */
|
||||
+ __nlink_t st_nlink; /* Link count. */
|
||||
+ __uid_t st_uid; /* User ID of the file's owner. */
|
||||
+ __gid_t st_gid; /* Group ID of the file's group.*/
|
||||
+ __dev_t st_rdev; /* Device number, if device. */
|
||||
+ __dev_t __pad1;
|
||||
+ __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */
|
||||
+ __blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
+ int __pad2;
|
||||
+ __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */
|
||||
+# ifdef __USE_XOPEN2K8
|
||||
+ /* Nanosecond resolution timestamps are stored in a format
|
||||
+ equivalent to 'struct timespec'. This is the type used
|
||||
+ whenever possible but the Unix namespace rules do not allow the
|
||||
+ identifier 'timespec' to appear in the <sys/stat.h> header.
|
||||
+ Therefore we have to handle the use of this header in strictly
|
||||
+ standard-compliant sources special. */
|
||||
+ struct timespec st_atim; /* Time of last access. */
|
||||
+ struct timespec st_mtim; /* Time of last modification. */
|
||||
+ struct timespec st_ctim; /* Time of last status change. */
|
||||
+# define st_atime st_atim.tv_sec /* Backward compatibility. */
|
||||
+# define st_mtime st_mtim.tv_sec
|
||||
+# define st_ctime st_ctim.tv_sec
|
||||
+# else
|
||||
+ __time_t st_atime; /* Time of last access. */
|
||||
+ unsigned long int st_atimensec; /* Nscecs of last access. */
|
||||
+ __time_t st_mtime; /* Time of last modification. */
|
||||
+ unsigned long int st_mtimensec; /* Nsecs of last modification. */
|
||||
+ __time_t st_ctime; /* Time of last status change. */
|
||||
+ unsigned long int st_ctimensec; /* Nsecs of last status change. */
|
||||
+# endif
|
||||
+ int __glibc_reserved[2];
|
||||
+#endif
|
||||
+ };
|
||||
+
|
||||
+#undef __field64
|
||||
+
|
||||
+#ifdef __USE_LARGEFILE64
|
||||
+struct stat64
|
||||
+ {
|
||||
+# ifdef __USE_TIME_BITS64
|
||||
+# include <bits/struct_stat_time64_helper.h>
|
||||
+# else
|
||||
+ __dev_t st_dev; /* Device. */
|
||||
+ __ino64_t st_ino; /* File serial number. */
|
||||
+ __mode_t st_mode; /* File mode. */
|
||||
+ __nlink_t st_nlink; /* Link count. */
|
||||
+ __uid_t st_uid; /* User ID of the file's owner. */
|
||||
+ __gid_t st_gid; /* Group ID of the file's group.*/
|
||||
+ __dev_t st_rdev; /* Device number, if device. */
|
||||
+ __dev_t __pad1;
|
||||
+ __off64_t st_size; /* Size of file, in bytes. */
|
||||
+ __blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
+ int __pad2;
|
||||
+ __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */
|
||||
+# ifdef __USE_XOPEN2K8
|
||||
+ /* Nanosecond resolution timestamps are stored in a format
|
||||
+ equivalent to 'struct timespec'. This is the type used
|
||||
+ whenever possible but the Unix namespace rules do not allow the
|
||||
+ identifier 'timespec' to appear in the <sys/stat.h> header.
|
||||
+ Therefore we have to handle the use of this header in strictly
|
||||
+ standard-compliant sources special. */
|
||||
+ struct timespec st_atim; /* Time of last access. */
|
||||
+ struct timespec st_mtim; /* Time of last modification. */
|
||||
+ struct timespec st_ctim; /* Time of last status change. */
|
||||
+# else
|
||||
+ __time_t st_atime; /* Time of last access. */
|
||||
+ unsigned long int st_atimensec; /* Nscecs of last access. */
|
||||
+ __time_t st_mtime; /* Time of last modification. */
|
||||
+ unsigned long int st_mtimensec; /* Nsecs of last modification. */
|
||||
+ __time_t st_ctime; /* Time of last status change. */
|
||||
+ unsigned long int st_ctimensec; /* Nsecs of last status change. */
|
||||
+# endif
|
||||
+ int __glibc_reserved[2];
|
||||
+# endif
|
||||
+ };
|
||||
+#endif
|
||||
+
|
||||
+/* Tell code we have these members. */
|
||||
+#define _STATBUF_ST_BLKSIZE
|
||||
+#define _STATBUF_ST_RDEV
|
||||
+/* Nanosecond resolution time values are supported. */
|
||||
+#define _STATBUF_ST_NSEC
|
||||
+
|
||||
+#endif /* _BITS_STRUCT_STAT_H */
|
||||
diff --git a/sysdeps/unix/sysv/linux/sh/bits/struct_stat.h b/sysdeps/unix/sysv/linux/sh/bits/struct_stat.h
|
||||
new file mode 100644
|
||||
index 0000000000000000..0f7c9cdc89ebf686
|
||||
--- /dev/null
|
||||
+++ b/sysdeps/unix/sysv/linux/sh/bits/struct_stat.h
|
||||
@@ -0,0 +1,139 @@
|
||||
+/* Definition for struct stat. Linux/sh version.
|
||||
+ Copyright (C) 2020-2022 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/>. */
|
||||
+
|
||||
+#if !defined _SYS_STAT_H && !defined _FCNTL_H
|
||||
+# error "Never include <bits/struct_stat.h> directly; use <sys/stat.h> instead."
|
||||
+#endif
|
||||
+
|
||||
+#ifndef _BITS_STRUCT_STAT_H
|
||||
+#define _BITS_STRUCT_STAT_H 1
|
||||
+
|
||||
+#include <bits/endian.h>
|
||||
+#include <bits/wordsize.h>
|
||||
+
|
||||
+struct stat
|
||||
+ {
|
||||
+#ifdef __USE_TIME_BITS64
|
||||
+# include <bits/struct_stat_time64_helper.h>
|
||||
+#else
|
||||
+ __dev_t st_dev; /* Device. */
|
||||
+ unsigned short int __pad1;
|
||||
+# ifndef __USE_FILE_OFFSET64
|
||||
+ __ino_t st_ino; /* File serial number. */
|
||||
+# else
|
||||
+ __ino_t __st_ino; /* 32bit file serial number. */
|
||||
+# endif
|
||||
+ __mode_t st_mode; /* File mode. */
|
||||
+ __nlink_t st_nlink; /* Link count. */
|
||||
+ __uid_t st_uid; /* User ID of the file's owner. */
|
||||
+ __gid_t st_gid; /* Group ID of the file's group.*/
|
||||
+ __dev_t st_rdev; /* Device number, if device. */
|
||||
+ unsigned short int __pad2;
|
||||
+# ifndef __USE_FILE_OFFSET64
|
||||
+ __off_t st_size; /* Size of file, in bytes. */
|
||||
+# else
|
||||
+ __off64_t st_size; /* Size of file, in bytes. */
|
||||
+# endif
|
||||
+ __blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
+
|
||||
+# ifndef __USE_FILE_OFFSET64
|
||||
+ __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */
|
||||
+# else
|
||||
+ __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
|
||||
+# endif
|
||||
+# ifdef __USE_XOPEN2K8
|
||||
+ /* Nanosecond resolution timestamps are stored in a format
|
||||
+ equivalent to 'struct timespec'. This is the type used
|
||||
+ whenever possible but the Unix namespace rules do not allow the
|
||||
+ identifier 'timespec' to appear in the <sys/stat.h> header.
|
||||
+ Therefore we have to handle the use of this header in strictly
|
||||
+ standard-compliant sources special. */
|
||||
+ struct timespec st_atim; /* Time of last access. */
|
||||
+ struct timespec st_mtim; /* Time of last modification. */
|
||||
+ struct timespec st_ctim; /* Time of last status change. */
|
||||
+# define st_atime st_atim.tv_sec /* Backward compatibility. */
|
||||
+# define st_mtime st_mtim.tv_sec
|
||||
+# define st_ctime st_ctim.tv_sec
|
||||
+# else
|
||||
+ __time_t st_atime; /* Time of last access. */
|
||||
+ unsigned long int st_atimensec; /* Nscecs of last access. */
|
||||
+ __time_t st_mtime; /* Time of last modification. */
|
||||
+ unsigned long int st_mtimensec; /* Nsecs of last modification. */
|
||||
+ __time_t st_ctime; /* Time of last status change. */
|
||||
+ unsigned long int st_ctimensec; /* Nsecs of last status change. */
|
||||
+# endif
|
||||
+# ifndef __USE_FILE_OFFSET64
|
||||
+ unsigned long int __glibc_reserved4;
|
||||
+ unsigned long int __glibc_reserved5;
|
||||
+# else
|
||||
+ __ino64_t st_ino; /* File serial number. */
|
||||
+# endif
|
||||
+#endif /* __USE_TIME_BITS64 */
|
||||
+ };
|
||||
+
|
||||
+#ifdef __USE_LARGEFILE64
|
||||
+struct stat64
|
||||
+ {
|
||||
+# ifdef __USE_TIME_BITS64
|
||||
+# include <bits/struct_stat_time64_helper.h>
|
||||
+# else
|
||||
+ __dev_t st_dev; /* Device. */
|
||||
+ unsigned int __pad1;
|
||||
+
|
||||
+ __ino_t __st_ino; /* 32bit file serial number. */
|
||||
+ __mode_t st_mode; /* File mode. */
|
||||
+ __nlink_t st_nlink; /* Link count. */
|
||||
+ __uid_t st_uid; /* User ID of the file's owner. */
|
||||
+ __gid_t st_gid; /* Group ID of the file's group.*/
|
||||
+ __dev_t st_rdev; /* Device number, if device. */
|
||||
+ unsigned int __pad2;
|
||||
+ __off64_t st_size; /* Size of file, in bytes. */
|
||||
+ __blksize_t st_blksize; /* Optimal block size for I/O. */
|
||||
+
|
||||
+ __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */
|
||||
+# ifdef __USE_XOPEN2K8
|
||||
+ /* Nanosecond resolution timestamps are stored in a format
|
||||
+ equivalent to 'struct timespec'. This is the type used
|
||||
+ whenever possible but the Unix namespace rules do not allow the
|
||||
+ identifier 'timespec' to appear in the <sys/stat.h> header.
|
||||
+ Therefore we have to handle the use of this header in strictly
|
||||
+ standard-compliant sources special. */
|
||||
+ struct timespec st_atim; /* Time of last access. */
|
||||
+ struct timespec st_mtim; /* Time of last modification. */
|
||||
+ struct timespec st_ctim; /* Time of last status change. */
|
||||
+# else
|
||||
+ __time_t st_atime; /* Time of last access. */
|
||||
+ unsigned long int st_atimensec; /* Nscecs of last access. */
|
||||
+ __time_t st_mtime; /* Time of last modification. */
|
||||
+ unsigned long int st_mtimensec; /* Nsecs of last modification. */
|
||||
+ __time_t st_ctime; /* Time of last status change. */
|
||||
+ unsigned long int st_ctimensec; /* Nsecs of last status change. */
|
||||
+# endif
|
||||
+ __ino64_t st_ino; /* File serial number. */
|
||||
+# endif /* __USE_TIME_BITS64 */
|
||||
+ };
|
||||
+#endif
|
||||
+
|
||||
+/* Tell code we have these members. */
|
||||
+#define _STATBUF_ST_BLKSIZE
|
||||
+#define _STATBUF_ST_RDEV
|
||||
+/* Nanosecond resolution time values are supported. */
|
||||
+#define _STATBUF_ST_NSEC
|
||||
+
|
||||
+
|
||||
+#endif /* _BITS_STRUCT_STAT_H */
|
@ -0,0 +1,73 @@
|
||||
commit 675ba1f361ea424626b48a40cfd24d113dfc1b65
|
||||
Author: Paul Eggert <eggert@cs.ucla.edu>
|
||||
Date: Thu Sep 8 20:08:32 2022 -0500
|
||||
|
||||
mktime: improve heuristic for ca-1986 Indiana DST
|
||||
|
||||
This patch syncs mktime.c from Gnulib, fixing a
|
||||
problem reported by Mark Krenz <https://bugs.gnu.org/48085>,
|
||||
and it should fix BZ#29035 too.
|
||||
* time/mktime.c (__mktime_internal): Be more generous about
|
||||
accepting arguments with the wrong value of tm_isdst, by falling
|
||||
back to a one-hour DST difference if we find no nearby DST that is
|
||||
unusual. This fixes a problem where "1986-04-28 00:00 EDT" was
|
||||
rejected when TZ="America/Indianapolis" because the nearest DST
|
||||
timestamp occurred in 1970, a temporal distance too great for the
|
||||
old heuristic. This also also narrows the search a bit, which
|
||||
is a minor performance win.
|
||||
|
||||
(cherry picked from commit 83859e1115269cf56d21669361d4ddbe2687831c)
|
||||
|
||||
diff --git a/time/mktime.c b/time/mktime.c
|
||||
index 8e78006eea7e693b..74d9bbaa5b375723 100644
|
||||
--- a/time/mktime.c
|
||||
+++ b/time/mktime.c
|
||||
@@ -429,8 +429,13 @@ __mktime_internal (struct tm *tp,
|
||||
time with the right value, and use its UTC offset.
|
||||
|
||||
Heuristic: probe the adjacent timestamps in both directions,
|
||||
- looking for the desired isdst. This should work for all real
|
||||
- time zone histories in the tz database. */
|
||||
+ looking for the desired isdst. If none is found within a
|
||||
+ reasonable duration bound, assume a one-hour DST difference.
|
||||
+ This should work for all real time zone histories in the tz
|
||||
+ database. */
|
||||
+
|
||||
+ /* +1 if we wanted standard time but got DST, -1 if the reverse. */
|
||||
+ int dst_difference = (isdst == 0) - (tm.tm_isdst == 0);
|
||||
|
||||
/* Distance between probes when looking for a DST boundary. In
|
||||
tzdata2003a, the shortest period of DST is 601200 seconds
|
||||
@@ -441,12 +446,14 @@ __mktime_internal (struct tm *tp,
|
||||
periods when probing. */
|
||||
int stride = 601200;
|
||||
|
||||
- /* The longest period of DST in tzdata2003a is 536454000 seconds
|
||||
- (e.g., America/Jujuy starting 1946-10-01 01:00). The longest
|
||||
- period of non-DST is much longer, but it makes no real sense
|
||||
- to search for more than a year of non-DST, so use the DST
|
||||
- max. */
|
||||
- int duration_max = 536454000;
|
||||
+ /* In TZDB 2021e, the longest period of DST (or of non-DST), in
|
||||
+ which the DST (or adjacent DST) difference is not one hour,
|
||||
+ is 457243209 seconds: e.g., America/Cambridge_Bay with leap
|
||||
+ seconds, starting 1965-10-31 00:00 in a switch from
|
||||
+ double-daylight time (-05) to standard time (-07), and
|
||||
+ continuing to 1980-04-27 02:00 in a switch from standard time
|
||||
+ (-07) to daylight time (-06). */
|
||||
+ int duration_max = 457243209;
|
||||
|
||||
/* Search in both directions, so the maximum distance is half
|
||||
the duration; add the stride to avoid off-by-1 problems. */
|
||||
@@ -483,6 +490,11 @@ __mktime_internal (struct tm *tp,
|
||||
}
|
||||
}
|
||||
|
||||
+ /* No unusual DST offset was found nearby. Assume one-hour DST. */
|
||||
+ t += 60 * 60 * dst_difference;
|
||||
+ if (mktime_min <= t && t <= mktime_max && convert_time (convert, t, &tm))
|
||||
+ goto offset_found;
|
||||
+
|
||||
__set_errno (EOVERFLOW);
|
||||
return -1;
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
commit 6e8044e910600f71f4802dba2d105007af8428c3
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Mon Nov 8 19:11:51 2021 +0000
|
||||
|
||||
Fix memmove call in vfprintf-internal.c:group_number
|
||||
|
||||
A recent GCC mainline change introduces errors of the form:
|
||||
|
||||
vfprintf-internal.c: In function 'group_number':
|
||||
vfprintf-internal.c:2093:15: error: 'memmove' specified bound between 9223372036854775808 and 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=]
|
||||
2093 | memmove (w, s, (front_ptr -s) * sizeof (CHAR_T));
|
||||
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This is a genuine bug in the glibc code: s > front_ptr is always true
|
||||
at this point in the code, and the intent is clearly for the
|
||||
subtraction to be the other way round. The other arguments to the
|
||||
memmove call here also appear to be wrong; w and s point just *after*
|
||||
the destination and source for copying the rest of the number, so the
|
||||
size needs to be subtracted to get appropriate pointers for the
|
||||
copying. Adjust the memmove call to conform to the apparent intent of
|
||||
the code, so fixing the -Wstringop-overflow error.
|
||||
|
||||
Now, if the original code were ever executed, a buffer overrun would
|
||||
result. However, I believe this code (introduced in commit
|
||||
edc1686af0c0fc2eb535f1d38cdf63c1a5a03675, "vfprintf: Reuse work_buffer
|
||||
in group_number", so in glibc 2.26) is unreachable in prior glibc
|
||||
releases (so there is no need for a bug in Bugzilla, no need to
|
||||
consider any backports unless someone wants to build older glibc
|
||||
releases with GCC 12 and no possibility of this buffer overrun
|
||||
resulting in a security issue).
|
||||
|
||||
work_buffer is 1000 bytes / 250 wide characters. This case is only
|
||||
reachable if an initial part of the number, plus a grouped copy of the
|
||||
rest of the number, fail to fit in that space; that is, if the grouped
|
||||
number fails to fit in the space. In the wide character case,
|
||||
grouping is always one wide character, so even with a locale (of which
|
||||
there aren't any in glibc) grouping every digit, a number would need
|
||||
to occupy at least 125 wide characters to overflow, and a 64-bit
|
||||
integer occupies at most 23 characters in octal including a leading 0.
|
||||
In the narrow character case, the multibyte encoding of the grouping
|
||||
separator would need to be at least 42 bytes to overflow, again
|
||||
supposing grouping every digit, but MB_LEN_MAX is 16. So even if we
|
||||
admit the case of artificially constructed locales not shipped with
|
||||
glibc, given that such a locale would need to use one of the character
|
||||
sets supported by glibc, this code cannot be reached at present. (And
|
||||
POSIX only actually specifies the ' flag for grouping for decimal
|
||||
output, though glibc acts on it for other bases as well.)
|
||||
|
||||
With binary output (if you consider use of grouping there to be
|
||||
valid), you'd need a 15-byte multibyte character for overflow; I don't
|
||||
know if any supported character set has such a character (if, again,
|
||||
we admit constructed locales using grouping every digit and a grouping
|
||||
separator chosen to have a multibyte encoding as long as possible, as
|
||||
well as accepting use of grouping with binary), but given that we have
|
||||
this code at all (clearly it's not *correct*, or in accordance with
|
||||
the principle of avoiding arbitrary limits, to skip grouping on
|
||||
running out of internal space like that), I don't think it should need
|
||||
any further changes for binary printf support to go in.
|
||||
|
||||
On the other hand, support for large sizes of _BitInt in printf (see
|
||||
the N2858 proposal) *would* require something to be done about such
|
||||
arbitrary limits (presumably using dynamic allocation in printf again,
|
||||
for sufficiently large _BitInt arguments only - currently only
|
||||
floating-point uses dynamic allocation, and, as previously discussed,
|
||||
that could actually be replaced by bounded allocation given smarter
|
||||
code).
|
||||
|
||||
Tested with build-many-glibcs.py for aarch64-linux-gnu (GCC mainline).
|
||||
Also tested natively for x86_64.
|
||||
|
||||
(cherry picked from commit db6c4935fae6005d46af413b32aa92f4f6059dce)
|
||||
|
||||
diff --git a/stdio-common/vfprintf-internal.c b/stdio-common/vfprintf-internal.c
|
||||
index 3f3d1e148a8e7fda..53d93b2f07ecb261 100644
|
||||
--- a/stdio-common/vfprintf-internal.c
|
||||
+++ b/stdio-common/vfprintf-internal.c
|
||||
@@ -2154,7 +2154,8 @@ group_number (CHAR_T *front_ptr, CHAR_T *w, CHAR_T *rear_ptr,
|
||||
copy_rest:
|
||||
/* No further grouping to be done. Copy the rest of the
|
||||
number. */
|
||||
- memmove (w, s, (front_ptr -s) * sizeof (CHAR_T));
|
||||
+ w -= s - front_ptr;
|
||||
+ memmove (w, front_ptr, (s - front_ptr) * sizeof (CHAR_T));
|
||||
break;
|
||||
}
|
||||
else if (*grouping != '\0')
|
@ -0,0 +1,35 @@
|
||||
commit 291d4402067760edb7c0f339f9e451787a25e20a
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Fri Aug 27 17:47:46 2021 +0000
|
||||
|
||||
Allow #pragma GCC in headers in conformtest
|
||||
|
||||
No "#pragma GCC" pragma allows macro-expansion of its arguments, so no
|
||||
namespace issues arise from use of such pragmas in installed headers.
|
||||
Ignore them in conformtest tests of header namespace.
|
||||
|
||||
Tested for x86_64, in conjunction with Paul's patch
|
||||
<https://sourceware.org/pipermail/libc-alpha/2021-August/130571.html>
|
||||
adding use of such pragmas to installed headers shared with gnulib.
|
||||
|
||||
(cherry picked from commit 6090a4a1b32fd7859d0ad5b7e9b240bd5fa04b3f)
|
||||
|
||||
diff --git a/conform/conformtest.py b/conform/conformtest.py
|
||||
index 4898e16c9fb96503..164cf2917d464aa1 100644
|
||||
--- a/conform/conformtest.py
|
||||
+++ b/conform/conformtest.py
|
||||
@@ -631,6 +631,14 @@ class HeaderTests(object):
|
||||
continue
|
||||
if re.match(r'# [1-9]', line):
|
||||
continue
|
||||
+ if line.startswith('#pragma GCC '):
|
||||
+ # No GCC pragma uses macro expansion, so no
|
||||
+ # namespace issues arise from such pragmas. (Some
|
||||
+ # pragmas not in the GCC namespace do macro-expand
|
||||
+ # their arguments and so could be affected by
|
||||
+ # macros defined by user code including the
|
||||
+ # header.)
|
||||
+ continue
|
||||
match = re.match(r'#define (.*)', line)
|
||||
if match:
|
||||
self.check_token(bad_tokens, match.group(1))
|
@ -0,0 +1,30 @@
|
||||
commit fa5044f1e38f4f6515253449b6ca77fd14f53b8e
|
||||
Author: Paul Eggert <eggert@cs.ucla.edu>
|
||||
Date: Wed Nov 24 14:16:09 2021 -0800
|
||||
|
||||
regex: fix buffer read overrun in search [BZ#28470]
|
||||
|
||||
Problem reported by Benno Schulenberg in:
|
||||
https://lists.gnu.org/r/bug-gnulib/2021-10/msg00035.html
|
||||
* posix/regexec.c (re_search_internal): Use better bounds check.
|
||||
|
||||
(cherry picked from commit c52ef24829f95a819965214eeae28e3289a91a61)
|
||||
|
||||
diff --git a/posix/regexec.c b/posix/regexec.c
|
||||
index 83e9aaf8cad956a2..6aeba3c0b4da23cc 100644
|
||||
--- a/posix/regexec.c
|
||||
+++ b/posix/regexec.c
|
||||
@@ -758,10 +758,9 @@ re_search_internal (const regex_t *preg, const char *string, Idx length,
|
||||
|
||||
offset = match_first - mctx.input.raw_mbs_idx;
|
||||
}
|
||||
- /* If MATCH_FIRST is out of the buffer, leave it as '\0'.
|
||||
- Note that MATCH_FIRST must not be smaller than 0. */
|
||||
- ch = (match_first >= length
|
||||
- ? 0 : re_string_byte_at (&mctx.input, offset));
|
||||
+ /* Use buffer byte if OFFSET is in buffer, otherwise '\0'. */
|
||||
+ ch = (offset < mctx.input.valid_len
|
||||
+ ? re_string_byte_at (&mctx.input, offset) : 0);
|
||||
if (fastmap[ch])
|
||||
break;
|
||||
match_first += incr;
|
@ -0,0 +1,203 @@
|
||||
commit 06afa5e09fbd984ed45ae6fc6ca050d544aba780
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Wed Aug 25 11:17:06 2021 -0300
|
||||
|
||||
io: Fix ftw internal realloc buffer (BZ #28126)
|
||||
|
||||
The 106ff08526d3ca did not take in consideration the buffer might be
|
||||
reallocated if the total path is larger than PATH_MAX. The realloc
|
||||
uses 'dirbuf', where 'dirstreams' is the allocated buffer.
|
||||
|
||||
Checked on x86_64-linux-gnu.
|
||||
|
||||
Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
(cherry picked from commit 1836bb2ebf62bd9a3588f2ed2d851c8ae810097a)
|
||||
|
||||
diff --git a/io/Makefile b/io/Makefile
|
||||
index 01968b81042e01e4..5284a1282dd07e3d 100644
|
||||
--- a/io/Makefile
|
||||
+++ b/io/Makefile
|
||||
@@ -79,6 +79,7 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \
|
||||
tst-futimens \
|
||||
tst-utimensat \
|
||||
tst-closefrom \
|
||||
+ tst-ftw-bz28126
|
||||
|
||||
tests-time64 := \
|
||||
tst-fcntl-time64 \
|
||||
diff --git a/io/ftw.c b/io/ftw.c
|
||||
index ce1c6a14a306152a..cf08d9f101657df0 100644
|
||||
--- a/io/ftw.c
|
||||
+++ b/io/ftw.c
|
||||
@@ -204,6 +204,20 @@ struct ftw_data
|
||||
void *known_objects;
|
||||
};
|
||||
|
||||
+static bool
|
||||
+ftw_allocate (struct ftw_data *data, size_t newsize)
|
||||
+{
|
||||
+ void *newp = realloc (data->dirstreams, data->maxdir
|
||||
+ * sizeof (struct dir_data *)
|
||||
+ + newsize);
|
||||
+ if (newp == NULL)
|
||||
+ return false;
|
||||
+ data->dirstreams = newp;
|
||||
+ data->dirbufsize = newsize;
|
||||
+ data->dirbuf = (char *) data->dirstreams
|
||||
+ + data->maxdir * sizeof (struct dir_data *);
|
||||
+ return true;
|
||||
+}
|
||||
|
||||
/* Internally we use the FTW_* constants used for `nftw'. When invoked
|
||||
as `ftw', map each flag to the subset of values used by `ftw'. */
|
||||
@@ -389,17 +403,9 @@ process_entry (struct ftw_data *data, struct dir_data *dir, const char *name,
|
||||
return 0;
|
||||
|
||||
new_buflen = data->ftw.base + namlen + 2;
|
||||
- if (data->dirbufsize < new_buflen)
|
||||
- {
|
||||
- /* Enlarge the buffer. */
|
||||
- char *newp;
|
||||
-
|
||||
- data->dirbufsize = 2 * new_buflen;
|
||||
- newp = (char *) realloc (data->dirbuf, data->dirbufsize);
|
||||
- if (newp == NULL)
|
||||
- return -1;
|
||||
- data->dirbuf = newp;
|
||||
- }
|
||||
+ if (data->dirbufsize < new_buflen
|
||||
+ && !ftw_allocate (data, 2 * new_buflen))
|
||||
+ return -1;
|
||||
|
||||
*((char *) __mempcpy (data->dirbuf + data->ftw.base, name, namlen)) = '\0';
|
||||
|
||||
@@ -629,7 +635,7 @@ __attribute ((noinline))
|
||||
ftw_startup (const char *dir, int is_nftw, void *func, int descriptors,
|
||||
int flags)
|
||||
{
|
||||
- struct ftw_data data;
|
||||
+ struct ftw_data data = { .dirstreams = NULL };
|
||||
struct STRUCT_STAT st;
|
||||
int result = 0;
|
||||
int save_err;
|
||||
@@ -647,16 +653,9 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors,
|
||||
data.maxdir = descriptors < 1 ? 1 : descriptors;
|
||||
data.actdir = 0;
|
||||
/* PATH_MAX is always defined when we get here. */
|
||||
- data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX);
|
||||
- data.dirstreams = malloc (data.maxdir * sizeof (struct dir_data *)
|
||||
- + data.dirbufsize);
|
||||
- if (data.dirstreams == NULL)
|
||||
+ if (!ftw_allocate (&data, MAX (2 * strlen (dir), PATH_MAX)))
|
||||
return -1;
|
||||
-
|
||||
memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *));
|
||||
-
|
||||
- data.dirbuf = (char *) data.dirstreams
|
||||
- + data.maxdir * sizeof (struct dir_data *);
|
||||
cp = __stpcpy (data.dirbuf, dir);
|
||||
/* Strip trailing slashes. */
|
||||
while (cp > data.dirbuf + 1 && cp[-1] == '/')
|
||||
diff --git a/io/tst-ftw-bz28126.c b/io/tst-ftw-bz28126.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..94044ab9d1d0275b
|
||||
--- /dev/null
|
||||
+++ b/io/tst-ftw-bz28126.c
|
||||
@@ -0,0 +1,97 @@
|
||||
+/* Check if internal buffer reallocation work for large paths (BZ #28126)
|
||||
+ Copyright (C) 2021 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 <ftw.h>
|
||||
+#include <limits.h>
|
||||
+#include <string.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <support/xunistd.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+static int
|
||||
+my_func (const char *file, const struct stat *sb, int flag)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const char folder[NAME_MAX] = { [0 ... 253] = 'a', [254] = '\0' };
|
||||
+
|
||||
+#define NSUBFOLDERS 16
|
||||
+static int nsubfolders;
|
||||
+
|
||||
+static void
|
||||
+do_cleanup (void)
|
||||
+{
|
||||
+ xchdir ("..");
|
||||
+ for (int i = 0; i < nsubfolders; i++)
|
||||
+ {
|
||||
+ remove (folder);
|
||||
+ xchdir ("..");
|
||||
+ }
|
||||
+ remove (folder);
|
||||
+}
|
||||
+#define CLEANUP_HANDLER do_cleanup
|
||||
+
|
||||
+static void
|
||||
+check_mkdir (const char *path)
|
||||
+{
|
||||
+ int r = mkdir (path, 0777);
|
||||
+ /* Some filesystem such as overlayfs does not support larger path required
|
||||
+ to trigger the internal buffer reallocation. */
|
||||
+ if (r != 0)
|
||||
+ {
|
||||
+ if (errno == ENAMETOOLONG)
|
||||
+ FAIL_UNSUPPORTED ("the filesystem does not support the required"
|
||||
+ "large path");
|
||||
+ else
|
||||
+ FAIL_EXIT1 ("mkdir (\"%s\", 0%o): %m", folder, 0777);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ char *tempdir = support_create_temp_directory ("tst-bz28126");
|
||||
+
|
||||
+ /* Create path with various subfolders to force an internal buffer
|
||||
+ reallocation within ntfw. */
|
||||
+ char *path = xasprintf ("%s/%s", tempdir, folder);
|
||||
+ check_mkdir (path);
|
||||
+ xchdir (path);
|
||||
+ free (path);
|
||||
+ for (int i = 0; i < NSUBFOLDERS - 1; i++)
|
||||
+ {
|
||||
+ check_mkdir (folder);
|
||||
+ xchdir (folder);
|
||||
+ nsubfolders++;
|
||||
+ }
|
||||
+
|
||||
+ TEST_COMPARE (ftw (tempdir, my_func, 20), 0);
|
||||
+
|
||||
+ free (tempdir);
|
||||
+
|
||||
+ do_cleanup ();
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
@ -0,0 +1,25 @@
|
||||
commit deea6ab1bcb2696be514e579f3263c234ecc1683
|
||||
Author: Martin Sebor <msebor@redhat.com>
|
||||
Date: Tue Jan 25 17:39:02 2022 -0700
|
||||
|
||||
io: Fix use-after-free in ftw [BZ #26779]
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit ee52ab25ba875f458981fce22c54e3c04c7a17d3)
|
||||
|
||||
diff --git a/io/ftw.c b/io/ftw.c
|
||||
index cf08d9f101657df0..91a4e8e6de151ca1 100644
|
||||
--- a/io/ftw.c
|
||||
+++ b/io/ftw.c
|
||||
@@ -324,8 +324,9 @@ open_dir_stream (int *dfdp, struct ftw_data *data, struct dir_data *dirp)
|
||||
buf[actsize++] = '\0';
|
||||
|
||||
/* Shrink the buffer to what we actually need. */
|
||||
- data->dirstreams[data->actdir]->content = realloc (buf, actsize);
|
||||
- if (data->dirstreams[data->actdir]->content == NULL)
|
||||
+ void *content = realloc (buf, actsize);
|
||||
+ data->dirstreams[data->actdir]->content = content;
|
||||
+ if (content == NULL)
|
||||
{
|
||||
int save_err = errno;
|
||||
free (buf);
|
@ -0,0 +1,46 @@
|
||||
commit 691f70b84a1284f35c8cf9fbf3ef3b1cec41c234
|
||||
Author: Vladislav Khmelevsky <och95@yandex.ru>
|
||||
Date: Thu Nov 17 12:47:29 2022 +0400
|
||||
|
||||
elf: Fix rtld-audit trampoline for aarch64
|
||||
|
||||
This patch fixes two problems with audit:
|
||||
|
||||
1. The DL_OFFSET_RV_VPCS offset was mixed up with DL_OFFSET_RG_VPCS,
|
||||
resulting in x2 register value nulling in RG structure.
|
||||
|
||||
2. We need to preserve the x8 register before function call, but
|
||||
don't have to save it's new value and restore it before return.
|
||||
|
||||
Anyway the final restore was using OFFSET_RV instead of OFFSET_RG value
|
||||
which is wrong (althoug doesn't affect anything).
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
(cherry picked from commit eb4181e9f4a512de37dad4ba623c921671584dea)
|
||||
|
||||
diff --git a/sysdeps/aarch64/dl-trampoline.S b/sysdeps/aarch64/dl-trampoline.S
|
||||
index 457570e7df5148c0..b84c53d1a544c1b1 100644
|
||||
--- a/sysdeps/aarch64/dl-trampoline.S
|
||||
+++ b/sysdeps/aarch64/dl-trampoline.S
|
||||
@@ -298,12 +298,11 @@ _dl_runtime_profile:
|
||||
stp x2, x3, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*1]
|
||||
stp x4, x5, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*2]
|
||||
stp x6, x7, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*3]
|
||||
- str x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4]
|
||||
stp q0, q1, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*0]
|
||||
stp q2, q3, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*1]
|
||||
stp q4, q5, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*2]
|
||||
stp q6, q7, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*3]
|
||||
- str xzr, [X29, #OFFSET_RV + DL_OFFSET_RG_VPCS]
|
||||
+ str xzr, [X29, #OFFSET_RV + DL_OFFSET_RV_VPCS]
|
||||
|
||||
/* Setup call to pltexit */
|
||||
ldp x0, x1, [x29, #OFFSET_SAVED_CALL_X0]
|
||||
@@ -315,7 +314,6 @@ _dl_runtime_profile:
|
||||
ldp x2, x3, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*1]
|
||||
ldp x4, x5, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*2]
|
||||
ldp x6, x7, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*3]
|
||||
- ldr x8, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*4]
|
||||
ldp q0, q1, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*0]
|
||||
ldp q2, q3, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*1]
|
||||
ldp q4, q5, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*2]
|
@ -0,0 +1,128 @@
|
||||
commit e3255e7d2188d1731aad83ad0dc147513560aa1e
|
||||
Author: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||
Date: Tue Sep 20 17:58:04 2022 -0700
|
||||
|
||||
x86: Fix wcsnlen-avx2 page cross length comparison [BZ #29591]
|
||||
|
||||
Previous implementation was adjusting length (rsi) to match
|
||||
bytes (eax), but since there is no bound to length this can cause
|
||||
overflow.
|
||||
|
||||
Fix is to just convert the byte-count (eax) to length by dividing by
|
||||
sizeof (wchar_t) before the comparison.
|
||||
|
||||
Full check passes on x86-64 and build succeeds w/ and w/o multiarch.
|
||||
|
||||
(cherry picked from commit b0969fa53a28b4ab2159806bf6c99a98999502ee)
|
||||
|
||||
diff --git a/string/test-strnlen.c b/string/test-strnlen.c
|
||||
index bb5d9b5f04fa6586..eac84cd17526d5d9 100644
|
||||
--- a/string/test-strnlen.c
|
||||
+++ b/string/test-strnlen.c
|
||||
@@ -75,7 +75,7 @@ do_test (size_t align, size_t len, size_t maxlen, int max_char)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
- align &= 63;
|
||||
+ align &= (getpagesize () / sizeof (CHAR) - 1);
|
||||
if ((align + len) * sizeof (CHAR) >= page_size)
|
||||
return;
|
||||
|
||||
@@ -92,36 +92,50 @@ do_test (size_t align, size_t len, size_t maxlen, int max_char)
|
||||
static void
|
||||
do_overflow_tests (void)
|
||||
{
|
||||
- size_t i, j, len;
|
||||
+ size_t i, j, al_idx, repeats, len;
|
||||
const size_t one = 1;
|
||||
uintptr_t buf_addr = (uintptr_t) buf1;
|
||||
+ const size_t alignments[] = { 0, 1, 7, 9, 31, 33, 63, 65, 95, 97, 127, 129 };
|
||||
|
||||
- for (i = 0; i < 750; ++i)
|
||||
+ for (al_idx = 0; al_idx < sizeof (alignments) / sizeof (alignments[0]);
|
||||
+ al_idx++)
|
||||
{
|
||||
- do_test (0, i, SIZE_MAX - i, BIG_CHAR);
|
||||
- do_test (0, i, i - buf_addr, BIG_CHAR);
|
||||
- do_test (0, i, -buf_addr - i, BIG_CHAR);
|
||||
- do_test (0, i, SIZE_MAX - buf_addr - i, BIG_CHAR);
|
||||
- do_test (0, i, SIZE_MAX - buf_addr + i, BIG_CHAR);
|
||||
-
|
||||
- len = 0;
|
||||
- for (j = 8 * sizeof(size_t) - 1; j ; --j)
|
||||
- {
|
||||
- len |= one << j;
|
||||
- do_test (0, i, len - i, BIG_CHAR);
|
||||
- do_test (0, i, len + i, BIG_CHAR);
|
||||
- do_test (0, i, len - buf_addr - i, BIG_CHAR);
|
||||
- do_test (0, i, len - buf_addr + i, BIG_CHAR);
|
||||
-
|
||||
- do_test (0, i, ~len - i, BIG_CHAR);
|
||||
- do_test (0, i, ~len + i, BIG_CHAR);
|
||||
- do_test (0, i, ~len - buf_addr - i, BIG_CHAR);
|
||||
- do_test (0, i, ~len - buf_addr + i, BIG_CHAR);
|
||||
-
|
||||
- do_test (0, i, -buf_addr, BIG_CHAR);
|
||||
- do_test (0, i, j - buf_addr, BIG_CHAR);
|
||||
- do_test (0, i, -buf_addr - j, BIG_CHAR);
|
||||
- }
|
||||
+ for (repeats = 0; repeats < 2; ++repeats)
|
||||
+ {
|
||||
+ size_t align = repeats ? (getpagesize () - alignments[al_idx])
|
||||
+ : alignments[al_idx];
|
||||
+ align /= sizeof (CHAR);
|
||||
+ for (i = 0; i < 750; ++i)
|
||||
+ {
|
||||
+ do_test (align, i, SIZE_MAX, BIG_CHAR);
|
||||
+
|
||||
+ do_test (align, i, SIZE_MAX - i, BIG_CHAR);
|
||||
+ do_test (align, i, i - buf_addr, BIG_CHAR);
|
||||
+ do_test (align, i, -buf_addr - i, BIG_CHAR);
|
||||
+ do_test (align, i, SIZE_MAX - buf_addr - i, BIG_CHAR);
|
||||
+ do_test (align, i, SIZE_MAX - buf_addr + i, BIG_CHAR);
|
||||
+
|
||||
+ len = 0;
|
||||
+ for (j = 8 * sizeof (size_t) - 1; j; --j)
|
||||
+ {
|
||||
+ len |= one << j;
|
||||
+ do_test (align, i, len, BIG_CHAR);
|
||||
+ do_test (align, i, len - i, BIG_CHAR);
|
||||
+ do_test (align, i, len + i, BIG_CHAR);
|
||||
+ do_test (align, i, len - buf_addr - i, BIG_CHAR);
|
||||
+ do_test (align, i, len - buf_addr + i, BIG_CHAR);
|
||||
+
|
||||
+ do_test (align, i, ~len - i, BIG_CHAR);
|
||||
+ do_test (align, i, ~len + i, BIG_CHAR);
|
||||
+ do_test (align, i, ~len - buf_addr - i, BIG_CHAR);
|
||||
+ do_test (align, i, ~len - buf_addr + i, BIG_CHAR);
|
||||
+
|
||||
+ do_test (align, i, -buf_addr, BIG_CHAR);
|
||||
+ do_test (align, i, j - buf_addr, BIG_CHAR);
|
||||
+ do_test (align, i, -buf_addr - j, BIG_CHAR);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/sysdeps/x86_64/multiarch/strlen-avx2.S b/sysdeps/x86_64/multiarch/strlen-avx2.S
|
||||
index b282a75613bf52ab..4d7d68396bcd4049 100644
|
||||
--- a/sysdeps/x86_64/multiarch/strlen-avx2.S
|
||||
+++ b/sysdeps/x86_64/multiarch/strlen-avx2.S
|
||||
@@ -542,14 +542,11 @@ L(return_vzeroupper):
|
||||
L(cross_page_less_vec):
|
||||
tzcntl %eax, %eax
|
||||
# ifdef USE_AS_WCSLEN
|
||||
- /* NB: Multiply length by 4 to get byte count. */
|
||||
- sall $2, %esi
|
||||
+ /* NB: Divide by 4 to convert from byte-count to length. */
|
||||
+ shrl $2, %eax
|
||||
# endif
|
||||
cmpq %rax, %rsi
|
||||
cmovb %esi, %eax
|
||||
-# ifdef USE_AS_WCSLEN
|
||||
- shrl $2, %eax
|
||||
-# endif
|
||||
VZEROUPPER_RETURN
|
||||
# endif
|
||||
|
@ -0,0 +1,26 @@
|
||||
commit 309c4708aca762f57263a66e5bea926fdbfd82eb
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Fri Mar 25 11:16:49 2022 -0300
|
||||
|
||||
elf: Fix wrong fscanf usage on tst-pldd
|
||||
|
||||
To take in consideration the extra '\0'.
|
||||
|
||||
Checked on x86_64-linux-gnu.
|
||||
|
||||
(cherry picked from commit b2cd93fce666fdc8c9a5c64af2741a8a6940ac99)
|
||||
|
||||
diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c
|
||||
index 210ca4d24b8338ab..72b7a99b369a105d 100644
|
||||
--- a/elf/tst-pldd.c
|
||||
+++ b/elf/tst-pldd.c
|
||||
@@ -113,7 +113,8 @@ do_test (void)
|
||||
TEST_VERIFY (out != NULL);
|
||||
|
||||
/* First line is in the form of <pid>: <full path of executable> */
|
||||
- TEST_COMPARE (fscanf (out, "%u: " STRINPUT (512), &pid, buffer), 2);
|
||||
+ TEST_COMPARE (fscanf (out, "%u: " STRINPUT (sizeof (buffer) - 1), &pid,
|
||||
+ buffer), 2);
|
||||
|
||||
TEST_COMPARE (pid, *target_pid_ptr);
|
||||
TEST_COMPARE (strcmp (basename (buffer), "tst-pldd"), 0);
|
@ -0,0 +1,39 @@
|
||||
commit 405b8ae13540e9fd614df614e3361ebf9abd14cf
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Tue Jul 5 12:58:40 2022 -0300
|
||||
|
||||
elf: Fix wrong fscanf usage on tst-pldd
|
||||
|
||||
The fix done b2cd93fce666fdc8c9a5c64af2741a8a6940ac99 does not really
|
||||
work since macro strification does not expand the sizeof nor the
|
||||
arithmetic operation.
|
||||
|
||||
Checked on x86_64-linux-gnu.
|
||||
|
||||
(cherry picked from commit c353689e49e72f3aafa1a9e68d4f7a4f33a79cbe)
|
||||
|
||||
diff --git a/elf/tst-pldd.c b/elf/tst-pldd.c
|
||||
index 6e4174cbf95b15c0..d3ecb99149d619c6 100644
|
||||
--- a/elf/tst-pldd.c
|
||||
+++ b/elf/tst-pldd.c
|
||||
@@ -108,15 +108,16 @@ do_test (void)
|
||||
loader and libc. */
|
||||
{
|
||||
pid_t pid;
|
||||
- char buffer[512];
|
||||
-#define STRINPUT(size) "%" # size "s"
|
||||
+#define BUFFERLEN 511
|
||||
+ char buffer[BUFFERLEN + 1];
|
||||
+#define STRINPUT(size) XSTRINPUT(size)
|
||||
+#define XSTRINPUT(size) "%" # size "s"
|
||||
|
||||
FILE *out = fmemopen (pldd.out.buffer, pldd.out.length, "r");
|
||||
TEST_VERIFY (out != NULL);
|
||||
|
||||
/* First line is in the form of <pid>: <full path of executable> */
|
||||
- TEST_COMPARE (fscanf (out, "%u: " STRINPUT (sizeof (buffer) - 1), &pid,
|
||||
- buffer), 2);
|
||||
+ TEST_COMPARE (fscanf (out, "%u: " STRINPUT (BUFFERLEN), &pid, buffer), 2);
|
||||
|
||||
TEST_COMPARE (pid, *target_pid_ptr);
|
||||
TEST_COMPARE (strcmp (basename (buffer), "tst-pldd"), 0);
|
@ -0,0 +1,29 @@
|
||||
commit a1c12fdf3f9b8665719835ce8330b3b2e2574b37
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Fri Sep 10 13:18:36 2021 +0200
|
||||
|
||||
_Static_assert needs two arguments for compatibility with GCC before 9
|
||||
|
||||
This macro definition enforces two arguments even with newer compilers
|
||||
that accept the single-argument form, too.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit c9fef4b7d1d0f2dad192c74f06102752247677a9)
|
||||
|
||||
diff --git a/include/sys/cdefs.h b/include/sys/cdefs.h
|
||||
index 6a76160ed4e4cabb..56adb231aa8f8cbe 100644
|
||||
--- a/include/sys/cdefs.h
|
||||
+++ b/include/sys/cdefs.h
|
||||
@@ -1,5 +1,12 @@
|
||||
#ifndef _SYS_CDEFS_H
|
||||
|
||||
+/* This is outside of _ISOMAC to enforce that _Static_assert always
|
||||
+ uses the two-argument form. This can be removed once the minimum
|
||||
+ GCC version used to compile glibc is GCC 9.1. */
|
||||
+#ifndef __cplusplus
|
||||
+# define _Static_assert(expr, diagnostic) _Static_assert (expr, diagnostic)
|
||||
+#endif
|
||||
+
|
||||
#include <misc/sys/cdefs.h>
|
||||
|
||||
#ifndef _ISOMAC
|
@ -0,0 +1,72 @@
|
||||
commit a4217408a3d6050a7f42ac23adb6ac7218dca85f
|
||||
Author: Tulio Magno Quites Machado Filho <tuliom@redhat.com>
|
||||
Date: Fri Nov 11 17:00:15 2022 -0300
|
||||
|
||||
Apply asm redirections in syslog.h before first use [BZ #27087]
|
||||
|
||||
Similar to d0fa09a770, but for syslog.h when _FORTIFY_SOURCE > 0.
|
||||
Fixes [BZ #27087] by applying long double-related asm redirections
|
||||
before using functions in bits/syslog.h.
|
||||
|
||||
Tested with build-many-glibcs.py.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
(cherry picked from commit 227df6243a2b5b4d70d11772d12c02eb9cb666ca)
|
||||
|
||||
diff --git a/misc/bits/syslog.h b/misc/bits/syslog.h
|
||||
index 6f3137a98ee593f3..10c9c1151382a51c 100644
|
||||
--- a/misc/bits/syslog.h
|
||||
+++ b/misc/bits/syslog.h
|
||||
@@ -24,6 +24,20 @@
|
||||
extern void __syslog_chk (int __pri, int __flag, const char *__fmt, ...)
|
||||
__attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
|
||||
+#ifdef __USE_MISC
|
||||
+extern void __vsyslog_chk (int __pri, int __flag, const char *__fmt,
|
||||
+ __gnuc_va_list __ap)
|
||||
+ __attribute__ ((__format__ (__printf__, 3, 0)));
|
||||
+#endif
|
||||
+
|
||||
+#include <bits/floatn.h>
|
||||
+#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
|
||||
+# include <bits/syslog-ldbl.h>
|
||||
+#endif
|
||||
+
|
||||
+/* The following functions must be used only after applying all asm
|
||||
+ redirections, e.g. long double asm redirections. */
|
||||
+
|
||||
#ifdef __va_arg_pack
|
||||
__fortify_function void
|
||||
syslog (int __pri, const char *__fmt, ...)
|
||||
@@ -37,10 +51,6 @@ syslog (int __pri, const char *__fmt, ...)
|
||||
|
||||
|
||||
#ifdef __USE_MISC
|
||||
-extern void __vsyslog_chk (int __pri, int __flag, const char *__fmt,
|
||||
- __gnuc_va_list __ap)
|
||||
- __attribute__ ((__format__ (__printf__, 3, 0)));
|
||||
-
|
||||
__fortify_function void
|
||||
vsyslog (int __pri, const char *__fmt, __gnuc_va_list __ap)
|
||||
{
|
||||
diff --git a/misc/sys/syslog.h b/misc/sys/syslog.h
|
||||
index dc3b0e7ef81de812..e7a98fb9b13ce132 100644
|
||||
--- a/misc/sys/syslog.h
|
||||
+++ b/misc/sys/syslog.h
|
||||
@@ -205,11 +205,11 @@ extern void vsyslog (int __pri, const char *__fmt, __gnuc_va_list __ap)
|
||||
/* Define some macros helping to catch buffer overflows. */
|
||||
#if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
|
||||
# include <bits/syslog.h>
|
||||
-#endif
|
||||
-
|
||||
-#include <bits/floatn.h>
|
||||
-#if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
|
||||
-# include <bits/syslog-ldbl.h>
|
||||
+#else
|
||||
+# include <bits/floatn.h>
|
||||
+# if defined __LDBL_COMPAT || __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI == 1
|
||||
+# include <bits/syslog-ldbl.h>
|
||||
+# endif
|
||||
#endif
|
||||
|
||||
__END_DECLS
|
@ -0,0 +1,241 @@
|
||||
commit 42eb735a5d3458a24a44ace9eca87c8b61573d97
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Thu May 20 14:20:18 2021 -0300
|
||||
|
||||
Use LFS and 64 bit time for installed programs (BZ #15333)
|
||||
|
||||
The installed programs are built with a combination of different
|
||||
values for MODULE_NAME, as below. To enable both Long File Support
|
||||
and 64 bt time, -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64 is added for
|
||||
nonlibi, nscd, lddlibc4, libresolv, ldconfig, locale_programs,
|
||||
iconvprogs, libnss_files, libnss_compat, libnss_db, libnss_hesiod,
|
||||
libutil, libpcprofile, and libSegFault.
|
||||
|
||||
nscd/nscd
|
||||
nscd/nscd.o MODULE_NAME=nscd
|
||||
nscd/connections.o MODULE_NAME=nscd
|
||||
nscd/pwdcache.o MODULE_NAME=nscd
|
||||
nscd/getpwnam_r.o MODULE_NAME=nscd
|
||||
nscd/getpwuid_r.o MODULE_NAME=nscd
|
||||
nscd/grpcache.o MODULE_NAME=nscd
|
||||
nscd/getgrnam_r.o MODULE_NAME=nscd
|
||||
nscd/getgrgid_r.o MODULE_NAME=nscd
|
||||
nscd/hstcache.o MODULE_NAME=nscd
|
||||
nscd/gethstbyad_r.o MODULE_NAME=nscd
|
||||
nscd/gethstbynm3_r.o MODULE_NAME=nscd
|
||||
nscd/getsrvbynm_r.o MODULE_NAME=nscd
|
||||
nscd/getsrvbypt_r.o MODULE_NAME=nscd
|
||||
nscd/servicescache.o MODULE_NAME=nscd
|
||||
nscd/dbg_log.o MODULE_NAME=nscd
|
||||
nscd/nscd_conf.o MODULE_NAME=nscd
|
||||
nscd/nscd_stat.o MODULE_NAME=nscd
|
||||
nscd/cache.o MODULE_NAME=nscd
|
||||
nscd/mem.o MODULE_NAME=nscd
|
||||
nscd/nscd_setup_thread.o MODULE_NAME=nscd
|
||||
nscd/xmalloc.o MODULE_NAME=nscd
|
||||
nscd/xstrdup.o MODULE_NAME=nscd
|
||||
nscd/aicache.o MODULE_NAME=nscd
|
||||
nscd/initgrcache.o MODULE_NAME=nscd
|
||||
nscd/gai.o MODULE_NAME=nscd
|
||||
nscd/res_hconf.o MODULE_NAME=nscd
|
||||
nscd/netgroupcache.o MODULE_NAME=nscd
|
||||
nscd/cachedumper.o MODULE_NAME=nscd
|
||||
elf/lddlibc4
|
||||
elf/lddlibc4 MODULE_NAME=lddlibc4
|
||||
elf/pldd
|
||||
elf/pldd.o MODULE_NAME=nonlib
|
||||
elf/xmalloc.o MODULE_NAME=nonlib
|
||||
elf/sln
|
||||
elf/sln.o MODULE_NAME=nonlib
|
||||
elf/static-stubs.o MODULE_NAME=nonlib
|
||||
elf/sprof MODULE_NAME=nonlib
|
||||
elf/ldconfig
|
||||
elf/ldconfig.o MODULE_NAME=ldconfig
|
||||
elf/cache.o MODULE_NAME=nonlib
|
||||
elf/readlib.o MODULE_NAME=nonlib
|
||||
elf/xmalloc.o MODULE_NAME=nonlib
|
||||
elf/xstrdup.o MODULE_NAME=nonlib
|
||||
elf/chroot_canon.o MODULE_NAME=nonlib
|
||||
elf/static-stubs.o MODULE_NAME=nonlib
|
||||
elf/stringtable.o MODULE_NAME=nonlib
|
||||
io/pwd
|
||||
io/pwd.o MODULE_NAME=nonlib
|
||||
locale/locale
|
||||
locale/locale.o MODULE_NAME=locale_programs
|
||||
locale/locale-spec.o MODULE_NAME=locale_programs
|
||||
locale/charmap-dir.o MODULE_NAME=locale_programs
|
||||
locale/simple-hash.o MODULE_NAME=locale_programs
|
||||
locale/xmalloc.o MODULE_NAME=locale_programs
|
||||
locale/xstrdup.o MODULE_NAME=locale_programs
|
||||
locale/record-status.o MODULE_NAME=locale_programs
|
||||
locale/xasprintf.o MODULE_NAME=locale_programs
|
||||
locale/localedef
|
||||
locale/localedef.o MODULE_NAME=locale_programs
|
||||
locale/ld-ctype.o MODULE_NAME=locale_programs
|
||||
locale/ld-messages.o MODULE_NAME=locale_programs
|
||||
locale/ld-monetary.o MODULE_NAME=locale_programs
|
||||
locale/ld-numeric.o MODULE_NAME=locale_programs
|
||||
locale/ld-time.o MODULE_NAME=locale_programs
|
||||
locale/ld-paper.o MODULE_NAME=locale_programs
|
||||
locale/ld-name.o MODULE_NAME=locale_programs
|
||||
locale/ld-address.o MODULE_NAME=locale_programs
|
||||
locale/ld-telephone.o MODULE_NAME=locale_programs
|
||||
locale/ld-measurement.o MODULE_NAME=locale_programs
|
||||
locale/ld-identification.o MODULE_NAME=locale_programs
|
||||
locale/ld-collate.o MODULE_NAME=locale_programs
|
||||
locale/charmap.o MODULE_NAME=locale_programs
|
||||
locale/linereader.o MODULE_NAME=locale_programs
|
||||
locale/locfile.o MODULE_NAME=locale_programs
|
||||
locale/repertoire.o MODULE_NAME=locale_programs
|
||||
locale/locarchive.o MODULE_NAME=locale_programs
|
||||
locale/md5.o MODULE_NAME=locale_programs
|
||||
locale/charmap-dir.o MODULE_NAME=locale_programs
|
||||
locale/simple-hash.o MODULE_NAME=locale_programs
|
||||
locale/xmalloc.o MODULE_NAME=locale_programs
|
||||
locale/xstrdup.o MODULE_NAME=locale_programs
|
||||
locale/record-status.o MODULE_NAME=locale_programs
|
||||
locale/xasprintf.o MODULE_NAME=locale_programs
|
||||
catgets/gencat
|
||||
catgets/gencat.o MODULE_NAME=nonlib
|
||||
catgets/xmalloc.o MODULE_NAME=nonlib
|
||||
nss/makedb
|
||||
nss/makedb.o MODULE_NAME=nonlib
|
||||
nss/xmalloc.o MODULE_NAME=nonlib
|
||||
nss/hash-string.o MODULE_NAME=nonlib
|
||||
nss/getent
|
||||
nss/getent.o MODULE_NAME=nonlib
|
||||
posix/getconf
|
||||
posix/getconf.o MODULE_NAME=nonlib
|
||||
login/utmpdump
|
||||
login/utmpdump.o MODULE_NAME=nonlib
|
||||
debug/pcprofiledump
|
||||
debug/pcprofiledump.o MODULE_NAME=nonlib
|
||||
timezone/zic
|
||||
timezone/zic.o MODULE_NAME=nonlib
|
||||
timezone/zdump
|
||||
timezone/zdump.o MODULE_NAME=nonlib
|
||||
iconv/iconv_prog
|
||||
iconv/iconv_prog.o MODULE_NAME=nonlib
|
||||
iconv/iconv_charmap.o MODULE_NAME=iconvprogs
|
||||
iconv/charmap.o MODULE_NAME=iconvprogs
|
||||
iconv/charmap-dir.o MODULE_NAME=iconvprogs
|
||||
iconv/linereader.o MODULE_NAME=iconvprogs
|
||||
iconv/dummy-repertoire.o MODULE_NAME=iconvprogs
|
||||
iconv/simple-hash.o MODULE_NAME=iconvprogs
|
||||
iconv/xstrdup.o MODULE_NAME=iconvprogs
|
||||
iconv/xmalloc.o MODULE_NAME=iconvprogs
|
||||
iconv/record-status.o MODULE_NAME=iconvprogs
|
||||
iconv/iconvconfig
|
||||
iconv/iconvconfig.o MODULE_NAME=nonlib
|
||||
iconv/strtab.o MODULE_NAME=iconvprogs
|
||||
iconv/xmalloc.o MODULE_NAME=iconvprogs
|
||||
iconv/hash-string.o MODULE_NAME=iconvprogs
|
||||
nss/libnss_files.so MODULE_NAME=libnss_files
|
||||
nss/libnss_compat.so.2 MODULE_NAME=libnss_compat
|
||||
nss/libnss_db.so MODULE_NAME=libnss_db
|
||||
hesiod/libnss_hesiod.so MODULE_NAME=libnss_hesiod
|
||||
login/libutil.so MODULE_NAME=libutil
|
||||
debug/libpcprofile.so MODULE_NAME=libpcprofile
|
||||
debug/libSegFault.so MODULE_NAME=libSegFault
|
||||
|
||||
Also, to avoid adding both LFS and 64 bit time support on internal
|
||||
tests they are moved to a newer 'testsuite-internal' module. It
|
||||
should be similar to 'nonlib' regarding internal definition and
|
||||
linking namespace.
|
||||
|
||||
This patch also enables LFS and 64 bit support of libsupport container
|
||||
programs (echo-container, test-container, shell-container, and
|
||||
true-container).
|
||||
|
||||
Checked on x86_64-linux-gnu and i686-linux-gnu.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
(cherry picked from commit a6d2f948b71adcb5ea395cb04833bc645eab45e6)
|
||||
|
||||
diff --git a/Makeconfig b/Makeconfig
|
||||
index 4e04dafb76a1e1a1..9accb5b38d1d37b3 100644
|
||||
--- a/Makeconfig
|
||||
+++ b/Makeconfig
|
||||
@@ -882,6 +882,13 @@ endif
|
||||
# -fno-math-errno.
|
||||
+extra-math-flags = $(if $(filter libm,$(in-module)),-fno-math-errno,-fmath-errno)
|
||||
|
||||
+# Use 64 bit time_t support for installed programs
|
||||
+installed-modules = nonlib nscd lddlibc4 libresolv ldconfig locale_programs \
|
||||
+ iconvprogs libnss_files libnss_compat libnss_db libnss_hesiod \
|
||||
+ libutil libpcprofile libSegFault
|
||||
++extra-time-flags = $(if $(filter $(installed-modules),\
|
||||
+ $(in-module)),-D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64)
|
||||
+
|
||||
# We might want to compile with some stack-protection flag.
|
||||
ifneq ($(stack-protector),)
|
||||
+stack-protector=$(stack-protector)
|
||||
@@ -986,7 +993,7 @@ libio-include = -I$(..)libio
|
||||
built-modules = iconvprogs iconvdata ldconfig lddlibc4 libmemusage \
|
||||
libSegFault libpcprofile librpcsvc locale-programs \
|
||||
memusagestat nonlib nscd extramodules libnldbl libsupport \
|
||||
- testsuite
|
||||
+ testsuite testsuite-internal
|
||||
|
||||
in-module = $(subst -,_,$(firstword $(libof-$(basename $(@F))) \
|
||||
$(libof-$(<F)) \
|
||||
@@ -1026,7 +1033,7 @@ endif
|
||||
|
||||
override CFLAGS = -std=gnu11 -fgnu89-inline $(config-extra-cflags) \
|
||||
$(filter-out %frame-pointer,$(+cflags)) $(+gccwarn-c) \
|
||||
- $(+extra-math-flags) \
|
||||
+ $(+extra-math-flags) $(+extra-time-flags) \
|
||||
$(sysdep-CFLAGS) $(CFLAGS-$(suffix $@)) $(CFLAGS-$(<F)) \
|
||||
$(CFLAGS-$(@F)) $(tls-model) \
|
||||
$(foreach lib,$(libof-$(basename $(@F))) \
|
||||
diff --git a/Makerules b/Makerules
|
||||
index e5916f29fa0d4593..689842ba56c71b0d 100644
|
||||
--- a/Makerules
|
||||
+++ b/Makerules
|
||||
@@ -1266,14 +1266,22 @@ lib := testsuite
|
||||
include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
|
||||
endif
|
||||
|
||||
-all-nonlib := $(strip $(tests-internal) $(test-internal-extras) \
|
||||
- $(others) $(others-extras))
|
||||
+all-nonlib := $(strip $(others) $(others-extras))
|
||||
ifneq (,$(all-nonlib))
|
||||
cpp-srcs-left = $(all-nonlib)
|
||||
lib := nonlib
|
||||
include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
|
||||
endif
|
||||
|
||||
+# All internal tests use testsuite-internal module since for 64 bit time
|
||||
+# support is set as default for MODULE_NAME=nonlib (which include some
|
||||
+# installed programs).
|
||||
+all-testsuite-internal := $(strip $(tests-internal) $(test-internal-extras))
|
||||
+ifneq (,$(all-testsuite-internal))
|
||||
+cpp-srcs-left = $(all-testsuite-internal)
|
||||
+lib := testsuite-internal
|
||||
+include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left))
|
||||
+endif
|
||||
|
||||
ifeq ($(build-shared),yes)
|
||||
# Generate normalized lists of symbols, versions, and data sizes.
|
||||
diff --git a/elf/sotruss-lib.c b/elf/sotruss-lib.c
|
||||
index e4ebc8dbc697df3f..45dc6d5ffe819475 100644
|
||||
--- a/elf/sotruss-lib.c
|
||||
+++ b/elf/sotruss-lib.c
|
||||
@@ -91,7 +91,7 @@ init (void)
|
||||
if (which_process == NULL || which_process[0] == '\0')
|
||||
snprintf (endp, 13, ".%ld", (long int) pid);
|
||||
|
||||
- out_fd = open (fullname, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
||||
+ out_fd = open64 (fullname, O_RDWR | O_CREAT | O_TRUNC, 0666);
|
||||
if (out_fd != -1)
|
||||
print_pid = 0;
|
||||
}
|
||||
@@ -104,7 +104,7 @@ init (void)
|
||||
program. */
|
||||
if (out_fd == -1)
|
||||
{
|
||||
- out_fd = fcntl (STDERR_FILENO, F_DUPFD, 1000);
|
||||
+ out_fd = fcntl64 (STDERR_FILENO, F_DUPFD, 1000);
|
||||
if (out_fd == -1)
|
||||
out_fd = dup (STDERR_FILENO);
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
commit d910ba48f47158d21c322b9f7e96831c83f69c67
|
||||
Author: Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>
|
||||
Date: Wed Oct 26 16:04:23 2022 -0300
|
||||
|
||||
nis: Build libnsl with 64 bit time_t
|
||||
|
||||
And remove the usage of glibc reserved names.
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
(cherry picked from commit 545eefc2f5da61801ba82b7a32ca2589b769ec90)
|
||||
|
||||
diff --git a/Makeconfig b/Makeconfig
|
||||
index 9accb5b38d1d37b3..89a2881b1ef605e4 100644
|
||||
--- a/Makeconfig
|
||||
+++ b/Makeconfig
|
||||
@@ -885,7 +885,7 @@ endif
|
||||
# Use 64 bit time_t support for installed programs
|
||||
installed-modules = nonlib nscd lddlibc4 libresolv ldconfig locale_programs \
|
||||
iconvprogs libnss_files libnss_compat libnss_db libnss_hesiod \
|
||||
- libutil libpcprofile libSegFault
|
||||
+ libutil libpcprofile libSegFault libnsl
|
||||
+extra-time-flags = $(if $(filter $(installed-modules),\
|
||||
$(in-module)),-D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64)
|
||||
|
||||
diff --git a/nis/nis_call.c b/nis/nis_call.c
|
||||
index 043f1bd4316aa284..37feba201c37cbca 100644
|
||||
--- a/nis/nis_call.c
|
||||
+++ b/nis/nis_call.c
|
||||
@@ -575,7 +575,7 @@ static struct nis_server_cache
|
||||
unsigned int size;
|
||||
unsigned int server_used;
|
||||
unsigned int current_ep;
|
||||
- __time64_t expires;
|
||||
+ time_t expires;
|
||||
char name[];
|
||||
} *nis_server_cache[16];
|
||||
static time_t nis_cold_start_mtime;
|
||||
@@ -584,7 +584,7 @@ __libc_lock_define_initialized (static, nis_server_cache_lock)
|
||||
static directory_obj *
|
||||
nis_server_cache_search (const_nis_name name, int search_parent,
|
||||
unsigned int *server_used, unsigned int *current_ep,
|
||||
- struct __timespec64 *now)
|
||||
+ struct timespec *now)
|
||||
{
|
||||
directory_obj *ret = NULL;
|
||||
int i;
|
||||
@@ -642,7 +642,7 @@ nis_server_cache_search (const_nis_name name, int search_parent,
|
||||
static void
|
||||
nis_server_cache_add (const_nis_name name, int search_parent,
|
||||
directory_obj *dir, unsigned int server_used,
|
||||
- unsigned int current_ep, struct __timespec64 *now)
|
||||
+ unsigned int current_ep, struct timespec *now)
|
||||
{
|
||||
struct nis_server_cache **loc;
|
||||
struct nis_server_cache *new;
|
||||
@@ -708,7 +708,7 @@ __nisfind_server (const_nis_name name, int search_parent,
|
||||
nis_error result = NIS_SUCCESS;
|
||||
nis_error status;
|
||||
directory_obj *obj;
|
||||
- struct __timespec64 ts;
|
||||
+ struct timespec ts;
|
||||
unsigned int server_used = ~0;
|
||||
unsigned int current_ep = ~0;
|
||||
|
||||
@@ -718,7 +718,7 @@ __nisfind_server (const_nis_name name, int search_parent,
|
||||
if (*dir != NULL)
|
||||
return NIS_SUCCESS;
|
||||
|
||||
- __clock_gettime64 (CLOCK_REALTIME, &ts);
|
||||
+ clock_gettime (CLOCK_REALTIME, &ts);
|
||||
|
||||
if ((flags & NO_CACHE) == 0)
|
||||
*dir = nis_server_cache_search (name, search_parent, &server_used,
|
@ -0,0 +1,38 @@
|
||||
commit 01c0a0405c5ea63d9b528e062b935d2ff6a6e2ed
|
||||
Author: Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>
|
||||
Date: Wed Oct 26 16:04:24 2022 -0300
|
||||
|
||||
nscd: Use 64 bit time_t on libc nscd routines (BZ# 29402)
|
||||
|
||||
Although the nscd module is built with 64 bit time_t, the routines
|
||||
linked direct to libc.so need to use the internal symbols.
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
(cherry picked from commit fa4a19277842fd09a4815a986f70e0fe0903836f)
|
||||
|
||||
diff --git a/nscd/nscd.h b/nscd/nscd.h
|
||||
index b5da5be98a11d4de..1ce4c1f7fdb215f0 100644
|
||||
--- a/nscd/nscd.h
|
||||
+++ b/nscd/nscd.h
|
||||
@@ -66,7 +66,7 @@ typedef enum
|
||||
struct traced_file
|
||||
{
|
||||
/* Tracks the last modified time of the traced file. */
|
||||
- time_t mtime;
|
||||
+ __time64_t mtime;
|
||||
/* Support multiple registered files per database. */
|
||||
struct traced_file *next;
|
||||
int call_res_init;
|
||||
diff --git a/nscd/nscd_gethst_r.c b/nscd/nscd_gethst_r.c
|
||||
index 81bf324256384de7..b6baa8abf881461c 100644
|
||||
--- a/nscd/nscd_gethst_r.c
|
||||
+++ b/nscd/nscd_gethst_r.c
|
||||
@@ -113,7 +113,7 @@ __nscd_get_nl_timestamp (void)
|
||||
if (map == NULL
|
||||
|| (map != NO_MAPPING
|
||||
&& map->head->nscd_certainly_running == 0
|
||||
- && map->head->timestamp + MAPPING_TIMEOUT < time_now ()))
|
||||
+ && map->head->timestamp + MAPPING_TIMEOUT < time64_now ()))
|
||||
map = __nscd_get_mapping (GETFDHST, "hosts", &__hst_map_handle.mapped);
|
||||
|
||||
if (map == NO_MAPPING)
|
@ -0,0 +1,24 @@
|
||||
commit e14a91e59d35bf2fa649a9726ccce838b8c6e4b7
|
||||
Author: Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>
|
||||
Date: Wed Oct 26 16:04:25 2022 -0300
|
||||
|
||||
time: Use 64 bit time on tzfile
|
||||
|
||||
The tzfile_mtime is already compared to 64 bit time_t stat call.
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
(cherry picked from commit 4e21c2075193e406a92c0d1cb091a7c804fda4d9)
|
||||
|
||||
diff --git a/time/tzfile.c b/time/tzfile.c
|
||||
index 8668392ad387af05..84fd9df65f76f148 100644
|
||||
--- a/time/tzfile.c
|
||||
+++ b/time/tzfile.c
|
||||
@@ -32,7 +32,7 @@
|
||||
int __use_tzfile;
|
||||
static dev_t tzfile_dev;
|
||||
static ino64_t tzfile_ino;
|
||||
-static time_t tzfile_mtime;
|
||||
+static __time64_t tzfile_mtime;
|
||||
|
||||
struct ttinfo
|
||||
{
|
@ -0,0 +1,28 @@
|
||||
commit d0e2ac0c5902bd0e671863cc6cb14024d0365e67
|
||||
Author: Alan Modra <amodra@gmail.com>
|
||||
Date: Sat Nov 12 11:20:31 2022 +1030
|
||||
|
||||
elf/tst-tlsopt-powerpc fails when compiled with -mcpu=power10 (BZ# 29776)
|
||||
|
||||
Supports pcrel addressing of TLS GOT entry. Also tweak the non-pcrel
|
||||
asm constraint to better reflect how the reg is used.
|
||||
|
||||
(cherry picked from commit 94628de77888c3292fc103840731ff85f283368e)
|
||||
|
||||
diff --git a/sysdeps/powerpc/mod-tlsopt-powerpc.c b/sysdeps/powerpc/mod-tlsopt-powerpc.c
|
||||
index ee0db12a737d6ab5..51cc502f2860e969 100644
|
||||
--- a/sysdeps/powerpc/mod-tlsopt-powerpc.c
|
||||
+++ b/sysdeps/powerpc/mod-tlsopt-powerpc.c
|
||||
@@ -24,7 +24,11 @@ tls_get_addr_opt_test (void)
|
||||
tls_index *tls_arg;
|
||||
#ifdef __powerpc64__
|
||||
register unsigned long thread_pointer __asm__ ("r13");
|
||||
- asm ("addi %0,2,foo@got@tlsgd" : "=r" (tls_arg));
|
||||
+# ifdef __PCREL__
|
||||
+ asm ("paddi %0,0,foo@got@tlsgd@pcrel,1" : "=b" (tls_arg));
|
||||
+# else
|
||||
+ asm ("addi %0,2,foo@got@tlsgd" : "=b" (tls_arg));
|
||||
+# endif
|
||||
#else
|
||||
register unsigned long thread_pointer __asm__ ("r2");
|
||||
asm ("bcl 20,31,1f\n1:\t"
|
Binary file not shown.
@ -0,0 +1,526 @@
|
||||
commit bbe4bbb6e8997b5ff9843bd3f32ac77dbaec7284
|
||||
Author: Fangrui Song <maskray@google.com>
|
||||
Date: Mon Aug 16 09:59:30 2021 -0700
|
||||
|
||||
elf: Drop elf/tls-macros.h in favor of __thread and tls_model attributes [BZ #28152] [BZ #28205]
|
||||
|
||||
elf/tls-macros.h was added for TLS testing when GCC did not support
|
||||
__thread. __thread and tls_model attributes are mature now and have been
|
||||
used by many newer tests.
|
||||
|
||||
Also delete tst-tls2.c which tests .tls_common (unused by modern GCC and
|
||||
unsupported by Clang/LLD). .tls_common and .tbss definition are almost
|
||||
identical after linking, so the runtime test doesn't add additional
|
||||
coverage. Assembler and linker tests should be on the binutils side.
|
||||
|
||||
When LLD 13.0.0 is allowed in configure.ac
|
||||
(https://sourceware.org/pipermail/libc-alpha/2021-August/129866.html),
|
||||
`make check` result is on par with glibc built with GNU ld on aarch64
|
||||
and x86_64.
|
||||
|
||||
As a future clean-up, TLS_GD/TLS_LD/TLS_IE/TLS_IE macros can be removed from
|
||||
sysdeps/*/tls-macros.h. We can add optional -mtls-dialect={gnu2,trad}
|
||||
tests to ensure coverage.
|
||||
|
||||
Tested on aarch64-linux-gnu, powerpc64le-linux-gnu, and x86_64-linux-gnu.
|
||||
|
||||
Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
||||
(cherry picked from commit 33c50ef42878b07ee6ead8b3f1a81d8c2c74697c)
|
||||
|
||||
Conflicts:
|
||||
elf/Makefile
|
||||
(different backport order)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index feec365e4e5fe9b3..3a8590e0d3cc33ab 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -275,7 +275,6 @@ tests-static-internal := \
|
||||
tst-ptrguard1-static \
|
||||
tst-stackguard1-static \
|
||||
tst-tls1-static \
|
||||
- tst-tls2-static \
|
||||
tst-tls1-static-non-pie \
|
||||
# tests-static-internal
|
||||
|
||||
@@ -308,7 +307,6 @@ tests := \
|
||||
tests-internal := \
|
||||
$(tests-static-internal) \
|
||||
tst-tls1 \
|
||||
- tst-tls2 \
|
||||
# tests-internal
|
||||
|
||||
tests-static := $(tests-static-normal) $(tests-static-internal)
|
||||
diff --git a/elf/tls-macros.h b/elf/tls-macros.h
|
||||
deleted file mode 100644
|
||||
index e25e33b0f032099d..0000000000000000
|
||||
--- a/elf/tls-macros.h
|
||||
+++ /dev/null
|
||||
@@ -1,25 +0,0 @@
|
||||
-/* Macros to support TLS testing in times of missing compiler support. */
|
||||
-
|
||||
-#define COMMON_INT_DEF(x) \
|
||||
- asm (".tls_common " #x ",4,4")
|
||||
-/* XXX Until we get compiler support we don't need declarations. */
|
||||
-#define COMMON_INT_DECL(x)
|
||||
-
|
||||
-/* XXX This definition will probably be machine specific, too. */
|
||||
-#define VAR_INT_DEF(x) \
|
||||
- asm (".section .tdata\n\t" \
|
||||
- ".globl " #x "\n" \
|
||||
- ".balign 4\n" \
|
||||
- #x ":\t.long 0\n\t" \
|
||||
- ".size " #x ",4\n\t" \
|
||||
- ".previous")
|
||||
-/* XXX Until we get compiler support we don't need declarations. */
|
||||
-#define VAR_INT_DECL(x)
|
||||
-
|
||||
-#include_next <tls-macros.h>
|
||||
-
|
||||
- /* XXX Each architecture must have its own asm for now. */
|
||||
-#if !defined TLS_LE || !defined TLS_IE \
|
||||
- || !defined TLS_LD || !defined TLS_GD
|
||||
-# error "No support for this architecture so far."
|
||||
-#endif
|
||||
diff --git a/elf/tst-tls1.c b/elf/tst-tls1.c
|
||||
index c31da56ce9cb3e8f..b3412213ee9eaa7e 100644
|
||||
--- a/elf/tst-tls1.c
|
||||
+++ b/elf/tst-tls1.c
|
||||
@@ -1,13 +1,14 @@
|
||||
/* glibc test for TLS in ld.so. */
|
||||
#include <stdio.h>
|
||||
|
||||
-#include "tls-macros.h"
|
||||
-
|
||||
-
|
||||
-/* Two common 'int' variables in TLS. */
|
||||
-COMMON_INT_DEF(foo);
|
||||
-COMMON_INT_DEF(bar);
|
||||
|
||||
+__thread int foo, bar __attribute__ ((tls_model("local-exec")));
|
||||
+extern __thread int foo_gd asm ("foo") __attribute__ ((tls_model("global-dynamic")));
|
||||
+extern __thread int foo_ld asm ("foo") __attribute__ ((tls_model("local-dynamic")));
|
||||
+extern __thread int foo_ie asm ("foo") __attribute__ ((tls_model("initial-exec")));
|
||||
+extern __thread int bar_gd asm ("bar") __attribute__ ((tls_model("global-dynamic")));
|
||||
+extern __thread int bar_ld asm ("bar") __attribute__ ((tls_model("local-dynamic")));
|
||||
+extern __thread int bar_ie asm ("bar") __attribute__ ((tls_model("initial-exec")));
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
@@ -18,63 +19,48 @@ do_test (void)
|
||||
|
||||
/* Set the variable using the local exec model. */
|
||||
puts ("set bar to 1 (LE)");
|
||||
- ap = TLS_LE (bar);
|
||||
- *ap = 1;
|
||||
+ bar = 1;
|
||||
|
||||
|
||||
/* Get variables using initial exec model. */
|
||||
fputs ("get sum of foo and bar (IE)", stdout);
|
||||
- ap = TLS_IE (foo);
|
||||
- bp = TLS_IE (bar);
|
||||
+ ap = &foo_ie;
|
||||
+ bp = &bar_ie;
|
||||
printf (" = %d\n", *ap + *bp);
|
||||
result |= *ap + *bp != 1;
|
||||
- if (*ap != 0)
|
||||
- {
|
||||
- printf ("foo = %d\n", *ap);
|
||||
- result = 1;
|
||||
- }
|
||||
- if (*bp != 1)
|
||||
+ if (*ap != 0 || *bp != 1)
|
||||
{
|
||||
- printf ("bar = %d\n", *bp);
|
||||
+ printf ("foo = %d\nbar = %d\n", *ap, *bp);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
|
||||
- /* Get variables using local dynamic model. */
|
||||
- fputs ("get sum of foo and bar (LD)", stdout);
|
||||
- ap = TLS_LD (foo);
|
||||
- bp = TLS_LD (bar);
|
||||
+ /* Get variables using local dynamic model or TLSDESC. */
|
||||
+ fputs ("get sum of foo and bar (LD or TLSDESC)", stdout);
|
||||
+ ap = &foo_ld;
|
||||
+ bp = &bar_ld;
|
||||
printf (" = %d\n", *ap + *bp);
|
||||
result |= *ap + *bp != 1;
|
||||
- if (*ap != 0)
|
||||
- {
|
||||
- printf ("foo = %d\n", *ap);
|
||||
- result = 1;
|
||||
- }
|
||||
- if (*bp != 1)
|
||||
+ if (*ap != 0 || *bp != 1)
|
||||
{
|
||||
- printf ("bar = %d\n", *bp);
|
||||
+ printf ("foo = %d\nbar = %d\n", *ap, *bp);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
|
||||
- /* Get variables using generic dynamic model. */
|
||||
- fputs ("get sum of foo and bar (GD)", stdout);
|
||||
- ap = TLS_GD (foo);
|
||||
- bp = TLS_GD (bar);
|
||||
+ /* Get variables using general dynamic model or TLSDESC. */
|
||||
+ fputs ("get sum of foo and bar (GD or TLSDESC)", stdout);
|
||||
+ ap = &foo_gd;
|
||||
+ bp = &bar_gd;
|
||||
printf (" = %d\n", *ap + *bp);
|
||||
result |= *ap + *bp != 1;
|
||||
- if (*ap != 0)
|
||||
- {
|
||||
- printf ("foo = %d\n", *ap);
|
||||
- result = 1;
|
||||
- }
|
||||
- if (*bp != 1)
|
||||
+ if (*ap != 0 || *bp != 1)
|
||||
{
|
||||
- printf ("bar = %d\n", *bp);
|
||||
+ printf ("foo = %d\nbar = %d\n", *ap, *bp);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
+
|
||||
return result;
|
||||
}
|
||||
|
||||
diff --git a/elf/tst-tls2.c b/elf/tst-tls2.c
|
||||
deleted file mode 100644
|
||||
index 963b8d6c88bba0b5..0000000000000000
|
||||
--- a/elf/tst-tls2.c
|
||||
+++ /dev/null
|
||||
@@ -1,82 +0,0 @@
|
||||
-/* glibc test for TLS in ld.so. */
|
||||
-#include <stdio.h>
|
||||
-
|
||||
-#include "tls-macros.h"
|
||||
-
|
||||
-
|
||||
-/* Two 'int' variables in TLS. */
|
||||
-VAR_INT_DEF(foo);
|
||||
-VAR_INT_DEF(bar);
|
||||
-
|
||||
-
|
||||
-static int
|
||||
-do_test (void)
|
||||
-{
|
||||
- int result = 0;
|
||||
- int *ap, *bp;
|
||||
-
|
||||
-
|
||||
- /* Set the variable using the local exec model. */
|
||||
- puts ("set bar to 1 (LE)");
|
||||
- ap = TLS_LE (bar);
|
||||
- *ap = 1;
|
||||
-
|
||||
-
|
||||
- /* Get variables using initial exec model. */
|
||||
- fputs ("get sum of foo and bar (IE)", stdout);
|
||||
- ap = TLS_IE (foo);
|
||||
- bp = TLS_IE (bar);
|
||||
- printf (" = %d\n", *ap + *bp);
|
||||
- result |= *ap + *bp != 1;
|
||||
- if (*ap != 0)
|
||||
- {
|
||||
- printf ("foo = %d\n", *ap);
|
||||
- result = 1;
|
||||
- }
|
||||
- if (*bp != 1)
|
||||
- {
|
||||
- printf ("bar = %d\n", *bp);
|
||||
- result = 1;
|
||||
- }
|
||||
-
|
||||
-
|
||||
- /* Get variables using local dynamic model. */
|
||||
- fputs ("get sum of foo and bar (LD)", stdout);
|
||||
- ap = TLS_LD (foo);
|
||||
- bp = TLS_LD (bar);
|
||||
- printf (" = %d\n", *ap + *bp);
|
||||
- result |= *ap + *bp != 1;
|
||||
- if (*ap != 0)
|
||||
- {
|
||||
- printf ("foo = %d\n", *ap);
|
||||
- result = 1;
|
||||
- }
|
||||
- if (*bp != 1)
|
||||
- {
|
||||
- printf ("bar = %d\n", *bp);
|
||||
- result = 1;
|
||||
- }
|
||||
-
|
||||
-
|
||||
- /* Get variables using generic dynamic model. */
|
||||
- fputs ("get sum of foo and bar (GD)", stdout);
|
||||
- ap = TLS_GD (foo);
|
||||
- bp = TLS_GD (bar);
|
||||
- printf (" = %d\n", *ap + *bp);
|
||||
- result |= *ap + *bp != 1;
|
||||
- if (*ap != 0)
|
||||
- {
|
||||
- printf ("foo = %d\n", *ap);
|
||||
- result = 1;
|
||||
- }
|
||||
- if (*bp != 1)
|
||||
- {
|
||||
- printf ("bar = %d\n", *bp);
|
||||
- result = 1;
|
||||
- }
|
||||
-
|
||||
- return result;
|
||||
-}
|
||||
-
|
||||
-
|
||||
-#include <support/test-driver.c>
|
||||
diff --git a/elf/tst-tls3.c b/elf/tst-tls3.c
|
||||
index 7e0abb4c58c8ff50..222b179626161897 100644
|
||||
--- a/elf/tst-tls3.c
|
||||
+++ b/elf/tst-tls3.c
|
||||
@@ -1,13 +1,12 @@
|
||||
/* glibc test for TLS in ld.so. */
|
||||
#include <stdio.h>
|
||||
|
||||
-#include "tls-macros.h"
|
||||
|
||||
-
|
||||
-/* One define int variable, two externs. */
|
||||
-COMMON_INT_DECL(foo);
|
||||
-VAR_INT_DECL(bar);
|
||||
-VAR_INT_DEF(baz);
|
||||
+__thread int foo, bar __attribute__ ((tls_model("initial-exec")));
|
||||
+__thread int baz __attribute__ ((tls_model("local-exec")));
|
||||
+extern __thread int foo_gd __attribute__ ((alias("foo"), tls_model("global-dynamic")));
|
||||
+extern __thread int bar_gd __attribute__ ((alias("bar"), tls_model("global-dynamic")));
|
||||
+extern __thread int baz_ld __attribute__ ((alias("baz"), tls_model("local-dynamic")));
|
||||
|
||||
|
||||
extern int in_dso (void);
|
||||
@@ -22,23 +21,20 @@ do_test (void)
|
||||
|
||||
/* Set the variable using the local exec model. */
|
||||
puts ("set baz to 3 (LE)");
|
||||
- ap = TLS_LE (baz);
|
||||
- *ap = 3;
|
||||
+ baz = 3;
|
||||
|
||||
|
||||
/* Get variables using initial exec model. */
|
||||
puts ("set variables foo and bar (IE)");
|
||||
- ap = TLS_IE (foo);
|
||||
- *ap = 1;
|
||||
- bp = TLS_IE (bar);
|
||||
- *bp = 2;
|
||||
+ foo = 1;
|
||||
+ bar = 2;
|
||||
|
||||
|
||||
/* Get variables using local dynamic model. */
|
||||
fputs ("get sum of foo, bar (GD) and baz (LD)", stdout);
|
||||
- ap = TLS_GD (foo);
|
||||
- bp = TLS_GD (bar);
|
||||
- cp = TLS_LD (baz);
|
||||
+ ap = &foo_gd;
|
||||
+ bp = &bar_gd;
|
||||
+ cp = &baz_ld;
|
||||
printf (" = %d\n", *ap + *bp + *cp);
|
||||
result |= *ap + *bp + *cp != 6;
|
||||
if (*ap != 1)
|
||||
diff --git a/elf/tst-tlsmod1.c b/elf/tst-tlsmod1.c
|
||||
index 8d9156791be9eabf..a448c4dc37eaf01b 100644
|
||||
--- a/elf/tst-tlsmod1.c
|
||||
+++ b/elf/tst-tlsmod1.c
|
||||
@@ -1,12 +1,12 @@
|
||||
#include <stdio.h>
|
||||
|
||||
-#include "tls-macros.h"
|
||||
|
||||
+__thread int foo, bar __attribute__ ((tls_model("global-dynamic")));
|
||||
+extern __thread int baz __attribute__ ((tls_model("global-dynamic")));
|
||||
+extern __thread int foo_ie asm ("foo") __attribute__ ((tls_model("initial-exec")));
|
||||
+extern __thread int bar_ie asm ("bar") __attribute__ ((tls_model("initial-exec")));
|
||||
+extern __thread int baz_ie asm ("baz") __attribute__ ((tls_model("initial-exec")));
|
||||
|
||||
-/* One define int variable, two externs. */
|
||||
-COMMON_INT_DEF(foo);
|
||||
-VAR_INT_DEF(bar);
|
||||
-VAR_INT_DECL(baz);
|
||||
|
||||
extern int in_dso (void);
|
||||
|
||||
@@ -19,8 +19,8 @@ in_dso (void)
|
||||
/* Get variables using initial exec model. */
|
||||
fputs ("get sum of foo and bar (IE)", stdout);
|
||||
asm ("" ::: "memory");
|
||||
- ap = TLS_IE (foo);
|
||||
- bp = TLS_IE (bar);
|
||||
+ ap = &foo_ie;
|
||||
+ bp = &bar_ie;
|
||||
printf (" = %d\n", *ap + *bp);
|
||||
result |= *ap + *bp != 3;
|
||||
if (*ap != 1)
|
||||
@@ -35,11 +35,11 @@ in_dso (void)
|
||||
}
|
||||
|
||||
|
||||
- /* Get variables using generic dynamic model. */
|
||||
- fputs ("get sum of foo and bar and baz (GD)", stdout);
|
||||
- ap = TLS_GD (foo);
|
||||
- bp = TLS_GD (bar);
|
||||
- cp = TLS_GD (baz);
|
||||
+ /* Get variables using generic dynamic model or TLSDESC. */
|
||||
+ fputs ("get sum of foo and bar and baz (GD or TLSDESC)", stdout);
|
||||
+ ap = &foo;
|
||||
+ bp = &bar;
|
||||
+ cp = &baz;
|
||||
printf (" = %d\n", *ap + *bp + *cp);
|
||||
result |= *ap + *bp + *cp != 6;
|
||||
if (*ap != 1)
|
||||
diff --git a/elf/tst-tlsmod2.c b/elf/tst-tlsmod2.c
|
||||
index 40eb1407f864f64a..3223fe494bb7e1f0 100644
|
||||
--- a/elf/tst-tlsmod2.c
|
||||
+++ b/elf/tst-tlsmod2.c
|
||||
@@ -1,9 +1,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
-#include "tls-macros.h"
|
||||
|
||||
-
|
||||
-COMMON_INT_DEF(foo);
|
||||
+__thread int foo;
|
||||
|
||||
|
||||
int
|
||||
@@ -15,7 +13,7 @@ in_dso (int n, int *caller_foop)
|
||||
puts ("foo"); /* Make sure PLT is used before macros. */
|
||||
asm ("" ::: "memory");
|
||||
|
||||
- foop = TLS_GD (foo);
|
||||
+ foop = &foo;
|
||||
|
||||
if (caller_foop != NULL && foop != caller_foop)
|
||||
{
|
||||
diff --git a/elf/tst-tlsmod3.c b/elf/tst-tlsmod3.c
|
||||
index 6d186c47ee6ba104..d6e7498fd8331cb7 100644
|
||||
--- a/elf/tst-tlsmod3.c
|
||||
+++ b/elf/tst-tlsmod3.c
|
||||
@@ -1,10 +1,10 @@
|
||||
#include <stdio.h>
|
||||
|
||||
-#include "tls-macros.h"
|
||||
|
||||
extern int in_dso (int n, int *caller_foop);
|
||||
|
||||
-COMMON_INT_DEF(comm_n);
|
||||
+extern __thread int foo;
|
||||
+__thread int comm_n;
|
||||
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ in_dso2 (void)
|
||||
puts ("foo"); /* Make sure PLT is used before macros. */
|
||||
asm ("" ::: "memory");
|
||||
|
||||
- foop = TLS_GD (foo);
|
||||
- np = TLS_GD (comm_n);
|
||||
+ foop = &foo;
|
||||
+ np = &comm_n;
|
||||
|
||||
if (n != *np)
|
||||
{
|
||||
diff --git a/elf/tst-tlsmod4.c b/elf/tst-tlsmod4.c
|
||||
index 86889aac7e58bcf5..f38919a8a94861c1 100644
|
||||
--- a/elf/tst-tlsmod4.c
|
||||
+++ b/elf/tst-tlsmod4.c
|
||||
@@ -1,9 +1,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
-#include "tls-macros.h"
|
||||
|
||||
-
|
||||
-COMMON_INT_DEF(baz);
|
||||
+__thread int baz;
|
||||
|
||||
|
||||
int
|
||||
@@ -15,7 +13,7 @@ in_dso (int n, int *caller_bazp)
|
||||
puts ("foo"); /* Make sure PLT is used before macros. */
|
||||
asm ("" ::: "memory");
|
||||
|
||||
- bazp = TLS_GD (baz);
|
||||
+ bazp = &baz;
|
||||
|
||||
if (caller_bazp != NULL && bazp != caller_bazp)
|
||||
{
|
||||
diff --git a/elf/tst-tlsmod5.c b/elf/tst-tlsmod5.c
|
||||
index a97c7e5e0c69de26..3f39c5bdb76e0b5c 100644
|
||||
--- a/elf/tst-tlsmod5.c
|
||||
+++ b/elf/tst-tlsmod5.c
|
||||
@@ -1,3 +1 @@
|
||||
-#include "tls-macros.h"
|
||||
-
|
||||
-COMMON_INT_DEF(foo);
|
||||
+__thread int foo;
|
||||
diff --git a/elf/tst-tlsmod6.c b/elf/tst-tlsmod6.c
|
||||
index e968596dd4ef7756..7b3571f428b7243b 100644
|
||||
--- a/elf/tst-tlsmod6.c
|
||||
+++ b/elf/tst-tlsmod6.c
|
||||
@@ -1,3 +1 @@
|
||||
-#include "tls-macros.h"
|
||||
-
|
||||
-COMMON_INT_DEF(bar);
|
||||
+__thread int bar;
|
||||
diff --git a/sysdeps/powerpc/mod-tlsopt-powerpc.c b/sysdeps/powerpc/mod-tlsopt-powerpc.c
|
||||
index 51cc502f2860e969..d941024963fc7e6a 100644
|
||||
--- a/sysdeps/powerpc/mod-tlsopt-powerpc.c
|
||||
+++ b/sysdeps/powerpc/mod-tlsopt-powerpc.c
|
||||
@@ -1,11 +1,9 @@
|
||||
/* shared library to test for __tls_get_addr optimization. */
|
||||
#include <stdio.h>
|
||||
|
||||
-#include "../../elf/tls-macros.h"
|
||||
#include "dl-tls.h"
|
||||
|
||||
-/* common 'int' variable in TLS. */
|
||||
-COMMON_INT_DEF(foo);
|
||||
+__thread int foo __attribute__ ((tls_model("global-dynamic")));
|
||||
|
||||
|
||||
int
|
||||
@@ -14,7 +12,7 @@ tls_get_addr_opt_test (void)
|
||||
int result = 0;
|
||||
|
||||
/* Get variable using general dynamic model. */
|
||||
- int *ap = TLS_GD (foo);
|
||||
+ int *ap = &foo;
|
||||
if (*ap != 0)
|
||||
{
|
||||
printf ("foo = %d\n", *ap);
|
||||
diff --git a/sysdeps/powerpc/tst-tlsifunc.c b/sysdeps/powerpc/tst-tlsifunc.c
|
||||
index 3095d41a68320d72..c8c0bada4547e1a4 100644
|
||||
--- a/sysdeps/powerpc/tst-tlsifunc.c
|
||||
+++ b/sysdeps/powerpc/tst-tlsifunc.c
|
||||
@@ -21,9 +21,9 @@
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <libc-symbols.h>
|
||||
-#include <tls-macros.h>
|
||||
|
||||
__thread int bar;
|
||||
+extern __thread int bar_gd asm ("bar") __attribute__ ((tls_model("global-dynamic")));
|
||||
static int *bar_ptr = NULL;
|
||||
|
||||
static uint32_t resolver_platform = 0;
|
||||
@@ -57,7 +57,7 @@ get_platform (void)
|
||||
void
|
||||
init_foo (void)
|
||||
{
|
||||
- bar_ptr = TLS_GD (bar);
|
||||
+ bar_ptr = &bar_gd;
|
||||
}
|
||||
|
||||
int
|
@ -0,0 +1,39 @@
|
||||
commit d36f457870a807f6f29880a2f2bde5e9b761f00c
|
||||
Author: Martin Sebor <msebor@redhat.com>
|
||||
Date: Tue Jan 25 17:38:31 2022 -0700
|
||||
|
||||
intl: Avoid -Wuse-after-free [BZ #26779]
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit 7845064d2d5a50e347ee9f4b78ec5e6316190154)
|
||||
|
||||
diff --git a/intl/localealias.c b/intl/localealias.c
|
||||
index 375af2b03153acce..28041f2a48f643fa 100644
|
||||
--- a/intl/localealias.c
|
||||
+++ b/intl/localealias.c
|
||||
@@ -318,7 +318,15 @@ read_alias_file (const char *fname, int fname_len)
|
||||
|
||||
if (string_space_act + alias_len + value_len > string_space_max)
|
||||
{
|
||||
- /* Increase size of memory pool. */
|
||||
+#pragma GCC diagnostic push
|
||||
+
|
||||
+#if defined __GNUC__ && __GNUC__ >= 12
|
||||
+ /* Suppress the valid GCC 12 warning until the code below is changed
|
||||
+ to avoid using pointers to the reallocated block. */
|
||||
+# pragma GCC diagnostic ignored "-Wuse-after-free"
|
||||
+#endif
|
||||
+
|
||||
+ /* Increase size of memory pool. */
|
||||
size_t new_size = (string_space_max
|
||||
+ (alias_len + value_len > 1024
|
||||
? alias_len + value_len : 1024));
|
||||
@@ -351,6 +359,8 @@ read_alias_file (const char *fname, int fname_len)
|
||||
value, value_len);
|
||||
string_space_act += value_len;
|
||||
|
||||
+#pragma GCC diagnostic pop
|
||||
+
|
||||
++nmap;
|
||||
++added;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
commit 92d5c52aaac0fa8e58b92e96bf2025d6848a2845
|
||||
Author: Martin Sebor <msebor@redhat.com>
|
||||
Date: Mon Oct 11 09:36:57 2021 -0600
|
||||
|
||||
resolv: Avoid GCC 12 false positive warning [BZ #28439].
|
||||
|
||||
Replace a call to sprintf with an equivalent pair of stpcpy/strcpy calls
|
||||
to avoid a GCC 12 -Wformat-overflow false positive due to recent optimizer
|
||||
improvements.
|
||||
|
||||
(cherry picked from commit eb73b87897798de981dbbf019aa957045d768adb)
|
||||
|
||||
diff --git a/resolv/res_query.c b/resolv/res_query.c
|
||||
index 2f3c28cfc8c0d832..1d2c81737bc889c9 100644
|
||||
--- a/resolv/res_query.c
|
||||
+++ b/resolv/res_query.c
|
||||
@@ -626,7 +626,9 @@ __res_context_querydomain (struct resolv_context *ctx,
|
||||
RES_SET_H_ERRNO(statp, NO_RECOVERY);
|
||||
return (-1);
|
||||
}
|
||||
- sprintf(nbuf, "%s.%s", name, domain);
|
||||
+ char *p = __stpcpy (nbuf, name);
|
||||
+ *p++ = '.';
|
||||
+ strcpy (p, domain);
|
||||
}
|
||||
return __res_context_query (ctx, longname, class, type, answer,
|
||||
anslen, answerp, answerp2, nanswerp2,
|
@ -0,0 +1,34 @@
|
||||
commit 26c7c6bac9da305b634a661aa491dae2756581ec
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Tue Oct 5 14:25:40 2021 +0000
|
||||
|
||||
Fix stdlib/tst-setcontext.c for GCC 12 -Warray-compare
|
||||
|
||||
Building stdlib/tst-setcontext.c fails with GCC mainline:
|
||||
|
||||
tst-setcontext.c: In function 'f2':
|
||||
tst-setcontext.c:61:16: error: comparison between two arrays [-Werror=array-compare]
|
||||
61 | if (on_stack < st2 || on_stack >= st2 + sizeof (st2))
|
||||
| ^
|
||||
tst-setcontext.c:61:16: note: use '&on_stack[0] < &st2[0]' to compare the addresses
|
||||
|
||||
The comparison in this case is deliberate, so adjust it as suggested
|
||||
in that note.
|
||||
|
||||
Tested with build-many-glibcs.py (GCC mainline) for aarch64-linux-gnu.
|
||||
|
||||
(cherry picked from commit a0f0c08e4fe18e78866539b0571f8e4b57dba7a3)
|
||||
|
||||
diff --git a/stdlib/tst-setcontext.c b/stdlib/tst-setcontext.c
|
||||
index 1b511708c1469444..1c2925bb760c9eb4 100644
|
||||
--- a/stdlib/tst-setcontext.c
|
||||
+++ b/stdlib/tst-setcontext.c
|
||||
@@ -58,7 +58,7 @@ f2 (void)
|
||||
puts ("start f2");
|
||||
|
||||
printf ("&on_stack=%p\n", on_stack);
|
||||
- if (on_stack < st2 || on_stack >= st2 + sizeof (st2))
|
||||
+ if (&on_stack[0] < &st2[0] || &on_stack[0] >= st2 + sizeof (st2))
|
||||
{
|
||||
printf ("%s: memory stack is not where it belongs!", __FUNCTION__);
|
||||
exit (1);
|
@ -0,0 +1,86 @@
|
||||
commit 6ff61a51459d141782fbcc32ae81c0ef1954dad6
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Mon Oct 4 19:10:43 2021 +0000
|
||||
|
||||
Fix stdio-common tests for GCC 12 -Waddress
|
||||
|
||||
My glibc bot shows failures building the testsuite with GCC mainline
|
||||
across all architectures:
|
||||
|
||||
tst-vfprintf-width-prec.c: In function 'do_test':
|
||||
tst-vfprintf-width-prec.c:90:16: error: the comparison will always evaluate as 'false' for the address of 'result' will never be NULL [-Werror=address]
|
||||
90 | if (result == NULL)
|
||||
| ^~
|
||||
tst-vfprintf-width-prec.c:89:13: note: 'result' declared here
|
||||
89 | wchar_t result[100];
|
||||
| ^~~~~~
|
||||
|
||||
This is clearly a correct warning; the comparison against NULL is
|
||||
clearly a cut-and-paste mistake from an earlier case in the test that
|
||||
does use calloc. Thus, remove the unnecessary check for NULL shown up
|
||||
by the warning.
|
||||
|
||||
Similarly, two other tests have bogus comparisons against NULL; remove
|
||||
those as well:
|
||||
|
||||
scanf14a.c:95:13: error: the comparison will always evaluate as 'false' for the address of 'fname' will never be NULL [-Werror=address]
|
||||
95 | if (fname == NULL)
|
||||
| ^~
|
||||
scanf14a.c:93:8: note: 'fname' declared here
|
||||
93 | char fname[strlen (tmpdir) + sizeof "/tst-scanf14.XXXXXX"];
|
||||
| ^~~~~
|
||||
|
||||
scanf16a.c:125:13: error: the comparison will always evaluate as 'false' for the address of 'fname' will never be NULL [-Werror=address]
|
||||
125 | if (fname == NULL)
|
||||
| ^~
|
||||
scanf16a.c:123:8: note: 'fname' declared here
|
||||
123 | char fname[strlen (tmpdir) + sizeof "/tst-scanf16.XXXXXX"];
|
||||
| ^~~~~
|
||||
|
||||
Tested with build-many-glibcs.py (GCC mainline) for aarch64-linux-gnu.
|
||||
|
||||
(cherry picked from commit a312e8fe6d89f5eae6a4583d5db577121e61c0b5)
|
||||
|
||||
diff --git a/stdio-common/scanf14a.c b/stdio-common/scanf14a.c
|
||||
index 12adcff5a4970da1..b37712d1c673fa3a 100644
|
||||
--- a/stdio-common/scanf14a.c
|
||||
+++ b/stdio-common/scanf14a.c
|
||||
@@ -92,8 +92,6 @@ main (void)
|
||||
|
||||
char fname[strlen (tmpdir) + sizeof "/tst-scanf14.XXXXXX"];
|
||||
sprintf (fname, "%s/tst-scanf14.XXXXXX", tmpdir);
|
||||
- if (fname == NULL)
|
||||
- FAIL ();
|
||||
|
||||
/* Create a temporary file. */
|
||||
int fd = mkstemp (fname);
|
||||
diff --git a/stdio-common/scanf16a.c b/stdio-common/scanf16a.c
|
||||
index 400d85a54e81c3cb..74d0295c97f73b14 100644
|
||||
--- a/stdio-common/scanf16a.c
|
||||
+++ b/stdio-common/scanf16a.c
|
||||
@@ -122,8 +122,6 @@ main (void)
|
||||
|
||||
char fname[strlen (tmpdir) + sizeof "/tst-scanf16.XXXXXX"];
|
||||
sprintf (fname, "%s/tst-scanf16.XXXXXX", tmpdir);
|
||||
- if (fname == NULL)
|
||||
- FAIL ();
|
||||
|
||||
/* Create a temporary file. */
|
||||
int fd = mkstemp (fname);
|
||||
diff --git a/stdio-common/tst-vfprintf-width-prec.c b/stdio-common/tst-vfprintf-width-prec.c
|
||||
index 3192fd797ad4ea90..278d57f739f576e9 100644
|
||||
--- a/stdio-common/tst-vfprintf-width-prec.c
|
||||
+++ b/stdio-common/tst-vfprintf-width-prec.c
|
||||
@@ -87,12 +87,6 @@ do_test (void)
|
||||
}
|
||||
{
|
||||
wchar_t result[100];
|
||||
- if (result == NULL)
|
||||
- {
|
||||
- printf ("error: calloc (%d, %zu): %m", ret + 1, sizeof (wchar_t));
|
||||
- return 1;
|
||||
- }
|
||||
-
|
||||
ret = swprintf (result, 100, L"%133000.999999999x", 17);
|
||||
if (ret >= 0)
|
||||
{
|
@ -0,0 +1,33 @@
|
||||
commit 803c959745fd7c679e00f9bad58822616f0e51cb
|
||||
Author: Joseph Myers <joseph@codesourcery.com>
|
||||
Date: Mon Aug 2 16:33:44 2021 +0000
|
||||
|
||||
Fix build of nptl/tst-thread_local1.cc with GCC 12
|
||||
|
||||
The test nptl/tst-thread_local1.cc fails to build with GCC mainline
|
||||
because of changes to what libstdc++ headers implicitly include what
|
||||
other headers:
|
||||
|
||||
tst-thread_local1.cc: In function 'int do_test()':
|
||||
tst-thread_local1.cc:177:5: error: variable 'std::array<std::pair<const char*, std::function<void(void* (*)(void*))> >, 2> do_thread_X' has initializer but incomplete type
|
||||
177 | do_thread_X
|
||||
| ^~~~~~~~~~~
|
||||
|
||||
Fix this by adding an explicit include of <array>.
|
||||
|
||||
Tested with build-many-glibcs.py for aarch64-linux-gnu.
|
||||
|
||||
(cherry picked from commit 2ee9b24f47db8d0a8d0ccadb999335a1d4cfc364)
|
||||
|
||||
diff --git a/nptl/tst-thread_local1.cc b/nptl/tst-thread_local1.cc
|
||||
index 9608afa4b739e360..338aafea059e10b7 100644
|
||||
--- a/nptl/tst-thread_local1.cc
|
||||
+++ b/nptl/tst-thread_local1.cc
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
+#include <array>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <thread>
|
@ -0,0 +1,176 @@
|
||||
commit 88b3228d9f6322b035fa89bb34f82d93b4190d48
|
||||
Author: Martin Sebor <msebor@redhat.com>
|
||||
Date: Tue Jan 25 15:39:38 2022 -0700
|
||||
|
||||
Avoid -Wuse-after-free in tests [BZ #26779].
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit c094c232eb3246154265bb035182f92fe1b17ab8)
|
||||
|
||||
diff --git a/malloc/tst-malloc-backtrace.c b/malloc/tst-malloc-backtrace.c
|
||||
index 4eb42e7f32f706e9..2ae3fb11efc245cb 100644
|
||||
--- a/malloc/tst-malloc-backtrace.c
|
||||
+++ b/malloc/tst-malloc-backtrace.c
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <support/support.h>
|
||||
+#include <libc-diag.h>
|
||||
|
||||
#define SIZE 4096
|
||||
|
||||
@@ -29,7 +30,15 @@ __attribute__((noinline))
|
||||
call_free (void *ptr)
|
||||
{
|
||||
free (ptr);
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ /* Ignore a valid warning about using a pointer made indeterminate
|
||||
+ by a prior call to free(). */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free");
|
||||
+#endif
|
||||
*(size_t *)(ptr - sizeof (size_t)) = 1;
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ DIAG_POP_NEEDS_COMMENT;
|
||||
+#endif
|
||||
}
|
||||
|
||||
int
|
||||
diff --git a/malloc/tst-malloc-check.c b/malloc/tst-malloc-check.c
|
||||
index 6650d09cf6cdde75..c5c9254a9e8936b0 100644
|
||||
--- a/malloc/tst-malloc-check.c
|
||||
+++ b/malloc/tst-malloc-check.c
|
||||
@@ -87,7 +87,15 @@ do_test (void)
|
||||
merror ("errno is not set correctly.");
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ /* Ignore a valid warning about using a pointer made indeterminate
|
||||
+ by a prior call to realloc(). */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free");
|
||||
+#endif
|
||||
free (p);
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ DIAG_POP_NEEDS_COMMENT;
|
||||
+#endif
|
||||
|
||||
p = malloc (512);
|
||||
if (p == NULL)
|
||||
@@ -105,7 +113,15 @@ do_test (void)
|
||||
merror ("errno is not set correctly.");
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ /* Ignore a valid warning about using a pointer made indeterminate
|
||||
+ by a prior call to realloc(). */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free");
|
||||
+#endif
|
||||
free (p);
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ DIAG_POP_NEEDS_COMMENT;
|
||||
+#endif
|
||||
free (q);
|
||||
|
||||
return errors != 0;
|
||||
diff --git a/malloc/tst-malloc-too-large.c b/malloc/tst-malloc-too-large.c
|
||||
index a4349a9b4c506dfc..328b4a2a4fd72cf4 100644
|
||||
--- a/malloc/tst-malloc-too-large.c
|
||||
+++ b/malloc/tst-malloc-too-large.c
|
||||
@@ -95,7 +95,15 @@ test_large_allocations (size_t size)
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
#endif
|
||||
TEST_VERIFY (errno == ENOMEM);
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ /* Ignore a warning about using a pointer made indeterminate by
|
||||
+ a prior call to realloc(). */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free");
|
||||
+#endif
|
||||
free (ptr_to_realloc);
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ DIAG_POP_NEEDS_COMMENT;
|
||||
+#endif
|
||||
|
||||
for (size_t nmemb = 1; nmemb <= 8; nmemb *= 2)
|
||||
if ((size % nmemb) == 0)
|
||||
@@ -113,14 +121,30 @@ test_large_allocations (size_t size)
|
||||
test_setup ();
|
||||
TEST_VERIFY (reallocarray (ptr_to_realloc, nmemb, size / nmemb) == NULL);
|
||||
TEST_VERIFY (errno == ENOMEM);
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ /* Ignore a warning about using a pointer made indeterminate by
|
||||
+ a prior call to realloc(). */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free");
|
||||
+#endif
|
||||
free (ptr_to_realloc);
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ DIAG_POP_NEEDS_COMMENT;
|
||||
+#endif
|
||||
|
||||
ptr_to_realloc = malloc (16);
|
||||
TEST_VERIFY_EXIT (ptr_to_realloc != NULL);
|
||||
test_setup ();
|
||||
TEST_VERIFY (reallocarray (ptr_to_realloc, size / nmemb, nmemb) == NULL);
|
||||
TEST_VERIFY (errno == ENOMEM);
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ /* Ignore a warning about using a pointer made indeterminate by
|
||||
+ a prior call to realloc(). */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free");
|
||||
+#endif
|
||||
free (ptr_to_realloc);
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ DIAG_POP_NEEDS_COMMENT;
|
||||
+#endif
|
||||
}
|
||||
else
|
||||
break;
|
||||
diff --git a/malloc/tst-obstack.c b/malloc/tst-obstack.c
|
||||
index ee1385d0f764e368..7d700c4f9a86b676 100644
|
||||
--- a/malloc/tst-obstack.c
|
||||
+++ b/malloc/tst-obstack.c
|
||||
@@ -21,8 +21,8 @@ verbose_malloc (size_t size)
|
||||
static void
|
||||
verbose_free (void *buf)
|
||||
{
|
||||
- free (buf);
|
||||
printf ("free (%p)\n", buf);
|
||||
+ free (buf);
|
||||
}
|
||||
|
||||
static int
|
||||
diff --git a/malloc/tst-realloc.c b/malloc/tst-realloc.c
|
||||
index c89ac07e192d70eb..80711beab1257ed5 100644
|
||||
--- a/malloc/tst-realloc.c
|
||||
+++ b/malloc/tst-realloc.c
|
||||
@@ -138,8 +138,16 @@ do_test (void)
|
||||
if (ok == 0)
|
||||
merror ("first 16 bytes were not correct after failed realloc");
|
||||
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ /* Ignore a valid warning about using a pointer made indeterminate
|
||||
+ by a prior call to realloc(). */
|
||||
+ DIAG_IGNORE_NEEDS_COMMENT (12, "-Wuse-after-free");
|
||||
+#endif
|
||||
/* realloc (p, 0) frees p (C89) and returns NULL (glibc). */
|
||||
p = realloc (p, 0);
|
||||
+#if __GNUC_PREREQ (12, 0)
|
||||
+ DIAG_POP_NEEDS_COMMENT;
|
||||
+#endif
|
||||
if (p != NULL)
|
||||
merror ("realloc (p, 0) returned non-NULL.");
|
||||
|
||||
diff --git a/support/tst-support-open-dev-null-range.c b/support/tst-support-open-dev-null-range.c
|
||||
index 8e29def1ce780629..80c97e51586bf6ce 100644
|
||||
--- a/support/tst-support-open-dev-null-range.c
|
||||
+++ b/support/tst-support-open-dev-null-range.c
|
||||
@@ -39,10 +39,11 @@ check_path (int fd)
|
||||
char file_path[PATH_MAX];
|
||||
ssize_t file_path_length
|
||||
= readlink (proc_fd_path, file_path, sizeof (file_path));
|
||||
- free (proc_fd_path);
|
||||
if (file_path_length < 0)
|
||||
FAIL_EXIT1 ("readlink (%s, %p, %zu)", proc_fd_path, file_path,
|
||||
sizeof (file_path));
|
||||
+
|
||||
+ free (proc_fd_path);
|
||||
file_path[file_path_length] = '\0';
|
||||
TEST_COMPARE_STRING (file_path, "/dev/null");
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
commit dd0c72fb461a8879164588cd870702efae0c7237
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Mon Dec 20 15:15:12 2021 -0800
|
||||
|
||||
Regenerate ulps on x86_64 with GCC 12
|
||||
|
||||
Fix
|
||||
|
||||
FAIL: math/test-float-clog10
|
||||
FAIL: math/test-float32-clog10
|
||||
|
||||
on Intel Core i7-1165G7 with GCC 12.
|
||||
|
||||
(cherry picked from commit de8a0897e3c084dc93676e331b610f146000a0ab)
|
||||
|
||||
diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps
|
||||
index 312575f93397c4b0..1c75f0ead46819a7 100644
|
||||
--- a/sysdeps/x86_64/fpu/libm-test-ulps
|
||||
+++ b/sysdeps/x86_64/fpu/libm-test-ulps
|
||||
@@ -705,7 +705,7 @@ ldouble: 3
|
||||
|
||||
Function: Real part of "clog10_towardzero":
|
||||
double: 5
|
||||
-float: 5
|
||||
+float: 6
|
||||
float128: 4
|
||||
ldouble: 8
|
||||
|
@ -0,0 +1,111 @@
|
||||
commit 80b24b86548eee3d96130a48e760d1d6c2e0c587
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Mon Dec 20 15:00:24 2021 -0800
|
||||
|
||||
math: Properly cast X_TLOSS to float [BZ #28713]
|
||||
|
||||
Add
|
||||
|
||||
#define AS_FLOAT_CONSTANT_1(x) x##f
|
||||
#define AS_FLOAT_CONSTANT(x) AS_FLOAT_CONSTANT_1(x)
|
||||
|
||||
to cast X_TLOSS to float at compile-time to fix:
|
||||
|
||||
FAIL: math/test-float-j0
|
||||
FAIL: math/test-float-jn
|
||||
FAIL: math/test-float-y0
|
||||
FAIL: math/test-float-y1
|
||||
FAIL: math/test-float-yn
|
||||
FAIL: math/test-float32-j0
|
||||
FAIL: math/test-float32-jn
|
||||
FAIL: math/test-float32-y0
|
||||
FAIL: math/test-float32-y1
|
||||
FAIL: math/test-float32-yn
|
||||
|
||||
when compiling with GCC 12.
|
||||
|
||||
Reviewed-by: Paul Zimmermann <Paul.Zimmermann@inria.fr>
|
||||
(cherry picked from commit 6e30181b4a3ab6c56da0378b65f4d60504982300)
|
||||
|
||||
diff --git a/math/math-svid-compat.h b/math/math-svid-compat.h
|
||||
index 5c18cb1b039cb3be..876cadde4084dab0 100644
|
||||
--- a/math/math-svid-compat.h
|
||||
+++ b/math/math-svid-compat.h
|
||||
@@ -49,6 +49,8 @@ extern int matherr (struct exception *__exc);
|
||||
extern int __matherr (struct exception *__exc);
|
||||
|
||||
#define X_TLOSS 1.41484755040568800000e+16
|
||||
+#define AS_FLOAT_CONSTANT_1(x) x##f
|
||||
+#define AS_FLOAT_CONSTANT(x) AS_FLOAT_CONSTANT_1(x)
|
||||
|
||||
/* Types of exceptions in the `type' field. */
|
||||
#define DOMAIN 1
|
||||
diff --git a/math/w_j0f_compat.c b/math/w_j0f_compat.c
|
||||
index a4882eadb33853b2..f35a55219f7baa78 100644
|
||||
--- a/math/w_j0f_compat.c
|
||||
+++ b/math/w_j0f_compat.c
|
||||
@@ -28,7 +28,8 @@
|
||||
float
|
||||
__j0f (float x)
|
||||
{
|
||||
- if (__builtin_expect (isgreater (fabsf (x), (float) X_TLOSS), 0)
|
||||
+ if (__builtin_expect (isgreater (fabsf (x),
|
||||
+ AS_FLOAT_CONSTANT (X_TLOSS)), 0)
|
||||
&& _LIB_VERSION != _IEEE_ && _LIB_VERSION != _POSIX_)
|
||||
/* j0(|x|>X_TLOSS) */
|
||||
return __kernel_standard_f (x, x, 134);
|
||||
@@ -43,7 +44,7 @@ float
|
||||
__y0f (float x)
|
||||
{
|
||||
if (__builtin_expect (islessequal (x, 0.0f)
|
||||
- || isgreater (x, (float) X_TLOSS), 0)
|
||||
+ || isgreater (x, AS_FLOAT_CONSTANT (X_TLOSS)), 0)
|
||||
&& _LIB_VERSION != _IEEE_)
|
||||
{
|
||||
if (x < 0.0f)
|
||||
diff --git a/math/w_j1f_compat.c b/math/w_j1f_compat.c
|
||||
index f2ec7b327d2bc90a..c5e3ccd035031799 100644
|
||||
--- a/math/w_j1f_compat.c
|
||||
+++ b/math/w_j1f_compat.c
|
||||
@@ -28,7 +28,8 @@
|
||||
float
|
||||
__j1f (float x)
|
||||
{
|
||||
- if (__builtin_expect (isgreater (fabsf (x), X_TLOSS), 0)
|
||||
+ if (__builtin_expect (isgreater (fabsf (x),
|
||||
+ AS_FLOAT_CONSTANT (X_TLOSS)), 0)
|
||||
&& _LIB_VERSION != _IEEE_ && _LIB_VERSION != _POSIX_)
|
||||
/* j1(|x|>X_TLOSS) */
|
||||
return __kernel_standard_f (x, x, 136);
|
||||
@@ -43,7 +44,7 @@ float
|
||||
__y1f (float x)
|
||||
{
|
||||
if (__builtin_expect (islessequal (x, 0.0f)
|
||||
- || isgreater (x, (float) X_TLOSS), 0)
|
||||
+ || isgreater (x, AS_FLOAT_CONSTANT (X_TLOSS)), 0)
|
||||
&& _LIB_VERSION != _IEEE_)
|
||||
{
|
||||
if (x < 0.0f)
|
||||
diff --git a/math/w_jnf_compat.c b/math/w_jnf_compat.c
|
||||
index fb6e5060096fb070..925ccc4cd0988a8f 100644
|
||||
--- a/math/w_jnf_compat.c
|
||||
+++ b/math/w_jnf_compat.c
|
||||
@@ -28,7 +28,8 @@
|
||||
float
|
||||
__jnf (int n, float x)
|
||||
{
|
||||
- if (__builtin_expect (isgreater (fabsf (x), (float) X_TLOSS), 0)
|
||||
+ if (__builtin_expect (isgreater (fabsf (x),
|
||||
+ AS_FLOAT_CONSTANT (X_TLOSS)), 0)
|
||||
&& _LIB_VERSION != _IEEE_ && _LIB_VERSION != _POSIX_)
|
||||
/* jn(n,|x|>X_TLOSS) */
|
||||
return __kernel_standard_f (n, x, 138);
|
||||
@@ -43,7 +44,7 @@ float
|
||||
__ynf (int n, float x)
|
||||
{
|
||||
if (__builtin_expect (islessequal (x, 0.0f)
|
||||
- || isgreater (x, (float) X_TLOSS), 0)
|
||||
+ || isgreater (x, AS_FLOAT_CONSTANT (X_TLOSS)), 0)
|
||||
&& _LIB_VERSION != _IEEE_)
|
||||
{
|
||||
if (x < 0.0f)
|
@ -0,0 +1,43 @@
|
||||
commit c5c666f34939d4bbf73aac8b753ab39621ebf33c
|
||||
Author: H.J. Lu <hjl.tools@gmail.com>
|
||||
Date: Mon Dec 20 14:37:26 2021 -0800
|
||||
|
||||
s_sincosf.h: Change pio4 type to float [BZ #28713]
|
||||
|
||||
s_cosf.c and s_sinf.c have
|
||||
|
||||
if (abstop12 (y) < abstop12 (pio4))
|
||||
|
||||
where abstop12 takes a float argument, but pio4 is static const double.
|
||||
pio4 is used only in calls to abstop12 and never in arithmetic. Apply
|
||||
|
||||
-static const double pio4 = 0x1.921FB54442D18p-1;
|
||||
+static const float pio4 = 0x1.921FB6p-1f;
|
||||
|
||||
to fix:
|
||||
|
||||
FAIL: math/test-float-cos
|
||||
FAIL: math/test-float-sin
|
||||
FAIL: math/test-float-sincos
|
||||
FAIL: math/test-float32-cos
|
||||
FAIL: math/test-float32-sin
|
||||
FAIL: math/test-float32-sincos
|
||||
|
||||
when compiling with GCC 12.
|
||||
|
||||
Reviewed-by: Paul Zimmermann <Paul.Zimmermann@inria.fr>
|
||||
(cherry picked from commit d3e4f5a1014db09ff1c62c6506f92cba469e193d)
|
||||
|
||||
diff --git a/sysdeps/ieee754/flt-32/s_sincosf.h b/sysdeps/ieee754/flt-32/s_sincosf.h
|
||||
index 125ab7f846c463c6..372d8542c2c9a9c7 100644
|
||||
--- a/sysdeps/ieee754/flt-32/s_sincosf.h
|
||||
+++ b/sysdeps/ieee754/flt-32/s_sincosf.h
|
||||
@@ -24,7 +24,7 @@
|
||||
/* 2PI * 2^-64. */
|
||||
static const double pi63 = 0x1.921FB54442D18p-62;
|
||||
/* PI / 4. */
|
||||
-static const double pio4 = 0x1.921FB54442D18p-1;
|
||||
+static const float pio4 = 0x1.921FB6p-1f;
|
||||
|
||||
/* Polynomial data (the cosine polynomial is negated in the 2nd entry). */
|
||||
extern const sincos_t __sincosf_table[2] attribute_hidden;
|
@ -0,0 +1,83 @@
|
||||
commit 6484ae5b8c4d4314f748e4d3c9a9baa5385e57c5
|
||||
Author: Carlos O'Donell <carlos@redhat.com>
|
||||
Date: Fri Jan 28 15:14:29 2022 -0500
|
||||
|
||||
malloc: Fix -Wuse-after-free warning in tst-mallocalign1 [BZ #26779]
|
||||
|
||||
The test leaks bits from the freed pointer via the return value
|
||||
in ret, and the compiler correctly identifies this issue.
|
||||
We switch the test to use TEST_VERIFY and terminate the test
|
||||
if any of the pointers return an unexpected alignment.
|
||||
|
||||
This fixes another -Wuse-after-free error when compiling glibc
|
||||
with gcc 12.
|
||||
|
||||
Tested on x86_64 and i686 without regression.
|
||||
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
(cherry picked from commit 3a7bed5f5a527dbd87412551f41e42e63aeef07a)
|
||||
|
||||
diff --git a/malloc/tst-mallocalign1.c b/malloc/tst-mallocalign1.c
|
||||
index 294e821afebd25ac..3e09ff30c4aa9f91 100644
|
||||
--- a/malloc/tst-mallocalign1.c
|
||||
+++ b/malloc/tst-mallocalign1.c
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <malloc-size.h>
|
||||
+#include <support/check.h>
|
||||
|
||||
static void *
|
||||
test (size_t s)
|
||||
@@ -31,41 +32,42 @@ test (size_t s)
|
||||
return p;
|
||||
}
|
||||
|
||||
+#define ALIGNED(p) (((uintptr_t )p & MALLOC_ALIGN_MASK) == 0)
|
||||
+
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
void *p;
|
||||
- int ret = 0;
|
||||
|
||||
p = test (2);
|
||||
- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
|
||||
+ TEST_VERIFY (ALIGNED (p));
|
||||
free (p);
|
||||
|
||||
p = test (8);
|
||||
- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
|
||||
+ TEST_VERIFY (ALIGNED (p));
|
||||
free (p);
|
||||
|
||||
p = test (13);
|
||||
- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
|
||||
+ TEST_VERIFY (ALIGNED (p));
|
||||
free (p);
|
||||
|
||||
p = test (16);
|
||||
- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
|
||||
+ TEST_VERIFY (ALIGNED (p));
|
||||
free (p);
|
||||
|
||||
p = test (23);
|
||||
- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
|
||||
+ TEST_VERIFY (ALIGNED (p));
|
||||
free (p);
|
||||
|
||||
p = test (43);
|
||||
- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
|
||||
+ TEST_VERIFY (ALIGNED (p));
|
||||
free (p);
|
||||
|
||||
p = test (123);
|
||||
- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
|
||||
+ TEST_VERIFY (ALIGNED (p));
|
||||
free (p);
|
||||
|
||||
- return ret;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
@ -0,0 +1,48 @@
|
||||
commit c5c792092b57687ae3ebecbe8645fa71ddb19f8c
|
||||
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Date: Thu Feb 2 07:49:02 2023 -0500
|
||||
|
||||
cdefs: Limit definition of fortification macros
|
||||
|
||||
Define the __glibc_fortify and other macros only when __FORTIFY_LEVEL >
|
||||
0. This has the effect of not defining these macros on older C90
|
||||
compilers that do not have support for variable length argument lists.
|
||||
|
||||
Also trim off the trailing backslashes from the definition of
|
||||
__glibc_fortify and __glibc_fortify_n macros.
|
||||
|
||||
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
Reviewed-by: Florian Weimer <fweimer@redhat.com>
|
||||
(cherry picked from commit 2337e04e21ba6040926ec871e403533f77043c40)
|
||||
|
||||
diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
|
||||
index b166f3d209fe361f..92dbd3e1fc68dae7 100644
|
||||
--- a/misc/sys/cdefs.h
|
||||
+++ b/misc/sys/cdefs.h
|
||||
@@ -151,6 +151,7 @@
|
||||
# define __glibc_objsize(__o) __bos (__o)
|
||||
#endif
|
||||
|
||||
+#if __USE_FORTIFY_LEVEL > 0
|
||||
/* Compile time conditions to choose between the regular, _chk and _chk_warn
|
||||
variants. These conditions should get evaluated to constant and optimized
|
||||
away. */
|
||||
@@ -186,7 +187,7 @@
|
||||
? __ ## f ## _alias (__VA_ARGS__) \
|
||||
: (__glibc_unsafe_len (__l, __s, __osz) \
|
||||
? __ ## f ## _chk_warn (__VA_ARGS__, __osz) \
|
||||
- : __ ## f ## _chk (__VA_ARGS__, __osz))) \
|
||||
+ : __ ## f ## _chk (__VA_ARGS__, __osz)))
|
||||
|
||||
/* Fortify function f, where object size argument passed to f is the number of
|
||||
elements and not total size. */
|
||||
@@ -196,7 +197,8 @@
|
||||
? __ ## f ## _alias (__VA_ARGS__) \
|
||||
: (__glibc_unsafe_len (__l, __s, __osz) \
|
||||
? __ ## f ## _chk_warn (__VA_ARGS__, (__osz) / (__s)) \
|
||||
- : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s)))) \
|
||||
+ : __ ## f ## _chk (__VA_ARGS__, (__osz) / (__s))))
|
||||
+#endif
|
||||
|
||||
#if __GNUC_PREREQ (4,3)
|
||||
# define __warnattr(msg) __attribute__((__warning__ (msg)))
|
@ -0,0 +1,127 @@
|
||||
commit 0b962177ee3b45cf775176eb454fcf6aa1b0f6e3
|
||||
Author: Andreas Schwab <schwab@suse.de>
|
||||
Date: Thu Jan 26 14:25:05 2023 +0100
|
||||
|
||||
Use 64-bit time_t interfaces in strftime and strptime (bug 30053)
|
||||
|
||||
Both functions use time_t only internally, so the ABI is not affected.
|
||||
|
||||
(cherry picked from commit 41349f6f67c83e7bafe49f985b56493d2c4c9c77)
|
||||
|
||||
diff --git a/time/Makefile b/time/Makefile
|
||||
index 38e3a7f4c77ea27f..ef3bb767b825f76a 100644
|
||||
--- a/time/Makefile
|
||||
+++ b/time/Makefile
|
||||
@@ -50,7 +50,7 @@ tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \
|
||||
tst-clock tst-clock2 tst-clock_nanosleep tst-cpuclock1 \
|
||||
tst-adjtime tst-ctime tst-difftime tst-mktime4 tst-clock_settime \
|
||||
tst-settimeofday tst-itimer tst-gmtime tst-timegm \
|
||||
- tst-timespec_get tst-timespec_getres
|
||||
+ tst-timespec_get tst-timespec_getres tst-strftime4
|
||||
|
||||
tests-time64 := \
|
||||
tst-adjtime-time64 \
|
||||
@@ -65,6 +65,7 @@ tests-time64 := \
|
||||
tst-itimer-time64 \
|
||||
tst-mktime4-time64 \
|
||||
tst-settimeofday-time64 \
|
||||
+ tst-strftime4-time64 \
|
||||
tst-timegm-time64 \
|
||||
tst-timespec_get-time64 \
|
||||
tst-timespec_getres-time64 \
|
||||
diff --git a/time/strftime_l.c b/time/strftime_l.c
|
||||
index d8cde9c5a3af87c7..57abbaa571694505 100644
|
||||
--- a/time/strftime_l.c
|
||||
+++ b/time/strftime_l.c
|
||||
@@ -159,6 +159,10 @@ extern char *tzname[];
|
||||
#ifdef _LIBC
|
||||
# define tzname __tzname
|
||||
# define tzset __tzset
|
||||
+
|
||||
+# define time_t __time64_t
|
||||
+# define __gmtime_r(t, tp) __gmtime64_r (t, tp)
|
||||
+# define mktime(tp) __mktime64 (tp)
|
||||
#endif
|
||||
|
||||
#if !HAVE_TM_GMTOFF
|
||||
diff --git a/time/strptime_l.c b/time/strptime_l.c
|
||||
index 02c5d63c798f9c13..39d1e59b0871f4b4 100644
|
||||
--- a/time/strptime_l.c
|
||||
+++ b/time/strptime_l.c
|
||||
@@ -30,8 +30,10 @@
|
||||
#ifdef _LIBC
|
||||
# define HAVE_LOCALTIME_R 0
|
||||
# include "../locale/localeinfo.h"
|
||||
-#endif
|
||||
|
||||
+# define time_t __time64_t
|
||||
+# define __localtime_r(t, tp) __localtime64_r (t, tp)
|
||||
+#endif
|
||||
|
||||
#if ! HAVE_LOCALTIME_R && ! defined localtime_r
|
||||
# ifdef _LIBC
|
||||
diff --git a/time/tst-strftime4-time64.c b/time/tst-strftime4-time64.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..4d47ee7d79f9e648
|
||||
--- /dev/null
|
||||
+++ b/time/tst-strftime4-time64.c
|
||||
@@ -0,0 +1 @@
|
||||
+#include "tst-strftime4.c"
|
||||
diff --git a/time/tst-strftime4.c b/time/tst-strftime4.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..659716d0fa4534ae
|
||||
--- /dev/null
|
||||
+++ b/time/tst-strftime4.c
|
||||
@@ -0,0 +1,52 @@
|
||||
+/* Test strftime and strptime after 2038-01-19 03:14:07 UTC (bug 30053).
|
||||
+ Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
+ This file is part of the GNU C Library.
|
||||
+
|
||||
+ The GNU C Library is free software; you can redistribute it and/or
|
||||
+ modify it under the terms of the GNU Lesser General Public
|
||||
+ License as published by the Free Software Foundation; either
|
||||
+ version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ Lesser General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU Lesser General Public
|
||||
+ License along with the GNU C Library; if not, see
|
||||
+ <https://www.gnu.org/licenses/>. */
|
||||
+
|
||||
+#include <time.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <stdio.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ TEST_VERIFY_EXIT (setenv ("TZ", "UTC0", 1) == 0);
|
||||
+ tzset ();
|
||||
+ if (sizeof (time_t) > 4)
|
||||
+ {
|
||||
+ time_t wrap = (time_t) 2147483648LL;
|
||||
+ char buf[80];
|
||||
+ struct tm *tm = gmtime (&wrap);
|
||||
+ TEST_VERIFY_EXIT (tm != NULL);
|
||||
+ TEST_VERIFY_EXIT (strftime (buf, sizeof buf, "%s", tm) > 0);
|
||||
+ puts (buf);
|
||||
+ TEST_VERIFY (strcmp (buf, "2147483648") == 0);
|
||||
+
|
||||
+ struct tm tm2;
|
||||
+ char *p = strptime (buf, "%s", &tm2);
|
||||
+ TEST_VERIFY_EXIT (p != NULL && *p == '\0');
|
||||
+ time_t t = mktime (&tm2);
|
||||
+ printf ("%lld\n", (long long) t);
|
||||
+ TEST_VERIFY (t == wrap);
|
||||
+ }
|
||||
+ else
|
||||
+ FAIL_UNSUPPORTED ("32-bit time_t");
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
@ -0,0 +1,328 @@
|
||||
commit 11ad405fd4c4c9f320d461d9ae1dd2e087cc8c32
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Wed Dec 29 10:20:46 2021 -0300
|
||||
|
||||
elf: Fix 64 time_t support for installed statically binaries
|
||||
|
||||
The usage of internal static symbol for statically linked binaries
|
||||
does not work correctly for objects built with -D_TIME_BITS=64,
|
||||
since the internal definition does not provide the expected aliases.
|
||||
|
||||
This patch makes it to use the default stat functions instead (which
|
||||
uses the default 64 time_t alias and types).
|
||||
|
||||
Checked on i686-linux-gnu.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
Tested-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit 9fe6f6363886aae6b2b210cae3ed1f5921299083)
|
||||
|
||||
diff --git a/elf/cache.c b/elf/cache.c
|
||||
index 8a3404923c625d18..062ec7fb0c9c300f 100644
|
||||
--- a/elf/cache.c
|
||||
+++ b/elf/cache.c
|
||||
@@ -319,8 +319,8 @@ print_cache (const char *cache_name)
|
||||
if (fd < 0)
|
||||
error (EXIT_FAILURE, errno, _("Can't open cache file %s\n"), cache_name);
|
||||
|
||||
- struct stat64 st;
|
||||
- if (__fstat64 (fd, &st) < 0
|
||||
+ struct stat st;
|
||||
+ if (fstat (fd, &st) < 0
|
||||
/* No need to map the file if it is empty. */
|
||||
|| st.st_size == 0)
|
||||
{
|
||||
@@ -933,7 +933,7 @@ init_aux_cache (void)
|
||||
}
|
||||
|
||||
int
|
||||
-search_aux_cache (struct stat64 *stat_buf, int *flags,
|
||||
+search_aux_cache (struct stat *stat_buf, int *flags,
|
||||
unsigned int *osversion, unsigned int *isa_level,
|
||||
char **soname)
|
||||
{
|
||||
@@ -995,7 +995,7 @@ insert_to_aux_cache (struct aux_cache_entry_id *id, int flags,
|
||||
}
|
||||
|
||||
void
|
||||
-add_to_aux_cache (struct stat64 *stat_buf, int flags,
|
||||
+add_to_aux_cache (struct stat *stat_buf, int flags,
|
||||
unsigned int osversion, unsigned int isa_level,
|
||||
const char *soname)
|
||||
{
|
||||
@@ -1018,8 +1018,8 @@ load_aux_cache (const char *aux_cache_name)
|
||||
return;
|
||||
}
|
||||
|
||||
- struct stat64 st;
|
||||
- if (__fstat64 (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file))
|
||||
+ struct stat st;
|
||||
+ if (fstat (fd, &st) < 0 || st.st_size < sizeof (struct aux_cache_file))
|
||||
{
|
||||
close (fd);
|
||||
init_aux_cache ();
|
||||
@@ -1135,8 +1135,8 @@ save_aux_cache (const char *aux_cache_name)
|
||||
char *dir = strdupa (aux_cache_name);
|
||||
dir = dirname (dir);
|
||||
|
||||
- struct stat64 st;
|
||||
- if (stat64 (dir, &st) < 0)
|
||||
+ struct stat st;
|
||||
+ if (stat (dir, &st) < 0)
|
||||
{
|
||||
if (mkdir (dir, 0700) < 0)
|
||||
goto out_fail;
|
||||
diff --git a/elf/chroot_canon.c b/elf/chroot_canon.c
|
||||
index 045611e730be9e41..a70fd25046112290 100644
|
||||
--- a/elf/chroot_canon.c
|
||||
+++ b/elf/chroot_canon.c
|
||||
@@ -67,7 +67,7 @@ chroot_canon (const char *chroot, const char *name)
|
||||
|
||||
for (start = end = name; *start; start = end)
|
||||
{
|
||||
- struct stat64 st;
|
||||
+ struct stat st;
|
||||
|
||||
/* Skip sequence of multiple path-separators. */
|
||||
while (*start == '/')
|
||||
@@ -114,7 +114,7 @@ chroot_canon (const char *chroot, const char *name)
|
||||
dest = mempcpy (dest, start, end - start);
|
||||
*dest = '\0';
|
||||
|
||||
- if (lstat64 (rpath, &st) < 0)
|
||||
+ if (lstat (rpath, &st) < 0)
|
||||
{
|
||||
if (*end == '\0')
|
||||
goto done;
|
||||
diff --git a/elf/ldconfig.c b/elf/ldconfig.c
|
||||
index b8893637f8aaea8d..be47ad8c2d7f89f3 100644
|
||||
--- a/elf/ldconfig.c
|
||||
+++ b/elf/ldconfig.c
|
||||
@@ -338,7 +338,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
|
||||
inode data from *ST. */
|
||||
static struct dir_entry *
|
||||
new_sub_entry (const struct dir_entry *entry, const char *path,
|
||||
- const struct stat64 *st)
|
||||
+ const struct stat *st)
|
||||
{
|
||||
struct dir_entry *new_entry = xmalloc (sizeof (struct dir_entry));
|
||||
new_entry->from_file = entry->from_file;
|
||||
@@ -428,8 +428,8 @@ add_glibc_hwcaps_subdirectories (struct dir_entry *entry, const char *path)
|
||||
continue;
|
||||
|
||||
/* See if this entry eventually resolves to a directory. */
|
||||
- struct stat64 st;
|
||||
- if (fstatat64 (dirfd (dir), e->d_name, &st, 0) < 0)
|
||||
+ struct stat st;
|
||||
+ if (fstatat (dirfd (dir), e->d_name, &st, 0) < 0)
|
||||
/* Ignore unreadable entries. */
|
||||
continue;
|
||||
|
||||
@@ -513,8 +513,8 @@ add_dir_1 (const char *line, const char *from_file, int from_line)
|
||||
if (opt_chroot != NULL)
|
||||
path = chroot_canon (opt_chroot, path);
|
||||
|
||||
- struct stat64 stat_buf;
|
||||
- if (path == NULL || stat64 (path, &stat_buf))
|
||||
+ struct stat stat_buf;
|
||||
+ if (path == NULL || stat (path, &stat_buf))
|
||||
{
|
||||
if (opt_verbose)
|
||||
error (0, errno, _("Can't stat %s"), entry->path);
|
||||
@@ -542,15 +542,15 @@ add_dir (const char *line)
|
||||
}
|
||||
|
||||
static int
|
||||
-chroot_stat (const char *real_path, const char *path, struct stat64 *st)
|
||||
+chroot_stat (const char *real_path, const char *path, struct stat *st)
|
||||
{
|
||||
int ret;
|
||||
char *canon_path;
|
||||
|
||||
if (!opt_chroot)
|
||||
- return stat64 (real_path, st);
|
||||
+ return stat (real_path, st);
|
||||
|
||||
- ret = lstat64 (real_path, st);
|
||||
+ ret = lstat (real_path, st);
|
||||
if (ret || !S_ISLNK (st->st_mode))
|
||||
return ret;
|
||||
|
||||
@@ -558,7 +558,7 @@ chroot_stat (const char *real_path, const char *path, struct stat64 *st)
|
||||
if (canon_path == NULL)
|
||||
return -1;
|
||||
|
||||
- ret = stat64 (canon_path, st);
|
||||
+ ret = stat (canon_path, st);
|
||||
free (canon_path);
|
||||
return ret;
|
||||
}
|
||||
@@ -570,7 +570,7 @@ create_links (const char *real_path, const char *path, const char *libname,
|
||||
{
|
||||
char *full_libname, *full_soname;
|
||||
char *real_full_libname, *real_full_soname;
|
||||
- struct stat64 stat_lib, stat_so, lstat_so;
|
||||
+ struct stat stat_lib, stat_so, lstat_so;
|
||||
int do_link = 1;
|
||||
int do_remove = 1;
|
||||
/* XXX: The logics in this function should be simplified. */
|
||||
@@ -605,7 +605,7 @@ create_links (const char *real_path, const char *path, const char *libname,
|
||||
&& stat_lib.st_ino == stat_so.st_ino)
|
||||
/* Link is already correct. */
|
||||
do_link = 0;
|
||||
- else if (lstat64 (full_soname, &lstat_so) == 0
|
||||
+ else if (lstat (full_soname, &lstat_so) == 0
|
||||
&& !S_ISLNK (lstat_so.st_mode))
|
||||
{
|
||||
error (0, 0, _("%s is not a symbolic link\n"), full_soname);
|
||||
@@ -613,7 +613,7 @@ create_links (const char *real_path, const char *path, const char *libname,
|
||||
do_remove = 0;
|
||||
}
|
||||
}
|
||||
- else if (lstat64 (real_full_soname, &lstat_so) != 0
|
||||
+ else if (lstat (real_full_soname, &lstat_so) != 0
|
||||
|| !S_ISLNK (lstat_so.st_mode))
|
||||
/* Unless it is a stale symlink, there is no need to remove. */
|
||||
do_remove = 0;
|
||||
@@ -657,7 +657,7 @@ manual_link (char *library)
|
||||
char *real_library;
|
||||
char *libname;
|
||||
char *soname;
|
||||
- struct stat64 stat_buf;
|
||||
+ struct stat stat_buf;
|
||||
int flag;
|
||||
unsigned int osversion;
|
||||
unsigned int isa_level;
|
||||
@@ -711,7 +711,7 @@ manual_link (char *library)
|
||||
}
|
||||
|
||||
/* Do some sanity checks first. */
|
||||
- if (lstat64 (real_library, &stat_buf))
|
||||
+ if (lstat (real_library, &stat_buf))
|
||||
{
|
||||
error (0, errno, _("Cannot lstat %s"), library);
|
||||
goto out;
|
||||
@@ -886,18 +886,18 @@ search_dir (const struct dir_entry *entry)
|
||||
sprintf (real_file_name, "%s/%s", dir_name, direntry->d_name);
|
||||
}
|
||||
|
||||
- struct stat64 lstat_buf;
|
||||
+ struct stat lstat_buf;
|
||||
/* We optimize and try to do the lstat call only if needed. */
|
||||
if (direntry->d_type != DT_UNKNOWN)
|
||||
lstat_buf.st_mode = DTTOIF (direntry->d_type);
|
||||
else
|
||||
- if (__glibc_unlikely (lstat64 (real_file_name, &lstat_buf)))
|
||||
+ if (__glibc_unlikely (lstat (real_file_name, &lstat_buf)))
|
||||
{
|
||||
error (0, errno, _("Cannot lstat %s"), file_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
- struct stat64 stat_buf;
|
||||
+ struct stat stat_buf;
|
||||
bool is_dir;
|
||||
int is_link = S_ISLNK (lstat_buf.st_mode);
|
||||
if (is_link)
|
||||
@@ -915,7 +915,7 @@ search_dir (const struct dir_entry *entry)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
- if (__glibc_unlikely (stat64 (target_name, &stat_buf)))
|
||||
+ if (__glibc_unlikely (stat (target_name, &stat_buf)))
|
||||
{
|
||||
if (opt_verbose)
|
||||
error (0, errno, _("Cannot stat %s"), file_name);
|
||||
@@ -951,7 +951,7 @@ search_dir (const struct dir_entry *entry)
|
||||
{
|
||||
if (!is_link
|
||||
&& direntry->d_type != DT_UNKNOWN
|
||||
- && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
|
||||
+ && __builtin_expect (lstat (real_file_name, &lstat_buf), 0))
|
||||
{
|
||||
error (0, errno, _("Cannot lstat %s"), file_name);
|
||||
continue;
|
||||
@@ -980,10 +980,10 @@ search_dir (const struct dir_entry *entry)
|
||||
else
|
||||
real_name = real_file_name;
|
||||
|
||||
- /* Call lstat64 if not done yet. */
|
||||
+ /* Call lstat if not done yet. */
|
||||
if (!is_link
|
||||
&& direntry->d_type != DT_UNKNOWN
|
||||
- && __builtin_expect (lstat64 (real_file_name, &lstat_buf), 0))
|
||||
+ && __builtin_expect (lstat (real_file_name, &lstat_buf), 0))
|
||||
{
|
||||
error (0, errno, _("Cannot lstat %s"), file_name);
|
||||
continue;
|
||||
diff --git a/elf/readlib.c b/elf/readlib.c
|
||||
index 7383c23249426c44..8901de2684835653 100644
|
||||
--- a/elf/readlib.c
|
||||
+++ b/elf/readlib.c
|
||||
@@ -76,10 +76,10 @@ int
|
||||
process_file (const char *real_file_name, const char *file_name,
|
||||
const char *lib, int *flag, unsigned int *osversion,
|
||||
unsigned int *isa_level, char **soname, int is_link,
|
||||
- struct stat64 *stat_buf)
|
||||
+ struct stat *stat_buf)
|
||||
{
|
||||
FILE *file;
|
||||
- struct stat64 statbuf;
|
||||
+ struct stat statbuf;
|
||||
void *file_contents;
|
||||
int ret;
|
||||
ElfW(Ehdr) *elf_header;
|
||||
@@ -99,7 +99,7 @@ process_file (const char *real_file_name, const char *file_name,
|
||||
return 1;
|
||||
}
|
||||
|
||||
- if (fstat64 (fileno (file), &statbuf) < 0)
|
||||
+ if (fstat (fileno (file), &statbuf) < 0)
|
||||
{
|
||||
error (0, 0, _("Cannot fstat file %s.\n"), file_name);
|
||||
fclose (file);
|
||||
diff --git a/elf/sln.c b/elf/sln.c
|
||||
index 26f371a4932cf475..f71321d565803f06 100644
|
||||
--- a/elf/sln.c
|
||||
+++ b/elf/sln.c
|
||||
@@ -153,11 +153,11 @@ makesymlinks (const char *file)
|
||||
static int
|
||||
makesymlink (const char *src, const char *dest)
|
||||
{
|
||||
- struct stat64 stats;
|
||||
+ struct stat stats;
|
||||
const char *error;
|
||||
|
||||
/* Destination must not be a directory. */
|
||||
- if (lstat64 (dest, &stats) == 0)
|
||||
+ if (lstat (dest, &stats) == 0)
|
||||
{
|
||||
if (S_ISDIR (stats.st_mode))
|
||||
{
|
||||
diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h
|
||||
index 3ab757077d160520..c0eb95bcf989dddc 100644
|
||||
--- a/sysdeps/generic/ldconfig.h
|
||||
+++ b/sysdeps/generic/ldconfig.h
|
||||
@@ -79,11 +79,11 @@ extern void init_aux_cache (void);
|
||||
|
||||
extern void load_aux_cache (const char *aux_cache_name);
|
||||
|
||||
-extern int search_aux_cache (struct stat64 *stat_buf, int *flags,
|
||||
+extern int search_aux_cache (struct stat *stat_buf, int *flags,
|
||||
unsigned int *osversion,
|
||||
unsigned int *isa_level, char **soname);
|
||||
|
||||
-extern void add_to_aux_cache (struct stat64 *stat_buf, int flags,
|
||||
+extern void add_to_aux_cache (struct stat *stat_buf, int flags,
|
||||
unsigned int osversion,
|
||||
unsigned int isa_level, const char *soname);
|
||||
|
||||
@@ -94,7 +94,7 @@ extern int process_file (const char *real_file_name, const char *file_name,
|
||||
const char *lib, int *flag,
|
||||
unsigned int *osversion, unsigned int *isa_level,
|
||||
char **soname, int is_link,
|
||||
- struct stat64 *stat_buf);
|
||||
+ struct stat *stat_buf);
|
||||
|
||||
extern char *implicit_soname (const char *lib, int flag);
|
||||
|
@ -0,0 +1,120 @@
|
||||
commit 2d7550e6cfff541380d3a1f2ac33e76aaf1273de
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Wed Feb 8 18:11:04 2023 +0100
|
||||
|
||||
elf: Smoke-test ldconfig -p against system /etc/ld.so.cache
|
||||
|
||||
The test is sufficient to detect the ldconfig bug fixed in
|
||||
commit 9fe6f6363886aae6b2b210cae3ed1f5921299083 ("elf: Fix 64 time_t
|
||||
support for installed statically binaries").
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
(cherry picked from commit 9fd63e35371b9939e9153907c6a753e6960b68ad)
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index 3a8590e0d3cc33ab..0daa8a85ec1a1bc5 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -553,6 +553,7 @@ ifeq ($(run-built-tests),yes)
|
||||
tests-special += \
|
||||
$(objpfx)noload-mem.out \
|
||||
$(objpfx)tst-ldconfig-X.out \
|
||||
+ $(objpfx)tst-ldconfig-p.out \
|
||||
$(objpfx)tst-leaks1-mem.out \
|
||||
$(objpfx)tst-rtld-help.out \
|
||||
# tests-special
|
||||
@@ -2259,6 +2260,11 @@ $(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
|
||||
'$(run-program-env)' > $@; \
|
||||
$(evaluate-test)
|
||||
|
||||
+$(objpfx)tst-ldconfig-p.out : tst-ldconfig-p.sh $(objpfx)ldconfig
|
||||
+ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper-env)' \
|
||||
+ '$(run-program-env)' > $@; \
|
||||
+ $(evaluate-test)
|
||||
+
|
||||
# Test static linking of all the libraries we can possibly link
|
||||
# together. Note that in some configurations this may be less than the
|
||||
# complete list of libraries we build but we try to maxmimize this list.
|
||||
diff --git a/elf/tst-ldconfig-p.sh b/elf/tst-ldconfig-p.sh
|
||||
new file mode 100644
|
||||
index 0000000000000000..ec937bf4ec04e8c0
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-ldconfig-p.sh
|
||||
@@ -0,0 +1,77 @@
|
||||
+#!/bin/sh
|
||||
+# Test that ldconfig -p prints something useful.
|
||||
+# Copyright (C) 2023 Free Software Foundation, Inc.
|
||||
+# This file is part of the GNU C Library.
|
||||
+
|
||||
+# The GNU C Library is free software; you can redistribute it and/or
|
||||
+# modify it under the terms of the GNU Lesser General Public
|
||||
+# License as published by the Free Software Foundation; either
|
||||
+# version 2.1 of the License, or (at your option) any later version.
|
||||
+
|
||||
+# The GNU C Library is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+# Lesser General Public License for more details.
|
||||
+
|
||||
+# You should have received a copy of the GNU Lesser General Public
|
||||
+# License along with the GNU C Library; if not, see
|
||||
+# <https://www.gnu.org/licenses/>.
|
||||
+
|
||||
+# Check that the newly built ldconfig -p can dump the system
|
||||
+# /etc/ld.so.cache file. This should always work even if the ABIs are
|
||||
+# not compatible, except in a cross-endian build (that presumably
|
||||
+# involves emulation when running ldconfig).
|
||||
+
|
||||
+common_objpfx=$1
|
||||
+test_wrapper_env=$2
|
||||
+run_program_env=$3
|
||||
+
|
||||
+if ! test -r /etc/ld.so.cache; then
|
||||
+ echo "warning: /etc/ld.so.cache does not exist, test skipped"
|
||||
+ exit 77
|
||||
+fi
|
||||
+
|
||||
+testout="${common_objpfx}elf/tst-ldconfig-p.out"
|
||||
+# Truncate file.
|
||||
+: > "$testout"
|
||||
+
|
||||
+${test_wrapper_env} \
|
||||
+${run_program_env} \
|
||||
+${common_objpfx}elf/ldconfig -p \
|
||||
+ $testroot/lib >>"$testout" 2>>"$testout"
|
||||
+status=$?
|
||||
+echo "info: ldconfig exit status: $status" >>"$testout"
|
||||
+
|
||||
+errors=0
|
||||
+case $status in
|
||||
+ (0)
|
||||
+ if head -n 1 "$testout" | \
|
||||
+ grep -q "libs found in cache \`/etc/ld.so.cache'\$" ; then
|
||||
+ echo "info: initial string found" >>"$testout"
|
||||
+ else
|
||||
+ echo "error: initial string not found" >>"$testout"
|
||||
+ errors=1
|
||||
+ fi
|
||||
+ if grep -q "^ libc\.so\..* => " "$testout"; then
|
||||
+ echo "info: libc.so.* string found" >>"$testout"
|
||||
+ else
|
||||
+ echo "error: libc.so.* string not found" >>"$testout"
|
||||
+ errors=1
|
||||
+ fi
|
||||
+ ;;
|
||||
+ (1)
|
||||
+ if head -n 1 "$testout" | \
|
||||
+ grep -q ": Cache file has wrong endianness\.$" ; then
|
||||
+ echo "info: cache file has wrong endianess" >> "$testout"
|
||||
+ else
|
||||
+ echo "error: unexpected ldconfig error message" >> "$testout"
|
||||
+ errors=1
|
||||
+ fi
|
||||
+ ;;
|
||||
+ (*)
|
||||
+ echo "error: unexpected exit status" >> "$testout"
|
||||
+ errors=1
|
||||
+ ;;
|
||||
+esac
|
||||
+
|
||||
+exit $errors
|
Loading…
Reference in new issue