Toshaan Bharvani
1 year ago
97 changed files with 14122 additions and 34 deletions
@ -0,0 +1,154 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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,31 @@
@@ -0,0 +1,31 @@
|
||||
commit 044755e2faeeca13bb77b2e9e638a45e6e90a5fa |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Tue Aug 30 13:30:03 2022 +0200 |
||||
|
||||
resolv: Fix building tst-resolv-invalid-cname for earlier C standards |
||||
|
||||
This fixes this compiler error: |
||||
|
||||
tst-resolv-invalid-cname.c: In function ‘test_mode_to_string’: |
||||
tst-resolv-invalid-cname.c:164:10: error: label at end of compound statement |
||||
case test_mode_num: |
||||
^~~~~~~~~~~~~ |
||||
|
||||
Fixes commit 9caf782276ecea4bc86fc94fbb52779736f3106d |
||||
("resolv: Add new tst-resolv-invalid-cname"). |
||||
|
||||
(cherry picked from commit d09aa4a17229bcaa2ec7642006b12612498582e7) |
||||
|
||||
diff --git a/resolv/tst-resolv-invalid-cname.c b/resolv/tst-resolv-invalid-cname.c |
||||
index ae2d4419b1978c02..63dac90e02d6cbc7 100644 |
||||
--- a/resolv/tst-resolv-invalid-cname.c |
||||
+++ b/resolv/tst-resolv-invalid-cname.c |
||||
@@ -162,7 +162,7 @@ test_mode_to_string (enum test_mode mode) |
||||
case gai_canon: |
||||
return "gai_canon"; |
||||
case test_mode_num: |
||||
- /* Report error below. */ |
||||
+ break; /* Report error below. */ |
||||
} |
||||
FAIL_EXIT1 ("invalid test_mode: %d", mode); |
||||
} |
@ -0,0 +1,33 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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,221 @@
@@ -0,0 +1,221 @@
|
||||
commit d57cdc1b5a52b5468b9259c0b9a215e22a1fa1f6 |
||||
Author: Florian Weimer <fweimer@redhat.com> |
||||
Date: Tue Nov 8 14:15:02 2022 +0100 |
||||
|
||||
Linux: Support __IPC_64 in sysvctl *ctl command arguments (bug 29771) |
||||
|
||||
Old applications pass __IPC_64 as part of the command argument because |
||||
old glibc did not check for unknown commands, and passed through the |
||||
arguments directly to the kernel, without adding __IPC_64. |
||||
Applications need to continue doing that for old glibc compatibility, |
||||
so this commit enables this approach in current glibc. |
||||
|
||||
For msgctl and shmctl, if no translation is required, make |
||||
direct system calls, as we did before the time64 changes. If |
||||
translation is required, mask __IPC_64 from the command argument. |
||||
|
||||
For semctl, the union-in-vararg argument handling means that |
||||
translation is needed on all architectures. |
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> |
||||
(cherry picked from commit 22a46dee24351fd5f4f188ad80554cad79c82524) |
||||
|
||||
diff --git a/sysdeps/unix/sysv/linux/ipc_priv.h b/sysdeps/unix/sysv/linux/ipc_priv.h |
||||
index f9852367a466cea9..d4efb9f3483daa9f 100644 |
||||
--- a/sysdeps/unix/sysv/linux/ipc_priv.h |
||||
+++ b/sysdeps/unix/sysv/linux/ipc_priv.h |
||||
@@ -63,4 +63,10 @@ struct __old_ipc_perm |
||||
# define __IPC_TIME64 0 |
||||
#endif |
||||
|
||||
+#if __IPC_TIME64 || defined __ASSUME_SYSVIPC_BROKEN_MODE_T |
||||
+# define IPC_CTL_NEED_TRANSLATION 1 |
||||
+#else |
||||
+# define IPC_CTL_NEED_TRANSLATION 0 |
||||
+#endif |
||||
+ |
||||
#include <ipc_ops.h> |
||||
diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c |
||||
index 9f38c06d53936390..ba7b94c22d17bc7f 100644 |
||||
--- a/sysdeps/unix/sysv/linux/msgctl.c |
||||
+++ b/sysdeps/unix/sysv/linux/msgctl.c |
||||
@@ -86,11 +86,19 @@ msgctl_syscall (int msqid, int cmd, msgctl_arg_t *buf) |
||||
int |
||||
__msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf) |
||||
{ |
||||
-#if __IPC_TIME64 |
||||
+#if IPC_CTL_NEED_TRANSLATION |
||||
+# if __IPC_TIME64 |
||||
struct kernel_msqid64_ds ksemid, *arg = NULL; |
||||
-#else |
||||
+# else |
||||
msgctl_arg_t *arg; |
||||
-#endif |
||||
+# endif |
||||
+ |
||||
+ /* Some applications pass the __IPC_64 flag in cmd, to invoke |
||||
+ previously unsupported commands back when there was no EINVAL |
||||
+ error checking in glibc. Mask the flag for the switch statements |
||||
+ below. msgctl_syscall adds back the __IPC_64 flag for the actual |
||||
+ system call. */ |
||||
+ cmd &= ~__IPC_64; |
||||
|
||||
switch (cmd) |
||||
{ |
||||
@@ -102,19 +110,19 @@ __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf) |
||||
case IPC_STAT: |
||||
case MSG_STAT: |
||||
case MSG_STAT_ANY: |
||||
-#if __IPC_TIME64 |
||||
+# if __IPC_TIME64 |
||||
if (buf != NULL) |
||||
{ |
||||
msqid64_to_kmsqid64 (buf, &ksemid); |
||||
arg = &ksemid; |
||||
} |
||||
-# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T |
||||
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T |
||||
if (cmd == IPC_SET) |
||||
arg->msg_perm.mode *= 0x10000U; |
||||
-# endif |
||||
-#else |
||||
+# endif |
||||
+# else |
||||
arg = buf; |
||||
-#endif |
||||
+# endif |
||||
break; |
||||
|
||||
case IPC_INFO: |
||||
@@ -138,21 +146,25 @@ __msgctl64 (int msqid, int cmd, struct __msqid64_ds *buf) |
||||
case IPC_STAT: |
||||
case MSG_STAT: |
||||
case MSG_STAT_ANY: |
||||
-#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T |
||||
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T |
||||
arg->msg_perm.mode >>= 16; |
||||
-#else |
||||
+# else |
||||
/* Old Linux kernel versions might not clear the mode padding. */ |
||||
if (sizeof ((struct msqid_ds){0}.msg_perm.mode) |
||||
!= sizeof (__kernel_mode_t)) |
||||
arg->msg_perm.mode &= 0xFFFF; |
||||
-#endif |
||||
+# endif |
||||
|
||||
-#if __IPC_TIME64 |
||||
+# if __IPC_TIME64 |
||||
kmsqid64_to_msqid64 (arg, buf); |
||||
-#endif |
||||
+# endif |
||||
} |
||||
|
||||
return ret; |
||||
+ |
||||
+#else /* !IPC_CTL_NEED_TRANSLATION */ |
||||
+ return msgctl_syscall (msqid, cmd, buf); |
||||
+#endif |
||||
} |
||||
#if __TIMESIZE != 64 |
||||
libc_hidden_def (__msgctl64) |
||||
diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c |
||||
index bb2690d30f80bb22..97fa411547fdd81e 100644 |
||||
--- a/sysdeps/unix/sysv/linux/semctl.c |
||||
+++ b/sysdeps/unix/sysv/linux/semctl.c |
||||
@@ -141,6 +141,13 @@ __semctl64 (int semid, int semnum, int cmd, ...) |
||||
union semun64 arg64 = { 0 }; |
||||
va_list ap; |
||||
|
||||
+ /* Some applications pass the __IPC_64 flag in cmd, to invoke |
||||
+ previously unsupported commands back when there was no EINVAL |
||||
+ error checking in glibc. Mask the flag for the switch statements |
||||
+ below. semctl_syscall adds back the __IPC_64 flag for the actual |
||||
+ system call. */ |
||||
+ cmd &= ~__IPC_64; |
||||
+ |
||||
/* Get the argument only if required. */ |
||||
switch (cmd) |
||||
{ |
||||
diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c |
||||
index f52018bfae4b3364..c44cbd6e4ac890a5 100644 |
||||
--- a/sysdeps/unix/sysv/linux/shmctl.c |
||||
+++ b/sysdeps/unix/sysv/linux/shmctl.c |
||||
@@ -86,11 +86,19 @@ shmctl_syscall (int shmid, int cmd, shmctl_arg_t *buf) |
||||
int |
||||
__shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf) |
||||
{ |
||||
-#if __IPC_TIME64 |
||||
+#if IPC_CTL_NEED_TRANSLATION |
||||
+# if __IPC_TIME64 |
||||
struct kernel_shmid64_ds kshmid, *arg = NULL; |
||||
-#else |
||||
+# else |
||||
shmctl_arg_t *arg; |
||||
-#endif |
||||
+# endif |
||||
+ |
||||
+ /* Some applications pass the __IPC_64 flag in cmd, to invoke |
||||
+ previously unsupported commands back when there was no EINVAL |
||||
+ error checking in glibc. Mask the flag for the switch statements |
||||
+ below. shmctl_syscall adds back the __IPC_64 flag for the actual |
||||
+ system call. */ |
||||
+ cmd &= ~__IPC_64; |
||||
|
||||
switch (cmd) |
||||
{ |
||||
@@ -104,19 +112,19 @@ __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf) |
||||
case IPC_STAT: |
||||
case SHM_STAT: |
||||
case SHM_STAT_ANY: |
||||
-#if __IPC_TIME64 |
||||
+# if __IPC_TIME64 |
||||
if (buf != NULL) |
||||
{ |
||||
shmid64_to_kshmid64 (buf, &kshmid); |
||||
arg = &kshmid; |
||||
} |
||||
-# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T |
||||
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T |
||||
if (cmd == IPC_SET) |
||||
arg->shm_perm.mode *= 0x10000U; |
||||
-# endif |
||||
-#else |
||||
+# endif |
||||
+# else |
||||
arg = buf; |
||||
-#endif |
||||
+# endif |
||||
break; |
||||
|
||||
case IPC_INFO: |
||||
@@ -141,21 +149,25 @@ __shmctl64 (int shmid, int cmd, struct __shmid64_ds *buf) |
||||
case IPC_STAT: |
||||
case SHM_STAT: |
||||
case SHM_STAT_ANY: |
||||
-#ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T |
||||
+# ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T |
||||
arg->shm_perm.mode >>= 16; |
||||
-#else |
||||
+# else |
||||
/* Old Linux kernel versions might not clear the mode padding. */ |
||||
if (sizeof ((struct shmid_ds){0}.shm_perm.mode) |
||||
!= sizeof (__kernel_mode_t)) |
||||
arg->shm_perm.mode &= 0xFFFF; |
||||
-#endif |
||||
+# endif |
||||
|
||||
-#if __IPC_TIME64 |
||||
+# if __IPC_TIME64 |
||||
kshmid64_to_shmid64 (arg, buf); |
||||
-#endif |
||||
+# endif |
||||
} |
||||
|
||||
return ret; |
||||
+ |
||||
+#else /* !IPC_CTL_NEED_TRANSLATION */ |
||||
+ return shmctl_syscall (shmid, cmd, buf); |
||||
+#endif |
||||
} |
||||
#if __TIMESIZE != 64 |
||||
libc_hidden_def (__shmctl64) |
@ -0,0 +1,46 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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